Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

i2c: uniphier-f: add suspend / resume support

When resuming, set up registers that have been lost in the sleep state.
Also, add clock handling in the resume / suspend hooks.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>

authored by

Masahiro Yamada and committed by
Wolfram Sang
822c8d45 9f9d6a40

+37 -9
+37 -9
drivers/i2c/busses/i2c-uniphier-f.c
··· 97 97 int error; 98 98 unsigned int flags; 99 99 unsigned int busy_cnt; 100 + unsigned int clk_cycle; 100 101 }; 101 102 102 103 static void uniphier_fi2c_fill_txfifo(struct uniphier_fi2c_priv *priv, ··· 462 461 .unprepare_recovery = uniphier_fi2c_unprepare_recovery, 463 462 }; 464 463 465 - static void uniphier_fi2c_hw_init(struct uniphier_fi2c_priv *priv, 466 - u32 bus_speed, unsigned long clk_rate) 464 + static void uniphier_fi2c_hw_init(struct uniphier_fi2c_priv *priv) 467 465 { 466 + unsigned int cyc = priv->clk_cycle; 468 467 u32 tmp; 469 468 470 469 tmp = readl(priv->membase + UNIPHIER_FI2C_CR); ··· 473 472 474 473 uniphier_fi2c_reset(priv); 475 474 476 - tmp = clk_rate / bus_speed; 477 - 478 - writel(tmp, priv->membase + UNIPHIER_FI2C_CYC); 479 - writel(tmp / 2, priv->membase + UNIPHIER_FI2C_LCTL); 480 - writel(tmp / 2, priv->membase + UNIPHIER_FI2C_SSUT); 481 - writel(tmp / 16, priv->membase + UNIPHIER_FI2C_DSUT); 475 + writel(cyc, priv->membase + UNIPHIER_FI2C_CYC); 476 + writel(cyc / 2, priv->membase + UNIPHIER_FI2C_LCTL); 477 + writel(cyc / 2, priv->membase + UNIPHIER_FI2C_SSUT); 478 + writel(cyc / 16, priv->membase + UNIPHIER_FI2C_DSUT); 482 479 483 480 uniphier_fi2c_prepare_operation(priv); 484 481 } ··· 530 531 goto disable_clk; 531 532 } 532 533 534 + priv->clk_cycle = clk_rate / bus_speed; 533 535 init_completion(&priv->comp); 534 536 priv->adap.owner = THIS_MODULE; 535 537 priv->adap.algo = &uniphier_fi2c_algo; ··· 541 541 i2c_set_adapdata(&priv->adap, priv); 542 542 platform_set_drvdata(pdev, priv); 543 543 544 - uniphier_fi2c_hw_init(priv, bus_speed, clk_rate); 544 + uniphier_fi2c_hw_init(priv); 545 545 546 546 ret = devm_request_irq(dev, irq, uniphier_fi2c_interrupt, 0, 547 547 pdev->name, priv); ··· 568 568 return 0; 569 569 } 570 570 571 + static int __maybe_unused uniphier_fi2c_suspend(struct device *dev) 572 + { 573 + struct uniphier_fi2c_priv *priv = dev_get_drvdata(dev); 574 + 575 + clk_disable_unprepare(priv->clk); 576 + 577 + return 0; 578 + } 579 + 580 + static int __maybe_unused uniphier_fi2c_resume(struct device *dev) 581 + { 582 + struct uniphier_fi2c_priv *priv = dev_get_drvdata(dev); 583 + int ret; 584 + 585 + ret = clk_prepare_enable(priv->clk); 586 + if (ret) 587 + return ret; 588 + 589 + uniphier_fi2c_hw_init(priv); 590 + 591 + return 0; 592 + } 593 + 594 + static const struct dev_pm_ops uniphier_fi2c_pm_ops = { 595 + SET_SYSTEM_SLEEP_PM_OPS(uniphier_fi2c_suspend, uniphier_fi2c_resume) 596 + }; 597 + 571 598 static const struct of_device_id uniphier_fi2c_match[] = { 572 599 { .compatible = "socionext,uniphier-fi2c" }, 573 600 { /* sentinel */ } ··· 607 580 .driver = { 608 581 .name = "uniphier-fi2c", 609 582 .of_match_table = uniphier_fi2c_match, 583 + .pm = &uniphier_fi2c_pm_ops, 610 584 }, 611 585 }; 612 586 module_platform_driver(uniphier_fi2c_drv);