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 a2ae2213ef3e..9e094478b9b3 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -209,16 +209,17 @@ 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); - 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); + if (!IS_ERR(dev->clk)) { + r = clk_prepare_enable(dev->clk); + if (r) + return r; - if (!dev->sda_hold_time && ht) { - u32 ic_clk = dev->get_clk_rate_khz(dev); + dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz; - dev->sda_hold_time = div_u64((u64)ic_clk * ht + 500000, - 1000000); + if (!dev->sda_hold_time && ht) + dev->sda_hold_time = div_u64( + (u64)dev->get_clk_rate_khz(dev) * ht + 500000, + 1000000); } if (!dev->tx_fifo_depth) { @@ -235,18 +236,26 @@ 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; - 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); - } + 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); r = i2c_dw_probe(dev); - if (r && !dev->pm_runtime_disabled) + if (r) { + 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_mark_last_busy(&pdev->dev); + pm_runtime_put(&pdev->dev); return r; } @@ -261,10 +270,16 @@ 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); - pm_runtime_put_sync(&pdev->dev); - if (!dev->pm_runtime_disabled) - pm_runtime_disable(&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); return 0; } @@ -277,62 +292,47 @@ static const struct of_device_id dw_i2c_of_match[] = { MODULE_DEVICE_TABLE(of, dw_i2c_of_match); #endif -#ifdef CONFIG_PM_SLEEP -static int dw_i2c_plat_prepare(struct device *dev) +#ifdef CONFIG_PM +static int i2c_dw_plat_prepare_clk(struct dw_i2c_dev *i_dev, bool prepare) { - return pm_runtime_suspended(dev); -} + if (IS_ERR(i_dev->clk)) + return PTR_ERR(i_dev->clk); -static void dw_i2c_plat_complete(struct device *dev) -{ - if (dev->power.direct_complete) - pm_request_resume(dev); + if (prepare) + return clk_prepare_enable(i_dev->clk); + + clk_disable_unprepare(i_dev->clk); + return 0; } -#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); - clk_disable_unprepare(i_dev->clk); + i2c_dw_plat_prepare_clk(i_dev, false); return 0; } -static int dw_i2c_plat_resume(struct device *dev) +static int dw_i2c_plat_runtime_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev); - clk_prepare_enable(i_dev->clk); - - if (!i_dev->pm_runtime_disabled) - i2c_dw_init(i_dev); + i2c_dw_plat_prepare_clk(i_dev, true); + 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 = { - .prepare = dw_i2c_plat_prepare, - .complete = dw_i2c_plat_complete, - SET_SYSTEM_SLEEP_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) SET_RUNTIME_PM_OPS(dw_i2c_plat_runtime_suspend, - dw_i2c_plat_resume, - NULL) + dw_i2c_plat_runtime_resume, + NULL) }; #define DW_I2C_DEV_PMOPS (&dw_i2c_dev_pm_ops) |