sam9260 adc module
- /*
- * driver/char/at91_adc.c
- *
- * Copyright (C) 2007 Embedall Technology Co., Ltd.
- *
- * Analog-to-digital Converter(ADC) Driver.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
- #include <linux/types.h>
- #include <linux/init.h>
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/version.h>
- #include <linux/spinlock.h>
- #include <linux/interrupt.h>
- #include <linux/platform_device.h>
- #include <linux/cdev.h>
- #include <linux/fs.h>
- #include <linux/ioctl.h>
- #include <linux/poll.h>
- #include <linux/at91_adc.h>
- #include <asm/arch/hardware.h>
- #include <asm/arch/gpio.h>
- #include <asm/arch/at91_adc.h>
- #include <asm/arch/at91_tc.h>
- #include <asm/arch/at91_pmc.h>
- #define DRV_NAME "at91_adc"
- #define DEV_NAME "adc0"
- #define adc_readl(adc,reg) (__raw_readl((adc)->membase + (reg)))
- #define adc_writel(adc,reg,v) (__raw_writel((v), (adc)->membase + (reg)))
- #define tc_readl(adc,reg) (__raw_readl((adc)->tcxbase + (reg)))
- #define tc_writel(adc,reg,v) (__raw_writel((v), (adc)->tcxbase + (reg)))
- #define ADC_MAX_CHANNEL CONFIG_AT91_ADC_CHANNELS
- #define BUF_SIZE 8
- //#define buf_cnt(channel) (((channel)->head - (channel)->tail) & ((BUF_SIZE)-1))
- //#define buf_space(channel) (((channel)->tail-((channel)->head+1))&(BUF_SIZE-1))
- struct adc;
- static int minor_num = 0;
- static int major_num = 0;
- struct adc_channel
- {
- struct cdev cdev;
- struct device *dev;
- struct class_device *class_dev;
- int id;
- int adc_data;
- int head;
- int tail;
- struct fasync_struct *fasync;
- struct adc *adc;
- };
- struct adc
- {
- dev_t devt;
- struct class *class;
- void __iomem *membase;
- void __iomem *tcbbase;
- void __iomem *tcxbase;
- unsigned int irq;
- struct adc_mode mode;
- spinlock_t lock;
- struct adc_channel *channel[ADC_MAX_CHANNEL];
- };
- static struct adc *adc;
- static inline int buf_in(struct adc_channel *channel, int v)
- {
- channel->adc_data = v;
- //channel->head = (channel->head + 1) & (BUF_SIZE - 1);
- return channel->adc_data;
- }
- static int adc_init_tc(struct adc *adc)
- {
- unsigned int dummy = 0;
- spin_lock(&adc->lock);
- if (adc->mode.trigger != ADC_TRIGGER_TIMER) {
- at91_sys_write(AT91_PMC_PCDR, 1 << AT91SAM9260_ID_TC2);
- spin_unlock(&adc->lock);
- return 0;
- }
- tc_writel(adc, AT91_TC_CCR, AT91_TC_CLKDIS);
- dummy |= (AT91_TC_TIMER_CLOCK5 | AT91_TC_CPCTRG | AT91_TC_WAVE |
- AT91_TC_WAVESEL_UP_AUTO | AT91_TC_ACPA_SET |
- AT91_TC_ACPC_CLEAR );
- tc_writel(adc, AT91_TC_CMR, dummy);
- if (adc->mode.trigger_time) {
- dummy = (adc->mode.trigger_time*1000000)/(1000000000/32768);
- if (dummy > 0xffff) dummy = 0xffff;
- tc_writel(adc, AT91_TC_RC, dummy);
- tc_writel(adc, AT91_TC_RA, dummy * 3 / 5);
- } else {
- tc_writel(adc, AT91_TC_RC, 32768);
- tc_writel(adc, AT91_TC_RA, 32768 * 3 / 5);
- }
- at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9260_ID_TC2);
- tc_writel(adc, AT91_TC_CCR, AT91_TC_CLKEN | AT91_TC_SWTRG);
- spin_unlock(&adc->lock);
- return 0;
- }
- static int adc_hw_init(struct adc *adc)
- {
- adc_writel(adc, AT91_ADC_CR, AT91_ADC_SWRST);
- adc_writel(adc, AT91_ADC_IER, AT91_ADC_DRDY);
- at91_sys_write(AT91_PMC_PCER, 1 << adc->irq);
- return 0;
- }
- static int adc_fasync(int fd, struct file *file, int mode)
- {
- struct adc_channel *channel = file->private_data;
- return fasync_helper(fd, file, mode, &channel->fasync);
- }
- static int adc_open(struct inode *inode, struct file *file)
- {
- struct adc *adc;
- struct adc_channel *channel;
- channel = container_of(inode->i_cdev, struct adc_channel, cdev);
- file->private_data = channel;
- adc = channel->adc;
- spin_lock(&adc->lock);
- at91_set_multi_drive(PIN_BASE + 0x40 + channel->id, 1);
- adc_writel(adc, AT91_ADC_IER, (1 << channel->id));
- adc_writel(adc, AT91_ADC_CHER, (1 << channel->id));
- spin_unlock(&adc->lock);
- return nonseekable_open(inode, file);
- }
- static int adc_release(struct inode *inode, struct file *file)
- {
- struct adc *adc;
- struct adc_channel *channel;
- channel = container_of(inode->i_cdev, struct adc_channel, cdev);
- adc = channel->adc;
- // adc_fasync(-1, file, 0);
- spin_lock(&adc->lock);
- adc_writel(adc, AT91_ADC_IDR, 1 << channel->id);
- adc_writel(adc, AT91_ADC_CHDR, 1 << channel->id);
- spin_unlock(&adc->lock);
- return 0;
- }
- static ssize_t adc_read(struct file *file, char __user *buf, size_t count, loff_t *f_pos)
- {
- return 0;
- }
- static ssize_t adc_write(struct file *file, const char __user *buf, size_t count, loff_t *f_pos)
- {
- return 0;
- }
- /* static void adc_sigio(struct adc_channel *channel) */
- /* { */
- /* if (channel->fasync) */
- /* kill_fasync(&channel->fasync, SIGIO, POLL_IN); */
- /* } */
- static int adc_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
- {
- struct adc *adc;
- struct adc_channel *channel;
- struct adc_mode *mode;
- int ret = 0;
- unsigned int dummy = 0;
- void __user *argp = (void __user *)arg;
- int __user *p = argp;
- channel = container_of(inode->i_cdev, struct adc_channel, cdev);
- adc = channel->adc;
- mode = &adc->mode;
- switch (cmd) {
- case ADCCTL_RESET:
- adc_writel(adc, AT91_ADC_CR, AT91_ADC_SWRST);
- return 0;
- case ADCCTL_START:
- adc_writel(adc, AT91_ADC_CR, AT91_ADC_START);
- return 0;
- case ADCCTL_SETMODE:
- ret = copy_from_user(mode, argp, sizeof(struct adc_mode));
- if (mode->trigger == ADC_TRIGGER_TIMER)
- dummy |= AT91_ADC_TRGEN | AT91_ADC_TRGSEL_TC2;
- else if (mode->trigger == ADC_TRIGGER_EXT)
- dummy |= AT91_ADC_TRGEN | AT91_ADC_TRGSEL_EXT;
- if (mode->resolution & ADC_M_8BIT)
- dummy |= AT91_ADC_LOWRES;
- if (mode->sleep_mode)
- dummy |= AT91_ADC_SLEEP;
- if (mode->adc_clock)
- dummy |= AT91_ADC_PRESCAL_(mode->adc_clock);
- if (mode->startup_time)
- dummy |= AT91_ADC_STARTUP_(mode->startup_time);
- if (mode->sample_time)
- dummy |= AT91_ADC_SHTIM_(mode->sample_time);
- adc_init_tc(adc);
- spin_lock(&adc->lock);
- adc_writel(adc, AT91_ADC_MR, dummy);
- spin_unlock(&adc->lock);
- return 0;
- case ADCCTL_GETMODE:
- ret = copy_to_user(argp, mode, sizeof(struct adc_mode));
- return 0;
- case ADCCTL_GETDATA:
- // ret = buf_cnt(channel);
- // if (ret > 0) {
- // if (!put_user(channel->buf[channel->tail], p))
- // channel->tail = (channel->tail + 1) & (BUF_SIZE -1);
- //return 0;
- //}
- put_user(channel->adc_data,p);
- return -EFAULT;
- // case ADCCTL_GETCNT:
- // return put_user(buf_cnt(channel), p);
- case ADCCTL_GETSTATUS:
- return put_user(adc_readl(adc, AT91_ADC_SR), p);
- default:
- return -EINVAL;
- }
- return -EINVAL;
- }
- static struct file_operations adc_fops = {
- .owner = THIS_MODULE,
- .read = adc_read,
- .write = adc_write,
- .open = adc_open,
- .release = adc_release,
- .ioctl = adc_ioctl,
- .fasync = adc_fasync,
- };
- static irqreturn_t adc_interrupt(int irq, void *dev_id)
- {
- struct adc *adc = dev_id;
- struct adc_channel *channel;
- unsigned int status;
- status = adc_readl(adc, AT91_ADC_SR) & adc_readl(adc, AT91_ADC_IMR);
- while (status) {
- printk(KERN_DEBUG "at91_adc: interrupt status reg 0x%08x\n",
- status);
- if (status & AT91_ADC_EOC0){
- channel = adc->channel[0];
- buf_in(channel, adc_readl(adc, AT91_ADC_CDR0));
- printk(KERN_INFO "the adc_data is %d\n",channel->adc_data);
- // adc_sigio(channel);
- }
- if (status & AT91_ADC_EOC1){
- channel = adc->channel[1];
- buf_in(channel, adc_readl(adc, AT91_ADC_CDR1));
- printk(KERN_INFO "the adc_data is %d\n",channel->adc_data);
- // adc_sigio(channel);
- }
- if (status & AT91_ADC_EOC2){
- channel = adc->channel[2];
- buf_in(channel, adc_readl(adc, AT91_ADC_CDR2));
- printk(KERN_INFO "the adc_data is %d\n",channel->adc_data);
- // adc_sigio(channel);
- }
- if (status & AT91_ADC_EOC3) {
- channel = adc->channel[3];
- buf_in(channel, adc_readl(adc, AT91_ADC_CDR3));
- printk(KERN_INFO "the adc_data is %d\n",channel->adc_data);
- // adc_sigio(channel);
- }
- if (status & AT91_ADC_DRDY)
- adc_readl(adc, AT91_ADC_LCDR);
- status = adc_readl(adc, AT91_ADC_SR) & adc_readl(adc, AT91_ADC_IMR);
- }
- return IRQ_HANDLED;
- }
- static int __exit adc_remove(struct platform_device *pdev)
- {
- struct adc_channel *channel = platform_get_drvdata(pdev);
- class_device_unregister(channel->class_dev);
- cdev_del(&channel->cdev);
- kfree(channel);
- return 0;
- }
- static struct platform_device adc_channel_device[ADC_MAX_CHANNEL];
- /*
- static int __init adc_add_channel_device(void)
- {
- int i;
- for (i=0; i<ADC_MAX_CHANNEL; i++){
- adc_channel_device[i].name = DRV_NAME;
- adc_channel_device[i].id = i;
- platform_device_register(&adc_channel_device[i]);
- }
- return 0;
- }
- */
- static int __init adc_init(void)
- {struct adc_channel *channel;
- int ret = 0;
- //struct adc_channel *channel;
- int ret1;
- adc = kmalloc(sizeof(struct adc), GFP_KERNEL);
- if (!adc)
- return -ENOMEM;
- if (!request_mem_region(AT91SAM9260_BASE_ADC, SZ_16K, DRV_NAME)){
- kfree(adc);
- return -EBUSY;
- }
- adc->membase = ioremap(AT91SAM9260_BASE_ADC, SZ_16K);
- if (adc->membase == NULL)
- goto adc_release_mem;
- if (!request_mem_region(AT91SAM9260_BASE_TC0, SZ_16K, DRV_NAME))
- goto adc_iounmap;
- adc->tcbbase = ioremap(AT91SAM9260_BASE_TC0, SZ_16K);
- if (adc->tcbbase == NULL)
- goto adc_release_mem_tc;
- adc->irq = AT91SAM9260_ID_ADC;
- adc->tcxbase = adc->tcbbase + 0x80;
- spin_lock_init(&adc->lock);
- adc->class = class_create(THIS_MODULE, DEV_NAME);
- if (IS_ERR(adc->class)){
- printk(KERN_ERR "at91_adc: faile to create device class\n");
- goto adc_iounmap_tc;
- }
- ret = alloc_chrdev_region(&adc->devt, 0, 1, DEV_NAME);
- if (ret < 0) {
- printk(KERN_ERR"%s: failed to allocate dev region\n", __FILE__);
- goto adc_destroy_class;
- }
- if (request_irq(adc->irq, adc_interrupt, IRQF_SHARED, DRV_NAME, adc)){
- printk(KERN_ERR"%s: request irq failed\n", __FILE__);
- goto adc_del_channel;
- }
- adc_hw_init(adc);
- printk(KERN_INFO "&&123456xx\n");
- //platform_driver_register(&adc_driver);
- printk(KERN_INFO "Analog-to-Digital Converter (irq %d)\n", adc->irq);
- // adc_add_channel_device();
- printk(KERN_ERR "&&123456&&\n");
- channel = kmalloc(sizeof(struct adc_channel), GFP_KERNEL);
- if (!channel){
- printk(KERN_ERR "&&123456&&\n");
- //printk(KERN_ERR "at91_adc: failed to kmalloc channel %d\n", pdev->id);
- return -ENOMEM;
- }
- // channel->fasync = kmalloc(sizeof(struct fasync_struct), GFP_KERNEL);
- // if (!channel->fasync) return -ENOMEM;
- channel->id = 0;
- //channel->dev = &pdev->dev;
- channel->adc = adc;
- channel->head = 0;
- channel->tail = 0;
- cdev_init(&channel->cdev, &adc_fops);
- channel->cdev.owner = THIS_MODULE;
- ret1 = cdev_add(&channel->cdev, MKDEV(MAJOR(adc->devt), channel->id), 1);
- if (ret1) {
- //printk(KERN_ERR "at91_adc: failed to add channel %d device\n", pdev->id);
- kfree(channel);
- return ret1;
- }
- channel->class_dev = class_device_create(adc->class, NULL,
- MKDEV(MAJOR(adc->devt),
- channel->id),
- NULL,
- DEV_NAME);
- if (IS_ERR(channel->class_dev)) {
- cdev_del(&channel->cdev);
- kfree(channel);
- return PTR_ERR(channel->class_dev);
- }
- adc->channel[channel->id] = channel;
- //platform_set_drvdata(pdev, channel);
- printk(KERN_INFO "at91_adc. major is %d\n",
- MAJOR(adc->devt));
- return 0;
- adc_del_channel:
- unregister_chrdev_region(adc->devt, 1);
- adc_destroy_class:
- class_destroy(adc->class);
- adc_iounmap_tc:
- iounmap(adc->tcbbase);
- adc_release_mem_tc:
- release_mem_region(AT91SAM9260_BASE_TC0, SZ_16K);
- adc_iounmap:
- iounmap(adc->membase);
- adc_release_mem:
- release_mem_region(AT91SAM9260_BASE_ADC, SZ_16K);
- kfree(adc);
- return ret;
- }
- static void __exit adc_exit(void)
- {
- //platform_driver_unregister(&adc_driver);
- unregister_chrdev_region(adc->devt, ADC_MAX_CHANNEL);
- class_destroy(adc->class);
- free_irq(adc->irq, adc);
- iounmap(adc->tcbbase);
- release_mem_region(AT91SAM9260_BASE_TC0, SZ_16K);
- iounmap(adc->membase);
- release_mem_region(AT91SAM9260_BASE_ADC, SZ_16K);
- kfree(adc);
- }
- module_init(adc_init);
- module_exit(adc_exit);
- MODULE_AUTHOR("jiang ming bo ");
- MODULE_LICENSE("GPL");
- MODULE_DESCRIPTION("AT91 Analog-to-Digital Converter Driver");
sam9260 adc module的更多相关文章
- sam9260 adc 测试
/* * adc_test.c * * Copyright (C) 2007 Mengrz */ #include <stdio.h> #include <stdlib.h> ...
- sam9260 adc 头文件
/* * driver/char/at91_adc.h * * Copyright (C) 2007 Embedall Technology Co., Ltd. * * Analog-to-digit ...
- mini2440驱动奇谭——ADC驱动与測试(动态挂载驱动)
博客:http://blog.csdn.net/muyang_ren 实现功能:开发板动态载入adc驱动模块并能通过測试程序 系统:Ubuntu 14.04 驱动交叉编译内核:linux-2. ...
- NUC131演示如何通过PWM触发ADC。
今天我来讲讲PWM触发ADC的例程 /**************************************************************************** * @f ...
- [转]A Guide To using IMU (Accelerometer and Gyroscope Devices) in Embedded Applications.
原文地址http://www.starlino.com/imu_guide.html Introduction There’s now a FRENCH translation of this art ...
- Unused port adds a PWM/analog channel to a microcontroller
Low-cost, 8-bit, single-chip microcontrollers are stingy when it comes to on-chip PWM (pulse-width-m ...
- [蓝牙] 5、Battery Service module
Detailed Description This module implements the Battery Service with the Battery Level characteristi ...
- 驱动之路四------adc驱动(input设备)
开发板:smdk6410 开发环境:Linux 突然想起一点,写这些驱动,内核需要配成支持抢占才行. 前面的博客已经将其它的基本知识都解释了,这里也就不过多的阐述了,咱就直接写代码吧 这次写的是adc ...
- STM32F207 两路ADC连续转换及GPIO模拟I2C给MT9V024初始化参数
1.为了更好的方便调试,串口必须要有的,主要打印一些信息,当前时钟.转换后的电压值和I2C读出的数据. 2.通过GPIO 模拟I2C对镁光的MT9V024进行参数初始化.之前用我以前公司SP0A19芯 ...
随机推荐
- 嵌入式Linux下MP4视频录制库MP4V2移植和简单介绍
**************************************************************************************************** ...
- Python 爬虫 数据清洗 去掉 超链接
有时候我们需要清洗数据,里面有超链接,怎么去掉他们,比如下面的问题 , - January , </p></li><li </p><div " ...
- 命令行运行python项目文件,报错:ModuleNotFoundError: No module named 'xxxx' 解决办法
在pycharm中写好了自动化测试脚本,并能在pycharm中正常运行,由于要考虑到无人值守时能自动执行,执行时就需要脱离pycharm,直接能用命令执行.但是直接用命令执行用例文件:python3 ...
- iOS常用RGB颜色的色值表
常用RGB颜色表 R G B 值 R G B 值 R G B 值 黑色 0 0 0 #000000 黄色 255 255 0 #FFFF00 浅灰蓝色 176 224 230 #B0E0E6 象牙黑 ...
- unity, ios skin crash
https://issuetracker.unity3d.com/issues/ios-loading-models-with-tangents-set-to-calculate-legacy-fro ...
- MySql(二):MySql架构组成
主要架构就是这张图展示的 具体细节看下面文章: MySql 物理文件组成 MySQL 自带工具使用介绍 Mysql Server系统架构介绍
- IOS开发之UIScrollVIew运用
UIScrollView可以实现在一个界面看到所有内容,同时也不需要担心所显示的内容超出屏幕的大小,当超出之后可以翻阅至下一页浏览. #pragma mark - UIScrollViewDelega ...
- 台式机vim配置
set autoread syntax on "set number " filetype ident on "set autoindent "set expa ...
- haproxy 配置https 同时技持443 80端口
确定haproxy支持https [root@c01 sbin]# ldd haproxy |grep ssl libssl.so.10 => /usr/lib64/libssl.so.10 ( ...
- 数据库存储引擎 show engines 修改引擎
mysql> show engines; +--------------------+---------+-------------------------------------------- ...