Loading Documentation/devicetree/bindings/power/qcom/apm.txt +6 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,12 @@ Required properties "apc0-cpu0-spm", "apc0-cpu1-spm", "apc1-cpu0-spm", "apc1-cpu1-spm", "apc0-l2-spm", and "apc1-l2-spm". Optional properties - qcom,clock-source-override: Specify this property to request a switch of the APC0 and APC1 clock sources to GPLL0 before the APM switch begins and to switch back to the original clock source after the APM switch completes. MSM APM Users Required properties: Loading drivers/power/qcom/apm.c +48 −0 Original line number Diff line number Diff line Loading @@ -78,6 +78,14 @@ #define MSM_APM_DRIVER_NAME "qcom,msm-apm" asmlinkage int __invoke_psci_fn_smc(u64, u64, u64, u64); enum { CLOCK_ASSERT_ENABLE, CLOCK_ASSERT_DISABLE, CLOCK_ASSERT_TOGGLE, }; struct msm_apm_ctrl_dev { struct list_head list; struct device *dev; Loading @@ -88,6 +96,7 @@ struct msm_apm_ctrl_dev { void __iomem **apcs_spm_events_addr; void __iomem *apc0_pll_ctl_addr; void __iomem *apc1_pll_ctl_addr; bool clk_src_override; u32 version; struct dentry *debugfs; }; Loading Loading @@ -140,6 +149,12 @@ static int msm_apm_ctrl_devm_ioremap(struct platform_device *pdev, return -ENOMEM; } ctrl->clk_src_override = of_property_read_bool(dev->of_node, "qcom,clock-source-override"); if (ctrl->clk_src_override) dev_info(dev, "overriding clock sources across APM switch\n"); ctrl->version = readl_relaxed(ctrl->apcs_csr_base + APCS_VERSION); if (ctrl->version >= HMSS_VERSION_1P2) Loading Loading @@ -216,6 +231,23 @@ free_events: return ret; } static int msm_apm_secure_clock_source_override( struct msm_apm_ctrl_dev *ctrl_dev, bool enable) { int ret; if (ctrl_dev->clk_src_override) { ret = __invoke_psci_fn_smc(0xC4000020, 3, enable ? CLOCK_ASSERT_ENABLE : CLOCK_ASSERT_DISABLE, 0); if (ret) dev_err(ctrl_dev->dev, "PSCI request to switch to %s clock source failed\n", enable ? "GPLL0" : "original"); } return 0; } static int msm_apm_switch_to_mx(struct msm_apm_ctrl_dev *ctrl_dev) { int i, timeout = MSM_APM_SWITCH_TIMEOUT_US; Loading @@ -226,6 +258,10 @@ static int msm_apm_switch_to_mx(struct msm_apm_ctrl_dev *ctrl_dev) mutex_lock(&scm_lmh_lock); spin_lock_irqsave(&ctrl_dev->lock, flags); ret = msm_apm_secure_clock_source_override(ctrl_dev, true); if (ret) return ret; /* Perform revision-specific programming steps */ if (ctrl_dev->version < HMSS_VERSION_1P2) { /* Clear SPM events */ Loading Loading @@ -293,6 +329,10 @@ static int msm_apm_switch_to_mx(struct msm_apm_ctrl_dev *ctrl_dev) ctrl_dev->apcs_spm_events_addr[i]); } ret = msm_apm_secure_clock_source_override(ctrl_dev, false); if (ret) return ret; if (!ret) { ctrl_dev->supply = MSM_APM_SUPPLY_MX; dev_dbg(ctrl_dev->dev, "APM supply switched to MX\n"); Loading @@ -314,6 +354,10 @@ static int msm_apm_switch_to_apcc(struct msm_apm_ctrl_dev *ctrl_dev) mutex_lock(&scm_lmh_lock); spin_lock_irqsave(&ctrl_dev->lock, flags); ret = msm_apm_secure_clock_source_override(ctrl_dev, true); if (ret) return ret; /* Perform revision-specific programming steps */ if (ctrl_dev->version < HMSS_VERSION_1P2) { /* Clear SPM events */ Loading Loading @@ -381,6 +425,10 @@ static int msm_apm_switch_to_apcc(struct msm_apm_ctrl_dev *ctrl_dev) ctrl_dev->apc1_pll_ctl_addr); } ret = msm_apm_secure_clock_source_override(ctrl_dev, false); if (ret) return ret; if (!ret) { ctrl_dev->supply = MSM_APM_SUPPLY_APCC; dev_dbg(ctrl_dev->dev, "APM supply switched to APCC\n"); Loading Loading
Documentation/devicetree/bindings/power/qcom/apm.txt +6 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,12 @@ Required properties "apc0-cpu0-spm", "apc0-cpu1-spm", "apc1-cpu0-spm", "apc1-cpu1-spm", "apc0-l2-spm", and "apc1-l2-spm". Optional properties - qcom,clock-source-override: Specify this property to request a switch of the APC0 and APC1 clock sources to GPLL0 before the APM switch begins and to switch back to the original clock source after the APM switch completes. MSM APM Users Required properties: Loading
drivers/power/qcom/apm.c +48 −0 Original line number Diff line number Diff line Loading @@ -78,6 +78,14 @@ #define MSM_APM_DRIVER_NAME "qcom,msm-apm" asmlinkage int __invoke_psci_fn_smc(u64, u64, u64, u64); enum { CLOCK_ASSERT_ENABLE, CLOCK_ASSERT_DISABLE, CLOCK_ASSERT_TOGGLE, }; struct msm_apm_ctrl_dev { struct list_head list; struct device *dev; Loading @@ -88,6 +96,7 @@ struct msm_apm_ctrl_dev { void __iomem **apcs_spm_events_addr; void __iomem *apc0_pll_ctl_addr; void __iomem *apc1_pll_ctl_addr; bool clk_src_override; u32 version; struct dentry *debugfs; }; Loading Loading @@ -140,6 +149,12 @@ static int msm_apm_ctrl_devm_ioremap(struct platform_device *pdev, return -ENOMEM; } ctrl->clk_src_override = of_property_read_bool(dev->of_node, "qcom,clock-source-override"); if (ctrl->clk_src_override) dev_info(dev, "overriding clock sources across APM switch\n"); ctrl->version = readl_relaxed(ctrl->apcs_csr_base + APCS_VERSION); if (ctrl->version >= HMSS_VERSION_1P2) Loading Loading @@ -216,6 +231,23 @@ free_events: return ret; } static int msm_apm_secure_clock_source_override( struct msm_apm_ctrl_dev *ctrl_dev, bool enable) { int ret; if (ctrl_dev->clk_src_override) { ret = __invoke_psci_fn_smc(0xC4000020, 3, enable ? CLOCK_ASSERT_ENABLE : CLOCK_ASSERT_DISABLE, 0); if (ret) dev_err(ctrl_dev->dev, "PSCI request to switch to %s clock source failed\n", enable ? "GPLL0" : "original"); } return 0; } static int msm_apm_switch_to_mx(struct msm_apm_ctrl_dev *ctrl_dev) { int i, timeout = MSM_APM_SWITCH_TIMEOUT_US; Loading @@ -226,6 +258,10 @@ static int msm_apm_switch_to_mx(struct msm_apm_ctrl_dev *ctrl_dev) mutex_lock(&scm_lmh_lock); spin_lock_irqsave(&ctrl_dev->lock, flags); ret = msm_apm_secure_clock_source_override(ctrl_dev, true); if (ret) return ret; /* Perform revision-specific programming steps */ if (ctrl_dev->version < HMSS_VERSION_1P2) { /* Clear SPM events */ Loading Loading @@ -293,6 +329,10 @@ static int msm_apm_switch_to_mx(struct msm_apm_ctrl_dev *ctrl_dev) ctrl_dev->apcs_spm_events_addr[i]); } ret = msm_apm_secure_clock_source_override(ctrl_dev, false); if (ret) return ret; if (!ret) { ctrl_dev->supply = MSM_APM_SUPPLY_MX; dev_dbg(ctrl_dev->dev, "APM supply switched to MX\n"); Loading @@ -314,6 +354,10 @@ static int msm_apm_switch_to_apcc(struct msm_apm_ctrl_dev *ctrl_dev) mutex_lock(&scm_lmh_lock); spin_lock_irqsave(&ctrl_dev->lock, flags); ret = msm_apm_secure_clock_source_override(ctrl_dev, true); if (ret) return ret; /* Perform revision-specific programming steps */ if (ctrl_dev->version < HMSS_VERSION_1P2) { /* Clear SPM events */ Loading Loading @@ -381,6 +425,10 @@ static int msm_apm_switch_to_apcc(struct msm_apm_ctrl_dev *ctrl_dev) ctrl_dev->apc1_pll_ctl_addr); } ret = msm_apm_secure_clock_source_override(ctrl_dev, false); if (ret) return ret; if (!ret) { ctrl_dev->supply = MSM_APM_SUPPLY_APCC; dev_dbg(ctrl_dev->dev, "APM supply switched to APCC\n"); Loading