diff options
Diffstat (limited to 'drivers/thermal/qoriq_thermal.c')
-rw-r--r-- | drivers/thermal/qoriq_thermal.c | 78 |
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); |