diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-designware-platdrv.c')
-rw-r--r-- | drivers/i2c/busses/i2c-designware-platdrv.c | 104 |
1 files changed, 52 insertions, 52 deletions
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index 9e094478b9b3..a2ae2213ef3e 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -209,17 +209,16 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST; dev->clk = devm_clk_get(&pdev->dev, NULL); - if (!IS_ERR(dev->clk)) { - r = clk_prepare_enable(dev->clk); - if (r) - return r; + dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz; + if (IS_ERR(dev->clk)) + return PTR_ERR(dev->clk); + clk_prepare_enable(dev->clk); - dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz; + if (!dev->sda_hold_time && ht) { + u32 ic_clk = dev->get_clk_rate_khz(dev); - if (!dev->sda_hold_time && ht) - dev->sda_hold_time = div_u64( - (u64)dev->get_clk_rate_khz(dev) * ht + 500000, - 1000000); + dev->sda_hold_time = div_u64((u64)ic_clk * ht + 500000, + 1000000); } if (!dev->tx_fifo_depth) { @@ -236,26 +235,18 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) ACPI_COMPANION_SET(&adap->dev, ACPI_COMPANION(&pdev->dev)); adap->dev.of_node = pdev->dev.of_node; - pm_runtime_get_noresume(&pdev->dev); - pm_runtime_set_autosuspend_delay(&pdev->dev, 1000); - pm_runtime_use_autosuspend(&pdev->dev); - pm_runtime_set_active(&pdev->dev); - pm_runtime_enable(&pdev->dev); - - if (dev->pm_runtime_disabled) - pm_runtime_get_noresume(&pdev->dev); + if (dev->pm_runtime_disabled) { + pm_runtime_forbid(&pdev->dev); + } else { + pm_runtime_set_autosuspend_delay(&pdev->dev, 1000); + pm_runtime_use_autosuspend(&pdev->dev); + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + } r = i2c_dw_probe(dev); - if (r) { - if (!IS_ERR(dev->clk)) - clk_disable_unprepare(dev->clk); + if (r && !dev->pm_runtime_disabled) pm_runtime_disable(&pdev->dev); - pm_runtime_dont_use_autosuspend(&pdev->dev); - if (dev->pm_runtime_disabled) - pm_runtime_put_noidle(&pdev->dev); - } - pm_runtime_mark_last_busy(&pdev->dev); - pm_runtime_put(&pdev->dev); return r; } @@ -270,16 +261,10 @@ static int dw_i2c_plat_remove(struct platform_device *pdev) i2c_dw_disable(dev); - if (!IS_ERR(dev->clk)) - clk_disable_unprepare(dev->clk); - - pm_runtime_disable(&pdev->dev); pm_runtime_dont_use_autosuspend(&pdev->dev); - if (dev->pm_runtime_disabled) - pm_runtime_put_noidle(&pdev->dev); - - pm_runtime_put_noidle(&pdev->dev); - pm_runtime_set_suspended(&pdev->dev); + pm_runtime_put_sync(&pdev->dev); + if (!dev->pm_runtime_disabled) + pm_runtime_disable(&pdev->dev); return 0; } @@ -292,47 +277,62 @@ static const struct of_device_id dw_i2c_of_match[] = { MODULE_DEVICE_TABLE(of, dw_i2c_of_match); #endif -#ifdef CONFIG_PM -static int i2c_dw_plat_prepare_clk(struct dw_i2c_dev *i_dev, bool prepare) +#ifdef CONFIG_PM_SLEEP +static int dw_i2c_plat_prepare(struct device *dev) { - if (IS_ERR(i_dev->clk)) - return PTR_ERR(i_dev->clk); - - if (prepare) - return clk_prepare_enable(i_dev->clk); + return pm_runtime_suspended(dev); +} - clk_disable_unprepare(i_dev->clk); - return 0; +static void dw_i2c_plat_complete(struct device *dev) +{ + if (dev->power.direct_complete) + pm_request_resume(dev); } +#else +#define dw_i2c_plat_prepare NULL +#define dw_i2c_plat_complete NULL +#endif +#ifdef CONFIG_PM static int dw_i2c_plat_runtime_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev); i2c_dw_disable(i_dev); - i2c_dw_plat_prepare_clk(i_dev, false); + clk_disable_unprepare(i_dev->clk); return 0; } -static int dw_i2c_plat_runtime_resume(struct device *dev) +static int dw_i2c_plat_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev); - i2c_dw_plat_prepare_clk(i_dev, true); - i2c_dw_init(i_dev); + clk_prepare_enable(i_dev->clk); + + if (!i_dev->pm_runtime_disabled) + i2c_dw_init(i_dev); return 0; } +#ifdef CONFIG_PM_SLEEP +static int dw_i2c_plat_suspend(struct device *dev) +{ + pm_runtime_resume(dev); + return dw_i2c_plat_runtime_suspend(dev); +} +#endif + static const struct dev_pm_ops dw_i2c_dev_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + .prepare = dw_i2c_plat_prepare, + .complete = dw_i2c_plat_complete, + SET_SYSTEM_SLEEP_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume) SET_RUNTIME_PM_OPS(dw_i2c_plat_runtime_suspend, - dw_i2c_plat_runtime_resume, - NULL) + dw_i2c_plat_resume, + NULL) }; #define DW_I2C_DEV_PMOPS (&dw_i2c_dev_pm_ops) |