/*
* 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);