📄 adc.c
字号:
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/miscdevice.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
#include <linux/wait.h>
#include <linux/device.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/types.h>
#include <linux/cdev.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/arch/regs-mem.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch-s3c2410/regs-adc.h>
#include <asm/arch-s3c2410/regs-clock.h>
#include <asm-arm/arch-s3c2410/map.h>
#include "adc.h"
#define DEVICE_NAME "adc"
static void __iomem *base_addr;
static int adc_major = 0;
static ssize_t adc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
int data;
unsigned long tmp;
//start ADC
tmp = readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START;
writel( tmp, base_addr+S3C2410_ADCCON);
//state
do{
tmp = readl(base_addr+S3C2410_ADCCON);
}while(!(((unsigned int)tmp)&0x8000));
//read data
data = readl(base_addr+S3C2410_ADCDAT0) & 0x3ff;
if(copy_to_user(buf, &data, sizeof(int)))
return -EFAULT;
return (sizeof(int));
}
static ssize_t adc_write(struct file * file, const char __user * buf, size_t count, loff_t * off)
{
unsigned long tmp;
struct ADC_DEV adcdev;
copy_from_user(&adcdev,(struct ADC_DEV *)buf,sizeof(struct ADC_DEV));
//S3C2410_CLKCON
writel((readl(S3C2410_CLKCON) | S3C2410_CLKCON_ADC),S3C2410_CLKCON);
//S3C2410_ADCTSC
tmp = readl(base_addr+S3C2410_ADCTSC);
tmp &= (~S3C2410_ADCTSC_AUTO_PST) | S3C2410_ADCTSC_XY_PST(S3C2410_NOP_MODE);
writel(tmp , base_addr+S3C2410_ADCTSC);
//S3C2410_ADCCON
tmp = readl(base_addr+S3C2410_ADCCON);
tmp = S3C2410_ADCCON_PRSCEN|S3C2410_ADCCON_PRSCVL(adcdev.prescale)|S3C2410_ADCCON_SELMUX(adcdev.channel);
writel( tmp, base_addr+S3C2410_ADCCON);
return 0;
}
static int adc_open(struct inode * inode, struct file * filp)
{
return 0;
}
static int adc_release(struct inode * inode, struct file * filp)
{
return 0;
}
static struct file_operations adc_fops = {
.owner = THIS_MODULE,
.write = adc_write,
.read = adc_read,
.open = adc_open,
.release=adc_release,
};
static int __init adc_init(void)
{
int ret;
ret = register_chrdev(0,DEVICE_NAME,&adc_fops);
if(ret < 0)
{
printk("adc: can't get major number\n");
return ret;
}
adc_major = ret;
#ifdef CONFIG_DEVFS_FS
ret = devfs_mk_cdev(MKDEV(adc_major,0), S_IFCHR | S_IRUGO | S_IWUSR,DEVICE_NAME);
if(ret)
{
unregister_chrdev(adc_major,DEVICE_NAME);
printk("adc: can't make char device fo devfs\n");
return ret;
}
#endif
base_addr=ioremap(S3C2410_PA_ADC,4);
if (base_addr == NULL)
{
printk(KERN_ERR "Failed to remap register block\n");
return -ENOMEM;
}
printk("s3c2410_adc driver initial\n");
return 0;
}
static void __exit adc_exit(void)
{
#ifdef CONFIG_DEVFS_FS
devfs_remove(DEVICE_NAME);
#endif
unregister_chrdev(adc_major,DEVICE_NAME);
iounmap(base_addr);
printk("s3c2410_adc driver removed\n");
}
module_init(adc_init);
module_exit(adc_exit);
MODULE_ALIAS("adc");
MODULE_DESCRIPTION("ADC IO Driver For EM104-MINI2410");
MODULE_AUTHOR("LIANXJ");
MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -