1 /* 2 * Marvell EBU Armada SoCs thermal sensor driver 3 * 4 * Copyright (C) 2013 Marvell 5 * 6 * This software is licensed under the terms of the GNU General Public 7 * License version 2, as published by the Free Software Foundation, and 8 * may be copied, distributed, and modified under those terms. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 */ 16 #include <linux/device.h> 17 #include <linux/err.h> 18 #include <linux/io.h> 19 #include <linux/kernel.h> 20 #include <linux/of.h> 21 #include <linux/module.h> 22 #include <linux/delay.h> 23 #include <linux/platform_device.h> 24 #include <linux/of_device.h> 25 #include <linux/thermal.h> 26 #include <linux/iopoll.h> 27 #include <linux/mfd/syscon.h> 28 #include <linux/regmap.h> 29 30 /* Thermal Manager Control and Status Register */ 31 #define PMU_TDC0_SW_RST_MASK (0x1 << 1) 32 #define PMU_TM_DISABLE_OFFS 0 33 #define PMU_TM_DISABLE_MASK (0x1 << PMU_TM_DISABLE_OFFS) 34 #define PMU_TDC0_REF_CAL_CNT_OFFS 11 35 #define PMU_TDC0_REF_CAL_CNT_MASK (0x1ff << PMU_TDC0_REF_CAL_CNT_OFFS) 36 #define PMU_TDC0_OTF_CAL_MASK (0x1 << 30) 37 #define PMU_TDC0_START_CAL_MASK (0x1 << 25) 38 39 #define A375_UNIT_CONTROL_SHIFT 27 40 #define A375_UNIT_CONTROL_MASK 0x7 41 #define A375_READOUT_INVERT BIT(15) 42 #define A375_HW_RESETn BIT(8) 43 44 /* Errata fields */ 45 #define CONTROL0_TSEN_TC_TRIM_MASK 0x7 46 #define CONTROL0_TSEN_TC_TRIM_VAL 0x3 47 48 #define CONTROL0_TSEN_START BIT(0) 49 #define CONTROL0_TSEN_RESET BIT(1) 50 #define CONTROL0_TSEN_ENABLE BIT(2) 51 #define CONTROL0_TSEN_AVG_BYPASS BIT(6) 52 #define CONTROL0_TSEN_CHAN_SHIFT 13 53 #define CONTROL0_TSEN_CHAN_MASK 0xF 54 #define CONTROL0_TSEN_OSR_SHIFT 24 55 #define CONTROL0_TSEN_OSR_MAX 0x3 56 #define CONTROL0_TSEN_MODE_SHIFT 30 57 #define CONTROL0_TSEN_MODE_EXTERNAL 0x2 58 #define CONTROL0_TSEN_MODE_MASK 0x3 59 60 #define CONTROL1_TSEN_AVG_SHIFT 0 61 #define CONTROL1_TSEN_AVG_MASK 0x7 62 #define CONTROL1_EXT_TSEN_SW_RESET BIT(7) 63 #define CONTROL1_EXT_TSEN_HW_RESETn BIT(8) 64 65 #define STATUS_POLL_PERIOD_US 1000 66 #define STATUS_POLL_TIMEOUT_US 100000 67 68 struct armada_thermal_data; 69 70 /* Marvell EBU Thermal Sensor Dev Structure */ 71 struct armada_thermal_priv { 72 struct device *dev; 73 struct regmap *syscon; 74 char zone_name[THERMAL_NAME_LENGTH]; 75 /* serialize temperature reads/updates */ 76 struct mutex update_lock; 77 struct armada_thermal_data *data; 78 int current_channel; 79 }; 80 81 struct armada_thermal_data { 82 /* Initialize the thermal IC */ 83 void (*init)(struct platform_device *pdev, 84 struct armada_thermal_priv *priv); 85 86 /* Formula coeficients: temp = (b - m * reg) / div */ 87 s64 coef_b; 88 s64 coef_m; 89 u32 coef_div; 90 bool inverted; 91 bool signed_sample; 92 93 /* Register shift and mask to access the sensor temperature */ 94 unsigned int temp_shift; 95 unsigned int temp_mask; 96 u32 is_valid_bit; 97 98 /* Syscon access */ 99 unsigned int syscon_control0_off; 100 unsigned int syscon_control1_off; 101 unsigned int syscon_status_off; 102 103 /* One sensor is in the thermal IC, the others are in the CPUs if any */ 104 unsigned int cpu_nr; 105 }; 106 107 struct armada_drvdata { 108 enum drvtype { 109 LEGACY, 110 SYSCON 111 } type; 112 union { 113 struct armada_thermal_priv *priv; 114 struct thermal_zone_device *tz; 115 } data; 116 }; 117 118 /* 119 * struct armada_thermal_sensor - hold the information of one thermal sensor 120 * @thermal: pointer to the local private structure 121 * @tzd: pointer to the thermal zone device 122 * @id: identifier of the thermal sensor 123 */ 124 struct armada_thermal_sensor { 125 struct armada_thermal_priv *priv; 126 int id; 127 }; 128 129 static void armadaxp_init(struct platform_device *pdev, 130 struct armada_thermal_priv *priv) 131 { 132 struct armada_thermal_data *data = priv->data; 133 u32 reg; 134 135 regmap_read(priv->syscon, data->syscon_control1_off, ®); 136 reg |= PMU_TDC0_OTF_CAL_MASK; 137 138 /* Reference calibration value */ 139 reg &= ~PMU_TDC0_REF_CAL_CNT_MASK; 140 reg |= (0xf1 << PMU_TDC0_REF_CAL_CNT_OFFS); 141 142 /* Reset the sensor */ 143 reg |= PMU_TDC0_SW_RST_MASK; 144 145 regmap_write(priv->syscon, data->syscon_control1_off, reg); 146 147 /* Enable the sensor */ 148 regmap_read(priv->syscon, data->syscon_status_off, ®); 149 reg &= ~PMU_TM_DISABLE_MASK; 150 regmap_write(priv->syscon, data->syscon_status_off, reg); 151 } 152 153 static void armada370_init(struct platform_device *pdev, 154 struct armada_thermal_priv *priv) 155 { 156 struct armada_thermal_data *data = priv->data; 157 u32 reg; 158 159 regmap_read(priv->syscon, data->syscon_control1_off, ®); 160 reg |= PMU_TDC0_OTF_CAL_MASK; 161 162 /* Reference calibration value */ 163 reg &= ~PMU_TDC0_REF_CAL_CNT_MASK; 164 reg |= (0xf1 << PMU_TDC0_REF_CAL_CNT_OFFS); 165 166 /* Reset the sensor */ 167 reg &= ~PMU_TDC0_START_CAL_MASK; 168 169 regmap_write(priv->syscon, data->syscon_control1_off, reg); 170 171 msleep(10); 172 } 173 174 static void armada375_init(struct platform_device *pdev, 175 struct armada_thermal_priv *priv) 176 { 177 struct armada_thermal_data *data = priv->data; 178 u32 reg; 179 180 regmap_read(priv->syscon, data->syscon_control1_off, ®); 181 reg &= ~(A375_UNIT_CONTROL_MASK << A375_UNIT_CONTROL_SHIFT); 182 reg &= ~A375_READOUT_INVERT; 183 reg &= ~A375_HW_RESETn; 184 regmap_write(priv->syscon, data->syscon_control1_off, reg); 185 186 msleep(20); 187 188 reg |= A375_HW_RESETn; 189 regmap_write(priv->syscon, data->syscon_control1_off, reg); 190 191 msleep(50); 192 } 193 194 static int armada_wait_sensor_validity(struct armada_thermal_priv *priv) 195 { 196 u32 reg; 197 198 return regmap_read_poll_timeout(priv->syscon, 199 priv->data->syscon_status_off, reg, 200 reg & priv->data->is_valid_bit, 201 STATUS_POLL_PERIOD_US, 202 STATUS_POLL_TIMEOUT_US); 203 } 204 205 static void armada380_init(struct platform_device *pdev, 206 struct armada_thermal_priv *priv) 207 { 208 struct armada_thermal_data *data = priv->data; 209 u32 reg; 210 211 /* Disable the HW/SW reset */ 212 regmap_read(priv->syscon, data->syscon_control1_off, ®); 213 reg |= CONTROL1_EXT_TSEN_HW_RESETn; 214 reg &= ~CONTROL1_EXT_TSEN_SW_RESET; 215 regmap_write(priv->syscon, data->syscon_control1_off, reg); 216 217 /* Set Tsen Tc Trim to correct default value (errata #132698) */ 218 regmap_read(priv->syscon, data->syscon_control0_off, ®); 219 reg &= ~CONTROL0_TSEN_TC_TRIM_MASK; 220 reg |= CONTROL0_TSEN_TC_TRIM_VAL; 221 regmap_write(priv->syscon, data->syscon_control0_off, reg); 222 } 223 224 static void armada_ap806_init(struct platform_device *pdev, 225 struct armada_thermal_priv *priv) 226 { 227 struct armada_thermal_data *data = priv->data; 228 u32 reg; 229 230 regmap_read(priv->syscon, data->syscon_control0_off, ®); 231 reg &= ~CONTROL0_TSEN_RESET; 232 reg |= CONTROL0_TSEN_START | CONTROL0_TSEN_ENABLE; 233 234 /* Sample every ~2ms */ 235 reg |= CONTROL0_TSEN_OSR_MAX << CONTROL0_TSEN_OSR_SHIFT; 236 237 /* Enable average (2 samples by default) */ 238 reg &= ~CONTROL0_TSEN_AVG_BYPASS; 239 240 regmap_write(priv->syscon, data->syscon_control0_off, reg); 241 } 242 243 static void armada_cp110_init(struct platform_device *pdev, 244 struct armada_thermal_priv *priv) 245 { 246 struct armada_thermal_data *data = priv->data; 247 u32 reg; 248 249 armada380_init(pdev, priv); 250 251 /* Sample every ~2ms */ 252 regmap_read(priv->syscon, data->syscon_control0_off, ®); 253 reg |= CONTROL0_TSEN_OSR_MAX << CONTROL0_TSEN_OSR_SHIFT; 254 regmap_write(priv->syscon, data->syscon_control0_off, reg); 255 256 /* Average the output value over 2^1 = 2 samples */ 257 regmap_read(priv->syscon, data->syscon_control1_off, ®); 258 reg &= ~CONTROL1_TSEN_AVG_MASK << CONTROL1_TSEN_AVG_SHIFT; 259 reg |= 1 << CONTROL1_TSEN_AVG_SHIFT; 260 regmap_write(priv->syscon, data->syscon_control1_off, reg); 261 } 262 263 static bool armada_is_valid(struct armada_thermal_priv *priv) 264 { 265 u32 reg; 266 267 if (!priv->data->is_valid_bit) 268 return true; 269 270 regmap_read(priv->syscon, priv->data->syscon_status_off, ®); 271 272 return reg & priv->data->is_valid_bit; 273 } 274 275 /* There is currently no board with more than one sensor per channel */ 276 static int armada_select_channel(struct armada_thermal_priv *priv, int channel) 277 { 278 struct armada_thermal_data *data = priv->data; 279 u32 ctrl0; 280 281 if (channel < 0 || channel > priv->data->cpu_nr) 282 return -EINVAL; 283 284 if (priv->current_channel == channel) 285 return 0; 286 287 /* Stop the measurements */ 288 regmap_read(priv->syscon, data->syscon_control0_off, &ctrl0); 289 ctrl0 &= ~CONTROL0_TSEN_START; 290 regmap_write(priv->syscon, data->syscon_control0_off, ctrl0); 291 292 /* Reset the mode, internal sensor will be automatically selected */ 293 ctrl0 &= ~(CONTROL0_TSEN_MODE_MASK << CONTROL0_TSEN_MODE_SHIFT); 294 295 /* Other channels are external and should be selected accordingly */ 296 if (channel) { 297 /* Change the mode to external */ 298 ctrl0 |= CONTROL0_TSEN_MODE_EXTERNAL << 299 CONTROL0_TSEN_MODE_SHIFT; 300 /* Select the sensor */ 301 ctrl0 &= ~(CONTROL0_TSEN_CHAN_MASK << CONTROL0_TSEN_CHAN_SHIFT); 302 ctrl0 |= (channel - 1) << CONTROL0_TSEN_CHAN_SHIFT; 303 } 304 305 /* Actually set the mode/channel */ 306 regmap_write(priv->syscon, data->syscon_control0_off, ctrl0); 307 priv->current_channel = channel; 308 309 /* Re-start the measurements */ 310 ctrl0 |= CONTROL0_TSEN_START; 311 regmap_write(priv->syscon, data->syscon_control0_off, ctrl0); 312 313 /* 314 * The IP has a latency of ~15ms, so after updating the selected source, 315 * we must absolutely wait for the sensor validity bit to ensure we read 316 * actual data. 317 */ 318 if (armada_wait_sensor_validity(priv)) { 319 dev_err(priv->dev, 320 "Temperature sensor reading not valid\n"); 321 return -EIO; 322 } 323 324 return 0; 325 } 326 327 static int armada_read_sensor(struct armada_thermal_priv *priv, int *temp) 328 { 329 u32 reg, div; 330 s64 sample, b, m; 331 332 regmap_read(priv->syscon, priv->data->syscon_status_off, ®); 333 reg = (reg >> priv->data->temp_shift) & priv->data->temp_mask; 334 if (priv->data->signed_sample) 335 /* The most significant bit is the sign bit */ 336 sample = sign_extend32(reg, fls(priv->data->temp_mask) - 1); 337 else 338 sample = reg; 339 340 /* Get formula coeficients */ 341 b = priv->data->coef_b; 342 m = priv->data->coef_m; 343 div = priv->data->coef_div; 344 345 if (priv->data->inverted) 346 *temp = div_s64((m * sample) - b, div); 347 else 348 *temp = div_s64(b - (m * sample), div); 349 350 return 0; 351 } 352 353 static int armada_get_temp_legacy(struct thermal_zone_device *thermal, 354 int *temp) 355 { 356 struct armada_thermal_priv *priv = thermal->devdata; 357 int ret; 358 359 /* Valid check */ 360 if (armada_is_valid(priv)) { 361 dev_err(priv->dev, 362 "Temperature sensor reading not valid\n"); 363 return -EIO; 364 } 365 366 /* Do the actual reading */ 367 ret = armada_read_sensor(priv, temp); 368 369 return ret; 370 } 371 372 static struct thermal_zone_device_ops legacy_ops = { 373 .get_temp = armada_get_temp_legacy, 374 }; 375 376 static int armada_get_temp(void *_sensor, int *temp) 377 { 378 struct armada_thermal_sensor *sensor = _sensor; 379 struct armada_thermal_priv *priv = sensor->priv; 380 int ret; 381 382 mutex_lock(&priv->update_lock); 383 384 /* Select the desired channel */ 385 ret = armada_select_channel(priv, sensor->id); 386 if (ret) 387 goto unlock_mutex; 388 389 /* Do the actual reading */ 390 ret = armada_read_sensor(priv, temp); 391 392 unlock_mutex: 393 mutex_unlock(&priv->update_lock); 394 395 return ret; 396 } 397 398 static struct thermal_zone_of_device_ops of_ops = { 399 .get_temp = armada_get_temp, 400 }; 401 402 static const struct armada_thermal_data armadaxp_data = { 403 .init = armadaxp_init, 404 .temp_shift = 10, 405 .temp_mask = 0x1ff, 406 .coef_b = 3153000000ULL, 407 .coef_m = 10000000ULL, 408 .coef_div = 13825, 409 .syscon_status_off = 0xb0, 410 .syscon_control1_off = 0xd0, 411 }; 412 413 static const struct armada_thermal_data armada370_data = { 414 .init = armada370_init, 415 .is_valid_bit = BIT(9), 416 .temp_shift = 10, 417 .temp_mask = 0x1ff, 418 .coef_b = 3153000000ULL, 419 .coef_m = 10000000ULL, 420 .coef_div = 13825, 421 .syscon_status_off = 0x0, 422 .syscon_control1_off = 0x4, 423 }; 424 425 static const struct armada_thermal_data armada375_data = { 426 .init = armada375_init, 427 .is_valid_bit = BIT(10), 428 .temp_shift = 0, 429 .temp_mask = 0x1ff, 430 .coef_b = 3171900000ULL, 431 .coef_m = 10000000ULL, 432 .coef_div = 13616, 433 .syscon_status_off = 0x78, 434 .syscon_control0_off = 0x7c, 435 .syscon_control1_off = 0x80, 436 }; 437 438 static const struct armada_thermal_data armada380_data = { 439 .init = armada380_init, 440 .is_valid_bit = BIT(10), 441 .temp_shift = 0, 442 .temp_mask = 0x3ff, 443 .coef_b = 1172499100ULL, 444 .coef_m = 2000096ULL, 445 .coef_div = 4201, 446 .inverted = true, 447 .syscon_control0_off = 0x70, 448 .syscon_control1_off = 0x74, 449 .syscon_status_off = 0x78, 450 }; 451 452 static const struct armada_thermal_data armada_ap806_data = { 453 .init = armada_ap806_init, 454 .is_valid_bit = BIT(16), 455 .temp_shift = 0, 456 .temp_mask = 0x3ff, 457 .coef_b = -150000LL, 458 .coef_m = 423ULL, 459 .coef_div = 1, 460 .inverted = true, 461 .signed_sample = true, 462 .syscon_control0_off = 0x84, 463 .syscon_control1_off = 0x88, 464 .syscon_status_off = 0x8C, 465 .cpu_nr = 4, 466 }; 467 468 static const struct armada_thermal_data armada_cp110_data = { 469 .init = armada_cp110_init, 470 .is_valid_bit = BIT(10), 471 .temp_shift = 0, 472 .temp_mask = 0x3ff, 473 .coef_b = 1172499100ULL, 474 .coef_m = 2000096ULL, 475 .coef_div = 4201, 476 .inverted = true, 477 .syscon_control0_off = 0x70, 478 .syscon_control1_off = 0x74, 479 .syscon_status_off = 0x78, 480 }; 481 482 static const struct of_device_id armada_thermal_id_table[] = { 483 { 484 .compatible = "marvell,armadaxp-thermal", 485 .data = &armadaxp_data, 486 }, 487 { 488 .compatible = "marvell,armada370-thermal", 489 .data = &armada370_data, 490 }, 491 { 492 .compatible = "marvell,armada375-thermal", 493 .data = &armada375_data, 494 }, 495 { 496 .compatible = "marvell,armada380-thermal", 497 .data = &armada380_data, 498 }, 499 { 500 .compatible = "marvell,armada-ap806-thermal", 501 .data = &armada_ap806_data, 502 }, 503 { 504 .compatible = "marvell,armada-cp110-thermal", 505 .data = &armada_cp110_data, 506 }, 507 { 508 /* sentinel */ 509 }, 510 }; 511 MODULE_DEVICE_TABLE(of, armada_thermal_id_table); 512 513 static const struct regmap_config armada_thermal_regmap_config = { 514 .reg_bits = 32, 515 .reg_stride = 4, 516 .val_bits = 32, 517 .fast_io = true, 518 }; 519 520 static int armada_thermal_probe_legacy(struct platform_device *pdev, 521 struct armada_thermal_priv *priv) 522 { 523 struct armada_thermal_data *data = priv->data; 524 struct resource *res; 525 void __iomem *base; 526 527 /* First memory region points towards the status register */ 528 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 529 if (IS_ERR(res)) 530 return PTR_ERR(res); 531 532 /* 533 * Edit the resource start address and length to map over all the 534 * registers, instead of pointing at them one by one. 535 */ 536 res->start -= data->syscon_status_off; 537 res->end = res->start + max(data->syscon_status_off, 538 max(data->syscon_control0_off, 539 data->syscon_control1_off)) + 540 sizeof(unsigned int) - 1; 541 542 base = devm_ioremap_resource(&pdev->dev, res); 543 if (IS_ERR(base)) 544 return PTR_ERR(base); 545 546 priv->syscon = devm_regmap_init_mmio(&pdev->dev, base, 547 &armada_thermal_regmap_config); 548 if (IS_ERR(priv->syscon)) 549 return PTR_ERR(priv->syscon); 550 551 return 0; 552 } 553 554 static int armada_thermal_probe_syscon(struct platform_device *pdev, 555 struct armada_thermal_priv *priv) 556 { 557 priv->syscon = syscon_node_to_regmap(pdev->dev.parent->of_node); 558 if (IS_ERR(priv->syscon)) 559 return PTR_ERR(priv->syscon); 560 561 return 0; 562 } 563 564 static void armada_set_sane_name(struct platform_device *pdev, 565 struct armada_thermal_priv *priv) 566 { 567 const char *name = dev_name(&pdev->dev); 568 char *insane_char; 569 570 if (strlen(name) > THERMAL_NAME_LENGTH) { 571 /* 572 * When inside a system controller, the device name has the 573 * form: f06f8000.system-controller:ap-thermal so stripping 574 * after the ':' should give us a shorter but meaningful name. 575 */ 576 name = strrchr(name, ':'); 577 if (!name) 578 name = "armada_thermal"; 579 else 580 name++; 581 } 582 583 /* Save the name locally */ 584 strncpy(priv->zone_name, name, THERMAL_NAME_LENGTH - 1); 585 priv->zone_name[THERMAL_NAME_LENGTH - 1] = '\0'; 586 587 /* Then check there are no '-' or hwmon core will complain */ 588 do { 589 insane_char = strpbrk(priv->zone_name, "-"); 590 if (insane_char) 591 *insane_char = '_'; 592 } while (insane_char); 593 } 594 595 static int armada_thermal_probe(struct platform_device *pdev) 596 { 597 struct thermal_zone_device *tz; 598 struct armada_thermal_sensor *sensor; 599 struct armada_drvdata *drvdata; 600 const struct of_device_id *match; 601 struct armada_thermal_priv *priv; 602 int sensor_id; 603 int ret; 604 605 match = of_match_device(armada_thermal_id_table, &pdev->dev); 606 if (!match) 607 return -ENODEV; 608 609 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 610 if (!priv) 611 return -ENOMEM; 612 613 drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); 614 if (!drvdata) 615 return -ENOMEM; 616 617 priv->dev = &pdev->dev; 618 priv->data = (struct armada_thermal_data *)match->data; 619 620 mutex_init(&priv->update_lock); 621 622 /* 623 * Legacy DT bindings only described "control1" register (also referred 624 * as "control MSB" on old documentation). Then, bindings moved to cover 625 * "control0/control LSB" and "control1/control MSB" registers within 626 * the same resource, which was then of size 8 instead of 4. 627 * 628 * The logic of defining sporadic registers is broken. For instance, it 629 * blocked the addition of the overheat interrupt feature that needed 630 * another resource somewhere else in the same memory area. One solution 631 * is to define an overall system controller and put the thermal node 632 * into it, which requires the use of regmaps across all the driver. 633 */ 634 if (IS_ERR(syscon_node_to_regmap(pdev->dev.parent->of_node))) { 635 /* Ensure device name is correct for the thermal core */ 636 armada_set_sane_name(pdev, priv); 637 638 ret = armada_thermal_probe_legacy(pdev, priv); 639 if (ret) 640 return ret; 641 642 priv->data->init(pdev, priv); 643 644 /* Wait the sensors to be valid */ 645 armada_wait_sensor_validity(priv); 646 647 tz = thermal_zone_device_register(priv->zone_name, 0, 0, priv, 648 &legacy_ops, NULL, 0, 0); 649 if (IS_ERR(tz)) { 650 dev_err(&pdev->dev, 651 "Failed to register thermal zone device\n"); 652 return PTR_ERR(tz); 653 } 654 655 drvdata->type = LEGACY; 656 drvdata->data.tz = tz; 657 platform_set_drvdata(pdev, drvdata); 658 659 return 0; 660 } 661 662 ret = armada_thermal_probe_syscon(pdev, priv); 663 if (ret) 664 return ret; 665 666 priv->current_channel = -1; 667 priv->data->init(pdev, priv); 668 drvdata->type = SYSCON; 669 drvdata->data.priv = priv; 670 platform_set_drvdata(pdev, drvdata); 671 672 /* 673 * There is one channel for the IC and one per CPU (if any), each 674 * channel has one sensor. 675 */ 676 for (sensor_id = 0; sensor_id <= priv->data->cpu_nr; sensor_id++) { 677 sensor = devm_kzalloc(&pdev->dev, 678 sizeof(struct armada_thermal_sensor), 679 GFP_KERNEL); 680 if (!sensor) 681 return -ENOMEM; 682 683 /* Register the sensor */ 684 sensor->priv = priv; 685 sensor->id = sensor_id; 686 tz = devm_thermal_zone_of_sensor_register(&pdev->dev, 687 sensor->id, sensor, 688 &of_ops); 689 if (IS_ERR(tz)) { 690 dev_info(&pdev->dev, "Thermal sensor %d unavailable\n", 691 sensor_id); 692 devm_kfree(&pdev->dev, sensor); 693 continue; 694 } 695 } 696 697 return 0; 698 } 699 700 static int armada_thermal_exit(struct platform_device *pdev) 701 { 702 struct armada_drvdata *drvdata = platform_get_drvdata(pdev); 703 704 if (drvdata->type == LEGACY) 705 thermal_zone_device_unregister(drvdata->data.tz); 706 707 return 0; 708 } 709 710 static struct platform_driver armada_thermal_driver = { 711 .probe = armada_thermal_probe, 712 .remove = armada_thermal_exit, 713 .driver = { 714 .name = "armada_thermal", 715 .of_match_table = armada_thermal_id_table, 716 }, 717 }; 718 719 module_platform_driver(armada_thermal_driver); 720 721 MODULE_AUTHOR("Ezequiel Garcia <ezequiel.garcia@free-electrons.com>"); 722 MODULE_DESCRIPTION("Marvell EBU Armada SoCs thermal driver"); 723 MODULE_LICENSE("GPL v2"); 724