⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c-samsung.c

📁 II2c driver for uclinux
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * (C) Copyright 2002  Soft I2C Char Device Driver for 
 *        my own SAMSUNGS3C4510B Board EDEN E-TECH4510 
 * but it is replanted from my MPC8250 Board Drivers 
 * Honeyandy Chen, EDEN E-TECH Co. ltd, honeyandy@thunis.com
 
 * if there is any problem ,call EDEN E-TECH  Co. ltd  by
 *  +86-028-85184225-8005
 
 * first edit date : 2002.7.2, author: Honeyandy Chen
 * history         : 2003.6.18, author: Honeyandy Chen
 * history         : 2003.7.1, author: Honeyandy Chen
 * history         : 2003.11.12, author: Honeyandy Chen for uClinux
 * history         : 2003.11.16, author: Honeyandy Chen for uClinux with Mutex
 */
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/ptrace.h>
#include <linux/ioport.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/vfs.h>
#include <linux/types.h>
#include <linux/malloc.h>
#include <linux/interrupt.h> 
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/wait.h>
#include <linux/signal.h>  
#include <linux/stat.h>
#include <linux/fcntl.h>
#include <linux/slab.h>

#include <asm/irq.h>
#include <asm/io.h>
#include <asm/semaphore.h> /* for MUTEX */
#include <asm/uaccess.h>
#include <asm/page.h>

#include "i2c-samsung.h"


/*
 *  * Deal with modules and CONFIG_MODVERSIONS
 *   */
#ifdef MODULE
# if CONFIG_MODVERSIONS==1
#  include <linux/modversions.h>
# endif
MODULE_AUTHOR("Honeyandy Chen, honeyandy@thunis.com");
MODULE_DESCRIPTION("SAMSUNG4510B Hardware I2C Driver for uClinux 4510B Project");
# endif
/*
 *  * Debugging Options
 *   *
*/
#ifdef DEBUG
#define DBG(x...)       printk(x)
#else
#define DBG(x...)
#endif

#define DEVICE_NAME	"i2c"

#define I2C_MAJOR	89 		/* define major id */

#define USE_KMALLOC    /* kmalloc is one way save memory */

#ifndef USE_KMALLOC
static volatile U8 priv_buf[128]; 
#endif

static struct semaphore i2c_samsung_sem; 

//devfs_handle_t	dev_handle;	/* register handle to store device fs */ 

static struct file_operations	i2c_ops ;

/* IIC paramters  */
typedef struct
{
        int i2c_speed;
        U8  i2c_slave;
        U8  i2c_addrlen;
        U8  i2c_operate;
        int i2c_pagesize;
        spinlock_t lock;
        U8 *buf;

} I2C_PRIVATE_T;

static I2C_PRIVATE_T	iic_priv;

static IIC_DATA_TX_FORMAT  iic_txmit;
static IIC_DATA_RX_FORMAT  iic_recv;


#ifdef MODULE
int  init_module(void);
void cleanup_module(void);
#endif

int __init i2c_samsung_init( void );

static ssize_t i2c_read (struct file * file ,char * buf, size_t count, loff_t * f_ops);
static ssize_t i2c_write (struct file * file ,const char * buf, size_t count, loff_t * f_ops);
static ssize_t i2c_ioctl (struct inode * inode ,struct file * file,
	       	   unsigned int cmd, U32 data);
static ssize_t i2c_open (struct inode * inode ,struct file * file);
static ssize_t i2c_release(struct inode * inode ,struct file * file);


/*=========== I2C Read =======================*/
static ssize_t i2c_read (struct file * file ,char * buf, size_t count, loff_t * f_ops)
{

	DBG("s34510: i2c device file-read operation!\n");	

	return count;
}	

/*=========== I2C Write =======================*/
static ssize_t i2c_write (struct file * file ,const char * buf, size_t count, loff_t * f_ops)
{

	DBG("s34510: i2c device file-write operation!\n");	
	
	return count;
}	



/*=========== I2C Ioctl =======================*/
static ssize_t i2c_ioctl (struct inode * inode ,struct file * file,
	       	   unsigned int cmd, U32 data)
{
	
	I2C_CHAIN_T	*chain = NULL;

	down(&i2c_samsung_sem);
	
	DBG("s34510: i2c device ioctl operation!\n");	
	
	switch( cmd )
	{
	case CMD_CHAIN_INIT:
		
		DBG("s34510: CMD_CHAIN_INIT command!\n");	
				

		goto ioctl_exit;
	
	case CMD_CHAIN_READ:
		DBG("s34510: CMD_CHAIN_READ command!\n");	
		
	
		chain = (I2C_CHAIN_T *)data;
		
		if( chain->mode.i2c_pagesize ==0 ){ /* at least one byte every write command*/
			break;
		}
		
		
		iic_priv.i2c_speed = chain->mode.i2c_speed;
		iic_priv.i2c_slave = chain->mode.i2c_slave;
		iic_priv.i2c_addrlen = chain->mode.i2c_addrlen;
		iic_priv.i2c_pagesize = chain->mode.i2c_pagesize;
		
		#ifndef USE_KMALLOC
		iic_priv.buf = priv_buf; 
		
		if( chain->len > 128 ){
			break;
		}
		#else
		iic_priv.buf = (volatile U8 *)kmalloc(chain->len +1, GFP_KERNEL);
		if( iic_priv.buf == NULL ){
			break;
		}
		#endif

		i2c_chain_read( chain->addr, iic_priv.buf, chain->len);	
		
		copy_to_user( chain->buffer, iic_priv.buf, chain->len);		 

		#ifdef USE_KMALLOC
		kfree( iic_priv.buf);
		#endif
		
		goto ioctl_exit;
	
	case CMD_CHAIN_WRITE:
		DBG("s34510: CMD_CHAIN_WRITE command!\n");	
		
		chain = (I2C_CHAIN_T *)data;	
		
		if( chain->mode.i2c_pagesize ==0 ){ /* at least one byte every write command*/
			break;
		}

		iic_priv.i2c_speed = chain->mode.i2c_speed;
		iic_priv.i2c_slave = chain->mode.i2c_slave;
		iic_priv.i2c_addrlen = chain->mode.i2c_addrlen;
		iic_priv.i2c_pagesize = chain->mode.i2c_pagesize;
		
		#ifndef USE_KMALLOC

		if( chain->len > 128 ){
			break;
		}
			
		iic_priv.buf = priv_buf; 
		#else
		iic_priv.buf = (volatile U8 *)kmalloc(chain->len +1, GFP_KERNEL);
		if( iic_priv.buf == NULL ){
			break;
		}
		#endif
		
		copy_from_user( iic_priv.buf , chain->buffer, chain->len );
		
		i2c_chain_write( chain->addr, iic_priv.buf, chain->len);	
		
		#ifdef USE_KMALLOC
		kfree( iic_priv.buf);
		#endif
		
		goto ioctl_exit;

	default:
		DBG("s34510: invaluable command :%08x\n !",(U32)cmd);	
			break;
	}
	
	up(&i2c_samsung_sem);
	return -EINVAL;
ioctl_exit:
	up(&i2c_samsung_sem);
	return (0);

}

/*============ I2C device open ==============*/ 
static ssize_t i2c_open (struct inode * inode ,struct file * file)
{
	DBG("s34510: i2c device open operation!\n");	
	MOD_INC_USE_COUNT;
	return 0;
}	

/*============ I2C device close =============*/
static ssize_t i2c_release (struct inode  * inode ,struct file * file)
{
	DBG("s34510: i2c device release operation!\n");	
	MOD_DEC_USE_COUNT;
	return 0;
}

/*======= device function interface =========*/
static struct file_operations i2c_ops ={
	
	open:		i2c_open,
	
	read:		i2c_read,
	
	write:		i2c_write,
	
	ioctl:		i2c_ioctl,
	
	release:	i2c_release,
};

/*===========================================*/
/* 		i2C interrupt handle	     */
/*===========================================*/				

static void s3c4510_i2c(int irq, void *dev_id, struct pt_regs *regs)
{
	spin_lock(&iic_priv.lock);
	
	DBG( "s34510: interrupt happen!\n");
	

	if( iic_priv.i2c_operate == IICWRITE )
	{
    	 if(!(iic_txmit.FLAG & (U32)iic_byte_addr_msb)) { 
         /* Send byte address: MSB */
         IICBUF = iic_txmit.BYTE_ADDR_MSB;
         iic_txmit.FLAG |= (U32)iic_byte_addr_msb; 
     	 }
     	 else if(!(iic_txmit.FLAG & (U32)iic_byte_addr_lsb)) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -