231 lines
5.5 KiB
C
231 lines
5.5 KiB
C
|
||
#include <linux/cdev.h>
|
||
#include <linux/delay.h>
|
||
#include <linux/errno.h>
|
||
#include <linux/fs.h>
|
||
#include <linux/gpio.h>
|
||
#include <linux/init.h>
|
||
#include <linux/interrupt.h>
|
||
#include <linux/ioctl.h>
|
||
#include <linux/kernel.h>
|
||
#include <linux/kthread.h>
|
||
#include <linux/list.h>
|
||
#include <linux/miscdevice.h>
|
||
#include <linux/mm.h>
|
||
#include <linux/module.h>
|
||
#include <linux/moduleparam.h>
|
||
#include <linux/pci.h>
|
||
#include <linux/slab.h>
|
||
#include <linux/string.h>
|
||
#include <linux/types.h>
|
||
#include <asm/uaccess.h>
|
||
#include <gsc3280/timer.h>
|
||
|
||
|
||
#define ADC_DEBUG 1
|
||
#ifdef ADC_DEBUG
|
||
#define dbg(msg...) printk(KERN_INFO msg)
|
||
#else
|
||
#define dbg(msg...) do{}while(0)
|
||
#endif
|
||
|
||
|
||
|
||
static void adcinit ( void )
|
||
{
|
||
unsigned int rsl = 0;
|
||
int c = 0;
|
||
*(volatile unsigned int *)0xbc04a00c |= 0x10;
|
||
*(volatile unsigned int *)0xbc04a0ac = 0x1; //enable adc & touchScreen
|
||
|
||
|
||
/*SPI0 CONFIG */
|
||
*((volatile unsigned int *)0xbc04a008) |= (1<<3);//spi0 clk enable
|
||
*((volatile unsigned int *)0xbc04a0b0) |= (1<<29);//spi0 iomux
|
||
*((volatile unsigned int *)0xbc04a0ac) = 0x1; //enable tsc
|
||
|
||
*((volatile unsigned int *)0xbc04a034) = 0x13;//PCLK 20 div
|
||
*((volatile unsigned int *)0xbc101004) = 0x1;//SPI_CLK 40 div
|
||
//*((volatile unsigned int *)0xbc101000) = 0x6f07;//MODE3,DATA WIDTH 16BIT
|
||
*((volatile unsigned int *)0xbc101000) = 0x6fc7;
|
||
|
||
msleep(300);
|
||
*(volatile unsigned int *) 0xbc101050 = 0x0; //cs0 enable
|
||
while(1)
|
||
{
|
||
*(volatile unsigned int *)0xbc101024 = 0x0;
|
||
while( *(volatile unsigned int *)0xbc101018 & 0x10 );
|
||
|
||
rsl = *(volatile unsigned int *)0xbc101024;
|
||
if(rsl == 0x8000)
|
||
break;
|
||
if(c++ > 1000)
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
static int auto_adc(unsigned int cmd)
|
||
{
|
||
unsigned int res = 0;
|
||
//unsigned int value = cmd;
|
||
*((volatile unsigned int *)0xbc101050) = 0x0; //spi0片选使能
|
||
*((volatile unsigned int *)0xbc101080) = 0x1; //自动采样使能
|
||
*((volatile unsigned int *)0xbc101060) = 0xf; //ADC通道选择
|
||
//*((volatile unsigned int *)0xbc101070) = 0x10; //ADC采样数目
|
||
*((volatile unsigned int *)0xbc101090) = 0x1; //自动采样开始
|
||
|
||
printk(KERN_INFO "SPI_CSN is 0x%x \n" , *(volatile unsigned int *)0xbc101050 );
|
||
printk(KERN_INFO "SPI_ADC_TRIGGER is 0x%x \n" , *(volatile unsigned int *)0xbc101090 );
|
||
|
||
dbg("start adc...\n");
|
||
|
||
while(1)
|
||
{
|
||
//while(!((*((volatile unsigned int *)0xbc101018))&0x4)); //一直等待状态寄存器非空
|
||
//res = *((volatile unsigned int *)0xbc101024); //read data from fifo
|
||
//while((readl(0xbc101018)&0x4)==0);
|
||
res = readl(0xbc101024); //read data from fifo
|
||
dbg("auto adc res = 0x%x\n",res&0xfff);
|
||
//dbg("auto adc res = 0x%x\n",res);
|
||
|
||
msleep(100);
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
static int GetVolt(unsigned int cmd)
|
||
{
|
||
unsigned int res = 0;
|
||
|
||
*((volatile unsigned int *)0xbc101050) = 0x0;//cs0 enable,这个片选仅作为ADC内部使用
|
||
*((volatile unsigned int *)0xbc101024) = cmd; //spi数据寄存器,将命令写入发送fifo,测量通道ADC通道1
|
||
|
||
|
||
while ( 1 )
|
||
{
|
||
while(!((*((volatile unsigned int *)0xbc101018))&0x4)); //一直等待状态寄存器非空
|
||
res = *((volatile unsigned int *)0xbc101024); //read data from fifo
|
||
//dbg("res = %d\n",res);
|
||
if ( res == 0xF000 || res == (0x8000|(cmd>>12)) )
|
||
{
|
||
*((volatile unsigned int *)0xbc101024) = 0xF000; //NOP命令
|
||
}
|
||
else if ( res < 0x1000 )
|
||
{
|
||
*((volatile unsigned int *)0xbc101050) = 0x1; //片选关闭
|
||
dbg("GetVolt res = %d\n",res);
|
||
break;
|
||
}
|
||
|
||
else
|
||
//dbg("xxxxx\n");
|
||
*((volatile unsigned int *)0xbc101024) = 0x9000; //采样ADC0通道??
|
||
}
|
||
|
||
printk(KERN_INFO "GetVolt return\n");
|
||
|
||
return res;
|
||
}
|
||
|
||
|
||
static ssize_t adctest_read ( struct file * pfile , char __user * pbuf , size_t size , loff_t * ppos )
|
||
{
|
||
size_t size_m=2*1024*1024;
|
||
char *buf;
|
||
char buf_t[10];
|
||
int i;
|
||
|
||
#if 0
|
||
uint8_t read_buffer[2];
|
||
unsigned int volt= GetVolt(0xa000);
|
||
read_buffer[0]=volt&0xff;
|
||
read_buffer[1]=(volt>>8)&0xff;
|
||
copy_to_user(pbuf, read_buffer, 2);
|
||
|
||
//auto_adc(0);
|
||
#endif
|
||
|
||
buf=kmalloc(size_m, GFP_KERNEL);
|
||
if (!buf)
|
||
return -ENOMEM;
|
||
printk(KERN_INFO "kmalloc ok! \n");
|
||
|
||
memset(buf,0xaa,size_m);
|
||
|
||
// memcpy(buf_t ,buf, 10);
|
||
// for(i=0;i<10;i++)
|
||
// printk(KERN_INFO "buf_t[%d]=%x \n",i, buf_t[i]);
|
||
|
||
copy_to_user(pbuf, buf, size);
|
||
|
||
kfree(buf);
|
||
|
||
return 0;
|
||
}
|
||
|
||
static int adctest_open ( struct inode * node , struct file * file )
|
||
{
|
||
return 0 ;
|
||
}
|
||
|
||
static int adctest_release ( struct inode * node , struct file * file )
|
||
{
|
||
return 0 ;
|
||
}
|
||
|
||
static struct file_operations m_fileadctest = {
|
||
.owner = THIS_MODULE ,
|
||
.llseek = no_llseek ,
|
||
.read = adctest_read ,
|
||
.unlocked_ioctl = NULL,
|
||
.open = adctest_open ,
|
||
.release = adctest_release ,
|
||
} ;
|
||
|
||
static struct miscdevice m_deviceAdc = {
|
||
.minor = MISC_DYNAMIC_MINOR ,
|
||
.name = "adctest",
|
||
.fops = & m_fileadctest ,
|
||
} ;
|
||
|
||
|
||
static int __init adctest_init ( void )
|
||
{
|
||
int result;
|
||
|
||
result = misc_register ( &m_deviceAdc ) ;
|
||
|
||
if ( result == 0 )
|
||
{
|
||
dbg("adc init...\n");
|
||
adcinit ( );
|
||
dbg("adc init ok ...\n");
|
||
}
|
||
else
|
||
{
|
||
printk ( KERN_WARNING "register device error !!!!\n") ;
|
||
}
|
||
|
||
return result ;
|
||
}
|
||
|
||
static void __exit adctest_exit ( void )
|
||
{
|
||
misc_deregister ( & m_deviceAdc ) ;
|
||
return ;
|
||
}
|
||
|
||
|
||
module_init ( adctest_init ) ;
|
||
module_exit ( adctest_exit ) ;
|
||
|
||
MODULE_AUTHOR ( "lufei" ) ;
|
||
MODULE_LICENSE ( "Dual BSD/GPL" ) ;
|
||
|