diff --git a/drivers/thermal/msm_lmh_dcvs.c b/drivers/thermal/msm_lmh_dcvs.c index 3758e39a1c02..ac1da854ab32 100644 --- a/drivers/thermal/msm_lmh_dcvs.c +++ b/drivers/thermal/msm_lmh_dcvs.c @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include @@ -83,6 +85,7 @@ struct msm_lmh_dcvs_hw { uint32_t max_freq; uint32_t hw_freq_limit; struct list_head list; + DECLARE_BITMAP(is_irq_enabled, 1); }; LIST_HEAD(lmh_dcvs_hw_list); @@ -145,6 +148,7 @@ static void msm_lmh_dcvs_poll(unsigned long data) if (max_limit >= hw->max_freq) { del_timer(&hw->poll_timer); writel_relaxed(0xFF, hw->int_clr_reg); + set_bit(1, hw->is_irq_enabled); enable_irq(hw->irq_num); } else { mod_timer(&hw->poll_timer, jiffies + msecs_to_jiffies( @@ -152,15 +156,21 @@ static void msm_lmh_dcvs_poll(unsigned long data) } } +static void lmh_dcvs_notify(struct msm_lmh_dcvs_hw *hw) +{ + if (test_and_clear_bit(1, hw->is_irq_enabled)) { + disable_irq_nosync(hw->irq_num); + msm_lmh_mitigation_notify(hw); + mod_timer(&hw->poll_timer, jiffies + msecs_to_jiffies( + MSM_LIMITS_POLLING_DELAY_MS)); + } +} + static irqreturn_t lmh_dcvs_handle_isr(int irq, void *data) { struct msm_lmh_dcvs_hw *hw = data; - disable_irq_nosync(irq); - msm_lmh_mitigation_notify(hw); - mod_timer(&hw->poll_timer, jiffies + msecs_to_jiffies( - MSM_LIMITS_POLLING_DELAY_MS)); - + lmh_dcvs_notify(hw); return IRQ_HANDLED; } @@ -314,6 +324,17 @@ static struct cpu_cooling_ops cd_ops = { .ceil_limit = lmh_set_max_limit, }; +int msm_lmh_dcvsh_sw_notify(int cpu) +{ + struct msm_lmh_dcvs_hw *hw = get_dcvsh_hw_from_cpu(cpu); + + if (!hw) + return -EINVAL; + + lmh_dcvs_notify(hw); + return 0; +} + static int msm_lmh_dcvs_probe(struct platform_device *pdev) { int ret; @@ -460,6 +481,7 @@ static int msm_lmh_dcvs_probe(struct platform_device *pdev) pr_err("Error getting IRQ number. err:%d\n", ret); return ret; } + set_bit(1, hw->is_irq_enabled); ret = devm_request_threaded_irq(&pdev->dev, hw->irq_num, NULL, lmh_dcvs_handle_isr, IRQF_TRIGGER_HIGH | IRQF_ONESHOT | IRQF_NO_SUSPEND, sensor_name, hw); diff --git a/include/linux/msm_thermal.h b/include/linux/msm_thermal.h index f3ec960536aa..33286c2d81fc 100644 --- a/include/linux/msm_thermal.h +++ b/include/linux/msm_thermal.h @@ -255,6 +255,15 @@ extern int devmgr_client_request_mitigation(struct device_clnt_data *clnt, extern void devmgr_unregister_mitigation_client( struct device *dev, struct device_clnt_data *clnt); +#ifdef CONFIG_QCOM_THERMAL_LIMITS_DCVS +extern int msm_lmh_dcvsh_sw_notify(int cpu); +#else +static inline int msm_lmh_dcvsh_sw_notify(int cpu) +{ + return -ENODEV; +} +#endif + #else static inline int msm_thermal_init(struct msm_thermal_data *pdata) { @@ -330,6 +339,10 @@ static inline void devmgr_unregister_mitigation_client( struct device_clnt_data *clnt) { } +static inline int msm_lmh_dcvsh_sw_notify(int cpu) +{ + return -ENODEV; +} #endif #endif /*__MSM_THERMAL_H*/