From: Shubhrajyoti Datta <shubhrajyoti.datta@xxxxxxxxxx> Implement save restore for i2c module. Since we have only a couple of registers an unconditional restore is done. Acked-by: Michal Simek <michal.simek@xxxxxxxxxx> Signed-off-by: Shubhrajyoti Datta <shubhraj@xxxxxxxxxx> Signed-off-by: Michal Simek <michal.simek@xxxxxxxxxx> Signed-off-by: Shubhrajyoti Datta <shubhrajyoti.datta@xxxxxxxxxx> --- drivers/i2c/busses/i2c-cadence.c | 41 ++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c index 08427e9..8a2983e 100644 --- a/drivers/i2c/busses/i2c-cadence.c +++ b/drivers/i2c/busses/i2c-cadence.c @@ -138,6 +138,7 @@ * @clk: Pointer to struct clk * @clk_rate_change_nb: Notifier block for clock rate changes * @quirks: flag for broken hold bit usage in r1p10 + * @ctrl_reg: Cached value of the control register. */ struct cdns_i2c { struct device *dev; @@ -158,6 +159,7 @@ struct cdns_i2c { struct clk *clk; struct notifier_block clk_rate_change_nb; u32 quirks; + u32 ctrl_reg; }; struct cdns_platform_data { @@ -748,12 +750,11 @@ static int cdns_i2c_setclk(unsigned long clk_in, struct cdns_i2c *id) if (ret) return ret; - ctrl_reg = cdns_i2c_readreg(CDNS_I2C_CR_OFFSET); + ctrl_reg = id->ctrl_reg; ctrl_reg &= ~(CDNS_I2C_CR_DIVA_MASK | CDNS_I2C_CR_DIVB_MASK); ctrl_reg |= ((div_a << CDNS_I2C_CR_DIVA_SHIFT) | (div_b << CDNS_I2C_CR_DIVB_SHIFT)); - cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET); - + id->ctrl_reg = ctrl_reg; return 0; } @@ -837,6 +838,26 @@ static int __maybe_unused cdns_i2c_runtime_suspend(struct device *dev) } /** + * cdns_i2c_init - Controller initialisation + * @id: Device private data structure + * + * Initialise the i2c controller. + * + */ +static void cdns_i2c_init(struct cdns_i2c *id) +{ + cdns_i2c_writereg(id->ctrl_reg, CDNS_I2C_CR_OFFSET); + /* + * Cadence I2C controller has a bug wherein it generates + * invalid read transaction after HW timeout in master receiver mode. + * HW timeout is not used by this driver and the interrupt is disabled. + * But the feature itself cannot be disabled. Hence maximum value + * is written to this register to reduce the chances of error. + */ + cdns_i2c_writereg(CDNS_I2C_TIMEOUT_MAX, CDNS_I2C_TIME_OUT_OFFSET); +} + +/** * cdns_i2c_runtime_resume - Runtime resume * @dev: Address of the platform_device structure * @@ -854,6 +875,7 @@ static int __maybe_unused cdns_i2c_runtime_resume(struct device *dev) dev_err(dev, "Cannot enable clock.\n"); return ret; } + cdns_i2c_init(xi2c); return 0; } @@ -947,8 +969,7 @@ static int cdns_i2c_probe(struct platform_device *pdev) if (ret || (id->i2c_clk > CDNS_I2C_SPEED_MAX)) id->i2c_clk = CDNS_I2C_SPEED_DEFAULT; - cdns_i2c_writereg(CDNS_I2C_CR_ACK_EN | CDNS_I2C_CR_NEA | CDNS_I2C_CR_MS, - CDNS_I2C_CR_OFFSET); + id->ctrl_reg = CDNS_I2C_CR_ACK_EN | CDNS_I2C_CR_NEA | CDNS_I2C_CR_MS; ret = cdns_i2c_setclk(id->input_clk, id); if (ret) { @@ -963,15 +984,7 @@ static int cdns_i2c_probe(struct platform_device *pdev) dev_err(&pdev->dev, "cannot get irq %d\n", id->irq); goto err_clk_dis; } - - /* - * Cadence I2C controller has a bug wherein it generates - * invalid read transaction after HW timeout in master receiver mode. - * HW timeout is not used by this driver and the interrupt is disabled. - * But the feature itself cannot be disabled. Hence maximum value - * is written to this register to reduce the chances of error. - */ - cdns_i2c_writereg(CDNS_I2C_TIMEOUT_MAX, CDNS_I2C_TIME_OUT_OFFSET); + cdns_i2c_init(id); ret = i2c_add_adapter(&id->adap); if (ret < 0) -- 2.1.1