海尔冰箱玻璃面板:linux e2prom 驱动代码

来源:百度文库 编辑:中财网 时间:2024/04/30 02:13:35

头文件

#ifndef _E2PROM_H_
#define _E2PROM_H_

#define E2PROM_MAGIC 'e'

#define E2PROM_WRITE_READ    _IOWR( E2PROM_MAGIC, 0, unsigned char )

#define E2PROM_MAXNR         1

#endif

 

源代码文件    

//////////////////////////////////////////////////////////////////////////
//      FILE  : e2prom.c
//      DATE   : 09/02/2010
//      DESCRIPTION : tamedia e2prom driver source
//      OS : Linux
//      AUTHOR : rui
//////////////////////////////////////////////////////////////////////////
#include
#include
#include
#include
#include
#include

#if !defined(CONFIG_TANGOX)
#error "Unsupport architecture (TANGOX only)."
#elif defined(CONFIG_TANGO2_SMP863X) && (EM86XX_REVISION < 4)
#error "Unsupport Tango2 (ES4 or above) or Tango3 chip."
#endif /*  */

#include

#ifdef CONFIG_TANGO2
#include
#elif defined(CONFIG_TANGO3)
#include
#endif /*  */

#include "e2prom.h"

#define GPIO_IIC_SCL        0
#define GPIO_IIC_SDA        1

#define I2C_AT24CXX_ADDRESS 0xa0
#define I2C_AT24C02_MAXSIZE 0xff

#define SCL_H  { em86xx_gpio_write( GPIO_IIC_SCL, 1 ) ; }
#define SCL_L  { em86xx_gpio_write( GPIO_IIC_SCL, 0 ) ; }
#define SDA_H  { em86xx_gpio_write( GPIO_IIC_SDA, 1 ) ; }
#define SDA_L  { em86xx_gpio_write( GPIO_IIC_SDA, 0 ) ; }
#define SDA_IN  { em86xx_gpio_setdirection ( GPIO_IIC_SDA, GPIO_INPUT ) ; }
#define SDA_OUT { em86xx_gpio_setdirection ( GPIO_IIC_SDA, GPIO_OUTPUT ) ; }
#define WHILE_SDA_HIGH (em86xx_gpio_read( GPIO_IIC_SDA ) == 1 )

MODULE_DESCRIPTION ( "EM86xx/SMP86xx tamedia e2prom m41t81 driver\n" ) ;
MODULE_AUTHOR ( "rui" ) ;
MODULE_LICENSE ( "GPL" ) ;

#define E2PROM_DEV_NAME "e2prom"
static int major = 221 ;
module_param( major, int, 0 ) ;

unsigned int ByteDelayTimeout = 0x1000 ;
unsigned int BitDelayTimeout = 0x200 ;

static void ByteDelay ( void ) ;
static void BitDelay ( void ) ;

static int e2prom_open ( struct inode *, struct file * ) ;
static int e2prom_release ( struct inode *, struct file * ) ;
static int e2prom_read ( struct file *, char *, size_t, loff_t * ) ;
static int e2prom_write ( struct file *, const char *, size_t, loff_t * ) ;
static int e2prom_ioctl ( struct inode *, struct file *, unsigned int,unsigned long ) ;

static void InterfaceInit ( void ) ;
static void I2C_Start ( void ) ;
static void I2C_Stop ( void ) ;
static void I2C_Ack ( void ) ;
static void I2C_Nack ( void ) ;

struct e2prom_private
{
 spinlock_t lock ;
 int ref_cnt ;
 unsigned char address ;
} ;

static struct e2prom_private e2prom_priv ;

static struct file_operations e2prom_fops =
{
 .owner = THIS_MODULE,
 .open = e2prom_open,
 .read = e2prom_read,
 .write = e2prom_write,
 .ioctl = e2prom_ioctl,
 .release =e2prom_release,
} ;

static void I2C_Start ()
{
 SDA_OUT ;
 SDA_H ;
 BitDelay () ;
 SCL_H ;
 BitDelay () ;
 SDA_L ;
 BitDelay () ;
 SCL_L ;
 BitDelay () ;
}

static void I2C_Stop ()
{
 SDA_OUT ;
 SDA_L ;
 BitDelay () ;
 SCL_H ;
 BitDelay () ;
 SDA_H ;
 BitDelay () ;
}

static void I2C_Ack()
{
 SDA_OUT ;
 SDA_L ;
 BitDelay () ;
 SCL_H ;
 BitDelay () ;
 SCL_L ;
 BitDelay () ;
}

static void I2C_Nack ()
{
 SDA_OUT ;
 SDA_H ;
 BitDelay () ;
 SCL_H ;
 BitDelay () ;
 SCL_L ;
 BitDelay () ;
}

static char Write_I2C_Byte ( char byte )
{
 char i ;

 SDA_OUT ;
 for ( i = 0 ; i < 8 ; i++ )
 {
  if ( (byte & 0x80) == 0x80 )
  {
   SDA_H ;
  }
  else
  {
   SDA_L ;
  }
  BitDelay () ;
  SCL_H ;
  BitDelay () ;
  SCL_L ;
  byte <<= 1 ;
 }

 return 1 ;
}

static char Read_I2C_Byte ( void )
{
 char i, buff = 0 ;

 for ( i = 0 ; i < 8 ; i++ )
 {
  SDA_OUT ;
  SDA_H ;
  BitDelay () ;
  SCL_H ;
  BitDelay () ;
  SDA_IN ;
  if ( WHILE_SDA_HIGH )
  {
   buff |= 0x01 ;
  }
  if ( i < 7 )
  {
   buff <<= 1 ;
  }

  SCL_L ;
  BitDelay () ;
 }

 return buff ;
}

static void ByteDelay ( void )
{
 volatile unsigned int dwTimeout ;
 dwTimeout = ByteDelayTimeout ;

 while ( --dwTimeout )
 {
  asm ( "nop" ) ;
 }
}

static void BitDelay ( void )
{
 volatile unsigned int dwTimeout ;
 dwTimeout = BitDelayTimeout ;

 while ( --dwTimeout )
 {
  asm ( "nop" ) ;
 }
}

static void InterfaceInit ( void )
{
 em86xx_gpio_setdirection ( GPIO_IIC_SDA, GPIO_OUTPUT ) ;
 em86xx_gpio_setdirection ( GPIO_IIC_SCL, GPIO_OUTPUT ) ;
 em86xx_gpio_write ( GPIO_IIC_SDA, 1 ) ;
 em86xx_gpio_write ( GPIO_IIC_SCL, 1 ) ;

 ByteDelay () ;
 ByteDelay () ;
 ByteDelay () ;

 I2C_Start () ;
 Write_I2C_Byte ( I2C_AT24CXX_ADDRESS ) ;
 I2C_Ack () ;
 Write_I2C_Byte ( 0x0c ) ;
 I2C_Ack () ;
 Write_I2C_Byte ( 0x00 ) ;
 I2C_Ack () ;
 I2C_Stop () ;
}

static int e2prom_open ( struct inode *inode_ptr, struct file *fptr )
{
 printk( "--------------------------------------------\n" ) ;
 
 if ( e2prom_priv.ref_cnt != 0 )
 {
  printk ( "%s: exclusive access only\n", E2PROM_DEV_NAME ) ;
  return -EIO ;
 }
 
 e2prom_priv.ref_cnt++ ;
 e2prom_priv.address = 0x00 ;
 fptr->f_op = &e2prom_fops ;
 fptr->private_data = (void *) &e2prom_priv ;

 return 0 ;
}

static int e2prom_release ( struct inode *inode_ptr, struct file *fptr )
{
 struct e2prom_private *priv = (struct e2prom_private *) fptr->private_data ;

 priv->ref_cnt-- ;
 priv->address = 0x00 ;

 return 0 ;
}

static int e2prom_read (struct file *fptr, char *buffer, size_t count, loff_t * fp)
{
 struct e2prom_private *priv = (struct e2prom_private *) fptr->private_data ;
 unsigned char data[I2C_AT24C02_MAXSIZE] = { 0x00, } ;
 int i = 0;
 printk( "e2prom_read : address : 0x%x\n",  priv->address ) ;

 if ( count <= 0 )
 {
  printk ( "e2prom_read : read size must big than 0 .\n" ) ;
  return -EIO ;  
 }
 
 if ( priv->address + count >= I2C_AT24C02_MAXSIZE )
 {
  printk ( "e2prom_read : read size overflow e2prom size .\n" ) ;
  count = I2C_AT24C02_MAXSIZE - priv->address ;
 }
 
 spin_lock ( &priv->lock ) ;

 I2C_Start () ;
 Write_I2C_Byte ( I2C_AT24CXX_ADDRESS ) ;
 I2C_Ack () ;
 Write_I2C_Byte ( priv->address ) ;
 I2C_Ack () ;

 I2C_Start () ;
 Write_I2C_Byte ( I2C_AT24CXX_ADDRESS + 1 ) ;
 I2C_Ack () ;

 for ( i = 0; i < count; i++ )
 {
  data[i] = Read_I2C_Byte () ;
  I2C_Ack () ;
  printk( "0x%x ", data[i] ) ;
 }
 Read_I2C_Byte () ;
 I2C_Nack () ;
 I2C_Stop () ;

 spin_unlock ( &priv->lock ) ;

 printk( "\n" ) ;
 
 if ( i == 0 )
 {
  return -EFAULT ;
 }

 if ( copy_to_user ( buffer, (char *) &data, count ) )
 {
  printk ( "e2prom_read : copy_to_user failed .\n" ) ;
  return -EFAULT ;
 }
 
 printk( "buffer : 0x%x, 0x%x, 0x%x, 0x%x\n", buffer[0], buffer[1], buffer[2], buffer[3] ) ;

 return count ;
}

static int e2prom_write ( struct file *fptr, const char *buffer, size_t size, loff_t * fp )
{
 struct e2prom_private *priv = (struct e2prom_private *) fptr->private_data ;
 unsigned char data[I2C_AT24C02_MAXSIZE] = { 0x00, } ;
 int i = 0;
 printk( "e2prom_write : address : 0x%x\n",  priv->address ) ;

 if ( size <= 0 )
 {
  printk ( "e2prom_read : read size must big than 0 .\n" ) ;
  return -EIO ;  
 }
 
 if ( priv->address + size > I2C_AT24C02_MAXSIZE )
 {
  printk ( "e2prom_read : read size overflow e2prom size .\n" ) ;
  size = I2C_AT24C02_MAXSIZE - priv->address ;
 }
 
 if ( copy_from_user ( (char *) data, buffer, size ) )
 {
  printk( "e2prom_write : copy_from_user failed. \n" ) ;
  return -EFAULT ;
 }

 spin_lock ( &priv->lock ) ;

 I2C_Start () ;
 Write_I2C_Byte ( I2C_AT24CXX_ADDRESS ) ;
 I2C_Ack () ;
 Write_I2C_Byte ( priv->address ) ;
 I2C_Ack () ;
 for ( i = 0; i < size; i++ )
 {
  printk( "0x%x ", data[i] ) ;
  Write_I2C_Byte ( data[i] ) ;
  I2C_Ack () ;
 }
 I2C_Stop () ;

 spin_unlock ( &priv->lock ) ;

 printk( "\n" ) ;
 
 if ( i == 0 )
 {
  return -EFAULT ;
 }
 
 return size ;
}

static int e2prom_ioctl ( struct inode *inode, struct file *fptr, unsigned int cmd, unsigned long arg )
{
 struct e2prom_private *priv = (struct e2prom_private *) fptr->private_data ;
 priv->address = (unsigned char)arg ;
 
 if ( priv->address >= I2C_AT24C02_MAXSIZE ||  priv->address < 0x00 )
 {
  printk( "e2prom_ioctl : the address you specificed is overflow e2prom area .\n" ) ;
  return -EFAULT ;
 }

 return 0 ;
}

static int e2prom_init ( void )
{
 int status = 0 ;

 memset ( &e2prom_priv, 0, sizeof (struct e2prom_private) ) ;
 InterfaceInit () ;
 spin_lock_init ( &e2prom_priv.lock ) ;
 e2prom_priv.ref_cnt = 0 ;
 e2prom_priv.address = 0x00 ;
 status = register_chrdev (major, E2PROM_DEV_NAME, &e2prom_fops) ;

 if ( status < 0 )
 {
  printk ( "e2prom_init : cannot get major number .\n" ) ;
  return status ;
 }
 else if ( major == 0 )
 {
  major = status ;
 }

 return 0 ;
}

static void e2prom_exit ( void )
{
 unregister_chrdev ( major, E2PROM_DEV_NAME) ;
}

module_init ( e2prom_init ) ;
module_exit ( e2prom_exit ) ;

 

makefile

kerdir=/root/8655/smp86xx_kernel_source_R2.6.22-19/linux-2.6.22.19/

obj-m := e2prom.o

modules:
 $(MAKE) -C $(kerdir) M=$(shell pwd) modules

clean:
     rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

 

 

 

测试程序

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#include "e2prom.h"

using namespace std ;

int main (int argc, char *argv[])
{
 int fd ;
 unsigned char dataA[4] = { 0xaa, 0xbb, 0xcc, 0xdd } ;
 unsigned char dataB[4] = { 0x00, } ;
 unsigned char address = 0x00 ;
 
 fd = open ( "/dev/e2prom", O_RDWR ) ;
 if ( fd == -1 )
 {
  printf( "Open device e2prom failed .\n" ) ;
  return false ;
 }

 if ( ioctl( fd, E2PROM_WRITE_READ, address ) < 0 )
 {
  printf( "ioctl failed .\n" ) ;
  close ( fd ) ;
  return false ;
 }

 
 if ( write ( fd, (char*)dataA, 4 ) != 4 )
 {
  printf( "Write device e2prom failed .\n" ) ;
  close ( fd ) ;
  return false ;
 }
 
 if ( ioctl( fd, E2PROM_WRITE_READ, address ) < 0 )
 {
  printf( "ioctl failed .\n" ) ;
  close ( fd ) ;
  return false ;
 }
 
 if ( read ( fd, dataB, 4 ) != 4 )
 {
  printf( "Read device e2prom failed .\n" ) ;
  close ( fd ) ;
  return false ;
 }
 
 printf( "dataB : 0x%x, 0x%x, 0x%x, 0x%x\n", dataB[0], dataB[1], dataB[2], dataB[3] ) ;
 
 close ( fd ) ;

 return EXIT_SUCCESS ;
}