Skip to content

Commit 5332613

Browse files
claudiubezneaAndi Shyti
authored andcommitted
i2c: riic: Add suspend/resume support
Add suspend/resume support for the RIIC driver. This is necessary for the Renesas RZ/G3S SoC which support suspend to deep sleep state where power to most of the SoC components is turned off. As a result the I2C controller needs to be reconfigured after suspend/resume. For this, the reset line was stored in the driver private data structure as well as i2c timings. The reset line and I2C timings are necessary to re-initialize the controller after resume. Reviewed-by: Andi Shyti <[email protected]> Signed-off-by: Claudiu Beznea <[email protected]> Signed-off-by: Andi Shyti <[email protected]>
1 parent 10d5c88 commit 5332613

File tree

1 file changed

+62
-11
lines changed

1 file changed

+62
-11
lines changed

drivers/i2c/busses/i2c-riic.c

Lines changed: 62 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ struct riic_dev {
105105
struct completion msg_done;
106106
struct i2c_adapter adapter;
107107
struct clk *clk;
108+
struct reset_control *rstc;
109+
struct i2c_timings i2c_t;
108110
};
109111

110112
struct riic_irq_desc {
@@ -302,11 +304,12 @@ static const struct i2c_algorithm riic_algo = {
302304
.functionality = riic_func,
303305
};
304306

305-
static int riic_init_hw(struct riic_dev *riic, struct i2c_timings *t)
307+
static int riic_init_hw(struct riic_dev *riic)
306308
{
307309
int ret;
308310
unsigned long rate;
309311
int total_ticks, cks, brl, brh;
312+
struct i2c_timings *t = &riic->i2c_t;
310313
struct device *dev = riic->adapter.dev.parent;
311314

312315
if (t->bus_freq_hz > I2C_MAX_FAST_MODE_FREQ) {
@@ -423,8 +426,6 @@ static int riic_i2c_probe(struct platform_device *pdev)
423426
struct device *dev = &pdev->dev;
424427
struct riic_dev *riic;
425428
struct i2c_adapter *adap;
426-
struct i2c_timings i2c_t;
427-
struct reset_control *rstc;
428429
int i, ret;
429430

430431
riic = devm_kzalloc(dev, sizeof(*riic), GFP_KERNEL);
@@ -441,16 +442,16 @@ static int riic_i2c_probe(struct platform_device *pdev)
441442
return PTR_ERR(riic->clk);
442443
}
443444

444-
rstc = devm_reset_control_get_optional_exclusive(dev, NULL);
445-
if (IS_ERR(rstc))
446-
return dev_err_probe(dev, PTR_ERR(rstc),
445+
riic->rstc = devm_reset_control_get_optional_exclusive(dev, NULL);
446+
if (IS_ERR(riic->rstc))
447+
return dev_err_probe(dev, PTR_ERR(riic->rstc),
447448
"Error: missing reset ctrl\n");
448449

449-
ret = reset_control_deassert(rstc);
450+
ret = reset_control_deassert(riic->rstc);
450451
if (ret)
451452
return ret;
452453

453-
ret = devm_add_action_or_reset(dev, riic_reset_control_assert, rstc);
454+
ret = devm_add_action_or_reset(dev, riic_reset_control_assert, riic->rstc);
454455
if (ret)
455456
return ret;
456457

@@ -479,14 +480,14 @@ static int riic_i2c_probe(struct platform_device *pdev)
479480

480481
init_completion(&riic->msg_done);
481482

482-
i2c_parse_fw_timings(dev, &i2c_t, true);
483+
i2c_parse_fw_timings(dev, &riic->i2c_t, true);
483484

484485
/* Default 0 to save power. Can be overridden via sysfs for lower latency. */
485486
pm_runtime_set_autosuspend_delay(dev, 0);
486487
pm_runtime_use_autosuspend(dev);
487488
pm_runtime_enable(dev);
488489

489-
ret = riic_init_hw(riic, &i2c_t);
490+
ret = riic_init_hw(riic);
490491
if (ret)
491492
goto out;
492493

@@ -496,7 +497,7 @@ static int riic_i2c_probe(struct platform_device *pdev)
496497

497498
platform_set_drvdata(pdev, riic);
498499

499-
dev_info(dev, "registered with %dHz bus speed\n", i2c_t.bus_freq_hz);
500+
dev_info(dev, "registered with %dHz bus speed\n", riic->i2c_t.bus_freq_hz);
500501
return 0;
501502

502503
out:
@@ -553,6 +554,55 @@ static const struct riic_of_data riic_rz_v2h_info = {
553554
},
554555
};
555556

557+
static int riic_i2c_suspend(struct device *dev)
558+
{
559+
struct riic_dev *riic = dev_get_drvdata(dev);
560+
int ret;
561+
562+
ret = pm_runtime_resume_and_get(dev);
563+
if (ret)
564+
return ret;
565+
566+
i2c_mark_adapter_suspended(&riic->adapter);
567+
568+
/* Disable output on SDA, SCL pins. */
569+
riic_clear_set_bit(riic, ICCR1_ICE, 0, RIIC_ICCR1);
570+
571+
pm_runtime_mark_last_busy(dev);
572+
pm_runtime_put_sync(dev);
573+
574+
return reset_control_assert(riic->rstc);
575+
}
576+
577+
static int riic_i2c_resume(struct device *dev)
578+
{
579+
struct riic_dev *riic = dev_get_drvdata(dev);
580+
int ret;
581+
582+
ret = reset_control_deassert(riic->rstc);
583+
if (ret)
584+
return ret;
585+
586+
ret = riic_init_hw(riic);
587+
if (ret) {
588+
/*
589+
* In case this happens there is no way to recover from this
590+
* state. The driver will remain loaded. We want to avoid
591+
* keeping the reset line de-asserted for no reason.
592+
*/
593+
reset_control_assert(riic->rstc);
594+
return ret;
595+
}
596+
597+
i2c_mark_adapter_resumed(&riic->adapter);
598+
599+
return 0;
600+
}
601+
602+
static const struct dev_pm_ops riic_i2c_pm_ops = {
603+
SYSTEM_SLEEP_PM_OPS(riic_i2c_suspend, riic_i2c_resume)
604+
};
605+
556606
static const struct of_device_id riic_i2c_dt_ids[] = {
557607
{ .compatible = "renesas,riic-rz", .data = &riic_rz_a_info },
558608
{ .compatible = "renesas,riic-r9a09g057", .data = &riic_rz_v2h_info },
@@ -565,6 +615,7 @@ static struct platform_driver riic_i2c_driver = {
565615
.driver = {
566616
.name = "i2c-riic",
567617
.of_match_table = riic_i2c_dt_ids,
618+
.pm = pm_ptr(&riic_i2c_pm_ops),
568619
},
569620
};
570621

0 commit comments

Comments
 (0)