| #include <linux/kernel.h> |
| #include <linux/module.h> |
| #include <linux/i2c.h> |
| #include <linux/input.h> |
| #include <linux/input-polldev.h> |
| #include <linux/interrupt.h> |
| #include <linux/delay.h> |
| #include <linux/slab.h> |
| #include <linux/pm.h> |
| #include <linux/pm_runtime.h> |
| #include <linux/string.h> |
| #include <linux/dma-mapping.h> |
| #include <linux/gpio.h> |
| #include <mach/mt_gpio.h> |
| #include <cust_gpio_usage.h> |
| #include <cust_eint.h> |
| #include <mach/eint.h> |
| #include <cust_cwmcu.h> |
| #include <mach/mt_pm_ldo.h> |
| #include <linux/spi/spi.h> |
| #include <mtk_spi.h> |
| #include <mach/mt_sleep.h> |
| #include "CwMcuSensor.h" |
| |
| //extern struct CWMCU_data *sensor; |
| static DEFINE_MUTEX(cwmcu_bus_lock); |
| |
| |
| #ifdef CWMCU_I2C_INTERFACE |
| static u8 *CWI2CDMABuf_va = NULL; |
| static dma_addr_t CWI2CDMABuf_pa = 0; |
| 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 = 400}, |
| { |
| .addr = (client->addr & I2C_MASK_FLAG), |
| .ext_flag = |
| (client->ext_flag | I2C_ENEXT_FLAG | I2C_DMA_FLAG), |
| .flags = I2C_M_RD, |
| .buf = (u8 *) CWI2CDMABuf_pa, |
| .len = len, |
| .timing = 400}, |
| }; |
| |
| 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 = (u8 *) CWI2CDMABuf_pa, |
| .len = 1 + len, |
| .timing = 400 |
| }; |
| |
| 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;retry<len+1;retry++) |
| //{ |
| // CW_DEBUG("fwq4,.....wr_buf[%d]=%x",retry,wr_buf[retry]); |
| //} |
| for (retry = 0; retry < 5; ++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: 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; |
| |
| 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 = (u8 *) CWI2CDMABuf_pa, |
| .len = len, |
| .timing = 400}, |
| }; |
| |
| 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 = (u8 *) CWI2CDMABuf_pa, |
| .len = len, |
| .timing = 400 |
| }; |
| |
| 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"); |
| } |
| } |
| |
| static int CWMCU_i2c_probe(struct i2c_client *client, |
| const struct i2c_device_id *id) |
| { |
| |
| CWMCU_probe(client); |
| |
| return 0; |
| } |
| |
| static void CWMCU_i2c_shutdown(struct i2c_client *client) |
| { |
| struct CWMCU_T *sensor = i2c_get_clientdata(client); |
| CWMCU_shutdown(sensor); |
| } |
| |
| |
| static int CWMCU_i2c_remove(struct i2c_client *client) |
| { |
| struct CWMCU_T *sensor = i2c_get_clientdata(client); |
| kfree(sensor); |
| |
| return 0; |
| } |
| |
| static int CWMCU_i2c_suspend(struct device *dev) |
| { |
| return CWMCU_system_suspend(); |
| } |
| |
| static int CWMCU_i2c_resume(struct device *dev) |
| { |
| CWMCU_system_resume(); |
| return 0; |
| } |
| |
| 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_I2C_NAME, 0}, |
| {} |
| }; |
| |
| MODULE_DEVICE_TABLE(i2c, CWMCU_id); |
| |
| static struct i2c_driver CWMCU_i2c_driver = { |
| .driver = { |
| .name = CWMCU_I2C_NAME, |
| .owner = THIS_MODULE, |
| .pm = &CWMCU_pm_ops, |
| }, |
| .probe = CWMCU_i2c_probe, |
| .remove = CWMCU_i2c_remove, |
| .shutdown = CWMCU_i2c_shutdown, |
| .id_table = CWMCU_id, |
| }; |
| |
| #elif defined(CWMCU_SPI_INTERFACE) |
| |
| extern struct CWMCU_data *sensor; |
| unsigned char *cwmcu_spi_src_buffer_all = NULL; |
| static struct mt_chip_conf spi_conf; |
| |
| void spi_io_enable(int enable) |
| { |
| 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); |
| } |
| |
| } |
| |
| static int spi_xfer(unsigned char *txbuf, unsigned char *rxbuf, int len) |
| { |
| int ret; |
| 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); |
| |
| spi_io_enable(1); |
| |
| //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)) |
| ret = -1; |
| else |
| ret = 0; |
| |
| spi_io_enable(0); |
| |
| return ret; |
| } |
| |
| 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_serial_chksum(unsigned char *buffer, int len) |
| { |
| int i; |
| static u8 checksum; |
| |
| checksum = 0; |
| |
| spi_read_bytes_serial(cwmcu_spi_src_buffer_all, len + 1); |
| |
| for (i == 0; i < len; i++) { |
| checksum += cwmcu_spi_src_buffer_all[i]; |
| //CW_DEBUG("[%d]:0x%x, checksum=0x%x", i, cwmcu_spi_src_buffer_all[i], checksum); |
| } |
| |
| //CW_DEBUG("=>cal_chksum:0x%x, data_chksum:0x%x", checksum, cwmcu_spi_src_buffer_all[len]); |
| |
| if (checksum != cwmcu_spi_src_buffer_all[len]) { |
| CW_ERROR("SPI read checksum failed:0x%x(0x%x)", checksum, |
| cwmcu_spi_src_buffer_all[len]); |
| return -1; |
| } |
| memcpy(buffer, cwmcu_spi_src_buffer_all, len); |
| return 0; |
| } |
| |
| 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; |
| |
| 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; |
| } |
| #if CWMCU_SPI_CHECKSUM_SUPPORT |
| ret = spi_read_bytes_serial_chksum(buffer, len); |
| #else |
| ret = spi_read_bytes_serial(buffer, len); |
| #endif |
| if (ret < 0) { |
| CW_ERROR("spi_read_bytes: read failed"); |
| return ret; |
| } |
| |
| 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); |
| |
| 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; |
| } |
| |
| return ret; |
| } |
| |
| 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_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"); |
| } |
| sensor->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"); |
| } |
| |
| spi_io_enable(0); |
| //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); |
| |
| return 0; |
| } |
| |
| 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); |
| return 0; |
| } |
| |
| int CWMCU_spi_resume(struct spi_device *spi) |
| { |
| 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_SPI_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_T *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_T *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(struct CWMCU_T *sensor, 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(struct CWMCU_T *sensor, 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; |
| } |