From 64a7b2e649b19e747fa805079c203f1d8753a81d Mon Sep 17 00:00:00 2001 From: Ram Chandrasekar Date: Wed, 23 Nov 2016 14:21:47 -0700 Subject: [PATCH] msm: lmh_dcvsh: Support new API to notify scheduler HLOS can place a mitigation frequency via the LMH DCVSh hardware using the software cap register and this request doesn't trigger a debug interrupt. Thus, this frequency mitigation change will not result in scheduler being notified by LMH DCVSh driver. Introduce a new API in LMH DCVSh driver, that can be used by other drivers to trigger the scheduler notification. This API and the interrupt handler follows the same code path to poll and notify the scheduler. Change-Id: Iefcdb57ff598ecb1bafc535958684f75b1f6e645 Signed-off-by: Ram Chandrasekar --- drivers/thermal/msm_lmh_dcvs.c | 32 +++++++++++++++++++++++++++----- include/linux/msm_thermal.h | 13 +++++++++++++ 2 files changed, 40 insertions(+), 5 deletions(-) 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*/