--- zzzz-none-000/linux-3.10.107/drivers/i2c/busses/i2c-sirf.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/i2c/busses/i2c-sirf.c 2021-02-04 17:41:59.000000000 +0000 @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -65,6 +64,8 @@ #define SIRFSOC_I2C_START BIT(7) #define SIRFSOC_I2C_DEFAULT_SPEED 100000 +#define SIRFSOC_I2C_ERR_NOACK 1 +#define SIRFSOC_I2C_ERR_TIMEOUT 2 struct sirfsoc_i2c { void __iomem *base; @@ -143,14 +144,24 @@ if (i2c_stat & SIRFSOC_I2C_STAT_ERR) { /* Error conditions */ - siic->err_status = 1; + siic->err_status = SIRFSOC_I2C_ERR_NOACK; writel(SIRFSOC_I2C_STAT_ERR, siic->base + SIRFSOC_I2C_STATUS); if (i2c_stat & SIRFSOC_I2C_STAT_NACK) - dev_err(&siic->adapter.dev, "ACK not received\n"); + dev_dbg(&siic->adapter.dev, "ACK not received\n"); else dev_err(&siic->adapter.dev, "I2C error\n"); + /* + * Due to hardware ANOMALY, we need to reset I2C earlier after + * we get NOACK while accessing non-existing clients, otherwise + * we will get errors even we access existing clients later + */ + writel(readl(siic->base + SIRFSOC_I2C_CTRL) | SIRFSOC_I2C_RESET, + siic->base + SIRFSOC_I2C_CTRL); + while (readl(siic->base + SIRFSOC_I2C_CTRL) & SIRFSOC_I2C_RESET) + cpu_relax(); + complete(&siic->done); } else if (i2c_stat & SIRFSOC_I2C_STAT_CMD_DONE) { /* CMD buffer execution complete */ @@ -183,6 +194,10 @@ if (msg->flags & I2C_M_RD) addr |= 1; + /* Reverse direction bit */ + if (msg->flags & I2C_M_REV_DIR_ADDR) + addr ^= 1; + writel(addr, siic->base + SIRFSOC_I2C_CMD(siic->cmd_ptr++)); } @@ -191,7 +206,6 @@ u32 regval = readl(siic->base + SIRFSOC_I2C_CTRL); /* timeout waiting for the xfer to finish or fail */ int timeout = msecs_to_jiffies((msg->len + 1) * 50); - int ret = 0; i2c_sirfsoc_set_address(siic, msg); @@ -200,7 +214,7 @@ i2c_sirfsoc_queue_cmd(siic); if (wait_for_completion_timeout(&siic->done, timeout) == 0) { - siic->err_status = 1; + siic->err_status = SIRFSOC_I2C_ERR_TIMEOUT; dev_err(&siic->adapter.dev, "Transfer timeout\n"); } @@ -208,16 +222,14 @@ siic->base + SIRFSOC_I2C_CTRL); writel(0, siic->base + SIRFSOC_I2C_CMD_START); - if (siic->err_status) { + /* i2c control doesn't response, reset it */ + if (siic->err_status == SIRFSOC_I2C_ERR_TIMEOUT) { writel(readl(siic->base + SIRFSOC_I2C_CTRL) | SIRFSOC_I2C_RESET, siic->base + SIRFSOC_I2C_CTRL); while (readl(siic->base + SIRFSOC_I2C_CTRL) & SIRFSOC_I2C_RESET) cpu_relax(); - - ret = -EIO; } - - return ret; + return siic->err_status ? -EAGAIN : 0; } static u32 i2c_sirfsoc_func(struct i2c_adapter *adap) @@ -295,12 +307,11 @@ siic = devm_kzalloc(&pdev->dev, sizeof(*siic), GFP_KERNEL); if (!siic) { - dev_err(&pdev->dev, "Can't allocate driver data\n"); err = -ENOMEM; goto out; } adap = &siic->adapter; - adap->class = I2C_CLASS_HWMON; + adap->class = I2C_CLASS_DEPRECATED; mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); siic->base = devm_ioremap_resource(&pdev->dev, mem_res); @@ -321,6 +332,7 @@ adap->algo = &i2c_sirfsoc_algo; adap->algo_data = siic; + adap->retries = 3; adap->dev.of_node = pdev->dev.of_node; adap->dev.parent = &pdev->dev; @@ -346,11 +358,29 @@ if (err < 0) bitrate = SIRFSOC_I2C_DEFAULT_SPEED; - if (bitrate < 100000) - regval = - (2 * ctrl_speed) / (2 * bitrate * 11); - else + /* + * Due to some hardware design issues, we need to tune the formula. + * Since i2c is open drain interface that allows the slave to + * stall the transaction by holding the SCL line at '0', the RTL + * implementation is waiting for SCL feedback from the pin after + * setting it to High-Z ('1'). This wait adds to the high-time + * interval counter few cycles of the input synchronization + * (depending on the SCL_FILTER_REG field), and also the time it + * takes for the board pull-up resistor to rise the SCL line. + * For slow SCL settings these additions are negligible, + * but they start to affect the speed when clock is set to faster + * frequencies. + * Through the actual tests, use the different user_div value(which + * in the divider formular 'Fio / (Fi2c * user_div)') to adapt + * the different ranges of i2c bus clock frequency, to make the SCL + * more accurate. + */ + if (bitrate <= 30000) regval = ctrl_speed / (bitrate * 5); + else if (bitrate > 30000 && bitrate <= 280000) + regval = (2 * ctrl_speed) / (bitrate * 11); + else + regval = ctrl_speed / (bitrate * 6); writel(regval, siic->base + SIRFSOC_I2C_CLK_CTRL); if (regval > 0xFF) @@ -366,8 +396,6 @@ clk_disable(clk); - of_i2c_register_devices(adap); - dev_info(&pdev->dev, " I2C adapter ready to operate\n"); return 0; @@ -416,6 +444,8 @@ clk_enable(siic->clk); writel(SIRFSOC_I2C_RESET, siic->base + SIRFSOC_I2C_CTRL); + while (readl(siic->base + SIRFSOC_I2C_CTRL) & SIRFSOC_I2C_RESET) + cpu_relax(); writel(SIRFSOC_I2C_CORE_EN | SIRFSOC_I2C_MASTER_MODE, siic->base + SIRFSOC_I2C_CTRL); writel(siic->clk_div, siic->base + SIRFSOC_I2C_CLK_CTRL); @@ -439,7 +469,6 @@ static struct platform_driver i2c_sirfsoc_driver = { .driver = { .name = "sirfsoc_i2c", - .owner = THIS_MODULE, #ifdef CONFIG_PM .pm = &i2c_sirfsoc_pm_ops, #endif