1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright 2020 NXP. 4 * 5 * Author: Anson Huang <Anson.Huang@nxp.com> 6 */ 7 8 #include <linux/bitfield.h> 9 #include <linux/clk.h> 10 #include <linux/err.h> 11 #include <linux/io.h> 12 #include <linux/module.h> 13 #include <linux/nvmem-consumer.h> 14 #include <linux/of.h> 15 #include <linux/platform_device.h> 16 #include <linux/slab.h> 17 #include <linux/thermal.h> 18 19 #include "thermal_hwmon.h" 20 21 #define TER 0x0 /* TMU enable */ 22 #define TPS 0x4 23 #define TRITSR 0x20 /* TMU immediate temp */ 24 /* TMU calibration data registers */ 25 #define TASR 0x28 26 #define TASR_BUF_SLOPE_MASK GENMASK(19, 16) 27 #define TASR_BUF_VREF_MASK GENMASK(4, 0) /* TMU_V1 */ 28 #define TASR_BUF_VERF_SEL_MASK GENMASK(1, 0) /* TMU_V2 */ 29 #define TCALIV(n) (0x30 + ((n) * 4)) 30 #define TCALIV_EN BIT(31) 31 #define TCALIV_HR_MASK GENMASK(23, 16) /* TMU_V1 */ 32 #define TCALIV_RT_MASK GENMASK(7, 0) /* TMU_V1 */ 33 #define TCALIV_SNSR105C_MASK GENMASK(27, 16) /* TMU_V2 */ 34 #define TCALIV_SNSR25C_MASK GENMASK(11, 0) /* TMU_V2 */ 35 #define TRIM 0x3c 36 #define TRIM_BJT_CUR_MASK GENMASK(23, 20) 37 #define TRIM_BGR_MASK GENMASK(31, 28) 38 #define TRIM_VLSB_MASK GENMASK(15, 12) 39 #define TRIM_EN_CH BIT(7) 40 41 #define TER_ADC_PD BIT(30) 42 #define TER_EN BIT(31) 43 #define TRITSR_TEMP0_VAL_MASK GENMASK(7, 0) 44 #define TRITSR_TEMP1_VAL_MASK GENMASK(23, 16) 45 46 #define PROBE_SEL_ALL GENMASK(31, 30) 47 48 #define probe_status_offset(x) (30 + x) 49 #define SIGN_BIT BIT(7) 50 #define TEMP_VAL_MASK GENMASK(6, 0) 51 52 /* TMU OCOTP calibration data bitfields */ 53 #define ANA0_EN BIT(25) 54 #define ANA0_BUF_VREF_MASK GENMASK(24, 20) 55 #define ANA0_BUF_SLOPE_MASK GENMASK(19, 16) 56 #define ANA0_HR_MASK GENMASK(15, 8) 57 #define ANA0_RT_MASK GENMASK(7, 0) 58 #define TRIM2_VLSB_MASK GENMASK(23, 20) 59 #define TRIM2_BGR_MASK GENMASK(19, 16) 60 #define TRIM2_BJT_CUR_MASK GENMASK(15, 12) 61 #define TRIM2_BUF_SLOP_SEL_MASK GENMASK(11, 8) 62 #define TRIM2_BUF_VERF_SEL_MASK GENMASK(7, 6) 63 #define TRIM3_TCA25_0_LSB_MASK GENMASK(31, 28) 64 #define TRIM3_TCA40_0_MASK GENMASK(27, 16) 65 #define TRIM4_TCA40_1_MASK GENMASK(31, 20) 66 #define TRIM4_TCA105_0_MASK GENMASK(19, 8) 67 #define TRIM4_TCA25_0_MSB_MASK GENMASK(7, 0) 68 #define TRIM5_TCA105_1_MASK GENMASK(23, 12) 69 #define TRIM5_TCA25_1_MASK GENMASK(11, 0) 70 71 #define VER1_TEMP_LOW_LIMIT 10000 72 #define VER2_TEMP_LOW_LIMIT -40000 73 #define VER2_TEMP_HIGH_LIMIT 125000 74 75 #define TMU_VER1 0x1 76 #define TMU_VER2 0x2 77 78 struct thermal_soc_data { 79 u32 num_sensors; 80 u32 version; 81 int (*get_temp)(void *data, int *temp); 82 }; 83 84 struct tmu_sensor { 85 struct imx8mm_tmu *priv; 86 u32 hw_id; 87 struct thermal_zone_device *tzd; 88 }; 89 90 struct imx8mm_tmu { 91 void __iomem *base; 92 struct clk *clk; 93 const struct thermal_soc_data *socdata; 94 struct tmu_sensor sensors[]; 95 }; 96 97 static int imx8mm_tmu_get_temp(void *data, int *temp) 98 { 99 struct tmu_sensor *sensor = data; 100 struct imx8mm_tmu *tmu = sensor->priv; 101 u32 val; 102 103 val = readl_relaxed(tmu->base + TRITSR) & TRITSR_TEMP0_VAL_MASK; 104 105 /* 106 * Do not validate against the V bit (bit 31) due to errata 107 * ERR051272: TMU: Bit 31 of registers TMU_TSCR/TMU_TRITSR/TMU_TRATSR invalid 108 */ 109 110 *temp = val * 1000; 111 if (*temp < VER1_TEMP_LOW_LIMIT || *temp > VER2_TEMP_HIGH_LIMIT) 112 return -EAGAIN; 113 114 return 0; 115 } 116 117 static int imx8mp_tmu_get_temp(void *data, int *temp) 118 { 119 struct tmu_sensor *sensor = data; 120 struct imx8mm_tmu *tmu = sensor->priv; 121 unsigned long val; 122 bool ready; 123 124 val = readl_relaxed(tmu->base + TRITSR); 125 ready = test_bit(probe_status_offset(sensor->hw_id), &val); 126 if (!ready) 127 return -EAGAIN; 128 129 val = sensor->hw_id ? FIELD_GET(TRITSR_TEMP1_VAL_MASK, val) : 130 FIELD_GET(TRITSR_TEMP0_VAL_MASK, val); 131 if (val & SIGN_BIT) /* negative */ 132 val = (~(val & TEMP_VAL_MASK) + 1); 133 134 *temp = val * 1000; 135 if (*temp < VER2_TEMP_LOW_LIMIT || *temp > VER2_TEMP_HIGH_LIMIT) 136 return -EAGAIN; 137 138 return 0; 139 } 140 141 static int tmu_get_temp(struct thermal_zone_device *tz, int *temp) 142 { 143 struct tmu_sensor *sensor = thermal_zone_device_priv(tz); 144 struct imx8mm_tmu *tmu = sensor->priv; 145 146 return tmu->socdata->get_temp(sensor, temp); 147 } 148 149 static const struct thermal_zone_device_ops tmu_tz_ops = { 150 .get_temp = tmu_get_temp, 151 }; 152 153 static void imx8mm_tmu_enable(struct imx8mm_tmu *tmu, bool enable) 154 { 155 u32 val; 156 157 val = readl_relaxed(tmu->base + TER); 158 val = enable ? (val | TER_EN) : (val & ~TER_EN); 159 if (tmu->socdata->version == TMU_VER2) 160 val = enable ? (val & ~TER_ADC_PD) : (val | TER_ADC_PD); 161 writel_relaxed(val, tmu->base + TER); 162 } 163 164 static void imx8mm_tmu_probe_sel_all(struct imx8mm_tmu *tmu) 165 { 166 u32 val; 167 168 val = readl_relaxed(tmu->base + TPS); 169 val |= PROBE_SEL_ALL; 170 writel_relaxed(val, tmu->base + TPS); 171 } 172 173 static int imx8mm_tmu_probe_set_calib_v1(struct platform_device *pdev, 174 struct imx8mm_tmu *tmu) 175 { 176 struct device *dev = &pdev->dev; 177 u32 ana0; 178 int ret; 179 180 ret = nvmem_cell_read_u32(&pdev->dev, "calib", &ana0); 181 if (ret) 182 return dev_err_probe(dev, ret, "Failed to read OCOTP nvmem cell\n"); 183 184 writel(FIELD_PREP(TASR_BUF_VREF_MASK, 185 FIELD_GET(ANA0_BUF_VREF_MASK, ana0)) | 186 FIELD_PREP(TASR_BUF_SLOPE_MASK, 187 FIELD_GET(ANA0_BUF_SLOPE_MASK, ana0)), 188 tmu->base + TASR); 189 190 writel(FIELD_PREP(TCALIV_RT_MASK, FIELD_GET(ANA0_RT_MASK, ana0)) | 191 FIELD_PREP(TCALIV_HR_MASK, FIELD_GET(ANA0_HR_MASK, ana0)) | 192 ((ana0 & ANA0_EN) ? TCALIV_EN : 0), 193 tmu->base + TCALIV(0)); 194 195 return 0; 196 } 197 198 static int imx8mm_tmu_probe_set_calib_v2(struct platform_device *pdev, 199 struct imx8mm_tmu *tmu) 200 { 201 struct device *dev = &pdev->dev; 202 struct nvmem_cell *cell; 203 u32 trim[4] = { 0 }; 204 size_t len; 205 void *buf; 206 207 cell = nvmem_cell_get(dev, "calib"); 208 if (IS_ERR(cell)) 209 return PTR_ERR(cell); 210 211 buf = nvmem_cell_read(cell, &len); 212 nvmem_cell_put(cell); 213 214 if (IS_ERR(buf)) 215 return PTR_ERR(buf); 216 217 memcpy(trim, buf, min(len, sizeof(trim))); 218 kfree(buf); 219 220 if (len != 16) { 221 dev_err(dev, 222 "OCOTP nvmem cell length is %zu, must be 16.\n", len); 223 return -EINVAL; 224 } 225 226 /* Blank sample hardware */ 227 if (!trim[0] && !trim[1] && !trim[2] && !trim[3]) { 228 /* Use a default 25C binary codes */ 229 writel(FIELD_PREP(TCALIV_SNSR25C_MASK, 0x63c), 230 tmu->base + TCALIV(0)); 231 writel(FIELD_PREP(TCALIV_SNSR25C_MASK, 0x63c), 232 tmu->base + TCALIV(1)); 233 return 0; 234 } 235 236 writel(FIELD_PREP(TASR_BUF_VERF_SEL_MASK, 237 FIELD_GET(TRIM2_BUF_VERF_SEL_MASK, trim[0])) | 238 FIELD_PREP(TASR_BUF_SLOPE_MASK, 239 FIELD_GET(TRIM2_BUF_SLOP_SEL_MASK, trim[0])), 240 tmu->base + TASR); 241 242 writel(FIELD_PREP(TRIM_BJT_CUR_MASK, 243 FIELD_GET(TRIM2_BJT_CUR_MASK, trim[0])) | 244 FIELD_PREP(TRIM_BGR_MASK, FIELD_GET(TRIM2_BGR_MASK, trim[0])) | 245 FIELD_PREP(TRIM_VLSB_MASK, FIELD_GET(TRIM2_VLSB_MASK, trim[0])) | 246 TRIM_EN_CH, 247 tmu->base + TRIM); 248 249 writel(FIELD_PREP(TCALIV_SNSR25C_MASK, 250 FIELD_GET(TRIM3_TCA25_0_LSB_MASK, trim[1]) | 251 (FIELD_GET(TRIM4_TCA25_0_MSB_MASK, trim[2]) << 4)) | 252 FIELD_PREP(TCALIV_SNSR105C_MASK, 253 FIELD_GET(TRIM4_TCA105_0_MASK, trim[2])), 254 tmu->base + TCALIV(0)); 255 256 writel(FIELD_PREP(TCALIV_SNSR25C_MASK, 257 FIELD_GET(TRIM5_TCA25_1_MASK, trim[3])) | 258 FIELD_PREP(TCALIV_SNSR105C_MASK, 259 FIELD_GET(TRIM5_TCA105_1_MASK, trim[3])), 260 tmu->base + TCALIV(1)); 261 262 writel(FIELD_PREP(TCALIV_SNSR25C_MASK, 263 FIELD_GET(TRIM3_TCA40_0_MASK, trim[1])) | 264 FIELD_PREP(TCALIV_SNSR105C_MASK, 265 FIELD_GET(TRIM4_TCA40_1_MASK, trim[2])), 266 tmu->base + TCALIV(2)); 267 268 return 0; 269 } 270 271 static int imx8mm_tmu_probe_set_calib(struct platform_device *pdev, 272 struct imx8mm_tmu *tmu) 273 { 274 struct device *dev = &pdev->dev; 275 276 /* 277 * Lack of calibration data OCOTP reference is not considered 278 * fatal to retain compatibility with old DTs. It is however 279 * strongly recommended to update such old DTs to get correct 280 * temperature compensation values for each SoC. 281 */ 282 if (!of_property_present(pdev->dev.of_node, "nvmem-cells")) { 283 dev_warn(dev, 284 "No OCOTP nvmem reference found, SoC-specific calibration not loaded. Please update your DT.\n"); 285 return 0; 286 } 287 288 if (tmu->socdata->version == TMU_VER1) 289 return imx8mm_tmu_probe_set_calib_v1(pdev, tmu); 290 291 return imx8mm_tmu_probe_set_calib_v2(pdev, tmu); 292 } 293 294 static int imx8mm_tmu_probe(struct platform_device *pdev) 295 { 296 const struct thermal_soc_data *data; 297 struct imx8mm_tmu *tmu; 298 int ret; 299 int i; 300 301 data = of_device_get_match_data(&pdev->dev); 302 303 tmu = devm_kzalloc(&pdev->dev, struct_size(tmu, sensors, 304 data->num_sensors), GFP_KERNEL); 305 if (!tmu) 306 return -ENOMEM; 307 308 tmu->socdata = data; 309 310 tmu->base = devm_platform_ioremap_resource(pdev, 0); 311 if (IS_ERR(tmu->base)) 312 return PTR_ERR(tmu->base); 313 314 tmu->clk = devm_clk_get(&pdev->dev, NULL); 315 if (IS_ERR(tmu->clk)) 316 return dev_err_probe(&pdev->dev, PTR_ERR(tmu->clk), 317 "failed to get tmu clock\n"); 318 319 ret = clk_prepare_enable(tmu->clk); 320 if (ret) { 321 dev_err(&pdev->dev, "failed to enable tmu clock: %d\n", ret); 322 return ret; 323 } 324 325 /* disable the monitor during initialization */ 326 imx8mm_tmu_enable(tmu, false); 327 328 for (i = 0; i < data->num_sensors; i++) { 329 tmu->sensors[i].priv = tmu; 330 tmu->sensors[i].tzd = 331 devm_thermal_of_zone_register(&pdev->dev, i, 332 &tmu->sensors[i], 333 &tmu_tz_ops); 334 if (IS_ERR(tmu->sensors[i].tzd)) { 335 ret = PTR_ERR(tmu->sensors[i].tzd); 336 dev_err(&pdev->dev, 337 "failed to register thermal zone sensor[%d]: %d\n", 338 i, ret); 339 goto disable_clk; 340 } 341 tmu->sensors[i].hw_id = i; 342 343 devm_thermal_add_hwmon_sysfs(&pdev->dev, tmu->sensors[i].tzd); 344 } 345 346 platform_set_drvdata(pdev, tmu); 347 348 ret = imx8mm_tmu_probe_set_calib(pdev, tmu); 349 if (ret) 350 goto disable_clk; 351 352 /* enable all the probes for V2 TMU */ 353 if (tmu->socdata->version == TMU_VER2) 354 imx8mm_tmu_probe_sel_all(tmu); 355 356 /* enable the monitor */ 357 imx8mm_tmu_enable(tmu, true); 358 359 return 0; 360 361 disable_clk: 362 clk_disable_unprepare(tmu->clk); 363 return ret; 364 } 365 366 static void imx8mm_tmu_remove(struct platform_device *pdev) 367 { 368 struct imx8mm_tmu *tmu = platform_get_drvdata(pdev); 369 370 /* disable TMU */ 371 imx8mm_tmu_enable(tmu, false); 372 373 clk_disable_unprepare(tmu->clk); 374 platform_set_drvdata(pdev, NULL); 375 } 376 377 static struct thermal_soc_data imx8mm_tmu_data = { 378 .num_sensors = 1, 379 .version = TMU_VER1, 380 .get_temp = imx8mm_tmu_get_temp, 381 }; 382 383 static struct thermal_soc_data imx8mp_tmu_data = { 384 .num_sensors = 2, 385 .version = TMU_VER2, 386 .get_temp = imx8mp_tmu_get_temp, 387 }; 388 389 static const struct of_device_id imx8mm_tmu_table[] = { 390 { .compatible = "fsl,imx8mm-tmu", .data = &imx8mm_tmu_data, }, 391 { .compatible = "fsl,imx8mp-tmu", .data = &imx8mp_tmu_data, }, 392 { }, 393 }; 394 MODULE_DEVICE_TABLE(of, imx8mm_tmu_table); 395 396 static struct platform_driver imx8mm_tmu = { 397 .driver = { 398 .name = "i.mx8mm_thermal", 399 .of_match_table = imx8mm_tmu_table, 400 }, 401 .probe = imx8mm_tmu_probe, 402 .remove = imx8mm_tmu_remove, 403 }; 404 module_platform_driver(imx8mm_tmu); 405 406 MODULE_AUTHOR("Anson Huang <Anson.Huang@nxp.com>"); 407 MODULE_DESCRIPTION("i.MX8MM Thermal Monitor Unit driver"); 408 MODULE_LICENSE("GPL v2"); 409