[PATCH 00/13] imx: tmu support and scu thermal update

This patchset is to support TMU in i.MX8M family, including i.MX8QM SCU thermal update.
Peng Fan (8): thermal: Add thermal driver for i.MX8M thermal: imx_tmu: Add support for thermal sensor on iMX8MM thermal: imx_tmu: support TMU arch level initialization thermal: imx_tmu: Fix for temperature out of range thermal: imx_tmu: Check the TEMP range for iMX8MM thermal: imx_tmu: support i.MX8MP imx: regs: add more fuse bank structure imx: cpu: support tmu
Ye Li (5): thermal: imx_scu_thermal: Update driver for i.MX8QM thermal sensor imx8mm: Load fuse for TMU TCALIV and TASR imx: i.MX8MN: Enable loading TASR and TCALIV from fuse imx: load calibration parameters from fuse for i.MX8MP imx8mp: Set default SNSR25C for TMU probe1
arch/arm/include/asm/arch-imx8m/imx-regs.h | 41 ++- arch/arm/mach-imx/cpu.c | 4 +- arch/arm/mach-imx/imx8m/soc.c | 75 ++++- drivers/thermal/Kconfig | 9 + drivers/thermal/Makefile | 1 + drivers/thermal/imx_scu_thermal.c | 8 + drivers/thermal/imx_tmu.c | 467 +++++++++++++++++++++++++++++ 7 files changed, 595 insertions(+), 10 deletions(-) create mode 100644 drivers/thermal/imx_tmu.c

From: Ye Li ye.li@nxp.com
Add iMX8QM thermal compatible string and its driver data.
Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Peng Fan peng.fan@nxp.com --- drivers/thermal/imx_scu_thermal.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/drivers/thermal/imx_scu_thermal.c b/drivers/thermal/imx_scu_thermal.c index 7e17377b69..da13121a09 100644 --- a/drivers/thermal/imx_scu_thermal.c +++ b/drivers/thermal/imx_scu_thermal.c @@ -179,12 +179,20 @@ static int imx_sc_thermal_ofdata_to_platdata(struct udevice *dev) 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, }, { }

From: Ye Li ye.li@nxp.com Add iMX8QM thermal compatible string and its driver data. Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Peng Fan peng.fan@nxp.com
Applied to u-boot-imx, master, thanks !
Best regards, Stefano Babic

The driver is ported form Linux Kernel and support driver model. Users need to provide the tmu node and sensors nodes in DTB.
Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Peng Fan peng.fan@nxp.com --- drivers/thermal/Kconfig | 9 ++ drivers/thermal/Makefile | 1 + drivers/thermal/imx_tmu.c | 325 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 335 insertions(+) create mode 100644 drivers/thermal/imx_tmu.c
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index bdf8dc6fef..97d4163e8e 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -26,6 +26,15 @@ config IMX_SCU_THERMAL boot is hold to the cool device to throttle CPUs when the passive trip is crossed
+config IMX_TMU + bool "Thermal Management Unit driver for NXP i.MX8M" + depends on ARCH_IMX8M + help + Support for Temperature sensors on NXP i.MX8M. + 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 ef2929d180..15fe847d9f 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile @@ -7,3 +7,4 @@ 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 +obj-$(CONFIG_IMX_TMU) += imx_tmu.o diff --git a/drivers/thermal/imx_tmu.c b/drivers/thermal/imx_tmu.c new file mode 100644 index 0000000000..f496ce03b6 --- /dev/null +++ b/drivers/thermal/imx_tmu.c @@ -0,0 +1,325 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2017~2020 NXP + * + */ + +#include <config.h> +#include <common.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/sys_proto.h> +#include <dm.h> +#include <dm/device-internal.h> +#include <dm/device.h> +#include <errno.h> +#include <fuse.h> +#include <malloc.h> +#include <thermal.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define SITES_MAX 16 + +#define TMR_DISABLE 0x0 +#define TMR_ME 0x80000000 +#define TMR_ALPF 0x0c000000 +#define TMTMIR_DEFAULT 0x00000002 +#define TIER_DISABLE 0x0 + +/* + * i.MX TMU Registers + */ +struct imx_tmu_site_regs { + u32 tritsr; /* Immediate Temperature Site Register */ + u32 tratsr; /* Average Temperature Site Register */ + u8 res0[0x8]; +}; + +struct imx_tmu_regs { + u32 tmr; /* Mode Register */ + u32 tsr; /* Status Register */ + u32 tmtmir; /* Temperature measurement interval Register */ + u8 res0[0x14]; + u32 tier; /* Interrupt Enable Register */ + u32 tidr; /* Interrupt Detect Register */ + u32 tiscr; /* Interrupt Site Capture Register */ + u32 ticscr; /* Interrupt Critical Site Capture Register */ + u8 res1[0x10]; + u32 tmhtcrh; /* High Temperature Capture Register */ + u32 tmhtcrl; /* Low Temperature Capture Register */ + u8 res2[0x8]; + u32 tmhtitr; /* High Temperature Immediate Threshold */ + u32 tmhtatr; /* High Temperature Average Threshold */ + u32 tmhtactr; /* High Temperature Average Crit Threshold */ + u8 res3[0x24]; + u32 ttcfgr; /* Temperature Configuration Register */ + u32 tscfgr; /* Sensor Configuration Register */ + u8 res4[0x78]; + struct imx_tmu_site_regs site[SITES_MAX]; + u8 res5[0x9f8]; + u32 ipbrr0; /* IP Block Revision Register 0 */ + u32 ipbrr1; /* IP Block Revision Register 1 */ + u8 res6[0x310]; + u32 ttr0cr; /* Temperature Range 0 Control Register */ + u32 ttr1cr; /* Temperature Range 1 Control Register */ + u32 ttr2cr; /* Temperature Range 2 Control Register */ + u32 ttr3cr; /* Temperature Range 3 Control Register */ +}; + +struct imx_tmu_plat { + int critical; + int alert; + int polling_delay; + int id; + bool zone_node; + struct imx_tmu_regs *regs; +}; + +static int read_temperature(struct udevice *dev, int *temp) +{ + struct imx_tmu_plat *pdata = dev_get_platdata(dev); + u32 val; + + do { + val = readl(&pdata->regs->site[pdata->id].tritsr); + } while (!(val & 0x80000000)); + + *temp = (val & 0xff) * 1000; + + return 0; +} + +int imx_tmu_get_temp(struct udevice *dev, int *temp) +{ + struct imx_tmu_plat *pdata = dev_get_platdata(dev); + int cpu_tmp = 0; + int ret; + + ret = read_temperature(dev, &cpu_tmp); + if (ret) + return ret; + + while (cpu_tmp >= pdata->alert) { + printf("CPU Temperature (%dC) has beyond alert (%dC), close to critical (%dC)", cpu_tmp, pdata->alert, pdata->critical); + puts(" waiting...\n"); + mdelay(pdata->polling_delay); + ret = read_temperature(dev, &cpu_tmp); + if (ret) + return ret; + } + + *temp = cpu_tmp / 1000; + + return 0; +} + +static const struct dm_thermal_ops imx_tmu_ops = { + .get_temp = imx_tmu_get_temp, +}; + +static int imx_tmu_calibration(struct udevice *dev) +{ + int i, val, len, ret; + u32 range[4]; + const fdt32_t *calibration; + struct imx_tmu_plat *pdata = dev_get_platdata(dev); + + debug("%s\n", __func__); + + ret = dev_read_u32_array(dev, "fsl,tmu-range", range, 4); + if (ret) { + printf("TMU: missing calibration range, ret = %d.\n", ret); + return ret; + } + + /* Init temperature range registers */ + writel(range[0], &pdata->regs->ttr0cr); + writel(range[1], &pdata->regs->ttr1cr); + writel(range[2], &pdata->regs->ttr2cr); + writel(range[3], &pdata->regs->ttr3cr); + + calibration = dev_read_prop(dev, "fsl,tmu-calibration", &len); + if (!calibration || len % 8) { + printf("TMU: invalid calibration data.\n"); + return -ENODEV; + } + + for (i = 0; i < len; i += 8, calibration += 2) { + val = fdt32_to_cpu(*calibration); + writel(val, &pdata->regs->ttcfgr); + val = fdt32_to_cpu(*(calibration + 1)); + writel(val, &pdata->regs->tscfgr); + } + + return 0; +} + +static void imx_tmu_init(struct imx_tmu_plat *pdata) +{ + debug("%s\n", __func__); + + /* Disable monitoring */ + writel(TMR_DISABLE, &pdata->regs->tmr); + + /* Disable interrupt, using polling instead */ + writel(TIER_DISABLE, &pdata->regs->tier); + + /* Set update_interval */ + writel(TMTMIR_DEFAULT, &pdata->regs->tmtmir); +} + +static int imx_tmu_enable_msite(struct udevice *dev) +{ + struct imx_tmu_plat *pdata = dev_get_platdata(dev); + u32 reg; + + debug("%s\n", __func__); + + if (!pdata->regs) + return -EIO; + + /* Clear the ME before setting MSITE and ALPF*/ + reg = readl(&pdata->regs->tmr); + reg &= ~TMR_ME; + writel(reg, &pdata->regs->tmr); + + reg |= 1 << (15 - pdata->id); + reg |= TMR_ALPF; + writel(reg, &pdata->regs->tmr); + + /* Enable ME */ + reg |= TMR_ME; + writel(reg, &pdata->regs->tmr); + + return 0; +} + +static int imx_tmu_bind(struct udevice *dev) +{ + struct imx_tmu_plat *pdata = dev_get_platdata(dev); + int ret; + ofnode node, offset; + const char *name; + const void *prop; + + debug("%s dev name %s\n", __func__, dev->name); + + prop = dev_read_prop(dev, "compatible", NULL); + if (!prop) + return 0; + + pdata->zone_node = 1; + + node = ofnode_path("/thermal-zones"); + ofnode_for_each_subnode(offset, node) { + /* Bind the subnode to this driver */ + name = ofnode_get_name(offset); + + ret = device_bind_with_driver_data(dev, dev->driver, name, + dev->driver_data, offset, + NULL); + if (ret) + printf("Error binding driver '%s': %d\n", + dev->driver->name, ret); + } + + return 0; +} + +static int imx_tmu_parse_fdt(struct udevice *dev) +{ + struct imx_tmu_plat *pdata = dev_get_platdata(dev), *p_parent_data; + struct ofnode_phandle_args args; + ofnode trips_np; + int ret; + + debug("%s dev name %s\n", __func__, dev->name); + + if (pdata->zone_node) { + pdata->regs = (struct imx_tmu_regs *)dev_read_addr_ptr(dev); + + if (!pdata->regs) + return -EINVAL; + return 0; + } + + p_parent_data = dev_get_platdata(dev->parent); + if (p_parent_data->zone_node) + pdata->regs = p_parent_data->regs; + + ret = dev_read_phandle_with_args(dev, "thermal-sensors", + "#thermal-sensor-cells", + 0, 0, &args); + if (ret) + return ret; + + if (!ofnode_equal(args.node, dev_ofnode(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 = dev_read_u32_default(dev, "polling-delay", 1000); + + trips_np = ofnode_path("/thermal-zones/cpu-thermal/trips"); + ofnode_for_each_subnode(trips_np, trips_np) { + const char *type; + + type = ofnode_get_property(trips_np, "type", NULL); + if (!type) + continue; + if (!strcmp(type, "critical")) + pdata->critical = ofnode_read_u32_default(trips_np, "temperature", 85); + else if (strcmp(type, "passive") == 0) + pdata->alert = ofnode_read_u32_default(trips_np, "temperature", 80); + else + continue; + } + + debug("id %d polling_delay %d, critical %d, alert %d\n", + pdata->id, pdata->polling_delay, pdata->critical, pdata->alert); + + return 0; +} + +static int imx_tmu_probe(struct udevice *dev) +{ + struct imx_tmu_plat *pdata = dev_get_platdata(dev); + int ret; + + ret = imx_tmu_parse_fdt(dev); + if (ret) { + printf("Error in parsing TMU FDT %d\n", ret); + return ret; + } + + if (pdata->zone_node) { + imx_tmu_init(pdata); + imx_tmu_calibration(dev); + } else { + imx_tmu_enable_msite(dev); + } + + return 0; +} + +static const struct udevice_id imx_tmu_ids[] = { + { .compatible = "fsl,imx8mq-tmu", }, + { } +}; + +U_BOOT_DRIVER(imx_tmu) = { + .name = "imx_tmu", + .id = UCLASS_THERMAL, + .ops = &imx_tmu_ops, + .of_match = imx_tmu_ids, + .bind = imx_tmu_bind, + .probe = imx_tmu_probe, + .platdata_auto_alloc_size = sizeof(struct imx_tmu_plat), + .flags = DM_FLAG_PRE_RELOC, +};

The driver is ported form Linux Kernel and support driver model. Users need to provide the tmu node and sensors nodes in DTB. Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Peng Fan peng.fan@nxp.com
Applied to u-boot-imx, master, thanks !
Best regards, Stefano Babic

The analog sensors on iMX8MM are new, used for 14LPP process. So the Temperature Sensor Monitoring Unit (TMU) has some change accordingly. We use version 2 in TMU driver to represent the new TMU, so the one driver can service for both i.MX8MQ/M.
Signed-off-by: Peng Fan peng.fan@nxp.com --- drivers/thermal/imx_tmu.c | 113 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 86 insertions(+), 27 deletions(-)
diff --git a/drivers/thermal/imx_tmu.c b/drivers/thermal/imx_tmu.c index f496ce03b6..df0b35b7ba 100644 --- a/drivers/thermal/imx_tmu.c +++ b/drivers/thermal/imx_tmu.c @@ -20,6 +20,7 @@ DECLARE_GLOBAL_DATA_PTR;
#define SITES_MAX 16 +#define FLAGS_VER2 0x1
#define TMR_DISABLE 0x0 #define TMR_ME 0x80000000 @@ -27,6 +28,8 @@ DECLARE_GLOBAL_DATA_PTR; #define TMTMIR_DEFAULT 0x00000002 #define TIER_DISABLE 0x0
+#define TER_EN 0x80000000 +#define TER_ADC_PD 0x40000000 /* * i.MX TMU Registers */ @@ -67,22 +70,47 @@ struct imx_tmu_regs { u32 ttr3cr; /* Temperature Range 3 Control Register */ };
+struct imx_tmu_regs_v2 { + u32 ter; /* TMU enable Register */ + u32 tsr; /* Status Register */ + u32 tier; /* Interrupt enable register */ + u32 tidr; /* Interrupt detect register */ + u32 tmhtitr; /* Monitor high temperature immediate threshold register */ + u32 tmhtatr; /* Monitor high temperature average threshold register */ + u32 tmhtactr; /* TMU monitor high temperature average critical threshold register */ + u32 tscr; /* Sensor value capture register */ + u32 tritsr; /* Report immediate temperature site register 0 */ + u32 tratsr; /* Report average temperature site register 0 */ + u32 tasr; /* Amplifier setting register */ + u32 ttmc; /* Test MUX control */ + u32 tcaliv; +}; + +union tmu_regs { + struct imx_tmu_regs regs_v1; + struct imx_tmu_regs_v2 regs_v2; +}; + struct imx_tmu_plat { int critical; int alert; int polling_delay; int id; bool zone_node; - struct imx_tmu_regs *regs; + union tmu_regs *regs; };
static int read_temperature(struct udevice *dev, int *temp) { struct imx_tmu_plat *pdata = dev_get_platdata(dev); + ulong drv_data = dev_get_driver_data(dev); u32 val;
do { - val = readl(&pdata->regs->site[pdata->id].tritsr); + if (drv_data & FLAGS_VER2) { + val = readl(&pdata->regs->regs_v2.tritsr); + else + val = readl(&pdata->regs->regs_v1.site[pdata->id].tritsr); } while (!(val & 0x80000000));
*temp = (val & 0xff) * 1000; @@ -124,9 +152,13 @@ static int imx_tmu_calibration(struct udevice *dev) u32 range[4]; const fdt32_t *calibration; struct imx_tmu_plat *pdata = dev_get_platdata(dev); + ulong drv_data = dev_get_driver_data(dev);
debug("%s\n", __func__);
+ if (drv_data & FLAGS_VER2) + return 0; + ret = dev_read_u32_array(dev, "fsl,tmu-range", range, 4); if (ret) { printf("TMU: missing calibration range, ret = %d.\n", ret); @@ -134,10 +166,10 @@ static int imx_tmu_calibration(struct udevice *dev) }
/* Init temperature range registers */ - writel(range[0], &pdata->regs->ttr0cr); - writel(range[1], &pdata->regs->ttr1cr); - writel(range[2], &pdata->regs->ttr2cr); - writel(range[3], &pdata->regs->ttr3cr); + writel(range[0], &pdata->regs->regs_v1.ttr0cr); + writel(range[1], &pdata->regs->regs_v1.ttr1cr); + writel(range[2], &pdata->regs->regs_v1.ttr2cr); + writel(range[3], &pdata->regs->regs_v1.ttr3cr);
calibration = dev_read_prop(dev, "fsl,tmu-calibration", &len); if (!calibration || len % 8) { @@ -147,31 +179,43 @@ static int imx_tmu_calibration(struct udevice *dev)
for (i = 0; i < len; i += 8, calibration += 2) { val = fdt32_to_cpu(*calibration); - writel(val, &pdata->regs->ttcfgr); + writel(val, &pdata->regs->regs_v1.ttcfgr); val = fdt32_to_cpu(*(calibration + 1)); - writel(val, &pdata->regs->tscfgr); + writel(val, &pdata->regs->regs_v1.tscfgr); }
return 0; }
-static void imx_tmu_init(struct imx_tmu_plat *pdata) +static void imx_tmu_init(struct udevice *dev) { + struct imx_tmu_plat *pdata = dev_get_platdata(dev); + ulong drv_data = dev_get_driver_data(dev); + debug("%s\n", __func__);
- /* Disable monitoring */ - writel(TMR_DISABLE, &pdata->regs->tmr); + if (drv_data & FLAGS_VER2) { + /* Disable monitoring */ + writel(0x0, &pdata->regs->regs_v2.ter); + + /* Disable interrupt, using polling instead */ + writel(0x0, &pdata->regs->regs_v2.tier); + } else { + /* Disable monitoring */ + writel(TMR_DISABLE, &pdata->regs->regs_v1.tmr);
- /* Disable interrupt, using polling instead */ - writel(TIER_DISABLE, &pdata->regs->tier); + /* Disable interrupt, using polling instead */ + writel(TIER_DISABLE, &pdata->regs->regs_v1.tier);
- /* Set update_interval */ - writel(TMTMIR_DEFAULT, &pdata->regs->tmtmir); + /* Set update_interval */ + writel(TMTMIR_DEFAULT, &pdata->regs->regs_v1.tmtmir); + } }
static int imx_tmu_enable_msite(struct udevice *dev) { struct imx_tmu_plat *pdata = dev_get_platdata(dev); + ulong drv_data = dev_get_driver_data(dev); u32 reg;
debug("%s\n", __func__); @@ -179,18 +223,32 @@ static int imx_tmu_enable_msite(struct udevice *dev) if (!pdata->regs) return -EIO;
- /* Clear the ME before setting MSITE and ALPF*/ - reg = readl(&pdata->regs->tmr); - reg &= ~TMR_ME; - writel(reg, &pdata->regs->tmr); + if (drv_data & FLAGS_VER2) { + reg = readl(&pdata->regs->regs_v2.ter); + reg &= ~TER_EN; + writel(reg, &pdata->regs->regs_v2.ter);
- reg |= 1 << (15 - pdata->id); - reg |= TMR_ALPF; - writel(reg, &pdata->regs->tmr); + reg &= ~TER_ALPF; + reg |= 0x1; + writel(reg, &pdata->regs->regs_v2.ter);
- /* Enable ME */ - reg |= TMR_ME; - writel(reg, &pdata->regs->tmr); + /* Enable monitor */ + reg |= TER_EN; + writel(reg, &pdata->regs->regs_v2.ter); + } else { + /* Clear the ME before setting MSITE and ALPF*/ + reg = readl(&pdata->regs->regs_v1.tmr); + reg &= ~TMR_ME; + writel(reg, &pdata->regs->regs_v1.tmr); + + reg |= 1 << (15 - pdata->id); + reg |= TMR_ALPF; + writel(reg, &pdata->regs->regs_v1.tmr); + + /* Enable ME */ + reg |= TMR_ME; + writel(reg, &pdata->regs->regs_v1.tmr); + }
return 0; } @@ -237,7 +295,7 @@ static int imx_tmu_parse_fdt(struct udevice *dev) debug("%s dev name %s\n", __func__, dev->name);
if (pdata->zone_node) { - pdata->regs = (struct imx_tmu_regs *)dev_read_addr_ptr(dev); + pdata->regs = (union tmu_regs *)dev_read_addr_ptr(dev);
if (!pdata->regs) return -EINVAL; @@ -299,7 +357,7 @@ static int imx_tmu_probe(struct udevice *dev) }
if (pdata->zone_node) { - imx_tmu_init(pdata); + imx_tmu_init(dev); imx_tmu_calibration(dev); } else { imx_tmu_enable_msite(dev); @@ -310,6 +368,7 @@ static int imx_tmu_probe(struct udevice *dev)
static const struct udevice_id imx_tmu_ids[] = { { .compatible = "fsl,imx8mq-tmu", }, + { .compatible = "fsl,imx8mm-tmu", .data = FLAGS_VER2, }, { } };

The analog sensors on iMX8MM are new, used for 14LPP process. So the Temperature Sensor Monitoring Unit (TMU) has some change accordingly. We use version 2 in TMU driver to represent the new TMU, so the one driver can service for both i.MX8MQ/M. Signed-off-by: Peng Fan peng.fan@nxp.com
Applied to u-boot-imx, master, thanks !
Best regards, Stefano Babic

i.MX8MM TMU needs to load some registers from fuse, this is arch dependent operation and may vary on different platforms. So add a interface for arch level initialization.
Signed-off-by: Peng Fan peng.fan@nxp.com --- drivers/thermal/imx_tmu.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/thermal/imx_tmu.c b/drivers/thermal/imx_tmu.c index df0b35b7ba..049f32c39e 100644 --- a/drivers/thermal/imx_tmu.c +++ b/drivers/thermal/imx_tmu.c @@ -187,6 +187,10 @@ static int imx_tmu_calibration(struct udevice *dev) return 0; }
+void __weak imx_tmu_arch_init(void *reg_base) +{ +} + static void imx_tmu_init(struct udevice *dev) { struct imx_tmu_plat *pdata = dev_get_platdata(dev); @@ -210,6 +214,8 @@ static void imx_tmu_init(struct udevice *dev) /* Set update_interval */ writel(TMTMIR_DEFAULT, &pdata->regs->regs_v1.tmtmir); } + + imx_tmu_arch_init((void *)pdata->regs); }
static int imx_tmu_enable_msite(struct udevice *dev)

i.MX8MM TMU needs to load some registers from fuse, this is arch dependent operation and may vary on different platforms. So add a interface for arch level initialization. Signed-off-by: Peng Fan peng.fan@nxp.com
Applied to u-boot-imx, master, thanks !
Best regards, Stefano Babic

When the temperature is out of sensor's range, the Valid bit won't be set in TRITSR register. So the polling loop won't go out.
Change the codes to retry 10 times with 100ms interval for the Valid bit. If the timeout, we give a warning for the invalid data.
Modifed from Ye's NXP patch
Signed-off-by: Peng Fan peng.fan@nxp.com --- drivers/thermal/imx_tmu.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/drivers/thermal/imx_tmu.c b/drivers/thermal/imx_tmu.c index 049f32c39e..2a08d5085c 100644 --- a/drivers/thermal/imx_tmu.c +++ b/drivers/thermal/imx_tmu.c @@ -105,15 +105,22 @@ static int read_temperature(struct udevice *dev, int *temp) struct imx_tmu_plat *pdata = dev_get_platdata(dev); ulong drv_data = dev_get_driver_data(dev); u32 val; + u32 retry = 10;
do { - if (drv_data & FLAGS_VER2) { + mdelay(100); + retry--; + + if (drv_data & FLAGS_VER2) val = readl(&pdata->regs->regs_v2.tritsr); else val = readl(&pdata->regs->regs_v1.site[pdata->id].tritsr); - } while (!(val & 0x80000000)); + } while (!(val & 0x80000000) && retry > 0);
- *temp = (val & 0xff) * 1000; + if (retry > 0) + *temp = (val & 0xff) * 1000; + else + return -EINVAL;
return 0; }

When the temperature is out of sensor's range, the Valid bit won't be set in TRITSR register. So the polling loop won't go out. Change the codes to retry 10 times with 100ms interval for the Valid bit. If the timeout, we give a warning for the invalid data. Modifed from Ye's NXP patch Signed-off-by: Peng Fan peng.fan@nxp.com
Applied to u-boot-imx, master, thanks !
Best regards, Stefano Babic

On iMX8MM, the V flag in TRISTR register only reflect the state of SNSR value, not the calibrated TEMP value. So checking this flag is not reliable. Per IC suggestion, change to read the TEMP/AVG_TEMP directly and check whether it in valid range 10-125C.
Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Peng Fan peng.fan@nxp.com --- drivers/thermal/imx_tmu.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/drivers/thermal/imx_tmu.c b/drivers/thermal/imx_tmu.c index 2a08d5085c..c577b0bd6c 100644 --- a/drivers/thermal/imx_tmu.c +++ b/drivers/thermal/imx_tmu.c @@ -106,16 +106,24 @@ static int read_temperature(struct udevice *dev, int *temp) ulong drv_data = dev_get_driver_data(dev); u32 val; u32 retry = 10; + u32 valid = 0;
do { mdelay(100); retry--;
- if (drv_data & FLAGS_VER2) + if (drv_data & FLAGS_VER2) { val = readl(&pdata->regs->regs_v2.tritsr); - else + /* + * Check if TEMP is in valid range, the V bit in TRITSR + * only reflects the RAW uncalibrated data + */ + valid = ((val & 0xff) < 10 || (val & 0xff) > 125) ? 0 : 1; + } else { val = readl(&pdata->regs->regs_v1.site[pdata->id].tritsr); - } while (!(val & 0x80000000) && retry > 0); + valid = val & 0x80000000; + } + } while (!valid && retry > 0);
if (retry > 0) *temp = (val & 0xff) * 1000;

On iMX8MM, the V flag in TRISTR register only reflect the state of SNSR value, not the calibrated TEMP value. So checking this flag is not reliable. Per IC suggestion, change to read the TEMP/AVG_TEMP directly and check whether it in valid range 10-125C. Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Peng Fan peng.fan@nxp.com
Applied to u-boot-imx, master, thanks !
Best regards, Stefano Babic

Support i.MX8MP thermal which has two probes and supports temperature range from -40 to 125. Still uses default 1p HW calibration at 25C and loads calibration parameters from fuse.
Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Peng Fan peng.fan@nxp.com --- drivers/thermal/imx_tmu.c | 76 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 69 insertions(+), 7 deletions(-)
diff --git a/drivers/thermal/imx_tmu.c b/drivers/thermal/imx_tmu.c index c577b0bd6c..4ca22089b8 100644 --- a/drivers/thermal/imx_tmu.c +++ b/drivers/thermal/imx_tmu.c @@ -21,6 +21,7 @@ DECLARE_GLOBAL_DATA_PTR;
#define SITES_MAX 16 #define FLAGS_VER2 0x1 +#define FLAGS_VER3 0x2
#define TMR_DISABLE 0x0 #define TMR_ME 0x80000000 @@ -30,6 +31,8 @@ DECLARE_GLOBAL_DATA_PTR;
#define TER_EN 0x80000000 #define TER_ADC_PD 0x40000000 +#define TER_ALPF 0x3 + /* * i.MX TMU Registers */ @@ -86,9 +89,29 @@ struct imx_tmu_regs_v2 { u32 tcaliv; };
+struct imx_tmu_regs_v3 { + u32 ter; /* TMU enable Register */ + u32 tps; /* Status Register */ + u32 tier; /* Interrupt enable register */ + u32 tidr; /* Interrupt detect register */ + u32 tmhtitr; /* Monitor high temperature immediate threshold register */ + u32 tmhtatr; /* Monitor high temperature average threshold register */ + u32 tmhtactr; /* TMU monitor high temperature average critical threshold register */ + u32 tscr; /* Sensor value capture register */ + u32 tritsr; /* Report immediate temperature site register 0 */ + u32 tratsr; /* Report average temperature site register 0 */ + u32 tasr; /* Amplifier setting register */ + u32 ttmc; /* Test MUX control */ + u32 tcaliv0; + u32 tcaliv1; + u32 tcaliv_m40; + u32 trim; +}; + union tmu_regs { struct imx_tmu_regs regs_v1; struct imx_tmu_regs_v2 regs_v2; + struct imx_tmu_regs_v3 regs_v3; };
struct imx_tmu_plat { @@ -112,7 +135,10 @@ static int read_temperature(struct udevice *dev, int *temp) mdelay(100); retry--;
- if (drv_data & FLAGS_VER2) { + if (drv_data & FLAGS_VER3) { + val = readl(&pdata->regs->regs_v3.tritsr); + valid = val & (1 << (30 + pdata->id)); + } else if (drv_data & FLAGS_VER2) { val = readl(&pdata->regs->regs_v2.tritsr); /* * Check if TEMP is in valid range, the V bit in TRITSR @@ -125,10 +151,23 @@ static int read_temperature(struct udevice *dev, int *temp) } } while (!valid && retry > 0);
- if (retry > 0) - *temp = (val & 0xff) * 1000; - else + if (retry > 0) { + if (drv_data & FLAGS_VER3) { + val = (val >> (pdata->id * 16)) & 0xff; + if (val & 0x80) /* Negative */ + val = (~(val & 0x7f) + 1); + + *temp = val; + if (*temp < -40 || *temp > 125) /* Check the range */ + return -EINVAL; + + *temp *= 1000; + } else { + *temp = (val & 0xff) * 1000; + } + } else { return -EINVAL; + }
return 0; } @@ -171,7 +210,7 @@ static int imx_tmu_calibration(struct udevice *dev)
debug("%s\n", __func__);
- if (drv_data & FLAGS_VER2) + if (drv_data & (FLAGS_VER2 | FLAGS_VER3)) return 0;
ret = dev_read_u32_array(dev, "fsl,tmu-range", range, 4); @@ -213,7 +252,14 @@ static void imx_tmu_init(struct udevice *dev)
debug("%s\n", __func__);
- if (drv_data & FLAGS_VER2) { + if (drv_data & FLAGS_VER3) { + /* Disable monitoring */ + writel(0x0, &pdata->regs->regs_v3.ter); + + /* Disable interrupt, using polling instead */ + writel(0x0, &pdata->regs->regs_v3.tier); + + } else if (drv_data & FLAGS_VER2) { /* Disable monitoring */ writel(0x0, &pdata->regs->regs_v2.ter);
@@ -244,7 +290,22 @@ static int imx_tmu_enable_msite(struct udevice *dev) if (!pdata->regs) return -EIO;
- if (drv_data & FLAGS_VER2) { + if (drv_data & FLAGS_VER3) { + reg = readl(&pdata->regs->regs_v3.ter); + reg &= ~TER_EN; + writel(reg, &pdata->regs->regs_v3.ter); + + writel(pdata->id << 30, &pdata->regs->regs_v3.tps); + + reg &= ~TER_ALPF; + reg |= 0x1; + reg &= ~TER_ADC_PD; + writel(reg, &pdata->regs->regs_v3.ter); + + /* Enable monitor */ + reg |= TER_EN; + writel(reg, &pdata->regs->regs_v3.ter); + } else if (drv_data & FLAGS_VER2) { reg = readl(&pdata->regs->regs_v2.ter); reg &= ~TER_EN; writel(reg, &pdata->regs->regs_v2.ter); @@ -390,6 +451,7 @@ static int imx_tmu_probe(struct udevice *dev) static const struct udevice_id imx_tmu_ids[] = { { .compatible = "fsl,imx8mq-tmu", }, { .compatible = "fsl,imx8mm-tmu", .data = FLAGS_VER2, }, + { .compatible = "fsl,imx8mp-tmu", .data = FLAGS_VER3, }, { } };

Support i.MX8MP thermal which has two probes and supports temperature range from -40 to 125. Still uses default 1p HW calibration at 25C and loads calibration parameters from fuse. Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Peng Fan peng.fan@nxp.com
Applied to u-boot-imx, master, thanks !
Best regards, Stefano Babic

From: Ye Li ye.li@nxp.com
On iMX8MM, the default value of TMU registers TCALIV and TASR need be loaded from fuse. HW won't do this, it expect SW loads them before using TMU.
Reviewed-by: Bai Ping ping.bai@nxp.com Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Peng Fan peng.fan@nxp.com --- arch/arm/mach-imx/imx8m/soc.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c index 7fcbd53f30..6567936f4b 100644 --- a/arch/arm/mach-imx/imx8m/soc.c +++ b/arch/arm/mach-imx/imx8m/soc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright 2017 NXP + * Copyright 2017-2019 NXP * * Peng Fan peng.fan@nxp.com */ @@ -400,3 +400,29 @@ void reset_cpu(ulong addr) } } #endif + +void imx_tmu_arch_init(void *reg_base) +{ + if (is_imx8mm()) { + /* Load TCALIV and TASR from fuses */ + struct ocotp_regs *ocotp = + (struct ocotp_regs *)OCOTP_BASE_ADDR; + struct fuse_bank *bank = &ocotp->bank[3]; + struct fuse_bank3_regs *fuse = + (struct fuse_bank3_regs *)bank->fuse_regs; + + u32 tca_rt, tca_hr, tca_en; + u32 buf_vref, buf_slope; + + tca_rt = fuse->ana0 & 0xFF; + tca_hr = (fuse->ana0 & 0xFF00) >> 8; + tca_en = (fuse->ana0 & 0x2000000) >> 25; + + buf_vref = (fuse->ana0 & 0x1F00000) >> 20; + buf_slope = (fuse->ana0 & 0xF0000) >> 16; + + writel(buf_vref | (buf_slope << 16), (ulong)reg_base + 0x28); + writel((tca_en << 31) | (tca_hr << 16) | tca_rt, + (ulong)reg_base + 0x30); + } +}

From: Ye Li ye.li@nxp.com On iMX8MM, the default value of TMU registers TCALIV and TASR need be loaded from fuse. HW won't do this, it expect SW loads them before using TMU. Reviewed-by: Bai Ping ping.bai@nxp.com Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Peng Fan peng.fan@nxp.com
Applied to u-boot-imx, master, thanks !
Best regards, Stefano Babic

From: Ye Li ye.li@nxp.com
Like iMX8MM, iMX8MN also needs SW to load TMU TASR and TCALIV registers value from fuse before enabling TMU calibration. Otherwise the calibration is not exact.
Reviewed-by: Anson Huang Anson.Huang@nxp.com Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Peng Fan peng.fan@nxp.com --- arch/arm/mach-imx/imx8m/soc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c index 6567936f4b..1f42455aa0 100644 --- a/arch/arm/mach-imx/imx8m/soc.c +++ b/arch/arm/mach-imx/imx8m/soc.c @@ -403,7 +403,7 @@ void reset_cpu(ulong addr)
void imx_tmu_arch_init(void *reg_base) { - if (is_imx8mm()) { + if (is_imx8mm() || is_imx8mn()) { /* Load TCALIV and TASR from fuses */ struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;

From: Ye Li ye.li@nxp.com Like iMX8MM, iMX8MN also needs SW to load TMU TASR and TCALIV registers value from fuse before enabling TMU calibration. Otherwise the calibration is not exact. Reviewed-by: Anson Huang Anson.Huang@nxp.com Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Peng Fan peng.fan@nxp.com
Applied to u-boot-imx, master, thanks !
Best regards, Stefano Babic

From: Ye Li ye.li@nxp.com
i.MX8MP thermal which has two probes and supports temperature range from -40 to 125. The driver still uses default 1p HW calibration at 25C and loads calibration parameters from fuse.
Reviewed-by: Peng Fan peng.fan@nxp.com Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Peng Fan peng.fan@nxp.com --- arch/arm/mach-imx/imx8m/soc.c | 45 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+)
diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c index 1f42455aa0..adb444b240 100644 --- a/arch/arm/mach-imx/imx8m/soc.c +++ b/arch/arm/mach-imx/imx8m/soc.c @@ -425,4 +425,49 @@ void imx_tmu_arch_init(void *reg_base) writel((tca_en << 31) | (tca_hr << 16) | tca_rt, (ulong)reg_base + 0x30); } +#ifdef CONFIG_IMX8MP + /* Load TCALIV0/1/m40 and TRIM from fuses */ + struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR; + struct fuse_bank *bank = &ocotp->bank[38]; + struct fuse_bank38_regs *fuse = + (struct fuse_bank38_regs *)bank->fuse_regs; + struct fuse_bank *bank2 = &ocotp->bank[39]; + struct fuse_bank39_regs *fuse2 = + (struct fuse_bank39_regs *)bank2->fuse_regs; + u32 buf_vref, buf_slope, bjt_cur, vlsb, bgr; + u32 reg; + u32 tca40[2], tca25[2], tca105[2]; + + /* For blank sample */ + if (!fuse->ana_trim2 && !fuse->ana_trim3 && + !fuse->ana_trim4 && !fuse2->ana_trim5) { + /* Use a default 25C binary codes */ + tca25[0] = 1596; + writel(tca25[0], (ulong)reg_base + 0x30); + return; + } + + buf_vref = (fuse->ana_trim2 & 0xc0) >> 6; + buf_slope = (fuse->ana_trim2 & 0xF00) >> 8; + bjt_cur = (fuse->ana_trim2 & 0xF000) >> 12; + bgr = (fuse->ana_trim2 & 0xF0000) >> 16; + vlsb = (fuse->ana_trim2 & 0xF00000) >> 20; + writel(buf_vref | (buf_slope << 16), (ulong)reg_base + 0x28); + + reg = (bgr << 28) | (bjt_cur << 20) | (vlsb << 12) | (1 << 7); + writel(reg, (ulong)reg_base + 0x3c); + + tca40[0] = (fuse->ana_trim3 & 0xFFF0000) >> 16; + tca25[0] = (fuse->ana_trim3 & 0xF0000000) >> 28; + tca25[0] |= ((fuse->ana_trim4 & 0xFF) << 4); + tca105[0] = (fuse->ana_trim4 & 0xFFF00) >> 8; + tca40[1] = (fuse->ana_trim4 & 0xFFF00000) >> 20; + tca25[1] = fuse2->ana_trim5 & 0xFFF; + tca105[1] = (fuse2->ana_trim5 & 0xFFF000) >> 12; + + /* use 25c for 1p calibration */ + writel(tca25[0] | (tca105[0] << 16), (ulong)reg_base + 0x30); + writel(tca25[1] | (tca105[1] << 16), (ulong)reg_base + 0x34); + writel(tca40[0] | (tca40[1] << 16), (ulong)reg_base + 0x38); +#endif }

Hi Peng and Ye Li,
On Sun, May 3, 2020 at 10:57 AM Peng Fan peng.fan@nxp.com wrote:
From: Ye Li ye.li@nxp.com
i.MX8MP thermal which has two probes and supports temperature range from -40 to 125. The driver still uses default 1p HW calibration at 25C and loads calibration parameters from fuse.
Reviewed-by: Peng Fan peng.fan@nxp.com Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Peng Fan peng.fan@nxp.com
Are you able to boot an NXP 5.4.3 kernel on a i.MX8MP EVK board?
I am getting a kernel hang right after the serial console is probed: https://pastebin.com/3AtvJqWS
Any suggestions?
I am using ATF from 5.4.3, firmware version is 8.6 and I pass 'export ATF_LOAD_ADDR=0x960000'.
Any ideas?
Thanks

Hi Fabio,
Subject: Re: [PATCH 10/13] imx: load calibration parameters from fuse for i.MX8MP
Hi Peng and Ye Li,
On Sun, May 3, 2020 at 10:57 AM Peng Fan peng.fan@nxp.com wrote:
From: Ye Li ye.li@nxp.com
i.MX8MP thermal which has two probes and supports temperature range from -40 to 125. The driver still uses default 1p HW calibration at 25C and loads calibration parameters from fuse.
Reviewed-by: Peng Fan peng.fan@nxp.com Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Peng Fan peng.fan@nxp.com
Are you able to boot an NXP 5.4.3 kernel on a i.MX8MP EVK board?
5.4.3 upstream kernel + latest upstream uboot?
I am getting a kernel hang right after the serial console is probed: https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpasteb in.com%2F3AtvJqWS&data=02%7C01%7Cpeng.fan%40nxp.com%7Cf3d1 e46ad41e4ca90b0608d7ef73f349%7C686ea1d3bc2b4c6fa92cd99c5c301635 %7C0%7C0%7C637241153594873754&sdata=gjGygSnftYVH58eLW%2By 6ZZ4uczLZUM0U0lUk9LQyx5Y%3D&reserved=0
Any suggestions?
I am using ATF from 5.4.3, firmware version is 8.6 and I pass 'export ATF_LOAD_ADDR=0x960000'.
Any ideas?
I am not holiday, not have a board at handle. I will give a try in a few days.
Disable busfreq, try clk_ignore_unused?
Regards, Peng.
Thanks

Hi Peng,
On Sun, May 3, 2020 at 8:39 PM Peng Fan peng.fan@nxp.com wrote:
5.4.3 upstream kernel + latest upstream boot?
No, I meant imx_5.4.3_2.0.0 NXP kernel + latest upstream U-Boot.
Disable busfreq, try clk_ignore_unused?
There is no way to disable busfreq from the NXP kernel. Passing clk_ignore_unused does not help either.
I have also tried to boot NXP 5.4.3 on a i.MX8MM EVK with the latest U-Boot and I also observe a hang.

Subject: Re: [PATCH 10/13] imx: load calibration parameters from fuse for i.MX8MP
Hi Peng,
On Sun, May 3, 2020 at 8:39 PM Peng Fan peng.fan@nxp.com wrote:
5.4.3 upstream kernel + latest upstream boot?
No, I meant imx_5.4.3_2.0.0 NXP kernel + latest upstream U-Boot.
Disable busfreq, try clk_ignore_unused?
There is no way to disable busfreq from the NXP kernel. Passing clk_ignore_unused does not help either.
Busfreq could be disabled by set the device tree node to disabled.
I have also tried to boot NXP 5.4.3 on a i.MX8MM EVK with the latest U-Boot and I also observe a hang.
I'll give a try tomorrow when I back to office. There is a ARM clock issue that could cause all i.MX8M kernel hang, but that should be a bit late, should not be that early just after console enabled.
Regards, Peng.

Hi Peng,
On Mon, May 4, 2020 at 11:50 PM Peng Fan peng.fan@nxp.com wrote:
Busfreq could be disabled by set the device tree node to disabled.
This does not help. If I use the NXP U-Boot I can boot the NXP 5.4.3 without problems.
I have also tried to boot NXP 5.4.3 on a i.MX8MM EVK with the latest U-Boot and I also observe a hang.
I'll give a try tomorrow when I back to office. There is a ARM clock issue that could cause all i.MX8M kernel hang, but that should be a bit late, should not be that early just after console enabled.
Currently, we can not even boot to the U-Boot prompt with mainline U-Boot.
Reverting f24dea4e1b ("ARM: imx8m: Fix reset in SPL on NXP iMX8MP EVK") allows it to boot again.
As discussed in the other thread, this means that the i.MX8MP clock driver is broken.
Please let me know if you can look at these issues.
Thanks

Subject: Re: [PATCH 10/13] imx: load calibration parameters from fuse for i.MX8MP
Hi Peng,
On Mon, May 4, 2020 at 11:50 PM Peng Fan peng.fan@nxp.com wrote:
Busfreq could be disabled by set the device tree node to disabled.
This does not help. If I use the NXP U-Boot I can boot the NXP 5.4.3 without problems.
I have also tried to boot NXP 5.4.3 on a i.MX8MM EVK with the latest U-Boot and I also observe a hang.
I'll give a try tomorrow when I back to office. There is a ARM clock issue that could cause all i.MX8M kernel hang, but that should be a bit late, should not be that early just after console enabled.
Currently, we can not even boot to the U-Boot prompt with mainline U-Boot.
Reverting f24dea4e1b ("ARM: imx8m: Fix reset in SPL on NXP iMX8MP EVK") allows it to boot again.
As discussed in the other thread, this means that the i.MX8MP clock driver is broken.
Please let me know if you can look at these issues.
I'll give a look. Thanks for raising the issue.
Thanks, Peng.
Thanks

Hi Peng,
On Wed, May 6, 2020 at 9:08 PM Peng Fan peng.fan@nxp.com wrote:
I'll give a look. Thanks for raising the issue.
I understand the issue now. I will send a patch soon.
Thanks

From: Ye Li ye.li@nxp.com i.MX8MP thermal which has two probes and supports temperature range from -40 to 125. The driver still uses default 1p HW calibration at 25C and loads calibration parameters from fuse. Reviewed-by: Peng Fan peng.fan@nxp.com Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Peng Fan peng.fan@nxp.com
Applied to u-boot-imx, master, thanks !
Best regards, Stefano Babic

From: Ye Li ye.li@nxp.com
So far u-boot only load SNSR25C for TMU main probe (probe 0). However, kernel enables two probes. So it also needs to set default SNSR25C of TCALIV1 for blank samples.
Reviewed-by: Peng Fan peng.fan@nxp.com Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Peng Fan peng.fan@nxp.com --- arch/arm/mach-imx/imx8m/soc.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c index adb444b240..c1e0f01f90 100644 --- a/arch/arm/mach-imx/imx8m/soc.c +++ b/arch/arm/mach-imx/imx8m/soc.c @@ -443,7 +443,9 @@ void imx_tmu_arch_init(void *reg_base) !fuse->ana_trim4 && !fuse2->ana_trim5) { /* Use a default 25C binary codes */ tca25[0] = 1596; + tca25[1] = 1596; writel(tca25[0], (ulong)reg_base + 0x30); + writel(tca25[1], (ulong)reg_base + 0x34); return; }

From: Ye Li ye.li@nxp.com So far u-boot only load SNSR25C for TMU main probe (probe 0). However, kernel enables two probes. So it also needs to set default SNSR25C of TCALIV1 for blank samples. Reviewed-by: Peng Fan peng.fan@nxp.com Signed-off-by: Ye Li ye.li@nxp.com Signed-off-by: Peng Fan peng.fan@nxp.com
Applied to u-boot-imx, master, thanks !
Best regards, Stefano Babic

Add more fuse bank structure for use.
Signed-off-by: Peng Fan peng.fan@nxp.com --- arch/arm/include/asm/arch-imx8m/imx-regs.h | 41 +++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 7 deletions(-)
diff --git a/arch/arm/include/asm/arch-imx8m/imx-regs.h b/arch/arm/include/asm/arch-imx8m/imx-regs.h index 62640d996e..3cfa169c97 100644 --- a/arch/arm/include/asm/arch-imx8m/imx-regs.h +++ b/arch/arm/include/asm/arch-imx8m/imx-regs.h @@ -137,6 +137,40 @@ struct fuse_bank1_regs { u32 rsvd3[3]; };
+struct fuse_bank3_regs { + u32 mem_trim0; + u32 rsvd0[3]; + u32 mem_trim1; + u32 rsvd1[3]; + u32 mem_trim2; + u32 rsvd2[3]; + u32 ana0; + u32 rsvd3[3]; +}; + +struct fuse_bank9_regs { + u32 mac_addr0; + u32 rsvd0[3]; + u32 mac_addr1; + u32 rsvd1[11]; +}; + +struct fuse_bank38_regs { + u32 ana_trim1; /* trim0 is at 0xD70, bank 37*/ + u32 rsvd0[3]; + u32 ana_trim2; + u32 rsvd1[3]; + u32 ana_trim3; + u32 rsvd2[3]; + u32 ana_trim4; + u32 rsvd3[3]; +}; + +struct fuse_bank39_regs { + u32 ana_trim5; + u32 rsvd[15]; +}; + #ifdef CONFIG_IMX8MQ struct anamix_pll { u32 audio_pll1_cfg0; @@ -227,13 +261,6 @@ struct anamix_pll { }; #endif
-struct fuse_bank9_regs { - u32 mac_addr0; - u32 rsvd0[3]; - u32 mac_addr1; - u32 rsvd1[11]; -}; - /* System Reset Controller (SRC) */ struct src { u32 scr;

Add more fuse bank structure for use. Signed-off-by: Peng Fan peng.fan@nxp.com
Applied to u-boot-imx, master, thanks !
Best regards, Stefano Babic

Support tmu when print cpu info
Signed-off-by: peng Fan peng.fan@nxp.com --- arch/arm/mach-imx/cpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-imx/cpu.c b/arch/arm/mach-imx/cpu.c index bfa85c64c6..2d70b6861d 100644 --- a/arch/arm/mach-imx/cpu.c +++ b/arch/arm/mach-imx/cpu.c @@ -154,7 +154,7 @@ int print_cpuinfo(void)
cpurev = get_cpu_rev();
-#if defined(CONFIG_IMX_THERMAL) +#if defined(CONFIG_IMX_THERMAL) || defined(CONFIG_IMX_TMU) struct udevice *thermal_dev; int cpu_tmp, minc, maxc, ret;
@@ -177,7 +177,7 @@ int print_cpuinfo(void) mxc_get_clock(MXC_ARM_CLK) / 1000000); #endif
-#if defined(CONFIG_IMX_THERMAL) +#if defined(CONFIG_IMX_THERMAL) || defined(CONFIG_IMX_TMU) puts("CPU: "); switch (get_cpu_temp_grade(&minc, &maxc)) { case TEMP_AUTOMOTIVE:

Support tmu when print cpu info Signed-off-by: peng Fan peng.fan@nxp.com
Applied to u-boot-imx, master, thanks !
Best regards, Stefano Babic
participants (3)
-
Fabio Estevam
-
Peng Fan
-
sbabic@denx.de