summaryrefslogtreecommitdiff
path: root/drivers/mxc/hantro
diff options
context:
space:
mode:
authorZhou Peng-B04994 <eagle.zhou@nxp.com>2017-09-21 11:52:38 +0800
committerLeonard Crestez <leonard.crestez@nxp.com>2018-08-24 12:41:33 +0300
commitc8ac6d1895154b60ad1f4d4ff81f7ff33488312d (patch)
tree91ab3aa125afcfc7091f1630b4d7224f7fe8fee8 /drivers/mxc/hantro
parent2e80a969498b195342dc529edfb7eec361133acd (diff)
MLK-16502 - [i.MX8MQ/Hantro]: Implement dynamic clock adjustement in high temperature
Register thermal notifier and implment dynamic clock - One module parameter is added to enable or disable dynamic clock: 'hantro_dynamic_clock' Default, dynamic clock is disabled - One module parameter is added to adjust ratio: 'hantro_clock_ratio' Default, decrease to 1/2 clock when receiving hot event Signed-off-by: Zhou Peng-B04994 <eagle.zhou@nxp.com>
Diffstat (limited to 'drivers/mxc/hantro')
-rwxr-xr-xdrivers/mxc/hantro/hantrodec.c88
1 files changed, 87 insertions, 1 deletions
diff --git a/drivers/mxc/hantro/hantrodec.c b/drivers/mxc/hantro/hantrodec.c
index 53c0e0ebfbe1..25d77fbba97d 100755
--- a/drivers/mxc/hantro/hantrodec.c
+++ b/drivers/mxc/hantro/hantrodec.c
@@ -48,6 +48,22 @@
#include <linux/pm_runtime.h>
#include <linux/clk.h>
+#ifdef CONFIG_DEVICE_THERMAL
+#include <linux/device_cooling.h>
+#define HANTRO_REG_THERMAL_NOTIFIER(a) register_devfreq_cooling_notifier(a)
+#define HANTRO_UNREG_THERMAL_NOTIFIER(a) unregister_devfreq_cooling_notifier(a)
+DEFINE_SPINLOCK(thermal_lock);
+/*1:hot, 0: not hot*/
+static int thermal_event;
+static int thermal_cur;
+static int hantro_clock_ratio = 2;
+static int hantro_dynamic_clock;
+module_param(hantro_clock_ratio, int, 0644);
+module_param(hantro_dynamic_clock, int, 0644);
+MODULE_PARM_DESC(hantro_clock_ratio, "clock ratio 1/N");
+MODULE_PARM_DESC(hantro_dynamic_clock, "enable or disable dynamic clock rate");
+#endif
+
/*hantro G1 regs config including dec and pp*/
#define HANTRO_DEC_ORG_REGS 60
#define HANTRO_PP_ORG_REGS 41
@@ -98,6 +114,9 @@
#define DEC_IO_SIZE_0 ((HANTRO_G2_DEC_REGS) * 4) /* bytes */
#define DEC_IO_SIZE_1 ((HANTRO_G2_DEC_REGS) * 4) /* bytes */
+#define HANTRO_G1_DEF_CLK (600000000)
+#define HANTRO_G2_DEF_CLK (600000000)
+#define HANTRO_BUS_DEF_CLK (800000000)
/***********************************************************************/
#define IS_G1(hw_id) ((hw_id == 0x6731) ? 1:0)
@@ -248,6 +267,56 @@ static int hantro_ctrlblk_reset(struct device *dev)
return 0;
}
+#ifdef CONFIG_DEVICE_THERMAL
+static int hantro_thermal_check(struct device *dev)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&thermal_lock, flags);
+ if (thermal_event == thermal_cur) {
+ /*nothing to do and return directly*/
+ spin_unlock_irqrestore(&thermal_lock, flags);
+ return 0;
+ }
+ thermal_cur = thermal_event;
+ spin_unlock_irqrestore(&thermal_lock, flags);
+
+ if (thermal_cur) {
+ int ratio = hantro_clock_ratio;
+
+ pr_debug("hantro: too hot, need to decrease clock, ratio: 1/%d\n", ratio);
+ /*clock disable/enable are not required for vpu clock rate operation*/
+ clk_set_rate(hantro_clk_g1, HANTRO_G1_DEF_CLK/ratio);
+ clk_set_rate(hantro_clk_g2, HANTRO_G2_DEF_CLK/ratio);
+ clk_set_rate(hantro_clk_bus, HANTRO_BUS_DEF_CLK/ratio);
+ } else {
+ pr_debug("hantro: not hot again, will restore default clock\n");
+ clk_set_rate(hantro_clk_g1, HANTRO_G1_DEF_CLK);
+ clk_set_rate(hantro_clk_g2, HANTRO_G2_DEF_CLK);
+ clk_set_rate(hantro_clk_bus, HANTRO_BUS_DEF_CLK);
+ }
+ pr_info("hantro: event(%d), g1, g2, bus clock: %ld, %ld, %ld\n", thermal_cur,
+ clk_get_rate(hantro_clk_g1), clk_get_rate(hantro_clk_g2), clk_get_rate(hantro_clk_bus));
+ return 0;
+}
+
+static int hantro_thermal_hot_notify(struct notifier_block *nb, unsigned long event, void *dummy)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&thermal_lock, flags);
+ thermal_event = event; /*event: 1: hot, 0: cool*/
+ spin_unlock_irqrestore(&thermal_lock, flags);
+ pr_info("hantro receive hot notification event: %ld\n", event);
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block hantro_thermal_hot_notifier = {
+ .notifier_call = hantro_thermal_hot_notify,
+};
+#endif //CONFIG_DEVICE_THERMAL
+
static void ReadCoreConfig(hantrodec_t *dev)
{
int c;
@@ -454,6 +523,11 @@ long ReserveDecoder(hantrodec_t *dev, struct file *filp, unsigned long format)
return -1;
}
+#ifdef CONFIG_DEVICE_THERMAL
+ if (hantro_dynamic_clock)
+ hantro_thermal_check(hantro_dev);
+#endif
+
return Core;
}
@@ -1686,6 +1760,13 @@ static int hantro_dev_probe(struct platform_device *pdev)
err = PTR_ERR(temp_class);
goto err_out_class;
}
+
+#ifdef CONFIG_DEVICE_THERMAL
+ HANTRO_REG_THERMAL_NOTIFIER(&hantro_thermal_hot_notifier);
+ thermal_event = 0;
+ thermal_cur = 0;
+ hantro_dynamic_clock = 0;
+#endif
timeout = 0;
goto out;
@@ -1713,6 +1794,11 @@ static int hantro_dev_remove(struct platform_device *pdev)
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
hantro_clk_disable(&pdev->dev);
+
+#ifdef CONFIG_DEVICE_THERMAL
+ HANTRO_UNREG_THERMAL_NOTIFIER(&hantro_thermal_hot_notifier);
+#endif
+
return 0;
}
@@ -1745,7 +1831,7 @@ static const struct dev_pm_ops hantro_pm_ops = {
SET_RUNTIME_PM_OPS(hantro_runtime_suspend, hantro_runtime_resume, NULL)
SET_SYSTEM_SLEEP_PM_OPS(hantro_suspend, hantro_resume)
};
-#endif
+#endif //CONFIG_PM
static const struct of_device_id hantro_of_match[] = {
{ .compatible = "nxp,imx8mq-hantro", },