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:
Ram Chandrasekar 2016-11-23 14:21:47 -07:00
parent c975089fd5
commit 64a7b2e649
2 changed files with 40 additions and 5 deletions

View file

@ -25,6 +25,8 @@
#include <linux/timer.h>
#include <linux/pm_opp.h>
#include <linux/cpu_cooling.h>
#include <linux/bitmap.h>
#include <linux/msm_thermal.h>
#include <asm/smp_plat.h>
#include <asm/cacheflush.h>
@ -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);

View file

@ -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*/