ad7888 linux driver


  1. /* 
  2.         ADCCONVERT.c : 
  3.                 Generate ADC signals from SPI ports, as the A/D control signals. 
  4.  
  5.         Author:  Aaron Fu 
  6.         2008-10-14 
  7. */  
  8.   
  9. #include <linux/module.h>  
  10. #include <linux/moduleparam.h>  
  11. #include <linux/init.h>  
  12.   
  13. #include <linux/kernel.h>   
  14. #include <linux/slab.h>       /* kmalloc */  
  15. #include <linux/fs.h>     /* struect file inode */  
  16. #include <linux/errno.h>  /* error codes */  
  17. #include <linux/types.h>  /* size_t */  
  18. #include <linux/proc_fs.h>    /* proc_fs */  
  19. #include <linux/fcntl.h>  /* O_ACCMODE */  
  20. #include <linux/seq_file.h> /* seq_file */  
  21. #include <linux/cdev.h>       /* register char device */  
  22.   
  23. #include <asm/system.h>       /* cli(), *_flags */  
  24. #include <asm/uaccess.h>  /* copy_*_user */  
  25. #include <asm/delay.h>        /* udelay */  
  26. #include <asm/io.h>           /* ioremap...*/  
  27.   
  28. #include "adconvert.h"      /* local definitions */  
  29.   
  30. int adc_major   = ADC_MAJOR;  
  31. int adc_minor   = 0;  
  32. int adc_nr_devs = ADC_NR_DEVS;  
  33.   
  34. static int      adcopen;  
  35. struct cdev     *adc_cdev;  
  36.   
  37. module_param( adc_major, int, S_IRUGO );  
  38. module_param( adc_minor, int, S_IRUGO );  
  39. module_param( adc_nr_devs, int, S_IRUGO );  
  40.   
  41. MODULE_LICENSE( "Aaron Fu" );  
  42. MODULE_DESCRIPTION( "Iconic Shanghai Co.,LTD." );  
  43. MODULE_AUTHOR( "GPL" );  
  44.   
  45. void adc_address_map(void){  
  46.     r_SPSTA0    =   ioremap( rSPSTA0, 0x00000004 );  
  47.       
  48.     r_SPPRE0    =   ioremap( rSPPRE0, 0x00000004 );         // rSPPRE0  
  49.     r_SPCON0    =   ioremap( rSPCON0, 0x00000004 );         // rSPCON0  
  50.     r_SPTDAT0   =   ioremap( rSPTDAT0, 0x00000004 );        // rSPTDAT0  
  51.     r_SPRDAT0   =   ioremap( rSPRDAT0, 0x00000004 );  
  52.       
  53.     r_GPECON    =   ioremap( rGPECON, 0x00000004 );     //rGPECON  
  54.     r_GPEUP     =   ioremap( rGPEUP, 0x00000004 );          // rGPEUP  
  55.       
  56.     r_GPHCON    =   ioremap( rGPHCON, 0x00000004 );     // rGPHCON  
  57.     r_GPHUP     =   ioremap( rGPHUP, 0x00000004 );          // rGPHUP  
  58.     r_GPHDAT    =   ioremap( rGPHDAT, 0x00000004 );     //rGPHDAT  
  59. }  
  60.   
  61. void adc_cancel_add_map( void ){  
  62.     iounmap( r_SPSTA0 );  
  63.     iounmap( r_SPPRE0 );  
  64.     iounmap( r_SPCON0 );  
  65.     iounmap( r_SPTDAT0 );  
  66.     iounmap( r_SPRDAT0 );  
  67.     iounmap( r_GPECON );  
  68.     iounmap( r_GPEUP );  
  69.     iounmap( r_GPHCON );  
  70.     iounmap( r_GPHUP );  
  71.     iounmap( r_GPHDAT );  
  72. }  
  73.   
  74. static void adc_spi_init( void ){  
  75.     int i;  
  76.       
  77.     /* 
  78.     rSPPRE0 = 0x32; 
  79.     rSPCON0 = 0x1e; 
  80.     for( i = 0; i < 10; i++ ) 
  81.         rSPTDAT0 = 0xff;     
  82.     
  83.     rGPECON |= 0x0a800000; 
  84.     rGPECON &= ( ~0x05400000 ); 
  85.     rGPEUP |= 0x3800; 
  86.     //GPH5----->CS 
  87.     rGPHCON |= 0x0400; 
  88.     rGPHCON &= ( ~0x0800 ); 
  89.     rGPHUP &= ( ~0x20 ); 
  90.     rGPHDAT |= 0x20;*/  
  91.       
  92.     iowrite32( ioread32( r_SPSTA0 ) | 0x01, r_SPSTA0 );  
  93.       
  94.     iowrite32( 0x4, r_SPPRE0 );  
  95.     iowrite32( 0x1e, r_SPCON0 );  
  96.      
  97.     for( i = 0; i < 10; i++ ){  
  98.         iowrite32( 0xff, r_SPTDAT0 );  
  99.     }  
  100.   
  101.     //for( i = 0; i < 10; i++ ){  
  102.         iowrite32( 0x00, r_SPRDAT0 );  
  103.     //}  
  104.      
  105.     iowrite32( ioread32( r_GPECON ) | 0x0a800000, r_GPECON );  
  106.     iowrite32( ioread32( r_GPECON ) & ( ~0x05400000 ), r_GPECON );  
  107.     iowrite32( ioread32( r_GPEUP ) | 0x3800, r_GPEUP );  
  108.       
  109.     iowrite32( ioread32( r_GPHCON ) | 0x0400, r_GPHCON );  
  110.     iowrite32( ioread32( r_GPHCON ) & ( ~0x0800 ), r_GPHCON );  
  111.     iowrite32( ioread32( r_GPHUP ) & ( ~0x20 ), r_GPHUP );  
  112.     iowrite32( ioread32( r_GPHDAT ) | ( 0x20 ), r_GPHDAT );  
  113. }  
  114.       
  115. static struct file_operations adc_fops = {        /* driver info  */  
  116.     .owner      =       THIS_MODULE,  
  117.     .open       =       adc_open,  
  118.     .read       =       adc_read,  
  119.     .write      =       adc_write,  
  120.     .release    =       adc_release,  
  121. };  
  122.   
  123.   
  124. static ssize_t adc_write( struct file *file, const char __user *buf, size_t count, loff_t *offset ){  
  125.     int ret = 0;  
  126.     int i = 0;  
  127.       
  128.     printk( "write count value = %d\n", count );  
  129.     dbuf = kmalloc( count * sizeof( unsigned char ), GFP_KERNEL);  
  130.     if ( dbuf == NULL ){  
  131.         printk( KERN_WARNING "write: dbuf alloc memory fail\n" );  
  132.         return -1;  
  133.     }  
  134.     memset( dbuf, 0, count *sizeof( unsigned char ) );  
  135.   
  136.     copy_from_user( dbuf, buf, count );  
  137.     printk( "**************  write bufx = %x  *******************\n", buf );      
  138.     printk( "*************   write bufs = %s  *******************\n", buf );  
  139.     for( i = 0; i < count; i++ ){  
  140.         ADCTxdata[i] = dbuf[i];  
  141.         printk( "write adctx value [%d] = %c\n", i, ADCTxdata[i] );  
  142.     }  
  143.       
  144.     kfree( dbuf );  
  145.   
  146.     return ret;  
  147. }  
  148.     
  149. static ssize_t adc_read( struct file *file, char __user *buf, size_t count, loff_t *offset ){  
  150.     int i = 0;  
  151.     int ret = 0;  
  152.       
  153.     iowrite32( ioread32( r_SPCON0 ) | 0x1, r_SPCON0 );  
  154.     adc_convert();  
  155.     adc_convert();  
  156.     printk( "\n\n" );  
  157.     printk( "read count value = %d\n", count );  
  158.       
  159.     dbuf = kmalloc( count * sizeof( unsigned char ), GFP_KERNEL );  
  160.     if ( dbuf == NULL ){  
  161.         printk( KERN_WARNING "read: dbuf alloc memory fail\n" );  
  162.         return -1;  
  163.     }  
  164.     memset( dbuf, 0, count * sizeof( unsigned char ) );  
  165.       
  166.     for( i = 0; i < count; i++ ){  
  167.         dbuf[i] = ADCRxdata[i];  
  168.         printk( "read adctx value [%d] = %c\n", i, ADCTxdata[i] );  
  169.     }  
  170.     printk( "\n" );  
  171.       
  172.     copy_to_user( buf, dbuf, count);  
  173.     printk( "**************  read bufx = %x  ************************\n", buf );  
  174.     printk( "**************  read bufs = %s  ************************\n", buf );  
  175.     kfree( dbuf );  
  176.   
  177.     return ret;  
  178. }  
  179.   
  180. void adc_convert( void ){  
  181.     /*rGPHDAT &= ( ~0x20 ); 
  182.     adc_tx_data( ADCTxdata[0] ); 
  183.     // ADCRXdata[0] = rSPRDATO; 
  184.     ADCRxdata[0] = r_SPRDAT0; 
  185.     adc_tx_data( 0xff ); 
  186.     // ADCRXdata[1] = rSPRDATO; 
  187.     ADCRxdata[1] = r_SPRDAT0; 
  188.     rGPHDAT |= 0x20;*/  
  189.       
  190.     iowrite32( ioread32( r_GPHDAT ) & ( 0x20 ), r_GPHDAT );  
  191.       
  192.     adc_tx_data( ADCTxdata[0] );  
  193.     ADCRxdata[0] = r_SPRDAT0;  
  194.     adc_tx_data( 0xff );  
  195.     ADCRxdata[1] = r_SPRDAT0;  
  196.     iowrite32( ioread32( r_GPHDAT ) | ( 0x20 ), r_GPHDAT );  
  197. }  
  198.   
  199. static void adc_tx_data( unsigned char data ){  
  200.     iowrite32( ioread32( r_SPSTA0 ) | 0x01, r_SPSTA0 );  
  201.     spi_poll_done();  
  202.     //rSPTDAT0 = data;  
  203.     iowrite32( data, r_SPTDAT0 );  
  204.     spi_poll_done();  
  205. }  
  206.   
  207. void spi_poll_done( void ){  
  208.     //while ( !( rSPSTA0 & 0x01 ) )  
  209.     while ( !( ioread32( r_SPSTA0 ) & 0x01 ) )  
  210.         ;  
  211. }  
  212.   
  213. int adc_release( struct inode *inode, struct file *filp ){  
  214.     adcopen--;  
  215.     module_put( THIS_MODULE );  
  216.       
  217.     return 0 ;  
  218. }  
  219.   
  220. int adc_init_module( void ){  
  221.     int     result;  
  222.     dev_t   dev = 0;  
  223.       
  224.     if ( adc_major ){  
  225.         dev = MKDEV( adc_major, adc_minor );  
  226.         result = register_chrdev_region( dev, adc_nr_devs, "adc" );  
  227.     }else{  
  228.         result = alloc_chrdev_region( &dev, adc_minor, adc_nr_devs, "adc" );  
  229.         adc_major = MAJOR( dev );  
  230.     }  
  231.       
  232.     adc_cdev = cdev_alloc();  
  233.     if ( adc_cdev == NULL ){  
  234.         return -1;  
  235.     }  
  236.       
  237.     if ( result < 0 ){  
  238.         printk( KERN_WARNING "adc: can't get major %d\n", adc_major );  
  239.         return result;  
  240.     }  
  241.     printk( KERN_INFO "adc: this major is %d\n", adc_major );  
  242.       
  243.     adcopen = 0;  
  244.     adc_cdev->ops = &adc_fops;  
  245.     cdev_init( adc_cdev, &adc_fops );  
  246.     cdev_add( adc_cdev, dev, 1 );  
  247.   
  248.     adc_address_map();  
  249.     adc_spi_init();  
  250.   
  251.     printk( KERN_INFO "***    adc_init() finished    *** \n" );  
  252.   
  253.     return 0;  
  254. }  
  255.   
  256. static int adc_open( struct inode *inode, struct file *filp ){  
  257.     if ( adcopen == 0 )  
  258.         adcopen++;  
  259.     else{  
  260.         printk( KERN_ALERT "Another process open the char device\n" );  
  261.         return -1;  
  262.     }  
  263.       
  264.     try_module_get( THIS_MODULE );  
  265.       
  266.     return 0;  
  267. }  
  268.   
  269. void adc_cleanup_module( void ){  
  270.     dev_t   devno;  
  271.       
  272.     adc_cancel_add_map();  
  273.       
  274.     devno = MKDEV( adc_major, adc_minor );  
  275.     unregister_chrdev_region( devno, adc_nr_devs );  
  276.     cdev_del( adc_cdev );  
  277. }  
  278.   
  279. module_init( adc_init_module );  
  280. module_exit( adc_cleanup_module );  
 

posted on 2015-09-29 23:22  嵌入式操作系统  阅读(379)  评论(0编辑  收藏  举报

导航