Loading drivers/i2c/busses/i2c-msm-v2.c +53 −17 Original line number Diff line number Diff line /* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -50,6 +50,8 @@ static int i2c_msm_xfer_wait_for_completion(struct i2c_msm_ctrl *ctrl, static int i2c_msm_pm_resume(struct device *dev); static void i2c_msm_pm_suspend(struct device *dev); static void i2c_msm_clk_path_init(struct i2c_msm_ctrl *ctrl); static void i2c_msm_pm_pinctrl_state(struct i2c_msm_ctrl *ctrl, bool runtime_active); /* string table for enum i2c_msm_xfer_mode_id */ const char * const i2c_msm_mode_str_tbl[] = { Loading Loading @@ -2157,27 +2159,54 @@ static bool i2c_msm_xfer_next_buf(struct i2c_msm_ctrl *ctrl) return true; } static void i2c_msm_pm_clk_disable_unprepare(struct i2c_msm_ctrl *ctrl) static void i2c_msm_pm_clk_unprepare(struct i2c_msm_ctrl *ctrl) { clk_disable_unprepare(ctrl->rsrcs.core_clk); clk_disable_unprepare(ctrl->rsrcs.iface_clk); clk_unprepare(ctrl->rsrcs.core_clk); clk_unprepare(ctrl->rsrcs.iface_clk); } static int i2c_msm_pm_clk_prepare_enable(struct i2c_msm_ctrl *ctrl) static int i2c_msm_pm_clk_prepare(struct i2c_msm_ctrl *ctrl) { int ret; ret = clk_prepare_enable(ctrl->rsrcs.iface_clk); ret = clk_prepare(ctrl->rsrcs.iface_clk); if (ret) { dev_err(ctrl->dev, "error on clk_prepare(iface_clk):%d\n", ret); return ret; } ret = clk_prepare(ctrl->rsrcs.core_clk); if (ret) { clk_unprepare(ctrl->rsrcs.iface_clk); dev_err(ctrl->dev, "error on clk_prepare_enable(iface_clk):%d\n", ret); "error clk_prepare(core_clk):%d\n", ret); } return ret; } ret = clk_prepare_enable(ctrl->rsrcs.core_clk); static void i2c_msm_pm_clk_disable(struct i2c_msm_ctrl *ctrl) { clk_disable(ctrl->rsrcs.core_clk); clk_disable(ctrl->rsrcs.iface_clk); } static int i2c_msm_pm_clk_enable(struct i2c_msm_ctrl *ctrl) { int ret; ret = clk_enable(ctrl->rsrcs.iface_clk); if (ret) { dev_err(ctrl->dev, "error on clk_enable(iface_clk):%d\n", ret); i2c_msm_pm_clk_unprepare(ctrl); return ret; } ret = clk_enable(ctrl->rsrcs.core_clk); if (ret) { clk_disable_unprepare(ctrl->rsrcs.iface_clk); clk_disable(ctrl->rsrcs.iface_clk); i2c_msm_pm_clk_unprepare(ctrl); dev_err(ctrl->dev, "error clk_prepare_enable(core_clk):%d\n", ret); "error clk_enable(core_clk):%d\n", ret); } return ret; } Loading @@ -2198,6 +2227,7 @@ static int i2c_msm_pm_xfer_start(struct i2c_msm_ctrl *ctrl) return -EIO; } i2c_msm_pm_pinctrl_state(ctrl, true); pm_runtime_get_sync(ctrl->dev); /* * if runtime PM callback was not invoked (when both runtime-pm Loading @@ -2208,7 +2238,7 @@ static int i2c_msm_pm_xfer_start(struct i2c_msm_ctrl *ctrl) i2c_msm_pm_resume(ctrl->dev); } ret = i2c_msm_pm_clk_prepare_enable(ctrl); ret = i2c_msm_pm_clk_enable(ctrl); if (ret) { mutex_unlock(&ctrl->xfer.mtx); return ret; Loading @@ -2235,13 +2265,14 @@ static void i2c_msm_pm_xfer_end(struct i2c_msm_ctrl *ctrl) if (ctrl->xfer.mode_id == I2C_MSM_XFER_MODE_DMA) i2c_msm_dma_free_channels(ctrl); i2c_msm_pm_clk_disable_unprepare(ctrl); i2c_msm_pm_clk_disable(ctrl); if (!pm_runtime_enabled(ctrl->dev)) i2c_msm_pm_suspend(ctrl->dev); pm_runtime_mark_last_busy(ctrl->dev); pm_runtime_put_autosuspend(ctrl->dev); i2c_msm_pm_pinctrl_state(ctrl, false); mutex_unlock(&ctrl->xfer.mtx); } Loading Loading @@ -2663,7 +2694,7 @@ static void i2c_msm_pm_suspend(struct device *dev) return; } i2c_msm_dbg(ctrl, MSM_DBG, "suspending..."); i2c_msm_pm_pinctrl_state(ctrl, false); i2c_msm_pm_clk_unprepare(ctrl); i2c_msm_clk_path_unvote(ctrl); /* Loading @@ -2690,7 +2721,7 @@ static int i2c_msm_pm_resume(struct device *dev) i2c_msm_dbg(ctrl, MSM_DBG, "resuming..."); i2c_msm_clk_path_vote(ctrl); i2c_msm_pm_pinctrl_state(ctrl, true); i2c_msm_pm_clk_prepare(ctrl); ctrl->pwr_state = I2C_MSM_PM_RT_ACTIVE; return 0; } Loading Loading @@ -2870,9 +2901,13 @@ static int i2c_msm_probe(struct platform_device *pdev) /* vote for clock to enable reading the version number off the HW */ i2c_msm_clk_path_vote(ctrl); ret = i2c_msm_pm_clk_prepare_enable(ctrl); ret = i2c_msm_pm_clk_prepare(ctrl); if (ret) goto clk_err; ret = i2c_msm_pm_clk_enable(ctrl); if (ret) { dev_err(ctrl->dev, "error in enabling clocks:%d\n", ret); i2c_msm_pm_clk_unprepare(ctrl); goto clk_err; } Loading @@ -2884,7 +2919,8 @@ static int i2c_msm_probe(struct platform_device *pdev) if (ret) dev_err(ctrl->dev, "error error on qup software reset\n"); i2c_msm_pm_clk_disable_unprepare(ctrl); i2c_msm_pm_clk_disable(ctrl); i2c_msm_pm_clk_unprepare(ctrl); i2c_msm_clk_path_unvote(ctrl); ret = i2c_msm_rsrcs_gpio_pinctrl_init(ctrl); Loading Loading
drivers/i2c/busses/i2c-msm-v2.c +53 −17 Original line number Diff line number Diff line /* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -50,6 +50,8 @@ static int i2c_msm_xfer_wait_for_completion(struct i2c_msm_ctrl *ctrl, static int i2c_msm_pm_resume(struct device *dev); static void i2c_msm_pm_suspend(struct device *dev); static void i2c_msm_clk_path_init(struct i2c_msm_ctrl *ctrl); static void i2c_msm_pm_pinctrl_state(struct i2c_msm_ctrl *ctrl, bool runtime_active); /* string table for enum i2c_msm_xfer_mode_id */ const char * const i2c_msm_mode_str_tbl[] = { Loading Loading @@ -2157,27 +2159,54 @@ static bool i2c_msm_xfer_next_buf(struct i2c_msm_ctrl *ctrl) return true; } static void i2c_msm_pm_clk_disable_unprepare(struct i2c_msm_ctrl *ctrl) static void i2c_msm_pm_clk_unprepare(struct i2c_msm_ctrl *ctrl) { clk_disable_unprepare(ctrl->rsrcs.core_clk); clk_disable_unprepare(ctrl->rsrcs.iface_clk); clk_unprepare(ctrl->rsrcs.core_clk); clk_unprepare(ctrl->rsrcs.iface_clk); } static int i2c_msm_pm_clk_prepare_enable(struct i2c_msm_ctrl *ctrl) static int i2c_msm_pm_clk_prepare(struct i2c_msm_ctrl *ctrl) { int ret; ret = clk_prepare_enable(ctrl->rsrcs.iface_clk); ret = clk_prepare(ctrl->rsrcs.iface_clk); if (ret) { dev_err(ctrl->dev, "error on clk_prepare(iface_clk):%d\n", ret); return ret; } ret = clk_prepare(ctrl->rsrcs.core_clk); if (ret) { clk_unprepare(ctrl->rsrcs.iface_clk); dev_err(ctrl->dev, "error on clk_prepare_enable(iface_clk):%d\n", ret); "error clk_prepare(core_clk):%d\n", ret); } return ret; } ret = clk_prepare_enable(ctrl->rsrcs.core_clk); static void i2c_msm_pm_clk_disable(struct i2c_msm_ctrl *ctrl) { clk_disable(ctrl->rsrcs.core_clk); clk_disable(ctrl->rsrcs.iface_clk); } static int i2c_msm_pm_clk_enable(struct i2c_msm_ctrl *ctrl) { int ret; ret = clk_enable(ctrl->rsrcs.iface_clk); if (ret) { dev_err(ctrl->dev, "error on clk_enable(iface_clk):%d\n", ret); i2c_msm_pm_clk_unprepare(ctrl); return ret; } ret = clk_enable(ctrl->rsrcs.core_clk); if (ret) { clk_disable_unprepare(ctrl->rsrcs.iface_clk); clk_disable(ctrl->rsrcs.iface_clk); i2c_msm_pm_clk_unprepare(ctrl); dev_err(ctrl->dev, "error clk_prepare_enable(core_clk):%d\n", ret); "error clk_enable(core_clk):%d\n", ret); } return ret; } Loading @@ -2198,6 +2227,7 @@ static int i2c_msm_pm_xfer_start(struct i2c_msm_ctrl *ctrl) return -EIO; } i2c_msm_pm_pinctrl_state(ctrl, true); pm_runtime_get_sync(ctrl->dev); /* * if runtime PM callback was not invoked (when both runtime-pm Loading @@ -2208,7 +2238,7 @@ static int i2c_msm_pm_xfer_start(struct i2c_msm_ctrl *ctrl) i2c_msm_pm_resume(ctrl->dev); } ret = i2c_msm_pm_clk_prepare_enable(ctrl); ret = i2c_msm_pm_clk_enable(ctrl); if (ret) { mutex_unlock(&ctrl->xfer.mtx); return ret; Loading @@ -2235,13 +2265,14 @@ static void i2c_msm_pm_xfer_end(struct i2c_msm_ctrl *ctrl) if (ctrl->xfer.mode_id == I2C_MSM_XFER_MODE_DMA) i2c_msm_dma_free_channels(ctrl); i2c_msm_pm_clk_disable_unprepare(ctrl); i2c_msm_pm_clk_disable(ctrl); if (!pm_runtime_enabled(ctrl->dev)) i2c_msm_pm_suspend(ctrl->dev); pm_runtime_mark_last_busy(ctrl->dev); pm_runtime_put_autosuspend(ctrl->dev); i2c_msm_pm_pinctrl_state(ctrl, false); mutex_unlock(&ctrl->xfer.mtx); } Loading Loading @@ -2663,7 +2694,7 @@ static void i2c_msm_pm_suspend(struct device *dev) return; } i2c_msm_dbg(ctrl, MSM_DBG, "suspending..."); i2c_msm_pm_pinctrl_state(ctrl, false); i2c_msm_pm_clk_unprepare(ctrl); i2c_msm_clk_path_unvote(ctrl); /* Loading @@ -2690,7 +2721,7 @@ static int i2c_msm_pm_resume(struct device *dev) i2c_msm_dbg(ctrl, MSM_DBG, "resuming..."); i2c_msm_clk_path_vote(ctrl); i2c_msm_pm_pinctrl_state(ctrl, true); i2c_msm_pm_clk_prepare(ctrl); ctrl->pwr_state = I2C_MSM_PM_RT_ACTIVE; return 0; } Loading Loading @@ -2870,9 +2901,13 @@ static int i2c_msm_probe(struct platform_device *pdev) /* vote for clock to enable reading the version number off the HW */ i2c_msm_clk_path_vote(ctrl); ret = i2c_msm_pm_clk_prepare_enable(ctrl); ret = i2c_msm_pm_clk_prepare(ctrl); if (ret) goto clk_err; ret = i2c_msm_pm_clk_enable(ctrl); if (ret) { dev_err(ctrl->dev, "error in enabling clocks:%d\n", ret); i2c_msm_pm_clk_unprepare(ctrl); goto clk_err; } Loading @@ -2884,7 +2919,8 @@ static int i2c_msm_probe(struct platform_device *pdev) if (ret) dev_err(ctrl->dev, "error error on qup software reset\n"); i2c_msm_pm_clk_disable_unprepare(ctrl); i2c_msm_pm_clk_disable(ctrl); i2c_msm_pm_clk_unprepare(ctrl); i2c_msm_clk_path_unvote(ctrl); ret = i2c_msm_rsrcs_gpio_pinctrl_init(ctrl); Loading