summaryrefslogtreecommitdiff
path: root/drivers/thermal/qoriq_thermal.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/thermal/qoriq_thermal.c')
-rw-r--r--drivers/thermal/qoriq_thermal.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/drivers/thermal/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c
index 644ba526d9ea..42abb043a1ec 100644
--- a/drivers/thermal/qoriq_thermal.c
+++ b/drivers/thermal/qoriq_thermal.c
@@ -1,5 +1,6 @@
/*
* Copyright 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -14,6 +15,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
+#include <linux/device_cooling.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/of.h>
@@ -24,6 +26,8 @@
#define SITES_MAX 16
+#define TMU_TEMP_PASSIVE_COOL_DELTA 10000
+
/*
* QorIQ TMU Registers
*/
@@ -74,9 +78,18 @@ struct qoriq_tmu_regs {
*/
struct qoriq_tmu_data {
struct thermal_zone_device *tz;
+ struct thermal_cooling_device *cdev;
struct qoriq_tmu_regs __iomem *regs;
int sensor_id;
bool little_endian;
+ int temp_passive;
+ int temp_critical;
+};
+
+enum tmu_trip {
+ TMU_TRIP_PASSIVE,
+ TMU_TRIP_CRITICAL,
+ TMU_TRIP_NUM,
};
static void tmu_write(struct qoriq_tmu_data *p, u32 val, void __iomem *addr)
@@ -188,8 +201,45 @@ static void qoriq_tmu_init_device(struct qoriq_tmu_data *data)
tmu_write(data, TMR_DISABLE, &data->regs->tmr);
}
+static int tmu_get_trend(void *p,
+ int trip, enum thermal_trend *trend)
+{
+ int trip_temp;
+ struct qoriq_tmu_data *data = p;
+
+ if (!data->tz)
+ return 0;
+
+ trip_temp = (trip == TMU_TRIP_PASSIVE) ? data->temp_passive :
+ data->temp_critical;
+
+ if (data->tz->temperature >=
+ (trip_temp - TMU_TEMP_PASSIVE_COOL_DELTA))
+ *trend = THERMAL_TREND_RAISE_FULL;
+ else
+ *trend = THERMAL_TREND_DROP_FULL;
+
+ return 0;
+}
+
+static int tmu_set_trip_temp(void *p, int trip,
+ int temp)
+{
+ struct qoriq_tmu_data *data = p;
+
+ if (trip == TMU_TRIP_CRITICAL)
+ data->temp_critical = temp;
+
+ if (trip == TMU_TRIP_PASSIVE)
+ data->temp_passive = temp;
+
+ return 0;
+}
+
static struct thermal_zone_of_device_ops tmu_tz_ops = {
.get_temp = tmu_get_temp,
+ .get_trend = tmu_get_trend,
+ .set_trip_temp = tmu_set_trip_temp,
};
static int qoriq_tmu_probe(struct platform_device *pdev)
@@ -243,7 +293,33 @@ static int qoriq_tmu_probe(struct platform_device *pdev)
goto err_tmu;
}
+ data->cdev = devfreq_cooling_register();
+ if (IS_ERR(data->cdev)) {
+ ret = PTR_ERR(data->cdev);
+ if (ret != -EPROBE_DEFER)
+ dev_err(&pdev->dev,
+ "failed to register devfreq cooling device: %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = thermal_zone_bind_cooling_device(data->tz,
+ TMU_TRIP_PASSIVE,
+ data->cdev,
+ THERMAL_NO_LIMIT,
+ THERMAL_NO_LIMIT,
+ THERMAL_WEIGHT_DEFAULT);
+ if (ret) {
+ dev_err(&data->tz->device,
+ "binding zone %s with cdev %s failed:%d\n",
+ data->tz->type, data->cdev->type, ret);
+ devfreq_cooling_unregister(data->cdev);
+ return ret;
+ }
+
trip = of_thermal_get_trip_points(data->tz);
+ data->temp_passive = trip[0].temperature;
+ data->temp_critical = trip[1].temperature;
/* Enable monitoring */
site |= 0x1 << (15 - data->sensor_id);
@@ -264,6 +340,7 @@ static int qoriq_tmu_remove(struct platform_device *pdev)
{
struct qoriq_tmu_data *data = platform_get_drvdata(pdev);
+ devfreq_cooling_unregister(data->cdev);
thermal_zone_of_sensor_unregister(&pdev->dev, data->tz);
/* Disable monitoring */
@@ -308,6 +385,7 @@ static SIMPLE_DEV_PM_OPS(qoriq_tmu_pm_ops,
static const struct of_device_id qoriq_tmu_match[] = {
{ .compatible = "fsl,qoriq-tmu", },
+ { .compatible = "fsl,imx8mq-tmu",},
{},
};
MODULE_DEVICE_TABLE(of, qoriq_tmu_match);