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 <rkumbako@codeaurora.org>
This commit is contained in:
parent
c975089fd5
commit
64a7b2e649
2 changed files with 40 additions and 5 deletions
|
@ -25,6 +25,8 @@
|
||||||
#include <linux/timer.h>
|
#include <linux/timer.h>
|
||||||
#include <linux/pm_opp.h>
|
#include <linux/pm_opp.h>
|
||||||
#include <linux/cpu_cooling.h>
|
#include <linux/cpu_cooling.h>
|
||||||
|
#include <linux/bitmap.h>
|
||||||
|
#include <linux/msm_thermal.h>
|
||||||
|
|
||||||
#include <asm/smp_plat.h>
|
#include <asm/smp_plat.h>
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
|
@ -83,6 +85,7 @@ struct msm_lmh_dcvs_hw {
|
||||||
uint32_t max_freq;
|
uint32_t max_freq;
|
||||||
uint32_t hw_freq_limit;
|
uint32_t hw_freq_limit;
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
|
DECLARE_BITMAP(is_irq_enabled, 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
LIST_HEAD(lmh_dcvs_hw_list);
|
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) {
|
if (max_limit >= hw->max_freq) {
|
||||||
del_timer(&hw->poll_timer);
|
del_timer(&hw->poll_timer);
|
||||||
writel_relaxed(0xFF, hw->int_clr_reg);
|
writel_relaxed(0xFF, hw->int_clr_reg);
|
||||||
|
set_bit(1, hw->is_irq_enabled);
|
||||||
enable_irq(hw->irq_num);
|
enable_irq(hw->irq_num);
|
||||||
} else {
|
} else {
|
||||||
mod_timer(&hw->poll_timer, jiffies + msecs_to_jiffies(
|
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)
|
static irqreturn_t lmh_dcvs_handle_isr(int irq, void *data)
|
||||||
{
|
{
|
||||||
struct msm_lmh_dcvs_hw *hw = data;
|
struct msm_lmh_dcvs_hw *hw = data;
|
||||||
|
|
||||||
disable_irq_nosync(irq);
|
lmh_dcvs_notify(hw);
|
||||||
msm_lmh_mitigation_notify(hw);
|
|
||||||
mod_timer(&hw->poll_timer, jiffies + msecs_to_jiffies(
|
|
||||||
MSM_LIMITS_POLLING_DELAY_MS));
|
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -314,6 +324,17 @@ static struct cpu_cooling_ops cd_ops = {
|
||||||
.ceil_limit = lmh_set_max_limit,
|
.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)
|
static int msm_lmh_dcvs_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
int ret;
|
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);
|
pr_err("Error getting IRQ number. err:%d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
set_bit(1, hw->is_irq_enabled);
|
||||||
ret = devm_request_threaded_irq(&pdev->dev, hw->irq_num, NULL,
|
ret = devm_request_threaded_irq(&pdev->dev, hw->irq_num, NULL,
|
||||||
lmh_dcvs_handle_isr, IRQF_TRIGGER_HIGH | IRQF_ONESHOT
|
lmh_dcvs_handle_isr, IRQF_TRIGGER_HIGH | IRQF_ONESHOT
|
||||||
| IRQF_NO_SUSPEND, sensor_name, hw);
|
| IRQF_NO_SUSPEND, sensor_name, hw);
|
||||||
|
|
|
@ -255,6 +255,15 @@ extern int devmgr_client_request_mitigation(struct device_clnt_data *clnt,
|
||||||
extern void devmgr_unregister_mitigation_client(
|
extern void devmgr_unregister_mitigation_client(
|
||||||
struct device *dev,
|
struct device *dev,
|
||||||
struct device_clnt_data *clnt);
|
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
|
#else
|
||||||
static inline int msm_thermal_init(struct msm_thermal_data *pdata)
|
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)
|
struct device_clnt_data *clnt)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
static inline int msm_lmh_dcvsh_sw_notify(int cpu)
|
||||||
|
{
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /*__MSM_THERMAL_H*/
|
#endif /*__MSM_THERMAL_H*/
|
||||||
|
|
Loading…
Add table
Reference in a new issue