Loading Documentation/devicetree/bindings/arm/cpus.txt +1 −0 Original line number Diff line number Diff line Loading @@ -181,6 +181,7 @@ nodes to be present and contain the properties described below. "spin-table" "psci" "qcom,arm-cortex-acc" "qcom,8994-arm-cortex-acc" # On ARM 32-bit systems this property is optional and can be one of: "qcom,gcc-msm8660" Loading arch/arm/boot/dts/qcom/msm8994.dtsi +24 −16 Original line number Diff line number Diff line Loading @@ -66,7 +66,7 @@ device_type = "cpu"; compatible = "arm,cortex-a53"; reg = <0x0>; enable-method = "qcom,arm-cortex-acc"; enable-method = "qcom,8994-arm-cortex-acc"; qcom,acc = <&acc0>; next-level-cache = <&L2_0>; L2_0: l2-cache { Loading @@ -80,7 +80,7 @@ device_type = "cpu"; compatible = "arm,cortex-a53"; reg = <0x1>; enable-method = "qcom,arm-cortex-acc"; enable-method = "qcom,8994-arm-cortex-acc"; qcom,acc = <&acc1>; next-level-cache = <&L2_0>; }; Loading @@ -89,7 +89,7 @@ device_type = "cpu"; compatible = "arm,cortex-a53"; reg = <0x2>; enable-method = "qcom,arm-cortex-acc"; enable-method = "qcom,8994-arm-cortex-acc"; qcom,acc = <&acc2>; next-level-cache = <&L2_0>; }; Loading @@ -98,7 +98,7 @@ device_type = "cpu"; compatible = "arm,cortex-a53"; reg = <0x3>; enable-method = "qcom,arm-cortex-acc"; enable-method = "qcom,8994-arm-cortex-acc"; qcom,acc = <&acc3>; next-level-cache = <&L2_0>; }; Loading @@ -107,7 +107,7 @@ device_type = "cpu"; compatible = "arm,cortex-a57"; reg = <0x100>; enable-method = "qcom,arm-cortex-acc"; enable-method = "qcom,8994-arm-cortex-acc"; qcom,acc = <&acc4>; next-level-cache = <&L2_1>; L2_1: l2-cache { Loading @@ -121,7 +121,7 @@ device_type = "cpu"; compatible = "arm,cortex-a57"; reg = <0x101>; enable-method = "qcom,arm-cortex-acc"; enable-method = "qcom,8994-arm-cortex-acc"; qcom,acc = <&acc5>; next-level-cache = <&L2_1>; }; Loading @@ -130,7 +130,7 @@ device_type = "cpu"; compatible = "arm,cortex-a57"; reg = <0x102>; enable-method = "qcom,arm-cortex-acc"; enable-method = "qcom,8994-arm-cortex-acc"; qcom,acc = <&acc6>; next-level-cache = <&L2_1>; }; Loading @@ -139,7 +139,7 @@ device_type = "cpu"; compatible = "arm,cortex-a57"; reg = <0x103>; enable-method = "qcom,arm-cortex-acc"; enable-method = "qcom,8994-arm-cortex-acc"; qcom,acc = <&acc7>; next-level-cache = <&L2_1>; }; Loading Loading @@ -210,49 +210,57 @@ acc0:clock-controller@f908b004 { compatible = "qcom,arm-cortex-acc"; reg = <0xf908b000 0x1000>, reg = <0xf9070000 0x1000>, <0xf908b000 0x1000>, <0xf900b000 0x1000>; }; acc1:clock-controller@f909b004 { compatible = "qcom,arm-cortex-acc"; reg = <0xf909b000 0x1000>, reg = <0xf9071000 0x1000>, <0xf909b000 0x1000>, <0xf900b000 0x1000>; }; acc2:clock-controller@f90ab004 { compatible = "qcom,arm-cortex-acc"; reg = <0xf90ab000 0x1000>, reg = <0xf9072000 0x1000>, <0xf90ab000 0x1000>, <0xf900b000 0x1000>; }; acc3:clock-controller@f90bb004 { compatible = "qcom,arm-cortex-acc"; reg = <0xf90bb000 0x1000>, reg = <0xf9073000 0x1000>, <0xf90bb000 0x1000>, <0xf900b000 0x1000>; }; acc4:clock-controller@f90cb004 { compatible = "qcom,arm-cortex-acc"; reg = <0xf90cb000 0x1000>, reg = <0xf9074000 0x1000>, <0xf90cb000 0x1000>, <0xf900b000 0x1000>; }; acc5:clock-controller@f90db004 { compatible = "qcom,arm-cortex-acc"; reg = <0xf90db000 0x1000>, reg = <0xf9075000 0x1000>, <0xf90db000 0x1000>, <0xf900b000 0x1000>; }; acc6:clock-controller@f90eb004 { compatible = "qcom,arm-cortex-acc"; reg = <0xf90eb000 0x1000>, reg = <0xf9076000 0x1000>, <0xf90eb000 0x1000>, <0xf900b000 0x1000>; }; acc7:clock-controller@f90fb004 { compatible = "qcom,arm-cortex-acc"; reg = <0xf90fb000 0x1000>, reg = <0xf9077000 0x1000>, <0xf90fb000 0x1000>, <0xf900b000 0x1000>; }; Loading drivers/soc/qcom/cpu_ops.c +32 −0 Original line number Diff line number Diff line Loading @@ -140,6 +140,25 @@ static int msm_cpu_boot(unsigned int cpu) return secondary_pen_release(cpu); } static int msm8994_cpu_boot(unsigned int cpu) { int ret = 0; if (per_cpu(cold_boot_done, cpu) == false) { if (of_board_is_sim()) { ret = msm_unclamp_secondary_arm_cpu_sim(cpu); if (ret) return ret; } else { ret = msm8994_unclamp_secondary_arm_cpu(cpu); if (ret) return ret; } per_cpu(cold_boot_done, cpu) = true; } return secondary_pen_release(cpu); } void msm_cpu_postboot(void) { /* Loading Loading @@ -186,3 +205,16 @@ static const struct cpu_operations msm_cortex_a_ops = { .cpu_suspend = msm_pm_collapse, }; CPU_METHOD_OF_DECLARE(msm_cortex_a_ops, &msm_cortex_a_ops); static const struct cpu_operations msm8994_cortex_a_ops = { .name = "qcom,8994-arm-cortex-acc", .cpu_init = msm_cpu_init, .cpu_prepare = msm_cpu_prepare, .cpu_boot = msm8994_cpu_boot, .cpu_postboot = msm_cpu_postboot, #ifdef CONFIG_HOTPLUG_CPU .cpu_die = msm_wfi_cpu_die, #endif .cpu_suspend = msm_pm_collapse, }; CPU_METHOD_OF_DECLARE(msm8994_cortex_a_ops, &msm8994_cortex_a_ops); drivers/soc/qcom/cpu_pwr_ctl.c +109 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ /* CPU power domain register offsets */ #define CPU_PWR_CTL 0x4 #define CPU_PWR_GATE_CTL 0x14 #define LDO_BHS_PWR_CTL 0x28 /* L2 power domain register offsets */ #define L2_PWR_CTL_OVERRIDE 0xc Loading Loading @@ -210,6 +211,114 @@ static int power_on_l2_cache(struct device_node *l2ccc_node) return -EIO; } int msm8994_unclamp_secondary_arm_cpu(unsigned int cpu) { int ret = 0; struct device_node *cpu_node, *acc_node, *l2_node, *l2ccc_node; void __iomem *acc_reg, *ldo_bhs_reg; cpu_node = of_get_cpu_node(cpu, NULL); if (!cpu_node) return -ENODEV; acc_node = of_parse_phandle(cpu_node, "qcom,acc", 0); if (!acc_node) { ret = -ENODEV; goto out_acc; } l2_node = of_parse_phandle(cpu_node, "next-level-cache", 0); if (!l2_node) { ret = -ENODEV; goto out_l2; } l2ccc_node = of_parse_phandle(l2_node, "power-domain", 0); if (!l2ccc_node) { ret = -ENODEV; goto out_l2; } /* * Ensure L2-cache of the CPU is powered on before * unclamping cpu power rails. */ ret = power_on_l2_cache(l2ccc_node); if (ret) { pr_err("L2 cache power up failed for CPU%d\n", cpu); goto out_l2ccc; } ldo_bhs_reg = of_iomap(acc_node, 0); if (!ldo_bhs_reg) { ret = -ENOMEM; goto out_bhs_reg; } acc_reg = of_iomap(acc_node, 1); if (!acc_reg) { ret = -ENOMEM; goto out_acc_reg; } /* Bypass LDO */ writel_relaxed(0x00000001, ldo_bhs_reg + LDO_BHS_PWR_CTL); mb(); udelay(2); /* Assert head switch enable few */ writel_relaxed(0x00000001, acc_reg + CPU_PWR_GATE_CTL); mb(); udelay(2); /* Assert head switch enable rest */ writel_relaxed(0x00000003, acc_reg + CPU_PWR_GATE_CTL); mb(); udelay(2); /* De-assert coremem clamp. This is asserted by default */ writel_relaxed(0x00000079, acc_reg + CPU_PWR_CTL); mb(); /* Close coremem array gdhs */ writel_relaxed(0x0000007D, acc_reg + CPU_PWR_CTL); mb(); udelay(2); /* De-assert clamp */ writel_relaxed(0x0000003D, acc_reg + CPU_PWR_CTL); mb(); /* De-assert clamp */ writel_relaxed(0x0000003C, acc_reg + CPU_PWR_CTL); mb(); udelay(2); /* De-assert core0 reset */ writel_relaxed(0x0000000C, acc_reg + CPU_PWR_CTL); mb(); /* Assert PWRDUP */ writel_relaxed(0x0000008C, acc_reg + CPU_PWR_CTL); mb(); iounmap(acc_reg); out_acc_reg: iounmap(ldo_bhs_reg); out_bhs_reg: of_node_put(l2ccc_node); out_l2ccc: of_node_put(l2_node); out_l2: of_node_put(acc_node); out_acc: of_node_put(cpu_node); return ret; } int msm_unclamp_secondary_arm_cpu(unsigned int cpu) { Loading include/soc/qcom/cpu_pwr_ctl.h +5 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #ifdef CONFIG_MSM_CPU_PWR_CTL int msm_unclamp_secondary_arm_cpu_sim(unsigned int cpu); int msm_unclamp_secondary_arm_cpu(unsigned int cpu); int msm8994_unclamp_secondary_arm_cpu(unsigned int cpu); #else static inline int msm_unclamp_secondary_arm_cpu_sim(unsigned int cpu) { Loading @@ -25,5 +26,9 @@ static inline int msm_unclamp_secondary_arm_cpu(unsigned int cpu) { return 0; } static inline int msm8994_unclamp_secondary_arm_cpu(unsigned int cpu) { return 0; } #endif #endif /*MSM_CPU_SUBSYS_H_*/ Loading
Documentation/devicetree/bindings/arm/cpus.txt +1 −0 Original line number Diff line number Diff line Loading @@ -181,6 +181,7 @@ nodes to be present and contain the properties described below. "spin-table" "psci" "qcom,arm-cortex-acc" "qcom,8994-arm-cortex-acc" # On ARM 32-bit systems this property is optional and can be one of: "qcom,gcc-msm8660" Loading
arch/arm/boot/dts/qcom/msm8994.dtsi +24 −16 Original line number Diff line number Diff line Loading @@ -66,7 +66,7 @@ device_type = "cpu"; compatible = "arm,cortex-a53"; reg = <0x0>; enable-method = "qcom,arm-cortex-acc"; enable-method = "qcom,8994-arm-cortex-acc"; qcom,acc = <&acc0>; next-level-cache = <&L2_0>; L2_0: l2-cache { Loading @@ -80,7 +80,7 @@ device_type = "cpu"; compatible = "arm,cortex-a53"; reg = <0x1>; enable-method = "qcom,arm-cortex-acc"; enable-method = "qcom,8994-arm-cortex-acc"; qcom,acc = <&acc1>; next-level-cache = <&L2_0>; }; Loading @@ -89,7 +89,7 @@ device_type = "cpu"; compatible = "arm,cortex-a53"; reg = <0x2>; enable-method = "qcom,arm-cortex-acc"; enable-method = "qcom,8994-arm-cortex-acc"; qcom,acc = <&acc2>; next-level-cache = <&L2_0>; }; Loading @@ -98,7 +98,7 @@ device_type = "cpu"; compatible = "arm,cortex-a53"; reg = <0x3>; enable-method = "qcom,arm-cortex-acc"; enable-method = "qcom,8994-arm-cortex-acc"; qcom,acc = <&acc3>; next-level-cache = <&L2_0>; }; Loading @@ -107,7 +107,7 @@ device_type = "cpu"; compatible = "arm,cortex-a57"; reg = <0x100>; enable-method = "qcom,arm-cortex-acc"; enable-method = "qcom,8994-arm-cortex-acc"; qcom,acc = <&acc4>; next-level-cache = <&L2_1>; L2_1: l2-cache { Loading @@ -121,7 +121,7 @@ device_type = "cpu"; compatible = "arm,cortex-a57"; reg = <0x101>; enable-method = "qcom,arm-cortex-acc"; enable-method = "qcom,8994-arm-cortex-acc"; qcom,acc = <&acc5>; next-level-cache = <&L2_1>; }; Loading @@ -130,7 +130,7 @@ device_type = "cpu"; compatible = "arm,cortex-a57"; reg = <0x102>; enable-method = "qcom,arm-cortex-acc"; enable-method = "qcom,8994-arm-cortex-acc"; qcom,acc = <&acc6>; next-level-cache = <&L2_1>; }; Loading @@ -139,7 +139,7 @@ device_type = "cpu"; compatible = "arm,cortex-a57"; reg = <0x103>; enable-method = "qcom,arm-cortex-acc"; enable-method = "qcom,8994-arm-cortex-acc"; qcom,acc = <&acc7>; next-level-cache = <&L2_1>; }; Loading Loading @@ -210,49 +210,57 @@ acc0:clock-controller@f908b004 { compatible = "qcom,arm-cortex-acc"; reg = <0xf908b000 0x1000>, reg = <0xf9070000 0x1000>, <0xf908b000 0x1000>, <0xf900b000 0x1000>; }; acc1:clock-controller@f909b004 { compatible = "qcom,arm-cortex-acc"; reg = <0xf909b000 0x1000>, reg = <0xf9071000 0x1000>, <0xf909b000 0x1000>, <0xf900b000 0x1000>; }; acc2:clock-controller@f90ab004 { compatible = "qcom,arm-cortex-acc"; reg = <0xf90ab000 0x1000>, reg = <0xf9072000 0x1000>, <0xf90ab000 0x1000>, <0xf900b000 0x1000>; }; acc3:clock-controller@f90bb004 { compatible = "qcom,arm-cortex-acc"; reg = <0xf90bb000 0x1000>, reg = <0xf9073000 0x1000>, <0xf90bb000 0x1000>, <0xf900b000 0x1000>; }; acc4:clock-controller@f90cb004 { compatible = "qcom,arm-cortex-acc"; reg = <0xf90cb000 0x1000>, reg = <0xf9074000 0x1000>, <0xf90cb000 0x1000>, <0xf900b000 0x1000>; }; acc5:clock-controller@f90db004 { compatible = "qcom,arm-cortex-acc"; reg = <0xf90db000 0x1000>, reg = <0xf9075000 0x1000>, <0xf90db000 0x1000>, <0xf900b000 0x1000>; }; acc6:clock-controller@f90eb004 { compatible = "qcom,arm-cortex-acc"; reg = <0xf90eb000 0x1000>, reg = <0xf9076000 0x1000>, <0xf90eb000 0x1000>, <0xf900b000 0x1000>; }; acc7:clock-controller@f90fb004 { compatible = "qcom,arm-cortex-acc"; reg = <0xf90fb000 0x1000>, reg = <0xf9077000 0x1000>, <0xf90fb000 0x1000>, <0xf900b000 0x1000>; }; Loading
drivers/soc/qcom/cpu_ops.c +32 −0 Original line number Diff line number Diff line Loading @@ -140,6 +140,25 @@ static int msm_cpu_boot(unsigned int cpu) return secondary_pen_release(cpu); } static int msm8994_cpu_boot(unsigned int cpu) { int ret = 0; if (per_cpu(cold_boot_done, cpu) == false) { if (of_board_is_sim()) { ret = msm_unclamp_secondary_arm_cpu_sim(cpu); if (ret) return ret; } else { ret = msm8994_unclamp_secondary_arm_cpu(cpu); if (ret) return ret; } per_cpu(cold_boot_done, cpu) = true; } return secondary_pen_release(cpu); } void msm_cpu_postboot(void) { /* Loading Loading @@ -186,3 +205,16 @@ static const struct cpu_operations msm_cortex_a_ops = { .cpu_suspend = msm_pm_collapse, }; CPU_METHOD_OF_DECLARE(msm_cortex_a_ops, &msm_cortex_a_ops); static const struct cpu_operations msm8994_cortex_a_ops = { .name = "qcom,8994-arm-cortex-acc", .cpu_init = msm_cpu_init, .cpu_prepare = msm_cpu_prepare, .cpu_boot = msm8994_cpu_boot, .cpu_postboot = msm_cpu_postboot, #ifdef CONFIG_HOTPLUG_CPU .cpu_die = msm_wfi_cpu_die, #endif .cpu_suspend = msm_pm_collapse, }; CPU_METHOD_OF_DECLARE(msm8994_cortex_a_ops, &msm8994_cortex_a_ops);
drivers/soc/qcom/cpu_pwr_ctl.c +109 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ /* CPU power domain register offsets */ #define CPU_PWR_CTL 0x4 #define CPU_PWR_GATE_CTL 0x14 #define LDO_BHS_PWR_CTL 0x28 /* L2 power domain register offsets */ #define L2_PWR_CTL_OVERRIDE 0xc Loading Loading @@ -210,6 +211,114 @@ static int power_on_l2_cache(struct device_node *l2ccc_node) return -EIO; } int msm8994_unclamp_secondary_arm_cpu(unsigned int cpu) { int ret = 0; struct device_node *cpu_node, *acc_node, *l2_node, *l2ccc_node; void __iomem *acc_reg, *ldo_bhs_reg; cpu_node = of_get_cpu_node(cpu, NULL); if (!cpu_node) return -ENODEV; acc_node = of_parse_phandle(cpu_node, "qcom,acc", 0); if (!acc_node) { ret = -ENODEV; goto out_acc; } l2_node = of_parse_phandle(cpu_node, "next-level-cache", 0); if (!l2_node) { ret = -ENODEV; goto out_l2; } l2ccc_node = of_parse_phandle(l2_node, "power-domain", 0); if (!l2ccc_node) { ret = -ENODEV; goto out_l2; } /* * Ensure L2-cache of the CPU is powered on before * unclamping cpu power rails. */ ret = power_on_l2_cache(l2ccc_node); if (ret) { pr_err("L2 cache power up failed for CPU%d\n", cpu); goto out_l2ccc; } ldo_bhs_reg = of_iomap(acc_node, 0); if (!ldo_bhs_reg) { ret = -ENOMEM; goto out_bhs_reg; } acc_reg = of_iomap(acc_node, 1); if (!acc_reg) { ret = -ENOMEM; goto out_acc_reg; } /* Bypass LDO */ writel_relaxed(0x00000001, ldo_bhs_reg + LDO_BHS_PWR_CTL); mb(); udelay(2); /* Assert head switch enable few */ writel_relaxed(0x00000001, acc_reg + CPU_PWR_GATE_CTL); mb(); udelay(2); /* Assert head switch enable rest */ writel_relaxed(0x00000003, acc_reg + CPU_PWR_GATE_CTL); mb(); udelay(2); /* De-assert coremem clamp. This is asserted by default */ writel_relaxed(0x00000079, acc_reg + CPU_PWR_CTL); mb(); /* Close coremem array gdhs */ writel_relaxed(0x0000007D, acc_reg + CPU_PWR_CTL); mb(); udelay(2); /* De-assert clamp */ writel_relaxed(0x0000003D, acc_reg + CPU_PWR_CTL); mb(); /* De-assert clamp */ writel_relaxed(0x0000003C, acc_reg + CPU_PWR_CTL); mb(); udelay(2); /* De-assert core0 reset */ writel_relaxed(0x0000000C, acc_reg + CPU_PWR_CTL); mb(); /* Assert PWRDUP */ writel_relaxed(0x0000008C, acc_reg + CPU_PWR_CTL); mb(); iounmap(acc_reg); out_acc_reg: iounmap(ldo_bhs_reg); out_bhs_reg: of_node_put(l2ccc_node); out_l2ccc: of_node_put(l2_node); out_l2: of_node_put(acc_node); out_acc: of_node_put(cpu_node); return ret; } int msm_unclamp_secondary_arm_cpu(unsigned int cpu) { Loading
include/soc/qcom/cpu_pwr_ctl.h +5 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #ifdef CONFIG_MSM_CPU_PWR_CTL int msm_unclamp_secondary_arm_cpu_sim(unsigned int cpu); int msm_unclamp_secondary_arm_cpu(unsigned int cpu); int msm8994_unclamp_secondary_arm_cpu(unsigned int cpu); #else static inline int msm_unclamp_secondary_arm_cpu_sim(unsigned int cpu) { Loading @@ -25,5 +26,9 @@ static inline int msm_unclamp_secondary_arm_cpu(unsigned int cpu) { return 0; } static inline int msm8994_unclamp_secondary_arm_cpu(unsigned int cpu) { return 0; } #endif #endif /*MSM_CPU_SUBSYS_H_*/