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