#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "CwMcuSensor.h" extern struct CWMCU_data *sensor; static DEFINE_MUTEX(cwmcu_bus_lock); #ifdef CWMCU_I2C_INTERFACE static u8 *CWI2CDMABuf_va = NULL; static u64 CWI2CDMABuf_pa = NULL; static struct i2c_board_info __initdata i2c_cw_boardinfo = { I2C_BOARD_INFO("CwMcuSensor", (0x3a))}; static s32 i2c_dma_read(struct i2c_client *client, u8 addr, u8 *rxbuf, s32 len) { int ret; s32 retry = 0; u8 buffer[2]; struct i2c_msg msg[2] = { { .addr = (client->addr & I2C_MASK_FLAG), .flags = 0,//(client->ext_flag | I2C_ENEXT_FLAG | I2C_DMA_FLAG), .buf = buffer, .len = 1, .timing = I2C_MASTER_CLOCK }, { .addr = (client->addr & I2C_MASK_FLAG), .ext_flag = (client->ext_flag | I2C_ENEXT_FLAG | I2C_DMA_FLAG), .flags = I2C_M_RD, .buf = CWI2CDMABuf_pa, .len = len, .timing = I2C_MASTER_CLOCK }, }; buffer[0] = addr; if (rxbuf == NULL) return -1; //GTP_DEBUG("dma i2c read: 0x%04X, %d bytes(s)", addr, len); for (retry = 0; retry < 10; ++retry) { ret = i2c_transfer(client->adapter, &msg[0], 2); if (ret < 0) { CW_ERROR("I2C DMA read error retry=%d", retry); continue; } memcpy(rxbuf, CWI2CDMABuf_va, len); return 0; } CW_ERROR("Dma I2C Read Error: 0x%04X, %d byte(s), err-code: %d", addr, len, ret); return ret; } static s32 i2c_dma_write(struct i2c_client *client, u8 addr, u8 *txbuf, s32 len) { int ret; s32 retry = 0; u8 *wr_buf = CWI2CDMABuf_va; //CW_DEBUG("fwq3,.....%x",txbuf[0]); struct i2c_msg msg = { .addr = (client->addr & I2C_MASK_FLAG), .ext_flag = (client->ext_flag | I2C_ENEXT_FLAG | I2C_DMA_FLAG), .flags = 0, .buf = CWI2CDMABuf_pa, .len = 1+len, .timing = I2C_MASTER_CLOCK }; wr_buf[0] = addr; if (txbuf == NULL) return -1; //GTP_DEBUG("dma i2c write: 0x%04X, %d bytes(s)", addr, len); memcpy(wr_buf+1, txbuf, len+1); //for(retry=0;retryadapter, &msg, 1); if (ret < 0) { CW_ERROR("I2C DMA write error retry=%d", retry); continue; } return 0; } CW_ERROR("Dma I2C Write Error: 0x%04X, %d byte(s), err-code: %d", addr, len, ret); return ret; } static s32 i2c_dma_read_serial(struct i2c_client *client, u8 *rxbuf, s32 len) { int ret; s32 retry = 0; u8 buffer[2]; struct i2c_msg msg[2] = { { .addr = (client->addr & I2C_MASK_FLAG), .ext_flag = (client->ext_flag | I2C_ENEXT_FLAG | I2C_DMA_FLAG), .flags = I2C_M_RD, .buf = CWI2CDMABuf_pa, .len = len, .timing = I2C_MASTER_CLOCK }, }; if (rxbuf == NULL) return -1; //GTP_DEBUG("dma i2c read: 0x%04X, %d bytes(s)", addr, len); for (retry = 0; retry < 5; ++retry) { ret = i2c_transfer(client->adapter, &msg[0], 1); if (ret < 0) { CW_ERROR("I2C DMA read error retry=%d", retry); continue; } memcpy(rxbuf, CWI2CDMABuf_va, len); return 0; } CW_ERROR("Dma I2C Read Error: %d byte(s), err-code: %d", len, ret); return ret; } static s32 i2c_dma_write_serial(struct i2c_client *client, u8 *txbuf, s32 len) { int ret; s32 retry = 0; u8 *wr_buf = CWI2CDMABuf_va; struct i2c_msg msg = { .addr = (client->addr & I2C_MASK_FLAG), .ext_flag = (client->ext_flag | I2C_ENEXT_FLAG | I2C_DMA_FLAG), .flags = 0, .buf = CWI2CDMABuf_pa, .len = len, .timing = I2C_MASTER_CLOCK }; if (txbuf == NULL) return -1; //GTP_DEBUG("dma i2c write: 0x%04X, %d bytes(s)", addr, len); memcpy(wr_buf, txbuf, len); for (retry = 0; retry < 10; ++retry) { ret = i2c_transfer(client->adapter, &msg, 1); if (ret < 0) { CW_ERROR("I2C DMA write error retry=%d", retry); continue; } return 0; } CW_ERROR("Dma I2C Write Error: %d byte(s), err-code: %d",len, ret); return ret; } static s32 i2c_read_bytes_dma(struct i2c_client *client, u8 addr, u8 *rxbuf, s32 len) { s32 left = len; s32 read_len = 0; u8 *rd_buf = rxbuf; s32 ret = 0; //GTP_DEBUG("Read bytes dma: 0x%04X, %d byte(s)", addr, len); while (left > 0) { if (left > GTP_DMA_MAX_TRANSACTION_LENGTH) { read_len = GTP_DMA_MAX_TRANSACTION_LENGTH; } else { read_len = left; } ret = i2c_dma_read(client, addr, rd_buf, read_len); if (ret < 0) { CW_ERROR("dma read failed"); return -1; } left -= read_len; addr += read_len; rd_buf += read_len; } return 0; } static s32 i2c_write_bytes_dma(struct i2c_client *client, u8 addr, u8 *txbuf, s32 len) { s32 ret = 0; s32 write_len = 0; s32 left = len; u8 *wr_buf = txbuf; //CW_DEBUG("fwq2...%x",txbuf[0]); //GTP_DEBUG("Write bytes dma: 0x%04X, %d byte(s)", addr, len); while (left > 0) { if (left > GTP_DMA_MAX_I2C_TRANSFER_SIZE) { write_len = GTP_DMA_MAX_I2C_TRANSFER_SIZE; } else { write_len = left; } ret = i2c_dma_write(client, addr, wr_buf, write_len); if (ret < 0) { CW_ERROR("dma i2c write failed!"); return -1; } left -= write_len; addr += write_len; wr_buf += write_len; } return 0; } static s32 i2c_write_bytes_dma_serial(struct i2c_client *client,u8 *txbuf, s32 len) { s32 ret = 0; s32 write_len = 0; s32 left = len; u8 *wr_buf = txbuf; //GTP_DEBUG("Write bytes dma: 0x%04X, %d byte(s)", addr, len); while (left > 0) { if (left > GTP_DMA_MAX_I2C_TRANSFER_SIZE) { write_len = GTP_DMA_MAX_I2C_TRANSFER_SIZE; } else { write_len = left; } ret = i2c_dma_write_serial(client, wr_buf, write_len); if (ret < 0) { CW_ERROR("dma i2c write failed!"); return -1; } left -= write_len; wr_buf += write_len; } return 0; } static s32 i2c_read_bytes_dma_serial(struct i2c_client *client, u8 *rxbuf, s32 len) { s32 left = len; s32 read_len = 0; u8 *rd_buf = rxbuf; s32 ret = 0; //GTP_DEBUG("Read bytes dma: 0x%04X, %d byte(s)", addr, len); while (left > 0) { if (left > GTP_DMA_MAX_TRANSACTION_LENGTH) { read_len = GTP_DMA_MAX_TRANSACTION_LENGTH; } else { read_len = left; } ret = i2c_dma_read_serial(client, rd_buf, read_len); if (ret < 0) { CW_ERROR("dma read serial failed"); return -1; } left -= read_len; rd_buf += read_len; } return 0; } void i2c_init(void *client) { CWI2CDMABuf_va = (u8 *)dma_alloc_coherent(NULL, GTP_DMA_MAX_TRANSACTION_LENGTH, &CWI2CDMABuf_pa, GFP_KERNEL); if(!CWI2CDMABuf_va) { CW_INFO("[sensorHUB] dma_alloc_coherent error"); } sensor->client = (struct i2c_client *)client; i2c_set_clientdata(sensor->client, sensor); } static int CWMCU_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { CW_ERROR("i2c_check_functionality error"); return -EIO; } CWMCU_probe(client); pm_runtime_enable(&client->dev); return 0; } static int CWMCU_i2c_remove(struct i2c_client *client) { struct CWMCU_data *sensor = i2c_get_clientdata(client); kfree(sensor); return 0; } static int CWMCU_i2c_suspend(struct device *dev) { CWMCU_suspend(&sensor->client->dev); } static int CWMCU_i2c_resume(struct device *dev) { CWMCU_resume(&sensor->client->dev); } static const struct dev_pm_ops CWMCU_pm_ops = { .suspend = CWMCU_i2c_suspend, .resume = CWMCU_i2c_resume }; static const struct i2c_device_id CWMCU_id[] = { { CWMCU_NAME, 0 }, { } }; MODULE_DEVICE_TABLE(i2c, CWMCU_id); static struct i2c_driver CWMCU_i2c_driver = { .driver = { .name = CWMCU_NAME, .owner = THIS_MODULE, /*.pm = &CWMCU_pm_ops,*/ }, .probe = CWMCU_i2c_probe, .remove = CWMCU_i2c_remove, .id_table = CWMCU_id, }; #elif defined(CWMCU_SPI_INTERFACE) #define CWMCU_SPI_OLD_PROTOCOL unsigned char* cwmcu_spi_src_buffer_all = NULL; static struct mt_chip_conf spi_conf; static int spi_xfer(unsigned char *txbuf,unsigned char *rxbuf, int len) { struct spi_transfer transfer_1[2]; int const pkt_count = len / CWMCU_SPI_INTERFACE_MAX_PKT_LENGTH_PER_TIMES; int const remainder = len % CWMCU_SPI_INTERFACE_MAX_PKT_LENGTH_PER_TIMES; struct spi_message msg; spi_message_init(&msg); //CW_INFO(" len=%d, txbuf=0x%x, rxbuf=0x%x", len, txbuf, rxbuf); if(len>CWMCU_SPI_INTERFACE_MAX_PKT_LENGTH_PER_TIMES){ transfer_1[0].tx_buf =(txbuf==NULL)?NULL: txbuf; transfer_1[0].rx_buf =(rxbuf==NULL)?NULL: rxbuf; transfer_1[0].len = CWMCU_SPI_INTERFACE_MAX_PKT_LENGTH_PER_TIMES * pkt_count; spi_message_add_tail(&transfer_1[0], &msg); if(0 != remainder) { transfer_1[1].tx_buf =(txbuf==NULL)?NULL:txbuf+ (CWMCU_SPI_INTERFACE_MAX_PKT_LENGTH_PER_TIMES * pkt_count); transfer_1[1].rx_buf =(rxbuf==NULL)?NULL:rxbuf+ (CWMCU_SPI_INTERFACE_MAX_PKT_LENGTH_PER_TIMES * pkt_count); transfer_1[1].len = remainder; spi_message_add_tail(&transfer_1[1], &msg); } } else{ transfer_1[0].tx_buf =(txbuf==NULL)?NULL: txbuf; transfer_1[0].rx_buf =(rxbuf==NULL)?NULL: rxbuf; transfer_1[0].len = len; spi_message_add_tail(&transfer_1[0], &msg); } if(spi_sync(sensor->spi, &msg)) return -1; else return 0; } static int spi_write_bytes_serial(unsigned char *buffer, int len) { int ret = 0; unsigned char* tx_buf=NULL, *rx_buf=NULL; if(len > CWMCU_SPI_INTERFACE_MAX_PKT_LENGTH_PER_TIMES){ tx_buf = buffer; rx_buf =NULL; } else{ if(cwmcu_spi_src_buffer_all==NULL) return -1; if(buffer != cwmcu_spi_src_buffer_all) memcpy(cwmcu_spi_src_buffer_all,buffer,len); tx_buf = cwmcu_spi_src_buffer_all; rx_buf =NULL; } ret = spi_xfer(tx_buf,rx_buf, len); return ret; } static int spi_read_bytes_serial(unsigned char *buffer, int len) { int ret = 0; unsigned char *tx_buf=NULL, *rx_buf=NULL; if(len>CWMCU_SPI_INTERFACE_MAX_PKT_LENGTH_PER_TIMES){ tx_buf = NULL; rx_buf = buffer; ret = spi_xfer(tx_buf,rx_buf, len); } else{ if(cwmcu_spi_src_buffer_all == NULL) return -1; tx_buf = NULL; rx_buf = cwmcu_spi_src_buffer_all; ret = spi_xfer(tx_buf,rx_buf, len); if(ret == 0) memcpy(buffer,cwmcu_spi_src_buffer_all,len); } return ret; } static int spi_read_bytes(u8 reg_addr, u8 *buffer, u8 len) { int ret = 0; //CW_DEBUG("[SPI]R_Reg:0x%x, len=%d", reg_addr, len); if(cwmcu_spi_src_buffer_all == NULL) return -1; #ifdef CWMCU_SPI_OLD_PROTOCOL cwmcu_spi_src_buffer_all[0]= reg_addr; ret = spi_xfer(cwmcu_spi_src_buffer_all, NULL, 1); if (ret < 0) { CW_ERROR("spi_read_bytes: write failed"); return ret; } ret = spi_read_bytes_serial(buffer, len); if (ret < 0) { CW_ERROR("spi_read_bytes: read failed"); return ret; } #else //New Protocol cwmcu_spi_src_buffer_all[0]= 0x0; cwmcu_spi_src_buffer_all[1]= 0xA1; cwmcu_spi_src_buffer_all[2]= reg_addr; ret = spi_xfer(cwmcu_spi_src_buffer_all, NULL, 15); if (ret < 0) { CW_ERROR("spi_read_bytes: write failed"); return ret; } ret = spi_read_bytes_serial(cwmcu_spi_src_buffer_all, 15); if (ret < 0) { CW_ERROR("spi_read_bytes: read failed"); return ret; } memcpy(buffer, &cwmcu_spi_src_buffer_all[3], len); #endif return ret; } static int spi_write_bytes(u8 reg_addr, u8 *buffer, u8 len) { int ret = 0; if(cwmcu_spi_src_buffer_all == NULL) return -1; //CW_DEBUG("[SPI]W_Reg:0x%x, len=%d", reg_addr, len); #if 0 cwmcu_spi_src_buffer_all[0] = reg_addr; memcpy(&cwmcu_spi_src_buffer_all[1], buffer, len); ret = spi_write_bytes_serial(cwmcu_spi_src_buffer_all, len+1); if (ret < 0) { CW_ERROR("spi_write_bytes: write failed"); return ret; }: #elif defined(CWMCU_SPI_OLD_PROTOCOL) cwmcu_spi_src_buffer_all[0] = reg_addr; ret = spi_xfer(cwmcu_spi_src_buffer_all, NULL, 1); if (ret < 0) { CW_ERROR("spi_write_bytes 1st: write failed"); return ret; } memcpy(&cwmcu_spi_src_buffer_all[0], buffer, len); ret = spi_write_bytes_serial(cwmcu_spi_src_buffer_all, len); if (ret < 0) { CW_ERROR("spi_write_bytes 2nd: write failed"); return ret; } #else //New protocol cwmcu_spi_src_buffer_all[0] = 0x0; cwmcu_spi_src_buffer_all[1] = 0xA0; cwmcu_spi_src_buffer_all[2] = reg_addr; memcpy(&cwmcu_spi_src_buffer_all[3], buffer, len); ret = spi_write_bytes_serial(cwmcu_spi_src_buffer_all, 15); if (ret < 0) { CW_ERROR("spi_write_bytes: write failed"); return ret; } #endif } int spi_rw_bytes_serial(u8 *wbuf, u8 *rbuf, u8 len) { int ret; unsigned char *tx_buf=NULL, *rx_buf=NULL; tx_buf = wbuf; rx_buf = cwmcu_spi_src_buffer_all; ret = spi_xfer(tx_buf, rx_buf, len); if(ret == 0) memcpy(rbuf,cwmcu_spi_src_buffer_all, len); else if (ret < 0) { CW_ERROR("spi_rw_bytes: read failed"); } return ret; } void spi_io_enable(int enable) { #if 1 if (enable){ mt_set_gpio_mode(GPIO_SPI_CS_PIN, GPIO_SPI_CS_PIN_M_SPI_CS); mt_set_gpio_mode(GPIO_SPI_SCK_PIN, GPIO_SPI_SCK_PIN_M_SPI_SCK); mt_set_gpio_mode(GPIO_SPI_MISO_PIN, GPIO_SPI_MISO_PIN_M_SPI_MISO); mt_set_gpio_mode(GPIO_SPI_MOSI_PIN, GPIO_SPI_MOSI_PIN_M_SPI_MOSI); } else{ //set dir pull to save power mt_set_gpio_mode(GPIO_SPI_CS_PIN, GPIO_SPI_CS_PIN_M_GPIO); mt_set_gpio_dir(GPIO_SPI_CS_PIN, GPIO_DIR_IN); mt_set_gpio_pull_enable(GPIO_SPI_CS_PIN, GPIO_PULL_DISABLE); mt_set_gpio_mode(GPIO_SPI_SCK_PIN, GPIO_SPI_SCK_PIN_M_GPIO); mt_set_gpio_dir(GPIO_SPI_SCK_PIN, GPIO_DIR_IN); mt_set_gpio_pull_enable(GPIO_SPI_SCK_PIN, GPIO_PULL_DISABLE); mt_set_gpio_mode(GPIO_SPI_MISO_PIN, GPIO_SPI_MISO_PIN_M_GPIO); mt_set_gpio_dir(GPIO_SPI_MISO_PIN, GPIO_DIR_IN); mt_set_gpio_pull_enable(GPIO_SPI_MISO_PIN, GPIO_PULL_DISABLE); mt_set_gpio_mode(GPIO_SPI_MOSI_PIN, GPIO_SPI_MOSI_PIN_M_GPIO); mt_set_gpio_dir(GPIO_SPI_MOSI_PIN, GPIO_DIR_IN); mt_set_gpio_pull_enable(GPIO_SPI_MOSI_PIN, GPIO_PULL_DISABLE); } #endif } void spi_init(void *dev) { struct mt_chip_conf* spi_par; sensor->spi = dev; spi_io_enable(1); cwmcu_spi_src_buffer_all = kmalloc(CWMCU_SPI_INTERFACE_MAX_PKT_LENGTH_PER_TIMES,GFP_KERNEL); if(cwmcu_spi_src_buffer_all== NULL){ CW_ERROR("error kmalloc fail cwmcu_spi_src_buffer_all"); } //INNODev->spi->controller_data =(void*)&spi_conf; spi_par =&spi_conf; if(!spi_par){ CW_ERROR("spi config fail"); } spi_par->setuptime = 15; spi_par->holdtime = 15; spi_par->high_time = 10; //10--6m 15--4m 20--3m 30--2m [ 60--1m 120--0.5m 300--0.2m] spi_par->low_time = 10; spi_par->cs_idletime = 20; spi_par->rx_mlsb = 1; spi_par->tx_mlsb = 1; spi_par->tx_endian = 0; spi_par->rx_endian = 0; spi_par->cpol = 0; spi_par->cpha = 0; spi_par->com_mod = DMA_TRANSFER; spi_par->pause = 0; spi_par->finish_intr = 1; spi_par->deassert = 0; if(spi_setup(sensor->spi)){ CW_ERROR("spi_setup fail"); } //TODO //SPI DMA SETTING } int CWMCU_spi_probe(struct spi_device *spi) { CW_INFO("CWMCU_spi_probe entry"); CWMCU_probe(spi); pm_runtime_enable(&spi->dev); } int CWMCU_spi_remove(struct spi_device *spi) { sensor->spi = NULL; return 0; } int CWMCU_spi_suspend(struct spi_device *spi, pm_message_t mesg) { CWMCU_suspend(&spi->dev); spi_io_enable(0); return 0; } int CWMCU_spi_resume(struct spi_device *spi) { spi_io_enable(1); CWMCU_resume(&spi->dev); } static struct spi_board_info spi_cw_boardinfo __initdata = { .modalias = CWMCU_NAME, .bus_num = 0, .chip_select=0, .mode = SPI_MODE_3, }; static struct spi_driver CWMCU_spi_driver = { .driver = { .name = CWMCU_NAME, .owner = THIS_MODULE, }, .probe = CWMCU_spi_probe, .remove = CWMCU_spi_remove, .suspend = CWMCU_spi_suspend, .resume = CWMCU_spi_resume, }; #endif //bus type /*======================================================== */ void CWMCU_bus_init(void *bus_dev) { #if defined(CWMCU_I2C_INTERFACE) i2c_init(bus_dev); #elif defined(CWMCU_SPI_INTERFACE) spi_init(bus_dev); #endif } int CWMCU_bus_register(void) { #if defined(CWMCU_I2C_INTERFACE) i2c_register_board_info(CWMCU_I2C_NUMBER, &i2c_cw_boardinfo, 1); return i2c_add_driver(&CWMCU_i2c_driver); #elif defined(CWMCU_SPI_INTERFACE) spi_register_board_info(&spi_cw_boardinfo, 1); return spi_register_driver(&CWMCU_spi_driver); #endif } void CWMCU_bus_unregister(void) { #if defined(CWMCU_I2C_INTERFACE) i2c_del_driver(&CWMCU_i2c_driver); #elif defined(CWMCU_SPI_INTERFACE) #endif } int CWMCU_bus_write(struct CWMCU_data *sensor, u8 reg_addr, u8 *data, u8 len) { int ret; mutex_lock(&cwmcu_bus_lock); #if defined(CWMCU_I2C_INTERFACE) ret = i2c_write_bytes_dma(sensor->client, reg_addr, data,len); #elif defined(CWMCU_SPI_INTERFACE) ret = spi_write_bytes(reg_addr, data, len); #endif mutex_unlock(&cwmcu_bus_lock); return ret; } /* Returns the number of read bytes on success */ int CWMCU_bus_read(struct CWMCU_data *sensor, u8 reg_addr, u8 *data, u8 len) { int ret = 0; mutex_lock(&cwmcu_bus_lock); #if defined(CWMCU_I2C_INTERFACE) ret = i2c_read_bytes_dma(sensor->client, reg_addr, data, len); #elif defined(CWMCU_SPI_INTERFACE) ret = spi_read_bytes(reg_addr, data, len); #endif mutex_unlock(&cwmcu_bus_lock); return ret; } int CWMCU_bus_write_serial(u8 *data, int len) { int ret = 0; mutex_lock(&cwmcu_bus_lock); #if defined(CWMCU_I2C_INTERFACE) ret = i2c_write_bytes_dma_serial(sensor->client, data, len); if (ret < 0) { CW_ERROR("i2c write error =%d", ret); goto BUS_WS_EXIT; } #elif defined(CWMCU_SPI_INTERFACE) ret = spi_write_bytes_serial(data, len); if (ret < 0) { CW_ERROR("spi write error =%d", ret); goto BUS_WS_EXIT; } #endif mutex_unlock(&cwmcu_bus_lock); BUS_WS_EXIT: return ret; } int CWMCU_bus_read_serial(u8 *data, int len) { int ret = 0; mutex_lock(&cwmcu_bus_lock); #if defined(CWMCU_I2C_INTERFACE) ret = i2c_read_bytes_dma_serial(sensor->client, data, len); if (ret < 0) { CW_ERROR("i2c read error =%d", ret); goto BUS_RS_EXIT; } #elif defined(CWMCU_SPI_INTERFACE) ret = spi_read_bytes_serial(data, len); if (ret < 0) { CW_ERROR("spi read error =%d", ret); goto BUS_RS_EXIT; } #endif mutex_unlock(&cwmcu_bus_lock); BUS_RS_EXIT: return ret; }