1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * HiSilicon thermal sensor driver 4 * 5 * Copyright (c) 2014-2015 HiSilicon Limited. 6 * Copyright (c) 2014-2015 Linaro Limited. 7 * 8 * Xinwei Kong <kong.kongxinwei@hisilicon.com> 9 * Leo Yan <leo.yan@linaro.org> 10 */ 11 12 #include <linux/cpufreq.h> 13 #include <linux/delay.h> 14 #include <linux/interrupt.h> 15 #include <linux/module.h> 16 #include <linux/platform_device.h> 17 #include <linux/io.h> 18 #include <linux/of_device.h> 19 20 #include "thermal_core.h" 21 22 #define HI6220_TEMP0_LAG (0x0) 23 #define HI6220_TEMP0_TH (0x4) 24 #define HI6220_TEMP0_RST_TH (0x8) 25 #define HI6220_TEMP0_CFG (0xC) 26 #define HI6220_TEMP0_CFG_SS_MSK (0xF000) 27 #define HI6220_TEMP0_CFG_HDAK_MSK (0x30) 28 #define HI6220_TEMP0_EN (0x10) 29 #define HI6220_TEMP0_INT_EN (0x14) 30 #define HI6220_TEMP0_INT_CLR (0x18) 31 #define HI6220_TEMP0_RST_MSK (0x1C) 32 #define HI6220_TEMP0_VALUE (0x28) 33 34 #define HI3660_OFFSET(chan) ((chan) * 0x40) 35 #define HI3660_TEMP(chan) (HI3660_OFFSET(chan) + 0x1C) 36 #define HI3660_TH(chan) (HI3660_OFFSET(chan) + 0x20) 37 #define HI3660_LAG(chan) (HI3660_OFFSET(chan) + 0x28) 38 #define HI3660_INT_EN(chan) (HI3660_OFFSET(chan) + 0x2C) 39 #define HI3660_INT_CLR(chan) (HI3660_OFFSET(chan) + 0x30) 40 41 #define HI6220_TEMP_BASE (-60000) 42 #define HI6220_TEMP_RESET (100000) 43 #define HI6220_TEMP_STEP (785) 44 #define HI6220_TEMP_LAG (3500) 45 46 #define HI3660_TEMP_BASE (-63780) 47 #define HI3660_TEMP_STEP (205) 48 #define HI3660_TEMP_LAG (4000) 49 50 #define HI6220_CLUSTER0_SENSOR 2 51 #define HI6220_CLUSTER1_SENSOR 1 52 53 #define HI3660_LITTLE_SENSOR 0 54 #define HI3660_BIG_SENSOR 1 55 #define HI3660_G3D_SENSOR 2 56 #define HI3660_MODEM_SENSOR 3 57 58 struct hisi_thermal_data; 59 60 struct hisi_thermal_sensor { 61 struct hisi_thermal_data *data; 62 struct thermal_zone_device *tzd; 63 const char *irq_name; 64 uint32_t id; 65 uint32_t thres_temp; 66 }; 67 68 struct hisi_thermal_ops { 69 int (*get_temp)(struct hisi_thermal_sensor *sensor); 70 int (*enable_sensor)(struct hisi_thermal_sensor *sensor); 71 int (*disable_sensor)(struct hisi_thermal_sensor *sensor); 72 int (*irq_handler)(struct hisi_thermal_sensor *sensor); 73 int (*probe)(struct hisi_thermal_data *data); 74 }; 75 76 struct hisi_thermal_data { 77 const struct hisi_thermal_ops *ops; 78 struct hisi_thermal_sensor *sensor; 79 struct platform_device *pdev; 80 struct clk *clk; 81 void __iomem *regs; 82 int nr_sensors; 83 }; 84 85 /* 86 * The temperature computation on the tsensor is as follow: 87 * Unit: millidegree Celsius 88 * Step: 200/255 (0.7843) 89 * Temperature base: -60°C 90 * 91 * The register is programmed in temperature steps, every step is 785 92 * millidegree and begins at -60 000 m°C 93 * 94 * The temperature from the steps: 95 * 96 * Temp = TempBase + (steps x 785) 97 * 98 * and the steps from the temperature: 99 * 100 * steps = (Temp - TempBase) / 785 101 * 102 */ 103 static inline int hi6220_thermal_step_to_temp(int step) 104 { 105 return HI6220_TEMP_BASE + (step * HI6220_TEMP_STEP); 106 } 107 108 static inline int hi6220_thermal_temp_to_step(int temp) 109 { 110 return DIV_ROUND_UP(temp - HI6220_TEMP_BASE, HI6220_TEMP_STEP); 111 } 112 113 /* 114 * for Hi3660, 115 * Step: 189/922 (0.205) 116 * Temperature base: -63.780°C 117 * 118 * The register is programmed in temperature steps, every step is 205 119 * millidegree and begins at -63 780 m°C 120 */ 121 static inline int hi3660_thermal_step_to_temp(int step) 122 { 123 return HI3660_TEMP_BASE + step * HI3660_TEMP_STEP; 124 } 125 126 static inline int hi3660_thermal_temp_to_step(int temp) 127 { 128 return DIV_ROUND_UP(temp - HI3660_TEMP_BASE, HI3660_TEMP_STEP); 129 } 130 131 /* 132 * The lag register contains 5 bits encoding the temperature in steps. 133 * 134 * Each time the temperature crosses the threshold boundary, an 135 * interrupt is raised. It could be when the temperature is going 136 * above the threshold or below. However, if the temperature is 137 * fluctuating around this value due to the load, we can receive 138 * several interrupts which may not desired. 139 * 140 * We can setup a temperature representing the delta between the 141 * threshold and the current temperature when the temperature is 142 * decreasing. 143 * 144 * For instance: the lag register is 5°C, the threshold is 65°C, when 145 * the temperature reaches 65°C an interrupt is raised and when the 146 * temperature decrease to 65°C - 5°C another interrupt is raised. 147 * 148 * A very short lag can lead to an interrupt storm, a long lag 149 * increase the latency to react to the temperature changes. In our 150 * case, that is not really a problem as we are polling the 151 * temperature. 152 * 153 * [0:4] : lag register 154 * 155 * The temperature is coded in steps, cf. HI6220_TEMP_STEP. 156 * 157 * Min : 0x00 : 0.0 °C 158 * Max : 0x1F : 24.3 °C 159 * 160 * The 'value' parameter is in milliCelsius. 161 */ 162 static inline void hi6220_thermal_set_lag(void __iomem *addr, int value) 163 { 164 writel(DIV_ROUND_UP(value, HI6220_TEMP_STEP) & 0x1F, 165 addr + HI6220_TEMP0_LAG); 166 } 167 168 static inline void hi6220_thermal_alarm_clear(void __iomem *addr, int value) 169 { 170 writel(value, addr + HI6220_TEMP0_INT_CLR); 171 } 172 173 static inline void hi6220_thermal_alarm_enable(void __iomem *addr, int value) 174 { 175 writel(value, addr + HI6220_TEMP0_INT_EN); 176 } 177 178 static inline void hi6220_thermal_alarm_set(void __iomem *addr, int temp) 179 { 180 writel(hi6220_thermal_temp_to_step(temp) | 0x0FFFFFF00, 181 addr + HI6220_TEMP0_TH); 182 } 183 184 static inline void hi6220_thermal_reset_set(void __iomem *addr, int temp) 185 { 186 writel(hi6220_thermal_temp_to_step(temp), addr + HI6220_TEMP0_RST_TH); 187 } 188 189 static inline void hi6220_thermal_reset_enable(void __iomem *addr, int value) 190 { 191 writel(value, addr + HI6220_TEMP0_RST_MSK); 192 } 193 194 static inline void hi6220_thermal_enable(void __iomem *addr, int value) 195 { 196 writel(value, addr + HI6220_TEMP0_EN); 197 } 198 199 static inline int hi6220_thermal_get_temperature(void __iomem *addr) 200 { 201 return hi6220_thermal_step_to_temp(readl(addr + HI6220_TEMP0_VALUE)); 202 } 203 204 /* 205 * [0:6] lag register 206 * 207 * The temperature is coded in steps, cf. HI3660_TEMP_STEP. 208 * 209 * Min : 0x00 : 0.0 °C 210 * Max : 0x7F : 26.0 °C 211 * 212 */ 213 static inline void hi3660_thermal_set_lag(void __iomem *addr, 214 int id, int value) 215 { 216 writel(DIV_ROUND_UP(value, HI3660_TEMP_STEP) & 0x7F, 217 addr + HI3660_LAG(id)); 218 } 219 220 static inline void hi3660_thermal_alarm_clear(void __iomem *addr, 221 int id, int value) 222 { 223 writel(value, addr + HI3660_INT_CLR(id)); 224 } 225 226 static inline void hi3660_thermal_alarm_enable(void __iomem *addr, 227 int id, int value) 228 { 229 writel(value, addr + HI3660_INT_EN(id)); 230 } 231 232 static inline void hi3660_thermal_alarm_set(void __iomem *addr, 233 int id, int value) 234 { 235 writel(value, addr + HI3660_TH(id)); 236 } 237 238 static inline int hi3660_thermal_get_temperature(void __iomem *addr, int id) 239 { 240 return hi3660_thermal_step_to_temp(readl(addr + HI3660_TEMP(id))); 241 } 242 243 /* 244 * Temperature configuration register - Sensor selection 245 * 246 * Bits [19:12] 247 * 248 * 0x0: local sensor (default) 249 * 0x1: remote sensor 1 (ACPU cluster 1) 250 * 0x2: remote sensor 2 (ACPU cluster 0) 251 * 0x3: remote sensor 3 (G3D) 252 */ 253 static inline void hi6220_thermal_sensor_select(void __iomem *addr, int sensor) 254 { 255 writel((readl(addr + HI6220_TEMP0_CFG) & ~HI6220_TEMP0_CFG_SS_MSK) | 256 (sensor << 12), addr + HI6220_TEMP0_CFG); 257 } 258 259 /* 260 * Temperature configuration register - Hdak conversion polling interval 261 * 262 * Bits [5:4] 263 * 264 * 0x0 : 0.768 ms 265 * 0x1 : 6.144 ms 266 * 0x2 : 49.152 ms 267 * 0x3 : 393.216 ms 268 */ 269 static inline void hi6220_thermal_hdak_set(void __iomem *addr, int value) 270 { 271 writel((readl(addr + HI6220_TEMP0_CFG) & ~HI6220_TEMP0_CFG_HDAK_MSK) | 272 (value << 4), addr + HI6220_TEMP0_CFG); 273 } 274 275 static int hi6220_thermal_irq_handler(struct hisi_thermal_sensor *sensor) 276 { 277 struct hisi_thermal_data *data = sensor->data; 278 279 hi6220_thermal_alarm_clear(data->regs, 1); 280 return 0; 281 } 282 283 static int hi3660_thermal_irq_handler(struct hisi_thermal_sensor *sensor) 284 { 285 struct hisi_thermal_data *data = sensor->data; 286 287 hi3660_thermal_alarm_clear(data->regs, sensor->id, 1); 288 return 0; 289 } 290 291 static int hi6220_thermal_get_temp(struct hisi_thermal_sensor *sensor) 292 { 293 struct hisi_thermal_data *data = sensor->data; 294 295 return hi6220_thermal_get_temperature(data->regs); 296 } 297 298 static int hi3660_thermal_get_temp(struct hisi_thermal_sensor *sensor) 299 { 300 struct hisi_thermal_data *data = sensor->data; 301 302 return hi3660_thermal_get_temperature(data->regs, sensor->id); 303 } 304 305 static int hi6220_thermal_disable_sensor(struct hisi_thermal_sensor *sensor) 306 { 307 struct hisi_thermal_data *data = sensor->data; 308 309 /* disable sensor module */ 310 hi6220_thermal_enable(data->regs, 0); 311 hi6220_thermal_alarm_enable(data->regs, 0); 312 hi6220_thermal_reset_enable(data->regs, 0); 313 314 clk_disable_unprepare(data->clk); 315 316 return 0; 317 } 318 319 static int hi3660_thermal_disable_sensor(struct hisi_thermal_sensor *sensor) 320 { 321 struct hisi_thermal_data *data = sensor->data; 322 323 /* disable sensor module */ 324 hi3660_thermal_alarm_enable(data->regs, sensor->id, 0); 325 return 0; 326 } 327 328 static int hi6220_thermal_enable_sensor(struct hisi_thermal_sensor *sensor) 329 { 330 struct hisi_thermal_data *data = sensor->data; 331 int ret; 332 333 /* enable clock for tsensor */ 334 ret = clk_prepare_enable(data->clk); 335 if (ret) 336 return ret; 337 338 /* disable module firstly */ 339 hi6220_thermal_reset_enable(data->regs, 0); 340 hi6220_thermal_enable(data->regs, 0); 341 342 /* select sensor id */ 343 hi6220_thermal_sensor_select(data->regs, sensor->id); 344 345 /* setting the hdak time */ 346 hi6220_thermal_hdak_set(data->regs, 0); 347 348 /* setting lag value between current temp and the threshold */ 349 hi6220_thermal_set_lag(data->regs, HI6220_TEMP_LAG); 350 351 /* enable for interrupt */ 352 hi6220_thermal_alarm_set(data->regs, sensor->thres_temp); 353 354 hi6220_thermal_reset_set(data->regs, HI6220_TEMP_RESET); 355 356 /* enable module */ 357 hi6220_thermal_reset_enable(data->regs, 1); 358 hi6220_thermal_enable(data->regs, 1); 359 360 hi6220_thermal_alarm_clear(data->regs, 0); 361 hi6220_thermal_alarm_enable(data->regs, 1); 362 363 return 0; 364 } 365 366 static int hi3660_thermal_enable_sensor(struct hisi_thermal_sensor *sensor) 367 { 368 unsigned int value; 369 struct hisi_thermal_data *data = sensor->data; 370 371 /* disable interrupt */ 372 hi3660_thermal_alarm_enable(data->regs, sensor->id, 0); 373 374 /* setting lag value between current temp and the threshold */ 375 hi3660_thermal_set_lag(data->regs, sensor->id, HI3660_TEMP_LAG); 376 377 /* set interrupt threshold */ 378 value = hi3660_thermal_temp_to_step(sensor->thres_temp); 379 hi3660_thermal_alarm_set(data->regs, sensor->id, value); 380 381 /* enable interrupt */ 382 hi3660_thermal_alarm_clear(data->regs, sensor->id, 1); 383 hi3660_thermal_alarm_enable(data->regs, sensor->id, 1); 384 385 return 0; 386 } 387 388 static int hi6220_thermal_probe(struct hisi_thermal_data *data) 389 { 390 struct platform_device *pdev = data->pdev; 391 struct device *dev = &pdev->dev; 392 int ret; 393 394 data->clk = devm_clk_get(dev, "thermal_clk"); 395 if (IS_ERR(data->clk)) { 396 ret = PTR_ERR(data->clk); 397 if (ret != -EPROBE_DEFER) 398 dev_err(dev, "failed to get thermal clk: %d\n", ret); 399 return ret; 400 } 401 402 data->sensor = devm_kzalloc(dev, sizeof(*data->sensor), GFP_KERNEL); 403 if (!data->sensor) 404 return -ENOMEM; 405 406 data->sensor[0].id = HI6220_CLUSTER0_SENSOR; 407 data->sensor[0].irq_name = "tsensor_intr"; 408 data->sensor[0].data = data; 409 data->nr_sensors = 1; 410 411 return 0; 412 } 413 414 static int hi3660_thermal_probe(struct hisi_thermal_data *data) 415 { 416 struct platform_device *pdev = data->pdev; 417 struct device *dev = &pdev->dev; 418 419 data->nr_sensors = 1; 420 421 data->sensor = devm_kzalloc(dev, sizeof(*data->sensor) * 422 data->nr_sensors, GFP_KERNEL); 423 if (!data->sensor) 424 return -ENOMEM; 425 426 data->sensor[0].id = HI3660_BIG_SENSOR; 427 data->sensor[0].irq_name = "tsensor_a73"; 428 data->sensor[0].data = data; 429 430 data->sensor[1].id = HI3660_LITTLE_SENSOR; 431 data->sensor[1].irq_name = "tsensor_a53"; 432 data->sensor[1].data = data; 433 434 return 0; 435 } 436 437 static int hisi_thermal_get_temp(struct thermal_zone_device *tz, int *temp) 438 { 439 struct hisi_thermal_sensor *sensor = tz->devdata; 440 struct hisi_thermal_data *data = sensor->data; 441 442 *temp = data->ops->get_temp(sensor); 443 444 dev_dbg(&data->pdev->dev, "tzd=%p, id=%d, temp=%d, thres=%d\n", 445 sensor->tzd, sensor->id, *temp, sensor->thres_temp); 446 447 return 0; 448 } 449 450 static const struct thermal_zone_device_ops hisi_of_thermal_ops = { 451 .get_temp = hisi_thermal_get_temp, 452 }; 453 454 static irqreturn_t hisi_thermal_alarm_irq_thread(int irq, void *dev) 455 { 456 struct hisi_thermal_sensor *sensor = dev; 457 struct hisi_thermal_data *data = sensor->data; 458 int temp = 0; 459 460 data->ops->irq_handler(sensor); 461 462 temp = data->ops->get_temp(sensor); 463 464 if (temp >= sensor->thres_temp) { 465 dev_crit(&data->pdev->dev, 466 "sensor <%d> THERMAL ALARM: %d > %d\n", 467 sensor->id, temp, sensor->thres_temp); 468 469 thermal_zone_device_update(sensor->tzd, 470 THERMAL_EVENT_UNSPECIFIED); 471 472 } else { 473 dev_crit(&data->pdev->dev, 474 "sensor <%d> THERMAL ALARM stopped: %d < %d\n", 475 sensor->id, temp, sensor->thres_temp); 476 } 477 478 return IRQ_HANDLED; 479 } 480 481 static int hisi_thermal_register_sensor(struct platform_device *pdev, 482 struct hisi_thermal_sensor *sensor) 483 { 484 int ret, i; 485 struct thermal_trip trip; 486 487 sensor->tzd = devm_thermal_of_zone_register(&pdev->dev, 488 sensor->id, sensor, 489 &hisi_of_thermal_ops); 490 if (IS_ERR(sensor->tzd)) { 491 ret = PTR_ERR(sensor->tzd); 492 sensor->tzd = NULL; 493 dev_err(&pdev->dev, "failed to register sensor id %d: %d\n", 494 sensor->id, ret); 495 return ret; 496 } 497 498 for (i = 0; i < thermal_zone_get_num_trips(sensor->tzd); i++) { 499 500 thermal_zone_get_trip(sensor->tzd, i, &trip); 501 502 if (trip.type == THERMAL_TRIP_PASSIVE) { 503 sensor->thres_temp = trip.temperature; 504 break; 505 } 506 } 507 508 return 0; 509 } 510 511 static const struct hisi_thermal_ops hi6220_ops = { 512 .get_temp = hi6220_thermal_get_temp, 513 .enable_sensor = hi6220_thermal_enable_sensor, 514 .disable_sensor = hi6220_thermal_disable_sensor, 515 .irq_handler = hi6220_thermal_irq_handler, 516 .probe = hi6220_thermal_probe, 517 }; 518 519 static const struct hisi_thermal_ops hi3660_ops = { 520 .get_temp = hi3660_thermal_get_temp, 521 .enable_sensor = hi3660_thermal_enable_sensor, 522 .disable_sensor = hi3660_thermal_disable_sensor, 523 .irq_handler = hi3660_thermal_irq_handler, 524 .probe = hi3660_thermal_probe, 525 }; 526 527 static const struct of_device_id of_hisi_thermal_match[] = { 528 { 529 .compatible = "hisilicon,tsensor", 530 .data = &hi6220_ops, 531 }, 532 { 533 .compatible = "hisilicon,hi3660-tsensor", 534 .data = &hi3660_ops, 535 }, 536 { /* end */ } 537 }; 538 MODULE_DEVICE_TABLE(of, of_hisi_thermal_match); 539 540 static void hisi_thermal_toggle_sensor(struct hisi_thermal_sensor *sensor, 541 bool on) 542 { 543 struct thermal_zone_device *tzd = sensor->tzd; 544 545 if (on) 546 thermal_zone_device_enable(tzd); 547 else 548 thermal_zone_device_disable(tzd); 549 } 550 551 static int hisi_thermal_probe(struct platform_device *pdev) 552 { 553 struct hisi_thermal_data *data; 554 struct device *dev = &pdev->dev; 555 struct resource *res; 556 int i, ret; 557 558 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 559 if (!data) 560 return -ENOMEM; 561 562 data->pdev = pdev; 563 platform_set_drvdata(pdev, data); 564 data->ops = of_device_get_match_data(dev); 565 566 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 567 data->regs = devm_ioremap_resource(dev, res); 568 if (IS_ERR(data->regs)) 569 return PTR_ERR(data->regs); 570 571 ret = data->ops->probe(data); 572 if (ret) 573 return ret; 574 575 for (i = 0; i < data->nr_sensors; i++) { 576 struct hisi_thermal_sensor *sensor = &data->sensor[i]; 577 578 ret = hisi_thermal_register_sensor(pdev, sensor); 579 if (ret) { 580 dev_err(dev, "failed to register thermal sensor: %d\n", 581 ret); 582 return ret; 583 } 584 585 ret = platform_get_irq(pdev, 0); 586 if (ret < 0) 587 return ret; 588 589 ret = devm_request_threaded_irq(dev, ret, NULL, 590 hisi_thermal_alarm_irq_thread, 591 IRQF_ONESHOT, sensor->irq_name, 592 sensor); 593 if (ret < 0) { 594 dev_err(dev, "Failed to request alarm irq: %d\n", ret); 595 return ret; 596 } 597 598 ret = data->ops->enable_sensor(sensor); 599 if (ret) { 600 dev_err(dev, "Failed to setup the sensor: %d\n", ret); 601 return ret; 602 } 603 604 hisi_thermal_toggle_sensor(sensor, true); 605 } 606 607 return 0; 608 } 609 610 static int hisi_thermal_remove(struct platform_device *pdev) 611 { 612 struct hisi_thermal_data *data = platform_get_drvdata(pdev); 613 int i; 614 615 for (i = 0; i < data->nr_sensors; i++) { 616 struct hisi_thermal_sensor *sensor = &data->sensor[i]; 617 618 hisi_thermal_toggle_sensor(sensor, false); 619 data->ops->disable_sensor(sensor); 620 } 621 622 return 0; 623 } 624 625 static int hisi_thermal_suspend(struct device *dev) 626 { 627 struct hisi_thermal_data *data = dev_get_drvdata(dev); 628 int i; 629 630 for (i = 0; i < data->nr_sensors; i++) 631 data->ops->disable_sensor(&data->sensor[i]); 632 633 return 0; 634 } 635 636 static int hisi_thermal_resume(struct device *dev) 637 { 638 struct hisi_thermal_data *data = dev_get_drvdata(dev); 639 int i, ret = 0; 640 641 for (i = 0; i < data->nr_sensors; i++) 642 ret |= data->ops->enable_sensor(&data->sensor[i]); 643 644 return ret; 645 } 646 647 static DEFINE_SIMPLE_DEV_PM_OPS(hisi_thermal_pm_ops, 648 hisi_thermal_suspend, hisi_thermal_resume); 649 650 static struct platform_driver hisi_thermal_driver = { 651 .driver = { 652 .name = "hisi_thermal", 653 .pm = pm_sleep_ptr(&hisi_thermal_pm_ops), 654 .of_match_table = of_hisi_thermal_match, 655 }, 656 .probe = hisi_thermal_probe, 657 .remove = hisi_thermal_remove, 658 }; 659 660 module_platform_driver(hisi_thermal_driver); 661 662 MODULE_AUTHOR("Xinwei Kong <kong.kongxinwei@hisilicon.com>"); 663 MODULE_AUTHOR("Leo Yan <leo.yan@linaro.org>"); 664 MODULE_DESCRIPTION("HiSilicon thermal driver"); 665 MODULE_LICENSE("GPL v2"); 666