Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux...
authorZhang Rui <rui.zhang@intel.com>
Sun, 21 Dec 2014 14:49:12 +0000 (22:49 +0800)
committerZhang Rui <rui.zhang@intel.com>
Sun, 21 Dec 2014 14:49:12 +0000 (22:49 +0800)
1  2 
drivers/thermal/db8500_cpufreq_cooling.c
drivers/thermal/imx_thermal.c
drivers/thermal/samsung/exynos_tmu.c
drivers/thermal/thermal_core.c
drivers/thermal/ti-soc-thermal/ti-thermal-common.c
include/linux/thermal.h

index 000d53e934a0600b7570de851dc08510240208d1,28bbff97f3dba4e09cf8f562111c1bf573686fd8..607b62c7e6114cc005ccf597e4f0ccb804e0e99b
@@@ -18,7 -18,6 +18,6 @@@
   */
  
  #include <linux/cpu_cooling.h>
- #include <linux/cpufreq.h>
  #include <linux/err.h>
  #include <linux/module.h>
  #include <linux/of.h>
  static int db8500_cpufreq_cooling_probe(struct platform_device *pdev)
  {
        struct thermal_cooling_device *cdev;
-       struct cpumask mask_val;
-       /* make sure cpufreq driver has been initialized */
-       if (!cpufreq_frequency_get_table(0))
-               return -EPROBE_DEFER;
-       cpumask_set_cpu(0, &mask_val);
-       cdev = cpufreq_cooling_register(&mask_val);
  
+       cdev = cpufreq_cooling_register(cpu_present_mask);
        if (IS_ERR(cdev)) {
-               dev_err(&pdev->dev, "Failed to register cooling device\n");
-               return PTR_ERR(cdev);
+               int ret = PTR_ERR(cdev);
+               if (ret != -EPROBE_DEFER)
+                       dev_err(&pdev->dev,
+                               "Failed to register cooling device %d\n",
+                               ret);
+                               
+               return ret;
        }
  
        platform_set_drvdata(pdev, cdev);
@@@ -78,6 -76,7 +76,6 @@@ static const struct of_device_id db8500
  
  static struct platform_driver db8500_cpufreq_cooling_driver = {
        .driver = {
 -              .owner = THIS_MODULE,
                .name = "db8500-cpufreq-cooling",
                .of_match_table = of_match_ptr(db8500_cpufreq_cooling_match),
        },
index 88b32f942dcf72839304dc32db3c10ccf681ee73,f94062bd78ebd0a6903590828859d29fb0916ba2..c1188ac053c9650ce163a3e9e37f34a877959dc2
@@@ -9,7 -9,6 +9,6 @@@
  
  #include <linux/clk.h>
  #include <linux/cpu_cooling.h>
- #include <linux/cpufreq.h>
  #include <linux/delay.h>
  #include <linux/device.h>
  #include <linux/init.h>
@@@ -454,15 -453,10 +453,10 @@@ static int imx_thermal_probe(struct pla
        const struct of_device_id *of_id =
                of_match_device(of_imx_thermal_match, &pdev->dev);
        struct imx_thermal_data *data;
-       struct cpumask clip_cpus;
        struct regmap *map;
        int measure_freq;
        int ret;
  
-       if (!cpufreq_get_current_driver()) {
-               dev_dbg(&pdev->dev, "no cpufreq driver!");
-               return -EPROBE_DEFER;
-       }
        data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
        if (!data)
                return -ENOMEM;
        regmap_write(map, MISC0 + REG_SET, MISC0_REFTOP_SELBIASOFF);
        regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
  
-       cpumask_set_cpu(0, &clip_cpus);
-       data->cdev = cpufreq_cooling_register(&clip_cpus);
+       data->cdev = cpufreq_cooling_register(cpu_present_mask);
        if (IS_ERR(data->cdev)) {
                ret = PTR_ERR(data->cdev);
-               dev_err(&pdev->dev,
-                       "failed to register cpufreq cooling device: %d\n", ret);
+               if (ret != -EPROBE_DEFER)
+                       dev_err(&pdev->dev,
+                               "failed to register cpufreq cooling device: %d\n",
+                               ret);
                return ret;
        }
  
@@@ -637,6 -632,7 +632,6 @@@ static SIMPLE_DEV_PM_OPS(imx_thermal_pm
  static struct platform_driver imx_thermal = {
        .driver = {
                .name   = "imx_thermal",
 -              .owner  = THIS_MODULE,
                .pm     = &imx_thermal_pm_ops,
                .of_match_table = of_imx_thermal_match,
        },
index d44d91d681d4333055526c28ff461e73ed709d0c,2afca9bf40d505feaa04954d42f603cb953a5c52..d2f1e62a42328095a35efb25ca461875e9f87c9f
  
  #include "exynos_thermal_common.h"
  #include "exynos_tmu.h"
 -#include "exynos_tmu_data.h"
 +
 +/* Exynos generic registers */
 +#define EXYNOS_TMU_REG_TRIMINFO               0x0
 +#define EXYNOS_TMU_REG_CONTROL                0x20
 +#define EXYNOS_TMU_REG_STATUS         0x28
 +#define EXYNOS_TMU_REG_CURRENT_TEMP   0x40
 +#define EXYNOS_TMU_REG_INTEN          0x70
 +#define EXYNOS_TMU_REG_INTSTAT                0x74
 +#define EXYNOS_TMU_REG_INTCLEAR               0x78
 +
 +#define EXYNOS_TMU_TEMP_MASK          0xff
 +#define EXYNOS_TMU_REF_VOLTAGE_SHIFT  24
 +#define EXYNOS_TMU_REF_VOLTAGE_MASK   0x1f
 +#define EXYNOS_TMU_BUF_SLOPE_SEL_MASK 0xf
 +#define EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT        8
 +#define EXYNOS_TMU_CORE_EN_SHIFT      0
 +
 +/* Exynos3250 specific registers */
 +#define EXYNOS_TMU_TRIMINFO_CON1      0x10
 +
 +/* Exynos4210 specific registers */
 +#define EXYNOS4210_TMU_REG_THRESHOLD_TEMP     0x44
 +#define EXYNOS4210_TMU_REG_TRIG_LEVEL0        0x50
 +
 +/* Exynos5250, Exynos4412, Exynos3250 specific registers */
 +#define EXYNOS_TMU_TRIMINFO_CON2      0x14
 +#define EXYNOS_THD_TEMP_RISE          0x50
 +#define EXYNOS_THD_TEMP_FALL          0x54
 +#define EXYNOS_EMUL_CON               0x80
 +
 +#define EXYNOS_TRIMINFO_RELOAD_ENABLE 1
 +#define EXYNOS_TRIMINFO_25_SHIFT      0
 +#define EXYNOS_TRIMINFO_85_SHIFT      8
 +#define EXYNOS_TMU_TRIP_MODE_SHIFT    13
 +#define EXYNOS_TMU_TRIP_MODE_MASK     0x7
 +#define EXYNOS_TMU_THERM_TRIP_EN_SHIFT        12
 +
 +#define EXYNOS_TMU_INTEN_RISE0_SHIFT  0
 +#define EXYNOS_TMU_INTEN_RISE1_SHIFT  4
 +#define EXYNOS_TMU_INTEN_RISE2_SHIFT  8
 +#define EXYNOS_TMU_INTEN_RISE3_SHIFT  12
 +#define EXYNOS_TMU_INTEN_FALL0_SHIFT  16
 +
 +#define EXYNOS_EMUL_TIME      0x57F0
 +#define EXYNOS_EMUL_TIME_MASK 0xffff
 +#define EXYNOS_EMUL_TIME_SHIFT        16
 +#define EXYNOS_EMUL_DATA_SHIFT        8
 +#define EXYNOS_EMUL_DATA_MASK 0xFF
 +#define EXYNOS_EMUL_ENABLE    0x1
 +
 +/* Exynos5260 specific */
 +#define EXYNOS5260_TMU_REG_INTEN              0xC0
 +#define EXYNOS5260_TMU_REG_INTSTAT            0xC4
 +#define EXYNOS5260_TMU_REG_INTCLEAR           0xC8
 +#define EXYNOS5260_EMUL_CON                   0x100
 +
 +/* Exynos4412 specific */
 +#define EXYNOS4412_MUX_ADDR_VALUE          6
 +#define EXYNOS4412_MUX_ADDR_SHIFT          20
 +
 +/*exynos5440 specific registers*/
 +#define EXYNOS5440_TMU_S0_7_TRIM              0x000
 +#define EXYNOS5440_TMU_S0_7_CTRL              0x020
 +#define EXYNOS5440_TMU_S0_7_DEBUG             0x040
 +#define EXYNOS5440_TMU_S0_7_TEMP              0x0f0
 +#define EXYNOS5440_TMU_S0_7_TH0                       0x110
 +#define EXYNOS5440_TMU_S0_7_TH1                       0x130
 +#define EXYNOS5440_TMU_S0_7_TH2                       0x150
 +#define EXYNOS5440_TMU_S0_7_IRQEN             0x210
 +#define EXYNOS5440_TMU_S0_7_IRQ                       0x230
 +/* exynos5440 common registers */
 +#define EXYNOS5440_TMU_IRQ_STATUS             0x000
 +#define EXYNOS5440_TMU_PMIN                   0x004
 +
 +#define EXYNOS5440_TMU_INTEN_RISE0_SHIFT      0
 +#define EXYNOS5440_TMU_INTEN_RISE1_SHIFT      1
 +#define EXYNOS5440_TMU_INTEN_RISE2_SHIFT      2
 +#define EXYNOS5440_TMU_INTEN_RISE3_SHIFT      3
 +#define EXYNOS5440_TMU_INTEN_FALL0_SHIFT      4
 +#define EXYNOS5440_TMU_TH_RISE4_SHIFT         24
 +#define EXYNOS5440_EFUSE_SWAP_OFFSET          8
  
  /**
   * struct exynos_tmu_data : A structure to hold the private data of the TMU
   * @temp_error2: fused value of the second point trim.
   * @regulator: pointer to the TMU regulator structure.
   * @reg_conf: pointer to structure to register with core thermal.
 + * @tmu_initialize: SoC specific TMU initialization method
 + * @tmu_control: SoC specific TMU control method
 + * @tmu_read: SoC specific TMU temperature read method
 + * @tmu_set_emulation: SoC specific TMU emulation setting method
 + * @tmu_clear_irqs: SoC specific TMU interrupts clearing method
   */
  struct exynos_tmu_data {
        int id;
        u8 temp_error1, temp_error2;
        struct regulator *regulator;
        struct thermal_sensor_conf *reg_conf;
 +      int (*tmu_initialize)(struct platform_device *pdev);
 +      void (*tmu_control)(struct platform_device *pdev, bool on);
 +      int (*tmu_read)(struct exynos_tmu_data *data);
 +      void (*tmu_set_emulation)(struct exynos_tmu_data *data,
 +                                unsigned long temp);
 +      void (*tmu_clear_irqs)(struct exynos_tmu_data *data);
  };
  
  /*
@@@ -213,10 -122,83 +213,10 @@@ static int code_to_temp(struct exynos_t
        return temp;
  }
  
 -static void exynos_tmu_clear_irqs(struct exynos_tmu_data *data)
 -{
 -      const struct exynos_tmu_registers *reg = data->pdata->registers;
 -      unsigned int val_irq;
 -
 -      val_irq = readl(data->base + reg->tmu_intstat);
 -      /*
 -       * Clear the interrupts.  Please note that the documentation for
 -       * Exynos3250, Exynos4412, Exynos5250 and Exynos5260 incorrectly
 -       * states that INTCLEAR register has a different placing of bits
 -       * responsible for FALL IRQs than INTSTAT register.  Exynos5420
 -       * and Exynos5440 documentation is correct (Exynos4210 doesn't
 -       * support FALL IRQs at all).
 -       */
 -      writel(val_irq, data->base + reg->tmu_intclear);
 -}
 -
 -static int exynos_tmu_initialize(struct platform_device *pdev)
 +static void sanitize_temp_error(struct exynos_tmu_data *data, u32 trim_info)
  {
 -      struct exynos_tmu_data *data = platform_get_drvdata(pdev);
        struct exynos_tmu_platform_data *pdata = data->pdata;
 -      const struct exynos_tmu_registers *reg = pdata->registers;
 -      unsigned int status, trim_info = 0, con, ctrl;
 -      unsigned int rising_threshold = 0, falling_threshold = 0;
 -      int ret = 0, threshold_code, i;
 -
 -      mutex_lock(&data->lock);
 -      clk_enable(data->clk);
 -      if (!IS_ERR(data->clk_sec))
 -              clk_enable(data->clk_sec);
  
 -      if (TMU_SUPPORTS(pdata, READY_STATUS)) {
 -              status = readb(data->base + reg->tmu_status);
 -              if (!status) {
 -                      ret = -EBUSY;
 -                      goto out;
 -              }
 -      }
 -
 -      if (TMU_SUPPORTS(pdata, TRIM_RELOAD)) {
 -              for (i = 0; i < reg->triminfo_ctrl_count; i++) {
 -                      if (pdata->triminfo_reload[i]) {
 -                              ctrl = readl(data->base +
 -                                              reg->triminfo_ctrl[i]);
 -                              ctrl |= pdata->triminfo_reload[i];
 -                              writel(ctrl, data->base +
 -                                              reg->triminfo_ctrl[i]);
 -                      }
 -              }
 -      }
 -
 -      /* Save trimming info in order to perform calibration */
 -      if (data->soc == SOC_ARCH_EXYNOS5440) {
 -              /*
 -               * For exynos5440 soc triminfo value is swapped between TMU0 and
 -               * TMU2, so the below logic is needed.
 -               */
 -              switch (data->id) {
 -              case 0:
 -                      trim_info = readl(data->base +
 -                      EXYNOS5440_EFUSE_SWAP_OFFSET + reg->triminfo_data);
 -                      break;
 -              case 1:
 -                      trim_info = readl(data->base + reg->triminfo_data);
 -                      break;
 -              case 2:
 -                      trim_info = readl(data->base -
 -                      EXYNOS5440_EFUSE_SWAP_OFFSET + reg->triminfo_data);
 -              }
 -      } else {
 -              /* On exynos5420 the triminfo register is in the shared space */
 -              if (data->soc == SOC_ARCH_EXYNOS5420_TRIMINFO)
 -                      trim_info = readl(data->base_second +
 -                                                      reg->triminfo_data);
 -              else
 -                      trim_info = readl(data->base + reg->triminfo_data);
 -      }
        data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK;
        data->temp_error2 = ((trim_info >> EXYNOS_TRIMINFO_85_SHIFT) &
                                EXYNOS_TMU_TEMP_MASK);
                data->temp_error2 =
                        (pdata->efuse_value >> EXYNOS_TRIMINFO_85_SHIFT) &
                        EXYNOS_TMU_TEMP_MASK;
 +}
  
 -      rising_threshold = readl(data->base + reg->threshold_th0);
 +static u32 get_th_reg(struct exynos_tmu_data *data, u32 threshold, bool falling)
 +{
 +      struct exynos_tmu_platform_data *pdata = data->pdata;
 +      int i;
  
 -      if (data->soc == SOC_ARCH_EXYNOS4210) {
 -              /* Write temperature code for threshold */
 -              threshold_code = temp_to_code(data, pdata->threshold);
 -              writeb(threshold_code,
 -                      data->base + reg->threshold_temp);
 -              for (i = 0; i < pdata->non_hw_trigger_levels; i++)
 -                      writeb(pdata->trigger_levels[i], data->base +
 -                      reg->threshold_th0 + i * sizeof(reg->threshold_th0));
 +      for (i = 0; i < pdata->non_hw_trigger_levels; i++) {
 +              u8 temp = pdata->trigger_levels[i];
  
 -              exynos_tmu_clear_irqs(data);
 -      } else {
 -              /* Write temperature code for rising and falling threshold */
 -              for (i = 0; i < pdata->non_hw_trigger_levels; i++) {
 -                      threshold_code = temp_to_code(data,
 -                                              pdata->trigger_levels[i]);
 -                      rising_threshold &= ~(0xff << 8 * i);
 -                      rising_threshold |= threshold_code << 8 * i;
 -                      if (pdata->threshold_falling) {
 -                              threshold_code = temp_to_code(data,
 -                                              pdata->trigger_levels[i] -
 -                                              pdata->threshold_falling);
 -                              falling_threshold |= threshold_code << 8 * i;
 -                      }
 -              }
 +              if (falling)
 +                      temp -= pdata->threshold_falling;
 +              else
 +                      threshold &= ~(0xff << 8 * i);
  
 -              writel(rising_threshold,
 -                              data->base + reg->threshold_th0);
 -              writel(falling_threshold,
 -                              data->base + reg->threshold_th1);
 -
 -              exynos_tmu_clear_irqs(data);
 -
 -              /* if last threshold limit is also present */
 -              i = pdata->max_trigger_level - 1;
 -              if (pdata->trigger_levels[i] &&
 -                              (pdata->trigger_type[i] == HW_TRIP)) {
 -                      threshold_code = temp_to_code(data,
 -                                              pdata->trigger_levels[i]);
 -                      if (i == EXYNOS_MAX_TRIGGER_PER_REG - 1) {
 -                              /* 1-4 level to be assigned in th0 reg */
 -                              rising_threshold &= ~(0xff << 8 * i);
 -                              rising_threshold |= threshold_code << 8 * i;
 -                              writel(rising_threshold,
 -                                      data->base + reg->threshold_th0);
 -                      } else if (i == EXYNOS_MAX_TRIGGER_PER_REG) {
 -                              /* 5th level to be assigned in th2 reg */
 -                              rising_threshold =
 -                              threshold_code << reg->threshold_th3_l0_shift;
 -                              writel(rising_threshold,
 -                                      data->base + reg->threshold_th2);
 -                      }
 -                      con = readl(data->base + reg->tmu_ctrl);
 -                      con |= (1 << reg->therm_trip_en_shift);
 -                      writel(con, data->base + reg->tmu_ctrl);
 -              }
 +              threshold |= temp_to_code(data, temp) << 8 * i;
        }
 -      /*Clear the PMIN in the common TMU register*/
 -      if (reg->tmu_pmin && !data->id)
 -              writel(0, data->base_second + reg->tmu_pmin);
 -out:
 +
 +      return threshold;
 +}
 +
 +static int exynos_tmu_initialize(struct platform_device *pdev)
 +{
 +      struct exynos_tmu_data *data = platform_get_drvdata(pdev);
 +      int ret;
 +
 +      mutex_lock(&data->lock);
 +      clk_enable(data->clk);
 +      if (!IS_ERR(data->clk_sec))
 +              clk_enable(data->clk_sec);
 +      ret = data->tmu_initialize(pdev);
        clk_disable(data->clk);
        mutex_unlock(&data->lock);
        if (!IS_ERR(data->clk_sec))
        return ret;
  }
  
 -static void exynos_tmu_control(struct platform_device *pdev, bool on)
 +static u32 get_con_reg(struct exynos_tmu_data *data, u32 con)
  {
 -      struct exynos_tmu_data *data = platform_get_drvdata(pdev);
        struct exynos_tmu_platform_data *pdata = data->pdata;
 -      const struct exynos_tmu_registers *reg = pdata->registers;
 -      unsigned int con, interrupt_en;
  
 -      mutex_lock(&data->lock);
 -      clk_enable(data->clk);
 -
 -      con = readl(data->base + reg->tmu_ctrl);
 -
 -      if (pdata->test_mux)
 -              con |= (pdata->test_mux << reg->test_mux_addr_shift);
 +      if (data->soc == SOC_ARCH_EXYNOS4412 ||
 +          data->soc == SOC_ARCH_EXYNOS3250)
 +              con |= (EXYNOS4412_MUX_ADDR_VALUE << EXYNOS4412_MUX_ADDR_SHIFT);
  
        con &= ~(EXYNOS_TMU_REF_VOLTAGE_MASK << EXYNOS_TMU_REF_VOLTAGE_SHIFT);
        con |= pdata->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT;
        con |= (pdata->gain << EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT);
  
        if (pdata->noise_cancel_mode) {
 -              con &= ~(reg->therm_trip_mode_mask <<
 -                                      reg->therm_trip_mode_shift);
 -              con |= (pdata->noise_cancel_mode << reg->therm_trip_mode_shift);
 +              con &= ~(EXYNOS_TMU_TRIP_MODE_MASK << EXYNOS_TMU_TRIP_MODE_SHIFT);
 +              con |= (pdata->noise_cancel_mode << EXYNOS_TMU_TRIP_MODE_SHIFT);
        }
  
 -      if (on) {
 -              con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
 -              interrupt_en =
 -                      pdata->trigger_enable[3] << reg->inten_rise3_shift |
 -                      pdata->trigger_enable[2] << reg->inten_rise2_shift |
 -                      pdata->trigger_enable[1] << reg->inten_rise1_shift |
 -                      pdata->trigger_enable[0] << reg->inten_rise0_shift;
 -              if (TMU_SUPPORTS(pdata, FALLING_TRIP))
 -                      interrupt_en |=
 -                              interrupt_en << reg->inten_fall0_shift;
 -      } else {
 -              con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
 -              interrupt_en = 0; /* Disable all interrupts */
 -      }
 -      writel(interrupt_en, data->base + reg->tmu_inten);
 -      writel(con, data->base + reg->tmu_ctrl);
 +      return con;
 +}
 +
 +static void exynos_tmu_control(struct platform_device *pdev, bool on)
 +{
 +      struct exynos_tmu_data *data = platform_get_drvdata(pdev);
  
 +      mutex_lock(&data->lock);
 +      clk_enable(data->clk);
 +      data->tmu_control(pdev, on);
        clk_disable(data->clk);
        mutex_unlock(&data->lock);
  }
  
 -static int exynos_tmu_read(struct exynos_tmu_data *data)
 +static int exynos4210_tmu_initialize(struct platform_device *pdev)
  {
 +      struct exynos_tmu_data *data = platform_get_drvdata(pdev);
        struct exynos_tmu_platform_data *pdata = data->pdata;
 -      const struct exynos_tmu_registers *reg = pdata->registers;
 -      u8 temp_code;
 -      int temp;
 +      unsigned int status;
 +      int ret = 0, threshold_code, i;
  
 -      mutex_lock(&data->lock);
 -      clk_enable(data->clk);
 +      status = readb(data->base + EXYNOS_TMU_REG_STATUS);
 +      if (!status) {
 +              ret = -EBUSY;
 +              goto out;
 +      }
  
 -      temp_code = readb(data->base + reg->tmu_cur_temp);
 +      sanitize_temp_error(data, readl(data->base + EXYNOS_TMU_REG_TRIMINFO));
  
 -      if (data->soc == SOC_ARCH_EXYNOS4210)
 -              /* temp_code should range between 75 and 175 */
 -              if (temp_code < 75 || temp_code > 175) {
 -                      temp = -ENODATA;
 -                      goto out;
 +      /* Write temperature code for threshold */
 +      threshold_code = temp_to_code(data, pdata->threshold);
 +      writeb(threshold_code, data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
 +
 +      for (i = 0; i < pdata->non_hw_trigger_levels; i++)
 +              writeb(pdata->trigger_levels[i], data->base +
 +                     EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4);
 +
 +      data->tmu_clear_irqs(data);
 +out:
 +      return ret;
 +}
 +
 +static int exynos4412_tmu_initialize(struct platform_device *pdev)
 +{
 +      struct exynos_tmu_data *data = platform_get_drvdata(pdev);
 +      struct exynos_tmu_platform_data *pdata = data->pdata;
 +      unsigned int status, trim_info, con, ctrl, rising_threshold;
 +      int ret = 0, threshold_code, i;
 +
 +      status = readb(data->base + EXYNOS_TMU_REG_STATUS);
 +      if (!status) {
 +              ret = -EBUSY;
 +              goto out;
 +      }
 +
 +      if (data->soc == SOC_ARCH_EXYNOS3250 ||
 +          data->soc == SOC_ARCH_EXYNOS4412 ||
 +          data->soc == SOC_ARCH_EXYNOS5250) {
 +              if (data->soc == SOC_ARCH_EXYNOS3250) {
 +                      ctrl = readl(data->base + EXYNOS_TMU_TRIMINFO_CON1);
 +                      ctrl |= EXYNOS_TRIMINFO_RELOAD_ENABLE;
 +                      writel(ctrl, data->base + EXYNOS_TMU_TRIMINFO_CON1);
                }
 +              ctrl = readl(data->base + EXYNOS_TMU_TRIMINFO_CON2);
 +              ctrl |= EXYNOS_TRIMINFO_RELOAD_ENABLE;
 +              writel(ctrl, data->base + EXYNOS_TMU_TRIMINFO_CON2);
 +      }
  
 -      temp = code_to_temp(data, temp_code);
 +      /* On exynos5420 the triminfo register is in the shared space */
 +      if (data->soc == SOC_ARCH_EXYNOS5420_TRIMINFO)
 +              trim_info = readl(data->base_second + EXYNOS_TMU_REG_TRIMINFO);
 +      else
 +              trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
 +
 +      sanitize_temp_error(data, trim_info);
 +
 +      /* Write temperature code for rising and falling threshold */
 +      rising_threshold = readl(data->base + EXYNOS_THD_TEMP_RISE);
 +      rising_threshold = get_th_reg(data, rising_threshold, false);
 +      writel(rising_threshold, data->base + EXYNOS_THD_TEMP_RISE);
 +      writel(get_th_reg(data, 0, true), data->base + EXYNOS_THD_TEMP_FALL);
 +
 +      data->tmu_clear_irqs(data);
 +
 +      /* if last threshold limit is also present */
 +      i = pdata->max_trigger_level - 1;
 +      if (pdata->trigger_levels[i] && pdata->trigger_type[i] == HW_TRIP) {
 +              threshold_code = temp_to_code(data, pdata->trigger_levels[i]);
 +              /* 1-4 level to be assigned in th0 reg */
 +              rising_threshold &= ~(0xff << 8 * i);
 +              rising_threshold |= threshold_code << 8 * i;
 +              writel(rising_threshold, data->base + EXYNOS_THD_TEMP_RISE);
 +              con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
 +              con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT);
 +              writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
 +      }
  out:
 -      clk_disable(data->clk);
 -      mutex_unlock(&data->lock);
 +      return ret;
 +}
  
 -      return temp;
 +static int exynos5440_tmu_initialize(struct platform_device *pdev)
 +{
 +      struct exynos_tmu_data *data = platform_get_drvdata(pdev);
 +      struct exynos_tmu_platform_data *pdata = data->pdata;
 +      unsigned int trim_info = 0, con, rising_threshold;
 +      int ret = 0, threshold_code, i;
 +
 +      /*
 +       * For exynos5440 soc triminfo value is swapped between TMU0 and
 +       * TMU2, so the below logic is needed.
 +       */
 +      switch (data->id) {
 +      case 0:
 +              trim_info = readl(data->base + EXYNOS5440_EFUSE_SWAP_OFFSET +
 +                               EXYNOS5440_TMU_S0_7_TRIM);
 +              break;
 +      case 1:
 +              trim_info = readl(data->base + EXYNOS5440_TMU_S0_7_TRIM);
 +              break;
 +      case 2:
 +              trim_info = readl(data->base - EXYNOS5440_EFUSE_SWAP_OFFSET +
 +                                EXYNOS5440_TMU_S0_7_TRIM);
 +      }
 +      sanitize_temp_error(data, trim_info);
 +
 +      /* Write temperature code for rising and falling threshold */
 +      rising_threshold = readl(data->base + EXYNOS5440_TMU_S0_7_TH0);
 +      rising_threshold = get_th_reg(data, rising_threshold, false);
 +      writel(rising_threshold, data->base + EXYNOS5440_TMU_S0_7_TH0);
 +      writel(0, data->base + EXYNOS5440_TMU_S0_7_TH1);
 +
 +      data->tmu_clear_irqs(data);
 +
 +      /* if last threshold limit is also present */
 +      i = pdata->max_trigger_level - 1;
 +      if (pdata->trigger_levels[i] && pdata->trigger_type[i] == HW_TRIP) {
 +              threshold_code = temp_to_code(data, pdata->trigger_levels[i]);
 +              /* 5th level to be assigned in th2 reg */
 +              rising_threshold =
 +                      threshold_code << EXYNOS5440_TMU_TH_RISE4_SHIFT;
 +              writel(rising_threshold, data->base + EXYNOS5440_TMU_S0_7_TH2);
 +              con = readl(data->base + EXYNOS5440_TMU_S0_7_CTRL);
 +              con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT);
 +              writel(con, data->base + EXYNOS5440_TMU_S0_7_CTRL);
 +      }
 +      /* Clear the PMIN in the common TMU register */
 +      if (!data->id)
 +              writel(0, data->base_second + EXYNOS5440_TMU_PMIN);
 +      return ret;
  }
  
 -#ifdef CONFIG_THERMAL_EMULATION
 -static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
 +static void exynos4210_tmu_control(struct platform_device *pdev, bool on)
  {
 -      struct exynos_tmu_data *data = drv_data;
 +      struct exynos_tmu_data *data = platform_get_drvdata(pdev);
        struct exynos_tmu_platform_data *pdata = data->pdata;
 -      const struct exynos_tmu_registers *reg = pdata->registers;
 -      unsigned int val;
 -      int ret = -EINVAL;
 +      unsigned int con, interrupt_en;
  
 -      if (!TMU_SUPPORTS(pdata, EMULATION))
 -              goto out;
 +      con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL));
  
 -      if (temp && temp < MCELSIUS)
 -              goto out;
 +      if (on) {
 +              con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
 +              interrupt_en =
 +                      pdata->trigger_enable[3] << EXYNOS_TMU_INTEN_RISE3_SHIFT |
 +                      pdata->trigger_enable[2] << EXYNOS_TMU_INTEN_RISE2_SHIFT |
 +                      pdata->trigger_enable[1] << EXYNOS_TMU_INTEN_RISE1_SHIFT |
 +                      pdata->trigger_enable[0] << EXYNOS_TMU_INTEN_RISE0_SHIFT;
 +              if (data->soc != SOC_ARCH_EXYNOS4210)
 +                      interrupt_en |=
 +                              interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
 +      } else {
 +              con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
 +              interrupt_en = 0; /* Disable all interrupts */
 +      }
 +      writel(interrupt_en, data->base + EXYNOS_TMU_REG_INTEN);
 +      writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
 +}
 +
 +static void exynos5440_tmu_control(struct platform_device *pdev, bool on)
 +{
 +      struct exynos_tmu_data *data = platform_get_drvdata(pdev);
 +      struct exynos_tmu_platform_data *pdata = data->pdata;
 +      unsigned int con, interrupt_en;
 +
 +      con = get_con_reg(data, readl(data->base + EXYNOS5440_TMU_S0_7_CTRL));
 +
 +      if (on) {
 +              con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
 +              interrupt_en =
 +                      pdata->trigger_enable[3] << EXYNOS5440_TMU_INTEN_RISE3_SHIFT |
 +                      pdata->trigger_enable[2] << EXYNOS5440_TMU_INTEN_RISE2_SHIFT |
 +                      pdata->trigger_enable[1] << EXYNOS5440_TMU_INTEN_RISE1_SHIFT |
 +                      pdata->trigger_enable[0] << EXYNOS5440_TMU_INTEN_RISE0_SHIFT;
 +              interrupt_en |= interrupt_en << EXYNOS5440_TMU_INTEN_FALL0_SHIFT;
 +      } else {
 +              con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
 +              interrupt_en = 0; /* Disable all interrupts */
 +      }
 +      writel(interrupt_en, data->base + EXYNOS5440_TMU_S0_7_IRQEN);
 +      writel(con, data->base + EXYNOS5440_TMU_S0_7_CTRL);
 +}
 +
 +static int exynos_tmu_read(struct exynos_tmu_data *data)
 +{
 +      int ret;
  
        mutex_lock(&data->lock);
        clk_enable(data->clk);
 +      ret = data->tmu_read(data);
 +      if (ret >= 0)
 +              ret = code_to_temp(data, ret);
 +      clk_disable(data->clk);
 +      mutex_unlock(&data->lock);
  
 -      val = readl(data->base + reg->emul_con);
 +      return ret;
 +}
  
 +#ifdef CONFIG_THERMAL_EMULATION
 +static u32 get_emul_con_reg(struct exynos_tmu_data *data, unsigned int val,
 +                          unsigned long temp)
 +{
        if (temp) {
                temp /= MCELSIUS;
  
 -              if (TMU_SUPPORTS(pdata, EMUL_TIME)) {
 -                      val &= ~(EXYNOS_EMUL_TIME_MASK << reg->emul_time_shift);
 -                      val |= (EXYNOS_EMUL_TIME << reg->emul_time_shift);
 +              if (data->soc != SOC_ARCH_EXYNOS5440) {
 +                      val &= ~(EXYNOS_EMUL_TIME_MASK << EXYNOS_EMUL_TIME_SHIFT);
 +                      val |= (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT);
                }
 -              val &= ~(EXYNOS_EMUL_DATA_MASK << reg->emul_temp_shift);
 -              val |= (temp_to_code(data, temp) << reg->emul_temp_shift) |
 +              val &= ~(EXYNOS_EMUL_DATA_MASK << EXYNOS_EMUL_DATA_SHIFT);
 +              val |= (temp_to_code(data, temp) << EXYNOS_EMUL_DATA_SHIFT) |
                        EXYNOS_EMUL_ENABLE;
        } else {
                val &= ~EXYNOS_EMUL_ENABLE;
        }
  
 -      writel(val, data->base + reg->emul_con);
 +      return val;
 +}
 +
 +static void exynos4412_tmu_set_emulation(struct exynos_tmu_data *data,
 +                                       unsigned long temp)
 +{
 +      unsigned int val;
 +      u32 emul_con;
 +
 +      if (data->soc == SOC_ARCH_EXYNOS5260)
 +              emul_con = EXYNOS5260_EMUL_CON;
 +      else
 +              emul_con = EXYNOS_EMUL_CON;
 +
 +      val = readl(data->base + emul_con);
 +      val = get_emul_con_reg(data, val, temp);
 +      writel(val, data->base + emul_con);
 +}
 +
 +static void exynos5440_tmu_set_emulation(struct exynos_tmu_data *data,
 +                                       unsigned long temp)
 +{
 +      unsigned int val;
 +
 +      val = readl(data->base + EXYNOS5440_TMU_S0_7_DEBUG);
 +      val = get_emul_con_reg(data, val, temp);
 +      writel(val, data->base + EXYNOS5440_TMU_S0_7_DEBUG);
 +}
 +
 +static int exynos_tmu_set_emulation(void *drv_data, unsigned long temp)
 +{
 +      struct exynos_tmu_data *data = drv_data;
 +      int ret = -EINVAL;
 +
 +      if (data->soc == SOC_ARCH_EXYNOS4210)
 +              goto out;
  
 +      if (temp && temp < MCELSIUS)
 +              goto out;
 +
 +      mutex_lock(&data->lock);
 +      clk_enable(data->clk);
 +      data->tmu_set_emulation(data, temp);
        clk_disable(data->clk);
        mutex_unlock(&data->lock);
        return 0;
@@@ -572,41 -401,23 +572,41 @@@ out
        return ret;
  }
  #else
 +#define exynos4412_tmu_set_emulation NULL
 +#define exynos5440_tmu_set_emulation NULL
  static int exynos_tmu_set_emulation(void *drv_data,   unsigned long temp)
        { return -EINVAL; }
  #endif/*CONFIG_THERMAL_EMULATION*/
  
 +static int exynos4210_tmu_read(struct exynos_tmu_data *data)
 +{
 +      int ret = readb(data->base + EXYNOS_TMU_REG_CURRENT_TEMP);
 +
 +      /* "temp_code" should range between 75 and 175 */
 +      return (ret < 75 || ret > 175) ? -ENODATA : ret;
 +}
 +
 +static int exynos4412_tmu_read(struct exynos_tmu_data *data)
 +{
 +      return readb(data->base + EXYNOS_TMU_REG_CURRENT_TEMP);
 +}
 +
 +static int exynos5440_tmu_read(struct exynos_tmu_data *data)
 +{
 +      return readb(data->base + EXYNOS5440_TMU_S0_7_TEMP);
 +}
 +
  static void exynos_tmu_work(struct work_struct *work)
  {
        struct exynos_tmu_data *data = container_of(work,
                        struct exynos_tmu_data, irq_work);
 -      struct exynos_tmu_platform_data *pdata = data->pdata;
 -      const struct exynos_tmu_registers *reg = pdata->registers;
        unsigned int val_type;
  
        if (!IS_ERR(data->clk_sec))
                clk_enable(data->clk_sec);
        /* Find which sensor generated this interrupt */
 -      if (reg->tmu_irqstatus) {
 -              val_type = readl(data->base_second + reg->tmu_irqstatus);
 +      if (data->soc == SOC_ARCH_EXYNOS5440) {
 +              val_type = readl(data->base_second + EXYNOS5440_TMU_IRQ_STATUS);
                if (!((val_type >> data->id) & 0x1))
                        goto out;
        }
        clk_enable(data->clk);
  
        /* TODO: take action based on particular interrupt */
 -      exynos_tmu_clear_irqs(data);
 +      data->tmu_clear_irqs(data);
  
        clk_disable(data->clk);
        mutex_unlock(&data->lock);
@@@ -626,40 -437,6 +626,40 @@@ out
        enable_irq(data->irq);
  }
  
 +static void exynos4210_tmu_clear_irqs(struct exynos_tmu_data *data)
 +{
 +      unsigned int val_irq;
 +      u32 tmu_intstat, tmu_intclear;
 +
 +      if (data->soc == SOC_ARCH_EXYNOS5260) {
 +              tmu_intstat = EXYNOS5260_TMU_REG_INTSTAT;
 +              tmu_intclear = EXYNOS5260_TMU_REG_INTCLEAR;
 +      } else {
 +              tmu_intstat = EXYNOS_TMU_REG_INTSTAT;
 +              tmu_intclear = EXYNOS_TMU_REG_INTCLEAR;
 +      }
 +
 +      val_irq = readl(data->base + tmu_intstat);
 +      /*
 +       * Clear the interrupts.  Please note that the documentation for
 +       * Exynos3250, Exynos4412, Exynos5250 and Exynos5260 incorrectly
 +       * states that INTCLEAR register has a different placing of bits
 +       * responsible for FALL IRQs than INTSTAT register.  Exynos5420
 +       * and Exynos5440 documentation is correct (Exynos4210 doesn't
 +       * support FALL IRQs at all).
 +       */
 +      writel(val_irq, data->base + tmu_intclear);
 +}
 +
 +static void exynos5440_tmu_clear_irqs(struct exynos_tmu_data *data)
 +{
 +      unsigned int val_irq;
 +
 +      val_irq = readl(data->base + EXYNOS5440_TMU_S0_7_IRQ);
 +      /* clear the interrupts */
 +      writel(val_irq, data->base + EXYNOS5440_TMU_S0_7_IRQ);
 +}
 +
  static irqreturn_t exynos_tmu_irq(int irq, void *id)
  {
        struct exynos_tmu_data *data = id;
  static const struct of_device_id exynos_tmu_match[] = {
        {
                .compatible = "samsung,exynos3250-tmu",
 -              .data = (void *)EXYNOS3250_TMU_DRV_DATA,
 +              .data = &exynos3250_default_tmu_data,
        },
        {
                .compatible = "samsung,exynos4210-tmu",
 -              .data = (void *)EXYNOS4210_TMU_DRV_DATA,
 +              .data = &exynos4210_default_tmu_data,
        },
        {
                .compatible = "samsung,exynos4412-tmu",
 -              .data = (void *)EXYNOS4412_TMU_DRV_DATA,
 +              .data = &exynos4412_default_tmu_data,
        },
        {
                .compatible = "samsung,exynos5250-tmu",
 -              .data = (void *)EXYNOS5250_TMU_DRV_DATA,
 +              .data = &exynos5250_default_tmu_data,
        },
        {
                .compatible = "samsung,exynos5260-tmu",
 -              .data = (void *)EXYNOS5260_TMU_DRV_DATA,
 +              .data = &exynos5260_default_tmu_data,
        },
        {
                .compatible = "samsung,exynos5420-tmu",
 -              .data = (void *)EXYNOS5420_TMU_DRV_DATA,
 +              .data = &exynos5420_default_tmu_data,
        },
        {
                .compatible = "samsung,exynos5420-tmu-ext-triminfo",
 -              .data = (void *)EXYNOS5420_TMU_DRV_DATA,
 +              .data = &exynos5420_default_tmu_data,
        },
        {
                .compatible = "samsung,exynos5440-tmu",
 -              .data = (void *)EXYNOS5440_TMU_DRV_DATA,
 +              .data = &exynos5440_default_tmu_data,
        },
        {},
  };
@@@ -776,47 -553,12 +776,47 @@@ static int exynos_map_dt_data(struct pl
                dev_err(&pdev->dev, "No platform init data supplied.\n");
                return -ENODEV;
        }
 +
        data->pdata = pdata;
 +      data->soc = pdata->type;
 +
 +      switch (data->soc) {
 +      case SOC_ARCH_EXYNOS4210:
 +              data->tmu_initialize = exynos4210_tmu_initialize;
 +              data->tmu_control = exynos4210_tmu_control;
 +              data->tmu_read = exynos4210_tmu_read;
 +              data->tmu_clear_irqs = exynos4210_tmu_clear_irqs;
 +              break;
 +      case SOC_ARCH_EXYNOS3250:
 +      case SOC_ARCH_EXYNOS4412:
 +      case SOC_ARCH_EXYNOS5250:
 +      case SOC_ARCH_EXYNOS5260:
 +      case SOC_ARCH_EXYNOS5420:
 +      case SOC_ARCH_EXYNOS5420_TRIMINFO:
 +              data->tmu_initialize = exynos4412_tmu_initialize;
 +              data->tmu_control = exynos4210_tmu_control;
 +              data->tmu_read = exynos4412_tmu_read;
 +              data->tmu_set_emulation = exynos4412_tmu_set_emulation;
 +              data->tmu_clear_irqs = exynos4210_tmu_clear_irqs;
 +              break;
 +      case SOC_ARCH_EXYNOS5440:
 +              data->tmu_initialize = exynos5440_tmu_initialize;
 +              data->tmu_control = exynos5440_tmu_control;
 +              data->tmu_read = exynos5440_tmu_read;
 +              data->tmu_set_emulation = exynos5440_tmu_set_emulation;
 +              data->tmu_clear_irqs = exynos5440_tmu_clear_irqs;
 +              break;
 +      default:
 +              dev_err(&pdev->dev, "Platform not supported\n");
 +              return -EINVAL;
 +      }
 +
        /*
         * Check if the TMU shares some registers and then try to map the
         * memory of common registers.
         */
 -      if (!TMU_SUPPORTS(pdata, ADDRESS_MULTIPLE))
 +      if (data->soc != SOC_ARCH_EXYNOS5420_TRIMINFO &&
 +          data->soc != SOC_ARCH_EXYNOS5440)
                return 0;
  
        if (of_address_to_resource(pdev->dev.of_node, 1, &res)) {
@@@ -883,6 -625,20 +883,6 @@@ static int exynos_tmu_probe(struct plat
                goto err_clk_sec;
        }
  
 -      if (pdata->type == SOC_ARCH_EXYNOS3250 ||
 -          pdata->type == SOC_ARCH_EXYNOS4210 ||
 -          pdata->type == SOC_ARCH_EXYNOS4412 ||
 -          pdata->type == SOC_ARCH_EXYNOS5250 ||
 -          pdata->type == SOC_ARCH_EXYNOS5260 ||
 -          pdata->type == SOC_ARCH_EXYNOS5420_TRIMINFO ||
 -          pdata->type == SOC_ARCH_EXYNOS5440)
 -              data->soc = pdata->type;
 -      else {
 -              ret = -EINVAL;
 -              dev_err(&pdev->dev, "Platform not supported\n");
 -              goto err_clk;
 -      }
 -
        ret = exynos_tmu_initialize(pdev);
        if (ret) {
                dev_err(&pdev->dev, "Failed to initialize TMU\n");
        /* Register the sensor with thermal management interface */
        ret = exynos_register_thermal(sensor_conf);
        if (ret) {
-               dev_err(&pdev->dev, "Failed to register thermal interface\n");
+               if (ret != -EPROBE_DEFER)
+                       dev_err(&pdev->dev,
+                               "Failed to register thermal interface: %d\n",
+                               ret);
                goto err_clk;
        }
        data->reg_conf = sensor_conf;
@@@ -994,6 -753,7 +997,6 @@@ static SIMPLE_DEV_PM_OPS(exynos_tmu_pm
  static struct platform_driver exynos_tmu_driver = {
        .driver = {
                .name   = "exynos-tmu",
 -              .owner  = THIS_MODULE,
                .pm     = EXYNOS_TMU_PM,
                .of_match_table = exynos_tmu_match,
        },
index 84fdf0792e27cf57c979288a6a9b79543628495f,85679295bfd5043acb81e68d8cb7d6701366bdb9..87e0b0782023cb37696a92150d9f0c10bd09b198
@@@ -368,7 -368,7 +368,7 @@@ static void handle_critical_trips(struc
        tz->ops->get_trip_temp(tz, trip, &trip_temp);
  
        /* If we have not crossed the trip_temp, we do not care. */
 -      if (tz->temperature < trip_temp)
 +      if (trip_temp <= 0 || tz->temperature < trip_temp)
                return;
  
        trace_thermal_zone_trip(tz, trip, trip_type);
@@@ -757,7 -757,6 +757,7 @@@ policy_store(struct device *dev, struc
        snprintf(name, sizeof(name), "%s", buf);
  
        mutex_lock(&thermal_governor_lock);
 +      mutex_lock(&tz->lock);
  
        gov = __find_governor(strim(name));
        if (!gov)
        ret = count;
  
  exit:
 +      mutex_unlock(&tz->lock);
        mutex_unlock(&thermal_governor_lock);
        return ret;
  }
@@@ -930,7 -928,7 +930,7 @@@ int thermal_zone_bind_cooling_device(st
        struct thermal_zone_device *pos1;
        struct thermal_cooling_device *pos2;
        unsigned long max_state;
-       int result;
+       int result, ret;
  
        if (trip >= tz->trips || (trip < 0 && trip != THERMAL_TRIPS_NONE))
                return -EINVAL;
        if (tz != pos1 || cdev != pos2)
                return -EINVAL;
  
-       cdev->ops->get_max_state(cdev, &max_state);
+       ret = cdev->ops->get_max_state(cdev, &max_state);
+       if (ret)
+               return ret;
  
        /* lower default 0, upper default max_state */
        lower = lower == THERMAL_NO_LIMIT ? 0 : lower;
@@@ -1837,10 -1837,10 +1839,10 @@@ static int __init thermal_init(void
  
  exit_netlink:
        genetlink_exit();
 -unregister_governors:
 -      thermal_unregister_governors();
  unregister_class:
        class_unregister(&thermal_class);
 +unregister_governors:
 +      thermal_unregister_governors();
  error:
        idr_destroy(&thermal_tz_idr);
        idr_destroy(&thermal_cdev_idr);
index 5fd03865e396e373d20e3c8e2dd54c79a26955ee,096fb2141b2879ffa72f08387181e6ca5006aa22..3fb054a10f6a0fde450e29a98ee4cdf90e18f6c7
@@@ -28,7 -28,6 +28,6 @@@
  #include <linux/kernel.h>
  #include <linux/workqueue.h>
  #include <linux/thermal.h>
- #include <linux/cpufreq.h>
  #include <linux/cpumask.h>
  #include <linux/cpu_cooling.h>
  #include <linux/of.h>
@@@ -286,11 -285,6 +285,11 @@@ static int ti_thermal_get_crit_temp(str
        return ti_thermal_get_trip_temp(thermal, OMAP_TRIP_NUMBER - 1, temp);
  }
  
 +static const struct thermal_zone_of_device_ops ti_of_thermal_ops = {
 +      .get_temp = __ti_thermal_get_temp,
 +      .get_trend = __ti_thermal_get_trend,
 +};
 +
  static struct thermal_zone_device_ops ti_thermal_ops = {
        .get_temp = ti_thermal_get_temp,
        .get_trend = ti_thermal_get_trend,
@@@ -338,7 -332,8 +337,7 @@@ int ti_thermal_expose_sensor(struct ti_
  
        /* in case this is specified by DT */
        data->ti_thermal = thermal_zone_of_sensor_register(bgp->dev, id,
 -                                      data, __ti_thermal_get_temp,
 -                                      __ti_thermal_get_trend);
 +                                      data, &ti_of_thermal_ops);
        if (IS_ERR(data->ti_thermal)) {
                /* Create thermal zone */
                data->ti_thermal = thermal_zone_device_register(domain,
@@@ -407,17 -402,17 +406,17 @@@ int ti_thermal_register_cpu_cooling(str
        if (!data)
                return -EINVAL;
  
-       if (!cpufreq_get_current_driver()) {
-               dev_dbg(bgp->dev, "no cpufreq driver yet\n");
-               return -EPROBE_DEFER;
-       }
        /* Register cooling device */
        data->cool_dev = cpufreq_cooling_register(cpu_present_mask);
        if (IS_ERR(data->cool_dev)) {
-               dev_err(bgp->dev,
-                       "Failed to register cpufreq cooling device\n");
-               return PTR_ERR(data->cool_dev);
+               int ret = PTR_ERR(data->cool_dev);
+               if (ret != -EPROBE_DEFER)
+                       dev_err(bgp->dev,
+                               "Failed to register cpu cooling device %d\n",
+                               ret);
+               return ret;
        }
        ti_bandgap_set_sensor_data(bgp, id, data);
  
diff --combined include/linux/thermal.h
index c611a02fbc51246c9ea71e81eb9ccd6a4030d763,005586fdf82dbca1d2957601d84833b4560076e6..fc52e307efab8768effbb7880702986653e0a07c
  #include <linux/idr.h>
  #include <linux/device.h>
  #include <linux/workqueue.h>
 +#include <uapi/linux/thermal.h>
  
  #define THERMAL_TRIPS_NONE    -1
  #define THERMAL_MAX_TRIPS     12
 -#define THERMAL_NAME_LENGTH   20
  
  /* invalid cooling state */
  #define THERMAL_CSTATE_INVALID -1UL
  
  /* No upper/lower limit requirement */
- #define THERMAL_NO_LIMIT      THERMAL_CSTATE_INVALID
+ #define THERMAL_NO_LIMIT      ((u32)~0)
  
  /* Unit conversion macros */
  #define KELVIN_TO_CELSIUS(t)  (long)(((long)t-2732 >= 0) ?    \
  #define MILLICELSIUS_TO_DECI_KELVIN_WITH_OFFSET(t, off) (((t) / 100) + (off))
  #define MILLICELSIUS_TO_DECI_KELVIN(t) MILLICELSIUS_TO_DECI_KELVIN_WITH_OFFSET(t, 2732)
  
 -/* Adding event notification support elements */
 -#define THERMAL_GENL_FAMILY_NAME                "thermal_event"
 -#define THERMAL_GENL_VERSION                    0x01
 -#define THERMAL_GENL_MCAST_GROUP_NAME           "thermal_mc_grp"
 -
  /* Default Thermal Governor */
  #if defined(CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE)
  #define DEFAULT_THERMAL_GOVERNOR       "step_wise"
@@@ -81,6 -86,30 +81,6 @@@ enum thermal_trend 
        THERMAL_TREND_DROP_FULL, /* apply lowest cooling action */
  };
  
 -/* Events supported by Thermal Netlink */
 -enum events {
 -      THERMAL_AUX0,
 -      THERMAL_AUX1,
 -      THERMAL_CRITICAL,
 -      THERMAL_DEV_FAULT,
 -};
 -
 -/* attributes of thermal_genl_family */
 -enum {
 -      THERMAL_GENL_ATTR_UNSPEC,
 -      THERMAL_GENL_ATTR_EVENT,
 -      __THERMAL_GENL_ATTR_MAX,
 -};
 -#define THERMAL_GENL_ATTR_MAX (__THERMAL_GENL_ATTR_MAX - 1)
 -
 -/* commands supported by the thermal_genl_family */
 -enum {
 -      THERMAL_GENL_CMD_UNSPEC,
 -      THERMAL_GENL_CMD_EVENT,
 -      __THERMAL_GENL_CMD_MAX,
 -};
 -#define THERMAL_GENL_CMD_MAX (__THERMAL_GENL_CMD_MAX - 1)
 -
  struct thermal_zone_device_ops {
        int (*bind) (struct thermal_zone_device *,
                     struct thermal_cooling_device *);
@@@ -260,49 -289,19 +260,49 @@@ struct thermal_genl_event 
        enum events event;
  };
  
 +/**
 + * struct thermal_zone_of_device_ops - scallbacks for handling DT based zones
 + *
 + * Mandatory:
 + * @get_temp: a pointer to a function that reads the sensor temperature.
 + *
 + * Optional:
 + * @get_trend: a pointer to a function that reads the sensor temperature trend.
 + * @set_emul_temp: a pointer to a function that sets sensor emulated
 + *               temperature.
 + */
 +struct thermal_zone_of_device_ops {
 +      int (*get_temp)(void *, long *);
 +      int (*get_trend)(void *, long *);
 +      int (*set_emul_temp)(void *, unsigned long);
 +};
 +
 +/**
 + * struct thermal_trip - representation of a point in temperature domain
 + * @np: pointer to struct device_node that this trip point was created from
 + * @temperature: temperature value in miliCelsius
 + * @hysteresis: relative hysteresis in miliCelsius
 + * @type: trip point type
 + */
 +
 +struct thermal_trip {
 +      struct device_node *np;
 +      unsigned long int temperature;
 +      unsigned long int hysteresis;
 +      enum thermal_trip_type type;
 +};
 +
  /* Function declarations */
  #ifdef CONFIG_THERMAL_OF
  struct thermal_zone_device *
 -thermal_zone_of_sensor_register(struct device *dev, int id,
 -                              void *data, int (*get_temp)(void *, long *),
 -                              int (*get_trend)(void *, long *));
 +thermal_zone_of_sensor_register(struct device *dev, int id, void *data,
 +                              const struct thermal_zone_of_device_ops *ops);
  void thermal_zone_of_sensor_unregister(struct device *dev,
                                       struct thermal_zone_device *tz);
  #else
  static inline struct thermal_zone_device *
 -thermal_zone_of_sensor_register(struct device *dev, int id,
 -                              void *data, int (*get_temp)(void *, long *),
 -                              int (*get_trend)(void *, long *))
 +thermal_zone_of_sensor_register(struct device *dev, int id, void *data,
 +                              const struct thermal_zone_of_device_ops *ops)
  {
        return NULL;
  }