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