Skip to content

Commit 0cbc9a2

Browse files
larsclausenwsakernel
authored andcommitted
i2c: cadence: Add reset controller support
The Cadence I2C controller has an external reset signal that needs to be de-asserted before the I2C controller can be used. Add support to the driver to be able to take the peripheral out of reset using the reset controller API. The reset is optional in the driver for compatibility to systems where the reset managed by the bootloader. Signed-off-by: Lars-Peter Clausen <[email protected]> Acked-by: Michal Simek <[email protected]> Signed-off-by: Wolfram Sang <[email protected]>
1 parent 8455460 commit 0cbc9a2

File tree

1 file changed

+22
-4
lines changed

1 file changed

+22
-4
lines changed

drivers/i2c/busses/i2c-cadence.c

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <linux/of.h>
1717
#include <linux/pm_runtime.h>
1818
#include <linux/pinctrl/consumer.h>
19+
#include <linux/reset.h>
1920

2021
/* Register offsets for the I2C device. */
2122
#define CDNS_I2C_CR_OFFSET 0x00 /* Control Register, RW */
@@ -178,6 +179,7 @@ enum cdns_i2c_slave_state {
178179
* @bus_hold_flag: Flag used in repeated start for clearing HOLD bit
179180
* @clk: Pointer to struct clk
180181
* @clk_rate_change_nb: Notifier block for clock rate changes
182+
* @reset: Reset control for the device
181183
* @quirks: flag for broken hold bit usage in r1p10
182184
* @ctrl_reg: Cached value of the control register.
183185
* @ctrl_reg_diva_divb: value of fields DIV_A and DIV_B from CR register
@@ -204,6 +206,7 @@ struct cdns_i2c {
204206
unsigned int bus_hold_flag;
205207
struct clk *clk;
206208
struct notifier_block clk_rate_change_nb;
209+
struct reset_control *reset;
207210
u32 quirks;
208211
u32 ctrl_reg;
209212
struct i2c_bus_recovery_info rinfo;
@@ -1325,10 +1328,22 @@ static int cdns_i2c_probe(struct platform_device *pdev)
13251328
return dev_err_probe(&pdev->dev, PTR_ERR(id->clk),
13261329
"input clock not found.\n");
13271330

1331+
id->reset = devm_reset_control_get_optional_shared(&pdev->dev, NULL);
1332+
if (IS_ERR(id->reset))
1333+
return dev_err_probe(&pdev->dev, PTR_ERR(id->reset),
1334+
"Failed to request reset.\n");
1335+
13281336
ret = clk_prepare_enable(id->clk);
13291337
if (ret)
13301338
dev_err(&pdev->dev, "Unable to enable clock.\n");
13311339

1340+
ret = reset_control_deassert(id->reset);
1341+
if (ret) {
1342+
dev_err_probe(&pdev->dev, ret,
1343+
"Failed to de-assert reset.\n");
1344+
goto err_clk_dis;
1345+
}
1346+
13321347
pm_runtime_set_autosuspend_delay(id->dev, CNDS_I2C_PM_TIMEOUT);
13331348
pm_runtime_use_autosuspend(id->dev);
13341349
pm_runtime_set_active(id->dev);
@@ -1360,28 +1375,30 @@ static int cdns_i2c_probe(struct platform_device *pdev)
13601375
if (ret) {
13611376
dev_err(&pdev->dev, "invalid SCL clock: %u Hz\n", id->i2c_clk);
13621377
ret = -EINVAL;
1363-
goto err_clk_dis;
1378+
goto err_clk_notifier_unregister;
13641379
}
13651380

13661381
ret = devm_request_irq(&pdev->dev, irq, cdns_i2c_isr, 0,
13671382
DRIVER_NAME, id);
13681383
if (ret) {
13691384
dev_err(&pdev->dev, "cannot get irq %d\n", irq);
1370-
goto err_clk_dis;
1385+
goto err_clk_notifier_unregister;
13711386
}
13721387
cdns_i2c_init(id);
13731388

13741389
ret = i2c_add_adapter(&id->adap);
13751390
if (ret < 0)
1376-
goto err_clk_dis;
1391+
goto err_clk_notifier_unregister;
13771392

13781393
dev_info(&pdev->dev, "%u kHz mmio %08lx irq %d\n",
13791394
id->i2c_clk / 1000, (unsigned long)r_mem->start, irq);
13801395

13811396
return 0;
13821397

1383-
err_clk_dis:
1398+
err_clk_notifier_unregister:
13841399
clk_notifier_unregister(id->clk, &id->clk_rate_change_nb);
1400+
reset_control_assert(id->reset);
1401+
err_clk_dis:
13851402
clk_disable_unprepare(id->clk);
13861403
pm_runtime_disable(&pdev->dev);
13871404
pm_runtime_set_suspended(&pdev->dev);
@@ -1406,6 +1423,7 @@ static int cdns_i2c_remove(struct platform_device *pdev)
14061423

14071424
i2c_del_adapter(&id->adap);
14081425
clk_notifier_unregister(id->clk, &id->clk_rate_change_nb);
1426+
reset_control_assert(id->reset);
14091427
clk_disable_unprepare(id->clk);
14101428

14111429
return 0;

0 commit comments

Comments
 (0)