diff options
Diffstat (limited to 'recipes-bsp/u-boot-mainline/files/0003-thermal-add-i.MX8-thermal-driver.patch')
-rw-r--r-- | recipes-bsp/u-boot-mainline/files/0003-thermal-add-i.MX8-thermal-driver.patch | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/recipes-bsp/u-boot-mainline/files/0003-thermal-add-i.MX8-thermal-driver.patch b/recipes-bsp/u-boot-mainline/files/0003-thermal-add-i.MX8-thermal-driver.patch new file mode 100644 index 0000000..93c7bbd --- /dev/null +++ b/recipes-bsp/u-boot-mainline/files/0003-thermal-add-i.MX8-thermal-driver.patch @@ -0,0 +1,257 @@ +From 9151a1401de39c05cbad1270517c31c41bfb576b Mon Sep 17 00:00:00 2001 +From: Peng Fan <peng.fan@nxp.com> +Date: Sun, 5 May 2019 13:23:54 +0000 +Subject: [PATCH 03/15] thermal: add i.MX8 thermal driver + +Add i.MX8 thermal driver to support get temperature from SCU. + +Signed-off-by: Peng Fan <peng.fan@nxp.com> +--- + drivers/thermal/Kconfig | 9 ++ + drivers/thermal/Makefile | 1 + + drivers/thermal/imx_scu_thermal.c | 203 ++++++++++++++++++++++++++++++++++++++ + 3 files changed, 213 insertions(+) + create mode 100644 drivers/thermal/imx_scu_thermal.c + +diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig +index a71b9be5fb..bdf8dc6fef 100644 +--- a/drivers/thermal/Kconfig ++++ b/drivers/thermal/Kconfig +@@ -17,6 +17,15 @@ config IMX_THERMAL + cpufreq is used as the cooling device to throttle CPUs when the + passive trip is crossed. + ++config IMX_SCU_THERMAL ++ bool "Temperature sensor driver for NXP i.MX8" ++ depends on ARCH_IMX8 ++ help ++ Support for Temperature sensors on NXP i.MX8. ++ It supports one critical trip point and one passive trip point. The ++ boot is hold to the cool device to throttle CPUs when the passive ++ trip is crossed ++ + config TI_DRA7_THERMAL + bool "Temperature sensor driver for TI dra7xx SOCs" + help +diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile +index cc75e387e4..ef2929d180 100644 +--- a/drivers/thermal/Makefile ++++ b/drivers/thermal/Makefile +@@ -5,4 +5,5 @@ + + obj-$(CONFIG_DM_THERMAL) += thermal-uclass.o + obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o ++obj-$(CONFIG_IMX_SCU_THERMAL) += imx_scu_thermal.o + obj-$(CONFIG_TI_DRA7_THERMAL) += ti-bandgap.o +diff --git a/drivers/thermal/imx_scu_thermal.c b/drivers/thermal/imx_scu_thermal.c +new file mode 100644 +index 0000000000..7e17377b69 +--- /dev/null ++++ b/drivers/thermal/imx_scu_thermal.c +@@ -0,0 +1,203 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* ++ * Copyright 2019 NXP ++ */ ++ ++#include <config.h> ++#include <common.h> ++#include <dm.h> ++#include <errno.h> ++#include <thermal.h> ++#include <dm/device-internal.h> ++#include <dm/device.h> ++#include <asm/arch/sci/sci.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_platdata(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_platdata(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) has 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; ++ } ++ ++ *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_platdata(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_ofdata_to_platdata(struct udevice *dev) ++{ ++ struct imx_sc_thermal_plat *pdata = dev_get_platdata(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 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,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, ++ .ofdata_to_platdata = imx_sc_thermal_ofdata_to_platdata, ++ .platdata_auto_alloc_size = sizeof(struct imx_sc_thermal_plat), ++ .flags = DM_FLAG_PRE_RELOC, ++}; +-- +2.13.6 + |