本帖最后由 月骅 于 2012-9-5 12:47 编辑
/*************************************
NAME:EmbedSky_hello.c
COPYRIGHT:www.embedsky.net
*************************************/
#include <linux/miscdevice.h>
#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/clk.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <mach/regs-clock.h>
#include <plat/regs-timer.h>
#include <linux/fs.h>
#include <plat/regs-adc.h>
#include <mach/regs-gpio.h>
#include <linux/cdev.h>
#include "tq2440_adc.h"
#include <linux/interrupt.h>
#undef DEBUG
#define DEBUG
#ifdef DEBUG
#define DPRINTK(x...) {printk(__FUNCTION__);printk("(%d): ",__LINE__);printk(x);}
#else
#define DPRINTK(x...) (void)(0)
#endif
#define DEVICE_NAME "adc"
static void __iomem *base_addr;
struct adc_dev
{
struct cdev cdev;
struct semaphore lock;
int channel;
int prescale;
};
struct adc_dev adc_dev;
struct adc_dev *adc_devp;
static struct clk *adc_clock;
#define START_ADC(ch, prescale) S3C2410_ADCCON_PRSCEN |S3C2410_ADCCON_PRSCVL(prescale) \
| S3C2410_ADCCON_SELMUX(ch) | S3C2410_ADCCON_ENABLE_START
static ssize_t adc_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)
{
unsigned long result=0;
unsigned int data;
if (down_interruptible(&adc_dev.lock))
return -ERESTARTSYS;
iowrite32(START_ADC(adc_dev.channel,adc_dev.prescale),base_addr + S3C2410_ADCCON);
do{
result=ioread32(base_addr+S3C2410_ADCCON);
}while((unsigned int)result&0x01);//ensure the start of conversion
do{
result=ioread32(base_addr+S3C2410_ADCCON);
}while(!(((unsigned int)result)&0x8000));//till the end of conversion
data = ioread32(base_addr + S3C2410_ADCDAT0) & 0x3ff;
copy_to_user(buffer,&data,sizeof(data));
up(&adc_dev.lock);
return sizeof(result);
}
static int adc_open(struct inode *inode, struct file *filp)
{
init_MUTEX(&adc_dev.lock);
filp->private_data = adc_devp;
adc_dev.channel=2;
adc_dev.prescale=0x13;
base_addr=ioremap(S3C2410_PA_ADC,0x20);
adc_clock=clk_get(NULL,"adc");
if (!adc_clock) {
DPRINTK("failed to get adc clock source\n");
return -ENOENT;
}
clk_enable(adc_clock);
DPRINTK( "ADC opened\n");
return 0;
}
static int adc_release(struct inode *inode, struct file *filp)
{
DPRINTK( "ADC closed\n");
return 0;
}
static struct file_operations adc_fops = {
owner: THIS_MODULE,
open: adc_open,
read: adc_read,
release: adc_release,
};
static struct miscdevice misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = DEVICE_NAME,
.fops = &adc_fops,
};
static int __init adc_init(void)
{
int ret;
ret=misc_register(&misc);
if(ret<0)
return ret;
adc_devp=kmalloc(sizeof(struct adc_dev),GFP_KERNEL);
if(!adc_devp)
ret=-ENOMEM;
memset(adc_devp,0,sizeof(struct adc_dev));
return 0;
return ret;
}
static void __exit adc_exit(void)
{
iounmap(base_addr);
if (adc_clock)
{
clk_disable(adc_clock);
clk_put(adc_clock);
adc_clock = NULL;
}
kfree(adc_devp);
misc_deregister(&misc);
}
module_init(adc_init);
module_exit(adc_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("jetsu.zju@gmail.com");
MODULE_DESCRIPTION("adc driver for my 10000 points");
————————————————————————————————————————————————————————————
改成了查询方式的ADC,还是不能达到1K points每秒啊,肿么办,求破。
|