diff options
Diffstat (limited to 'drivers/pmdomain/qcom/rpmhpd.c')
-rw-r--r-- | drivers/pmdomain/qcom/rpmhpd.c | 129 |
1 files changed, 120 insertions, 9 deletions
diff --git a/drivers/pmdomain/qcom/rpmhpd.c b/drivers/pmdomain/qcom/rpmhpd.c index 3078896b1300..078323b85b56 100644 --- a/drivers/pmdomain/qcom/rpmhpd.c +++ b/drivers/pmdomain/qcom/rpmhpd.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* Copyright (c) 2018, The Linux Foundation. All rights reserved.*/ +#include <linux/cleanup.h> #include <linux/err.h> #include <linux/init.h> #include <linux/kernel.h> @@ -40,6 +41,7 @@ * @addr: Resource address as looped up using resource name from * cmd-db * @state_synced: Indicator that sync_state has been invoked for the rpmhpd resource + * @skip_retention_level: Indicate that retention level should not be used for the power domain */ struct rpmhpd { struct device *dev; @@ -56,6 +58,7 @@ struct rpmhpd { const char *res_name; u32 addr; bool state_synced; + bool skip_retention_level; }; struct rpmhpd_desc { @@ -173,6 +176,7 @@ static struct rpmhpd mxc = { .pd = { .name = "mxc", }, .peer = &mxc_ao, .res_name = "mxc.lvl", + .skip_retention_level = true, }; static struct rpmhpd mxc_ao = { @@ -180,6 +184,7 @@ static struct rpmhpd mxc_ao = { .active_only = true, .peer = &mxc, .res_name = "mxc.lvl", + .skip_retention_level = true, }; static struct rpmhpd nsp = { @@ -217,7 +222,6 @@ static struct rpmhpd *sa8540p_rpmhpds[] = { [SC8280XP_CX] = &cx, [SC8280XP_CX_AO] = &cx_ao, [SC8280XP_EBI] = &ebi, - [SC8280XP_GFX] = &gfx, [SC8280XP_LCX] = &lcx, [SC8280XP_LMX] = &lmx, [SC8280XP_MMCX] = &mmcx, @@ -255,6 +259,30 @@ static const struct rpmhpd_desc sa8775p_desc = { .num_pds = ARRAY_SIZE(sa8775p_rpmhpds), }; +/* SAR2130P RPMH powerdomains */ +static struct rpmhpd *sar2130p_rpmhpds[] = { + [RPMHPD_CX] = &cx, + [RPMHPD_CX_AO] = &cx_ao, + [RPMHPD_EBI] = &ebi, + [RPMHPD_GFX] = &gfx, + [RPMHPD_LCX] = &lcx, + [RPMHPD_LMX] = &lmx, + [RPMHPD_MMCX] = &mmcx_w_cx_parent, + [RPMHPD_MMCX_AO] = &mmcx_ao_w_cx_parent, + [RPMHPD_MSS] = &mss, + [RPMHPD_MX] = &mx, + [RPMHPD_MX_AO] = &mx_ao, + [RPMHPD_MXC] = &mxc, + [RPMHPD_MXC_AO] = &mxc_ao, + [RPMHPD_NSP] = &nsp, + [RPMHPD_QPHY] = &qphy, +}; + +static const struct rpmhpd_desc sar2130p_desc = { + .rpmhpds = sar2130p_rpmhpds, + .num_pds = ARRAY_SIZE(sar2130p_rpmhpds), +}; + /* SDM670 RPMH powerdomains */ static struct rpmhpd *sdm670_rpmhpds[] = { [SDM670_CX] = &cx_w_mx_parent, @@ -332,6 +360,21 @@ static const struct rpmhpd_desc sdx75_desc = { .num_pds = ARRAY_SIZE(sdx75_rpmhpds), }; +/* SM4450 RPMH powerdomains */ +static struct rpmhpd *sm4450_rpmhpds[] = { + [RPMHPD_CX] = &cx, + [RPMHPD_CX_AO] = &cx_ao, + [RPMHPD_EBI] = &ebi, + [RPMHPD_LMX] = &lmx, + [RPMHPD_MSS] = &mss, + [RPMHPD_MX] = &mx, +}; + +static const struct rpmhpd_desc sm4450_desc = { + .rpmhpds = sm4450_rpmhpds, + .num_pds = ARRAY_SIZE(sm4450_rpmhpds), +}; + /* SM6350 RPMH powerdomains */ static struct rpmhpd *sm6350_rpmhpds[] = { [SM6350_CX] = &cx_w_mx_parent, @@ -509,6 +552,31 @@ static const struct rpmhpd_desc sm8650_desc = { .num_pds = ARRAY_SIZE(sm8650_rpmhpds), }; +/* SM8750 RPMH powerdomains */ +static struct rpmhpd *sm8750_rpmhpds[] = { + [RPMHPD_CX] = &cx, + [RPMHPD_CX_AO] = &cx_ao, + [RPMHPD_EBI] = &ebi, + [RPMHPD_GFX] = &gfx, + [RPMHPD_GMXC] = &gmxc, + [RPMHPD_LCX] = &lcx, + [RPMHPD_LMX] = &lmx, + [RPMHPD_MX] = &mx, + [RPMHPD_MX_AO] = &mx_ao, + [RPMHPD_MMCX] = &mmcx_w_cx_parent, + [RPMHPD_MMCX_AO] = &mmcx_ao_w_cx_parent, + [RPMHPD_MSS] = &mss, + [RPMHPD_MXC] = &mxc, + [RPMHPD_MXC_AO] = &mxc_ao, + [RPMHPD_NSP] = &nsp, + [RPMHPD_NSP2] = &nsp2, +}; + +static const struct rpmhpd_desc sm8750_desc = { + .rpmhpds = sm8750_rpmhpds, + .num_pds = ARRAY_SIZE(sm8750_rpmhpds), +}; + /* QDU1000/QRU1000 RPMH powerdomains */ static struct rpmhpd *qdu1000_rpmhpds[] = { [QDU1000_CX] = &cx, @@ -620,11 +688,48 @@ static const struct rpmhpd_desc x1e80100_desc = { .num_pds = ARRAY_SIZE(x1e80100_rpmhpds), }; +/* QCS8300 RPMH power domains */ +static struct rpmhpd *qcs8300_rpmhpds[] = { + [RPMHPD_CX] = &cx, + [RPMHPD_CX_AO] = &cx_ao, + [RPMHPD_EBI] = &ebi, + [RPMHPD_GFX] = &gfx, + [RPMHPD_LCX] = &lcx, + [RPMHPD_LMX] = &lmx, + [RPMHPD_MMCX] = &mmcx_w_cx_parent, + [RPMHPD_MMCX_AO] = &mmcx_ao_w_cx_parent, + [RPMHPD_MXC] = &mxc, + [RPMHPD_MXC_AO] = &mxc_ao, + [RPMHPD_MX] = &mx, + [RPMHPD_MX_AO] = &mx_ao, + [RPMHPD_NSP0] = &nsp0, + [RPMHPD_NSP1] = &nsp1, +}; + +static const struct rpmhpd_desc qcs8300_desc = { + .rpmhpds = qcs8300_rpmhpds, + .num_pds = ARRAY_SIZE(qcs8300_rpmhpds), +}; + +/* QCS615 RPMH powerdomains */ +static struct rpmhpd *qcs615_rpmhpds[] = { + [RPMHPD_CX] = &cx, + [RPMHPD_CX_AO] = &cx_ao, +}; + +static const struct rpmhpd_desc qcs615_desc = { + .rpmhpds = qcs615_rpmhpds, + .num_pds = ARRAY_SIZE(qcs615_rpmhpds), +}; + static const struct of_device_id rpmhpd_match_table[] = { + { .compatible = "qcom,qcs615-rpmhpd", .data = &qcs615_desc }, + { .compatible = "qcom,qcs8300-rpmhpd", .data = &qcs8300_desc }, { .compatible = "qcom,qdu1000-rpmhpd", .data = &qdu1000_desc }, { .compatible = "qcom,sa8155p-rpmhpd", .data = &sa8155p_desc }, { .compatible = "qcom,sa8540p-rpmhpd", .data = &sa8540p_desc }, { .compatible = "qcom,sa8775p-rpmhpd", .data = &sa8775p_desc }, + { .compatible = "qcom,sar2130p-rpmhpd", .data = &sar2130p_desc}, { .compatible = "qcom,sc7180-rpmhpd", .data = &sc7180_desc }, { .compatible = "qcom,sc7280-rpmhpd", .data = &sc7280_desc }, { .compatible = "qcom,sc8180x-rpmhpd", .data = &sc8180x_desc }, @@ -634,6 +739,7 @@ static const struct of_device_id rpmhpd_match_table[] = { { .compatible = "qcom,sdx55-rpmhpd", .data = &sdx55_desc}, { .compatible = "qcom,sdx65-rpmhpd", .data = &sdx65_desc}, { .compatible = "qcom,sdx75-rpmhpd", .data = &sdx75_desc}, + { .compatible = "qcom,sm4450-rpmhpd", .data = &sm4450_desc }, { .compatible = "qcom,sm6350-rpmhpd", .data = &sm6350_desc }, { .compatible = "qcom,sm7150-rpmhpd", .data = &sm7150_desc }, { .compatible = "qcom,sm8150-rpmhpd", .data = &sm8150_desc }, @@ -642,6 +748,7 @@ static const struct of_device_id rpmhpd_match_table[] = { { .compatible = "qcom,sm8450-rpmhpd", .data = &sm8450_desc }, { .compatible = "qcom,sm8550-rpmhpd", .data = &sm8550_desc }, { .compatible = "qcom,sm8650-rpmhpd", .data = &sm8650_desc }, + { .compatible = "qcom,sm8750-rpmhpd", .data = &sm8750_desc }, { .compatible = "qcom,x1e80100-rpmhpd", .data = &x1e80100_desc }, { } }; @@ -692,6 +799,7 @@ static int rpmhpd_aggregate_corner(struct rpmhpd *pd, unsigned int corner) unsigned int active_corner, sleep_corner; unsigned int this_active_corner = 0, this_sleep_corner = 0; unsigned int peer_active_corner = 0, peer_sleep_corner = 0; + unsigned int peer_enabled_corner; if (pd->state_synced) { to_active_sleep(pd, corner, &this_active_corner, &this_sleep_corner); @@ -701,9 +809,11 @@ static int rpmhpd_aggregate_corner(struct rpmhpd *pd, unsigned int corner) this_sleep_corner = pd->level_count - 1; } - if (peer && peer->enabled) - to_active_sleep(peer, peer->corner, &peer_active_corner, + if (peer && peer->enabled) { + peer_enabled_corner = max(peer->corner, peer->enable_corner); + to_active_sleep(peer, peer_enabled_corner, &peer_active_corner, &peer_sleep_corner); + } active_corner = max(this_active_corner, peer_active_corner); @@ -769,9 +879,9 @@ static int rpmhpd_set_performance_state(struct generic_pm_domain *domain, unsigned int level) { struct rpmhpd *pd = domain_to_rpmhpd(domain); - int ret = 0, i; + int ret, i; - mutex_lock(&rpmhpd_lock); + guard(mutex)(&rpmhpd_lock); for (i = 0; i < pd->level_count; i++) if (level <= pd->level[i]) @@ -791,14 +901,12 @@ static int rpmhpd_set_performance_state(struct generic_pm_domain *domain, ret = rpmhpd_aggregate_corner(pd, i); if (ret) - goto out; + return ret; } pd->corner = i; -out: - mutex_unlock(&rpmhpd_lock); - return ret; + return 0; } static int rpmhpd_update_level_mapping(struct rpmhpd *rpmhpd) @@ -817,6 +925,9 @@ static int rpmhpd_update_level_mapping(struct rpmhpd *rpmhpd) return -EINVAL; for (i = 0; i < rpmhpd->level_count; i++) { + if (rpmhpd->skip_retention_level && buf[i] == RPMH_REGULATOR_LEVEL_RETENTION) + continue; + rpmhpd->level[i] = buf[i]; /* Remember the first corner with non-zero level */ |