zoukankan      html  css  js  c++  java
  • sam9260 adc module

    1. /*  
    2.  * driver/char/at91_adc.c  
    3.  *  
    4.  * Copyright (C) 2007 Embedall Technology Co., Ltd.  
    5.  *  
    6.  * Analog-to-digital Converter(ADC) Driver.  
    7.  *  
    8.  * This program is free software; you can redistribute it and/or modify  
    9.  * it under the terms of the GNU General Public License as published by  
    10.  * the Free Software Foundation; either version 2 of the License, or  
    11.  * (at your option) any later version.  
    12.  */   
    13.    
    14. #include <linux/types.h>   
    15. #include <linux/init.h>   
    16. #include <linux/kernel.h>   
    17. #include <linux/module.h>   
    18. #include <linux/version.h>   
    19. #include <linux/spinlock.h>   
    20. #include <linux/interrupt.h>   
    21. #include <linux/platform_device.h>   
    22. #include <linux/cdev.h>   
    23. #include <linux/fs.h>   
    24. #include <linux/ioctl.h>   
    25. #include <linux/poll.h>   
    26.    
    27. #include <linux/at91_adc.h>   
    28.    
    29. #include <asm/arch/hardware.h>   
    30. #include <asm/arch/gpio.h>   
    31. #include <asm/arch/at91_adc.h>   
    32. #include <asm/arch/at91_tc.h>   
    33. #include <asm/arch/at91_pmc.h>   
    34.    
    35.    
    36.    
    37.    
    38. #define DRV_NAME "at91_adc"   
    39. #define DEV_NAME "adc0"   
    40.    
    41. #define adc_readl(adc,reg)     (__raw_readl((adc)->membase + (reg)))   
    42. #define adc_writel(adc,reg,v)  (__raw_writel((v), (adc)->membase + (reg)))   
    43. #define tc_readl(adc,reg)      (__raw_readl((adc)->tcxbase + (reg)))   
    44. #define tc_writel(adc,reg,v)   (__raw_writel((v), (adc)->tcxbase + (reg)))   
    45.    
    46.    
    47. #define ADC_MAX_CHANNEL CONFIG_AT91_ADC_CHANNELS   
    48. #define BUF_SIZE        8   
    49.    
    50. //#define buf_cnt(channel) (((channel)->head - (channel)->tail) & ((BUF_SIZE)-1))   
    51. //#define buf_space(channel) (((channel)->tail-((channel)->head+1))&(BUF_SIZE-1))   
    52.    
    53. struct adc;   
    54.    
    55. static int minor_num = 0;   
    56. static int major_num = 0;   
    57. struct adc_channel    
    58. {   
    59.     struct cdev         cdev;   
    60.     struct device       *dev;   
    61.     struct class_device *class_dev;   
    62.        
    63.     int id;   
    64.     int adc_data;   
    65.     int head;   
    66.     int tail;   
    67.        
    68.     struct fasync_struct *fasync;   
    69.     struct adc *adc;   
    70. };   
    71.    
    72. struct adc   
    73. {   
    74.     dev_t           devt;   
    75.     struct class    *class;   
    76.     void __iomem    *membase;   
    77.     void __iomem    *tcbbase;   
    78.     void __iomem    *tcxbase;   
    79.     unsigned int    irq;   
    80.     struct adc_mode mode;   
    81.    
    82.     spinlock_t      lock;   
    83.    
    84.     struct adc_channel *channel[ADC_MAX_CHANNEL];   
    85. };   
    86.    
    87.    
    88. static struct adc *adc;   
    89.    
    90. static inline int buf_in(struct adc_channel *channel, int v)   
    91. {   
    92.     channel->adc_data = v;   
    93.     //channel->head = (channel->head + 1) & (BUF_SIZE - 1);   
    94.     return channel->adc_data;   
    95. }   
    96.    
    97. static int adc_init_tc(struct adc *adc)   
    98. {   
    99.     unsigned int dummy = 0;   
    100.    
    101.     spin_lock(&adc->lock);   
    102.        
    103.     if (adc->mode.trigger != ADC_TRIGGER_TIMER) {   
    104.         at91_sys_write(AT91_PMC_PCDR, 1 << AT91SAM9260_ID_TC2);   
    105.         spin_unlock(&adc->lock);   
    106.         return 0;   
    107.     }   
    108.        
    109.     tc_writel(adc, AT91_TC_CCR, AT91_TC_CLKDIS);   
    110.        
    111.     dummy |= (AT91_TC_TIMER_CLOCK5 | AT91_TC_CPCTRG | AT91_TC_WAVE |   
    112.           AT91_TC_WAVESEL_UP_AUTO | AT91_TC_ACPA_SET |   
    113.           AT91_TC_ACPC_CLEAR );   
    114.     tc_writel(adc, AT91_TC_CMR, dummy);   
    115.        
    116.     if (adc->mode.trigger_time) {   
    117.         dummy = (adc->mode.trigger_time*1000000)/(1000000000/32768);   
    118.         if (dummy > 0xffff) dummy = 0xffff;   
    119.         tc_writel(adc, AT91_TC_RC, dummy);   
    120.         tc_writel(adc, AT91_TC_RA, dummy * 3 / 5);   
    121.     } else {   
    122.         tc_writel(adc, AT91_TC_RC, 32768);   
    123.         tc_writel(adc, AT91_TC_RA, 32768 * 3 / 5);   
    124.     }   
    125.        
    126.     at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9260_ID_TC2);   
    127.     tc_writel(adc, AT91_TC_CCR, AT91_TC_CLKEN | AT91_TC_SWTRG);   
    128.     spin_unlock(&adc->lock);   
    129.     return 0;   
    130. }   
    131.    
    132. static int adc_hw_init(struct adc *adc)   
    133. {   
    134.     adc_writel(adc, AT91_ADC_CR,  AT91_ADC_SWRST);   
    135.     adc_writel(adc, AT91_ADC_IER, AT91_ADC_DRDY);   
    136.     at91_sys_write(AT91_PMC_PCER, 1 << adc->irq);   
    137.     return 0;   
    138. }   
    139.    
    140. static int adc_fasync(int fd, struct file *file, int mode)   
    141. {   
    142.     struct adc_channel *channel = file->private_data;   
    143.     return fasync_helper(fd, file, mode, &channel->fasync);   
    144. }   
    145.    
    146. static int adc_open(struct inode *inode, struct file *file)   
    147. {   
    148.     struct adc *adc;   
    149.     struct adc_channel *channel;   
    150.     channel = container_of(inode->i_cdev, struct adc_channel, cdev);   
    151.     file->private_data = channel;   
    152.     adc = channel->adc;   
    153.    
    154.     spin_lock(&adc->lock);   
    155.     at91_set_multi_drive(PIN_BASE + 0x40 + channel->id, 1);   
    156.     adc_writel(adc, AT91_ADC_IER,  (1 << channel->id));   
    157.     adc_writel(adc, AT91_ADC_CHER, (1 << channel->id));   
    158.     spin_unlock(&adc->lock);   
    159.        
    160.     return nonseekable_open(inode, file);   
    161. }   
    162.    
    163. static int adc_release(struct inode *inode, struct file *file)   
    164. {   
    165.     struct adc *adc;   
    166.     struct adc_channel *channel;   
    167.     channel = container_of(inode->i_cdev, struct adc_channel, cdev);   
    168.     adc = channel->adc;   
    169.        
    170. //  adc_fasync(-1, file, 0);   
    171.    
    172.     spin_lock(&adc->lock);   
    173.     adc_writel(adc, AT91_ADC_IDR,  1 << channel->id);   
    174.     adc_writel(adc, AT91_ADC_CHDR, 1 << channel->id);   
    175.     spin_unlock(&adc->lock);   
    176.        
    177.     return 0;   
    178. }   
    179.    
    180. static ssize_t adc_read(struct file *file, char __user *buf, size_t count, loff_t *f_pos)   
    181. {   
    182.     return 0;   
    183. }   
    184.    
    185. static ssize_t adc_write(struct file *file, const char __user *buf, size_t count, loff_t *f_pos)   
    186. {   
    187.     return 0;   
    188. }   
    189.    
    190. /* static void adc_sigio(struct adc_channel *channel) */   
    191. /* { */   
    192. /*  if (channel->fasync) */   
    193. /*      kill_fasync(&channel->fasync, SIGIO, POLL_IN); */   
    194. /* } */   
    195.    
    196. static int adc_ioctl(struct inode *inode, struct file *file,   
    197.              unsigned int cmd, unsigned long arg)   
    198. {   
    199.     struct adc *adc;   
    200.     struct adc_channel *channel;   
    201.     struct adc_mode *mode;   
    202.    
    203.     int ret = 0;   
    204.     unsigned int dummy = 0;   
    205.        
    206.     void __user *argp = (void __user *)arg;   
    207.     int __user *p = argp;   
    208.        
    209.     channel = container_of(inode->i_cdev, struct adc_channel, cdev);   
    210.     adc = channel->adc;   
    211.     mode = &adc->mode;   
    212.        
    213.     switch (cmd) {   
    214.     case ADCCTL_RESET:   
    215.         adc_writel(adc, AT91_ADC_CR, AT91_ADC_SWRST);   
    216.         return 0;   
    217.     case ADCCTL_START:   
    218.         adc_writel(adc, AT91_ADC_CR, AT91_ADC_START);   
    219.         return 0;   
    220.     case ADCCTL_SETMODE:   
    221.         ret = copy_from_user(mode, argp, sizeof(struct adc_mode));   
    222.            
    223.         if (mode->trigger == ADC_TRIGGER_TIMER)   
    224.             dummy |= AT91_ADC_TRGEN | AT91_ADC_TRGSEL_TC2;   
    225.         else if (mode->trigger == ADC_TRIGGER_EXT)   
    226.             dummy |= AT91_ADC_TRGEN | AT91_ADC_TRGSEL_EXT;   
    227.         if (mode->resolution & ADC_M_8BIT)   
    228.             dummy |= AT91_ADC_LOWRES;   
    229.         if (mode->sleep_mode)   
    230.             dummy |= AT91_ADC_SLEEP;   
    231.         if (mode->adc_clock)   
    232.             dummy |= AT91_ADC_PRESCAL_(mode->adc_clock);   
    233.         if (mode->startup_time)   
    234.             dummy |= AT91_ADC_STARTUP_(mode->startup_time);   
    235.         if (mode->sample_time)   
    236.             dummy |= AT91_ADC_SHTIM_(mode->sample_time);   
    237.         adc_init_tc(adc);   
    238.         spin_lock(&adc->lock);   
    239.         adc_writel(adc, AT91_ADC_MR, dummy);   
    240.         spin_unlock(&adc->lock);   
    241.         return 0;   
    242.     case ADCCTL_GETMODE:   
    243.         ret = copy_to_user(argp, mode, sizeof(struct adc_mode));   
    244.         return 0;   
    245.     case ADCCTL_GETDATA:   
    246. //      ret = buf_cnt(channel);   
    247.     //  if (ret > 0) {   
    248.         //  if (!put_user(channel->buf[channel->tail], p))   
    249.             //  channel->tail = (channel->tail + 1) & (BUF_SIZE -1);   
    250.             //return 0;   
    251.         //}   
    252.          put_user(channel->adc_data,p);   
    253.         return -EFAULT;   
    254. //  case ADCCTL_GETCNT:   
    255.     //  return put_user(buf_cnt(channel), p);   
    256.     case ADCCTL_GETSTATUS:   
    257.         return put_user(adc_readl(adc, AT91_ADC_SR), p);   
    258.     default:   
    259.         return -EINVAL;   
    260.     }   
    261.     return -EINVAL;   
    262. }   
    263.    
    264. static struct file_operations adc_fops = {   
    265.         .owner     = THIS_MODULE,   
    266.         .read      = adc_read,   
    267.         .write     = adc_write,   
    268.         .open      = adc_open,   
    269.         .release   = adc_release,   
    270.     .ioctl     = adc_ioctl,   
    271.         .fasync    = adc_fasync,   
    272. };   
    273.            
    274. static irqreturn_t adc_interrupt(int irq, void *dev_id)   
    275. {   
    276.     struct adc *adc = dev_id;   
    277.     struct adc_channel *channel;   
    278.        
    279.    
    280.     unsigned int status;   
    281.    
    282.     status = adc_readl(adc, AT91_ADC_SR) & adc_readl(adc, AT91_ADC_IMR);   
    283.     while (status) {   
    284.         printk(KERN_DEBUG "at91_adc: interrupt status reg 0x%08x ",   
    285.                status);   
    286.            
    287.         if (status & AT91_ADC_EOC0){   
    288.             channel = adc->channel[0];   
    289.             buf_in(channel, adc_readl(adc, AT91_ADC_CDR0));   
    290.              printk(KERN_INFO "the adc_data is %d ",channel->adc_data);   
    291. //          adc_sigio(channel);   
    292.         }   
    293.         if (status & AT91_ADC_EOC1){   
    294.             channel = adc->channel[1];   
    295.             buf_in(channel, adc_readl(adc, AT91_ADC_CDR1));   
    296.             printk(KERN_INFO "the adc_data is %d ",channel->adc_data);   
    297. //          adc_sigio(channel);   
    298.         }   
    299.         if (status & AT91_ADC_EOC2){   
    300.             channel = adc->channel[2];   
    301.             buf_in(channel, adc_readl(adc, AT91_ADC_CDR2));   
    302.             printk(KERN_INFO "the adc_data is %d ",channel->adc_data);   
    303. //          adc_sigio(channel);   
    304.         }   
    305.         if (status & AT91_ADC_EOC3) {   
    306.             channel = adc->channel[3];   
    307.             buf_in(channel, adc_readl(adc, AT91_ADC_CDR3));   
    308.             printk(KERN_INFO "the adc_data is %d ",channel->adc_data);   
    309. //          adc_sigio(channel);   
    310.         }   
    311.         if (status & AT91_ADC_DRDY)   
    312.             adc_readl(adc, AT91_ADC_LCDR);   
    313.            
    314.         status = adc_readl(adc, AT91_ADC_SR) & adc_readl(adc, AT91_ADC_IMR);   
    315.     }   
    316.     return IRQ_HANDLED;   
    317. }   
    318.    
    319. static int __exit adc_remove(struct platform_device *pdev)   
    320. {   
    321.     struct adc_channel *channel = platform_get_drvdata(pdev);   
    322.        
    323.     class_device_unregister(channel->class_dev);   
    324.     cdev_del(&channel->cdev);   
    325.     kfree(channel);   
    326.     return 0;   
    327. }   
    328. static struct platform_device adc_channel_device[ADC_MAX_CHANNEL];   
    329. /*  
    330. static int __init adc_add_channel_device(void)  
    331. {  
    332.     int i;  
    333.   
    334.     for (i=0; i<ADC_MAX_CHANNEL; i++){  
    335.         adc_channel_device[i].name = DRV_NAME;  
    336.         adc_channel_device[i].id   = i;  
    337.         platform_device_register(&adc_channel_device[i]);  
    338.     }  
    339.     return 0;  
    340. }  
    341. */   
    342.    
    343. static int __init adc_init(void)   
    344. {struct adc_channel *channel;   
    345.    
    346.     int ret = 0;   
    347.     //struct adc_channel *channel;   
    348.     int ret1;     
    349.     adc = kmalloc(sizeof(struct adc), GFP_KERNEL);   
    350.     if (!adc)   
    351.         return -ENOMEM;   
    352.    
    353.     if (!request_mem_region(AT91SAM9260_BASE_ADC, SZ_16K, DRV_NAME)){   
    354.         kfree(adc);   
    355.         return -EBUSY;   
    356.     }   
    357.     adc->membase = ioremap(AT91SAM9260_BASE_ADC, SZ_16K);   
    358.     if (adc->membase == NULL)   
    359.         goto adc_release_mem;   
    360.    
    361.     if (!request_mem_region(AT91SAM9260_BASE_TC0, SZ_16K, DRV_NAME))   
    362.         goto adc_iounmap;   
    363.     adc->tcbbase = ioremap(AT91SAM9260_BASE_TC0, SZ_16K);   
    364.     if (adc->tcbbase == NULL)   
    365.         goto adc_release_mem_tc;   
    366.    
    367.     adc->irq = AT91SAM9260_ID_ADC;   
    368.     adc->tcxbase = adc->tcbbase + 0x80;   
    369.     spin_lock_init(&adc->lock);   
    370.        
    371.     adc->class = class_create(THIS_MODULE, DEV_NAME);   
    372.     if (IS_ERR(adc->class)){   
    373.         printk(KERN_ERR "at91_adc: faile to create device class ");   
    374.         goto adc_iounmap_tc;   
    375.     }   
    376.        
    377.     ret = alloc_chrdev_region(&adc->devt, 0, 1, DEV_NAME);   
    378.     if (ret < 0) {   
    379.         printk(KERN_ERR"%s: failed to allocate dev region ", __FILE__);   
    380.         goto adc_destroy_class;   
    381.     }   
    382.    
    383.     if (request_irq(adc->irq, adc_interrupt, IRQF_SHARED, DRV_NAME, adc)){   
    384.         printk(KERN_ERR"%s: request irq failed ", __FILE__);   
    385.         goto adc_del_channel;   
    386.     }   
    387.        
    388.     adc_hw_init(adc);   
    389.         printk(KERN_INFO "&&123456xx ");   
    390.     //platform_driver_register(&adc_driver);   
    391.     printk(KERN_INFO "Analog-to-Digital Converter (irq %d) ", adc->irq);   
    392.        
    393. //  adc_add_channel_device();   
    394.        
    395.    
    396.         printk(KERN_ERR "&&123456&& ");   
    397.     channel = kmalloc(sizeof(struct adc_channel), GFP_KERNEL);   
    398.     if (!channel){   
    399.       printk(KERN_ERR "&&123456&& ");       
    400.         //printk(KERN_ERR "at91_adc: failed to kmalloc channel %d ", pdev->id);   
    401.         return -ENOMEM;   
    402.     }   
    403. //  channel->fasync = kmalloc(sizeof(struct fasync_struct), GFP_KERNEL);   
    404. //  if (!channel->fasync) return -ENOMEM;   
    405.     channel->id  = 0;   
    406.     //channel->dev = &pdev->dev;   
    407.     channel->adc = adc;   
    408.     channel->head = 0;   
    409.     channel->tail = 0;   
    410.        
    411.     cdev_init(&channel->cdev, &adc_fops);   
    412.     channel->cdev.owner = THIS_MODULE;   
    413.     ret1 = cdev_add(&channel->cdev, MKDEV(MAJOR(adc->devt), channel->id), 1);   
    414.     if (ret1) {   
    415.         //printk(KERN_ERR "at91_adc: failed to add channel %d device ", pdev->id);   
    416.            
    417.         kfree(channel);   
    418.         return ret1;   
    419.     }   
    420.     channel->class_dev = class_device_create(adc->class, NULL,   
    421.                          MKDEV(MAJOR(adc->devt),   
    422.                                channel->id),   
    423.                          NULL,   
    424.                          DEV_NAME);   
    425.     if (IS_ERR(channel->class_dev)) {   
    426.         cdev_del(&channel->cdev);   
    427.         kfree(channel);   
    428.         return PTR_ERR(channel->class_dev);   
    429.     }   
    430.    
    431.     adc->channel[channel->id] = channel;   
    432.     //platform_set_drvdata(pdev, channel);   
    433.    
    434.     printk(KERN_INFO "at91_adc. major  is %d ",   
    435.            MAJOR(adc->devt));   
    436.        
    437.     return 0;   
    438.            
    439. adc_del_channel:   
    440.     unregister_chrdev_region(adc->devt, 1);   
    441. adc_destroy_class:   
    442.     class_destroy(adc->class);   
    443. adc_iounmap_tc:   
    444.     iounmap(adc->tcbbase);   
    445. adc_release_mem_tc:   
    446.     release_mem_region(AT91SAM9260_BASE_TC0, SZ_16K);   
    447. adc_iounmap:   
    448.     iounmap(adc->membase);   
    449. adc_release_mem:   
    450.     release_mem_region(AT91SAM9260_BASE_ADC, SZ_16K);   
    451.     kfree(adc);   
    452.     return ret;   
    453. }   
    454.    
    455.            
    456. static void __exit adc_exit(void)   
    457. {   
    458.     //platform_driver_unregister(&adc_driver);   
    459.     unregister_chrdev_region(adc->devt, ADC_MAX_CHANNEL);   
    460.     class_destroy(adc->class);   
    461.     free_irq(adc->irq, adc);   
    462.     iounmap(adc->tcbbase);   
    463.     release_mem_region(AT91SAM9260_BASE_TC0, SZ_16K);   
    464.     iounmap(adc->membase);   
    465.     release_mem_region(AT91SAM9260_BASE_ADC, SZ_16K);   
    466.     kfree(adc);   
    467. }   
    468.    
    469.    
    470. module_init(adc_init);   
    471. module_exit(adc_exit);   
    472.    
    473. MODULE_AUTHOR("jiang ming bo ");   
    474. MODULE_LICENSE("GPL");   
    475. MODULE_DESCRIPTION("AT91 Analog-to-Digital Converter Driver");   
    476.    
     

  • 相关阅读:
    如何很好的使用Linq的Distinct方法
    根据字符串获取对应类型(Type) 转
    .Net 读取xml
    认识ASP.NET MVC的5种AuthorizationFilter
    使用admin插入数据失败
    乱序批量精确修改文件名
    多进程+协程方案处理高IO密集,提升爬取效率
    Linux 安装 CMake
    Ubuntu 截图工具deepin-screenshot添加使用
    Linux virtualenv .bashrc配置文件
  • 原文地址:https://www.cnblogs.com/zym0805/p/5863694.html
Copyright © 2011-2022 走看看