thermal: imx8mm: Add device cooling support

Register device cooling for first thermal zone manually, when
temperature exceeds passive trip, system wide cooling notification
will be triggered.

Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
This commit is contained in:
Anson Huang 2019-08-07 13:42:48 +08:00 committed by Dong Aisheng
parent 23eba08685
commit eafc897eb6
1 changed files with 74 additions and 0 deletions

View File

@ -6,6 +6,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/device_cooling.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/module.h>
@ -23,11 +24,22 @@
#define TRITSR_VAL_MASK 0xff
#define TEMP_LOW_LIMIT 10
#define IMX_TEMP_PASSIVE_COOL_DELTA 10000
struct imx8mm_tmu {
struct thermal_zone_device *tzd;
void __iomem *base;
struct clk *clk;
struct thermal_cooling_device *cdev;
int temp_passive;
int temp_critical;
};
/* The driver support 1 passive trip point and 1 critical trip point */
enum imx_thermal_trip {
IMX_TRIP_PASSIVE,
IMX_TRIP_CRITICAL,
IMX_TRIP_NUM,
};
static int tmu_get_temp(void *data, int *temp)
@ -47,12 +59,46 @@ static int tmu_get_temp(void *data, int *temp)
return 0;
}
static int tmu_get_trend(void *p, int trip, enum thermal_trend *trend)
{
int trip_temp;
struct imx8mm_tmu *tmu = p;
if (!tmu->tzd)
return 0;
trip_temp = (trip == IMX_TRIP_PASSIVE) ? tmu->temp_passive : tmu->temp_critical;
if (tmu->tzd->temperature >= (trip_temp - IMX_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 imx8mm_tmu *tmu = p;
if (trip == IMX_TRIP_CRITICAL)
tmu->temp_critical = temp;
if (trip == IMX_TRIP_PASSIVE)
tmu->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 imx8mm_tmu_probe(struct platform_device *pdev)
{
const struct thermal_trip *trips;
struct imx8mm_tmu *tmu;
u32 val;
int ret;
@ -90,6 +136,34 @@ static int imx8mm_tmu_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, tmu);
tmu->cdev = devfreq_cooling_register();
if (IS_ERR(tmu->cdev)) {
ret = PTR_ERR(tmu->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(tmu->tzd,
IMX_TRIP_PASSIVE,
tmu->cdev,
THERMAL_NO_LIMIT,
THERMAL_NO_LIMIT,
THERMAL_WEIGHT_DEFAULT);
if (ret) {
dev_err(&pdev->dev,
"binding zone %s with cdev %s failed:%d\n",
tmu->tzd->type, tmu->cdev->type, ret);
devfreq_cooling_unregister(tmu->cdev);
return ret;
}
trips = of_thermal_get_trip_points(tmu->tzd);
/* get the thermal trip temp */
tmu->temp_passive = trips[0].temperature;
tmu->temp_critical = trips[1].temperature;
/* enable the monitor */
val = readl_relaxed(tmu->base + TER);
val |= TER_EN;