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