linux24内核驱动,linux2.6.24.4内核adc驱动

/*

* s3c2410-adc.c

*

* S3C2410 ADC

*exclusive with s3c2410-ts.c

*

* Author: SeonKon Choi

* Date: $Date: 2003/01/20 14:24:49 $

*

* $Revision: 1.1.2.6 $

*

2008-6-14 add a device by lyj_uptech

Fri Dec 03 2002 SeonKon Choi

- initial

*

* This file is subject to the terms and conditions of the GNU General Public

* License.See the file COPYING in the main directory of this archive

* for more details.

*/

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include 3c/regs-adc.h>

#include

#include

#include

#include

#include

#include

#include

#include

#include "s3c2410-adc.h"

MODULE_LICENSE("Dual BSD/GPL");

int adc_major;

int adc_minor;

struct cdev adc_cdev;

static void __iomem *base_addr;

struct clk *clk;

static int ch;

int adc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)

{

printk(KERN_ERR "cmd %d\n",cmd);

ch=cmd; //set up channel

return 0;

}

ssize_t s3c2410_adc_read(struct file *filp,char __user *buf,size_t count,loff_t *f_pos)

{

int i,LOOP=10000;

clk_enable(clk); //enable clk

writel((1<<14)|S3C2410_ADCCON_PRSCVL(49)|(ch<<3)|(0<<1)|(0<<0),base_addr+S3C2410_ADCCON); //setup channel

for(i=0;i

writel((readl(base_addr+S3C2410_ADCCON)|0x1),base_addr+S3C2410_ADCCON); //start ADC

while((readl(base_addr+S3C2410_ADCCON) & 0x1)); //check if enable start flag is low

while(!(readl(base_addr+S3C2410_ADCCON) & 0x8000)); //check if EC(End of Conversion) flag is high

writel(0,base_addr+S3C2410_ADCCON); //stop ADC

i=readl(base_addr+S3C2410_ADCDAT0);

i= i & 0x3ff;

copy_to_user(buf, &i, sizeof i);

return sizeof i;

}

static ssize_t s3c2410_adc_write(struct file *file, const char *buffer, size_t count, loff_t * ppos)

{

int data;

if(count!=sizeof(data)){

printk("the size ofinput data must be %d\n", sizeof(data));

return 0;

}

copy_from_user(&data, buffer, count);

ch=ADC_WRITE_GETCH(data);

return count;

}

struct file_operations adc_fops = {

.owner = THIS_MODULE,

.ioctl = adc_ioctl,

.read = s3c2410_adc_read,

.write = s3c2410_adc_write,

};

int S3C2410adc_init(void)

{

int result,err;

dev_t dev =0;

result=alloc_chrdev_region(&dev,adc_minor,0,"2410adc");

adc_major = MAJOR(dev);

adc_minor = MINOR(dev);

if(result < 0)

printk(KERN_ERR "can't get major %d\n",adc_major);

else

printk("adc_major: %d\n",adc_major);

cdev_init(&adc_cdev,&adc_fops);

adc_cdev.owner=THIS_MODULE;

adc_cdev.ops=&adc_fops;

err=cdev_add(&adc_cdev,dev,1);

if (err < 0)

printk(KERN_ERR "can't add 2410_adc");

base_addr = ioremap(0x58000000, 0x20);

if (base_addr == NULL) {

printk(KERN_ERR "Failed to remap register block\n");

return -ENOMEM;

}

/* get our clock */

clk = clk_get(NULL, "adc");

if (IS_ERR(clk) || clk == NULL) {

printk(KERN_ERR "ADC clk_get err!!!!!!!!!!!!!\n");

}

/* only enable the clock when we are actually using the adc */

printk(KERN_ERR "add 2410_adc ok!!!!!!!!!!!!\n");

return 0;

}

void S3C2410adc_exit(void)

{

dev_t dev=MKDEV(adc_major,adc_minor);

cdev_del(&adc_cdev);

iounmap(base_addr);

unregister_chrdev_region(dev,1);

}

module_init(S3C2410adc_init);

module_exit(S3C2410adc_exit);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值