1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Marvell EBU Armada SoCs thermal sensor driver 4 * 5 * Copyright (C) 2013 Marvell 6 */ 7 #include <linux/bitfield.h> 8 #include <linux/device.h> 9 #include <linux/err.h> 10 #include <linux/io.h> 11 #include <linux/kernel.h> 12 #include <linux/of.h> 13 #include <linux/module.h> 14 #include <linux/delay.h> 15 #include <linux/platform_device.h> 16 #include <linux/of_device.h> 17 #include <linux/thermal.h> 18 #include <linux/iopoll.h> 19 #include <linux/mfd/syscon.h> 20 #include <linux/regmap.h> 21 #include <linux/interrupt.h> 22 23 /* Thermal Manager Control and Status Register */ 24 #define PMU_TDC0_SW_RST_MASK BIT(1) 25 #define PMU_TM_DISABLE_MASK BIT(0) 26 #define PMU_TDC0_REF_CAL_CNT_MASK GENMASK(19, 11) 27 #define PMU_TDC0_OTF_CAL_MASK BIT(30) 28 #define PMU_TDC0_START_CAL_MASK BIT(25) 29 30 #define A375_UNIT_CONTROL_MASK GENMASK(29, 27) 31 #define A375_READOUT_INVERT BIT(15) 32 #define A375_HW_RESETn BIT(8) 33 34 /* Errata fields */ 35 #define CONTROL0_TSEN_TC_TRIM_MASK GENMASK(2, 0) 36 #define CONTROL0_TSEN_TC_TRIM_VAL 0x3 37 38 #define CONTROL0_TSEN_START BIT(0) 39 #define CONTROL0_TSEN_RESET BIT(1) 40 #define CONTROL0_TSEN_ENABLE BIT(2) 41 #define CONTROL0_TSEN_AVG_BYPASS BIT(6) 42 #define CONTROL0_TSEN_CHAN_MASK GENMASK(16, 13) 43 #define CONTROL0_TSEN_OSR_MASK GENMASK(25, 24) 44 #define CONTROL0_TSEN_OSR_MAX FIELD_MAX(CONTROL0_TSEN_OSR_MASK) 45 #define CONTROL0_TSEN_MODE_MASK GENMASK(31, 30) 46 #define CONTROL0_TSEN_MODE_EXTERNAL 0x2 47 48 #define CONTROL1_TSEN_AVG_MASK GENMASK(2, 0) 49 #define CONTROL1_EXT_TSEN_SW_RESET BIT(7) 50 #define CONTROL1_EXT_TSEN_HW_RESETn BIT(8) 51 #define CONTROL1_TSEN_INT_EN BIT(25) 52 #define CONTROL1_TSEN_SELECT_MASK GENMASK(22, 21) 53 54 #define STATUS_POLL_PERIOD_US 1000 55 #define STATUS_POLL_TIMEOUT_US 100000 56 #define OVERHEAT_INT_POLL_DELAY_MS 1000 57 58 struct armada_thermal_data; 59 60 /* Marvell EBU Thermal Sensor Dev Structure */ 61 struct armada_thermal_priv { 62 struct device *dev; 63 struct regmap *syscon; 64 char zone_name[THERMAL_NAME_LENGTH]; 65 /* serialize temperature reads/updates */ 66 struct mutex update_lock; 67 struct armada_thermal_data *data; 68 struct thermal_zone_device *overheat_sensor; 69 int interrupt_source; 70 int current_channel; 71 long current_threshold; 72 long current_hysteresis; 73 }; 74 75 struct armada_thermal_data { 76 /* Initialize the thermal IC */ 77 void (*init)(struct platform_device *pdev, 78 struct armada_thermal_priv *priv); 79 80 /* Formula coeficients: temp = (b - m * reg) / div */ 81 s64 coef_b; 82 s64 coef_m; 83 u32 coef_div; 84 bool inverted; 85 bool signed_sample; 86 87 /* Register shift and mask to access the sensor temperature */ 88 unsigned int temp_shift; 89 unsigned int temp_mask; 90 unsigned int thresh_shift; 91 unsigned int hyst_shift; 92 unsigned int hyst_mask; 93 u32 is_valid_bit; 94 95 /* Syscon access */ 96 unsigned int syscon_control0_off; 97 unsigned int syscon_control1_off; 98 unsigned int syscon_status_off; 99 unsigned int dfx_irq_cause_off; 100 unsigned int dfx_irq_mask_off; 101 unsigned int dfx_overheat_irq; 102 unsigned int dfx_server_irq_mask_off; 103 unsigned int dfx_server_irq_en; 104 105 /* One sensor is in the thermal IC, the others are in the CPUs if any */ 106 unsigned int cpu_nr; 107 }; 108 109 struct armada_drvdata { 110 enum drvtype { 111 LEGACY, 112 SYSCON 113 } type; 114 union { 115 struct armada_thermal_priv *priv; 116 struct thermal_zone_device *tz; 117 } data; 118 }; 119 120 /* 121 * struct armada_thermal_sensor - hold the information of one thermal sensor 122 * @thermal: pointer to the local private structure 123 * @tzd: pointer to the thermal zone device 124 * @id: identifier of the thermal sensor 125 */ 126 struct armada_thermal_sensor { 127 struct armada_thermal_priv *priv; 128 int id; 129 }; 130 131 static void armadaxp_init(struct platform_device *pdev, 132 struct armada_thermal_priv *priv) 133 { 134 struct armada_thermal_data *data = priv->data; 135 u32 reg; 136 137 regmap_read(priv->syscon, data->syscon_control1_off, ®); 138 FIELD_MODIFY(PMU_TDC0_OTF_CAL_MASK, ®, 1); 139 140 /* Reference calibration value */ 141 FIELD_MODIFY(PMU_TDC0_REF_CAL_CNT_MASK, ®, 0xf1); 142 143 /* Reset the sensor */ 144 FIELD_MODIFY(PMU_TDC0_SW_RST_MASK, ®, 1); 145 regmap_write(priv->syscon, data->syscon_control1_off, reg); 146 147 FIELD_MODIFY(PMU_TDC0_SW_RST_MASK, ®, 0); 148 regmap_write(priv->syscon, data->syscon_control1_off, reg); 149 150 /* Enable the sensor */ 151 regmap_read(priv->syscon, data->syscon_status_off, ®); 152 FIELD_MODIFY(PMU_TM_DISABLE_MASK, ®, 0); 153 regmap_write(priv->syscon, data->syscon_status_off, reg); 154 } 155 156 static void armada370_init(struct platform_device *pdev, 157 struct armada_thermal_priv *priv) 158 { 159 struct armada_thermal_data *data = priv->data; 160 u32 reg; 161 162 regmap_read(priv->syscon, data->syscon_control1_off, ®); 163 FIELD_MODIFY(PMU_TDC0_OTF_CAL_MASK, ®, 1); 164 165 /* Reference calibration value */ 166 FIELD_MODIFY(PMU_TDC0_REF_CAL_CNT_MASK, ®, 0xf1); 167 168 /* Reset the sensor */ 169 FIELD_MODIFY(PMU_TDC0_START_CAL_MASK, ®, 0); 170 171 regmap_write(priv->syscon, data->syscon_control1_off, reg); 172 173 msleep(10); 174 } 175 176 static void armada375_init(struct platform_device *pdev, 177 struct armada_thermal_priv *priv) 178 { 179 struct armada_thermal_data *data = priv->data; 180 u32 reg; 181 182 regmap_read(priv->syscon, data->syscon_control1_off, ®); 183 FIELD_MODIFY(A375_UNIT_CONTROL_MASK, ®, 0); 184 FIELD_MODIFY(A375_READOUT_INVERT, ®, 0); 185 FIELD_MODIFY(A375_HW_RESETn, ®, 0); 186 regmap_write(priv->syscon, data->syscon_control1_off, reg); 187 188 msleep(20); 189 190 FIELD_MODIFY(A375_HW_RESETn, ®, 1); 191 regmap_write(priv->syscon, data->syscon_control1_off, reg); 192 193 msleep(50); 194 } 195 196 static int armada_wait_sensor_validity(struct armada_thermal_priv *priv) 197 { 198 u32 reg; 199 200 return regmap_read_poll_timeout(priv->syscon, 201 priv->data->syscon_status_off, reg, 202 reg & priv->data->is_valid_bit, 203 STATUS_POLL_PERIOD_US, 204 STATUS_POLL_TIMEOUT_US); 205 } 206 207 static void armada380_init(struct platform_device *pdev, 208 struct armada_thermal_priv *priv) 209 { 210 struct armada_thermal_data *data = priv->data; 211 u32 reg; 212 213 /* Disable the HW/SW reset */ 214 regmap_read(priv->syscon, data->syscon_control1_off, ®); 215 FIELD_MODIFY(CONTROL1_EXT_TSEN_HW_RESETn, ®, 1); 216 FIELD_MODIFY(CONTROL1_EXT_TSEN_SW_RESET, ®, 0); 217 regmap_write(priv->syscon, data->syscon_control1_off, reg); 218 219 /* Set Tsen Tc Trim to correct default value (errata #132698) */ 220 regmap_read(priv->syscon, data->syscon_control0_off, ®); 221 FIELD_MODIFY(CONTROL0_TSEN_TC_TRIM_MASK, ®, CONTROL0_TSEN_TC_TRIM_VAL); 222 regmap_write(priv->syscon, data->syscon_control0_off, reg); 223 } 224 225 static void armada_ap80x_init(struct platform_device *pdev, 226 struct armada_thermal_priv *priv) 227 { 228 struct armada_thermal_data *data = priv->data; 229 u32 reg; 230 231 regmap_read(priv->syscon, data->syscon_control0_off, ®); 232 FIELD_MODIFY(CONTROL0_TSEN_RESET, ®, 0); 233 FIELD_MODIFY(CONTROL0_TSEN_START, ®, 1); 234 FIELD_MODIFY(CONTROL0_TSEN_ENABLE, ®, 1); 235 236 /* Sample every ~2ms */ 237 FIELD_MODIFY(CONTROL0_TSEN_OSR_MASK, ®, CONTROL0_TSEN_OSR_MAX); 238 239 /* Enable average (2 samples by default) */ 240 FIELD_MODIFY(CONTROL0_TSEN_AVG_BYPASS, ®, 0); 241 242 regmap_write(priv->syscon, data->syscon_control0_off, reg); 243 } 244 245 static void armada_cp110_init(struct platform_device *pdev, 246 struct armada_thermal_priv *priv) 247 { 248 struct armada_thermal_data *data = priv->data; 249 u32 reg; 250 251 armada380_init(pdev, priv); 252 253 /* Sample every ~2ms */ 254 regmap_read(priv->syscon, data->syscon_control0_off, ®); 255 FIELD_MODIFY(CONTROL0_TSEN_OSR_MASK, ®, CONTROL0_TSEN_OSR_MAX); 256 regmap_write(priv->syscon, data->syscon_control0_off, reg); 257 258 /* Average the output value over 2^1 = 2 samples */ 259 regmap_read(priv->syscon, data->syscon_control1_off, ®); 260 FIELD_MODIFY(CONTROL1_TSEN_AVG_MASK, ®, 1); 261 regmap_write(priv->syscon, data->syscon_control1_off, reg); 262 } 263 264 static bool armada_is_valid(struct armada_thermal_priv *priv) 265 { 266 u32 reg; 267 268 if (!priv->data->is_valid_bit) 269 return true; 270 271 regmap_read(priv->syscon, priv->data->syscon_status_off, ®); 272 273 return reg & priv->data->is_valid_bit; 274 } 275 276 static void armada_enable_overheat_interrupt(struct armada_thermal_priv *priv) 277 { 278 struct armada_thermal_data *data = priv->data; 279 u32 reg; 280 281 /* Clear DFX temperature IRQ cause */ 282 regmap_read(priv->syscon, data->dfx_irq_cause_off, ®); 283 284 /* Enable DFX Temperature IRQ */ 285 regmap_read(priv->syscon, data->dfx_irq_mask_off, ®); 286 reg |= data->dfx_overheat_irq; 287 regmap_write(priv->syscon, data->dfx_irq_mask_off, reg); 288 289 /* Enable DFX server IRQ */ 290 regmap_read(priv->syscon, data->dfx_server_irq_mask_off, ®); 291 reg |= data->dfx_server_irq_en; 292 regmap_write(priv->syscon, data->dfx_server_irq_mask_off, reg); 293 294 /* Enable overheat interrupt */ 295 regmap_read(priv->syscon, data->syscon_control1_off, ®); 296 reg |= CONTROL1_TSEN_INT_EN; 297 regmap_write(priv->syscon, data->syscon_control1_off, reg); 298 } 299 300 static void __maybe_unused 301 armada_disable_overheat_interrupt(struct armada_thermal_priv *priv) 302 { 303 struct armada_thermal_data *data = priv->data; 304 u32 reg; 305 306 regmap_read(priv->syscon, data->syscon_control1_off, ®); 307 FIELD_MODIFY(CONTROL1_TSEN_INT_EN, ®, 0); 308 regmap_write(priv->syscon, data->syscon_control1_off, reg); 309 } 310 311 /* There is currently no board with more than one sensor per channel */ 312 static int armada_select_channel(struct armada_thermal_priv *priv, int channel) 313 { 314 struct armada_thermal_data *data = priv->data; 315 u32 ctrl0; 316 317 if (channel < 0 || channel > priv->data->cpu_nr) 318 return -EINVAL; 319 320 if (priv->current_channel == channel) 321 return 0; 322 323 /* Stop the measurements */ 324 regmap_read(priv->syscon, data->syscon_control0_off, &ctrl0); 325 FIELD_MODIFY(CONTROL0_TSEN_START, &ctrl0, 0); 326 regmap_write(priv->syscon, data->syscon_control0_off, ctrl0); 327 328 /* Other channels are external and should be selected accordingly */ 329 if (channel) { 330 /* Change the mode to external */ 331 FIELD_MODIFY(CONTROL0_TSEN_MODE_MASK, &ctrl0, CONTROL0_TSEN_MODE_EXTERNAL); 332 /* Select the sensor */ 333 FIELD_MODIFY(CONTROL0_TSEN_CHAN_MASK, &ctrl0, channel - 1); 334 } else { 335 /* Reset the mode, internal sensor will be automatically selected */ 336 FIELD_MODIFY(CONTROL0_TSEN_MODE_MASK, &ctrl0, 0); 337 } 338 339 /* Actually set the mode/channel */ 340 regmap_write(priv->syscon, data->syscon_control0_off, ctrl0); 341 priv->current_channel = channel; 342 343 /* Re-start the measurements */ 344 FIELD_MODIFY(CONTROL0_TSEN_START, &ctrl0, 1); 345 regmap_write(priv->syscon, data->syscon_control0_off, ctrl0); 346 347 /* 348 * The IP has a latency of ~15ms, so after updating the selected source, 349 * we must absolutely wait for the sensor validity bit to ensure we read 350 * actual data. 351 */ 352 if (armada_wait_sensor_validity(priv)) 353 return -EIO; 354 355 return 0; 356 } 357 358 static int armada_read_sensor(struct armada_thermal_priv *priv, int *temp) 359 { 360 u32 reg, div; 361 s64 sample, b, m; 362 363 regmap_read(priv->syscon, priv->data->syscon_status_off, ®); 364 reg = (reg >> priv->data->temp_shift) & priv->data->temp_mask; 365 if (priv->data->signed_sample) 366 /* The most significant bit is the sign bit */ 367 sample = sign_extend32(reg, fls(priv->data->temp_mask) - 1); 368 else 369 sample = reg; 370 371 /* Get formula coeficients */ 372 b = priv->data->coef_b; 373 m = priv->data->coef_m; 374 div = priv->data->coef_div; 375 376 if (priv->data->inverted) 377 *temp = div_s64((m * sample) - b, div); 378 else 379 *temp = div_s64(b - (m * sample), div); 380 381 return 0; 382 } 383 384 static int armada_get_temp_legacy(struct thermal_zone_device *thermal, 385 int *temp) 386 { 387 struct armada_thermal_priv *priv = thermal_zone_device_priv(thermal); 388 int ret; 389 390 /* Valid check */ 391 if (!armada_is_valid(priv)) 392 return -EIO; 393 394 /* Do the actual reading */ 395 ret = armada_read_sensor(priv, temp); 396 397 return ret; 398 } 399 400 static const struct thermal_zone_device_ops legacy_ops = { 401 .get_temp = armada_get_temp_legacy, 402 }; 403 404 static int armada_get_temp(struct thermal_zone_device *tz, int *temp) 405 { 406 struct armada_thermal_sensor *sensor = thermal_zone_device_priv(tz); 407 struct armada_thermal_priv *priv = sensor->priv; 408 int ret; 409 410 mutex_lock(&priv->update_lock); 411 412 /* Select the desired channel */ 413 ret = armada_select_channel(priv, sensor->id); 414 if (ret) 415 goto unlock_mutex; 416 417 /* Do the actual reading */ 418 ret = armada_read_sensor(priv, temp); 419 if (ret) 420 goto unlock_mutex; 421 422 /* 423 * Select back the interrupt source channel from which a potential 424 * critical trip point has been set. 425 */ 426 ret = armada_select_channel(priv, priv->interrupt_source); 427 428 unlock_mutex: 429 mutex_unlock(&priv->update_lock); 430 431 return ret; 432 } 433 434 static const struct thermal_zone_device_ops of_ops = { 435 .get_temp = armada_get_temp, 436 }; 437 438 static unsigned int armada_mc_to_reg_temp(struct armada_thermal_data *data, 439 unsigned int temp_mc) 440 { 441 s64 b = data->coef_b; 442 s64 m = data->coef_m; 443 s64 div = data->coef_div; 444 unsigned int sample; 445 446 if (data->inverted) 447 sample = div_s64(((temp_mc * div) + b), m); 448 else 449 sample = div_s64((b - (temp_mc * div)), m); 450 451 return sample & data->temp_mask; 452 } 453 454 /* 455 * The documentation states: 456 * high/low watermark = threshold +/- 0.4761 * 2^(hysteresis + 2) 457 * which is the mathematical derivation for: 458 * 0x0 <=> 1.9°C, 0x1 <=> 3.8°C, 0x2 <=> 7.6°C, 0x3 <=> 15.2°C 459 */ 460 static unsigned int hyst_levels_mc[] = {1900, 3800, 7600, 15200}; 461 462 static unsigned int armada_mc_to_reg_hyst(struct armada_thermal_data *data, 463 unsigned int hyst_mc) 464 { 465 int i; 466 467 /* 468 * We will always take the smallest possible hysteresis to avoid risking 469 * the hardware integrity by enlarging the threshold by +8°C in the 470 * worst case. 471 */ 472 for (i = ARRAY_SIZE(hyst_levels_mc) - 1; i > 0; i--) 473 if (hyst_mc >= hyst_levels_mc[i]) 474 break; 475 476 return i & data->hyst_mask; 477 } 478 479 static void armada_set_overheat_thresholds(struct armada_thermal_priv *priv, 480 int thresh_mc, int hyst_mc) 481 { 482 struct armada_thermal_data *data = priv->data; 483 unsigned int threshold = armada_mc_to_reg_temp(data, thresh_mc); 484 unsigned int hysteresis = armada_mc_to_reg_hyst(data, hyst_mc); 485 u32 ctrl1; 486 487 regmap_read(priv->syscon, data->syscon_control1_off, &ctrl1); 488 489 /* Set Threshold */ 490 if (thresh_mc >= 0) { 491 ctrl1 &= ~(data->temp_mask << data->thresh_shift); 492 ctrl1 |= threshold << data->thresh_shift; 493 priv->current_threshold = thresh_mc; 494 } 495 496 /* Set Hysteresis */ 497 if (hyst_mc >= 0) { 498 ctrl1 &= ~(data->hyst_mask << data->hyst_shift); 499 ctrl1 |= hysteresis << data->hyst_shift; 500 priv->current_hysteresis = hyst_mc; 501 } 502 503 regmap_write(priv->syscon, data->syscon_control1_off, ctrl1); 504 } 505 506 static irqreturn_t armada_overheat_isr(int irq, void *blob) 507 { 508 /* 509 * Disable the IRQ and continue in thread context (thermal core 510 * notification and temperature monitoring). 511 */ 512 disable_irq_nosync(irq); 513 514 return IRQ_WAKE_THREAD; 515 } 516 517 static irqreturn_t armada_overheat_isr_thread(int irq, void *blob) 518 { 519 struct armada_thermal_priv *priv = blob; 520 int low_threshold = priv->current_threshold - priv->current_hysteresis; 521 int temperature; 522 u32 dummy; 523 int ret; 524 525 /* Notify the core in thread context */ 526 thermal_zone_device_update(priv->overheat_sensor, 527 THERMAL_EVENT_UNSPECIFIED); 528 529 /* 530 * The overheat interrupt must be cleared by reading the DFX interrupt 531 * cause _after_ the temperature has fallen down to the low threshold. 532 * Otherwise future interrupts might not be served. 533 */ 534 do { 535 msleep(OVERHEAT_INT_POLL_DELAY_MS); 536 mutex_lock(&priv->update_lock); 537 ret = armada_read_sensor(priv, &temperature); 538 mutex_unlock(&priv->update_lock); 539 if (ret) 540 goto enable_irq; 541 } while (temperature >= low_threshold); 542 543 regmap_read(priv->syscon, priv->data->dfx_irq_cause_off, &dummy); 544 545 /* Notify the thermal core that the temperature is acceptable again */ 546 thermal_zone_device_update(priv->overheat_sensor, 547 THERMAL_EVENT_UNSPECIFIED); 548 549 enable_irq: 550 enable_irq(irq); 551 552 return IRQ_HANDLED; 553 } 554 555 static const struct armada_thermal_data armadaxp_data = { 556 .init = armadaxp_init, 557 .temp_shift = 10, 558 .temp_mask = 0x1ff, 559 .coef_b = 3153000000ULL, 560 .coef_m = 10000000ULL, 561 .coef_div = 13825, 562 .syscon_status_off = 0xb0, 563 .syscon_control1_off = 0x2d0, 564 }; 565 566 static const struct armada_thermal_data armada370_data = { 567 .init = armada370_init, 568 .is_valid_bit = BIT(9), 569 .temp_shift = 10, 570 .temp_mask = 0x1ff, 571 .coef_b = 3153000000ULL, 572 .coef_m = 10000000ULL, 573 .coef_div = 13825, 574 .syscon_status_off = 0x0, 575 .syscon_control1_off = 0x4, 576 }; 577 578 static const struct armada_thermal_data armada375_data = { 579 .init = armada375_init, 580 .is_valid_bit = BIT(10), 581 .temp_shift = 0, 582 .temp_mask = 0x1ff, 583 .coef_b = 3171900000ULL, 584 .coef_m = 10000000ULL, 585 .coef_div = 13616, 586 .syscon_status_off = 0x78, 587 .syscon_control0_off = 0x7c, 588 .syscon_control1_off = 0x80, 589 }; 590 591 static const struct armada_thermal_data armada380_data = { 592 .init = armada380_init, 593 .is_valid_bit = BIT(10), 594 .temp_shift = 0, 595 .temp_mask = 0x3ff, 596 .coef_b = 1172499100ULL, 597 .coef_m = 2000096ULL, 598 .coef_div = 4201, 599 .inverted = true, 600 .syscon_control0_off = 0x70, 601 .syscon_control1_off = 0x74, 602 .syscon_status_off = 0x78, 603 }; 604 605 static const struct armada_thermal_data armada_ap806_data = { 606 .init = armada_ap80x_init, 607 .is_valid_bit = BIT(16), 608 .temp_shift = 0, 609 .temp_mask = 0x3ff, 610 .thresh_shift = 3, 611 .hyst_shift = 19, 612 .hyst_mask = 0x3, 613 .coef_b = -150000LL, 614 .coef_m = 423ULL, 615 .coef_div = 1, 616 .inverted = true, 617 .signed_sample = true, 618 .syscon_control0_off = 0x84, 619 .syscon_control1_off = 0x88, 620 .syscon_status_off = 0x8C, 621 .dfx_irq_cause_off = 0x108, 622 .dfx_irq_mask_off = 0x10C, 623 .dfx_overheat_irq = BIT(22), 624 .dfx_server_irq_mask_off = 0x104, 625 .dfx_server_irq_en = BIT(1), 626 .cpu_nr = 4, 627 }; 628 629 static const struct armada_thermal_data armada_ap807_data = { 630 .init = armada_ap80x_init, 631 .is_valid_bit = BIT(16), 632 .temp_shift = 0, 633 .temp_mask = 0x3ff, 634 .thresh_shift = 3, 635 .hyst_shift = 19, 636 .hyst_mask = 0x3, 637 .coef_b = -128900LL, 638 .coef_m = 394ULL, 639 .coef_div = 1, 640 .inverted = true, 641 .signed_sample = true, 642 .syscon_control0_off = 0x84, 643 .syscon_control1_off = 0x88, 644 .syscon_status_off = 0x8C, 645 .dfx_irq_cause_off = 0x108, 646 .dfx_irq_mask_off = 0x10C, 647 .dfx_overheat_irq = BIT(22), 648 .dfx_server_irq_mask_off = 0x104, 649 .dfx_server_irq_en = BIT(1), 650 .cpu_nr = 4, 651 }; 652 653 static const struct armada_thermal_data armada_cp110_data = { 654 .init = armada_cp110_init, 655 .is_valid_bit = BIT(10), 656 .temp_shift = 0, 657 .temp_mask = 0x3ff, 658 .thresh_shift = 16, 659 .hyst_shift = 26, 660 .hyst_mask = 0x3, 661 .coef_b = 1172499100ULL, 662 .coef_m = 2000096ULL, 663 .coef_div = 4201, 664 .inverted = true, 665 .syscon_control0_off = 0x70, 666 .syscon_control1_off = 0x74, 667 .syscon_status_off = 0x78, 668 .dfx_irq_cause_off = 0x108, 669 .dfx_irq_mask_off = 0x10C, 670 .dfx_overheat_irq = BIT(20), 671 .dfx_server_irq_mask_off = 0x104, 672 .dfx_server_irq_en = BIT(1), 673 }; 674 675 static const struct of_device_id armada_thermal_id_table[] = { 676 { 677 .compatible = "marvell,armadaxp-thermal", 678 .data = &armadaxp_data, 679 }, 680 { 681 .compatible = "marvell,armada370-thermal", 682 .data = &armada370_data, 683 }, 684 { 685 .compatible = "marvell,armada375-thermal", 686 .data = &armada375_data, 687 }, 688 { 689 .compatible = "marvell,armada380-thermal", 690 .data = &armada380_data, 691 }, 692 { 693 .compatible = "marvell,armada-ap806-thermal", 694 .data = &armada_ap806_data, 695 }, 696 { 697 .compatible = "marvell,armada-ap807-thermal", 698 .data = &armada_ap807_data, 699 }, 700 { 701 .compatible = "marvell,armada-cp110-thermal", 702 .data = &armada_cp110_data, 703 }, 704 { 705 /* sentinel */ 706 }, 707 }; 708 MODULE_DEVICE_TABLE(of, armada_thermal_id_table); 709 710 static const struct regmap_config armada_thermal_regmap_config = { 711 .reg_bits = 32, 712 .reg_stride = 4, 713 .val_bits = 32, 714 }; 715 716 static int armada_thermal_probe_legacy(struct platform_device *pdev, 717 struct armada_thermal_priv *priv) 718 { 719 struct armada_thermal_data *data = priv->data; 720 void __iomem *base; 721 722 /* First memory region points towards the status register */ 723 base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); 724 if (IS_ERR(base)) 725 return PTR_ERR(base); 726 727 /* 728 * Fix up from the old individual DT register specification to 729 * cover all the registers. We do this by adjusting the ioremap() 730 * result, which should be fine as ioremap() deals with pages. 731 * However, validate that we do not cross a page boundary while 732 * making this adjustment. 733 */ 734 if (((unsigned long)base & ~PAGE_MASK) < data->syscon_status_off) 735 return -EINVAL; 736 base -= data->syscon_status_off; 737 738 priv->syscon = devm_regmap_init_mmio(&pdev->dev, base, 739 &armada_thermal_regmap_config); 740 return PTR_ERR_OR_ZERO(priv->syscon); 741 } 742 743 static int armada_thermal_probe_syscon(struct platform_device *pdev, 744 struct armada_thermal_priv *priv) 745 { 746 priv->syscon = syscon_node_to_regmap(pdev->dev.parent->of_node); 747 return PTR_ERR_OR_ZERO(priv->syscon); 748 } 749 750 static void armada_set_sane_name(struct platform_device *pdev, 751 struct armada_thermal_priv *priv) 752 { 753 const char *name = dev_name(&pdev->dev); 754 755 if (strlen(name) > THERMAL_NAME_LENGTH) { 756 /* 757 * When inside a system controller, the device name has the 758 * form: f06f8000.system-controller:ap-thermal so stripping 759 * after the ':' should give us a shorter but meaningful name. 760 */ 761 name = strrchr(name, ':'); 762 if (!name) 763 name = "armada_thermal"; 764 else 765 name++; 766 } 767 768 /* Save the name locally */ 769 strscpy(priv->zone_name, name, THERMAL_NAME_LENGTH); 770 771 /* Then ensure there are no '-' or hwmon core will complain */ 772 strreplace(priv->zone_name, '-', '_'); 773 } 774 775 /* 776 * The IP can manage to trigger interrupts on overheat situation from all the 777 * sensors. However, the interrupt source changes along with the last selected 778 * source (ie. the last read sensor), which is an inconsistent behavior. Avoid 779 * possible glitches by always selecting back only one channel (arbitrarily: the 780 * first in the DT which has a critical trip point). We also disable sensor 781 * switch during overheat situations. 782 */ 783 static int armada_configure_overheat_int(struct armada_thermal_priv *priv, 784 struct thermal_zone_device *tz, 785 int sensor_id) 786 { 787 /* Retrieve the critical trip point to enable the overheat interrupt */ 788 int temperature; 789 int ret; 790 791 ret = thermal_zone_get_crit_temp(tz, &temperature); 792 if (ret) 793 return ret; 794 795 ret = armada_select_channel(priv, sensor_id); 796 if (ret) 797 return ret; 798 799 /* 800 * A critical temperature does not have a hysteresis 801 */ 802 armada_set_overheat_thresholds(priv, temperature, 0); 803 priv->overheat_sensor = tz; 804 priv->interrupt_source = sensor_id; 805 armada_enable_overheat_interrupt(priv); 806 807 return 0; 808 } 809 810 static int armada_thermal_probe(struct platform_device *pdev) 811 { 812 struct thermal_zone_device *tz; 813 struct armada_thermal_sensor *sensor; 814 struct armada_drvdata *drvdata; 815 const struct of_device_id *match; 816 struct armada_thermal_priv *priv; 817 int sensor_id, irq; 818 int ret; 819 820 match = of_match_device(armada_thermal_id_table, &pdev->dev); 821 if (!match) 822 return -ENODEV; 823 824 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 825 if (!priv) 826 return -ENOMEM; 827 828 drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); 829 if (!drvdata) 830 return -ENOMEM; 831 832 priv->dev = &pdev->dev; 833 priv->data = (struct armada_thermal_data *)match->data; 834 835 mutex_init(&priv->update_lock); 836 837 /* 838 * Legacy DT bindings only described "control1" register (also referred 839 * as "control MSB" on old documentation). Then, bindings moved to cover 840 * "control0/control LSB" and "control1/control MSB" registers within 841 * the same resource, which was then of size 8 instead of 4. 842 * 843 * The logic of defining sporadic registers is broken. For instance, it 844 * blocked the addition of the overheat interrupt feature that needed 845 * another resource somewhere else in the same memory area. One solution 846 * is to define an overall system controller and put the thermal node 847 * into it, which requires the use of regmaps across all the driver. 848 */ 849 if (IS_ERR(syscon_node_to_regmap(pdev->dev.parent->of_node))) { 850 /* Ensure device name is correct for the thermal core */ 851 armada_set_sane_name(pdev, priv); 852 853 ret = armada_thermal_probe_legacy(pdev, priv); 854 if (ret) 855 return ret; 856 857 priv->data->init(pdev, priv); 858 859 /* Wait the sensors to be valid */ 860 armada_wait_sensor_validity(priv); 861 862 tz = thermal_tripless_zone_device_register(priv->zone_name, 863 priv, &legacy_ops, 864 NULL); 865 if (IS_ERR(tz)) { 866 dev_err(&pdev->dev, 867 "Failed to register thermal zone device\n"); 868 return PTR_ERR(tz); 869 } 870 871 ret = thermal_zone_device_enable(tz); 872 if (ret) { 873 thermal_zone_device_unregister(tz); 874 return ret; 875 } 876 877 drvdata->type = LEGACY; 878 drvdata->data.tz = tz; 879 platform_set_drvdata(pdev, drvdata); 880 881 return 0; 882 } 883 884 ret = armada_thermal_probe_syscon(pdev, priv); 885 if (ret) 886 return ret; 887 888 priv->current_channel = -1; 889 priv->data->init(pdev, priv); 890 drvdata->type = SYSCON; 891 drvdata->data.priv = priv; 892 platform_set_drvdata(pdev, drvdata); 893 894 irq = platform_get_irq(pdev, 0); 895 if (irq == -EPROBE_DEFER) 896 return irq; 897 898 /* The overheat interrupt feature is not mandatory */ 899 if (irq > 0) { 900 ret = devm_request_threaded_irq(&pdev->dev, irq, 901 armada_overheat_isr, 902 armada_overheat_isr_thread, 903 0, NULL, priv); 904 if (ret) 905 return ret; 906 } 907 908 /* 909 * There is one channel for the IC and one per CPU (if any), each 910 * channel has one sensor. 911 */ 912 for (sensor_id = 0; sensor_id <= priv->data->cpu_nr; sensor_id++) { 913 sensor = devm_kzalloc(&pdev->dev, 914 sizeof(struct armada_thermal_sensor), 915 GFP_KERNEL); 916 if (!sensor) 917 return -ENOMEM; 918 919 /* Register the sensor */ 920 sensor->priv = priv; 921 sensor->id = sensor_id; 922 tz = devm_thermal_of_zone_register(&pdev->dev, 923 sensor->id, sensor, 924 &of_ops); 925 if (IS_ERR(tz)) { 926 dev_info(&pdev->dev, "Thermal sensor %d unavailable\n", 927 sensor_id); 928 devm_kfree(&pdev->dev, sensor); 929 continue; 930 } 931 932 /* 933 * The first channel that has a critical trip point registered 934 * in the DT will serve as interrupt source. Others possible 935 * critical trip points will simply be ignored by the driver. 936 */ 937 if (irq > 0 && !priv->overheat_sensor) 938 armada_configure_overheat_int(priv, tz, sensor->id); 939 } 940 941 /* Just complain if no overheat interrupt was set up */ 942 if (!priv->overheat_sensor) 943 dev_warn(&pdev->dev, "Overheat interrupt not available\n"); 944 945 return 0; 946 } 947 948 static void armada_thermal_exit(struct platform_device *pdev) 949 { 950 struct armada_drvdata *drvdata = platform_get_drvdata(pdev); 951 952 if (drvdata->type == LEGACY) 953 thermal_zone_device_unregister(drvdata->data.tz); 954 } 955 956 static struct platform_driver armada_thermal_driver = { 957 .probe = armada_thermal_probe, 958 .remove = armada_thermal_exit, 959 .driver = { 960 .name = "armada_thermal", 961 .of_match_table = armada_thermal_id_table, 962 }, 963 }; 964 965 module_platform_driver(armada_thermal_driver); 966 967 MODULE_AUTHOR("Ezequiel Garcia <ezequiel.garcia@free-electrons.com>"); 968 MODULE_DESCRIPTION("Marvell EBU Armada SoCs thermal driver"); 969 MODULE_LICENSE("GPL v2"); 970