diff options
Diffstat (limited to 'drivers/clk/qcom/clk-smd-rpm.c')
-rw-r--r-- | drivers/clk/qcom/clk-smd-rpm.c | 58 |
1 files changed, 34 insertions, 24 deletions
diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index 887b945a6fb7..e4de74b68797 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -67,7 +67,7 @@ type, r_id, key) #define __DEFINE_CLK_SMD_RPM_BRANCH_PREFIX(_prefix, _name, _active,\ - type, r_id, r, key) \ + type, r_id, r, key, ao_flags) \ static struct clk_smd_rpm clk_smd_rpm_##_prefix##_active; \ static struct clk_smd_rpm clk_smd_rpm_##_prefix##_name = { \ .rpm_res_type = (type), \ @@ -102,12 +102,13 @@ .name = "xo_board", \ }, \ .num_parents = 1, \ + .flags = (ao_flags), \ }, \ } #define __DEFINE_CLK_SMD_RPM_BRANCH(_name, _active, type, r_id, r, key) \ __DEFINE_CLK_SMD_RPM_BRANCH_PREFIX(/* empty */, \ - _name, _active, type, r_id, r, key) + _name, _active, type, r_id, r, key, 0) #define DEFINE_CLK_SMD_RPM(_name, type, r_id) \ __DEFINE_CLK_SMD_RPM(_name##_clk, _name##_a_clk, \ @@ -126,12 +127,12 @@ #define DEFINE_CLK_SMD_RPM_BRANCH(_name, type, r_id, r) \ __DEFINE_CLK_SMD_RPM_BRANCH_PREFIX(branch_, \ _name##_clk, _name##_a_clk, \ - type, r_id, r, QCOM_RPM_SMD_KEY_ENABLE) + type, r_id, r, QCOM_RPM_SMD_KEY_ENABLE, 0) -#define DEFINE_CLK_SMD_RPM_BRANCH_A(_name, type, r_id, r) \ +#define DEFINE_CLK_SMD_RPM_BRANCH_A(_name, type, r_id, r, ao_flags) \ __DEFINE_CLK_SMD_RPM_BRANCH_PREFIX(branch_, \ _name, _name##_a, type, \ - r_id, r, QCOM_RPM_SMD_KEY_ENABLE) + r_id, r, QCOM_RPM_SMD_KEY_ENABLE, ao_flags) #define DEFINE_CLK_SMD_RPM_QDSS(_name, type, r_id) \ __DEFINE_CLK_SMD_RPM(_name##_clk, _name##_a_clk, \ @@ -146,7 +147,7 @@ __DEFINE_CLK_SMD_RPM_BRANCH_PREFIX(_prefix, \ _name, _name##_a, \ QCOM_SMD_RPM_CLK_BUF_A, r_id, r, \ - QCOM_RPM_KEY_SOFTWARE_ENABLE) + QCOM_RPM_KEY_SOFTWARE_ENABLE, 0) #define DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(_name, r_id, r) \ DEFINE_CLK_SMD_RPM_XO_BUFFER(_name, r_id, r); \ @@ -156,6 +157,8 @@ #define to_clk_smd_rpm(_hw) container_of(_hw, struct clk_smd_rpm, hw) +static struct qcom_smd_rpm *rpmcc_smd_rpm; + struct clk_smd_rpm { const int rpm_res_type; const int rpm_key; @@ -166,7 +169,6 @@ struct clk_smd_rpm { struct clk_smd_rpm *peer; struct clk_hw hw; unsigned long rate; - struct qcom_smd_rpm *rpm; }; struct clk_smd_rpm_req { @@ -178,6 +180,7 @@ struct clk_smd_rpm_req { struct rpm_smd_clk_desc { struct clk_smd_rpm **clks; size_t num_clks; + bool scaling_before_handover; }; static DEFINE_MUTEX(rpm_smd_clk_lock); @@ -191,12 +194,12 @@ static int clk_smd_rpm_handoff(struct clk_smd_rpm *r) .value = cpu_to_le32(r->branch ? 1 : INT_MAX), }; - ret = qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_ACTIVE_STATE, + ret = qcom_rpm_smd_write(rpmcc_smd_rpm, QCOM_SMD_RPM_ACTIVE_STATE, r->rpm_res_type, r->rpm_clk_id, &req, sizeof(req)); if (ret) return ret; - ret = qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_SLEEP_STATE, + ret = qcom_rpm_smd_write(rpmcc_smd_rpm, QCOM_SMD_RPM_SLEEP_STATE, r->rpm_res_type, r->rpm_clk_id, &req, sizeof(req)); if (ret) @@ -214,7 +217,7 @@ static int clk_smd_rpm_set_rate_active(struct clk_smd_rpm *r, .value = cpu_to_le32(DIV_ROUND_UP(rate, 1000)), /* to kHz */ }; - return qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_ACTIVE_STATE, + return qcom_rpm_smd_write(rpmcc_smd_rpm, QCOM_SMD_RPM_ACTIVE_STATE, r->rpm_res_type, r->rpm_clk_id, &req, sizeof(req)); } @@ -228,7 +231,7 @@ static int clk_smd_rpm_set_rate_sleep(struct clk_smd_rpm *r, .value = cpu_to_le32(DIV_ROUND_UP(rate, 1000)), /* to kHz */ }; - return qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_SLEEP_STATE, + return qcom_rpm_smd_write(rpmcc_smd_rpm, QCOM_SMD_RPM_SLEEP_STATE, r->rpm_res_type, r->rpm_clk_id, &req, sizeof(req)); } @@ -395,7 +398,7 @@ static unsigned long clk_smd_rpm_recalc_rate(struct clk_hw *hw, return r->rate; } -static int clk_smd_rpm_enable_scaling(struct qcom_smd_rpm *rpm) +static int clk_smd_rpm_enable_scaling(void) { int ret; struct clk_smd_rpm_req req = { @@ -404,7 +407,7 @@ static int clk_smd_rpm_enable_scaling(struct qcom_smd_rpm *rpm) .value = cpu_to_le32(1), }; - ret = qcom_rpm_smd_write(rpm, QCOM_SMD_RPM_SLEEP_STATE, + ret = qcom_rpm_smd_write(rpmcc_smd_rpm, QCOM_SMD_RPM_SLEEP_STATE, QCOM_SMD_RPM_MISC_CLK, QCOM_RPM_SCALING_ENABLE_ID, &req, sizeof(req)); if (ret) { @@ -412,7 +415,7 @@ static int clk_smd_rpm_enable_scaling(struct qcom_smd_rpm *rpm) return ret; } - ret = qcom_rpm_smd_write(rpm, QCOM_SMD_RPM_ACTIVE_STATE, + ret = qcom_rpm_smd_write(rpmcc_smd_rpm, QCOM_SMD_RPM_ACTIVE_STATE, QCOM_SMD_RPM_MISC_CLK, QCOM_RPM_SCALING_ENABLE_ID, &req, sizeof(req)); if (ret) { @@ -438,10 +441,11 @@ static const struct clk_ops clk_smd_rpm_branch_ops = { .recalc_rate = clk_smd_rpm_recalc_rate, }; -DEFINE_CLK_SMD_RPM_BRANCH_A(bi_tcxo, QCOM_SMD_RPM_MISC_CLK, 0, 19200000); +/* Disabling BI_TCXO_AO could gate the root clock source of the entire system. */ +DEFINE_CLK_SMD_RPM_BRANCH_A(bi_tcxo, QCOM_SMD_RPM_MISC_CLK, 0, 19200000, CLK_IS_CRITICAL); DEFINE_CLK_SMD_RPM_BRANCH(qdss, QCOM_SMD_RPM_MISC_CLK, 1, 19200000); DEFINE_CLK_SMD_RPM_QDSS(qdss, QCOM_SMD_RPM_MISC_CLK, 1); -DEFINE_CLK_SMD_RPM_BRANCH_A(bimc_freq_log, QCOM_SMD_RPM_MISC_CLK, 4, 1); +DEFINE_CLK_SMD_RPM_BRANCH_A(bimc_freq_log, QCOM_SMD_RPM_MISC_CLK, 4, 1, 0); DEFINE_CLK_SMD_RPM_BRANCH(mss_cfg_ahb, QCOM_SMD_RPM_MCFG_CLK, 0, 19200000); @@ -693,6 +697,7 @@ static struct clk_smd_rpm *msm8974_clks[] = { static const struct rpm_smd_clk_desc rpm_clk_msm8974 = { .clks = msm8974_clks, .num_clks = ARRAY_SIZE(msm8974_clks), + .scaling_before_handover = true, }; static struct clk_smd_rpm *msm8976_clks[] = { @@ -1301,12 +1306,11 @@ static int rpm_smd_clk_probe(struct platform_device *pdev) { int ret; size_t num_clks, i; - struct qcom_smd_rpm *rpm; struct clk_smd_rpm **rpm_smd_clks; const struct rpm_smd_clk_desc *desc; - rpm = dev_get_drvdata(pdev->dev.parent); - if (!rpm) { + rpmcc_smd_rpm = dev_get_drvdata(pdev->dev.parent); + if (!rpmcc_smd_rpm) { dev_err(&pdev->dev, "Unable to retrieve handle to RPM\n"); return -ENODEV; } @@ -1318,20 +1322,26 @@ static int rpm_smd_clk_probe(struct platform_device *pdev) rpm_smd_clks = desc->clks; num_clks = desc->num_clks; + if (desc->scaling_before_handover) { + ret = clk_smd_rpm_enable_scaling(); + if (ret) + goto err; + } + for (i = 0; i < num_clks; i++) { if (!rpm_smd_clks[i]) continue; - rpm_smd_clks[i]->rpm = rpm; - ret = clk_smd_rpm_handoff(rpm_smd_clks[i]); if (ret) goto err; } - ret = clk_smd_rpm_enable_scaling(rpm); - if (ret) - goto err; + if (!desc->scaling_before_handover) { + ret = clk_smd_rpm_enable_scaling(); + if (ret) + goto err; + } for (i = 0; i < num_clks; i++) { if (!rpm_smd_clks[i]) |