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 <xuhua.zhang@amlogic.com>
This commit is contained in:
Xuhua Zhang
2017-06-17 19:38:28 +08:00
committed by Jianxin Pan
parent c924fd661a
commit 3fd64633be
4 changed files with 142 additions and 10 deletions

View File

@@ -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 {

View File

@@ -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

View File

@@ -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

View File

@@ -22,6 +22,10 @@
#include <linux/interrupt.h>
#include <linux/amlogic/iomap.h>
/*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,