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:
parent
23eba08685
commit
eafc897eb6
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue