]> Git Repo - linux.git/commitdiff
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux
authorLinus Torvalds <[email protected]>
Fri, 26 Jun 2015 00:51:55 +0000 (17:51 -0700)
committerLinus Torvalds <[email protected]>
Fri, 26 Jun 2015 00:51:55 +0000 (17:51 -0700)
Pull thermal management updates from Zhang Rui:
 "Specifics:

   - enhance Thermal Framework with several new capabilities:

       * use power estimates
       * compute weights with relative integers instead of percentages
       * allow governors to have private data in thermal zones
       * export thermal zone parameters through sysfs

     Thanks to the ARM thermal team (Javi, Punit, KP).

   - introduce a new thermal governor: power allocator.  First in kernel
     closed loop PI(D) controller for thermal control.  Thanks to ARM
     thermal team.

   - enhance OF thermal to allow thermal zones to have sustainable power
     HW specification.  Thanks to Punit.

   - introduce thermal driver for Intel Quark SoC x1000platform.  Thanks
     to Ong, Boon Leong.

   - introduce QPNP PMIC temperature alarm driver.  Thanks to Ivan T. I.

   - introduce thermal driver for Hisilicon hi6220.  Thanks to
     kongxinwei.

   - enhance Exynos thermal driver to handle Exynos5433 TMU.  Thanks to
     Chanwoo C.

   - TI thermal driver now has a better implementation for EOCZ bit.
     From Pavel M.

   - add id for Skylake processors in int340x processor thermal driver.

   - a couple of small fixes and cleanups."

* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux: (36 commits)
  thermal: hisilicon: add new hisilicon thermal sensor driver
  dt-bindings: Document the hi6220 thermal sensor bindings
  thermal: of-thermal: add support for reading coefficients property
  thermal: support slope and offset coefficients
  thermal: power_allocator: round the division when divvying up power
  thermal: exynos: Add the support for Exynos5433 TMU
  thermal: cpu_cooling: Fix power calculation when CPUs are offline
  thermal: cpu_cooling: Remove cpu_dev update on policy CPU update
  thermal: export thermal_zone_parameters to sysfs
  thermal: cpu_cooling: Check memory allocation of power_table
  ti-soc-thermal: request temperature periodically if hw can't do that itself
  ti-soc-thermal: implement eocz bit to make driver useful on omap3
  cleanup ti-soc-thermal
  thermal: remove stale THERMAL_POWER_ACTOR select
  thermal: Default OF created trip points to writable
  thermal: core: Add Kconfig option to enable writable trips
  thermal: x86_pkg_temp: drop const for thermal_zone_parameters
  of: thermal: Introduce sustainable power for a thermal zone
  thermal: add trace events to the power allocator governor
  thermal: introduce the Power Allocator governor
  ...

1  2 
drivers/thermal/ti-soc-thermal/ti-bandgap.c

index bc14dc874594e4d9fd37a68874bb6adb6eb4b562,63e2f5ce7e94a212a9b118fa53472f8bfe2f2f8a..10c47c048f7a3b0e4f5538c3698492fd5482c21b
@@@ -43,6 -43,8 +43,8 @@@
  
  #include "ti-bandgap.h"
  
+ static int ti_bandgap_force_single_read(struct ti_bandgap *bgp, int id);
  /***   Helper functions to access registers and their bitfields   ***/
  
  /**
@@@ -103,52 -105,17 +105,48 @@@ do {                                                            
   */
  static int ti_bandgap_power(struct ti_bandgap *bgp, bool on)
  {
-       int i, ret = 0;
+       int i;
  
-       if (!TI_BANDGAP_HAS(bgp, POWER_SWITCH)) {
-               ret = -ENOTSUPP;
-               goto exit;
-       }
+       if (!TI_BANDGAP_HAS(bgp, POWER_SWITCH))
+               return -ENOTSUPP;
  
        for (i = 0; i < bgp->conf->sensor_count; i++)
                /* active on 0 */
                RMW_BITS(bgp, i, temp_sensor_ctrl, bgap_tempsoff_mask, !on);
- exit:
-       return ret;
+       return 0;
  }
  
 +/**
 + * ti_errata814_bandgap_read_temp() - helper function to read dra7 sensor temperature
 + * @bgp: pointer to ti_bandgap structure
 + * @reg: desired register (offset) to be read
 + *
 + * Function to read dra7 bandgap sensor temperature. This is done separately
 + * so as to workaround the errata "Bandgap Temperature read Dtemp can be
 + * corrupted" - Errata ID: i814".
 + * Read accesses to registers listed below can be corrupted due to incorrect
 + * resynchronization between clock domains.
 + * Read access to registers below can be corrupted :
 + * CTRL_CORE_DTEMP_MPU/GPU/CORE/DSPEVE/IVA_n (n = 0 to 4)
 + * CTRL_CORE_TEMP_SENSOR_MPU/GPU/CORE/DSPEVE/IVA_n
 + *
 + * Return: the register value.
 + */
 +static u32 ti_errata814_bandgap_read_temp(struct ti_bandgap *bgp,  u32 reg)
 +{
 +      u32 val1, val2;
 +
 +      val1 = ti_bandgap_readl(bgp, reg);
 +      val2 = ti_bandgap_readl(bgp, reg);
 +
 +      /* If both times we read the same value then that is right */
 +      if (val1 == val2)
 +              return val1;
 +
 +      /* if val1 and val2 are different read it third time */
 +      return ti_bandgap_readl(bgp, reg);
 +}
 +
  /**
   * ti_bandgap_read_temp() - helper function to read sensor temperature
   * @bgp: pointer to ti_bandgap structure
@@@ -179,11 -146,7 +177,11 @@@ static u32 ti_bandgap_read_temp(struct 
        }
  
        /* read temperature */
 -      temp = ti_bandgap_readl(bgp, reg);
 +      if (TI_BANDGAP_HAS(bgp, ERRATA_814))
 +              temp = ti_errata814_bandgap_read_temp(bgp, reg);
 +      else
 +              temp = ti_bandgap_readl(bgp, reg);
 +
        temp &= tsr->bgap_dtemp_mask;
  
        if (TI_BANDGAP_HAS(bgp, FREEZE_BIT))
@@@ -298,18 -261,13 +296,13 @@@ stati
  int ti_bandgap_adc_to_mcelsius(struct ti_bandgap *bgp, int adc_val, int *t)
  {
        const struct ti_bandgap_data *conf = bgp->conf;
-       int ret = 0;
  
        /* look up for temperature in the table and return the temperature */
-       if (adc_val < conf->adc_start_val || adc_val > conf->adc_end_val) {
-               ret = -ERANGE;
-               goto exit;
-       }
+       if (adc_val < conf->adc_start_val || adc_val > conf->adc_end_val)
+               return -ERANGE;
  
        *t = bgp->conf->conv_table[adc_val - conf->adc_start_val];
- exit:
-       return ret;
+       return 0;
  }
  
  /**
@@@ -330,16 -288,14 +323,14 @@@ int ti_bandgap_mcelsius_to_adc(struct t
  {
        const struct ti_bandgap_data *conf = bgp->conf;
        const int *conv_table = bgp->conf->conv_table;
-       int high, low, mid, ret = 0;
+       int high, low, mid;
  
        low = 0;
        high = conf->adc_end_val - conf->adc_start_val;
        mid = (high + low) / 2;
  
-       if (temp < conv_table[low] || temp > conv_table[high]) {
-               ret = -ERANGE;
-               goto exit;
-       }
+       if (temp < conv_table[low] || temp > conv_table[high])
+               return -ERANGE;
  
        while (low < high) {
                if (temp < conv_table[mid])
        }
  
        *adc = conf->adc_start_val + low;
- exit:
-       return ret;
+       return 0;
  }
  
  /**
@@@ -378,13 -332,11 +367,11 @@@ int ti_bandgap_add_hyst(struct ti_bandg
         */
        ret = ti_bandgap_adc_to_mcelsius(bgp, adc_val, &temp);
        if (ret < 0)
-               goto exit;
+               return ret;
  
        temp += hyst_val;
  
        ret = ti_bandgap_mcelsius_to_adc(bgp, temp, sum);
- exit:
        return ret;
  }
  
@@@ -445,7 -397,7 +432,7 @@@ static int ti_bandgap_update_alert_thre
  {
        struct temp_sensor_data *ts_data = bgp->conf->sensors[id].ts_data;
        struct temp_sensor_registers *tsr;
 -      u32 thresh_val, reg_val, t_hot, t_cold;
 +      u32 thresh_val, reg_val, t_hot, t_cold, ctrl;
        int err = 0;
  
        tsr = bgp->conf->sensors[id].registers;
                  ~(tsr->threshold_thot_mask | tsr->threshold_tcold_mask);
        reg_val |= (t_hot << __ffs(tsr->threshold_thot_mask)) |
                   (t_cold << __ffs(tsr->threshold_tcold_mask));
 +
 +      /**
 +       * Errata i813:
 +       * Spurious Thermal Alert: Talert can happen randomly while the device
 +       * remains under the temperature limit defined for this event to trig.
 +       * This spurious event is caused by a incorrect re-synchronization
 +       * between clock domains. The comparison between configured threshold
 +       * and current temperature value can happen while the value is
 +       * transitioning (metastable), thus causing inappropriate event
 +       * generation. No spurious event occurs as long as the threshold value
 +       * stays unchanged. Spurious event can be generated while a thermal
 +       * alert threshold is modified in
 +       * CONTROL_BANDGAP_THRESHOLD_MPU/GPU/CORE/DSPEVE/IVA_n.
 +       */
 +
 +      if (TI_BANDGAP_HAS(bgp, ERRATA_813)) {
 +              /* Mask t_hot and t_cold events at the IP Level */
 +              ctrl = ti_bandgap_readl(bgp, tsr->bgap_mask_ctrl);
 +
 +              if (hot)
 +                      ctrl &= ~tsr->mask_hot_mask;
 +              else
 +                      ctrl &= ~tsr->mask_cold_mask;
 +
 +              ti_bandgap_writel(bgp, ctrl, tsr->bgap_mask_ctrl);
 +      }
 +
 +      /* Write the threshold value */
        ti_bandgap_writel(bgp, reg_val, tsr->bgap_threshold);
  
 +      if (TI_BANDGAP_HAS(bgp, ERRATA_813)) {
 +              /* Unmask t_hot and t_cold events at the IP Level */
 +              ctrl = ti_bandgap_readl(bgp, tsr->bgap_mask_ctrl);
 +              if (hot)
 +                      ctrl |= tsr->mask_hot_mask;
 +              else
 +                      ctrl |= tsr->mask_cold_mask;
 +
 +              ti_bandgap_writel(bgp, ctrl, tsr->bgap_mask_ctrl);
 +      }
 +
        if (err) {
                dev_err(bgp->dev, "failed to reprogram thot threshold\n");
                err = -EIO;
@@@ -542,22 -455,18 +529,18 @@@ exit
   */
  static inline int ti_bandgap_validate(struct ti_bandgap *bgp, int id)
  {
-       int ret = 0;
        if (!bgp || IS_ERR(bgp)) {
                pr_err("%s: invalid bandgap pointer\n", __func__);
-               ret = -EINVAL;
-               goto exit;
+               return -EINVAL;
        }
  
        if ((id < 0) || (id >= bgp->conf->sensor_count)) {
                dev_err(bgp->dev, "%s: sensor id out of range (%d)\n",
                        __func__, id);
-               ret = -ERANGE;
+               return -ERANGE;
        }
  
- exit:
-       return ret;
+       return 0;
  }
  
  /**
@@@ -585,12 -494,10 +568,10 @@@ static int _ti_bandgap_write_threshold(
  
        ret = ti_bandgap_validate(bgp, id);
        if (ret)
-               goto exit;
+               return ret;
  
-       if (!TI_BANDGAP_HAS(bgp, TALERT)) {
-               ret = -ENOTSUPP;
-               goto exit;
-       }
+       if (!TI_BANDGAP_HAS(bgp, TALERT))
+               return -ENOTSUPP;
  
        ts_data = bgp->conf->sensors[id].ts_data;
        tsr = bgp->conf->sensors[id].registers;
        }
  
        if (ret)
-               goto exit;
+               return ret;
  
        ret = ti_bandgap_mcelsius_to_adc(bgp, val, &adc_val);
        if (ret < 0)
-               goto exit;
+               return ret;
  
        spin_lock(&bgp->lock);
        ret = ti_bandgap_update_alert_threshold(bgp, id, adc_val, hot);
        spin_unlock(&bgp->lock);
- exit:
        return ret;
  }
  
@@@ -656,7 -561,7 +635,7 @@@ static int _ti_bandgap_read_threshold(s
  
        temp = ti_bandgap_readl(bgp, tsr->bgap_threshold);
        temp = (temp & mask) >> __ffs(mask);
-       ret |= ti_bandgap_adc_to_mcelsius(bgp, temp, &temp);
+       ret = ti_bandgap_adc_to_mcelsius(bgp, temp, &temp);
        if (ret) {
                dev_err(bgp->dev, "failed to read thot\n");
                ret = -EIO;
@@@ -926,11 -831,17 +905,17 @@@ int ti_bandgap_read_temperature(struct 
        if (ret)
                return ret;
  
+       if (!TI_BANDGAP_HAS(bgp, MODE_CONFIG)) {
+               ret = ti_bandgap_force_single_read(bgp, id);
+               if (ret)
+                       return ret;
+       }
        spin_lock(&bgp->lock);
        temp = ti_bandgap_read_temp(bgp, id);
        spin_unlock(&bgp->lock);
  
-       ret |= ti_bandgap_adc_to_mcelsius(bgp, temp, &temp);
+       ret = ti_bandgap_adc_to_mcelsius(bgp, temp, &temp);
        if (ret)
                return -EIO;
  
@@@ -991,7 -902,8 +976,8 @@@ void *ti_bandgap_get_sensor_data(struc
  static int
  ti_bandgap_force_single_read(struct ti_bandgap *bgp, int id)
  {
-       u32 temp = 0, counter = 1000;
+       u32 counter = 1000;
+       struct temp_sensor_registers *tsr;
  
        /* Select single conversion mode */
        if (TI_BANDGAP_HAS(bgp, MODE_CONFIG))
  
        /* Start of Conversion = 1 */
        RMW_BITS(bgp, id, temp_sensor_ctrl, bgap_soc_mask, 1);
-       /* Wait until DTEMP is updated */
-       temp = ti_bandgap_read_temp(bgp, id);
  
-       while ((temp == 0) && --counter)
-               temp = ti_bandgap_read_temp(bgp, id);
-       /* REVISIT: Check correct condition for end of conversion */
+       /* Wait for EOCZ going up */
+       tsr = bgp->conf->sensors[id].registers;
+       while (--counter) {
+               if (ti_bandgap_readl(bgp, tsr->temp_sensor_ctrl) &
+                   tsr->bgap_eocz_mask)
+                       break;
+       }
  
        /* Start of Conversion = 0 */
        RMW_BITS(bgp, id, temp_sensor_ctrl, bgap_soc_mask, 0);
  
+       /* Wait for EOCZ going down */
+       counter = 1000;
+       while (--counter) {
+               if (!(ti_bandgap_readl(bgp, tsr->temp_sensor_ctrl) &
+                     tsr->bgap_eocz_mask))
+                       break;
+       }
        return 0;
  }
  
@@@ -1294,11 -1217,10 +1291,10 @@@ int ti_bandgap_probe(struct platform_de
                goto free_irqs;
        }
  
-       bgp->div_clk = clk_get(NULL,  bgp->conf->div_ck_name);
+       bgp->div_clk = clk_get(NULL, bgp->conf->div_ck_name);
        ret = IS_ERR(bgp->div_clk);
        if (ret) {
-               dev_err(&pdev->dev,
-                       "failed to request div_ts_ck clock ref\n");
+               dev_err(&pdev->dev, "failed to request div_ts_ck clock ref\n");
                ret = PTR_ERR(bgp->div_clk);
                goto free_irqs;
        }
This page took 0.079109 seconds and 4 git commands to generate.