/* driver/char/adc0809.c
* this is a adc0809 char device driver.
* Any problem pls contact [email]support@hhcn.com[/email]
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/interrupt.h>
#include <asm/irq.h>
#include <asm/arch/hardware.h>
#include <asm/arch/irqs.h>
#include <asm/io.h>
#include "adc0809_ioctl.h"
MODULE_LICENSE("GPL");
#define ADC0809_MAJOR 231
/*define the adc0809 major node is 231*/
#define adc0809_sle (*(volatile unsigned long *)ADC_GPACON)
#define adc0809_sle_data (*(volatile unsigned long *)ADC_GPADATA)
unsigned long ADC_GPACON, ADC_GPADATA;
static unsigned long ADC_0, ADC_1, ADC_2, ADC_3, ADC_4, ADC_5, ADC_6, ADC_7;
unsigned long ADC_DATA;
static unsigned int r_TCFG0,r_TCFG1,r_TCNTB1,r_TCMPB1,r_TCON,r_GPCCON;
//unsigned long adc_write_addr;
//unsigned long adc_read_addr;
int * adc_read_addr,* adc_write_addr;
devfs_handle_t devfs_adc;
void adc0809_interrupt(int,void *,struct pt_regs *);
int adc0809_open(struct inode *, struct file *);
int adc0809_release(struct inode *, struct file *);
//int adc0809_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
ssize_t adc0809_read(struct file *, char * , size_t , loff_t *);
ssize_t adc0809_write(struct file *, const char *, size_t , loff_t *);
static struct file_operations adc0809_fops = {
// ioctl: adc0809_ioctl, //根据参数确定读取的引脚;
open: adc0809_open, //选中片选NGCS2(初始化ADC0809的管脚配置),初始化adc_read_addr;
read: adc0809_read,
write: adc0809_write,
release: adc0809_release,
};
//struct timer_list timer_ForData; // 定时器
char data; //变量类型不同也会出错,之前使用unsigned long所得是一连串八位数字要么是-1
unsigned long addr;
int adc0809_sum=0;
/*------------中断处理函数------------------*/
void adc0809_interrupt(int irq,void *d,struct pt_regs *regs)
{
char adc0809_v=0,adc0809_u=0;
/*clear interrupt register for INT_TIMER0*/
SRCPND &= (~0x00000800); //bit11
INTPND = INTPND;
[b]/*---下面这一段使自己加的--------*/[/b]
data = (*(volatile unsigned long *) adc_read_addr);
if(data<200){adc0809_v=0;}
else adc0809_v=1;
if(adc0809_v<adc0809_u){adc0809_sum=adc0809_sum+1;}
else adc0809_sum=adc0809_sum;
adc0809_u=adc0809_v;
printk("data:%d\n",data);
printk("adc0809_u:%d\n",adc0809_u);
printk("adc0809_v:%d\n",adc0809_v);
printk("adc0809_sum:%d\n",adc0809_sum);
}
/*------- Open/close code for raw IO.-----*/
int adc0809_open(struct inode *inode, struct file *filp)
{
adc_read_addr = ADC_DATA;
adc_write_addr = ADC_1;
(*(volatile unsigned char *) adc_write_addr) = (char) 0;
printk("open ok\n");
return 0;
}
/*------------read()----------------*/
ssize_t adc0809_read(struct file *filp, char * buf,
size_t size, loff_t *offp)
{
char key;
key =adc0809_sum;
printk("key_driver:%d\n",key);
copy_to_user(buf,&key,1);//put_user(key,buf);
//printk("adc0809_read:adc_read_addr=0x%x\n",adc_read_addr);
return 1;
}
/*------------------write()-------------------------------*/
ssize_t adc0809_write(struct file *filp, const char *buf,
size_t size, loff_t *offp)
{
char key;
if (get_user(key, buf))
return -EFAULT;
printk("adc0809_write:adc_write_addr=0x%x; key = %c\n",adc_write_addr,key);
(*(volatile unsigned char *) adc_write_addr) = key;
//put_user(key,buf);
return 1;
}
/*----------------release()---------------------*/
int adc0809_release(struct inode *inode, struct file *filp)
{
printk("release ok\n");
return 0;
}
[b]/*---这里我吧ioctl函数给删除了 就是不使用它,而是在初始化函数中来选着引脚并赋值[/b]
Deal with ioctls against the raw-device control interface, to bind
and unbind other raw devices.
int adc0809_ioctl(struct inode *inode, //octl选着待测的引脚 并触发中断
struct file *flip, //就是给 是0809的寄存器 一旦这个引角得到一个触发信号
unsigned int command, //那么相应的管脚就工作,然后才能输出ADC_DATA
unsigned long arg)
{
int err = 0;
switch (command) {
case IOCTRL_ADC_0:
adc_write_addr = ADC_0;
//printk("adc0809_ioctl: adc addr: %x\n",adc_write_addr);
/* start collect and convert
(*(volatile unsigned char *) adc_write_addr) = (char) arg;
return 0;
case IOCTRL_ADC_1: //通道选择 因为ADC0809工作通道选择是由ADDC,ADDB,ADDA来实现的.
adc_write_addr = ADC_1;
(*(volatile unsigned char *) adc_write_addr) = (char) arg;
return 0;
default:
err = -EINVAL;
}
// adc_read_addr = ADC_DATA;
//adc_write_addr = ADC_2;
//(*(volatile unsigned char *) adc_write_addr) = (char) arg;
return err;
}
/*-------------------iormap()--地址影射函数---*/
static int address_map(void)
{
r_TCFG0 = ioremap(0x51000000,4); //定时器配置寄存器0
r_TCFG1 = ioremap(0x51000004,4); //定时器配置寄存器1
r_TCNTB1 = ioremap(0x51000018,4);
r_TCMPB1 = ioremap(0x5100001C,4);
r_TCON = ioremap(0x51000008,4);
r_GPCCON = ioremap(0x56000020,4);
ADC_GPACON = (unsigned int)ioremap(0x56000000,4); //物理寄存器的影射,个人认为这里都是指CPLD的物理寄存器
ADC_GPADATA = ioremap(0x56000004,4);
ADC_0 = ioremap(0x10000010,4);
ADC_1 = ioremap(0x10002010,4);
ADC_2 = ioremap(0x10004010,4);
ADC_3 = ioremap(0x10006010,4);
ADC_4 = ioremap(0x10008010,4);
ADC_5 = ioremap(0x1000a010,4);
ADC_6 = ioremap(0x1000c010,4);
ADC_7 = ioremap(0x1000e010,4);
ADC_DATA = ioremap(0x10000020,4);
return 0;
}
/*--------------------------------------------------------------------------*/
int __init adc0809_init(void)
{
static int result;
// unsigned long gpfup;
//volatile unsigned int bankcon2;
address_map();
printk("*********************adc0809_init**************\n");
adc_write_addr = ADC_0; [b] //ioctl函数的功能放到初始化函数中[/b]
(*(volatile unsigned char *) adc_write_addr) = (char) arg;
// bankcon2=(volatile unsigned int)ioremap(0x4800000c,4);
// *(volatile unsigned int*)bankcon2 |= 3<<13; //
/* select NGCS2 */
adc0809_sle |= 0x2000;
adc0809_sle_data &= (~0x2000);
[b]/*-----------初始化S3C2410的时钟timer0-------------原驱动没有的后来添加的-------------*/[/b]
(*(volatile unsigned int *)r_TCFG0) &= 0x11111100;//prescaler=0
(*(volatile unsigned int *)r_TCFG1) &= (~0x000000F0);//MUX1=1/2
// (*(volatile unsigned int *)r_TCFG1) &= (~0x000000D0);//MUX1=1/8 时间T=r_TCNTB1/625000(s)
(*(volatile unsigned int *)r_TCNTB1) = 25000; //时间为10ms
(*(volatile unsigned int *)r_TCMPB1) = 0x00000000;
(*(volatile unsigned int *)r_TCON) |= 0x00000E00;
(*(volatile unsigned int *)r_TCON) &= (~0x00000200);
(*(volatile unsigned int *)r_TCON) |= 0x00000100;
disable_irq(IRQ_TIMER1);
enable_irq(IRQ_TIMER1);
result=request_irq(IRQ_TIMER1,&adc0809_interrupt,SA_INTERRUPT,"adc0809",NULL);
if (!result)
{
printk("Get assigned irq %d,result=%d\n",IRQ_TIMER1,result);
// return result;
}
printk("***********Init ok!!***********\n");
devfs_adc =
devfs_register(NULL,"adc0809",DEVFS_FL_DEFAULT,
ADC0809_MAJOR, 0,
S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
&adc0809_fops,NULL);
return 0;
}
int __init adc0809_exit(void)
{
(*(volatile unsigned int *)r_TCON) &= (~0x00000100);
disable_irq(IRQ_TIMER1);
free_irq(IRQ_TIMER1, adc0809_interrupt);
printk("exit ok\n");
//free_irq(IRQ_EINT2, adc0809_interrupt);
devfs_unregister(devfs_adc);
return 0;
}
/*
__initcall(adc0809_init);
*/
module_init(adc0809_init);
module_exit(adc0809_exit);