#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/gpio.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <mach/regs-clock.h>
#include <plat/regs-timer.h>
#include <plat/regs-adc.h>
#include <mach/regs-gpio.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/poll.h>
static DECLARE_WAIT_QUEUE_HEAD(adc_wait);
static int major=0;
static int adc_flage=0;
static struct clk *adc_clock;
struct cdev adc_devices;
static struct class *adc_class;
static struct class_device *adc_class_dev;
static volatile unsigned long *adccon;
static volatile unsigned long *adctsc;
static volatile unsigned long *adcdly;
static volatile unsigned long *adcdat0;
static volatile unsigned long *adcdat1;
static volatile unsigned long *adcupdn;
static void adc_start()
{
*adccon |=0x01;
}
static irqreturn_t s3c2410_adc_irq(int irq, void *dev_id)
{
adc_flage=1;
wake_up_interruptible(&adc_wait);
return IRQ_RETVAL(IRQ_HANDLED);
}
static int s3c2410_adc_open(struct inode *inode, struct file *file)
{
int re;
adccon = ioremap(0x58000000,4); /*映射adc寄存器*/
adcdat0 = ioremap(0x5800000c,4);
re=request_irq(IRQ_ADC,s3c2410_adc_irq,IRQF_SHARED,"2410adc",1);
if(re<0)
{
printk("%s %s %d\n",__FILE__,__FUNCTION__,__LINE__);
}
return 0;
}
static ssize_t adc_drv_read (struct file *file, char __user *buf, size_t size, loff_t * opps)
{
int data0;
int data1;
wait_event_interruptible(adc_wait,adc_flage);
data1=*adcdat0;
data0=data1&0x3ff;/*读出转换数据*/
copy_to_user(buf,&data0,sizeof(data0));/*拷贝到用户空间*/
adc_flage=0;
adc_start();
return size;
}
static ssize_t s3c2410_adc_write (struct file *file, const char __user *buf, size_t size, loff_t *opps)
{
char val;
static char chanel;
copy_from_user(&val, buf, 1);
chanel=val;
switch(chanel)
{
case 0:
*adccon = ((0x01 << 14)|(0xff<<6)|(0x00<< 3)) ; /*分频使能*/
break;
case 1:
*adccon = ((0x01 << 14)|(0xff<<6)|(0x01<< 3)) ; /*分频使能*/
break;
case 2:
*adccon = ((0x01 << 14)|(0xff<<6)|(0x02<< 3)) ; /*分频使能*/
break;
case 3:
*adccon = ((0x01 << 14)|(0xff<<6)|(0x03<< 3)) ; /*分频使能*/
break;
}
adc_start();
return 0;
}
static loff_t s3c2410_adc_llseek (struct file *file, loff_t offset, int orig)
{
loff_t ret=0;
file->f_pos=(unsigned int )offset;
ret=file->f_pos;
return ret;
}
static void s3c2410_adc_close(struct inode *inode, struct file *file)
{
return 0;
}
static struct file_operations s3c2410_adc_ops = {
.owner = THIS_MODULE,
.open = s3c2410_adc_open,
.write = s3c2410_adc_write,
.read = adc_drv_read,
.release = s3c2410_adc_close,
};
static dev_t s3c2410_dev;
static int s3c2410_adc_init(void)
{
int ret;
int error;
int re;
adc_clock = clk_get(NULL, "adc");
clk_enable(adc_clock);
s3c2410_dev = MKDEV(major, 0);
if (major)
ret = register_chrdev_region(s3c2410_dev, 1, "adc_devices");
else {
ret = alloc_chrdev_region(&s3c2410_dev, 0, 1, "adc_devices");
major = MAJOR( s3c2410_dev);
}
if (ret < 0)
{
printk(KERN_WARNING "adc_devices: File exists: unable to get major %d\n", major);
return ret;
}
cdev_init(&adc_devices, &s3c2410_adc_ops);
if ((ret = cdev_add(&adc_devices,s3c2410_dev, 1)) != 0) {
printk(KERN_ERR "dvb-core: unable register character device\n");
goto error;
}
adc_class=class_create(THIS_MODULE, "adc_devices"); /*创建类*/
if (IS_ERR(adc_class)) {
ret = PTR_ERR(adc_class);
goto error;
}
adc_class_dev= device_create(adc_class, NULL, MKDEV(major, 0), NULL, "2410adc");
if (!adc_class_dev) {
printk(KERN_ERR "device_create failed for adc_drv\n");
goto error;
}
return 0;
error:
cdev_del(&adc_devices);
unregister_chrdev_region(s3c2410_dev, 1);
return ret;
}
static void s3c2410_adc_exit(void)
{
iounmap(adccon);
iounmap(adcdat0);
clk_disable(adc_clock);
clk_put(adc_clock);
free_irq(IRQ_ADC, NULL);
cdev_del(&adc_devices);
unregister_chrdev_region(s3c2410_dev, 1);
device_destroy( adc_class_dev, s3c2410_dev);
class_destroy(adc_class);
return 0;
}
module_init(s3c2410_adc_init);
module_exit(s3c2410_adc_exit);
MODULE_AUTHOR("4M小水管");
MODULE_LICENSE("GPL");