| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451 |
- #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 <linux/delay.h>
- #include "i2c-mtk.h"
- /* filer out error messages */
- static char data_buffer[256 * 4];
- static inline void i2c_writew_d(struct mt_i2c *i2c, u8 offset, u16 value)
- {
- writew(value, (void *)((i2c->base) + (offset)));
- }
- static inline u16 i2c_readw_d(struct mt_i2c *i2c, u8 offset)
- {
- return readw((void const *)((i2c->base) + (offset)));
- }
- int mt_i2c_test(int id, int addr)
- {
- int ret = 0;
- /* ret = i2c_trans_data(id, addr, buffer,,buffer, 1, 1, 0); */
- return ret;
- }
- EXPORT_SYMBOL(mt_i2c_test);
- int mt_i2c_test_wrrd(int id, int addr, int wr_len, int rd_len, char *wr_buf, char *rd_buf)
- {
- int ret;
- struct i2c_msg msg[2];
- struct i2c_adapter *adap;
- adap = i2c_get_adapter(id);
- if (!adap)
- return -1;
- msg[0].addr = addr;
- msg[0].flags = 0;
- msg[0].len = wr_len;
- msg[0].buf = wr_buf;
- /*for(i = 0; i < wr_len; i++)
- {
- printk("cxd wr_len = %d i2c_trans_data-%d = 0x%x\n",wr_len, i, wr_buf[i]);
- } */
- msg[1].addr = addr;
- msg[1].flags = I2C_M_RD;
- msg[1].len = rd_len;
- msg[1].buf = rd_buf;
- ret = i2c_transfer(adap, &msg[0], 2);
- /*printk("cxd i2c_trans_ret = %d\n", ret);
- for(ii = 0; ii<rd_len; ii++)
- {
- printk("cxd i2c_trans_data-%d = 0x%x\n", ii, rd_buf[ii]);
- } */
- return ret;
- }
- static ssize_t show_config(struct device *dev, struct device_attribute *attr, char *buff)
- {
- int len = strlen(data_buffer);
- memcpy(buff, data_buffer, len);
- pr_alert("Return Value:%s\n\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_wr, char *buf_rd, int operation, int len_wr,
- int len_rd)
- {
- int ret;
- struct i2c_msg msg;
- struct i2c_adapter *adap;
- adap = i2c_get_adapter(bus_id);
- if (!adap)
- return -1;
- msg.addr = address;
- if (operation == 2) {
- msg.flags = I2C_M_RD;
- msg.len = len_rd;
- msg.buf = (char *)buf_rd;
- } else {
- msg.flags = 0;
- msg.len = len_wr;
- msg.buf = (char *)buf_wr;
- }
- ret = i2c_transfer(adap, &msg, 1);
- /*if(ret > 0) {
- for(i = 0; i<msg.len; i++)
- {
- printk("cxd i2c_trans_data-%d = 0x%x\n", i, msg.buf[i]);
- }
- } */
- i2c_put_adapter(adap);
- return (ret == 1) ? msg.len : ret;
- }
- /* extern mt_i2c ; */
- static int i2c_test_reg(int bus_id, int val)
- {
- int ret = 0;
- struct i2c_adapter *adap;
- struct mt_i2c *i2c;
- adap = i2c_get_adapter(bus_id);
- if (!adap)
- return -1;
- i2c = container_of(adap, struct mt_i2c, adap);
- /* printk("I2C%d base address %8x\n", bus_id, (unsigned int)(i2c->base)); */
- /* write i2c writable register with 0 */
- i2c_writew_d(i2c, OFFSET_SLAVE_ADDR, val);
- i2c_writew_d(i2c, OFFSET_INTR_MASK, val);
- i2c_writew_d(i2c, OFFSET_INTR_STAT, val);
- i2c_writew_d(i2c, OFFSET_CONTROL, val);
- i2c_writew_d(i2c, OFFSET_TRANSFER_LEN, val);
- i2c_writew_d(i2c, OFFSET_TRANSAC_LEN, val);
- i2c_writew_d(i2c, OFFSET_DELAY_LEN, val);
- i2c_writew_d(i2c, OFFSET_TIMING, val);
- i2c_writew_d(i2c, OFFSET_EXT_CONF, val);
- i2c_writew_d(i2c, OFFSET_IO_CONFIG, val);
- i2c_writew_d(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 *i2c;
- adap = i2c_get_adapter(bus_id);
- if (!adap)
- return -1;
- i2c = container_of(adap, struct mt_i2c, adap);
- /* printk("I2C%d base address %8x\n", bus_id, (unsigned int)(i2c->base)); */
- /* write i2c writable register with 0 */
- i2c_writew_d(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 *i2c;
- adap = i2c_get_adapter(bus_id);
- if (!adap)
- return -1;
- i2c = container_of(adap, struct mt_i2c, adap);
- /* printk("I2C%d base address %8x\n", bus_id, (unsigned int)(i2c->base)); */
- /* write i2c writable register with 0 */
- i2c_writew_d(i2c, OFFSET_EXT_CONF, val);
- /* printk("EXT_CONF 0x%x", i2c_readw_d(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 wr_number = 0;
- int rd_number = 0;
- int length = 0;
- void *vir_addr_wr = NULL;
- void *vir_addr_rd = NULL;
- /* int status; */
- int ret = 0;
- int scanf_ret = 0;
- unsigned char tmpbuffer[128];
- pr_alert("%s\n", buf);
- scanf_ret = sscanf
- (buf, "%d %x %d %d %d %s", &bus_id, &address, &operation, &wr_number, &rd_number,
- data_buffer);
- if (scanf_ret) {
- pr_alert("bus_id:%d,address:%x,operation:0x%x\n",
- bus_id, address, operation);
- if ((address != 0) && (operation <= 2)) {
- length = strlen(data_buffer);
- if (operation == 1) {
- if ((length >> 1) != wr_number)
- pr_alert("Error length of data number = %d,length = %d\n",
- wr_number, length >> 1);
- vir_addr_wr = kzalloc(wr_number, GFP_KERNEL);
- if (vir_addr_wr == NULL) {
- pr_err("alloc virtual memory failed\n");
- goto err;
- }
- get_hexbuffer(data_buffer, vir_addr_wr);
- pr_alert("data_buffer:%s\n", data_buffer);
- }
- if (operation == 2) {
- vir_addr_rd = kzalloc(rd_number, GFP_KERNEL);
- if (vir_addr_rd == NULL) {
- pr_err("alloc virtual memory failed\n");
- goto err;
- }
- }
- if (operation == 0) {
- vir_addr_wr = kzalloc(wr_number, GFP_KERNEL);
- if (vir_addr_wr == NULL) {
- pr_err("alloc virtual memory failed\n");
- goto err;
- }
- vir_addr_rd = kzalloc(rd_number, GFP_KERNEL);
- if (vir_addr_rd == NULL) {
- pr_err("alloc virtual memory failed\n");
- goto err;
- }
- get_hexbuffer(data_buffer, vir_addr_wr);
- pr_alert("data_buffer:%s\n", data_buffer);
- }
- if (operation == 0) { /* 0:WRRD 1:WR 2:RD */
- ret =
- mt_i2c_test_wrrd(bus_id, address, wr_number, rd_number,
- vir_addr_wr, vir_addr_rd);
- } else {
- ret =
- i2c_trans_data(bus_id, address, vir_addr_wr, vir_addr_rd,
- operation, wr_number, rd_number);
- }
- /* dealing */
- if (ret >= 0) {
- if (operation == 2) {
- hex2string(vir_addr_rd, tmpbuffer, rd_number);
- sprintf(data_buffer, "1 %s", tmpbuffer);
- pr_alert("Actual return Value:%d %s\n", ret, data_buffer);
- } else if (operation == 0) {
- hex2string(vir_addr_rd, tmpbuffer, rd_number);
- sprintf(data_buffer, "1 %s", tmpbuffer);
- pr_alert("Actual return Value:%d %s\n", ret, data_buffer);
- } else {
- sprintf(data_buffer, "1 %s", "00");
- pr_alert("Actual return Value:%d %s\n", ret, data_buffer);
- }
- } 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");
- pr_alert("Actual return Value:%d %p\n", ret, data_buffer);
- }
- kfree(vir_addr_rd);
- kfree(vir_addr_wr);
- } else {
- struct i2c_adapter *adap = i2c_get_adapter(bus_id);
- struct mt_i2c *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");
- }
- }
- } else {
- /*parameter invalid */
- dev_err(dev, "i2c debug system: Parameter invalid!\n");
- }
- return count;
- err:
- pr_err("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 */
- pr_alert("i2c_common device probe\n");
- ret = device_create_file(&pdev->dev, &dev_attr_ut);
- pr_alert("i2c_common device probe ret = %d\n", ret);
- 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-iicd",
- .owner = THIS_MODULE,
- },
- .probe = i2c_common_probe,
- .remove = i2c_common_remove,
- };
- /* platform device */
- static struct platform_device i2c_common_device = {
- .name = "mt-iicd",
- };
- static int __init xxx_init(void)
- {
- pr_alert("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_platform_driver(i2c_common_driver); */
- MODULE_LICENSE("GPL");
- MODULE_DESCRIPTION("MediaTek I2C Bus Driver Test Driver");
- MODULE_AUTHOR("Ranran Lu");
|