Loading Documentation/devicetree/bindings/arm/cpus.txt +5 −0 Original line number Diff line number Diff line Loading @@ -211,6 +211,11 @@ nodes to be present and contain the properties described below. Value type: <phandle> Definition: Specifies the ACC[2] node associated with this CPU. - qcom,ldo Usage: required for systems that need LDO configuration. Value type: <phandle> Definition: Specifies the LDO reference node associated with this cpu. Example 1 (dual-cluster big.LITTLE system 32-bit): Loading Documentation/devicetree/bindings/arm/msm/cpu-ldo-ret-8994.txt 0 → 100644 +22 −0 Original line number Diff line number Diff line *8994 CPU LDO Retention Voltage Configuration This device is used to program the appropriate LDO voltage for 8994 target from the pre-programmed register. Required properties: - compatible: Must be "qcom,8994-cpu-ldo-vref" - reg: The register holds the base address to LDO_BHS. Use this register base to configure the LDO for all the cpus. - qcom,ldo-vref-ret: Value to which the ldo voltage reference needs to be programmed. Value to be used is encoded. 0x20 = 0.5V and 0x2a = 0x55V Example: ldo0:ldo-vref@f9070000 { compatible = "qcom,8994-cpu-ldo-vref"; reg = <0xf9070000 0x30>, qcom,ldo-vref-ret = <0x20>; }; drivers/soc/qcom/cpu_ops.c +18 −1 Original line number Diff line number Diff line Loading @@ -126,6 +126,20 @@ static int __init msm_cpu_prepare(unsigned int cpu) return 0; } static int __init msm8994_cpu_prepare(unsigned int cpu) { int ret; if (per_cpu(cold_boot_done, 0) == false) { ret = msm8994_cpu_ldo_config(0); if (ret) return ret; } return msm_cpu_prepare(cpu); } static int msm_cpu_boot(unsigned int cpu) { int ret = 0; Loading Loading @@ -159,6 +173,9 @@ static int msm8994_cpu_boot(unsigned int cpu) if (ret) return ret; } ret = msm8994_cpu_ldo_config(cpu); if (ret) return ret; per_cpu(cold_boot_done, cpu) = true; } return secondary_pen_release(cpu); Loading Loading @@ -217,7 +234,7 @@ 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_prepare = msm8994_cpu_prepare, .cpu_boot = msm8994_cpu_boot, .cpu_postboot = msm_cpu_postboot, #ifdef CONFIG_HOTPLUG_CPU Loading drivers/soc/qcom/cpu_pwr_ctl.c +85 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,10 @@ #define L2_SPM_STS 0xc #define L2_VREG_CTL 0x1c #define APC_LDO_CFG1 0xc #define APC_LDO_CFG2 0x10 #define APC_LDO_VREF_CFG 0x4 /* * struct msm_l2ccc_of_info: represents of data for l2 cache clock controller. * @compat: compat string for l2 cache clock controller Loading Loading @@ -288,6 +292,87 @@ static int power_on_l2_cache(struct device_node *l2ccc_node, int cpu) return -EIO; } int msm8994_cpu_ldo_config(unsigned int cpu) { struct device_node *cpu_node, *ldo_node; void __iomem *ldo_bhs_reg_base; u32 ldo_vref_ret = 0; u32 ref_val = 0; int ret = 0; u32 val; cpu_node = of_get_cpu_node(cpu, NULL); if (!cpu_node) return -ENODEV; ldo_node = of_parse_phandle(cpu_node, "qcom,ldo", 0); if (!ldo_node) { pr_debug("LDO is not configured to enable retention\n"); goto exit_cpu_node; } ldo_bhs_reg_base = of_iomap(ldo_node, 0); if (!ldo_bhs_reg_base) { pr_err("LDO configuration failed due to iomap failure\n"); ret = -ENOMEM; goto exit_cpu_node; } ret = of_property_read_u32(ldo_node, "qcom,ldo-vref-ret", &ref_val); if (ret) { pr_err("Failed to get LDO Reference voltage for CPU%u\n", cpu); BUG_ON(1); } /* Program LDO CFG registers */ val = readl_relaxed(ldo_bhs_reg_base + APC_LDO_CFG1); val = (val & 0xffffff00) | 0xc2; writel_relaxed(val, ldo_bhs_reg_base + APC_LDO_CFG1); val = readl_relaxed(ldo_bhs_reg_base + APC_LDO_CFG1); val = (val & 0xffff00ff) | (0x98 << 8); writel_relaxed(val, ldo_bhs_reg_base + APC_LDO_CFG1); val = readl_relaxed(ldo_bhs_reg_base + APC_LDO_CFG2); val = (val & 0xffffff00) | 0x60; writel_relaxed(val, ldo_bhs_reg_base + APC_LDO_CFG2); val = readl_relaxed(ldo_bhs_reg_base + APC_LDO_CFG2); val = (val & 0xff00ffff) | (0x4a << 16); writel_relaxed(val, ldo_bhs_reg_base + APC_LDO_CFG2); /* Bring LDO out of reset */ ldo_vref_ret = readl_relaxed(ldo_bhs_reg_base + APC_LDO_VREF_CFG); ldo_vref_ret &= ~BIT(16); writel_relaxed(ldo_vref_ret, ldo_bhs_reg_base + APC_LDO_VREF_CFG); /* Program the retention voltage */ ldo_vref_ret = readl_relaxed(ldo_bhs_reg_base + APC_LDO_VREF_CFG); ldo_vref_ret = (ldo_vref_ret & 0xffff80ff) | (ref_val << 8); writel_relaxed(ldo_vref_ret, ldo_bhs_reg_base + APC_LDO_VREF_CFG); /* Write the sequence to latch on the LDO voltage */ writel_relaxed(0x0, ldo_bhs_reg_base); writel_relaxed(0x1, ldo_bhs_reg_base); /* After writing 1 to the UPDATE register, '1 xo clk cycle' delay * is required for the update to take effect. This delay needs to * start after the reg write is complete. Make sure that the reg * write is complete using a memory barrier */ mb(); usleep(1); writel_relaxed(0x0, ldo_bhs_reg_base); /* Use a memory barrier to make sure the reg write is complete before * the node is unmapped. */ mb(); of_node_put(ldo_node); iounmap(ldo_bhs_reg_base); exit_cpu_node: of_node_put(cpu_node); return ret; } int msm8994_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 @@ -17,6 +17,7 @@ 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); int msm8994_cpu_ldo_config(unsigned int cpu); #else static inline int msm_unclamp_secondary_arm_cpu_sim(unsigned int cpu) { Loading @@ -30,5 +31,9 @@ static inline int msm8994_unclamp_secondary_arm_cpu(unsigned int cpu) { return 0; } static inline int msm8994_cpu_ldo_config(unsigned int cpu) { return 0; } #endif #endif /*MSM_CPU_SUBSYS_H_*/ Loading
Documentation/devicetree/bindings/arm/cpus.txt +5 −0 Original line number Diff line number Diff line Loading @@ -211,6 +211,11 @@ nodes to be present and contain the properties described below. Value type: <phandle> Definition: Specifies the ACC[2] node associated with this CPU. - qcom,ldo Usage: required for systems that need LDO configuration. Value type: <phandle> Definition: Specifies the LDO reference node associated with this cpu. Example 1 (dual-cluster big.LITTLE system 32-bit): Loading
Documentation/devicetree/bindings/arm/msm/cpu-ldo-ret-8994.txt 0 → 100644 +22 −0 Original line number Diff line number Diff line *8994 CPU LDO Retention Voltage Configuration This device is used to program the appropriate LDO voltage for 8994 target from the pre-programmed register. Required properties: - compatible: Must be "qcom,8994-cpu-ldo-vref" - reg: The register holds the base address to LDO_BHS. Use this register base to configure the LDO for all the cpus. - qcom,ldo-vref-ret: Value to which the ldo voltage reference needs to be programmed. Value to be used is encoded. 0x20 = 0.5V and 0x2a = 0x55V Example: ldo0:ldo-vref@f9070000 { compatible = "qcom,8994-cpu-ldo-vref"; reg = <0xf9070000 0x30>, qcom,ldo-vref-ret = <0x20>; };
drivers/soc/qcom/cpu_ops.c +18 −1 Original line number Diff line number Diff line Loading @@ -126,6 +126,20 @@ static int __init msm_cpu_prepare(unsigned int cpu) return 0; } static int __init msm8994_cpu_prepare(unsigned int cpu) { int ret; if (per_cpu(cold_boot_done, 0) == false) { ret = msm8994_cpu_ldo_config(0); if (ret) return ret; } return msm_cpu_prepare(cpu); } static int msm_cpu_boot(unsigned int cpu) { int ret = 0; Loading Loading @@ -159,6 +173,9 @@ static int msm8994_cpu_boot(unsigned int cpu) if (ret) return ret; } ret = msm8994_cpu_ldo_config(cpu); if (ret) return ret; per_cpu(cold_boot_done, cpu) = true; } return secondary_pen_release(cpu); Loading Loading @@ -217,7 +234,7 @@ 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_prepare = msm8994_cpu_prepare, .cpu_boot = msm8994_cpu_boot, .cpu_postboot = msm_cpu_postboot, #ifdef CONFIG_HOTPLUG_CPU Loading
drivers/soc/qcom/cpu_pwr_ctl.c +85 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,10 @@ #define L2_SPM_STS 0xc #define L2_VREG_CTL 0x1c #define APC_LDO_CFG1 0xc #define APC_LDO_CFG2 0x10 #define APC_LDO_VREF_CFG 0x4 /* * struct msm_l2ccc_of_info: represents of data for l2 cache clock controller. * @compat: compat string for l2 cache clock controller Loading Loading @@ -288,6 +292,87 @@ static int power_on_l2_cache(struct device_node *l2ccc_node, int cpu) return -EIO; } int msm8994_cpu_ldo_config(unsigned int cpu) { struct device_node *cpu_node, *ldo_node; void __iomem *ldo_bhs_reg_base; u32 ldo_vref_ret = 0; u32 ref_val = 0; int ret = 0; u32 val; cpu_node = of_get_cpu_node(cpu, NULL); if (!cpu_node) return -ENODEV; ldo_node = of_parse_phandle(cpu_node, "qcom,ldo", 0); if (!ldo_node) { pr_debug("LDO is not configured to enable retention\n"); goto exit_cpu_node; } ldo_bhs_reg_base = of_iomap(ldo_node, 0); if (!ldo_bhs_reg_base) { pr_err("LDO configuration failed due to iomap failure\n"); ret = -ENOMEM; goto exit_cpu_node; } ret = of_property_read_u32(ldo_node, "qcom,ldo-vref-ret", &ref_val); if (ret) { pr_err("Failed to get LDO Reference voltage for CPU%u\n", cpu); BUG_ON(1); } /* Program LDO CFG registers */ val = readl_relaxed(ldo_bhs_reg_base + APC_LDO_CFG1); val = (val & 0xffffff00) | 0xc2; writel_relaxed(val, ldo_bhs_reg_base + APC_LDO_CFG1); val = readl_relaxed(ldo_bhs_reg_base + APC_LDO_CFG1); val = (val & 0xffff00ff) | (0x98 << 8); writel_relaxed(val, ldo_bhs_reg_base + APC_LDO_CFG1); val = readl_relaxed(ldo_bhs_reg_base + APC_LDO_CFG2); val = (val & 0xffffff00) | 0x60; writel_relaxed(val, ldo_bhs_reg_base + APC_LDO_CFG2); val = readl_relaxed(ldo_bhs_reg_base + APC_LDO_CFG2); val = (val & 0xff00ffff) | (0x4a << 16); writel_relaxed(val, ldo_bhs_reg_base + APC_LDO_CFG2); /* Bring LDO out of reset */ ldo_vref_ret = readl_relaxed(ldo_bhs_reg_base + APC_LDO_VREF_CFG); ldo_vref_ret &= ~BIT(16); writel_relaxed(ldo_vref_ret, ldo_bhs_reg_base + APC_LDO_VREF_CFG); /* Program the retention voltage */ ldo_vref_ret = readl_relaxed(ldo_bhs_reg_base + APC_LDO_VREF_CFG); ldo_vref_ret = (ldo_vref_ret & 0xffff80ff) | (ref_val << 8); writel_relaxed(ldo_vref_ret, ldo_bhs_reg_base + APC_LDO_VREF_CFG); /* Write the sequence to latch on the LDO voltage */ writel_relaxed(0x0, ldo_bhs_reg_base); writel_relaxed(0x1, ldo_bhs_reg_base); /* After writing 1 to the UPDATE register, '1 xo clk cycle' delay * is required for the update to take effect. This delay needs to * start after the reg write is complete. Make sure that the reg * write is complete using a memory barrier */ mb(); usleep(1); writel_relaxed(0x0, ldo_bhs_reg_base); /* Use a memory barrier to make sure the reg write is complete before * the node is unmapped. */ mb(); of_node_put(ldo_node); iounmap(ldo_bhs_reg_base); exit_cpu_node: of_node_put(cpu_node); return ret; } int msm8994_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 @@ -17,6 +17,7 @@ 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); int msm8994_cpu_ldo_config(unsigned int cpu); #else static inline int msm_unclamp_secondary_arm_cpu_sim(unsigned int cpu) { Loading @@ -30,5 +31,9 @@ static inline int msm8994_unclamp_secondary_arm_cpu(unsigned int cpu) { return 0; } static inline int msm8994_cpu_ldo_config(unsigned int cpu) { return 0; } #endif #endif /*MSM_CPU_SUBSYS_H_*/