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

📄 i2c-iop3xx.c

📁 I2C总线LINUX驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
		DEB2(printk( DFN "ERROR status 0x%02x\n", status ) ); 	}	return rc;#undef DFN}static int iop3xx_adap_write_byte( 	struct i2c_algo_iop3xx_data *iop3xx_adap, char byte, int stop ){#define DFN KERN_DEBUG "iop3xx_iop3xx_adap_write_byte()"	unsigned cr = *iop3xx_adap->biu->CR;	int status;	int rc;	*iop3xx_adap->biu->DBR = byte;	cr &= ~IOP321_ICR_MSTART;	if ( stop ){		cr |= IOP321_ICR_MSTOP;	}else{		cr &= ~IOP321_ICR_MSTOP;	}	*iop3xx_adap->biu->CR = cr |= IOP321_ICR_TBYTE;	rc = iop3xx_adap_wait_tx_done( iop3xx_adap, &status );	if ( rc != 0 ){		DEB(printk( DFN" ERROR status 0x%02x\n", status ));	}	return rc;#undef DFN} static int iop3xx_adap_read_byte(	struct i2c_algo_iop3xx_data *iop3xx_adap, char* byte, int stop ){#define DFN KERN_DEBUG "iop3xx_iop3xx_adap_read_byte()"	unsigned cr = *iop3xx_adap->biu->CR;	int status;	int rc;	cr &= ~IOP321_ICR_MSTART;	if ( stop ){		cr |= IOP321_ICR_MSTOP|IOP321_ICR_NACK;	}else{		cr &= ~(IOP321_ICR_MSTOP|IOP321_ICR_NACK);	}	*iop3xx_adap->biu->CR = cr |= IOP321_ICR_TBYTE;	rc = iop3xx_adap_wait_rx_done( iop3xx_adap, &status );	*byte = *iop3xx_adap->biu->DBR;	if ( rc != 0 ){		DEB(printk( DFN" ERROR status 0x%02x\n", status ));	}		return rc;#undef DFN}static int iop3xx_i2c_writebytes( struct i2c_adapter *i2c_adap, 				  const char *buf, int count ){	struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;	int ii;	int rc = 0;	for ( ii = 0; rc == 0 && ii != count; ++ii ){		rc = iop3xx_adap_write_byte(iop3xx_adap, buf[ii], ii==count-1);	}	return rc;}static int iop3xx_i2c_readbytes( struct i2c_adapter *i2c_adap, 				 char *buf, int count ){	struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;	int ii;	int rc = 0;	for ( ii = 0; rc == 0 && ii != count; ++ii ){		rc = iop3xx_adap_read_byte(iop3xx_adap, &buf[ii], ii==count-1);	}	return rc;}/* * Description:  This function implements combined transactions.  Combined * transactions consist of combinations of reading and writing blocks of data. * FROM THE SAME ADDRESS * Each transfer (i.e. a read or a write) is separated by a repeated start * condition. */static int iop3xx_handle_msg(	struct i2c_adapter *i2c_adap, struct i2c_msg* pmsg ) {	struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;	int rc;	rc = iop3xx_adap_send_target_slave_addr( iop3xx_adap, pmsg );	if ( rc < 0 ){		return rc;	}	if ( (pmsg->flags&I2C_M_RD) ){		return iop3xx_i2c_readbytes( i2c_adap, pmsg->buf, pmsg->len );	}else{		return iop3xx_i2c_writebytes( i2c_adap, pmsg->buf, pmsg->len );	}}/* * master_xfer() - main read/write entry */static int iop3xx_master_xfer(	struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num ){#define DFN KERN_DEBUG "iop3xx_master_xfer()"	struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;	int im = 0;	int ret = 0;	int status;	DEB2(printk(DFN "Waiting completion any pending transfers\n"));	iop3xx_adap_wait_idle( iop3xx_adap, &status );#ifdef PGMCOMOUT	DEB2(printk(DFN "init - this may not be necessary _every_ time\n"));	iop3xx_adap_init(iop3xx_adap);#else	iop3xx_adap_reset( iop3xx_adap );	iop3xx_adap_enable( iop3xx_adap );#endif	for ( im = 0; ret == 0 && im != num; ++im ){		ret = iop3xx_handle_msg( i2c_adap, &msgs[im] );	}	iop3xx_adap_transaction_cleanup( iop3xx_adap );	DEB2( if ( ret!=0 ) printk(DFN" ERROR return %d [%d]\n", ret, im ) );	return ret;   #undef DFN}static int algo_control(struct i2c_adapter *adapter, 	unsigned int cmd, unsigned long arg){	return 0;}static u32 iic_func(struct i2c_adapter *adap){	return I2C_FUNC_I2C|I2C_FUNC_SMBUS_EMUL;}/* -----exported algorithm data: -------------------------------------	*/static struct i2c_algorithm iic_algo = {	.name		= "IOP3xx I2C algorithm",	.id		= I2C_ALGO_IOP3XX,	.master_xfer	= iop3xx_master_xfer,	.algo_control	= algo_control,	.functionality	= iic_func,};/*  * registering functions to load algorithms at runtime  */static int i2c_iop3xx_add_bus(struct i2c_adapter *iic_adap){#define DFN KERN_DEBUG "i2c_iop3xx_add_bus() "	struct i2c_algo_iop3xx_data *iop3xx_adap = iic_adap->algo_data;	DEB2(printk(DFN": hw routines for %s registered.\n", iic_adap->name));	if ( !request_region( REGION_START(iop3xx_adap), 			      REGION_LENGTH(iop3xx_adap),			      iic_adap->name ) ){		return -ENODEV;	}			      	init_waitqueue_head( &iop3xx_adap->waitq );	spin_lock_init( &iop3xx_adap->lock );	if ( request_irq( 		     iop3xx_adap->biu->irq,		     iop3xx_i2c_handler,		     /* SA_SAMPLE_RANDOM */ 0,		     iic_adap->name,		     iop3xx_adap )          ){		return -ENODEV;	}			  /* register new iic_adapter to i2c module... */	iic_adap->id |= iic_algo.id;	iic_adap->algo = &iic_algo;	iic_adap->timeout = 100;	/* default values, should	*/	iic_adap->retries = 3;		/* be replaced by defines	*/	iop3xx_adap_init( iic_adap->algo_data );	i2c_add_adapter(iic_adap);	return 0;#undef DFN}static int i2c_iop3xx_del_bus(struct i2c_adapter *iic_adap){	struct i2c_algo_iop3xx_data *iop3xx_adap = iic_adap->algo_data;	iop3xx_adap_final_cleanup( iop3xx_adap );	free_irq( iop3xx_adap->biu->irq, iop3xx_adap );	release_region( REGION_START(iop3xx_adap), REGION_LENGTH(iop3xx_adap));	return i2c_del_adapter( iic_adap );}static void i2c_iop3xx_inc_use(struct i2c_adapter *adap){#ifdef MODULE	MOD_INC_USE_COUNT;#endif}static void i2c_iop3xx_dec_use(struct i2c_adapter *adap){#ifdef MODULE	MOD_DEC_USE_COUNT;#endif}#ifdef CONFIG_ARCH_IOP321static struct iop3xx_biu biu0 = {	.CR     = IOP321_ICR0,	.SR     = IOP321_ISR0,	.SAR    = IOP321_ISAR0,	.DBR    = IOP321_IDBR0,	.BMR    = IOP321_IBMR0,	.irq    = IRQ_IOP321_I2C_0};static struct iop3xx_biu biu1 = {	.CR     = IOP321_ICR1,	.SR     = IOP321_ISR1,	.SAR    = IOP321_ISAR1,	.DBR    = IOP321_IDBR1,	.BMR    = IOP321_IBMR1,	.irq    = IRQ_IOP321_I2C_1};#define ADAPTER_NAME_ROOT "IOP321 i2c biu adapter "#else#error Please define the BIU struct iop3xx_biu for your processor arch#endifstatic struct i2c_algo_iop3xx_data  algo_iop3xx_data0 = {	.channel                = 0,	.biu                    = &biu0,	.timeout                = 1*HZ};static struct i2c_algo_iop3xx_data  algo_iop3xx_data1 = {        .channel                = 1,	.biu                    = &biu1,	.timeout                = 1*HZ};static struct i2c_adapter iop3xx_ops0 = {	.name			= ADAPTER_NAME_ROOT "0",	.id			= I2C_HW_IOP321,	.algo_data		= &algo_iop3xx_data0,	.inc_use		= i2c_iop3xx_inc_use,	.dec_use		= i2c_iop3xx_dec_use,};static struct i2c_adapter iop3xx_ops1 = {	.name			= ADAPTER_NAME_ROOT "1",	.id			= I2C_HW_IOP321,	.algo_data		= &algo_iop3xx_data1,	.inc_use		= i2c_iop3xx_inc_use,	.dec_use		= i2c_iop3xx_dec_use,};static int __init i2c_iop3xx_init (void){	return i2c_iop3xx_add_bus(&iop3xx_ops0) ||		i2c_iop3xx_add_bus(&iop3xx_ops1);}static void __exit i2c_iop3xx_exit (void){	i2c_iop3xx_del_bus(&iop3xx_ops0);	i2c_iop3xx_del_bus(&iop3xx_ops1);}module_init (i2c_iop3xx_init);module_exit (i2c_iop3xx_exit);MODULE_AUTHOR("D-TACQ Solutions Ltd <www.d-tacq.com>");MODULE_DESCRIPTION("IOP3xx iic algorithm and driver");MODULE_LICENSE("GPL");MODULE_PARM(i2c_debug,"i");MODULE_PARM_DESC(i2c_debug,        "debug level - 0 off; 1 normal; 2,3 more verbose; 9 iic-protocol");

⌨️ 快捷键说明

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