Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // Copyright 2013 Freescale Semiconductor, Inc.
0004 
0005 #include <linux/clk.h>
0006 #include <linux/cpufreq.h>
0007 #include <linux/cpu_cooling.h>
0008 #include <linux/delay.h>
0009 #include <linux/interrupt.h>
0010 #include <linux/io.h>
0011 #include <linux/mfd/syscon.h>
0012 #include <linux/module.h>
0013 #include <linux/of.h>
0014 #include <linux/of_device.h>
0015 #include <linux/regmap.h>
0016 #include <linux/thermal.h>
0017 #include <linux/nvmem-consumer.h>
0018 #include <linux/pm_runtime.h>
0019 
0020 #define REG_SET     0x4
0021 #define REG_CLR     0x8
0022 #define REG_TOG     0xc
0023 
0024 /* i.MX6 specific */
0025 #define IMX6_MISC0              0x0150
0026 #define IMX6_MISC0_REFTOP_SELBIASOFF        (1 << 3)
0027 #define IMX6_MISC1              0x0160
0028 #define IMX6_MISC1_IRQ_TEMPHIGH         (1 << 29)
0029 /* Below LOW and PANIC bits are only for TEMPMON_IMX6SX */
0030 #define IMX6_MISC1_IRQ_TEMPLOW          (1 << 28)
0031 #define IMX6_MISC1_IRQ_TEMPPANIC        (1 << 27)
0032 
0033 #define IMX6_TEMPSENSE0             0x0180
0034 #define IMX6_TEMPSENSE0_ALARM_VALUE_SHIFT   20
0035 #define IMX6_TEMPSENSE0_ALARM_VALUE_MASK    (0xfff << 20)
0036 #define IMX6_TEMPSENSE0_TEMP_CNT_SHIFT      8
0037 #define IMX6_TEMPSENSE0_TEMP_CNT_MASK       (0xfff << 8)
0038 #define IMX6_TEMPSENSE0_FINISHED        (1 << 2)
0039 #define IMX6_TEMPSENSE0_MEASURE_TEMP        (1 << 1)
0040 #define IMX6_TEMPSENSE0_POWER_DOWN      (1 << 0)
0041 
0042 #define IMX6_TEMPSENSE1             0x0190
0043 #define IMX6_TEMPSENSE1_MEASURE_FREQ        0xffff
0044 #define IMX6_TEMPSENSE1_MEASURE_FREQ_SHIFT  0
0045 
0046 #define OCOTP_MEM0          0x0480
0047 #define OCOTP_ANA1          0x04e0
0048 
0049 /* Below TEMPSENSE2 is only for TEMPMON_IMX6SX */
0050 #define IMX6_TEMPSENSE2             0x0290
0051 #define IMX6_TEMPSENSE2_LOW_VALUE_SHIFT     0
0052 #define IMX6_TEMPSENSE2_LOW_VALUE_MASK      0xfff
0053 #define IMX6_TEMPSENSE2_PANIC_VALUE_SHIFT   16
0054 #define IMX6_TEMPSENSE2_PANIC_VALUE_MASK    0xfff0000
0055 
0056 /* i.MX7 specific */
0057 #define IMX7_ANADIG_DIGPROG         0x800
0058 #define IMX7_TEMPSENSE0             0x300
0059 #define IMX7_TEMPSENSE0_PANIC_ALARM_SHIFT   18
0060 #define IMX7_TEMPSENSE0_PANIC_ALARM_MASK    (0x1ff << 18)
0061 #define IMX7_TEMPSENSE0_HIGH_ALARM_SHIFT    9
0062 #define IMX7_TEMPSENSE0_HIGH_ALARM_MASK     (0x1ff << 9)
0063 #define IMX7_TEMPSENSE0_LOW_ALARM_SHIFT     0
0064 #define IMX7_TEMPSENSE0_LOW_ALARM_MASK      0x1ff
0065 
0066 #define IMX7_TEMPSENSE1             0x310
0067 #define IMX7_TEMPSENSE1_MEASURE_FREQ_SHIFT  16
0068 #define IMX7_TEMPSENSE1_MEASURE_FREQ_MASK   (0xffff << 16)
0069 #define IMX7_TEMPSENSE1_FINISHED        (1 << 11)
0070 #define IMX7_TEMPSENSE1_MEASURE_TEMP        (1 << 10)
0071 #define IMX7_TEMPSENSE1_POWER_DOWN      (1 << 9)
0072 #define IMX7_TEMPSENSE1_TEMP_VALUE_SHIFT    0
0073 #define IMX7_TEMPSENSE1_TEMP_VALUE_MASK     0x1ff
0074 
0075 /* The driver supports 1 passive trip point and 1 critical trip point */
0076 enum imx_thermal_trip {
0077     IMX_TRIP_PASSIVE,
0078     IMX_TRIP_CRITICAL,
0079     IMX_TRIP_NUM,
0080 };
0081 
0082 #define IMX_POLLING_DELAY       2000 /* millisecond */
0083 #define IMX_PASSIVE_DELAY       1000
0084 
0085 #define TEMPMON_IMX6Q           1
0086 #define TEMPMON_IMX6SX          2
0087 #define TEMPMON_IMX7D           3
0088 
0089 struct thermal_soc_data {
0090     u32 version;
0091 
0092     u32 sensor_ctrl;
0093     u32 power_down_mask;
0094     u32 measure_temp_mask;
0095 
0096     u32 measure_freq_ctrl;
0097     u32 measure_freq_mask;
0098     u32 measure_freq_shift;
0099 
0100     u32 temp_data;
0101     u32 temp_value_mask;
0102     u32 temp_value_shift;
0103     u32 temp_valid_mask;
0104 
0105     u32 panic_alarm_ctrl;
0106     u32 panic_alarm_mask;
0107     u32 panic_alarm_shift;
0108 
0109     u32 high_alarm_ctrl;
0110     u32 high_alarm_mask;
0111     u32 high_alarm_shift;
0112 
0113     u32 low_alarm_ctrl;
0114     u32 low_alarm_mask;
0115     u32 low_alarm_shift;
0116 };
0117 
0118 static struct thermal_soc_data thermal_imx6q_data = {
0119     .version = TEMPMON_IMX6Q,
0120 
0121     .sensor_ctrl = IMX6_TEMPSENSE0,
0122     .power_down_mask = IMX6_TEMPSENSE0_POWER_DOWN,
0123     .measure_temp_mask = IMX6_TEMPSENSE0_MEASURE_TEMP,
0124 
0125     .measure_freq_ctrl = IMX6_TEMPSENSE1,
0126     .measure_freq_shift = IMX6_TEMPSENSE1_MEASURE_FREQ_SHIFT,
0127     .measure_freq_mask = IMX6_TEMPSENSE1_MEASURE_FREQ,
0128 
0129     .temp_data = IMX6_TEMPSENSE0,
0130     .temp_value_mask = IMX6_TEMPSENSE0_TEMP_CNT_MASK,
0131     .temp_value_shift = IMX6_TEMPSENSE0_TEMP_CNT_SHIFT,
0132     .temp_valid_mask = IMX6_TEMPSENSE0_FINISHED,
0133 
0134     .high_alarm_ctrl = IMX6_TEMPSENSE0,
0135     .high_alarm_mask = IMX6_TEMPSENSE0_ALARM_VALUE_MASK,
0136     .high_alarm_shift = IMX6_TEMPSENSE0_ALARM_VALUE_SHIFT,
0137 };
0138 
0139 static struct thermal_soc_data thermal_imx6sx_data = {
0140     .version = TEMPMON_IMX6SX,
0141 
0142     .sensor_ctrl = IMX6_TEMPSENSE0,
0143     .power_down_mask = IMX6_TEMPSENSE0_POWER_DOWN,
0144     .measure_temp_mask = IMX6_TEMPSENSE0_MEASURE_TEMP,
0145 
0146     .measure_freq_ctrl = IMX6_TEMPSENSE1,
0147     .measure_freq_shift = IMX6_TEMPSENSE1_MEASURE_FREQ_SHIFT,
0148     .measure_freq_mask = IMX6_TEMPSENSE1_MEASURE_FREQ,
0149 
0150     .temp_data = IMX6_TEMPSENSE0,
0151     .temp_value_mask = IMX6_TEMPSENSE0_TEMP_CNT_MASK,
0152     .temp_value_shift = IMX6_TEMPSENSE0_TEMP_CNT_SHIFT,
0153     .temp_valid_mask = IMX6_TEMPSENSE0_FINISHED,
0154 
0155     .high_alarm_ctrl = IMX6_TEMPSENSE0,
0156     .high_alarm_mask = IMX6_TEMPSENSE0_ALARM_VALUE_MASK,
0157     .high_alarm_shift = IMX6_TEMPSENSE0_ALARM_VALUE_SHIFT,
0158 
0159     .panic_alarm_ctrl = IMX6_TEMPSENSE2,
0160     .panic_alarm_mask = IMX6_TEMPSENSE2_PANIC_VALUE_MASK,
0161     .panic_alarm_shift = IMX6_TEMPSENSE2_PANIC_VALUE_SHIFT,
0162 
0163     .low_alarm_ctrl = IMX6_TEMPSENSE2,
0164     .low_alarm_mask = IMX6_TEMPSENSE2_LOW_VALUE_MASK,
0165     .low_alarm_shift = IMX6_TEMPSENSE2_LOW_VALUE_SHIFT,
0166 };
0167 
0168 static struct thermal_soc_data thermal_imx7d_data = {
0169     .version = TEMPMON_IMX7D,
0170 
0171     .sensor_ctrl = IMX7_TEMPSENSE1,
0172     .power_down_mask = IMX7_TEMPSENSE1_POWER_DOWN,
0173     .measure_temp_mask = IMX7_TEMPSENSE1_MEASURE_TEMP,
0174 
0175     .measure_freq_ctrl = IMX7_TEMPSENSE1,
0176     .measure_freq_shift = IMX7_TEMPSENSE1_MEASURE_FREQ_SHIFT,
0177     .measure_freq_mask = IMX7_TEMPSENSE1_MEASURE_FREQ_MASK,
0178 
0179     .temp_data = IMX7_TEMPSENSE1,
0180     .temp_value_mask = IMX7_TEMPSENSE1_TEMP_VALUE_MASK,
0181     .temp_value_shift = IMX7_TEMPSENSE1_TEMP_VALUE_SHIFT,
0182     .temp_valid_mask = IMX7_TEMPSENSE1_FINISHED,
0183 
0184     .panic_alarm_ctrl = IMX7_TEMPSENSE1,
0185     .panic_alarm_mask = IMX7_TEMPSENSE0_PANIC_ALARM_MASK,
0186     .panic_alarm_shift = IMX7_TEMPSENSE0_PANIC_ALARM_SHIFT,
0187 
0188     .high_alarm_ctrl = IMX7_TEMPSENSE0,
0189     .high_alarm_mask = IMX7_TEMPSENSE0_HIGH_ALARM_MASK,
0190     .high_alarm_shift = IMX7_TEMPSENSE0_HIGH_ALARM_SHIFT,
0191 
0192     .low_alarm_ctrl = IMX7_TEMPSENSE0,
0193     .low_alarm_mask = IMX7_TEMPSENSE0_LOW_ALARM_MASK,
0194     .low_alarm_shift = IMX7_TEMPSENSE0_LOW_ALARM_SHIFT,
0195 };
0196 
0197 struct imx_thermal_data {
0198     struct device *dev;
0199     struct cpufreq_policy *policy;
0200     struct thermal_zone_device *tz;
0201     struct thermal_cooling_device *cdev;
0202     struct regmap *tempmon;
0203     u32 c1, c2; /* See formula in imx_init_calib() */
0204     int temp_passive;
0205     int temp_critical;
0206     int temp_max;
0207     int alarm_temp;
0208     int last_temp;
0209     bool irq_enabled;
0210     int irq;
0211     struct clk *thermal_clk;
0212     const struct thermal_soc_data *socdata;
0213     const char *temp_grade;
0214 };
0215 
0216 static void imx_set_panic_temp(struct imx_thermal_data *data,
0217                    int panic_temp)
0218 {
0219     const struct thermal_soc_data *soc_data = data->socdata;
0220     struct regmap *map = data->tempmon;
0221     int critical_value;
0222 
0223     critical_value = (data->c2 - panic_temp) / data->c1;
0224 
0225     regmap_write(map, soc_data->panic_alarm_ctrl + REG_CLR,
0226              soc_data->panic_alarm_mask);
0227     regmap_write(map, soc_data->panic_alarm_ctrl + REG_SET,
0228              critical_value << soc_data->panic_alarm_shift);
0229 }
0230 
0231 static void imx_set_alarm_temp(struct imx_thermal_data *data,
0232                    int alarm_temp)
0233 {
0234     struct regmap *map = data->tempmon;
0235     const struct thermal_soc_data *soc_data = data->socdata;
0236     int alarm_value;
0237 
0238     data->alarm_temp = alarm_temp;
0239 
0240     if (data->socdata->version == TEMPMON_IMX7D)
0241         alarm_value = alarm_temp / 1000 + data->c1 - 25;
0242     else
0243         alarm_value = (data->c2 - alarm_temp) / data->c1;
0244 
0245     regmap_write(map, soc_data->high_alarm_ctrl + REG_CLR,
0246              soc_data->high_alarm_mask);
0247     regmap_write(map, soc_data->high_alarm_ctrl + REG_SET,
0248              alarm_value << soc_data->high_alarm_shift);
0249 }
0250 
0251 static int imx_get_temp(struct thermal_zone_device *tz, int *temp)
0252 {
0253     struct imx_thermal_data *data = tz->devdata;
0254     const struct thermal_soc_data *soc_data = data->socdata;
0255     struct regmap *map = data->tempmon;
0256     unsigned int n_meas;
0257     u32 val;
0258     int ret;
0259 
0260     ret = pm_runtime_resume_and_get(data->dev);
0261     if (ret < 0)
0262         return ret;
0263 
0264     regmap_read(map, soc_data->temp_data, &val);
0265 
0266     if ((val & soc_data->temp_valid_mask) == 0) {
0267         dev_dbg(&tz->device, "temp measurement never finished\n");
0268         return -EAGAIN;
0269     }
0270 
0271     n_meas = (val & soc_data->temp_value_mask)
0272         >> soc_data->temp_value_shift;
0273 
0274     /* See imx_init_calib() for formula derivation */
0275     if (data->socdata->version == TEMPMON_IMX7D)
0276         *temp = (n_meas - data->c1 + 25) * 1000;
0277     else
0278         *temp = data->c2 - n_meas * data->c1;
0279 
0280     /* Update alarm value to next higher trip point for TEMPMON_IMX6Q */
0281     if (data->socdata->version == TEMPMON_IMX6Q) {
0282         if (data->alarm_temp == data->temp_passive &&
0283             *temp >= data->temp_passive)
0284             imx_set_alarm_temp(data, data->temp_critical);
0285         if (data->alarm_temp == data->temp_critical &&
0286             *temp < data->temp_passive) {
0287             imx_set_alarm_temp(data, data->temp_passive);
0288             dev_dbg(&tz->device, "thermal alarm off: T < %d\n",
0289                 data->alarm_temp / 1000);
0290         }
0291     }
0292 
0293     if (*temp != data->last_temp) {
0294         dev_dbg(&tz->device, "millicelsius: %d\n", *temp);
0295         data->last_temp = *temp;
0296     }
0297 
0298     /* Reenable alarm IRQ if temperature below alarm temperature */
0299     if (!data->irq_enabled && *temp < data->alarm_temp) {
0300         data->irq_enabled = true;
0301         enable_irq(data->irq);
0302     }
0303 
0304     pm_runtime_put(data->dev);
0305 
0306     return 0;
0307 }
0308 
0309 static int imx_change_mode(struct thermal_zone_device *tz,
0310                enum thermal_device_mode mode)
0311 {
0312     struct imx_thermal_data *data = tz->devdata;
0313 
0314     if (mode == THERMAL_DEVICE_ENABLED) {
0315         pm_runtime_get(data->dev);
0316 
0317         if (!data->irq_enabled) {
0318             data->irq_enabled = true;
0319             enable_irq(data->irq);
0320         }
0321     } else {
0322         pm_runtime_put(data->dev);
0323 
0324         if (data->irq_enabled) {
0325             disable_irq(data->irq);
0326             data->irq_enabled = false;
0327         }
0328     }
0329 
0330     return 0;
0331 }
0332 
0333 static int imx_get_trip_type(struct thermal_zone_device *tz, int trip,
0334                  enum thermal_trip_type *type)
0335 {
0336     *type = (trip == IMX_TRIP_PASSIVE) ? THERMAL_TRIP_PASSIVE :
0337                          THERMAL_TRIP_CRITICAL;
0338     return 0;
0339 }
0340 
0341 static int imx_get_crit_temp(struct thermal_zone_device *tz, int *temp)
0342 {
0343     struct imx_thermal_data *data = tz->devdata;
0344 
0345     *temp = data->temp_critical;
0346     return 0;
0347 }
0348 
0349 static int imx_get_trip_temp(struct thermal_zone_device *tz, int trip,
0350                  int *temp)
0351 {
0352     struct imx_thermal_data *data = tz->devdata;
0353 
0354     *temp = (trip == IMX_TRIP_PASSIVE) ? data->temp_passive :
0355                          data->temp_critical;
0356     return 0;
0357 }
0358 
0359 static int imx_set_trip_temp(struct thermal_zone_device *tz, int trip,
0360                  int temp)
0361 {
0362     struct imx_thermal_data *data = tz->devdata;
0363     int ret;
0364 
0365     ret = pm_runtime_resume_and_get(data->dev);
0366     if (ret < 0)
0367         return ret;
0368 
0369     /* do not allow changing critical threshold */
0370     if (trip == IMX_TRIP_CRITICAL)
0371         return -EPERM;
0372 
0373     /* do not allow passive to be set higher than critical */
0374     if (temp < 0 || temp > data->temp_critical)
0375         return -EINVAL;
0376 
0377     data->temp_passive = temp;
0378 
0379     imx_set_alarm_temp(data, temp);
0380 
0381     pm_runtime_put(data->dev);
0382 
0383     return 0;
0384 }
0385 
0386 static int imx_bind(struct thermal_zone_device *tz,
0387             struct thermal_cooling_device *cdev)
0388 {
0389     int ret;
0390 
0391     ret = thermal_zone_bind_cooling_device(tz, IMX_TRIP_PASSIVE, cdev,
0392                            THERMAL_NO_LIMIT,
0393                            THERMAL_NO_LIMIT,
0394                            THERMAL_WEIGHT_DEFAULT);
0395     if (ret) {
0396         dev_err(&tz->device,
0397             "binding zone %s with cdev %s failed:%d\n",
0398             tz->type, cdev->type, ret);
0399         return ret;
0400     }
0401 
0402     return 0;
0403 }
0404 
0405 static int imx_unbind(struct thermal_zone_device *tz,
0406               struct thermal_cooling_device *cdev)
0407 {
0408     int ret;
0409 
0410     ret = thermal_zone_unbind_cooling_device(tz, IMX_TRIP_PASSIVE, cdev);
0411     if (ret) {
0412         dev_err(&tz->device,
0413             "unbinding zone %s with cdev %s failed:%d\n",
0414             tz->type, cdev->type, ret);
0415         return ret;
0416     }
0417 
0418     return 0;
0419 }
0420 
0421 static struct thermal_zone_device_ops imx_tz_ops = {
0422     .bind = imx_bind,
0423     .unbind = imx_unbind,
0424     .get_temp = imx_get_temp,
0425     .change_mode = imx_change_mode,
0426     .get_trip_type = imx_get_trip_type,
0427     .get_trip_temp = imx_get_trip_temp,
0428     .get_crit_temp = imx_get_crit_temp,
0429     .set_trip_temp = imx_set_trip_temp,
0430 };
0431 
0432 static int imx_init_calib(struct platform_device *pdev, u32 ocotp_ana1)
0433 {
0434     struct imx_thermal_data *data = platform_get_drvdata(pdev);
0435     int n1;
0436     u64 temp64;
0437 
0438     if (ocotp_ana1 == 0 || ocotp_ana1 == ~0) {
0439         dev_err(&pdev->dev, "invalid sensor calibration data\n");
0440         return -EINVAL;
0441     }
0442 
0443     /*
0444      * On i.MX7D, we only use the calibration data at 25C to get the temp,
0445      * Tmeas = ( Nmeas - n1) + 25; n1 is the fuse value for 25C.
0446      */
0447     if (data->socdata->version == TEMPMON_IMX7D) {
0448         data->c1 = (ocotp_ana1 >> 9) & 0x1ff;
0449         return 0;
0450     }
0451 
0452     /*
0453      * The sensor is calibrated at 25 °C (aka T1) and the value measured
0454      * (aka N1) at this temperature is provided in bits [31:20] in the
0455      * i.MX's OCOTP value ANA1.
0456      * To find the actual temperature T, the following formula has to be used
0457      * when reading value n from the sensor:
0458      *
0459      * T = T1 + (N - N1) / (0.4148468 - 0.0015423 * N1) °C + 3.580661 °C
0460      *   = [T1' - N1 / (0.4148468 - 0.0015423 * N1) °C] + N / (0.4148468 - 0.0015423 * N1) °C
0461      *   = [T1' + N1 / (0.0015423 * N1 - 0.4148468) °C] - N / (0.0015423 * N1 - 0.4148468) °C
0462      *   = c2 - c1 * N
0463      *
0464      * with
0465      *
0466      *  T1' = 28.580661 °C
0467      *   c1 = 1 / (0.0015423 * N1 - 0.4297157) °C
0468      *   c2 = T1' + N1 / (0.0015423 * N1 - 0.4148468) °C
0469      *      = T1' + N1 * c1
0470      */
0471     n1 = ocotp_ana1 >> 20;
0472 
0473     temp64 = 10000000; /* use 10^7 as fixed point constant for values in formula */
0474     temp64 *= 1000; /* to get result in °mC */
0475     do_div(temp64, 15423 * n1 - 4148468);
0476     data->c1 = temp64;
0477     data->c2 = n1 * data->c1 + 28581;
0478 
0479     return 0;
0480 }
0481 
0482 static void imx_init_temp_grade(struct platform_device *pdev, u32 ocotp_mem0)
0483 {
0484     struct imx_thermal_data *data = platform_get_drvdata(pdev);
0485 
0486     /* The maximum die temp is specified by the Temperature Grade */
0487     switch ((ocotp_mem0 >> 6) & 0x3) {
0488     case 0: /* Commercial (0 to 95 °C) */
0489         data->temp_grade = "Commercial";
0490         data->temp_max = 95000;
0491         break;
0492     case 1: /* Extended Commercial (-20 °C to 105 °C) */
0493         data->temp_grade = "Extended Commercial";
0494         data->temp_max = 105000;
0495         break;
0496     case 2: /* Industrial (-40 °C to 105 °C) */
0497         data->temp_grade = "Industrial";
0498         data->temp_max = 105000;
0499         break;
0500     case 3: /* Automotive (-40 °C to 125 °C) */
0501         data->temp_grade = "Automotive";
0502         data->temp_max = 125000;
0503         break;
0504     }
0505 
0506     /*
0507      * Set the critical trip point at 5 °C under max
0508      * Set the passive trip point at 10 °C under max (changeable via sysfs)
0509      */
0510     data->temp_critical = data->temp_max - (1000 * 5);
0511     data->temp_passive = data->temp_max - (1000 * 10);
0512 }
0513 
0514 static int imx_init_from_tempmon_data(struct platform_device *pdev)
0515 {
0516     struct regmap *map;
0517     int ret;
0518     u32 val;
0519 
0520     map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
0521                           "fsl,tempmon-data");
0522     if (IS_ERR(map)) {
0523         ret = PTR_ERR(map);
0524         dev_err(&pdev->dev, "failed to get sensor regmap: %d\n", ret);
0525         return ret;
0526     }
0527 
0528     ret = regmap_read(map, OCOTP_ANA1, &val);
0529     if (ret) {
0530         dev_err(&pdev->dev, "failed to read sensor data: %d\n", ret);
0531         return ret;
0532     }
0533     ret = imx_init_calib(pdev, val);
0534     if (ret)
0535         return ret;
0536 
0537     ret = regmap_read(map, OCOTP_MEM0, &val);
0538     if (ret) {
0539         dev_err(&pdev->dev, "failed to read sensor data: %d\n", ret);
0540         return ret;
0541     }
0542     imx_init_temp_grade(pdev, val);
0543 
0544     return 0;
0545 }
0546 
0547 static int imx_init_from_nvmem_cells(struct platform_device *pdev)
0548 {
0549     int ret;
0550     u32 val;
0551 
0552     ret = nvmem_cell_read_u32(&pdev->dev, "calib", &val);
0553     if (ret)
0554         return ret;
0555 
0556     ret = imx_init_calib(pdev, val);
0557     if (ret)
0558         return ret;
0559 
0560     ret = nvmem_cell_read_u32(&pdev->dev, "temp_grade", &val);
0561     if (ret)
0562         return ret;
0563     imx_init_temp_grade(pdev, val);
0564 
0565     return 0;
0566 }
0567 
0568 static irqreturn_t imx_thermal_alarm_irq(int irq, void *dev)
0569 {
0570     struct imx_thermal_data *data = dev;
0571 
0572     disable_irq_nosync(irq);
0573     data->irq_enabled = false;
0574 
0575     return IRQ_WAKE_THREAD;
0576 }
0577 
0578 static irqreturn_t imx_thermal_alarm_irq_thread(int irq, void *dev)
0579 {
0580     struct imx_thermal_data *data = dev;
0581 
0582     dev_dbg(&data->tz->device, "THERMAL ALARM: T > %d\n",
0583         data->alarm_temp / 1000);
0584 
0585     thermal_zone_device_update(data->tz, THERMAL_EVENT_UNSPECIFIED);
0586 
0587     return IRQ_HANDLED;
0588 }
0589 
0590 static const struct of_device_id of_imx_thermal_match[] = {
0591     { .compatible = "fsl,imx6q-tempmon", .data = &thermal_imx6q_data, },
0592     { .compatible = "fsl,imx6sx-tempmon", .data = &thermal_imx6sx_data, },
0593     { .compatible = "fsl,imx7d-tempmon", .data = &thermal_imx7d_data, },
0594     { /* end */ }
0595 };
0596 MODULE_DEVICE_TABLE(of, of_imx_thermal_match);
0597 
0598 #ifdef CONFIG_CPU_FREQ
0599 /*
0600  * Create cooling device in case no #cooling-cells property is available in
0601  * CPU node
0602  */
0603 static int imx_thermal_register_legacy_cooling(struct imx_thermal_data *data)
0604 {
0605     struct device_node *np;
0606     int ret = 0;
0607 
0608     data->policy = cpufreq_cpu_get(0);
0609     if (!data->policy) {
0610         pr_debug("%s: CPUFreq policy not found\n", __func__);
0611         return -EPROBE_DEFER;
0612     }
0613 
0614     np = of_get_cpu_node(data->policy->cpu, NULL);
0615 
0616     if (!np || !of_find_property(np, "#cooling-cells", NULL)) {
0617         data->cdev = cpufreq_cooling_register(data->policy);
0618         if (IS_ERR(data->cdev)) {
0619             ret = PTR_ERR(data->cdev);
0620             cpufreq_cpu_put(data->policy);
0621         }
0622     }
0623 
0624     of_node_put(np);
0625 
0626     return ret;
0627 }
0628 
0629 static void imx_thermal_unregister_legacy_cooling(struct imx_thermal_data *data)
0630 {
0631     cpufreq_cooling_unregister(data->cdev);
0632     cpufreq_cpu_put(data->policy);
0633 }
0634 
0635 #else
0636 
0637 static inline int imx_thermal_register_legacy_cooling(struct imx_thermal_data *data)
0638 {
0639     return 0;
0640 }
0641 
0642 static inline void imx_thermal_unregister_legacy_cooling(struct imx_thermal_data *data)
0643 {
0644 }
0645 #endif
0646 
0647 static int imx_thermal_probe(struct platform_device *pdev)
0648 {
0649     struct imx_thermal_data *data;
0650     struct regmap *map;
0651     int measure_freq;
0652     int ret;
0653 
0654     data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
0655     if (!data)
0656         return -ENOMEM;
0657 
0658     data->dev = &pdev->dev;
0659 
0660     map = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "fsl,tempmon");
0661     if (IS_ERR(map)) {
0662         ret = PTR_ERR(map);
0663         dev_err(&pdev->dev, "failed to get tempmon regmap: %d\n", ret);
0664         return ret;
0665     }
0666     data->tempmon = map;
0667 
0668     data->socdata = of_device_get_match_data(&pdev->dev);
0669     if (!data->socdata) {
0670         dev_err(&pdev->dev, "no device match found\n");
0671         return -ENODEV;
0672     }
0673 
0674     /* make sure the IRQ flag is clear before enabling irq on i.MX6SX */
0675     if (data->socdata->version == TEMPMON_IMX6SX) {
0676         regmap_write(map, IMX6_MISC1 + REG_CLR,
0677             IMX6_MISC1_IRQ_TEMPHIGH | IMX6_MISC1_IRQ_TEMPLOW
0678             | IMX6_MISC1_IRQ_TEMPPANIC);
0679         /*
0680          * reset value of LOW ALARM is incorrect, set it to lowest
0681          * value to avoid false trigger of low alarm.
0682          */
0683         regmap_write(map, data->socdata->low_alarm_ctrl + REG_SET,
0684                  data->socdata->low_alarm_mask);
0685     }
0686 
0687     data->irq = platform_get_irq(pdev, 0);
0688     if (data->irq < 0)
0689         return data->irq;
0690 
0691     platform_set_drvdata(pdev, data);
0692 
0693     if (of_find_property(pdev->dev.of_node, "nvmem-cells", NULL)) {
0694         ret = imx_init_from_nvmem_cells(pdev);
0695         if (ret)
0696             return dev_err_probe(&pdev->dev, ret,
0697                          "failed to init from nvmem\n");
0698     } else {
0699         ret = imx_init_from_tempmon_data(pdev);
0700         if (ret) {
0701             dev_err(&pdev->dev, "failed to init from fsl,tempmon-data\n");
0702             return ret;
0703         }
0704     }
0705 
0706     /* Make sure sensor is in known good state for measurements */
0707     regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,
0708              data->socdata->power_down_mask);
0709     regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,
0710              data->socdata->measure_temp_mask);
0711     regmap_write(map, data->socdata->measure_freq_ctrl + REG_CLR,
0712              data->socdata->measure_freq_mask);
0713     if (data->socdata->version != TEMPMON_IMX7D)
0714         regmap_write(map, IMX6_MISC0 + REG_SET,
0715             IMX6_MISC0_REFTOP_SELBIASOFF);
0716     regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
0717              data->socdata->power_down_mask);
0718 
0719     ret = imx_thermal_register_legacy_cooling(data);
0720     if (ret)
0721         return dev_err_probe(&pdev->dev, ret,
0722                      "failed to register cpufreq cooling device\n");
0723 
0724     data->thermal_clk = devm_clk_get(&pdev->dev, NULL);
0725     if (IS_ERR(data->thermal_clk)) {
0726         ret = PTR_ERR(data->thermal_clk);
0727         if (ret != -EPROBE_DEFER)
0728             dev_err(&pdev->dev,
0729                 "failed to get thermal clk: %d\n", ret);
0730         goto legacy_cleanup;
0731     }
0732 
0733     /*
0734      * Thermal sensor needs clk on to get correct value, normally
0735      * we should enable its clk before taking measurement and disable
0736      * clk after measurement is done, but if alarm function is enabled,
0737      * hardware will auto measure the temperature periodically, so we
0738      * need to keep the clk always on for alarm function.
0739      */
0740     ret = clk_prepare_enable(data->thermal_clk);
0741     if (ret) {
0742         dev_err(&pdev->dev, "failed to enable thermal clk: %d\n", ret);
0743         goto legacy_cleanup;
0744     }
0745 
0746     data->tz = thermal_zone_device_register("imx_thermal_zone",
0747                         IMX_TRIP_NUM,
0748                         BIT(IMX_TRIP_PASSIVE), data,
0749                         &imx_tz_ops, NULL,
0750                         IMX_PASSIVE_DELAY,
0751                         IMX_POLLING_DELAY);
0752     if (IS_ERR(data->tz)) {
0753         ret = PTR_ERR(data->tz);
0754         dev_err(&pdev->dev,
0755             "failed to register thermal zone device %d\n", ret);
0756         goto clk_disable;
0757     }
0758 
0759     dev_info(&pdev->dev, "%s CPU temperature grade - max:%dC"
0760          " critical:%dC passive:%dC\n", data->temp_grade,
0761          data->temp_max / 1000, data->temp_critical / 1000,
0762          data->temp_passive / 1000);
0763 
0764     /* Enable measurements at ~ 10 Hz */
0765     regmap_write(map, data->socdata->measure_freq_ctrl + REG_CLR,
0766              data->socdata->measure_freq_mask);
0767     measure_freq = DIV_ROUND_UP(32768, 10); /* 10 Hz */
0768     regmap_write(map, data->socdata->measure_freq_ctrl + REG_SET,
0769              measure_freq << data->socdata->measure_freq_shift);
0770     imx_set_alarm_temp(data, data->temp_passive);
0771 
0772     if (data->socdata->version == TEMPMON_IMX6SX)
0773         imx_set_panic_temp(data, data->temp_critical);
0774 
0775     regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,
0776              data->socdata->power_down_mask);
0777     regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
0778              data->socdata->measure_temp_mask);
0779     /* After power up, we need a delay before first access can be done. */
0780     usleep_range(20, 50);
0781 
0782     /* the core was configured and enabled just before */
0783     pm_runtime_set_active(&pdev->dev);
0784     pm_runtime_enable(data->dev);
0785 
0786     ret = pm_runtime_resume_and_get(data->dev);
0787     if (ret < 0)
0788         goto disable_runtime_pm;
0789 
0790     data->irq_enabled = true;
0791     ret = thermal_zone_device_enable(data->tz);
0792     if (ret)
0793         goto thermal_zone_unregister;
0794 
0795     ret = devm_request_threaded_irq(&pdev->dev, data->irq,
0796             imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread,
0797             0, "imx_thermal", data);
0798     if (ret < 0) {
0799         dev_err(&pdev->dev, "failed to request alarm irq: %d\n", ret);
0800         goto thermal_zone_unregister;
0801     }
0802 
0803     pm_runtime_put(data->dev);
0804 
0805     return 0;
0806 
0807 thermal_zone_unregister:
0808     thermal_zone_device_unregister(data->tz);
0809 disable_runtime_pm:
0810     pm_runtime_put_noidle(data->dev);
0811     pm_runtime_disable(data->dev);
0812 clk_disable:
0813     clk_disable_unprepare(data->thermal_clk);
0814 legacy_cleanup:
0815     imx_thermal_unregister_legacy_cooling(data);
0816 
0817     return ret;
0818 }
0819 
0820 static int imx_thermal_remove(struct platform_device *pdev)
0821 {
0822     struct imx_thermal_data *data = platform_get_drvdata(pdev);
0823 
0824     pm_runtime_put_noidle(data->dev);
0825     pm_runtime_disable(data->dev);
0826 
0827     thermal_zone_device_unregister(data->tz);
0828     imx_thermal_unregister_legacy_cooling(data);
0829 
0830     return 0;
0831 }
0832 
0833 static int __maybe_unused imx_thermal_suspend(struct device *dev)
0834 {
0835     struct imx_thermal_data *data = dev_get_drvdata(dev);
0836     int ret;
0837 
0838     /*
0839      * Need to disable thermal sensor, otherwise, when thermal core
0840      * try to get temperature before thermal sensor resume, a wrong
0841      * temperature will be read as the thermal sensor is powered
0842      * down. This is done in change_mode() operation called from
0843      * thermal_zone_device_disable()
0844      */
0845     ret = thermal_zone_device_disable(data->tz);
0846     if (ret)
0847         return ret;
0848 
0849     return pm_runtime_force_suspend(data->dev);
0850 }
0851 
0852 static int __maybe_unused imx_thermal_resume(struct device *dev)
0853 {
0854     struct imx_thermal_data *data = dev_get_drvdata(dev);
0855     int ret;
0856 
0857     ret = pm_runtime_force_resume(data->dev);
0858     if (ret)
0859         return ret;
0860     /* Enabled thermal sensor after resume */
0861     return thermal_zone_device_enable(data->tz);
0862 }
0863 
0864 static int __maybe_unused imx_thermal_runtime_suspend(struct device *dev)
0865 {
0866     struct imx_thermal_data *data = dev_get_drvdata(dev);
0867     const struct thermal_soc_data *socdata = data->socdata;
0868     struct regmap *map = data->tempmon;
0869     int ret;
0870 
0871     ret = regmap_write(map, socdata->sensor_ctrl + REG_CLR,
0872                socdata->measure_temp_mask);
0873     if (ret)
0874         return ret;
0875 
0876     ret = regmap_write(map, socdata->sensor_ctrl + REG_SET,
0877                socdata->power_down_mask);
0878     if (ret)
0879         return ret;
0880 
0881     clk_disable_unprepare(data->thermal_clk);
0882 
0883     return 0;
0884 }
0885 
0886 static int __maybe_unused imx_thermal_runtime_resume(struct device *dev)
0887 {
0888     struct imx_thermal_data *data = dev_get_drvdata(dev);
0889     const struct thermal_soc_data *socdata = data->socdata;
0890     struct regmap *map = data->tempmon;
0891     int ret;
0892 
0893     ret = clk_prepare_enable(data->thermal_clk);
0894     if (ret)
0895         return ret;
0896 
0897     ret = regmap_write(map, socdata->sensor_ctrl + REG_CLR,
0898                socdata->power_down_mask);
0899     if (ret)
0900         return ret;
0901 
0902     ret = regmap_write(map, socdata->sensor_ctrl + REG_SET,
0903                socdata->measure_temp_mask);
0904     if (ret)
0905         return ret;
0906 
0907     /*
0908      * According to the temp sensor designers, it may require up to ~17us
0909      * to complete a measurement.
0910      */
0911     usleep_range(20, 50);
0912 
0913     return 0;
0914 }
0915 
0916 static const struct dev_pm_ops imx_thermal_pm_ops = {
0917     SET_SYSTEM_SLEEP_PM_OPS(imx_thermal_suspend, imx_thermal_resume)
0918     SET_RUNTIME_PM_OPS(imx_thermal_runtime_suspend,
0919                imx_thermal_runtime_resume, NULL)
0920 };
0921 
0922 static struct platform_driver imx_thermal = {
0923     .driver = {
0924         .name   = "imx_thermal",
0925         .pm = &imx_thermal_pm_ops,
0926         .of_match_table = of_imx_thermal_match,
0927     },
0928     .probe      = imx_thermal_probe,
0929     .remove     = imx_thermal_remove,
0930 };
0931 module_platform_driver(imx_thermal);
0932 
0933 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
0934 MODULE_DESCRIPTION("Thermal driver for Freescale i.MX SoCs");
0935 MODULE_LICENSE("GPL v2");
0936 MODULE_ALIAS("platform:imx-thermal");