Loading Documentation/devicetree/bindings/arm/msm/spm-v2.txt +3 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,9 @@ Optional properties - qcom,use-qchannel-for-pc: Boolean property to specify if qchannel should be ignored when entering power collapse. If this property is set qchannel will not be ignored in power collapse. - qcom,supports-rpm-hs: Indicates that this SPM instance allow handshake with RPM processor when executing the sleep command in the SPM sequence. Supported only on SAW2 v3.0 and above. Example 1: qcom,spm@f9089000 { Loading drivers/cpuidle/lpm-levels.c +1 −1 Original line number Diff line number Diff line Loading @@ -213,7 +213,7 @@ int set_l2_mode(struct low_power_ops *ops, int mode, bool notify_rpm) lpm = MSM_SPM_MODE_DISABLED; break; } rc = msm_spm_config_low_power_mode(ops->spm, lpm, true); rc = msm_spm_config_low_power_mode(ops->spm, lpm, notify_rpm); if (rc) pr_err("%s: Failed to set L2 low power mode %d, ERR %d", Loading drivers/soc/qcom/spm.c +27 −7 Original line number Diff line number Diff line Loading @@ -134,22 +134,41 @@ static inline uint32_t msm_spm_drv_get_num_spm_entry( return (dev->reg_shadow[MSM_SPM_REG_SAW2_ID] >> 24) & 0xFF; } static inline void msm_spm_drv_set_start_addr( static inline void msm_spm_drv_set_notify_rpm( struct msm_spm_driver_data *dev, bool notify_rpm) { if (dev->major != 0x3) return; dev->reg_shadow[MSM_SPM_REG_SAW2_SPM_CTL] &= ~BIT(17); dev->reg_shadow[MSM_SPM_REG_SAW2_SPM_CTL] |= notify_rpm << 17; } static inline void msm_spm_drv_set_start_addr2( struct msm_spm_driver_data *dev, uint32_t addr, bool pc_mode) { addr &= 0x7F; addr &= 0x1FF; addr <<= 4; dev->reg_shadow[MSM_SPM_REG_SAW2_SPM_CTL] &= 0xFFFFF80F; dev->reg_shadow[MSM_SPM_REG_SAW2_SPM_CTL] &= ~0x1FF0; dev->reg_shadow[MSM_SPM_REG_SAW2_SPM_CTL] |= addr; if (dev->major != 0x3) return; dev->reg_shadow[MSM_SPM_REG_SAW2_SPM_CTL] &= 0xFFFEFFFF; if (pc_mode) dev->reg_shadow[MSM_SPM_REG_SAW2_SPM_CTL] |= 0x00010000; } static inline void msm_spm_drv_set_start_addr( struct msm_spm_driver_data *dev, uint32_t addr, bool pc_mode) { if (dev->major == 0x3) return msm_spm_drv_set_start_addr2(dev, addr, pc_mode); addr &= 0x7F; addr <<= 4; dev->reg_shadow[MSM_SPM_REG_SAW2_SPM_CTL] &= 0xFFFFF80F; dev->reg_shadow[MSM_SPM_REG_SAW2_SPM_CTL] |= addr; } static inline bool msm_spm_pmic_arb_present(struct msm_spm_driver_data *dev) { msm_spm_drv_load_shadow(dev, MSM_SPM_REG_SAW2_ID); Loading Loading @@ -299,7 +318,7 @@ int msm_spm_drv_write_seq_data(struct msm_spm_driver_data *dev, } int msm_spm_drv_set_low_power_mode(struct msm_spm_driver_data *dev, uint32_t addr, bool pc_mode) uint32_t addr, bool pc_mode, bool notify_rpm) { /* SPM is configured to reset start address to zero after end of Program Loading @@ -308,6 +327,7 @@ int msm_spm_drv_set_low_power_mode(struct msm_spm_driver_data *dev, return -EINVAL; msm_spm_drv_set_start_addr(dev, addr, pc_mode); msm_spm_drv_set_notify_rpm(dev, notify_rpm); msm_spm_drv_flush_shadow(dev, MSM_SPM_REG_SAW2_SPM_CTL); wmb(); Loading drivers/soc/qcom/spm_devices.c +21 −18 Original line number Diff line number Diff line Loading @@ -29,7 +29,6 @@ struct msm_spm_power_modes { uint32_t mode; bool notify_rpm; uint32_t start_addr; }; Loading @@ -44,6 +43,7 @@ struct msm_spm_device { struct cpumask mask; void __iomem *q2s_reg; bool qchannel_ignore; bool allow_rpm_hs; }; struct msm_spm_vdd_info { Loading Loading @@ -201,14 +201,17 @@ static int msm_spm_dev_set_low_power_mode(struct msm_spm_device *dev, ret = msm_spm_drv_set_spm_enable(&dev->reg_data, false); } else if (!msm_spm_drv_set_spm_enable(&dev->reg_data, true)) { for (i = 0; i < dev->num_modes; i++) { if ((dev->modes[i].mode == mode) && (dev->modes[i].notify_rpm == notify_rpm)) { if (dev->modes[i].mode != mode) continue; if (!dev->allow_rpm_hs && notify_rpm) notify_rpm = false; start_addr = dev->modes[i].start_addr; break; } } ret = msm_spm_drv_set_low_power_mode(&dev->reg_data, start_addr, pc_mode); start_addr, pc_mode, notify_rpm); } msm_spm_config_q2s(dev, mode); Loading Loading @@ -249,10 +252,10 @@ static int msm_spm_dev_init(struct msm_spm_device *dev, goto spm_failed_init; dev->modes[i].mode = data->modes[i].mode; dev->modes[i].notify_rpm = data->modes[i].notify_rpm; } msm_spm_drv_flush_seq_entry(&dev->reg_data); dev->initialized = true; return 0; spm_failed_init: Loading Loading @@ -552,15 +555,14 @@ static int msm_spm_dev_probe(struct platform_device *pdev) struct mode_of { char *key; uint32_t id; uint32_t notify_rpm; }; struct mode_of mode_of_data[] = { {"qcom,saw2-spm-cmd-wfi", MSM_SPM_MODE_CLOCK_GATING, 0}, {"qcom,saw2-spm-cmd-ret", MSM_SPM_MODE_RETENTION, 0}, {"qcom,saw2-spm-cmd-gdhs", MSM_SPM_MODE_GDHS, 1}, {"qcom,saw2-spm-cmd-spc", MSM_SPM_MODE_POWER_COLLAPSE, 0}, {"qcom,saw2-spm-cmd-pc", MSM_SPM_MODE_POWER_COLLAPSE, 1}, {"qcom,saw2-spm-cmd-wfi", MSM_SPM_MODE_CLOCK_GATING}, {"qcom,saw2-spm-cmd-ret", MSM_SPM_MODE_RETENTION}, {"qcom,saw2-spm-cmd-gdhs", MSM_SPM_MODE_GDHS}, {"qcom,saw2-spm-cmd-spc", MSM_SPM_MODE_POWER_COLLAPSE}, {"qcom,saw2-spm-cmd-pc", MSM_SPM_MODE_POWER_COLLAPSE}, }; dev = msm_spm_get_device(pdev); Loading Loading @@ -650,16 +652,17 @@ static int msm_spm_dev_probe(struct platform_device *pdev) if (!modes[mode_count].cmd) continue; modes[mode_count].mode = mode_of_data[i].id; modes[mode_count].notify_rpm = mode_of_data[i].notify_rpm; pr_debug("%s(): dev: %s cmd:%s, mode:%d rpm:%d\n", __func__, dev->name, key, modes[mode_count].mode, modes[mode_count].notify_rpm); pr_debug("%s(): dev: %s cmd:%s, mode:%d\n", __func__, dev->name, key, modes[mode_count].mode); mode_count++; } spm_data.modes = modes; spm_data.num_modes = mode_count; key = "qcom,supports-rpm-hs"; dev->allow_rpm_hs = of_property_read_bool(pdev->dev.of_node, key); ret = msm_spm_dev_init(dev, &spm_data); if (ret) goto fail; Loading drivers/soc/qcom/spm_driver.h +1 −1 Original line number Diff line number Diff line Loading @@ -98,7 +98,7 @@ int msm_spm_drv_init(struct msm_spm_driver_data *dev, struct msm_spm_platform_data *data); void msm_spm_drv_reinit(struct msm_spm_driver_data *dev); int msm_spm_drv_set_low_power_mode(struct msm_spm_driver_data *dev, uint32_t addr, bool pc_mode); uint32_t addr, bool pc_mode, bool notify_rpm); int msm_spm_drv_set_vdd(struct msm_spm_driver_data *dev, unsigned int vlevel); void dump_regs(struct msm_spm_driver_data *dev, int cpu); Loading Loading
Documentation/devicetree/bindings/arm/msm/spm-v2.txt +3 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,9 @@ Optional properties - qcom,use-qchannel-for-pc: Boolean property to specify if qchannel should be ignored when entering power collapse. If this property is set qchannel will not be ignored in power collapse. - qcom,supports-rpm-hs: Indicates that this SPM instance allow handshake with RPM processor when executing the sleep command in the SPM sequence. Supported only on SAW2 v3.0 and above. Example 1: qcom,spm@f9089000 { Loading
drivers/cpuidle/lpm-levels.c +1 −1 Original line number Diff line number Diff line Loading @@ -213,7 +213,7 @@ int set_l2_mode(struct low_power_ops *ops, int mode, bool notify_rpm) lpm = MSM_SPM_MODE_DISABLED; break; } rc = msm_spm_config_low_power_mode(ops->spm, lpm, true); rc = msm_spm_config_low_power_mode(ops->spm, lpm, notify_rpm); if (rc) pr_err("%s: Failed to set L2 low power mode %d, ERR %d", Loading
drivers/soc/qcom/spm.c +27 −7 Original line number Diff line number Diff line Loading @@ -134,22 +134,41 @@ static inline uint32_t msm_spm_drv_get_num_spm_entry( return (dev->reg_shadow[MSM_SPM_REG_SAW2_ID] >> 24) & 0xFF; } static inline void msm_spm_drv_set_start_addr( static inline void msm_spm_drv_set_notify_rpm( struct msm_spm_driver_data *dev, bool notify_rpm) { if (dev->major != 0x3) return; dev->reg_shadow[MSM_SPM_REG_SAW2_SPM_CTL] &= ~BIT(17); dev->reg_shadow[MSM_SPM_REG_SAW2_SPM_CTL] |= notify_rpm << 17; } static inline void msm_spm_drv_set_start_addr2( struct msm_spm_driver_data *dev, uint32_t addr, bool pc_mode) { addr &= 0x7F; addr &= 0x1FF; addr <<= 4; dev->reg_shadow[MSM_SPM_REG_SAW2_SPM_CTL] &= 0xFFFFF80F; dev->reg_shadow[MSM_SPM_REG_SAW2_SPM_CTL] &= ~0x1FF0; dev->reg_shadow[MSM_SPM_REG_SAW2_SPM_CTL] |= addr; if (dev->major != 0x3) return; dev->reg_shadow[MSM_SPM_REG_SAW2_SPM_CTL] &= 0xFFFEFFFF; if (pc_mode) dev->reg_shadow[MSM_SPM_REG_SAW2_SPM_CTL] |= 0x00010000; } static inline void msm_spm_drv_set_start_addr( struct msm_spm_driver_data *dev, uint32_t addr, bool pc_mode) { if (dev->major == 0x3) return msm_spm_drv_set_start_addr2(dev, addr, pc_mode); addr &= 0x7F; addr <<= 4; dev->reg_shadow[MSM_SPM_REG_SAW2_SPM_CTL] &= 0xFFFFF80F; dev->reg_shadow[MSM_SPM_REG_SAW2_SPM_CTL] |= addr; } static inline bool msm_spm_pmic_arb_present(struct msm_spm_driver_data *dev) { msm_spm_drv_load_shadow(dev, MSM_SPM_REG_SAW2_ID); Loading Loading @@ -299,7 +318,7 @@ int msm_spm_drv_write_seq_data(struct msm_spm_driver_data *dev, } int msm_spm_drv_set_low_power_mode(struct msm_spm_driver_data *dev, uint32_t addr, bool pc_mode) uint32_t addr, bool pc_mode, bool notify_rpm) { /* SPM is configured to reset start address to zero after end of Program Loading @@ -308,6 +327,7 @@ int msm_spm_drv_set_low_power_mode(struct msm_spm_driver_data *dev, return -EINVAL; msm_spm_drv_set_start_addr(dev, addr, pc_mode); msm_spm_drv_set_notify_rpm(dev, notify_rpm); msm_spm_drv_flush_shadow(dev, MSM_SPM_REG_SAW2_SPM_CTL); wmb(); Loading
drivers/soc/qcom/spm_devices.c +21 −18 Original line number Diff line number Diff line Loading @@ -29,7 +29,6 @@ struct msm_spm_power_modes { uint32_t mode; bool notify_rpm; uint32_t start_addr; }; Loading @@ -44,6 +43,7 @@ struct msm_spm_device { struct cpumask mask; void __iomem *q2s_reg; bool qchannel_ignore; bool allow_rpm_hs; }; struct msm_spm_vdd_info { Loading Loading @@ -201,14 +201,17 @@ static int msm_spm_dev_set_low_power_mode(struct msm_spm_device *dev, ret = msm_spm_drv_set_spm_enable(&dev->reg_data, false); } else if (!msm_spm_drv_set_spm_enable(&dev->reg_data, true)) { for (i = 0; i < dev->num_modes; i++) { if ((dev->modes[i].mode == mode) && (dev->modes[i].notify_rpm == notify_rpm)) { if (dev->modes[i].mode != mode) continue; if (!dev->allow_rpm_hs && notify_rpm) notify_rpm = false; start_addr = dev->modes[i].start_addr; break; } } ret = msm_spm_drv_set_low_power_mode(&dev->reg_data, start_addr, pc_mode); start_addr, pc_mode, notify_rpm); } msm_spm_config_q2s(dev, mode); Loading Loading @@ -249,10 +252,10 @@ static int msm_spm_dev_init(struct msm_spm_device *dev, goto spm_failed_init; dev->modes[i].mode = data->modes[i].mode; dev->modes[i].notify_rpm = data->modes[i].notify_rpm; } msm_spm_drv_flush_seq_entry(&dev->reg_data); dev->initialized = true; return 0; spm_failed_init: Loading Loading @@ -552,15 +555,14 @@ static int msm_spm_dev_probe(struct platform_device *pdev) struct mode_of { char *key; uint32_t id; uint32_t notify_rpm; }; struct mode_of mode_of_data[] = { {"qcom,saw2-spm-cmd-wfi", MSM_SPM_MODE_CLOCK_GATING, 0}, {"qcom,saw2-spm-cmd-ret", MSM_SPM_MODE_RETENTION, 0}, {"qcom,saw2-spm-cmd-gdhs", MSM_SPM_MODE_GDHS, 1}, {"qcom,saw2-spm-cmd-spc", MSM_SPM_MODE_POWER_COLLAPSE, 0}, {"qcom,saw2-spm-cmd-pc", MSM_SPM_MODE_POWER_COLLAPSE, 1}, {"qcom,saw2-spm-cmd-wfi", MSM_SPM_MODE_CLOCK_GATING}, {"qcom,saw2-spm-cmd-ret", MSM_SPM_MODE_RETENTION}, {"qcom,saw2-spm-cmd-gdhs", MSM_SPM_MODE_GDHS}, {"qcom,saw2-spm-cmd-spc", MSM_SPM_MODE_POWER_COLLAPSE}, {"qcom,saw2-spm-cmd-pc", MSM_SPM_MODE_POWER_COLLAPSE}, }; dev = msm_spm_get_device(pdev); Loading Loading @@ -650,16 +652,17 @@ static int msm_spm_dev_probe(struct platform_device *pdev) if (!modes[mode_count].cmd) continue; modes[mode_count].mode = mode_of_data[i].id; modes[mode_count].notify_rpm = mode_of_data[i].notify_rpm; pr_debug("%s(): dev: %s cmd:%s, mode:%d rpm:%d\n", __func__, dev->name, key, modes[mode_count].mode, modes[mode_count].notify_rpm); pr_debug("%s(): dev: %s cmd:%s, mode:%d\n", __func__, dev->name, key, modes[mode_count].mode); mode_count++; } spm_data.modes = modes; spm_data.num_modes = mode_count; key = "qcom,supports-rpm-hs"; dev->allow_rpm_hs = of_property_read_bool(pdev->dev.of_node, key); ret = msm_spm_dev_init(dev, &spm_data); if (ret) goto fail; Loading
drivers/soc/qcom/spm_driver.h +1 −1 Original line number Diff line number Diff line Loading @@ -98,7 +98,7 @@ int msm_spm_drv_init(struct msm_spm_driver_data *dev, struct msm_spm_platform_data *data); void msm_spm_drv_reinit(struct msm_spm_driver_data *dev); int msm_spm_drv_set_low_power_mode(struct msm_spm_driver_data *dev, uint32_t addr, bool pc_mode); uint32_t addr, bool pc_mode, bool notify_rpm); int msm_spm_drv_set_vdd(struct msm_spm_driver_data *dev, unsigned int vlevel); void dump_regs(struct msm_spm_driver_data *dev, int cpu); Loading