From 3fd64633be01b85ce07bf0322f0a4dd764b6f048 Mon Sep 17 00:00:00 2001 From: Xuhua Zhang Date: Sat, 17 Jun 2017 19:38:28 +0800 Subject: [PATCH] i2c: add auto test i2c master and slave on axg skt. PD#142470: add i2c auto test on axg. 1. if uboot parm(i2c_auto_test) is "open", open the i2c auto test function. 2. before the test,we should connect i2c slave and master. Change-Id: Ia37e080dc7995d31e46c9122b389be1ed21acc63 Signed-off-by: Xuhua Zhang --- arch/arm64/boot/dts/amlogic/mesonaxg.dtsi | 17 ++++++ arch/arm64/configs/meson64_defconfig | 1 + drivers/amlogic/i2c/aml_master.c | 95 +++++++++++++++++++++++++++++++ drivers/amlogic/i2c/aml_slave.c | 39 +++++++++---- 4 files changed, 142 insertions(+), 10 deletions(-) diff --git a/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi b/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi index c72e8bc..a0f7a94 100644 --- a/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi +++ b/arch/arm64/boot/dts/amlogic/mesonaxg.dtsi @@ -652,6 +652,15 @@ clock-names = "clk_i2c"; }; + i2c_slave:i2c_slave@ff806000{ + compatible = "amlogic, meson-i2c-slave"; + status = "disabled"; + reg = <0x0 0xff806000 0x0 0x20>; + interrupts = <0 194 1>; + pinctrl-names="default"; + pinctrl-0=<&i2c_slave_pin>; + }; + aml_aes { compatible = "amlogic,aes_dma"; dev_name = "aml_aes_dma"; @@ -721,6 +730,14 @@ function = "i2c_ao"; }; }; + + i2c_slave_pin:s_i2c{ + mux { + pins = "GPIOAO_10","GPIOAO_11"; + function = "i2c_slave_ao"; + }; + }; + }; /* end of pinctrl_aobus */ &pinctrl_periphs { diff --git a/arch/arm64/configs/meson64_defconfig b/arch/arm64/configs/meson64_defconfig index 7daed21..fa40b38 100644 --- a/arch/arm64/configs/meson64_defconfig +++ b/arch/arm64/configs/meson64_defconfig @@ -204,6 +204,7 @@ CONFIG_AMLOGIC_USBPHY=y CONFIG_AMLOGIC_USB2PHY=y CONFIG_AMLOGIC_USB3PHY=y CONFIG_AMLOGIC_I2C=y +CONFIG_AMLOGIC_I2C_SLAVE=y CONFIG_AMLOGIC_I2C_MASTER=y CONFIG_AMLOGIC_SPICC_MASTER=y CONFIG_AMLOGIC_SEC=y diff --git a/drivers/amlogic/i2c/aml_master.c b/drivers/amlogic/i2c/aml_master.c index 53dfb0f..4e0b2a7 100644 --- a/drivers/amlogic/i2c/aml_master.c +++ b/drivers/amlogic/i2c/aml_master.c @@ -747,6 +747,92 @@ err_arg: return -1; } +static int aml_i2c_auto_test(struct aml_i2c *i2c, unsigned int val) +{ + struct i2c_msg msgs, *msgp = &msgs; + struct i2c_msg msgx[2], *msgz = &msgx[0]; + int msg_num = 0; + unsigned int addr = 0, wnum = 0, rnum = 0; + char wbuf1[5] = {0, 0xaa, 0x55, 0x88, 0x99}; + char wbufdef[5] = {0, 0xff, 0xff, 0xff, 0xff}; + char rbuf[4] = {0}; + char wbuf2 = 0; + int i; + + if ((val) && (val <= 0x7f)) + addr = val; + else + addr = 0x20; + + wnum = 5; + if (wnum) { + msgp->flags = !I2C_M_RD; + msgp->addr = addr; + msgp->len = wnum; + msgp->buf = wbuf1; + msg_num++; + } + + if (i2c_transfer(&i2c->adap, &msgs, msg_num) != msg_num) { + pr_info("i2c auto test failed at speed %d KHZ!\n", + (i2c->master_i2c_speed)/1000); + return -1; + } + + msleep(200); + msg_num = 0; + wnum = 1; + rnum = 4; + if (wnum) { + msgz->flags = !I2C_M_RD; + msgz->addr = addr; + msgz->len = wnum; + msgz->buf = &wbuf2; + msg_num++; + msgz++; + } + if (rnum) { + msgz->flags = I2C_M_RD; + msgz->addr = addr; + msgz->len = rnum; + msgz->buf = rbuf; + msg_num++; + msgz++; + } + + if (i2c_transfer(&i2c->adap, &msgx[0], msg_num) == msg_num) { + for (i = 0; i < rnum; i++) { + if (wbuf1[i+1] != rbuf[i]) { + pr_info("i2c auto test failed 1 at speed %d KHZ!\n", + (i2c->master_i2c_speed)/1000); + return -1; + } + } + } else { + pr_info("i2c auto test failed 2 at speed %d KHZ!\n", + (i2c->master_i2c_speed)/1000); + return -1; + } + + msleep(200); + /* fill up default date*/ + wnum = 5; + if (wnum) { + msgp->flags = !I2C_M_RD; + msgp->addr = addr; + msgp->len = wnum; + msgp->buf = wbufdef; + msg_num++; + } + if (i2c_transfer(&i2c->adap, &msgs, msg_num) != msg_num) + return -1; + + msleep(100); + pr_info("I2C auto test master and slave ok! speed = %d KHZ!\n", + (i2c->master_i2c_speed)/1000); + return 0; +} + #ifdef ENABLE_GPIO_TRIGGER static int aml_i2c_set_trig_gpio(struct aml_i2c *i2c, char *gpio_name) { @@ -850,6 +936,14 @@ static ssize_t store_aml_i2c(struct class *class, "enable" : "disable"); } + else if (!strcmp(attr->attr.name, "auto_test")) { + mutex_lock(i2c->lock); + i2c->master_i2c_speed = val; + mutex_unlock(i2c->lock); + //pr_info("set speed: %d\n", i2c->master_i2c_speed); + aml_i2c_auto_test(i2c, val2); + } + else if (!strcmp(attr->attr.name, "slave")) { aml_i2c_test_slave(i2c, argn, argv); } @@ -867,6 +961,7 @@ static struct class_attribute i2c_class_attrs[] = { __ATTR(mode, 0644, show_aml_i2c, store_aml_i2c), __ATTR(debug, 0644, show_aml_i2c, store_aml_i2c), __ATTR(slave, 0644, show_aml_i2c, store_aml_i2c), + __ATTR(auto_test, 0644, show_aml_i2c, store_aml_i2c), #ifdef ENABLE_GPIO_TRIGGER __ATTR(trig_gpio, 0644, show_aml_i2c, store_aml_i2c), #endif diff --git a/drivers/amlogic/i2c/aml_slave.c b/drivers/amlogic/i2c/aml_slave.c index 636cdc0..a19b091 100644 --- a/drivers/amlogic/i2c/aml_slave.c +++ b/drivers/amlogic/i2c/aml_slave.c @@ -22,6 +22,10 @@ #include #include +/*uboot i2c_auto_test: open/disable*/ +static char i2c_auto_test_mode[10] = "disable"; +static char i2c_auto_test_flag; + void i2c_slave_dts_parse(struct platform_device *pdev, struct aml_i2c_slave *slave) { @@ -45,7 +49,7 @@ struct aml_i2c_slave *slave) slave->slave_regs->s_reg_ctrl |= (1<<28);/*send en*/ slave->slave_regs->s_reg_ctrl |= (1<<27);/*recv en*/ slave->slave_regs->s_reg_ctrl |= (0x40<<16); /*slave addr*/ - slave->slave_regs->s_reg_ctrl |= (0x27<<8); /*hold time*/ + slave->slave_regs->s_reg_ctrl |= (0x0<<8); /*hold time*/ slave->slave_regs->s_reg_ctrl |= (0x6); /*sampling rate*/ } @@ -88,7 +92,8 @@ struct class_attribute *attr, const char *buf, size_t count) if (!strcmp(attr->attr.name, "addr")) { mutex_lock(i2c->lock); - i2c->slave_regs->s_reg_ctrl |= ((val&0xff)<<16); + i2c->slave_regs->s_reg_ctrl &= ~(0xff<<16); + i2c->slave_regs->s_reg_ctrl |= (val&0xff)<<16; mutex_unlock(i2c->lock); } else if (!strcmp(attr->attr.name, "control_reg")) { mutex_lock(i2c->lock); @@ -116,8 +121,12 @@ struct aml_i2c_slave_reg_ctrl *slave_ctrl) rev_data = (slave->slave_regs->s_rev_reg); - pr_info("data:0x%8x\n", rev_data); + pr_info("slave receive data:0x%8x\n", rev_data); + if (i2c_auto_test_flag) { + if (rev_data == 0x998855aa) + slave->slave_regs->s_send_reg = rev_data&0xffffffff; + } slave->slave_regs->s_reg_ctrl |= (1<<27); return 0; @@ -149,13 +158,12 @@ static irqreturn_t i2c_slave_xfer_isr(int irq, void *dev_id) slave = (struct aml_i2c_slave *)dev_id; slave_ctrl = (struct aml_i2c_slave_reg_ctrl *)& (slave->slave_regs->s_reg_ctrl); - if (((slave->slave_regs->s_reg_ctrl>>27)&(0x1)) == 0x0) if (!i2c_slave_read_data(slave, slave_ctrl)) return IRQ_HANDLED; if (((slave->slave_regs->s_reg_ctrl>>28)&(0x1)) == 0x0) - pr_info("send:\n"); + pr_info("\n"); #ifdef CONFIG_I2C_SLAVE_TIMER slave->timer.data = (unsigned long)slave; mod_timer(&slave->timer, jiffies + @@ -170,6 +178,10 @@ static int i2c_slave_probe(struct platform_device *pdev) int ret; struct aml_i2c_slave *slave; + i2c_auto_test_flag = 0; + if (!strcmp(i2c_auto_test_mode, "open")) + i2c_auto_test_flag = 1; + slave = kzalloc(sizeof(struct aml_i2c_slave), GFP_KERNEL); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -200,7 +212,7 @@ static int i2c_slave_probe(struct platform_device *pdev) slave->cls.name = kzalloc(8, GFP_KERNEL); - sprintf((char *)slave->cls.name, "aml_slave"); + sprintf((char *)slave->cls.name, "i2c_slave"); slave->cls.class_attrs = slave_class_attrs; @@ -216,6 +228,16 @@ static int i2c_slave_probe(struct platform_device *pdev) return 0; } + +static int __init i2c_auto_test_setup(char *s) +{ + if (s != NULL) + sprintf(i2c_auto_test_mode, "%s", s); + + return 0; +} +__setup("i2c_auto_test=", i2c_auto_test_setup); + static int i2c_slave_remove(struct platform_device *pdev) { struct aml_i2c_slave *slave; @@ -252,18 +274,15 @@ static int i2c_slave_resume(struct device *dev) enable_irq(slave->irq); mutex_unlock(slave->lock); pr_info("%s: enable #%d irq\n", __func__, slave->irq); - return 0; } - #ifdef CONFIG_OF static const struct of_device_id i2c_slave_matches[] = { { .compatible = "amlogic, meson-i2c-slave", }, {}, }; - #endif static const struct dev_pm_ops i2c_slave_pm_ops = { .suspend_noirq = i2c_slave_suspend, @@ -272,7 +291,7 @@ static const struct dev_pm_ops i2c_slave_pm_ops = { static struct platform_driver i2c_slave_driver = { .driver = { - .name = "aml-i2c-slave", + .name = "aml_i2c_slave", .owner = THIS_MODULE, .of_match_table = of_match_ptr(i2c_slave_matches), .pm = &i2c_slave_pm_ops, -- 2.7.4