diff options
author | Anson Huang <Anson.Huang@nxp.com> | 2019-08-07 13:24:26 +0800 |
---|---|---|
committer | Dong Aisheng <aisheng.dong@nxp.com> | 2019-11-25 15:44:14 +0800 |
commit | 6f5ee8814f48157746bfe2aee2e4da612da90442 (patch) | |
tree | ed23dc961081ec81e676b0b52d4b8646bb12ed6c /drivers/thermal | |
parent | a74bea82319cd2610a5fdeb7625fa5cc27a87a2f (diff) |
thermal: qoriq: 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>
Diffstat (limited to 'drivers/thermal')
-rw-r--r-- | drivers/thermal/qoriq_thermal.c | 80 |
1 files changed, 79 insertions, 1 deletions
diff --git a/drivers/thermal/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c index 39542c670301..bdf31fcd3e04 100644 --- a/drivers/thermal/qoriq_thermal.c +++ b/drivers/thermal/qoriq_thermal.c @@ -3,6 +3,7 @@ // Copyright 2016 Freescale Semiconductor, Inc. #include <linux/clk.h> +#include <linux/device_cooling.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/err.h> @@ -14,6 +15,7 @@ #include "thermal_core.h" #define SITES_MAX 16 +#define TMU_TEMP_PASSIVE_COOL_DELTA 10000 /* * QorIQ TMU Registers @@ -69,6 +71,9 @@ struct qoriq_sensor { struct thermal_zone_device *tzd; struct qoriq_tmu_data *qdata; int id; + int temp_passive; + int temp_critical; + struct thermal_cooling_device *cdev; }; struct qoriq_tmu_data { @@ -78,6 +83,12 @@ struct qoriq_tmu_data { struct qoriq_sensor *sensor[SITES_MAX]; }; +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) { if (p->little_endian) @@ -106,14 +117,51 @@ static int tmu_get_temp(void *p, int *temp) return 0; } +static int tmu_get_trend(void *p, int trip, enum thermal_trend *trend) +{ + struct qoriq_sensor *qsensor = p; + int trip_temp; + + if (!qsensor->tzd) + return 0; + + trip_temp = (trip == TMU_TRIP_PASSIVE) ? qsensor->temp_passive : + qsensor->temp_critical; + + if (qsensor->tzd->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_sensor *qsensor = p; + + if (trip == TMU_TRIP_CRITICAL) + qsensor->temp_critical = temp; + + if (trip == TMU_TRIP_PASSIVE) + qsensor->temp_passive = temp; + + return 0; +} + static const 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_register_tmu_zone(struct platform_device *pdev) { struct qoriq_tmu_data *qdata = platform_get_drvdata(pdev); - int id, sites = 0; + const struct thermal_trip *trip; + int id, sites = 0, ret; for (id = 0; id < SITES_MAX; id++) { qdata->sensor[id] = devm_kzalloc(&pdev->dev, @@ -132,6 +180,36 @@ static int qoriq_tmu_register_tmu_zone(struct platform_device *pdev) return PTR_ERR(qdata->sensor[id]->tzd); } + /* first thermal zone takes care of system-wide device cooling */ + if (id == 0) { + qdata->sensor[id]->cdev = devfreq_cooling_register(); + if (IS_ERR(qdata->sensor[id]->cdev)) { + ret = PTR_ERR(qdata->sensor[id]->cdev); + pr_err("failed to register devfreq cooling device: %d\n", + ret); + return ret; + } + + ret = thermal_zone_bind_cooling_device(qdata->sensor[id]->tzd, + TMU_TRIP_PASSIVE, + qdata->sensor[id]->cdev, + THERMAL_NO_LIMIT, + THERMAL_NO_LIMIT, + THERMAL_WEIGHT_DEFAULT); + if (ret) { + pr_err("binding zone %s with cdev %s failed:%d\n", + qdata->sensor[id]->tzd->type, + qdata->sensor[id]->cdev->type, + ret); + devfreq_cooling_unregister(qdata->sensor[id]->cdev); + return ret; + } + + trip = of_thermal_get_trip_points(qdata->sensor[id]->tzd); + qdata->sensor[id]->temp_passive = trip[0].temperature; + qdata->sensor[id]->temp_critical = trip[1].temperature; + } + sites |= 0x1 << (15 - id); } |