static int i2c_speed[] = {AML_I2C_SPEED_50K, AML_I2C_SPEED_100K,
AML_I2C_SPEED_200K, AML_I2C_SPEED_300K, AML_I2C_SPEED_400K};
+#define I2C_COUNTERVAIL 14
+static const int auto_test_speed[] = {AML_I2C_SPEED_50K, AML_I2C_SPEED_100K,
+ AML_I2C_SPEED_200K, AML_I2C_SPEED_300K, AML_I2C_SPEED_400K,
+ AML_I2C_SPEED_1000K, AML_I2C_SPEED_2000K, AML_I2C_SPEED_3000K,
+ AML_I2C_SPEED_3400K};
+
#define aml_i2c_dbg(i2c, fmt, args...) { if (i2c->i2c_debug) \
pr_info("[i2c@%d] " fmt, i2c->master_no, ## args); }
#define aml_i2c_dump(i2c) \
{
unsigned int i2c_clock_set;
unsigned int sys_clk_rate;
+ unsigned int i2c_standard_time;
/* struct clk *sys_clk; */
struct aml_i2c_reg_ctrl *ctrl;
/* sys_clk_rate = get_mpeg_clk(); */
i2c_clock_set = sys_clk_rate / speed;
+
+ /*i2c_standard_time: set for i2c T_high/T_low standard*/
+ if (speed >= 1000000)
+ i2c_standard_time = 5;
+ else
+ i2c_standard_time = 20;
if (get_meson_cpu_version(MESON_CPU_VERSION_LVL_MAJOR)
> MESON_CPU_MAJOR_ID_GXBB) {
i2c_clock_set >>= 1;
ctrl = (struct aml_i2c_reg_ctrl *)&(i2c->master_regs->i2c_ctrl);
if (i2c_clock_set > 0xfff)
i2c_clock_set = 0xfff;
- ctrl->clk_delay = i2c_clock_set & 0x3ff;
- ctrl->unused.b.clk_delay_ext = i2c_clock_set >> 10;
+
+ ctrl->clk_delay =
+ (i2c_clock_set - I2C_COUNTERVAIL - i2c_standard_time*2) & 0x3ff;
+ ctrl->clk_delay_ext =
+ (i2c_clock_set - I2C_COUNTERVAIL - i2c_standard_time*2) >> 10;
i2c->master_regs->i2c_slave_addr &= ~(0xfff<<16);
- i2c->master_regs->i2c_slave_addr |= (i2c_clock_set>>1)<<16;
+ i2c->master_regs->i2c_slave_addr |=
+ ((i2c_clock_set>>1) + i2c_standard_time)<<16;
i2c->master_regs->i2c_slave_addr |= 1<<28;
i2c->master_regs->i2c_slave_addr &= ~(0x3f<<8);
/* no filter on scl&sda */
} else{
i2c_clock_set >>= 2;
-
- ctrl = (struct aml_i2c_reg_ctrl *)&(i2c->master_regs->i2c_ctrl);
- ctrl->clk_delay = i2c_clock_set & AML_I2C_CTRL_CLK_DELAY_MASK;
-}
+ ctrl = (struct aml_i2c_reg_ctrl *)&(i2c->master_regs->i2c_ctrl);
+ ctrl->clk_delay = i2c_clock_set & AML_I2C_CTRL_CLK_DELAY_MASK;
+ }
}
static void aml_i2c_set_platform_data(struct aml_i2c *i2c,
i2c->master_regs->i2c_slave_addr |= i2c->cur_slave_addr<<1;
} else
i2c->master_regs->i2c_slave_addr = i2c->cur_slave_addr<<1;
+
return 0;
}
{
struct aml_i2c *i2c = i2c_get_adapdata(i2c_adap);
struct i2c_msg *p = NULL;
+ static int local_err_i2c = 1;
+ static int pre_err_i2c = 1;
unsigned int i;
unsigned int ret = 0, speed = 0;
gpiod_direction_output(i2c->i2c_gdesc, !i);
}
#endif
- dev_err(&i2c_adap->dev,
- "[aml_i2c_xfer] error ret = %d (%s)",
- ret, ret == -EIO ? "-EIO" : "-ETIMEOUT");
- dev_err(&i2c_adap->dev,
- "token %d, master_no(%d) %dK addr 0x%x\n",
- i2c->cur_token, i2c->master_no,
- i2c->master_i2c_speed/1000,
- i2c->cur_slave_addr);
- aml_i2c_dump(i2c);
+ local_err_i2c = i2c->cur_slave_addr;
+ if (pre_err_i2c != local_err_i2c) {
+ dev_err(&i2c_adap->dev,
+ "[aml_i2c_xfer] error ret = %d (%s)",
+ ret, ret == -EIO ? "-EIO" : "-ETIMEOUT");
+ dev_err(&i2c_adap->dev,
+ "token %d, master_no(%d) %dK addr 0x%x\n",
+ i2c->cur_token, i2c->master_no,
+ i2c->master_i2c_speed/1000,
+ i2c->cur_slave_addr);
+ aml_i2c_dump(i2c);
+ }
+ pre_err_i2c = local_err_i2c;
}
mutex_unlock(i2c->lock);
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);
+ if (i2c_transfer(&i2c->adap, &msgs, msg_num) != msg_num)
return -1;
- }
msleep(200);
msg_num = 0;
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);
+ pr_info("i2c auto test receive buff error!\n");
return -1;
}
}
- } else {
- pr_info("i2c auto test failed 2 at speed %d KHZ!\n",
- (i2c->master_i2c_speed)/1000);
+ } else
return -1;
- }
msleep(200);
/* fill up default date*/
return -1;
msleep(100);
- pr_info("I2C auto test master and slave ok! speed = %d KHZ!\n",
- (i2c->master_i2c_speed)/1000);
+ return 0;
+}
+
+static int aml_i2c_auto_test_loop(struct aml_i2c *i2c, unsigned int val)
+{
+ int i, ret;
+ int num = ARRAY_SIZE(auto_test_speed);
+
+ for (i = 0; i < num; i++) {
+ mutex_lock(i2c->lock);
+ i2c->master_i2c_speed = auto_test_speed[i];
+ mutex_unlock(i2c->lock);
+ ret = aml_i2c_auto_test(i2c, val);
+ if (ret < 0) {
+ pr_info("i2c auto test error at %d KHZ\n",
+ auto_test_speed[i]/1000);
+ return -1;
+ }
+ pr_info("i2c speed %d KHZ test ok!\n", auto_test_speed[i]/1000);
+ }
+ pr_info("I2C auto test master and slave ok!\n");
return 0;
}
}
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);
+ aml_i2c_auto_test_loop(i2c, val);
}
else if (!strcmp(attr->attr.name, "slave")) {
if (i2c->adap.nr)
sprintf((char *)i2c->cls.name, "i2c%d", i2c->adap.nr);
else
- sprintf((char *)i2c->cls.name, "i2c");
+ sprintf((char *)i2c->cls.name, "i2c0");
i2c->cls.class_attrs = i2c_class_attrs;
ret = class_register(&i2c->cls);
if (ret)