linux/drivers/thermal/imx_thermal.c
<<
>>
Prefs
   1/*
   2 * Copyright 2013 Freescale Semiconductor, Inc.
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License version 2 as
   6 * published by the Free Software Foundation.
   7 *
   8 */
   9
  10#include <linux/clk.h>
  11#include <linux/cpu_cooling.h>
  12#include <linux/delay.h>
  13#include <linux/device.h>
  14#include <linux/init.h>
  15#include <linux/interrupt.h>
  16#include <linux/io.h>
  17#include <linux/kernel.h>
  18#include <linux/mfd/syscon.h>
  19#include <linux/module.h>
  20#include <linux/of.h>
  21#include <linux/of_device.h>
  22#include <linux/platform_device.h>
  23#include <linux/regmap.h>
  24#include <linux/slab.h>
  25#include <linux/thermal.h>
  26#include <linux/types.h>
  27
  28#define REG_SET         0x4
  29#define REG_CLR         0x8
  30#define REG_TOG         0xc
  31
  32#define MISC0                           0x0150
  33#define MISC0_REFTOP_SELBIASOFF         (1 << 3)
  34#define MISC1                           0x0160
  35#define MISC1_IRQ_TEMPHIGH              (1 << 29)
  36/* Below LOW and PANIC bits are only for TEMPMON_IMX6SX */
  37#define MISC1_IRQ_TEMPLOW               (1 << 28)
  38#define MISC1_IRQ_TEMPPANIC             (1 << 27)
  39
  40#define TEMPSENSE0                      0x0180
  41#define TEMPSENSE0_ALARM_VALUE_SHIFT    20
  42#define TEMPSENSE0_ALARM_VALUE_MASK     (0xfff << TEMPSENSE0_ALARM_VALUE_SHIFT)
  43#define TEMPSENSE0_TEMP_CNT_SHIFT       8
  44#define TEMPSENSE0_TEMP_CNT_MASK        (0xfff << TEMPSENSE0_TEMP_CNT_SHIFT)
  45#define TEMPSENSE0_FINISHED             (1 << 2)
  46#define TEMPSENSE0_MEASURE_TEMP         (1 << 1)
  47#define TEMPSENSE0_POWER_DOWN           (1 << 0)
  48
  49#define TEMPSENSE1                      0x0190
  50#define TEMPSENSE1_MEASURE_FREQ         0xffff
  51/* Below TEMPSENSE2 is only for TEMPMON_IMX6SX */
  52#define TEMPSENSE2                      0x0290
  53#define TEMPSENSE2_LOW_VALUE_SHIFT      0
  54#define TEMPSENSE2_LOW_VALUE_MASK       0xfff
  55#define TEMPSENSE2_PANIC_VALUE_SHIFT    16
  56#define TEMPSENSE2_PANIC_VALUE_MASK     0xfff0000
  57
  58#define OCOTP_MEM0                      0x0480
  59#define OCOTP_ANA1                      0x04e0
  60
  61/* The driver supports 1 passive trip point and 1 critical trip point */
  62enum imx_thermal_trip {
  63        IMX_TRIP_PASSIVE,
  64        IMX_TRIP_CRITICAL,
  65        IMX_TRIP_NUM,
  66};
  67
  68#define IMX_POLLING_DELAY               2000 /* millisecond */
  69#define IMX_PASSIVE_DELAY               1000
  70
  71#define FACTOR0                         10000000
  72#define FACTOR1                         15976
  73#define FACTOR2                         4297157
  74
  75#define TEMPMON_IMX6Q                   1
  76#define TEMPMON_IMX6SX                  2
  77
  78struct thermal_soc_data {
  79        u32 version;
  80};
  81
  82static struct thermal_soc_data thermal_imx6q_data = {
  83        .version = TEMPMON_IMX6Q,
  84};
  85
  86static struct thermal_soc_data thermal_imx6sx_data = {
  87        .version = TEMPMON_IMX6SX,
  88};
  89
  90struct imx_thermal_data {
  91        struct thermal_zone_device *tz;
  92        struct thermal_cooling_device *cdev;
  93        enum thermal_device_mode mode;
  94        struct regmap *tempmon;
  95        u32 c1, c2; /* See formula in imx_get_sensor_data() */
  96        int temp_passive;
  97        int temp_critical;
  98        int temp_max;
  99        int alarm_temp;
 100        int last_temp;
 101        bool irq_enabled;
 102        int irq;
 103        struct clk *thermal_clk;
 104        const struct thermal_soc_data *socdata;
 105        const char *temp_grade;
 106};
 107
 108static void imx_set_panic_temp(struct imx_thermal_data *data,
 109                               int panic_temp)
 110{
 111        struct regmap *map = data->tempmon;
 112        int critical_value;
 113
 114        critical_value = (data->c2 - panic_temp) / data->c1;
 115        regmap_write(map, TEMPSENSE2 + REG_CLR, TEMPSENSE2_PANIC_VALUE_MASK);
 116        regmap_write(map, TEMPSENSE2 + REG_SET, critical_value <<
 117                        TEMPSENSE2_PANIC_VALUE_SHIFT);
 118}
 119
 120static void imx_set_alarm_temp(struct imx_thermal_data *data,
 121                               int alarm_temp)
 122{
 123        struct regmap *map = data->tempmon;
 124        int alarm_value;
 125
 126        data->alarm_temp = alarm_temp;
 127        alarm_value = (data->c2 - alarm_temp) / data->c1;
 128        regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_ALARM_VALUE_MASK);
 129        regmap_write(map, TEMPSENSE0 + REG_SET, alarm_value <<
 130                        TEMPSENSE0_ALARM_VALUE_SHIFT);
 131}
 132
 133static int imx_get_temp(struct thermal_zone_device *tz, int *temp)
 134{
 135        struct imx_thermal_data *data = tz->devdata;
 136        struct regmap *map = data->tempmon;
 137        unsigned int n_meas;
 138        bool wait;
 139        u32 val;
 140
 141        if (data->mode == THERMAL_DEVICE_ENABLED) {
 142                /* Check if a measurement is currently in progress */
 143                regmap_read(map, TEMPSENSE0, &val);
 144                wait = !(val & TEMPSENSE0_FINISHED);
 145        } else {
 146                /*
 147                 * Every time we measure the temperature, we will power on the
 148                 * temperature sensor, enable measurements, take a reading,
 149                 * disable measurements, power off the temperature sensor.
 150                 */
 151                regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
 152                regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);
 153
 154                wait = true;
 155        }
 156
 157        /*
 158         * According to the temp sensor designers, it may require up to ~17us
 159         * to complete a measurement.
 160         */
 161        if (wait)
 162                usleep_range(20, 50);
 163
 164        regmap_read(map, TEMPSENSE0, &val);
 165
 166        if (data->mode != THERMAL_DEVICE_ENABLED) {
 167                regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP);
 168                regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
 169        }
 170
 171        if ((val & TEMPSENSE0_FINISHED) == 0) {
 172                dev_dbg(&tz->device, "temp measurement never finished\n");
 173                return -EAGAIN;
 174        }
 175
 176        n_meas = (val & TEMPSENSE0_TEMP_CNT_MASK) >> TEMPSENSE0_TEMP_CNT_SHIFT;
 177
 178        /* See imx_get_sensor_data() for formula derivation */
 179        *temp = data->c2 - n_meas * data->c1;
 180
 181        /* Update alarm value to next higher trip point for TEMPMON_IMX6Q */
 182        if (data->socdata->version == TEMPMON_IMX6Q) {
 183                if (data->alarm_temp == data->temp_passive &&
 184                        *temp >= data->temp_passive)
 185                        imx_set_alarm_temp(data, data->temp_critical);
 186                if (data->alarm_temp == data->temp_critical &&
 187                        *temp < data->temp_passive) {
 188                        imx_set_alarm_temp(data, data->temp_passive);
 189                        dev_dbg(&tz->device, "thermal alarm off: T < %d\n",
 190                                data->alarm_temp / 1000);
 191                }
 192        }
 193
 194        if (*temp != data->last_temp) {
 195                dev_dbg(&tz->device, "millicelsius: %d\n", *temp);
 196                data->last_temp = *temp;
 197        }
 198
 199        /* Reenable alarm IRQ if temperature below alarm temperature */
 200        if (!data->irq_enabled && *temp < data->alarm_temp) {
 201                data->irq_enabled = true;
 202                enable_irq(data->irq);
 203        }
 204
 205        return 0;
 206}
 207
 208static int imx_get_mode(struct thermal_zone_device *tz,
 209                        enum thermal_device_mode *mode)
 210{
 211        struct imx_thermal_data *data = tz->devdata;
 212
 213        *mode = data->mode;
 214
 215        return 0;
 216}
 217
 218static int imx_set_mode(struct thermal_zone_device *tz,
 219                        enum thermal_device_mode mode)
 220{
 221        struct imx_thermal_data *data = tz->devdata;
 222        struct regmap *map = data->tempmon;
 223
 224        if (mode == THERMAL_DEVICE_ENABLED) {
 225                tz->polling_delay = IMX_POLLING_DELAY;
 226                tz->passive_delay = IMX_PASSIVE_DELAY;
 227
 228                regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
 229                regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);
 230
 231                if (!data->irq_enabled) {
 232                        data->irq_enabled = true;
 233                        enable_irq(data->irq);
 234                }
 235        } else {
 236                regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP);
 237                regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
 238
 239                tz->polling_delay = 0;
 240                tz->passive_delay = 0;
 241
 242                if (data->irq_enabled) {
 243                        disable_irq(data->irq);
 244                        data->irq_enabled = false;
 245                }
 246        }
 247
 248        data->mode = mode;
 249        thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
 250
 251        return 0;
 252}
 253
 254static int imx_get_trip_type(struct thermal_zone_device *tz, int trip,
 255                             enum thermal_trip_type *type)
 256{
 257        *type = (trip == IMX_TRIP_PASSIVE) ? THERMAL_TRIP_PASSIVE :
 258                                             THERMAL_TRIP_CRITICAL;
 259        return 0;
 260}
 261
 262static int imx_get_crit_temp(struct thermal_zone_device *tz, int *temp)
 263{
 264        struct imx_thermal_data *data = tz->devdata;
 265
 266        *temp = data->temp_critical;
 267        return 0;
 268}
 269
 270static int imx_get_trip_temp(struct thermal_zone_device *tz, int trip,
 271                             int *temp)
 272{
 273        struct imx_thermal_data *data = tz->devdata;
 274
 275        *temp = (trip == IMX_TRIP_PASSIVE) ? data->temp_passive :
 276                                             data->temp_critical;
 277        return 0;
 278}
 279
 280static int imx_set_trip_temp(struct thermal_zone_device *tz, int trip,
 281                             int temp)
 282{
 283        struct imx_thermal_data *data = tz->devdata;
 284
 285        /* do not allow changing critical threshold */
 286        if (trip == IMX_TRIP_CRITICAL)
 287                return -EPERM;
 288
 289        /* do not allow passive to be set higher than critical */
 290        if (temp < 0 || temp > data->temp_critical)
 291                return -EINVAL;
 292
 293        data->temp_passive = temp;
 294
 295        imx_set_alarm_temp(data, temp);
 296
 297        return 0;
 298}
 299
 300static int imx_bind(struct thermal_zone_device *tz,
 301                    struct thermal_cooling_device *cdev)
 302{
 303        int ret;
 304
 305        ret = thermal_zone_bind_cooling_device(tz, IMX_TRIP_PASSIVE, cdev,
 306                                               THERMAL_NO_LIMIT,
 307                                               THERMAL_NO_LIMIT,
 308                                               THERMAL_WEIGHT_DEFAULT);
 309        if (ret) {
 310                dev_err(&tz->device,
 311                        "binding zone %s with cdev %s failed:%d\n",
 312                        tz->type, cdev->type, ret);
 313                return ret;
 314        }
 315
 316        return 0;
 317}
 318
 319static int imx_unbind(struct thermal_zone_device *tz,
 320                      struct thermal_cooling_device *cdev)
 321{
 322        int ret;
 323
 324        ret = thermal_zone_unbind_cooling_device(tz, IMX_TRIP_PASSIVE, cdev);
 325        if (ret) {
 326                dev_err(&tz->device,
 327                        "unbinding zone %s with cdev %s failed:%d\n",
 328                        tz->type, cdev->type, ret);
 329                return ret;
 330        }
 331
 332        return 0;
 333}
 334
 335static struct thermal_zone_device_ops imx_tz_ops = {
 336        .bind = imx_bind,
 337        .unbind = imx_unbind,
 338        .get_temp = imx_get_temp,
 339        .get_mode = imx_get_mode,
 340        .set_mode = imx_set_mode,
 341        .get_trip_type = imx_get_trip_type,
 342        .get_trip_temp = imx_get_trip_temp,
 343        .get_crit_temp = imx_get_crit_temp,
 344        .set_trip_temp = imx_set_trip_temp,
 345};
 346
 347static int imx_get_sensor_data(struct platform_device *pdev)
 348{
 349        struct imx_thermal_data *data = platform_get_drvdata(pdev);
 350        struct regmap *map;
 351        int t1, n1;
 352        int ret;
 353        u32 val;
 354        u64 temp64;
 355
 356        map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
 357                                              "fsl,tempmon-data");
 358        if (IS_ERR(map)) {
 359                ret = PTR_ERR(map);
 360                dev_err(&pdev->dev, "failed to get sensor regmap: %d\n", ret);
 361                return ret;
 362        }
 363
 364        ret = regmap_read(map, OCOTP_ANA1, &val);
 365        if (ret) {
 366                dev_err(&pdev->dev, "failed to read sensor data: %d\n", ret);
 367                return ret;
 368        }
 369
 370        if (val == 0 || val == ~0) {
 371                dev_err(&pdev->dev, "invalid sensor calibration data\n");
 372                return -EINVAL;
 373        }
 374
 375        /*
 376         * Sensor data layout:
 377         *   [31:20] - sensor value @ 25C
 378         * Use universal formula now and only need sensor value @ 25C
 379         * slope = 0.4297157 - (0.0015976 * 25C fuse)
 380         */
 381        n1 = val >> 20;
 382        t1 = 25; /* t1 always 25C */
 383
 384        /*
 385         * Derived from linear interpolation:
 386         * slope = 0.4297157 - (0.0015976 * 25C fuse)
 387         * slope = (FACTOR2 - FACTOR1 * n1) / FACTOR0
 388         * (Nmeas - n1) / (Tmeas - t1) = slope
 389         * We want to reduce this down to the minimum computation necessary
 390         * for each temperature read.  Also, we want Tmeas in millicelsius
 391         * and we don't want to lose precision from integer division. So...
 392         * Tmeas = (Nmeas - n1) / slope + t1
 393         * milli_Tmeas = 1000 * (Nmeas - n1) / slope + 1000 * t1
 394         * milli_Tmeas = -1000 * (n1 - Nmeas) / slope + 1000 * t1
 395         * Let constant c1 = (-1000 / slope)
 396         * milli_Tmeas = (n1 - Nmeas) * c1 + 1000 * t1
 397         * Let constant c2 = n1 *c1 + 1000 * t1
 398         * milli_Tmeas = c2 - Nmeas * c1
 399         */
 400        temp64 = FACTOR0;
 401        temp64 *= 1000;
 402        do_div(temp64, FACTOR1 * n1 - FACTOR2);
 403        data->c1 = temp64;
 404        data->c2 = n1 * data->c1 + 1000 * t1;
 405
 406        /* use OTP for thermal grade */
 407        ret = regmap_read(map, OCOTP_MEM0, &val);
 408        if (ret) {
 409                dev_err(&pdev->dev, "failed to read temp grade: %d\n", ret);
 410                return ret;
 411        }
 412
 413        /* The maximum die temp is specified by the Temperature Grade */
 414        switch ((val >> 6) & 0x3) {
 415        case 0: /* Commercial (0 to 95C) */
 416                data->temp_grade = "Commercial";
 417                data->temp_max = 95000;
 418                break;
 419        case 1: /* Extended Commercial (-20 to 105C) */
 420                data->temp_grade = "Extended Commercial";
 421                data->temp_max = 105000;
 422                break;
 423        case 2: /* Industrial (-40 to 105C) */
 424                data->temp_grade = "Industrial";
 425                data->temp_max = 105000;
 426                break;
 427        case 3: /* Automotive (-40 to 125C) */
 428                data->temp_grade = "Automotive";
 429                data->temp_max = 125000;
 430                break;
 431        }
 432
 433        /*
 434         * Set the critical trip point at 5C under max
 435         * Set the passive trip point at 10C under max (can change via sysfs)
 436         */
 437        data->temp_critical = data->temp_max - (1000 * 5);
 438        data->temp_passive = data->temp_max - (1000 * 10);
 439
 440        return 0;
 441}
 442
 443static irqreturn_t imx_thermal_alarm_irq(int irq, void *dev)
 444{
 445        struct imx_thermal_data *data = dev;
 446
 447        disable_irq_nosync(irq);
 448        data->irq_enabled = false;
 449
 450        return IRQ_WAKE_THREAD;
 451}
 452
 453static irqreturn_t imx_thermal_alarm_irq_thread(int irq, void *dev)
 454{
 455        struct imx_thermal_data *data = dev;
 456
 457        dev_dbg(&data->tz->device, "THERMAL ALARM: T > %d\n",
 458                data->alarm_temp / 1000);
 459
 460        thermal_zone_device_update(data->tz, THERMAL_EVENT_UNSPECIFIED);
 461
 462        return IRQ_HANDLED;
 463}
 464
 465static const struct of_device_id of_imx_thermal_match[] = {
 466        { .compatible = "fsl,imx6q-tempmon", .data = &thermal_imx6q_data, },
 467        { .compatible = "fsl,imx6sx-tempmon", .data = &thermal_imx6sx_data, },
 468        { /* end */ }
 469};
 470MODULE_DEVICE_TABLE(of, of_imx_thermal_match);
 471
 472static int imx_thermal_probe(struct platform_device *pdev)
 473{
 474        struct imx_thermal_data *data;
 475        struct regmap *map;
 476        int measure_freq;
 477        int ret;
 478
 479        data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
 480        if (!data)
 481                return -ENOMEM;
 482
 483        map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "fsl,tempmon");
 484        if (IS_ERR(map)) {
 485                ret = PTR_ERR(map);
 486                dev_err(&pdev->dev, "failed to get tempmon regmap: %d\n", ret);
 487                return ret;
 488        }
 489        data->tempmon = map;
 490
 491        data->socdata = of_device_get_match_data(&pdev->dev);
 492
 493        /* make sure the IRQ flag is clear before enabling irq on i.MX6SX */
 494        if (data->socdata->version == TEMPMON_IMX6SX) {
 495                regmap_write(map, MISC1 + REG_CLR, MISC1_IRQ_TEMPHIGH |
 496                        MISC1_IRQ_TEMPLOW | MISC1_IRQ_TEMPPANIC);
 497                /*
 498                 * reset value of LOW ALARM is incorrect, set it to lowest
 499                 * value to avoid false trigger of low alarm.
 500                 */
 501                regmap_write(map, TEMPSENSE2 + REG_SET,
 502                        TEMPSENSE2_LOW_VALUE_MASK);
 503        }
 504
 505        data->irq = platform_get_irq(pdev, 0);
 506        if (data->irq < 0)
 507                return data->irq;
 508
 509        platform_set_drvdata(pdev, data);
 510
 511        ret = imx_get_sensor_data(pdev);
 512        if (ret) {
 513                dev_err(&pdev->dev, "failed to get sensor data\n");
 514                return ret;
 515        }
 516
 517        /* Make sure sensor is in known good state for measurements */
 518        regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
 519        regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP);
 520        regmap_write(map, TEMPSENSE1 + REG_CLR, TEMPSENSE1_MEASURE_FREQ);
 521        regmap_write(map, MISC0 + REG_SET, MISC0_REFTOP_SELBIASOFF);
 522        regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
 523
 524        data->cdev = cpufreq_cooling_register(cpu_present_mask);
 525        if (IS_ERR(data->cdev)) {
 526                ret = PTR_ERR(data->cdev);
 527                if (ret != -EPROBE_DEFER)
 528                        dev_err(&pdev->dev,
 529                                "failed to register cpufreq cooling device: %d\n",
 530                                ret);
 531                return ret;
 532        }
 533
 534        data->thermal_clk = devm_clk_get(&pdev->dev, NULL);
 535        if (IS_ERR(data->thermal_clk)) {
 536                ret = PTR_ERR(data->thermal_clk);
 537                if (ret != -EPROBE_DEFER)
 538                        dev_err(&pdev->dev,
 539                                "failed to get thermal clk: %d\n", ret);
 540                cpufreq_cooling_unregister(data->cdev);
 541                return ret;
 542        }
 543
 544        /*
 545         * Thermal sensor needs clk on to get correct value, normally
 546         * we should enable its clk before taking measurement and disable
 547         * clk after measurement is done, but if alarm function is enabled,
 548         * hardware will auto measure the temperature periodically, so we
 549         * need to keep the clk always on for alarm function.
 550         */
 551        ret = clk_prepare_enable(data->thermal_clk);
 552        if (ret) {
 553                dev_err(&pdev->dev, "failed to enable thermal clk: %d\n", ret);
 554                cpufreq_cooling_unregister(data->cdev);
 555                return ret;
 556        }
 557
 558        data->tz = thermal_zone_device_register("imx_thermal_zone",
 559                                                IMX_TRIP_NUM,
 560                                                BIT(IMX_TRIP_PASSIVE), data,
 561                                                &imx_tz_ops, NULL,
 562                                                IMX_PASSIVE_DELAY,
 563                                                IMX_POLLING_DELAY);
 564        if (IS_ERR(data->tz)) {
 565                ret = PTR_ERR(data->tz);
 566                dev_err(&pdev->dev,
 567                        "failed to register thermal zone device %d\n", ret);
 568                clk_disable_unprepare(data->thermal_clk);
 569                cpufreq_cooling_unregister(data->cdev);
 570                return ret;
 571        }
 572
 573        dev_info(&pdev->dev, "%s CPU temperature grade - max:%dC"
 574                 " critical:%dC passive:%dC\n", data->temp_grade,
 575                 data->temp_max / 1000, data->temp_critical / 1000,
 576                 data->temp_passive / 1000);
 577
 578        /* Enable measurements at ~ 10 Hz */
 579        regmap_write(map, TEMPSENSE1 + REG_CLR, TEMPSENSE1_MEASURE_FREQ);
 580        measure_freq = DIV_ROUND_UP(32768, 10); /* 10 Hz */
 581        regmap_write(map, TEMPSENSE1 + REG_SET, measure_freq);
 582        imx_set_alarm_temp(data, data->temp_passive);
 583
 584        if (data->socdata->version == TEMPMON_IMX6SX)
 585                imx_set_panic_temp(data, data->temp_critical);
 586
 587        regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
 588        regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);
 589
 590        ret = devm_request_threaded_irq(&pdev->dev, data->irq,
 591                        imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread,
 592                        0, "imx_thermal", data);
 593        if (ret < 0) {
 594                dev_err(&pdev->dev, "failed to request alarm irq: %d\n", ret);
 595                clk_disable_unprepare(data->thermal_clk);
 596                thermal_zone_device_unregister(data->tz);
 597                cpufreq_cooling_unregister(data->cdev);
 598                return ret;
 599        }
 600
 601        data->irq_enabled = true;
 602        data->mode = THERMAL_DEVICE_ENABLED;
 603
 604        return 0;
 605}
 606
 607static int imx_thermal_remove(struct platform_device *pdev)
 608{
 609        struct imx_thermal_data *data = platform_get_drvdata(pdev);
 610        struct regmap *map = data->tempmon;
 611
 612        /* Disable measurements */
 613        regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
 614        if (!IS_ERR(data->thermal_clk))
 615                clk_disable_unprepare(data->thermal_clk);
 616
 617        thermal_zone_device_unregister(data->tz);
 618        cpufreq_cooling_unregister(data->cdev);
 619
 620        return 0;
 621}
 622
 623#ifdef CONFIG_PM_SLEEP
 624static int imx_thermal_suspend(struct device *dev)
 625{
 626        struct imx_thermal_data *data = dev_get_drvdata(dev);
 627        struct regmap *map = data->tempmon;
 628
 629        /*
 630         * Need to disable thermal sensor, otherwise, when thermal core
 631         * try to get temperature before thermal sensor resume, a wrong
 632         * temperature will be read as the thermal sensor is powered
 633         * down.
 634         */
 635        regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP);
 636        regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
 637        data->mode = THERMAL_DEVICE_DISABLED;
 638        clk_disable_unprepare(data->thermal_clk);
 639
 640        return 0;
 641}
 642
 643static int imx_thermal_resume(struct device *dev)
 644{
 645        struct imx_thermal_data *data = dev_get_drvdata(dev);
 646        struct regmap *map = data->tempmon;
 647
 648        clk_prepare_enable(data->thermal_clk);
 649        /* Enabled thermal sensor after resume */
 650        regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
 651        regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);
 652        data->mode = THERMAL_DEVICE_ENABLED;
 653
 654        return 0;
 655}
 656#endif
 657
 658static SIMPLE_DEV_PM_OPS(imx_thermal_pm_ops,
 659                         imx_thermal_suspend, imx_thermal_resume);
 660
 661static struct platform_driver imx_thermal = {
 662        .driver = {
 663                .name   = "imx_thermal",
 664                .pm     = &imx_thermal_pm_ops,
 665                .of_match_table = of_imx_thermal_match,
 666        },
 667        .probe          = imx_thermal_probe,
 668        .remove         = imx_thermal_remove,
 669};
 670module_platform_driver(imx_thermal);
 671
 672MODULE_AUTHOR("Freescale Semiconductor, Inc.");
 673MODULE_DESCRIPTION("Thermal driver for Freescale i.MX SoCs");
 674MODULE_LICENSE("GPL v2");
 675MODULE_ALIAS("platform:imx-thermal");
 676