| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493 |
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/i2c.h>
- #include <linux/platform_device.h>
- #include <linux/dma-mapping.h>
- #include <linux/slab.h>
- #include <linux/errno.h>
- #include <linux/err.h>
- /* #include <mach/mt_pm_ldo.h> */
- #include <asm/memory.h>
- #include <mt_i2c.h>
- static char data_buffer[256 * 4];
- static ssize_t show_config(struct device *dev, struct device_attribute *attr, char *buff)
- {
- int len = strlen(data_buffer);
- memcpy(buff, data_buffer, len);
- I2CLOG("Return Value:%s\n", data_buffer);
- return len;
- }
- static int pows(int x, int y)
- {
- int result = 1;
- while (y--)
- result *= x;
- return result;
- }
- int string2hex(const char *buffer, int cnt)
- {
- int c = 0;
- char t = 0;
- int count = cnt;
- while (count--) {
- t = *(buffer + cnt - count - 1);
- if (t >= 'A' && t <= 'F')
- c += ((t - 'A') + 10) * pows(16, count);
- else if (t >= '0' && t <= '9')
- c += (t - '0') * pows(16, count);
- else
- c = -1;
- }
- return c;
- }
- char *get_hexbuffer(char *data_buffer, char *hex_buffer)
- {
- char *ptr = data_buffer;
- int index = 0;
- while (*ptr && *++ptr) {
- *(hex_buffer + index++) = string2hex(ptr - 1, 2);
- ptr++;
- }
- *(hex_buffer + index) = 0;
- return hex_buffer;
- }
- int i2c_trans_data(int bus_id, int address, char *buf, int count, unsigned int ext_flag, int timing,
- int op)
- {
- int ret;
- struct i2c_msg msg;
- struct i2c_adapter *adap;
- adap = i2c_get_adapter(bus_id);
- if (!adap)
- return -1;
- msg.addr = address;
- if (0 == op)
- msg.flags = 0;
- else if (1 == op)
- msg.flags = I2C_M_RD;
- else if (2 == op)
- msg.flags = 0;
- /* msg.flags = ((ext_flag & 0x80000000)?I2C_M_RD:0); */
- msg.len = count;
- msg.buf = (char *)buf;
- #ifdef CONFIG_MTK_I2C_EXTENSION
- msg.timing = timing;
- msg.ext_flag = ext_flag;
- #endif
- /* msg.ext_flag = (ext_flag & 0x7FFF00FF); */
- /* msg.addr |= ext_flag & 0x0000FF00; */
- ret = i2c_transfer(adap, &msg, 1);
- /* If everything went ok (i.e. 1 msg transmitted), return #bytes
- transmitted, else error code. */
- i2c_put_adapter(adap);
- return (ret == 1) ? count : ret;
- }
- int mt_i2c_test(int id, int addr)
- {
- int ret = 0;
- unsigned long flag;
- /* unsigned char buffer[]={0x55}; */
- if (id > 3)
- flag = I2C_DIRECTION_FLAG;
- /* flag |= 0x80000000; */
- /* ret = i2c_trans_data(id, addr,buffer,1,flag,200); */
- return ret;
- }
- EXPORT_SYMBOL(mt_i2c_test);
- /* extern struct mt_i2c_t ; */
- static int i2c_test_reg(int bus_id, int val)
- {
- int ret = 0;
- struct i2c_adapter *adap;
- struct mt_i2c_t *i2c;
- adap = i2c_get_adapter(bus_id);
- if (!adap)
- return -1;
- i2c = container_of(adap, struct mt_i2c_t, adap);
- I2CLOG("I2C%d base address 0x%p\n", bus_id, i2c->base);
- /* write i2c writable register with 0 */
- i2c_writel(i2c, OFFSET_SLAVE_ADDR, val);
- i2c_writel(i2c, OFFSET_INTR_MASK, val);
- i2c_writel(i2c, OFFSET_INTR_STAT, val);
- i2c_writel(i2c, OFFSET_CONTROL, val);
- i2c_writel(i2c, OFFSET_TRANSFER_LEN, val);
- i2c_writel(i2c, OFFSET_TRANSAC_LEN, val);
- i2c_writel(i2c, OFFSET_DELAY_LEN, val);
- i2c_writel(i2c, OFFSET_TIMING, val);
- i2c_writel(i2c, OFFSET_EXT_CONF, val);
- i2c_writel(i2c, OFFSET_IO_CONFIG, val);
- i2c_writel(i2c, OFFSET_HS, val);
- /* If everything went ok (i.e. 1 msg transmitted), return #bytes
- transmitted, else error code. */
- i2c_put_adapter(adap);
- return ret;
- }
- static int i2c_soft_reset(int bus_id)
- {
- int ret = 0;
- struct i2c_adapter *adap;
- struct mt_i2c_t *i2c;
- adap = i2c_get_adapter(bus_id);
- if (!adap)
- return -1;
- i2c = container_of(adap, struct mt_i2c_t, adap);
- I2CLOG("I2C%d base address 0x%p\n", bus_id, i2c->base);
- /* write i2c writable register with 0 */
- i2c_writel(i2c, OFFSET_SOFTRESET, 1);
- /* If everything went ok (i.e. 1 msg transmitted), return #bytes
- transmitted, else error code. */
- i2c_put_adapter(adap);
- return ret;
- }
- static int i2c_ext_conf_test(int bus_id, int val)
- {
- int ret = 0;
- struct i2c_adapter *adap;
- struct mt_i2c_t *i2c;
- adap = i2c_get_adapter(bus_id);
- if (!adap)
- return -1;
- i2c = container_of(adap, struct mt_i2c_t, adap);
- I2CLOG("I2C%d base address 0x%p\n", bus_id, i2c->base);
- /* write i2c writable register with 0 */
- i2c_writel(i2c, OFFSET_EXT_CONF, val);
- I2CLOG("EXT_CONF 0x%x", i2c_readl(i2c, OFFSET_EXT_CONF));
- /* If everything went ok (i.e. 1 msg transmitted), return #bytes
- transmitted, else error code. */
- i2c_put_adapter(adap);
- return ret;
- }
- static void hex2string(unsigned char *in, unsigned char *out, int length)
- {
- unsigned char *ptr = in;
- unsigned char *ptrout = out;
- unsigned char t;
- while (length--) {
- t = (*ptr & 0xF0) >> 4;
- if (t < 10)
- *ptrout = t + '0';
- else
- *ptrout = t + 'A' - 10;
- ptrout++;
- t = (*ptr & 0x0F);
- if (t < 10)
- *ptrout = t + '0';
- else
- *ptrout = t + 'A' - 10;
- ptr++;
- ptrout++;
- }
- *ptrout = 0;
- }
- static ssize_t set_config(struct device *dev, struct device_attribute *attr, const char *buf,
- size_t count)
- {
- int bus_id;
- int address;
- int operation;
- int trans_mode;
- int trans_stop;
- int speed_mode;
- int pushpull_mode;
- int query_mode;
- int timing;
- int trans_num;
- int trans_auxlen;
- int dir = 0;
- int number = 0;
- int length = 0;
- unsigned int ext_flag = 0;
- dma_addr_t dma_addr = 0;
- void *vir_addr = NULL;
- /* int status; */
- int ret = 0;
- unsigned char tmpbuffer[128];
- I2CLOG("%s\n", buf);
- /* if ( sscanf(buf, "%d %d %d %d %d %d %d %d %d %d %d %d %s",
- &bus_id, &address, &operation, &trans_mode, &trans_stop,
- &speed_mode, &pushpull_mode, &query_mode, &timing, &trans_num,
- &trans_auxlen,&dir, data_buffer) ) { */
- if (sscanf(buf, "%d %x %d %d %d %d %d %d %d %d %d %s", &bus_id, &address, &operation, &trans_mode,
- &trans_stop, &speed_mode, &pushpull_mode, &query_mode, &timing, &trans_num,
- &trans_auxlen, data_buffer) != 0) {
- if ((address != 0) && (operation <= 2)) {
- length = strlen(data_buffer);
- if (operation == 0) {
- ext_flag |= I2C_WR_FLAG;
- number = (trans_auxlen << 8) | (length >> 1); /* /TODO:need to confitm 8 Or 16 */
- } else if (operation == 1) {
- /* ext_flag |= 0x80000000; */
- number = (trans_num << 16) | (length >> 1);
- } else if (operation == 2) {
- /* ext_flag &= 0x7FFFFFFF; */
- number = (trans_num << 16) | (length >> 1);
- } else {
- I2CERR("invalid operation\n");
- goto err;
- }
- if (dir > 0)
- ext_flag |= I2C_DIRECTION_FLAG;
- if (trans_mode == 0) {
- /* default is fifo */
- } else if (trans_mode == 1) {
- ext_flag |= I2C_DMA_FLAG;
- } else {
- I2CERR("invalid trans_mod fifo/dma\n");
- goto err;
- }
- if (trans_stop == 0) {
- /* default */
- } else if (trans_stop == 1) {
- ext_flag |= I2C_RS_FLAG;
- } else {
- I2CERR("invalid trans_stop\n");
- goto err;
- }
- if (speed_mode == 0) {
- timing = 0; /* ST mode */
- } else if (speed_mode == 1) {
- /* ext_flag |= I2C_FS_FLAG;//FS MODE */
- } else if (speed_mode == 2) {
- ext_flag |= I2C_HS_FLAG; /* HS mode */
- } else {
- I2CERR("invalid speed_mode\n");
- goto err;
- }
- if (pushpull_mode == 0) {
- /* default */
- } else if (pushpull_mode == 1) {
- ext_flag |= I2C_PUSHPULL_FLAG;
- } else {
- I2CERR("invalid pushpull mode\n");
- goto err;
- }
- if (query_mode == 0) {
- /* */
- } else if (query_mode == 1) {
- ext_flag |= I2C_POLLING_FLAG;
- } else {
- I2CERR("invalid query mode interrupt/polling\n");
- goto err;
- }
- if (trans_mode == 1) { /*DMA MODE */
- /*need GFP_DMA32 flag to confirm DMA alloc PA is 32bit range */
- vir_addr =
- dma_alloc_coherent(dev, length >> 1, &dma_addr,
- GFP_KERNEL | GFP_DMA32);
- if (vir_addr == NULL) {
- I2CERR("alloc dma memory failed\n");
- goto err;
- }
- } else {
- vir_addr = kzalloc(length >> 1, GFP_KERNEL);
- if (vir_addr == NULL) {
- I2CERR("alloc virtual memory failed\n");
- goto err;
- }
- }
- get_hexbuffer(data_buffer, vir_addr);
- I2CLOG("bus_id:%d,address:%x,count:%x,ext_flag:0x%x,timing:%d\n", bus_id,
- address, number, ext_flag, timing);
- I2CLOG("data_buffer:%s\n", data_buffer);
- if (trans_mode == 1) {
- #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
- pr_info("phys_addr: 0x%llx\n", dma_addr);
- #else
- pr_info("phys_addr: 0x%x\n", dma_addr);
- #endif
- ret =
- i2c_trans_data(bus_id, address, mt_i2c_bus_to_virt(dma_addr),
- number, ext_flag, timing, operation);
- } else {
- ret =
- i2c_trans_data(bus_id, address, vir_addr, number, ext_flag,
- timing, operation);
- }
- /* dealing */
- if (ret >= 0) {
- if (operation == 1) {
- hex2string(vir_addr, tmpbuffer, length >> 1);
- sprintf(data_buffer, "1 %s", tmpbuffer);
- I2CLOG("received data: %s\n", tmpbuffer);
- } else if (operation == 0) {
- hex2string(vir_addr, tmpbuffer, trans_auxlen);
- sprintf(data_buffer, "1 %s", tmpbuffer);
- I2CLOG("received data: %s\n", tmpbuffer);
- } else {
- sprintf(data_buffer, "1 %s", "00");
- }
- I2CLOG("Actual return Value:%d 0x%p\n", ret, vir_addr);
- } else if (ret < 0) {
- if (ret == -EINVAL)
- sprintf(data_buffer, "0 %s", "Invalid Parameter");
- else if (ret == -ETIMEDOUT)
- sprintf(data_buffer, "0 %s", "Transfer Timeout");
- else if (ret == -EREMOTEIO)
- sprintf(data_buffer, "0 %s", "Ack Error");
- else
- sprintf(data_buffer, "0 %s", "unknown error");
- I2CLOG("Actual return Value:%d 0x%p\n", ret, vir_addr);
- }
- if (trans_mode == 1 && vir_addr != NULL) { /*DMA MODE */
- dma_free_coherent(dev, length >> 1, vir_addr, dma_addr);
- } else {
- kfree(vir_addr);
- }
- /* log for UT test. */
- {
- struct i2c_adapter *adap = i2c_get_adapter(bus_id);
- struct mt_i2c_t *i2c = i2c_get_adapdata(adap);
- _i2c_dump_info(i2c);
- }
- } else {
- struct i2c_adapter *adap = i2c_get_adapter(bus_id);
- struct mt_i2c_t *i2c = i2c_get_adapdata(adap);
- if (operation == 3) {
- _i2c_dump_info(i2c);
- } else if (operation == 4) {
- i2c_test_reg(bus_id, 0);
- _i2c_dump_info(i2c);
- i2c_test_reg(bus_id, 0xFFFFFFFF);
- _i2c_dump_info(i2c);
- } else if (operation == 5) {
- i2c_ext_conf_test(bus_id, address);
- } else if (operation == 9) {
- i2c_soft_reset(bus_id);
- _i2c_dump_info(i2c);
- } else if (operation == 6) {
- if (bus_id == 0) {
- /* I2C0 PINMUX2 power on */
- /* hwPowerOn(MT65XX_POWER_LDO_VMC1,VOL_DEFAULT,"i2c_pinmux"); */
- /* hwPowerOn(MT65XX_POWER_LDO_VMCH1,VOL_DEFAULT,"i2c_pinmux"); */
- }
- } else if (operation == 7) {
- mt_i2c_test(1, 0x50);
- } else {
- dev_err(dev, "i2c debug system: Parameter invalid!\n");
- }
- _i2c_dump_info(i2c);
- }
- } else {
- /*parameter invalid */
- dev_err(dev, "i2c debug system: Parameter invalid!\n");
- }
- return count;
- err:
- I2CERR("analyze failed\n");
- return -1;
- }
- static DEVICE_ATTR(ut, 0660, show_config, set_config);
- static int i2c_common_probe(struct platform_device *pdev)
- {
- int ret = 0;
- /* your code here£¬your should save client in your own way */
- I2CLOG("i2c_common device probe\n");
- ret = device_create_file(&pdev->dev, &dev_attr_ut);
- return ret;
- }
- static int i2c_common_remove(struct platform_device *pdev)
- {
- int ret = 0;
- /* your code here */
- device_remove_file(&pdev->dev, &dev_attr_ut);
- return ret;
- }
- static struct platform_driver i2c_common_driver = {
- .driver = {
- .name = "mt-i2cd",
- .owner = THIS_MODULE,
- },
- .probe = i2c_common_probe,
- .remove = i2c_common_remove,
- };
- /* platform device */
- static struct platform_device i2c_common_device = {
- .name = "mt-i2cd",
- .dev = {
- .coherent_dma_mask = DMA_BIT_MASK(32),
- },
- };
- static int __init xxx_init(void)
- {
- I2CLOG("i2c_common device init\n");
- platform_device_register(&i2c_common_device);
- return platform_driver_register(&i2c_common_driver);
- }
- static void __exit xxx_exit(void)
- {
- platform_driver_unregister(&i2c_common_driver);
- platform_device_unregister(&i2c_common_device);
- }
- module_init(xxx_init);
- module_exit(xxx_exit);
- MODULE_LICENSE("GPL");
- MODULE_DESCRIPTION("MediaTek I2C Bus Driver Test Driver");
- MODULE_AUTHOR("Ranran Lu");
|