mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 19:30:30 +09:00
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:
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user