diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi index 9254e4423d0c..b7e871d8f857 100644 --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi @@ -11,6 +11,7 @@ #include #include #include +#include / { interrupt-parent = <&intc>; @@ -106,10 +107,11 @@ CPU0: cpu@0 { next-level-cache = <&L2_0>; enable-method = "psci"; clocks = <&apcs>; + cpu-supply = <&pm8916_spmi_s2>; operating-points-v2 = <&cpu_opp_table>; #cooling-cells = <2>; - power-domains = <&CPU_PD0>; - power-domain-names = "psci"; + power-domains = <&CPU_PD0>, <&rpmpd MSM8916_VDDMX_AO>; + power-domain-names = "psci", "mx"; }; CPU1: cpu@1 { @@ -119,10 +121,11 @@ CPU1: cpu@1 { next-level-cache = <&L2_0>; enable-method = "psci"; clocks = <&apcs>; + cpu-supply = <&pm8916_spmi_s2>; operating-points-v2 = <&cpu_opp_table>; #cooling-cells = <2>; - power-domains = <&CPU_PD1>; - power-domain-names = "psci"; + power-domains = <&CPU_PD1>, <&rpmpd MSM8916_VDDMX_AO>; + power-domain-names = "psci", "mx"; }; CPU2: cpu@2 { @@ -132,10 +135,11 @@ CPU2: cpu@2 { next-level-cache = <&L2_0>; enable-method = "psci"; clocks = <&apcs>; + cpu-supply = <&pm8916_spmi_s2>; operating-points-v2 = <&cpu_opp_table>; #cooling-cells = <2>; - power-domains = <&CPU_PD2>; - power-domain-names = "psci"; + power-domains = <&CPU_PD2>, <&rpmpd MSM8916_VDDMX_AO>; + power-domain-names = "psci", "mx"; }; CPU3: cpu@3 { @@ -145,10 +149,11 @@ CPU3: cpu@3 { next-level-cache = <&L2_0>; enable-method = "psci"; clocks = <&apcs>; + cpu-supply = <&pm8916_spmi_s2>; operating-points-v2 = <&cpu_opp_table>; #cooling-cells = <2>; - power-domains = <&CPU_PD3>; - power-domain-names = "psci"; + power-domains = <&CPU_PD3>, <&rpmpd MSM8916_VDDMX_AO>; + power-domain-names = "psci", "mx"; }; L2_0: l2-cache { @@ -340,20 +345,48 @@ modem_alert0: trip-point@0 { }; cpu_opp_table: cpu_opp_table { - compatible = "operating-points-v2"; + compatible = "operating-points-v2-qcom-cpu"; opp-shared; opp-200000000 { opp-hz = /bits/ 64 <200000000>; + opp-microvolt = <1050000>; + required-opps = <&rpmpd_opp_svs_soc>; }; opp-400000000 { opp-hz = /bits/ 64 <400000000>; + opp-microvolt = <1050000>; + required-opps = <&rpmpd_opp_svs_soc>; + }; + opp-533330000 { + opp-hz = /bits/ 64 <533330000>; + opp-microvolt = <1150000>; + required-opps = <&rpmpd_opp_nom>; }; opp-800000000 { opp-hz = /bits/ 64 <800000000>; + opp-microvolt = <1150000>; + required-opps = <&rpmpd_opp_nom>; }; opp-998400000 { opp-hz = /bits/ 64 <998400000>; + opp-microvolt = <1350000>; + required-opps = <&rpmpd_opp_super_turbo>; + }; + opp-1094400000 { + opp-hz = /bits/ 64 <1094400000>; + opp-microvolt = <1350000>; + required-opps = <&rpmpd_opp_super_turbo>; + }; + opp-1152000000 { + opp-hz = /bits/ 64 <1152000000>; + opp-microvolt = <1350000>; + required-opps = <&rpmpd_opp_super_turbo>; + }; + opp-1209600000 { + opp-hz = /bits/ 64 <1209600000>; + opp-microvolt = <1350000>; + required-opps = <&rpmpd_opp_super_turbo>; }; }; @@ -1725,10 +1758,45 @@ rpmcc: qcom,rpmcc { #clock-cells = <1>; }; + rpmpd: power-controller { + compatible = "qcom,msm8916-rpmpd"; + #power-domain-cells = <1>; + operating-points-v2 = <&rpmpd_opp_table>; + + rpmpd_opp_table: opp-table { + compatible = "operating-points-v2"; + + rpmpd_opp_ret: opp1 { + opp-level = <1>; + }; + + rpmpd_opp_svs: opp2 { + opp-level = <2>; + }; + + rpmpd_opp_svs_soc: opp3 { + opp-level = <3>; + }; + + rpmpd_opp_nom: opp4 { + opp-level = <4>; + }; + + rpmpd_opp_turbo: opp5 { + opp-level = <5>; + }; + + rpmpd_opp_super_turbo: opp6 { + opp-level = <6>; + }; + }; + }; + smd_rpm_regulators: pm8916-regulators { compatible = "qcom,rpm-pm8916-regulators"; pm8916_s1: s1 {}; + /* s2 is directly controlled via spmi */ pm8916_s3: s3 {}; pm8916_s4: s4 {}; diff --git a/arch/arm64/boot/dts/qcom/pm8916.dtsi b/arch/arm64/boot/dts/qcom/pm8916.dtsi index cbb96f23c2f7..c1505fc4a077 100644 --- a/arch/arm64/boot/dts/qcom/pm8916.dtsi +++ b/arch/arm64/boot/dts/qcom/pm8916.dtsi @@ -163,5 +163,18 @@ wcd_codec: codec@f000 { vdd-micbias-supply = <&pm8916_l13>; #sound-dai-cells = <1>; }; + + spmi_regulators: spmi_regulators { + compatible = "qcom,pm8916-regulators"; + #address-cells = <1>; + #size-cells = <1>; + + pm8916_spmi_s2: s2 { + regulator-always-on; + regulator-min-microvolt = <1050000>; + regulator-max-microvolt = <1350000>; + }; + /* other regulators can be controlled via rpm */ + }; }; }; diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index cb9db16bea61..4a261101de3f 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -128,6 +128,7 @@ static const struct of_device_id blacklist[] __initconst = { { .compatible = "nvidia,tegra210", }, { .compatible = "qcom,apq8096", }, + { .compatible = "qcom,msm8916", }, { .compatible = "qcom,msm8996", }, { .compatible = "qcom,qcs404", }, diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c index a1b8238872a2..16d31f724bb8 100644 --- a/drivers/cpufreq/qcom-cpufreq-nvmem.c +++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -252,6 +253,16 @@ static const struct qcom_cpufreq_match_data match_data_krait = { .get_version = qcom_cpufreq_krait_name_version, }; +static const char *msm8916_genpd_names[] = { "mx", NULL }; + +static const struct qcom_cpufreq_match_data match_data_msm8916 = { + /* + * FIXME: Might need to implement .get_version here to handle + * different frequencies depending on speedbin/pvs version. + */ + .genpd_names = msm8916_genpd_names, +}; + static const char *qcs404_genpd_names[] = { "cpr", NULL }; static const struct qcom_cpufreq_match_data match_data_qcs404 = { @@ -370,10 +381,13 @@ static int qcom_cpufreq_probe(struct platform_device *pdev) } if (drv->data->genpd_names) { + struct device **pd_dev; + const char **name = drv->data->genpd_names; + drv->genpd_opp_tables[cpu] = dev_pm_opp_attach_genpd(cpu_dev, drv->data->genpd_names, - NULL); + &pd_dev); if (IS_ERR(drv->genpd_opp_tables[cpu])) { ret = PTR_ERR(drv->genpd_opp_tables[cpu]); if (ret != -EPROBE_DEFER) @@ -382,6 +396,12 @@ static int qcom_cpufreq_probe(struct platform_device *pdev) ret); goto free_genpd_opp; } + + while (*name) { + pm_runtime_get_sync(*pd_dev); + name++; + pd_dev++; + } } } @@ -456,6 +476,7 @@ static struct platform_driver qcom_cpufreq_driver = { static const struct of_device_id qcom_cpufreq_match_list[] __initconst = { { .compatible = "qcom,apq8096", .data = &match_data_kryo }, + { .compatible = "qcom,msm8916", .data = &match_data_msm8916 }, { .compatible = "qcom,msm8996", .data = &match_data_kryo }, { .compatible = "qcom,qcs404", .data = &match_data_qcs404 }, { .compatible = "qcom,ipq8064", .data = &match_data_krait }, diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c index 2b1834c5609a..705a52b9ebc5 100644 --- a/drivers/soc/qcom/rpmpd.c +++ b/drivers/soc/qcom/rpmpd.c @@ -115,6 +115,26 @@ struct rpmpd_desc { static DEFINE_MUTEX(rpmpd_lock); +/* msm8916 RPM Power Domains */ +DEFINE_RPMPD_PAIR(msm8916, vddcx, vddcx_ao, SMPA, CORNER, 1); +DEFINE_RPMPD_PAIR(msm8916, vddmx, vddmx_ao, LDOA, CORNER, 3); + +DEFINE_RPMPD_VFC(msm8916, vddcx_vfc, SMPA, 1); + +static struct rpmpd *msm8916_rpmpds[] = { + [MSM8916_VDDCX] = &msm8916_vddcx, + [MSM8916_VDDCX_AO] = &msm8916_vddcx_ao, + [MSM8916_VDDCX_VFC] = &msm8916_vddcx_vfc, + [MSM8916_VDDMX] = &msm8916_vddmx, + [MSM8916_VDDMX_AO] = &msm8916_vddmx_ao, +}; + +static const struct rpmpd_desc msm8916_desc = { + .rpmpds = msm8916_rpmpds, + .num_pds = ARRAY_SIZE(msm8916_rpmpds), + .max_state = MAX_8996_RPMPD_STATE, +}; + /* msm8976 RPM Power Domains */ DEFINE_RPMPD_PAIR(msm8976, vddcx, vddcx_ao, SMPA, LEVEL, 2); DEFINE_RPMPD_PAIR(msm8976, vddmx, vddmx_ao, SMPA, LEVEL, 6); @@ -220,6 +240,7 @@ static const struct rpmpd_desc qcs404_desc = { }; static const struct of_device_id rpmpd_match_table[] = { + { .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc }, { .compatible = "qcom,msm8976-rpmpd", .data = &msm8976_desc }, { .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc }, { .compatible = "qcom,msm8998-rpmpd", .data = &msm8998_desc }, @@ -235,6 +256,8 @@ static int rpmpd_send_enable(struct rpmpd *pd, bool enable) .value = cpu_to_le32(enable), }; + pr_err("rpmpd enable %#x %#x: %d\n", pd->res_type, pd->res_id, enable); + return qcom_rpm_smd_write(pd->rpm, QCOM_SMD_RPM_ACTIVE_STATE, pd->res_type, pd->res_id, &req, sizeof(req)); } @@ -247,6 +270,8 @@ static int rpmpd_send_corner(struct rpmpd *pd, int state, unsigned int corner) .value = cpu_to_le32(corner), }; + pr_err("rpmpd corner %#x %#x state %d: %u\n", pd->res_type, pd->res_id, state, corner); + return qcom_rpm_smd_write(pd->rpm, state, pd->res_type, pd->res_id, &req, sizeof(req)); }; @@ -331,6 +356,8 @@ static int rpmpd_set_performance(struct generic_pm_domain *domain, int ret = 0; struct rpmpd *pd = domain_to_rpmpd(domain); + pr_err("set performance: %d\n", state); + if (state > pd->max_state) state = pd->max_state; @@ -340,8 +367,10 @@ static int rpmpd_set_performance(struct generic_pm_domain *domain, /* Always send updates for vfc and vfl */ if (!pd->enabled && pd->key != KEY_FLOOR_CORNER && - pd->key != KEY_FLOOR_LEVEL) + pd->key != KEY_FLOOR_LEVEL) { + pr_err("not enabled\n"); goto out; + } ret = rpmpd_aggregate_corner(pd); diff --git a/include/dt-bindings/power/qcom-rpmpd.h b/include/dt-bindings/power/qcom-rpmpd.h index 3f74096d5a7c..70d304a2deae 100644 --- a/include/dt-bindings/power/qcom-rpmpd.h +++ b/include/dt-bindings/power/qcom-rpmpd.h @@ -51,6 +51,13 @@ #define RPMH_REGULATOR_LEVEL_TURBO 384 #define RPMH_REGULATOR_LEVEL_TURBO_L1 416 +/* MSM8916 Power Domain Indexes */ +#define MSM8916_VDDCX 0 +#define MSM8916_VDDCX_AO 1 +#define MSM8916_VDDCX_VFC 2 +#define MSM8916_VDDMX 3 +#define MSM8916_VDDMX_AO 4 + /* MSM8976 Power Domain Indexes */ #define MSM8976_VDDCX 0 #define MSM8976_VDDCX_AO 1