linux/drivers/thermal/hisi_thermal.c
<<
>>
Prefs
   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
  66struct hisi_thermal_data;
  67
  68struct 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
  76struct 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
  84struct 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 */
 111static inline int hi6220_thermal_step_to_temp(int step)
 112{
 113        return HI6220_TEMP_BASE + (step * HI6220_TEMP_STEP);
 114}
 115
 116static 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 */
 129static inline int hi3660_thermal_step_to_temp(int step)
 130{
 131        return HI3660_TEMP_BASE + step * HI3660_TEMP_STEP;
 132}
 133
 134static 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 */
 170static 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
 176static inline void hi6220_thermal_alarm_clear(void __iomem *addr, int value)
 177{
 178        writel(value, addr + HI6220_TEMP0_INT_CLR);
 179}
 180
 181static inline void hi6220_thermal_alarm_enable(void __iomem *addr, int value)
 182{
 183        writel(value, addr + HI6220_TEMP0_INT_EN);
 184}
 185
 186static 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
 192static 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
 197static inline void hi6220_thermal_reset_enable(void __iomem *addr, int value)
 198{
 199        writel(value, addr + HI6220_TEMP0_RST_MSK);
 200}
 201
 202static inline void hi6220_thermal_enable(void __iomem *addr, int value)
 203{
 204        writel(value, addr + HI6220_TEMP0_EN);
 205}
 206
 207static 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 */
 221static 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
 228static 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
 234static 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
 240static inline void hi3660_thermal_alarm_set(void __iomem *addr,
 241                                            int id, int value)
 242{
 243        writel(value, addr + HI3660_TH(id));
 244}
 245
 246static 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 */
 261static 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 */
 277static 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
 283static 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
 291static 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
 299static 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
 306static 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
 313static 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
 327static 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
 336static 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
 374static 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
 396static 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
 422static 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
 445static 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
 458static const struct thermal_zone_of_device_ops hisi_of_thermal_ops = {
 459        .get_temp = hisi_thermal_get_temp,
 460};
 461
 462static 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
 489static 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
 518static 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
 526static 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
 534static 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};
 545MODULE_DEVICE_TABLE(of, of_hisi_thermal_match);
 546
 547static 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
 558static 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
 617static 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#ifdef CONFIG_PM_SLEEP
 633static int hisi_thermal_suspend(struct device *dev)
 634{
 635        struct hisi_thermal_data *data = dev_get_drvdata(dev);
 636        int i;
 637
 638        for (i = 0; i < data->nr_sensors; i++)
 639                data->ops->disable_sensor(&data->sensor[i]);
 640
 641        return 0;
 642}
 643
 644static int hisi_thermal_resume(struct device *dev)
 645{
 646        struct hisi_thermal_data *data = dev_get_drvdata(dev);
 647        int i, ret = 0;
 648
 649        for (i = 0; i < data->nr_sensors; i++)
 650                ret |= data->ops->enable_sensor(&data->sensor[i]);
 651
 652        return ret;
 653}
 654#endif
 655
 656static SIMPLE_DEV_PM_OPS(hisi_thermal_pm_ops,
 657                         hisi_thermal_suspend, hisi_thermal_resume);
 658
 659static struct platform_driver hisi_thermal_driver = {
 660        .driver = {
 661                .name           = "hisi_thermal",
 662                .pm             = &hisi_thermal_pm_ops,
 663                .of_match_table = of_hisi_thermal_match,
 664        },
 665        .probe  = hisi_thermal_probe,
 666        .remove = hisi_thermal_remove,
 667};
 668
 669module_platform_driver(hisi_thermal_driver);
 670
 671MODULE_AUTHOR("Xinwei Kong <kong.kongxinwei@hisilicon.com>");
 672MODULE_AUTHOR("Leo Yan <leo.yan@linaro.org>");
 673MODULE_DESCRIPTION("HiSilicon thermal driver");
 674MODULE_LICENSE("GPL v2");
 675