本人已经解决,程序如下
#include<linux/module.h>
#include<mach/regs-gpio.h>
#include<mach/hardware.h>
#include <linux/device.h>
#include<linux/kernel.h>
#include <linux/fs.h>
#include <asm/irq.h>
#include<linux/sched.h>
#include<linux/timer.h>
#include<linux/init.h>
#include <linux/clk.h>
#include <plat/regs-timer.h>
#include <asm/io.h>
#include <plat/regs-adc.h>
#include<linux/interrupt.h>
#include <asm/uaccess.h>
#define DEVICE_NAME "lvl-adc"
#define ADC_MAJOR 234
static void __iomem *adc_base;
static int adc_data;
static struct clk *adc_clk;
extern struct semaphore ADC_LOCK;
//DEFINE_MUTEX(ADC_LOCK);
static volatile int ev_adc = 0;
static DECLARE_WAIT_QUEUE_HEAD(adc_waitq);
static irqreturn_t adc_irq(int irq, void *dev_id)
{
if(!ev_adc)
{
adc_data = readl(adc_base + S3C2410_ADCDAT0) & 0x3ff;
ev_adc = 1;
wake_up_interruptible(&adc_waitq);
}
return IRQ_HANDLED;
}
static int lvl_adc_open(struct inode *inode, struct file *file)
{
int ret;
ret = request_irq(IRQ_ADC, (void *)adc_irq, IRQF_SHARED, DEVICE_NAME, 1);
if (ret)
{
printk(KERN_ERR "IRQ%d error %d\n", IRQ_ADC, ret);
return -EINVAL;
}
return 0;
}
static int lvl_adc_close(struct inode *inode, struct file *file)
{
return 0;
}
static ssize_t lvl_adc_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)
{
//if (mutex_trylock(&ADC_LOCK) == 0)
if (down_trylock(&ADC_LOCK) )
{
return -EBUSY;
}
if(!ev_adc)
{
if(filp->f_flags & O_NONBLOCK)
{
return -EAGAIN;
}
else
{
unsigned int tmp;
tmp=(1<<14)|(255<<6)|(1<<4)| (1 << 0);
writel(tmp, adc_base + S3C2410_ADCCON);
wait_event_interruptible(adc_waitq, ev_adc);
}
}
ev_adc = 0;
copy_to_user(buffer, (char *)&adc_data, sizeof(adc_data));
up(&ADC_LOCK);
return sizeof(adc_data);
}
static struct file_operations lvl_adc_fops =
{
.owner = THIS_MODULE,
.open = lvl_adc_open,
.release = lvl_adc_close,
.read = lvl_adc_read,
};
static struct class *adc_class;
static char __initdata banner[] = "lvlei adc test\n";
static int __init lvl_adc_init(void)
{
int ret;
printk(banner);
ret = register_chrdev(ADC_MAJOR, DEVICE_NAME, &lvl_adc_fops);
if (ret < 0)
{
printk(DEVICE_NAME " can't register major number\n");
return ret;
}
adc_class = class_create(THIS_MODULE, DEVICE_NAME);
if(IS_ERR(adc_class))
{
printk("Err: failed in EmbedSky-adc class. \n");
return -1;
}
device_create(adc_class, NULL, MKDEV(ADC_MAJOR, 0), NULL, DEVICE_NAME);
adc_base = ioremap(S3C2410_PA_ADC, 0x20);
printk(DEVICE_NAME " initialized\n");
adc_clk = clk_get(NULL, "adc");
if (!adc_clk)
{
printk(KERN_ERR "failed to find adc clock source\n");
return -ENOENT;
}
clk_enable(adc_clk);
return 0;
}
static void __exit lvl_adc_exit(void)
{
unregister_chrdev(ADC_MAJOR, DEVICE_NAME);
device_destroy(adc_class, MKDEV(ADC_MAJOR, 0));
class_destroy(adc_class);
iounmap(adc_base);
if (adc_clk)
{
clk_disable(adc_clk);
clk_put(adc_clk);
adc_clk = NULL;
}
}
//EXPORT_SYMBOL(ADC_LOCK);
module_init(lvl_adc_init);
module_exit(lvl_adc_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("lv lei");
MODULE_DESCRIPTION("my2440 adc driver");
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
int main(void)
{
int fd,ret,val;
char i;
fd = open("/dev/lvl-adc", O_RDWR);
if(fd < 0)
{
printf("Open ADC Device Faild!\n");
exit(1);
}
else
{
for (i=f0;i<50;i++)
{
ret=read(fd, &val, sizeof(val));
if (ret==sizeof(val))
printf ("val= %d\n",val);
usleep(500000);
}
ret= close(fd);
printf("close adc driver test\n");
}
return 0;
}
|