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(void *__data, int *temp) 438 { 439 struct hisi_thermal_sensor *sensor = __data; 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_of_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 hisi_thermal_get_temp(sensor, &temp); 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 const struct thermal_trip *trip; 486 487 sensor->tzd = devm_thermal_zone_of_sensor_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 trip = of_thermal_get_trip_points(sensor->tzd); 499 500 for (i = 0; i < of_thermal_get_ntrips(sensor->tzd); i++) { 501 if (trip[i].type == THERMAL_TRIP_PASSIVE) { 502 sensor->thres_temp = trip[i].temperature; 503 break; 504 } 505 } 506 507 return 0; 508 } 509 510 static const struct hisi_thermal_ops hi6220_ops = { 511 .get_temp = hi6220_thermal_get_temp, 512 .enable_sensor = hi6220_thermal_enable_sensor, 513 .disable_sensor = hi6220_thermal_disable_sensor, 514 .irq_handler = hi6220_thermal_irq_handler, 515 .probe = hi6220_thermal_probe, 516 }; 517 518 static const struct hisi_thermal_ops hi3660_ops = { 519 .get_temp = hi3660_thermal_get_temp, 520 .enable_sensor = hi3660_thermal_enable_sensor, 521 .disable_sensor = hi3660_thermal_disable_sensor, 522 .irq_handler = hi3660_thermal_irq_handler, 523 .probe = hi3660_thermal_probe, 524 }; 525 526 static const struct of_device_id of_hisi_thermal_match[] = { 527 { 528 .compatible = "hisilicon,tsensor", 529 .data = &hi6220_ops, 530 }, 531 { 532 .compatible = "hisilicon,hi3660-tsensor", 533 .data = &hi3660_ops, 534 }, 535 { /* end */ } 536 }; 537 MODULE_DEVICE_TABLE(of, of_hisi_thermal_match); 538 539 static void hisi_thermal_toggle_sensor(struct hisi_thermal_sensor *sensor, 540 bool on) 541 { 542 struct thermal_zone_device *tzd = sensor->tzd; 543 544 if (on) 545 thermal_zone_device_enable(tzd); 546 else 547 thermal_zone_device_disable(tzd); 548 } 549 550 static int hisi_thermal_probe(struct platform_device *pdev) 551 { 552 struct hisi_thermal_data *data; 553 struct device *dev = &pdev->dev; 554 struct resource *res; 555 int i, ret; 556 557 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 558 if (!data) 559 return -ENOMEM; 560 561 data->pdev = pdev; 562 platform_set_drvdata(pdev, data); 563 data->ops = of_device_get_match_data(dev); 564 565 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 566 data->regs = devm_ioremap_resource(dev, res); 567 if (IS_ERR(data->regs)) 568 return PTR_ERR(data->regs); 569 570 ret = data->ops->probe(data); 571 if (ret) 572 return ret; 573 574 for (i = 0; i < data->nr_sensors; i++) { 575 struct hisi_thermal_sensor *sensor = &data->sensor[i]; 576 577 ret = hisi_thermal_register_sensor(pdev, sensor); 578 if (ret) { 579 dev_err(dev, "failed to register thermal sensor: %d\n", 580 ret); 581 return ret; 582 } 583 584 ret = platform_get_irq(pdev, 0); 585 if (ret < 0) 586 return ret; 587 588 ret = devm_request_threaded_irq(dev, ret, NULL, 589 hisi_thermal_alarm_irq_thread, 590 IRQF_ONESHOT, sensor->irq_name, 591 sensor); 592 if (ret < 0) { 593 dev_err(dev, "Failed to request alarm irq: %d\n", ret); 594 return ret; 595 } 596 597 ret = data->ops->enable_sensor(sensor); 598 if (ret) { 599 dev_err(dev, "Failed to setup the sensor: %d\n", ret); 600 return ret; 601 } 602 603 hisi_thermal_toggle_sensor(sensor, true); 604 } 605 606 return 0; 607 } 608 609 static int hisi_thermal_remove(struct platform_device *pdev) 610 { 611 struct hisi_thermal_data *data = platform_get_drvdata(pdev); 612 int i; 613 614 for (i = 0; i < data->nr_sensors; i++) { 615 struct hisi_thermal_sensor *sensor = &data->sensor[i]; 616 617 hisi_thermal_toggle_sensor(sensor, false); 618 data->ops->disable_sensor(sensor); 619 } 620 621 return 0; 622 } 623 624 static int hisi_thermal_suspend(struct device *dev) 625 { 626 struct hisi_thermal_data *data = dev_get_drvdata(dev); 627 int i; 628 629 for (i = 0; i < data->nr_sensors; i++) 630 data->ops->disable_sensor(&data->sensor[i]); 631 632 return 0; 633 } 634 635 static int hisi_thermal_resume(struct device *dev) 636 { 637 struct hisi_thermal_data *data = dev_get_drvdata(dev); 638 int i, ret = 0; 639 640 for (i = 0; i < data->nr_sensors; i++) 641 ret |= data->ops->enable_sensor(&data->sensor[i]); 642 643 return ret; 644 } 645 646 static DEFINE_SIMPLE_DEV_PM_OPS(hisi_thermal_pm_ops, 647 hisi_thermal_suspend, hisi_thermal_resume); 648 649 static struct platform_driver hisi_thermal_driver = { 650 .driver = { 651 .name = "hisi_thermal", 652 .pm = pm_sleep_ptr(&hisi_thermal_pm_ops), 653 .of_match_table = of_hisi_thermal_match, 654 }, 655 .probe = hisi_thermal_probe, 656 .remove = hisi_thermal_remove, 657 }; 658 659 module_platform_driver(hisi_thermal_driver); 660 661 MODULE_AUTHOR("Xinwei Kong <kong.kongxinwei@hisilicon.com>"); 662 MODULE_AUTHOR("Leo Yan <leo.yan@linaro.org>"); 663 MODULE_DESCRIPTION("HiSilicon thermal driver"); 664 MODULE_LICENSE("GPL v2"); 665