📄 i2c-iop3xx.c
字号:
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 + -