会员
周边
众包
新闻
博问
闪存
赞助商
所有博客
当前博客
我的博客
我的园子
账号设置
简洁模式
...
退出登录
注册
登录
张鹏的博客
嵌入式系统
ad7888 linux driver
/*
ADCCONVERT.c :
Generate ADC signals from SPI ports, as the A/D control signals.
Author: Aaron Fu
2008-10-14
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/slab.h> /* kmalloc */
#include <linux/fs.h> /* struect file inode */
#include <linux/errno.h> /* error codes */
#include <linux/types.h> /* size_t */
#include <linux/proc_fs.h> /* proc_fs */
#include <linux/fcntl.h> /* O_ACCMODE */
#include <linux/seq_file.h> /* seq_file */
#include <linux/cdev.h> /* register char device */
#include <asm/system.h> /* cli(), *_flags */
#include <asm/uaccess.h> /* copy_*_user */
#include <asm/delay.h> /* udelay */
#include <asm/io.h> /* ioremap...*/
#include "adconvert.h" /* local definitions */
int adc_major = ADC_MAJOR;
int adc_minor = 0;
int adc_nr_devs = ADC_NR_DEVS;
static
int adcopen;
struct cdev *adc_cdev;
module_param( adc_major,
int, S_IRUGO );
module_param( adc_minor,
int, S_IRUGO );
module_param( adc_nr_devs,
int, S_IRUGO );
MODULE_LICENSE(
"Aaron Fu" );
MODULE_DESCRIPTION(
"Iconic Shanghai Co.,LTD." );
MODULE_AUTHOR(
"GPL" );
void adc_address_map(
void){
r_SPSTA0 = ioremap( rSPSTA0, 0x00000004 );
r_SPPRE0 = ioremap( rSPPRE0, 0x00000004 );
// rSPPRE0
r_SPCON0 = ioremap( rSPCON0, 0x00000004 );
// rSPCON0
r_SPTDAT0 = ioremap( rSPTDAT0, 0x00000004 );
// rSPTDAT0
r_SPRDAT0 = ioremap( rSPRDAT0, 0x00000004 );
r_GPECON = ioremap( rGPECON, 0x00000004 );
//rGPECON
r_GPEUP = ioremap( rGPEUP, 0x00000004 );
// rGPEUP
r_GPHCON = ioremap( rGPHCON, 0x00000004 );
// rGPHCON
r_GPHUP = ioremap( rGPHUP, 0x00000004 );
// rGPHUP
r_GPHDAT = ioremap( rGPHDAT, 0x00000004 );
//rGPHDAT
}
void adc_cancel_add_map(
void ){
iounmap( r_SPSTA0 );
iounmap( r_SPPRE0 );
iounmap( r_SPCON0 );
iounmap( r_SPTDAT0 );
iounmap( r_SPRDAT0 );
iounmap( r_GPECON );
iounmap( r_GPEUP );
iounmap( r_GPHCON );
iounmap( r_GPHUP );
iounmap( r_GPHDAT );
}
static
void adc_spi_init(
void ){
int i;
/*
rSPPRE0 = 0x32;
rSPCON0 = 0x1e;
for( i = 0; i < 10; i++ )
rSPTDAT0 = 0xff;
rGPECON |= 0x0a800000;
rGPECON &= ( ~0x05400000 );
rGPEUP |= 0x3800;
//GPH5----->CS
rGPHCON |= 0x0400;
rGPHCON &= ( ~0x0800 );
rGPHUP &= ( ~0x20 );
rGPHDAT |= 0x20;*/
iowrite32( ioread32( r_SPSTA0 ) | 0x01, r_SPSTA0 );
iowrite32( 0x4, r_SPPRE0 );
iowrite32( 0x1e, r_SPCON0 );
for( i = 0; i < 10; i++ ){
iowrite32( 0xff, r_SPTDAT0 );
}
//for( i = 0; i < 10; i++ ){
iowrite32( 0x00, r_SPRDAT0 );
//}
iowrite32( ioread32( r_GPECON ) | 0x0a800000, r_GPECON );
iowrite32( ioread32( r_GPECON ) & ( ~0x05400000 ), r_GPECON );
iowrite32( ioread32( r_GPEUP ) | 0x3800, r_GPEUP );
iowrite32( ioread32( r_GPHCON ) | 0x0400, r_GPHCON );
iowrite32( ioread32( r_GPHCON ) & ( ~0x0800 ), r_GPHCON );
iowrite32( ioread32( r_GPHUP ) & ( ~0x20 ), r_GPHUP );
iowrite32( ioread32( r_GPHDAT ) | ( 0x20 ), r_GPHDAT );
}
static
struct file_operations adc_fops = {
/* driver info */
.owner = THIS_MODULE,
.open = adc_open,
.read = adc_read,
.write = adc_write,
.release = adc_release,
};
static ssize_t adc_write(
struct file *file,
const
char __user *buf,
size_t count, loff_t *offset ){
int ret = 0;
int i = 0;
printk(
"write count value = %d\n", count );
dbuf = kmalloc( count *
sizeof( unsigned
char ), GFP_KERNEL);
if ( dbuf == NULL ){
printk( KERN_WARNING
"write: dbuf alloc memory fail\n" );
return -1;
}
memset( dbuf, 0, count *
sizeof( unsigned
char ) );
copy_from_user( dbuf, buf, count );
printk(
"************** write bufx = %x *******************\n", buf );
printk(
"************* write bufs = %s *******************\n", buf );
for( i = 0; i < count; i++ ){
ADCTxdata[i] = dbuf[i];
printk(
"write adctx value [%d] = %c\n", i, ADCTxdata[i] );
}
kfree( dbuf );
return ret;
}
static ssize_t adc_read(
struct file *file,
char __user *buf,
size_t count, loff_t *offset ){
int i = 0;
int ret = 0;
iowrite32( ioread32( r_SPCON0 ) | 0x1, r_SPCON0 );
adc_convert();
adc_convert();
printk(
"\n\n" );
printk(
"read count value = %d\n", count );
dbuf = kmalloc( count *
sizeof( unsigned
char ), GFP_KERNEL );
if ( dbuf == NULL ){
printk( KERN_WARNING
"read: dbuf alloc memory fail\n" );
return -1;
}
memset( dbuf, 0, count *
sizeof( unsigned
char ) );
for( i = 0; i < count; i++ ){
dbuf[i] = ADCRxdata[i];
printk(
"read adctx value [%d] = %c\n", i, ADCTxdata[i] );
}
printk(
"\n" );
copy_to_user( buf, dbuf, count);
printk(
"************** read bufx = %x ************************\n", buf );
printk(
"************** read bufs = %s ************************\n", buf );
kfree( dbuf );
return ret;
}
void adc_convert(
void ){
/*rGPHDAT &= ( ~0x20 );
adc_tx_data( ADCTxdata[0] );
// ADCRXdata[0] = rSPRDATO;
ADCRxdata[0] = r_SPRDAT0;
adc_tx_data( 0xff );
// ADCRXdata[1] = rSPRDATO;
ADCRxdata[1] = r_SPRDAT0;
rGPHDAT |= 0x20;*/
iowrite32( ioread32( r_GPHDAT ) & ( 0x20 ), r_GPHDAT );
adc_tx_data( ADCTxdata[0] );
ADCRxdata[0] = r_SPRDAT0;
adc_tx_data( 0xff );
ADCRxdata[1] = r_SPRDAT0;
iowrite32( ioread32( r_GPHDAT ) | ( 0x20 ), r_GPHDAT );
}
static
void adc_tx_data( unsigned
char data ){
iowrite32( ioread32( r_SPSTA0 ) | 0x01, r_SPSTA0 );
spi_poll_done();
//rSPTDAT0 = data;
iowrite32( data, r_SPTDAT0 );
spi_poll_done();
}
void spi_poll_done(
void ){
//while ( !( rSPSTA0 & 0x01 ) )
while ( !( ioread32( r_SPSTA0 ) & 0x01 ) )
;
}
int adc_release(
struct inode *inode,
struct file *filp ){
adcopen--;
module_put( THIS_MODULE );
return 0 ;
}
int adc_init_module(
void ){
int result;
dev_t dev = 0;
if ( adc_major ){
dev = MKDEV( adc_major, adc_minor );
result = register_chrdev_region( dev, adc_nr_devs,
"adc" );
}
else{
result = alloc_chrdev_region( &dev, adc_minor, adc_nr_devs,
"adc" );
adc_major = MAJOR( dev );
}
adc_cdev = cdev_alloc();
if ( adc_cdev == NULL ){
return -1;
}
if ( result < 0 ){
printk( KERN_WARNING
"adc: can't get major %d\n", adc_major );
return result;
}
printk( KERN_INFO
"adc: this major is %d\n", adc_major );
adcopen = 0;
adc_cdev->ops = &adc_fops;
cdev_init( adc_cdev, &adc_fops );
cdev_add( adc_cdev, dev, 1 );
adc_address_map();
adc_spi_init();
printk( KERN_INFO
"*** adc_init() finished *** \n" );
return 0;
}
static
int adc_open(
struct inode *inode,
struct file *filp ){
if ( adcopen == 0 )
adcopen++;
else{
printk( KERN_ALERT
"Another process open the char device\n" );
return -1;
}
try_module_get( THIS_MODULE );
return 0;
}
void adc_cleanup_module(
void ){
dev_t devno;
adc_cancel_add_map();
devno = MKDEV( adc_major, adc_minor );
unregister_chrdev_region( devno, adc_nr_devs );
cdev_del( adc_cdev );
}
module_init( adc_init_module );
module_exit( adc_cleanup_module );
posted on
2015-09-29 23:22
嵌入式操作系统
阅读(
379
) 评论(
0
)
编辑
收藏
举报
刷新页面
返回顶部
导航
博客园
首页
新随笔
联系
订阅
管理
公告