From: Eunki Kim Date: Wed, 22 Jan 2014 03:22:56 +0000 (+0900) Subject: i2c: s3c2410: hw init after LPA X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=8114b69965d5f647a4d40237bebf8e2090d31f9a;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git i2c: s3c2410: hw init after LPA Signed-off-by: Eunki Kim Conflicts: drivers/i2c/busses/i2c-s3c2410.c Change-Id: Ie61c476af4a56e94611051434453bcfc34df89be --- diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 2fa1b44617f8..1d6cc844c8c5 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -39,6 +39,10 @@ #include +#include + +static LIST_HEAD(drvdata_list); + /* see s3c2410x user guide, v1.1, section 9 (p447) for more info */ #define S3C2410_IICCON 0x00 @@ -102,8 +106,10 @@ enum s3c24xx_i2c_state { }; struct s3c24xx_i2c { + struct list_head node; wait_queue_head_t wait; kernel_ulong_t quirks; + unsigned int need_hw_init; unsigned int suspended:1; struct i2c_msg *msg; @@ -819,6 +825,7 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, * first port of call from the i2c bus code when an message needs * transferring across the i2c bus. */ +static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c); static int s3c24xx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) @@ -826,20 +833,14 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap, struct s3c24xx_i2c *i2c = (struct s3c24xx_i2c *)adap->algo_data; int retry; int ret; - unsigned int freq; pm_runtime_get_sync(&adap->dev); ret = clk_enable(i2c->clk); if (ret) return ret; - if (i2c->quirks & QUIRK_FIMC_I2C) { - ret = s3c24xx_i2c_clockrate(i2c, &freq); - if (ret < 0) { - dev_err(i2c->dev, "cannot find frequency\n"); - return ret; - } - } + if (i2c->need_hw_init) + s3c24xx_i2c_init(i2c); for (retry = 0; retry < adap->retries; retry++) { @@ -1129,6 +1130,7 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) dev_dbg(i2c->dev, "S3C2410_IICCON=0x%02x\n", readl(i2c->regs + S3C2410_IICCON)); + i2c->need_hw_init = 0; return 0; } @@ -1160,6 +1162,27 @@ s3c24xx_i2c_parse_dt(struct device_node *np, struct s3c24xx_i2c *i2c) } #endif +#ifdef CONFIG_CPU_IDLE +static int s3c24xx_i2c_notifier(struct notifier_block *self, + unsigned long cmd, void *v) +{ + struct s3c24xx_i2c *i2c; + + switch (cmd) { + case LPA_EXIT: + list_for_each_entry(i2c, &drvdata_list, node) + i2c->need_hw_init = 1; + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block s3c24xx_i2c_notifier_block = { + .notifier_call = s3c24xx_i2c_notifier, +}; +#endif /*CONFIG_CPU_IDLE */ + /* s3c24xx_i2c_probe * * called by the bus driver when a suitable device is found @@ -1247,17 +1270,8 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) return -EINVAL; } - /* initialise the i2c controller */ + i2c->need_hw_init = 1; - if (!(i2c->quirks & QUIRK_FIMC_I2C)) { - clk_prepare_enable(i2c->clk); - ret = s3c24xx_i2c_init(i2c); - clk_disable_unprepare(i2c->clk); - if (ret != 0) { - dev_err(&pdev->dev, "I2C controller init failed\n"); - return ret; - } - } /* find the IRQ for this unit (note, this relies on the init call to * ensure no current IRQs pending */ @@ -1303,6 +1317,8 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) pm_runtime_enable(&i2c->adap.dev); + list_add_tail(&i2c->node, &drvdata_list); + dev_info(&pdev->dev, "%s: S3C I2C adapter\n", dev_name(&i2c->adap.dev)); return 0; } @@ -1345,11 +1361,7 @@ static int s3c24xx_i2c_resume_noirq(struct device *dev) int ret; i2c->suspended = 0; - if (!(i2c->quirks & QUIRK_FIMC_I2C)) { - clk_prepare_enable(i2c->clk); - s3c24xx_i2c_init(i2c); - clk_disable_unprepare(i2c->clk); - } + i2c->need_hw_init = 1; return 0; } @@ -1361,11 +1373,8 @@ static int s3c24xx_i2c_runtime_resume(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev); - if (i2c->quirks & QUIRK_FIMC_I2C) { - clk_prepare_enable(i2c->clk); - s3c24xx_i2c_init(i2c); - clk_disable_unprepare(i2c->clk); - } + if (i2c->quirks & QUIRK_FIMC_I2C) + i2c->need_hw_init = 1; return 0; } @@ -1406,6 +1415,9 @@ static struct platform_driver s3c24xx_i2c_driver = { static int __init i2c_adap_s3c_init(void) { +#ifdef CONFIG_CPU_IDLE + exynos_pm_register_notifier(&s3c24xx_i2c_notifier_block); +#endif return platform_driver_register(&s3c24xx_i2c_driver); } subsys_initcall(i2c_adap_s3c_init);