u-boot/drivers/thermal/imx_scu_thermal.c
Tom Rini d678a59d2d Revert "Merge patch series "arm: dts: am62-beagleplay: Fix Beagleplay Ethernet""
When bringing in the series 'arm: dts: am62-beagleplay: Fix Beagleplay
Ethernet"' I failed to notice that b4 noticed it was based on next and
so took that as the base commit and merged that part of next to master.

This reverts commit c8ffd1356d, reversing
changes made to 2ee6f3a5f7.

Reported-by: Jonas Karlman <jonas@kwiboo.se>
Signed-off-by: Tom Rini <trini@konsulko.com>
2024-05-19 08:16:36 -06:00

218 lines
5.0 KiB
C

// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2019 NXP
*/
#include <config.h>
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <log.h>
#include <thermal.h>
#include <asm/global_data.h>
#include <dm/device-internal.h>
#include <dm/device.h>
#include <firmware/imx/sci/sci.h>
#include <linux/delay.h>
#include <linux/libfdt.h>
DECLARE_GLOBAL_DATA_PTR;
struct imx_sc_thermal_plat {
int critical;
int alert;
int polling_delay;
int id;
bool zone_node;
};
static int read_temperature(struct udevice *dev, int *temp)
{
s16 celsius;
s8 tenths;
int ret;
sc_rsrc_t *sensor_rsrc = (sc_rsrc_t *)dev_get_driver_data(dev);
struct imx_sc_thermal_plat *pdata = dev_get_plat(dev);
if (!temp)
return -EINVAL;
ret = sc_misc_get_temp(-1, sensor_rsrc[pdata->id], SC_C_TEMP,
&celsius, &tenths);
if (ret) {
printf("Error: get temperature failed! (error = %d)\n", ret);
return ret;
}
*temp = celsius * 1000 + tenths * 100;
return 0;
}
int imx_sc_thermal_get_temp(struct udevice *dev, int *temp)
{
struct imx_sc_thermal_plat *pdata = dev_get_plat(dev);
int cpu_temp = 0;
int ret;
ret = read_temperature(dev, &cpu_temp);
if (ret)
return ret;
while (cpu_temp >= pdata->alert) {
printf("CPU Temperature (%dC) beyond alert (%dC), close to critical (%dC)",
cpu_temp, pdata->alert, pdata->critical);
puts(" waiting...\n");
mdelay(pdata->polling_delay);
ret = read_temperature(dev, &cpu_temp);
if (ret)
return ret;
if (cpu_temp >= pdata->alert && !pdata->alert)
break;
}
*temp = cpu_temp / 1000;
return 0;
}
static const struct dm_thermal_ops imx_sc_thermal_ops = {
.get_temp = imx_sc_thermal_get_temp,
};
static int imx_sc_thermal_probe(struct udevice *dev)
{
debug("%s dev name %s\n", __func__, dev->name);
return 0;
}
static int imx_sc_thermal_bind(struct udevice *dev)
{
struct imx_sc_thermal_plat *pdata = dev_get_plat(dev);
int reg, ret;
int offset;
const char *name;
const void *prop;
debug("%s dev name %s\n", __func__, dev->name);
prop = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "compatible",
NULL);
if (!prop)
return 0;
pdata->zone_node = 1;
reg = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "tsens-num", 0);
if (reg == 0) {
printf("%s: no temp sensor number provided!\n", __func__);
return -EINVAL;
}
offset = fdt_subnode_offset(gd->fdt_blob, 0, "thermal-zones");
fdt_for_each_subnode(offset, gd->fdt_blob, offset) {
/* Bind the subnode to this driver */
name = fdt_get_name(gd->fdt_blob, offset, NULL);
ret = device_bind_with_driver_data(dev, dev->driver, name,
dev->driver_data,
offset_to_ofnode(offset),
NULL);
if (ret)
printf("Error binding driver '%s': %d\n",
dev->driver->name, ret);
}
return 0;
}
static int imx_sc_thermal_of_to_plat(struct udevice *dev)
{
struct imx_sc_thermal_plat *pdata = dev_get_plat(dev);
struct fdtdec_phandle_args args;
const char *type;
int ret;
int trips_np;
debug("%s dev name %s\n", __func__, dev->name);
if (pdata->zone_node)
return 0;
ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev_of_offset(dev),
"thermal-sensors",
"#thermal-sensor-cells",
0, 0, &args);
if (ret)
return ret;
if (args.node != dev_of_offset(dev->parent))
return -EFAULT;
if (args.args_count >= 1)
pdata->id = args.args[0];
else
pdata->id = 0;
debug("args.args_count %d, id %d\n", args.args_count, pdata->id);
pdata->polling_delay = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
"polling-delay", 1000);
trips_np = fdt_subnode_offset(gd->fdt_blob, dev_of_offset(dev),
"trips");
fdt_for_each_subnode(trips_np, gd->fdt_blob, trips_np) {
type = fdt_getprop(gd->fdt_blob, trips_np, "type", NULL);
if (type) {
if (strcmp(type, "critical") == 0) {
pdata->critical = fdtdec_get_int(gd->fdt_blob,
trips_np,
"temperature",
85);
} else if (strcmp(type, "passive") == 0) {
pdata->alert = fdtdec_get_int(gd->fdt_blob,
trips_np,
"temperature",
80);
}
}
}
debug("id %d polling_delay %d, critical %d, alert %d\n", pdata->id,
pdata->polling_delay, pdata->critical, pdata->alert);
return 0;
}
static const sc_rsrc_t imx8qm_sensor_rsrc[] = {
SC_R_A53, SC_R_A72, SC_R_GPU_0_PID0, SC_R_GPU_1_PID0,
SC_R_DRC_0, SC_R_DRC_1, SC_R_VPU_PID0, SC_R_PMIC_0,
SC_R_PMIC_1, SC_R_PMIC_2,
};
static const sc_rsrc_t imx8qxp_sensor_rsrc[] = {
SC_R_SYSTEM, SC_R_DRC_0, SC_R_PMIC_0,
SC_R_PMIC_1, SC_R_PMIC_2,
};
static const struct udevice_id imx_sc_thermal_ids[] = {
{ .compatible = "nxp,imx8qm-sc-tsens", .data =
(ulong)&imx8qm_sensor_rsrc, },
{ .compatible = "nxp,imx8qxp-sc-tsens", .data =
(ulong)&imx8qxp_sensor_rsrc, },
{ }
};
U_BOOT_DRIVER(imx_sc_thermal) = {
.name = "imx_sc_thermal",
.id = UCLASS_THERMAL,
.ops = &imx_sc_thermal_ops,
.of_match = imx_sc_thermal_ids,
.bind = imx_sc_thermal_bind,
.probe = imx_sc_thermal_probe,
.of_to_plat = imx_sc_thermal_of_to_plat,
.plat_auto = sizeof(struct imx_sc_thermal_plat),
.flags = DM_FLAG_PRE_RELOC,
};