Loading Documentation/devicetree/bindings/arm/msm/clock-cpu-8939.txt +3 −1 Original line number Original line Diff line number Diff line Loading @@ -7,7 +7,7 @@ fmax tables, avs settings table, etc. Required properties: Required properties: - compatible: Must be one of "qcom,clock-cpu-8939" or - compatible: Must be one of "qcom,clock-cpu-8939" or "qcom,cpu-clock-8952" "qcom,cpu-clock-8952", "qcom,cpu-clock-gold". - reg: Pairs of physical base addresses and region sizes of - reg: Pairs of physical base addresses and region sizes of memory mapped registers. memory mapped registers. - reg-names: Names of the bases for the above registers. Expected - reg-names: Names of the bases for the above registers. Expected Loading @@ -33,6 +33,8 @@ Required properties: Optional properties: Optional properties: - qcom,cpu-pcnoc-vote: Boolean to indicate cpu clocks would need to keep - qcom,cpu-pcnoc-vote: Boolean to indicate cpu clocks would need to keep active pcnoc vote. active pcnoc vote. - qcom,num-cluster: Boolean to indicate cpu clock code is used for single cluster. Example: Example: clock_cpu: qcom,cpu-clock-8939@f9015000 { clock_cpu: qcom,cpu-clock-8939@f9015000 { compatible = "qcom,cpu-clock-8939"; compatible = "qcom,cpu-clock-8939"; Loading arch/arm/boot/dts/qcom/msm8937.dtsi +6 −6 Original line number Original line Diff line number Diff line Loading @@ -566,11 +566,11 @@ clock_gcc: qcom,gcc@1800000 { clock_gcc: qcom,gcc@1800000 { compatible = "qcom,gcc-8937"; compatible = "qcom,gcc-8937"; reg = <0x1800000 0x80000>, reg = <0x1800000 0x80000>, <0xb116000 0x00040>, <0xb016000 0x00040>, <0xb016000 0x00040>, <0xb116000 0x00040>, <0xb1d0000 0x00040>; <0xb1d0000 0x00040>; reg-names = "cc_base", "apcs_c0_base", reg-names = "cc_base", "apcs_c1_base", "apcs_c1_base", "apcs_cci_base"; "apcs_c0_base", "apcs_cci_base"; vdd_dig-supply = <&pm8937_s2_level>; vdd_dig-supply = <&pm8937_s2_level>; vdd_sr2_dig-supply = <&pm8937_s2_level_ao>; vdd_sr2_dig-supply = <&pm8937_s2_level_ao>; vdd_sr2_pll-supply = <&pm8937_l7_ao>; vdd_sr2_pll-supply = <&pm8937_l7_ao>; Loading Loading @@ -607,11 +607,11 @@ clock_cpu: qcom,cpu-clock-8939@b111050 { clock_cpu: qcom,cpu-clock-8939@b111050 { compatible = "qcom,cpu-clock-8939"; compatible = "qcom,cpu-clock-8939"; reg = <0xb111050 0x8>, reg = <0xb011050 0x8>, <0xb011050 0x8>, <0xb111050 0x8>, <0xb1d1050 0x8>, <0xb1d1050 0x8>, <0x00a412c 0x8>; <0x00a412c 0x8>; reg-names = "apcs-c0-rcg-base", "apcs-c1-rcg-base", reg-names = "apcs-c1-rcg-base", "apcs-c0-rcg-base", "apcs-cci-rcg-base", "efuse"; "apcs-cci-rcg-base", "efuse"; vdd-c0-supply = <&apc_vreg_corner>; vdd-c0-supply = <&apc_vreg_corner>; vdd-c1-supply = <&apc_vreg_corner>; vdd-c1-supply = <&apc_vreg_corner>; Loading arch/arm/boot/dts/qcom/msm8952.dtsi +6 −6 Original line number Original line Diff line number Diff line Loading @@ -145,11 +145,11 @@ #size-cells = <1>; #size-cells = <1>; compatible = "qcom,gcc-8952"; compatible = "qcom,gcc-8952"; reg = <0x1800000 0x80000>, reg = <0x1800000 0x80000>, <0xb116000 0x00040>, <0xb016000 0x00040>, <0xb016000 0x00040>, <0xb116000 0x00040>, <0xb1d0000 0x00040>; <0xb1d0000 0x00040>; reg-names = "cc_base", "apcs_c0_base", reg-names = "cc_base", "apcs_c1_base", "apcs_c1_base", "apcs_cci_base"; "apcs_c0_base", "apcs_cci_base"; vdd_dig-supply = <&pm8950_s2_level>; vdd_dig-supply = <&pm8950_s2_level>; vdd_sr2_dig-supply = <&pm8950_s2_level_ao>; vdd_sr2_dig-supply = <&pm8950_s2_level_ao>; vdd_sr2_pll-supply = <&pm8950_l7_ao>; vdd_sr2_pll-supply = <&pm8950_l7_ao>; Loading Loading @@ -185,11 +185,11 @@ clock_cpu: qcom,cpu-clock-8939@b111050 { clock_cpu: qcom,cpu-clock-8939@b111050 { compatible = "qcom,cpu-clock-8939"; compatible = "qcom,cpu-clock-8939"; reg = <0xb111050 0x8>, reg = <0xb011050 0x8>, <0xb011050 0x8>, <0xb111050 0x8>, <0xb1d1050 0x8>, <0xb1d1050 0x8>, <0x005c00c 0x8>; <0x005c00c 0x8>; reg-names = "apcs-c0-rcg-base", "apcs-c1-rcg-base", reg-names = "apcs-c1-rcg-base", "apcs-c0-rcg-base", "apcs-cci-rcg-base", "efuse"; "apcs-cci-rcg-base", "efuse"; vdd-c0-supply = <&apc_vreg_corner>; vdd-c0-supply = <&apc_vreg_corner>; vdd-c1-supply = <&apc_vreg_corner>; vdd-c1-supply = <&apc_vreg_corner>; Loading drivers/clk/msm/clock-cpu-8939.c +86 −30 Original line number Original line Diff line number Diff line Loading @@ -203,6 +203,12 @@ static struct clk_lookup cpu_clocks_8939[] = { CLK_LIST(cci_clk), CLK_LIST(cci_clk), }; }; static struct clk_lookup cpu_clocks_8939_single_cluster[] = { CLK_LIST(a53ssmux_bc), CLK_LIST(a53_bc_clk), }; static struct mux_div_clk *a53ssmux[] = {&a53ssmux_bc, static struct mux_div_clk *a53ssmux[] = {&a53ssmux_bc, &a53ssmux_lc, &a53ssmux_cci}; &a53ssmux_lc, &a53ssmux_cci}; Loading Loading @@ -516,30 +522,33 @@ static int add_opp(struct clk *c, struct device *cpudev, struct device *vregdev, return 0; return 0; } } static void print_opp_table(int a53_c0_cpu, int a53_c1_cpu) static void print_opp_table(int a53_c0_cpu, int a53_c1_cpu, bool single_cluster) { { struct dev_pm_opp *oppfmax, *oppfmin; struct dev_pm_opp *oppfmax, *oppfmin; unsigned long apc0_fmax, apc1_fmax, apc0_fmin, apc1_fmin; unsigned long apc0_fmax, apc1_fmax, apc0_fmin, apc1_fmin; if (!single_cluster) { apc0_fmax = a53_lc_clk.c.fmax[a53_lc_clk.c.num_fmax - 1]; apc0_fmax = a53_lc_clk.c.fmax[a53_lc_clk.c.num_fmax - 1]; apc1_fmax = a53_bc_clk.c.fmax[a53_bc_clk.c.num_fmax - 1]; apc0_fmin = a53_lc_clk.c.fmax[1]; apc0_fmin = a53_lc_clk.c.fmax[1]; } apc1_fmax = a53_bc_clk.c.fmax[a53_bc_clk.c.num_fmax - 1]; apc1_fmin = a53_bc_clk.c.fmax[1]; apc1_fmin = a53_bc_clk.c.fmax[1]; rcu_read_lock(); rcu_read_lock(); if (!single_cluster) { oppfmax = dev_pm_opp_find_freq_exact(get_cpu_device(a53_c0_cpu), oppfmax = dev_pm_opp_find_freq_exact(get_cpu_device(a53_c0_cpu), apc0_fmax, true); apc0_fmax, true); oppfmin = dev_pm_opp_find_freq_exact(get_cpu_device(a53_c0_cpu), oppfmin = dev_pm_opp_find_freq_exact(get_cpu_device(a53_c0_cpu), apc0_fmin, true); apc0_fmin, true); /* /* * One time information during boot. Important to know that this looks * One time information during boot. Important to know that this * sane since it can eventually make its way to the scheduler. * looks sane since it can eventually make its way to the * scheduler. */ */ pr_info("clock_cpu: a53_c0: OPP voltage for %lu: %ld\n", apc0_fmin, pr_info("clock_cpu: a53_c0: OPP voltage for %lu: %ld\n", dev_pm_opp_get_voltage(oppfmin)); apc0_fmin, dev_pm_opp_get_voltage(oppfmin)); pr_info("clock_cpu: a53_c0: OPP voltage for %lu: %ld\n", apc0_fmax, pr_info("clock_cpu: a53_c0: OPP voltage for %lu: %ld\n", dev_pm_opp_get_voltage(oppfmax)); apc0_fmax, dev_pm_opp_get_voltage(oppfmax)); } oppfmax = dev_pm_opp_find_freq_exact(get_cpu_device(a53_c1_cpu), oppfmax = dev_pm_opp_find_freq_exact(get_cpu_device(a53_c1_cpu), apc1_fmax, true); apc1_fmax, true); oppfmin = dev_pm_opp_find_freq_exact(get_cpu_device(a53_c1_cpu), oppfmin = dev_pm_opp_find_freq_exact(get_cpu_device(a53_c1_cpu), Loading @@ -551,16 +560,19 @@ static void print_opp_table(int a53_c0_cpu, int a53_c1_cpu) rcu_read_unlock(); rcu_read_unlock(); } } static void populate_opp_table(struct platform_device *pdev) static void populate_opp_table(struct platform_device *pdev, bool single_cluster) { { struct platform_device *apc0_dev, *apc1_dev; struct platform_device *apc0_dev, *apc1_dev; struct device_node *apc0_node, *apc1_node; struct device_node *apc0_node, *apc1_node; unsigned long apc0_fmax, apc1_fmax; unsigned long apc0_fmax, apc1_fmax; int cpu, a53_c0_cpu, a53_c1_cpu; int cpu, a53_c0_cpu, a53_c1_cpu; apc0_node = of_parse_phandle(pdev->dev.of_node, "vdd-c0-supply", 0); if (!single_cluster) apc0_node = of_parse_phandle(pdev->dev.of_node, "vdd-c0-supply", 0); apc1_node = of_parse_phandle(pdev->dev.of_node, "vdd-c1-supply", 0); apc1_node = of_parse_phandle(pdev->dev.of_node, "vdd-c1-supply", 0); if (!apc0_node) { if (!apc0_node && !single_cluster) { pr_err("can't find the apc0 dt node.\n"); pr_err("can't find the apc0 dt node.\n"); return; return; } } Loading @@ -568,10 +580,11 @@ static void populate_opp_table(struct platform_device *pdev) pr_err("can't find the apc1 dt node.\n"); pr_err("can't find the apc1 dt node.\n"); return; return; } } if (!single_cluster) apc0_dev = of_find_device_by_node(apc0_node); apc0_dev = of_find_device_by_node(apc0_node); apc1_dev = of_find_device_by_node(apc1_node); apc1_dev = of_find_device_by_node(apc1_node); if (!apc0_dev) { if (!apc1_dev && !single_cluster) { pr_err("can't find the apc0 device node.\n"); pr_err("can't find the apc0 device node.\n"); return; return; } } Loading @@ -580,7 +593,9 @@ static void populate_opp_table(struct platform_device *pdev) return; return; } } if (!single_cluster) apc0_fmax = a53_lc_clk.c.fmax[a53_lc_clk.c.num_fmax - 1]; apc0_fmax = a53_lc_clk.c.fmax[a53_lc_clk.c.num_fmax - 1]; apc1_fmax = a53_bc_clk.c.fmax[a53_bc_clk.c.num_fmax - 1]; apc1_fmax = a53_bc_clk.c.fmax[a53_bc_clk.c.num_fmax - 1]; for_each_possible_cpu(cpu) { for_each_possible_cpu(cpu) { Loading @@ -590,7 +605,7 @@ static void populate_opp_table(struct platform_device *pdev) WARN(add_opp(&a53_bc_clk.c, get_cpu_device(cpu), WARN(add_opp(&a53_bc_clk.c, get_cpu_device(cpu), &apc1_dev->dev, apc1_fmax), &apc1_dev->dev, apc1_fmax), "Failed to add OPP levels for A53 big cluster\n"); "Failed to add OPP levels for A53 big cluster\n"); } else if (cpu/4 == 1) { } else if (cpu/4 == 1 && !single_cluster) { a53_c0_cpu = cpu; a53_c0_cpu = cpu; WARN(add_opp(&a53_lc_clk.c, get_cpu_device(cpu), WARN(add_opp(&a53_lc_clk.c, get_cpu_device(cpu), &apc0_dev->dev, apc0_fmax), &apc0_dev->dev, apc0_fmax), Loading @@ -602,7 +617,8 @@ static void populate_opp_table(struct platform_device *pdev) pr_info("clock-cpu-8939: OPP tables populated (cpu %d and %d)", pr_info("clock-cpu-8939: OPP tables populated (cpu %d and %d)", a53_c0_cpu, a53_c1_cpu); a53_c0_cpu, a53_c1_cpu); print_opp_table(a53_c0_cpu, a53_c1_cpu); print_opp_table(a53_c0_cpu, a53_c1_cpu, single_cluster); } } static void config_pll(int mux_id) static void config_pll(int mux_id) Loading Loading @@ -644,18 +660,47 @@ static int clock_8939_pm_event(struct notifier_block *this, return NOTIFY_DONE; return NOTIFY_DONE; } } static int clock_8939_pm_event_single_cluster(struct notifier_block *this, unsigned long event, void *ptr) { switch (event) { case PM_POST_HIBERNATION: case PM_POST_SUSPEND: clk_unprepare(&a53_bc_clk.c); break; case PM_HIBERNATION_PREPARE: case PM_SUSPEND_PREPARE: clk_prepare(&a53_bc_clk.c); break; default: break; } return NOTIFY_DONE; } static struct notifier_block clock_8939_pm_notifier = { static struct notifier_block clock_8939_pm_notifier = { .notifier_call = clock_8939_pm_event, .notifier_call = clock_8939_pm_event, }; }; static struct notifier_block clock_8939_pm_notifier_single_cluster = { .notifier_call = clock_8939_pm_event_single_cluster, }; static int clock_a53_probe(struct platform_device *pdev) static int clock_a53_probe(struct platform_device *pdev) { { int speed_bin, version, rc, cpu, mux_id, rate; int speed_bin, version, rc, cpu, mux_id, rate; char prop_name[] = "qcom,speedX-bin-vX-XXX"; char prop_name[] = "qcom,speedX-bin-vX-XXX"; int mux_num; bool single_cluster; single_cluster = of_property_read_bool(pdev->dev.of_node, "qcom,num-cluster"); get_speed_bin(pdev, &speed_bin, &version); get_speed_bin(pdev, &speed_bin, &version); for (mux_id = 0; mux_id < A53SS_MUX_NUM; mux_id++) { mux_num = single_cluster ? A53SS_MUX_LC:A53SS_MUX_NUM; for (mux_id = 0; mux_id < mux_num; mux_id++) { rc = cpu_parse_devicetree(pdev, mux_id); rc = cpu_parse_devicetree(pdev, mux_id); if (rc) if (rc) return rc; return rc; Loading Loading @@ -683,16 +728,23 @@ static int clock_a53_probe(struct platform_device *pdev) dev_info(&pdev->dev, "Safe voltage plan loaded.\n"); dev_info(&pdev->dev, "Safe voltage plan loaded.\n"); } } } } if (single_cluster) rc = of_msm_clock_register(pdev->dev.of_node, cpu_clocks_8939_single_cluster, ARRAY_SIZE(cpu_clocks_8939_single_cluster)); else rc = of_msm_clock_register(pdev->dev.of_node, rc = of_msm_clock_register(pdev->dev.of_node, cpu_clocks_8939, ARRAY_SIZE(cpu_clocks_8939)); cpu_clocks_8939, ARRAY_SIZE(cpu_clocks_8939)); if (rc) { if (rc) { dev_err(&pdev->dev, "msm_clock_register failed\n"); dev_err(&pdev->dev, "msm_clock_register failed\n"); return rc; return rc; } } if (!single_cluster) { rate = clk_get_rate(&cci_clk.c); rate = clk_get_rate(&cci_clk.c); clk_set_rate(&cci_clk.c, rate); clk_set_rate(&cci_clk.c, rate); } for (mux_id = 0; mux_id < A53SS_MUX_CCI; mux_id++) { for (mux_id = 0; mux_id < A53SS_MUX_CCI; mux_id++) { /* Force a PLL reconfiguration */ /* Force a PLL reconfiguration */ Loading Loading @@ -724,15 +776,19 @@ static int clock_a53_probe(struct platform_device *pdev) a53_lc_clk.hw_low_power_ctrl = true; a53_lc_clk.hw_low_power_ctrl = true; a53_bc_clk.hw_low_power_ctrl = true; a53_bc_clk.hw_low_power_ctrl = true; if (single_cluster) register_pm_notifier(&clock_8939_pm_notifier_single_cluster); else register_pm_notifier(&clock_8939_pm_notifier); register_pm_notifier(&clock_8939_pm_notifier); populate_opp_table(pdev); populate_opp_table(pdev, single_cluster); return 0; return 0; } } static struct of_device_id clock_a53_match_table[] = { static struct of_device_id clock_a53_match_table[] = { {.compatible = "qcom,cpu-clock-8939"}, {.compatible = "qcom,cpu-clock-8939"}, {.compatible = "qcom,cpu-clock-gold"}, {} {} }; }; Loading Loading
Documentation/devicetree/bindings/arm/msm/clock-cpu-8939.txt +3 −1 Original line number Original line Diff line number Diff line Loading @@ -7,7 +7,7 @@ fmax tables, avs settings table, etc. Required properties: Required properties: - compatible: Must be one of "qcom,clock-cpu-8939" or - compatible: Must be one of "qcom,clock-cpu-8939" or "qcom,cpu-clock-8952" "qcom,cpu-clock-8952", "qcom,cpu-clock-gold". - reg: Pairs of physical base addresses and region sizes of - reg: Pairs of physical base addresses and region sizes of memory mapped registers. memory mapped registers. - reg-names: Names of the bases for the above registers. Expected - reg-names: Names of the bases for the above registers. Expected Loading @@ -33,6 +33,8 @@ Required properties: Optional properties: Optional properties: - qcom,cpu-pcnoc-vote: Boolean to indicate cpu clocks would need to keep - qcom,cpu-pcnoc-vote: Boolean to indicate cpu clocks would need to keep active pcnoc vote. active pcnoc vote. - qcom,num-cluster: Boolean to indicate cpu clock code is used for single cluster. Example: Example: clock_cpu: qcom,cpu-clock-8939@f9015000 { clock_cpu: qcom,cpu-clock-8939@f9015000 { compatible = "qcom,cpu-clock-8939"; compatible = "qcom,cpu-clock-8939"; Loading
arch/arm/boot/dts/qcom/msm8937.dtsi +6 −6 Original line number Original line Diff line number Diff line Loading @@ -566,11 +566,11 @@ clock_gcc: qcom,gcc@1800000 { clock_gcc: qcom,gcc@1800000 { compatible = "qcom,gcc-8937"; compatible = "qcom,gcc-8937"; reg = <0x1800000 0x80000>, reg = <0x1800000 0x80000>, <0xb116000 0x00040>, <0xb016000 0x00040>, <0xb016000 0x00040>, <0xb116000 0x00040>, <0xb1d0000 0x00040>; <0xb1d0000 0x00040>; reg-names = "cc_base", "apcs_c0_base", reg-names = "cc_base", "apcs_c1_base", "apcs_c1_base", "apcs_cci_base"; "apcs_c0_base", "apcs_cci_base"; vdd_dig-supply = <&pm8937_s2_level>; vdd_dig-supply = <&pm8937_s2_level>; vdd_sr2_dig-supply = <&pm8937_s2_level_ao>; vdd_sr2_dig-supply = <&pm8937_s2_level_ao>; vdd_sr2_pll-supply = <&pm8937_l7_ao>; vdd_sr2_pll-supply = <&pm8937_l7_ao>; Loading Loading @@ -607,11 +607,11 @@ clock_cpu: qcom,cpu-clock-8939@b111050 { clock_cpu: qcom,cpu-clock-8939@b111050 { compatible = "qcom,cpu-clock-8939"; compatible = "qcom,cpu-clock-8939"; reg = <0xb111050 0x8>, reg = <0xb011050 0x8>, <0xb011050 0x8>, <0xb111050 0x8>, <0xb1d1050 0x8>, <0xb1d1050 0x8>, <0x00a412c 0x8>; <0x00a412c 0x8>; reg-names = "apcs-c0-rcg-base", "apcs-c1-rcg-base", reg-names = "apcs-c1-rcg-base", "apcs-c0-rcg-base", "apcs-cci-rcg-base", "efuse"; "apcs-cci-rcg-base", "efuse"; vdd-c0-supply = <&apc_vreg_corner>; vdd-c0-supply = <&apc_vreg_corner>; vdd-c1-supply = <&apc_vreg_corner>; vdd-c1-supply = <&apc_vreg_corner>; Loading
arch/arm/boot/dts/qcom/msm8952.dtsi +6 −6 Original line number Original line Diff line number Diff line Loading @@ -145,11 +145,11 @@ #size-cells = <1>; #size-cells = <1>; compatible = "qcom,gcc-8952"; compatible = "qcom,gcc-8952"; reg = <0x1800000 0x80000>, reg = <0x1800000 0x80000>, <0xb116000 0x00040>, <0xb016000 0x00040>, <0xb016000 0x00040>, <0xb116000 0x00040>, <0xb1d0000 0x00040>; <0xb1d0000 0x00040>; reg-names = "cc_base", "apcs_c0_base", reg-names = "cc_base", "apcs_c1_base", "apcs_c1_base", "apcs_cci_base"; "apcs_c0_base", "apcs_cci_base"; vdd_dig-supply = <&pm8950_s2_level>; vdd_dig-supply = <&pm8950_s2_level>; vdd_sr2_dig-supply = <&pm8950_s2_level_ao>; vdd_sr2_dig-supply = <&pm8950_s2_level_ao>; vdd_sr2_pll-supply = <&pm8950_l7_ao>; vdd_sr2_pll-supply = <&pm8950_l7_ao>; Loading Loading @@ -185,11 +185,11 @@ clock_cpu: qcom,cpu-clock-8939@b111050 { clock_cpu: qcom,cpu-clock-8939@b111050 { compatible = "qcom,cpu-clock-8939"; compatible = "qcom,cpu-clock-8939"; reg = <0xb111050 0x8>, reg = <0xb011050 0x8>, <0xb011050 0x8>, <0xb111050 0x8>, <0xb1d1050 0x8>, <0xb1d1050 0x8>, <0x005c00c 0x8>; <0x005c00c 0x8>; reg-names = "apcs-c0-rcg-base", "apcs-c1-rcg-base", reg-names = "apcs-c1-rcg-base", "apcs-c0-rcg-base", "apcs-cci-rcg-base", "efuse"; "apcs-cci-rcg-base", "efuse"; vdd-c0-supply = <&apc_vreg_corner>; vdd-c0-supply = <&apc_vreg_corner>; vdd-c1-supply = <&apc_vreg_corner>; vdd-c1-supply = <&apc_vreg_corner>; Loading
drivers/clk/msm/clock-cpu-8939.c +86 −30 Original line number Original line Diff line number Diff line Loading @@ -203,6 +203,12 @@ static struct clk_lookup cpu_clocks_8939[] = { CLK_LIST(cci_clk), CLK_LIST(cci_clk), }; }; static struct clk_lookup cpu_clocks_8939_single_cluster[] = { CLK_LIST(a53ssmux_bc), CLK_LIST(a53_bc_clk), }; static struct mux_div_clk *a53ssmux[] = {&a53ssmux_bc, static struct mux_div_clk *a53ssmux[] = {&a53ssmux_bc, &a53ssmux_lc, &a53ssmux_cci}; &a53ssmux_lc, &a53ssmux_cci}; Loading Loading @@ -516,30 +522,33 @@ static int add_opp(struct clk *c, struct device *cpudev, struct device *vregdev, return 0; return 0; } } static void print_opp_table(int a53_c0_cpu, int a53_c1_cpu) static void print_opp_table(int a53_c0_cpu, int a53_c1_cpu, bool single_cluster) { { struct dev_pm_opp *oppfmax, *oppfmin; struct dev_pm_opp *oppfmax, *oppfmin; unsigned long apc0_fmax, apc1_fmax, apc0_fmin, apc1_fmin; unsigned long apc0_fmax, apc1_fmax, apc0_fmin, apc1_fmin; if (!single_cluster) { apc0_fmax = a53_lc_clk.c.fmax[a53_lc_clk.c.num_fmax - 1]; apc0_fmax = a53_lc_clk.c.fmax[a53_lc_clk.c.num_fmax - 1]; apc1_fmax = a53_bc_clk.c.fmax[a53_bc_clk.c.num_fmax - 1]; apc0_fmin = a53_lc_clk.c.fmax[1]; apc0_fmin = a53_lc_clk.c.fmax[1]; } apc1_fmax = a53_bc_clk.c.fmax[a53_bc_clk.c.num_fmax - 1]; apc1_fmin = a53_bc_clk.c.fmax[1]; apc1_fmin = a53_bc_clk.c.fmax[1]; rcu_read_lock(); rcu_read_lock(); if (!single_cluster) { oppfmax = dev_pm_opp_find_freq_exact(get_cpu_device(a53_c0_cpu), oppfmax = dev_pm_opp_find_freq_exact(get_cpu_device(a53_c0_cpu), apc0_fmax, true); apc0_fmax, true); oppfmin = dev_pm_opp_find_freq_exact(get_cpu_device(a53_c0_cpu), oppfmin = dev_pm_opp_find_freq_exact(get_cpu_device(a53_c0_cpu), apc0_fmin, true); apc0_fmin, true); /* /* * One time information during boot. Important to know that this looks * One time information during boot. Important to know that this * sane since it can eventually make its way to the scheduler. * looks sane since it can eventually make its way to the * scheduler. */ */ pr_info("clock_cpu: a53_c0: OPP voltage for %lu: %ld\n", apc0_fmin, pr_info("clock_cpu: a53_c0: OPP voltage for %lu: %ld\n", dev_pm_opp_get_voltage(oppfmin)); apc0_fmin, dev_pm_opp_get_voltage(oppfmin)); pr_info("clock_cpu: a53_c0: OPP voltage for %lu: %ld\n", apc0_fmax, pr_info("clock_cpu: a53_c0: OPP voltage for %lu: %ld\n", dev_pm_opp_get_voltage(oppfmax)); apc0_fmax, dev_pm_opp_get_voltage(oppfmax)); } oppfmax = dev_pm_opp_find_freq_exact(get_cpu_device(a53_c1_cpu), oppfmax = dev_pm_opp_find_freq_exact(get_cpu_device(a53_c1_cpu), apc1_fmax, true); apc1_fmax, true); oppfmin = dev_pm_opp_find_freq_exact(get_cpu_device(a53_c1_cpu), oppfmin = dev_pm_opp_find_freq_exact(get_cpu_device(a53_c1_cpu), Loading @@ -551,16 +560,19 @@ static void print_opp_table(int a53_c0_cpu, int a53_c1_cpu) rcu_read_unlock(); rcu_read_unlock(); } } static void populate_opp_table(struct platform_device *pdev) static void populate_opp_table(struct platform_device *pdev, bool single_cluster) { { struct platform_device *apc0_dev, *apc1_dev; struct platform_device *apc0_dev, *apc1_dev; struct device_node *apc0_node, *apc1_node; struct device_node *apc0_node, *apc1_node; unsigned long apc0_fmax, apc1_fmax; unsigned long apc0_fmax, apc1_fmax; int cpu, a53_c0_cpu, a53_c1_cpu; int cpu, a53_c0_cpu, a53_c1_cpu; apc0_node = of_parse_phandle(pdev->dev.of_node, "vdd-c0-supply", 0); if (!single_cluster) apc0_node = of_parse_phandle(pdev->dev.of_node, "vdd-c0-supply", 0); apc1_node = of_parse_phandle(pdev->dev.of_node, "vdd-c1-supply", 0); apc1_node = of_parse_phandle(pdev->dev.of_node, "vdd-c1-supply", 0); if (!apc0_node) { if (!apc0_node && !single_cluster) { pr_err("can't find the apc0 dt node.\n"); pr_err("can't find the apc0 dt node.\n"); return; return; } } Loading @@ -568,10 +580,11 @@ static void populate_opp_table(struct platform_device *pdev) pr_err("can't find the apc1 dt node.\n"); pr_err("can't find the apc1 dt node.\n"); return; return; } } if (!single_cluster) apc0_dev = of_find_device_by_node(apc0_node); apc0_dev = of_find_device_by_node(apc0_node); apc1_dev = of_find_device_by_node(apc1_node); apc1_dev = of_find_device_by_node(apc1_node); if (!apc0_dev) { if (!apc1_dev && !single_cluster) { pr_err("can't find the apc0 device node.\n"); pr_err("can't find the apc0 device node.\n"); return; return; } } Loading @@ -580,7 +593,9 @@ static void populate_opp_table(struct platform_device *pdev) return; return; } } if (!single_cluster) apc0_fmax = a53_lc_clk.c.fmax[a53_lc_clk.c.num_fmax - 1]; apc0_fmax = a53_lc_clk.c.fmax[a53_lc_clk.c.num_fmax - 1]; apc1_fmax = a53_bc_clk.c.fmax[a53_bc_clk.c.num_fmax - 1]; apc1_fmax = a53_bc_clk.c.fmax[a53_bc_clk.c.num_fmax - 1]; for_each_possible_cpu(cpu) { for_each_possible_cpu(cpu) { Loading @@ -590,7 +605,7 @@ static void populate_opp_table(struct platform_device *pdev) WARN(add_opp(&a53_bc_clk.c, get_cpu_device(cpu), WARN(add_opp(&a53_bc_clk.c, get_cpu_device(cpu), &apc1_dev->dev, apc1_fmax), &apc1_dev->dev, apc1_fmax), "Failed to add OPP levels for A53 big cluster\n"); "Failed to add OPP levels for A53 big cluster\n"); } else if (cpu/4 == 1) { } else if (cpu/4 == 1 && !single_cluster) { a53_c0_cpu = cpu; a53_c0_cpu = cpu; WARN(add_opp(&a53_lc_clk.c, get_cpu_device(cpu), WARN(add_opp(&a53_lc_clk.c, get_cpu_device(cpu), &apc0_dev->dev, apc0_fmax), &apc0_dev->dev, apc0_fmax), Loading @@ -602,7 +617,8 @@ static void populate_opp_table(struct platform_device *pdev) pr_info("clock-cpu-8939: OPP tables populated (cpu %d and %d)", pr_info("clock-cpu-8939: OPP tables populated (cpu %d and %d)", a53_c0_cpu, a53_c1_cpu); a53_c0_cpu, a53_c1_cpu); print_opp_table(a53_c0_cpu, a53_c1_cpu); print_opp_table(a53_c0_cpu, a53_c1_cpu, single_cluster); } } static void config_pll(int mux_id) static void config_pll(int mux_id) Loading Loading @@ -644,18 +660,47 @@ static int clock_8939_pm_event(struct notifier_block *this, return NOTIFY_DONE; return NOTIFY_DONE; } } static int clock_8939_pm_event_single_cluster(struct notifier_block *this, unsigned long event, void *ptr) { switch (event) { case PM_POST_HIBERNATION: case PM_POST_SUSPEND: clk_unprepare(&a53_bc_clk.c); break; case PM_HIBERNATION_PREPARE: case PM_SUSPEND_PREPARE: clk_prepare(&a53_bc_clk.c); break; default: break; } return NOTIFY_DONE; } static struct notifier_block clock_8939_pm_notifier = { static struct notifier_block clock_8939_pm_notifier = { .notifier_call = clock_8939_pm_event, .notifier_call = clock_8939_pm_event, }; }; static struct notifier_block clock_8939_pm_notifier_single_cluster = { .notifier_call = clock_8939_pm_event_single_cluster, }; static int clock_a53_probe(struct platform_device *pdev) static int clock_a53_probe(struct platform_device *pdev) { { int speed_bin, version, rc, cpu, mux_id, rate; int speed_bin, version, rc, cpu, mux_id, rate; char prop_name[] = "qcom,speedX-bin-vX-XXX"; char prop_name[] = "qcom,speedX-bin-vX-XXX"; int mux_num; bool single_cluster; single_cluster = of_property_read_bool(pdev->dev.of_node, "qcom,num-cluster"); get_speed_bin(pdev, &speed_bin, &version); get_speed_bin(pdev, &speed_bin, &version); for (mux_id = 0; mux_id < A53SS_MUX_NUM; mux_id++) { mux_num = single_cluster ? A53SS_MUX_LC:A53SS_MUX_NUM; for (mux_id = 0; mux_id < mux_num; mux_id++) { rc = cpu_parse_devicetree(pdev, mux_id); rc = cpu_parse_devicetree(pdev, mux_id); if (rc) if (rc) return rc; return rc; Loading Loading @@ -683,16 +728,23 @@ static int clock_a53_probe(struct platform_device *pdev) dev_info(&pdev->dev, "Safe voltage plan loaded.\n"); dev_info(&pdev->dev, "Safe voltage plan loaded.\n"); } } } } if (single_cluster) rc = of_msm_clock_register(pdev->dev.of_node, cpu_clocks_8939_single_cluster, ARRAY_SIZE(cpu_clocks_8939_single_cluster)); else rc = of_msm_clock_register(pdev->dev.of_node, rc = of_msm_clock_register(pdev->dev.of_node, cpu_clocks_8939, ARRAY_SIZE(cpu_clocks_8939)); cpu_clocks_8939, ARRAY_SIZE(cpu_clocks_8939)); if (rc) { if (rc) { dev_err(&pdev->dev, "msm_clock_register failed\n"); dev_err(&pdev->dev, "msm_clock_register failed\n"); return rc; return rc; } } if (!single_cluster) { rate = clk_get_rate(&cci_clk.c); rate = clk_get_rate(&cci_clk.c); clk_set_rate(&cci_clk.c, rate); clk_set_rate(&cci_clk.c, rate); } for (mux_id = 0; mux_id < A53SS_MUX_CCI; mux_id++) { for (mux_id = 0; mux_id < A53SS_MUX_CCI; mux_id++) { /* Force a PLL reconfiguration */ /* Force a PLL reconfiguration */ Loading Loading @@ -724,15 +776,19 @@ static int clock_a53_probe(struct platform_device *pdev) a53_lc_clk.hw_low_power_ctrl = true; a53_lc_clk.hw_low_power_ctrl = true; a53_bc_clk.hw_low_power_ctrl = true; a53_bc_clk.hw_low_power_ctrl = true; if (single_cluster) register_pm_notifier(&clock_8939_pm_notifier_single_cluster); else register_pm_notifier(&clock_8939_pm_notifier); register_pm_notifier(&clock_8939_pm_notifier); populate_opp_table(pdev); populate_opp_table(pdev, single_cluster); return 0; return 0; } } static struct of_device_id clock_a53_match_table[] = { static struct of_device_id clock_a53_match_table[] = { {.compatible = "qcom,cpu-clock-8939"}, {.compatible = "qcom,cpu-clock-8939"}, {.compatible = "qcom,cpu-clock-gold"}, {} {} }; }; Loading