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