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