📄 adc.c
字号:
//#include <linux/config.h>#include <linux/init.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/slab.h>#include <linux/delay.h>#include <linux/interrupt.h>#include <linux/errno.h>#include <linux/ioport.h>#include <linux/crc32.h>#include <linux/device.h>#include <linux/spinlock.h>#include <linux/workqueue.h>#include <linux/miscdevice.h>#include <linux/list.h>#include <linux/string.h>#include <linux/errno.h>#include <linux/time.h>#include <asm/hardware.h>#include <asm/system.h>#include <linux/fs.h>#include <linux/types.h>#include <asm/uaccess.h>#include <linux/spinlock.h>#include <linux/irq.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/arch/gpio.h>#include <asm/arch/at91_adc.h>#include <linux/clk.h>#include "adc.h"#define MAX_CHAN_NUM 4#define MAX_SAMPLES 128000#define ADC_GET 1 typedef struct adc_data { unsigned int data[MAX_CHAN_NUM];}adc_data;void __iomem *adc_base;struct clk *adc_clk;unsigned char *adc_val;static inline int at91_adc_drdy(unsigned int chan);static inline unsigned char channel_read(unsigned int chan);/* Function to read last conversion of channels*/static inline unsigned char channel_read(unsigned int chan){ __raw_writel(0x02, adc_base + ADC_CR); //Start the ADC while(!at91_adc_drdy(chan)) //Is conversion ready? cpu_relax(); return __raw_readl(adc_base + ADC_CDR + chan*4); //Read & Return the conversion}/* Function to check if DRDY is set */static inline int at91_adc_drdy(unsigned int chan){ return (__raw_readl(adc_base + ADC_SR) & (0x01<<chan));}static int adc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ static struct adc_data local_data; int i=0; if (copy_from_user(&local_data, (struct adc_data *)arg, sizeof(local_data))) return -EFAULT; switch (cmd) { case ADC_GET: for(i = 0; i < MAX_CHAN_NUM; i ++) local_data.data[i] = channel_read(i); if (copy_to_user((struct adc_data *)arg, &local_data, sizeof(local_data))) return -EFAULT; return 0; break; default: return -EINVAL; break; } return -EINVAL;}static int adc_open(struct inode *inode, struct file *file){ return 0;}static int adc_release(struct inode *inode, struct file *file){ return 0;}static struct file_operations adc_fops = { .open = adc_open, .release = adc_release, .ioctl = adc_ioctl,};static struct miscdevice adc_dev = { .minor = 198, .name = "ADC", .fops = &adc_fops,};static int __init adc_init(void){ /* ADC Set Up */ adc_clk = clk_get(NULL, "adc_clk"); //Start ADC Clock clk_enable(adc_clk); at91_set_A_periph(AT91_PIN_PC0,0); //Mux ADC0 to GPIO at91_set_A_periph(AT91_PIN_PC1,0); //Mux ADC1 to GPIO at91_set_A_periph(AT91_PIN_PC2,0); //Mux ADC2 to GPIO at91_set_A_periph(AT91_PIN_PC3,0); //Mux ADC3 to GPIO adc_base = ioremap(AT91SAM9260_BASE_ADC,SZ_16K); //Map the mem region __raw_writel(0x01, adc_base + ADC_CR); //Reset the ADC __raw_writel((SHTIM << 24 | STARTUP << 16 | PRESCAL << 8 | SLEEP_MODE << 5 | LOWRES << 4 | TRGSEL << 1 | TRGEN), adc_base + ADC_MR); //Mode setup __raw_writel(CH_EN, adc_base + ADC_CHER); //Enable Channels __raw_writel(CH_DIS, adc_base + ADC_CHDR); //Disable Channels misc_register(&adc_dev); return 0;}static void __exit adc_exit(void){ clk_disable(adc_clk); //Turn off ADC clock clk_put(adc_clk); iounmap(adc_base); //Unmap the ADC mem region misc_deregister(&adc_dev);}MODULE_AUTHOR("Yanjun Luo <yanjun.luo@gmail.com");MODULE_DESCRIPTION("adc driver");MODULE_LICENSE("GPL");module_init(adc_init);module_exit(adc_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -