diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2015-07-20 10:08:17 -0700 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2015-07-20 10:08:17 -0700 |
commit | c57d5621d2f2dc238f4b9c4d00b2a54187a75445 (patch) | |
tree | ece13738a44545fb110e5d73adbf2625bc7a1ea6 /drivers/thermal/ti-soc-thermal | |
parent | 6ccfe64c770139675a080ee5029ded7d89d9ea0d (diff) | |
parent | 52721d9d3334c1cb1f76219a161084094ec634dc (diff) | |
download | blackbird-op-linux-c57d5621d2f2dc238f4b9c4d00b2a54187a75445.tar.gz blackbird-op-linux-c57d5621d2f2dc238f4b9c4d00b2a54187a75445.zip |
Merge tag 'v4.2-rc3' into next
Sync up with Linux 4.2-rc3 to bring in infrastructure (OF) pieces.
Diffstat (limited to 'drivers/thermal/ti-soc-thermal')
-rw-r--r-- | drivers/thermal/ti-soc-thermal/dra752-thermal-data.c | 3 | ||||
-rw-r--r-- | drivers/thermal/ti-soc-thermal/omap5-thermal-data.c | 3 | ||||
-rw-r--r-- | drivers/thermal/ti-soc-thermal/ti-bandgap.c | 180 | ||||
-rw-r--r-- | drivers/thermal/ti-soc-thermal/ti-bandgap.h | 6 | ||||
-rw-r--r-- | drivers/thermal/ti-soc-thermal/ti-thermal-common.c | 5 |
5 files changed, 138 insertions, 59 deletions
diff --git a/drivers/thermal/ti-soc-thermal/dra752-thermal-data.c b/drivers/thermal/ti-soc-thermal/dra752-thermal-data.c index a4929272074f..58b5c6694cd4 100644 --- a/drivers/thermal/ti-soc-thermal/dra752-thermal-data.c +++ b/drivers/thermal/ti-soc-thermal/dra752-thermal-data.c @@ -420,7 +420,8 @@ const struct ti_bandgap_data dra752_data = { TI_BANDGAP_FEATURE_FREEZE_BIT | TI_BANDGAP_FEATURE_TALERT | TI_BANDGAP_FEATURE_COUNTER_DELAY | - TI_BANDGAP_FEATURE_HISTORY_BUFFER, + TI_BANDGAP_FEATURE_HISTORY_BUFFER | + TI_BANDGAP_FEATURE_ERRATA_814, .fclock_name = "l3instr_ts_gclk_div", .div_ck_name = "l3instr_ts_gclk_div", .conv_table = dra752_adc_to_temp, diff --git a/drivers/thermal/ti-soc-thermal/omap5-thermal-data.c b/drivers/thermal/ti-soc-thermal/omap5-thermal-data.c index eff0c80fd4af..79ff70c446ba 100644 --- a/drivers/thermal/ti-soc-thermal/omap5-thermal-data.c +++ b/drivers/thermal/ti-soc-thermal/omap5-thermal-data.c @@ -319,7 +319,8 @@ const struct ti_bandgap_data omap5430_data = { TI_BANDGAP_FEATURE_FREEZE_BIT | TI_BANDGAP_FEATURE_TALERT | TI_BANDGAP_FEATURE_COUNTER_DELAY | - TI_BANDGAP_FEATURE_HISTORY_BUFFER, + TI_BANDGAP_FEATURE_HISTORY_BUFFER | + TI_BANDGAP_FEATURE_ERRATA_813, .fclock_name = "l3instr_ts_gclk_div", .div_ck_name = "l3instr_ts_gclk_div", .conv_table = omap5430_adc_to_temp, diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.c b/drivers/thermal/ti-soc-thermal/ti-bandgap.c index 62a5d449c388..10c47c048f7a 100644 --- a/drivers/thermal/ti-soc-thermal/ti-bandgap.c +++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.c @@ -43,6 +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,19 +105,46 @@ 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); + return 0; +} -exit: - return ret; +/** + * 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); } /** @@ -148,7 +177,11 @@ static u32 ti_bandgap_read_temp(struct ti_bandgap *bgp, int id) } /* 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)) @@ -263,18 +296,13 @@ static 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; } /** @@ -295,16 +323,14 @@ int ti_bandgap_mcelsius_to_adc(struct ti_bandgap *bgp, long temp, int *adc) { 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]) @@ -315,9 +341,7 @@ int ti_bandgap_mcelsius_to_adc(struct ti_bandgap *bgp, long temp, int *adc) } *adc = conf->adc_start_val + low; - -exit: - return ret; + return 0; } /** @@ -343,13 +367,11 @@ int ti_bandgap_add_hyst(struct ti_bandgap *bgp, int adc_val, int hyst_val, */ 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; } @@ -410,7 +432,7 @@ static int ti_bandgap_update_alert_threshold(struct ti_bandgap *bgp, int id, { 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; @@ -442,8 +464,47 @@ static int ti_bandgap_update_alert_threshold(struct ti_bandgap *bgp, int id, ~(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; @@ -468,22 +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; } /** @@ -511,12 +568,10 @@ static int _ti_bandgap_write_threshold(struct ti_bandgap *bgp, int id, int val, 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; @@ -529,17 +584,15 @@ static int _ti_bandgap_write_threshold(struct ti_bandgap *bgp, int id, int val, } 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; } @@ -582,7 +635,7 @@ static int _ti_bandgap_read_threshold(struct ti_bandgap *bgp, int id, 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; @@ -852,11 +905,17 @@ int ti_bandgap_read_temperature(struct ti_bandgap *bgp, int id, 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; @@ -917,7 +976,8 @@ void *ti_bandgap_get_sensor_data(struct ti_bandgap *bgp, int id) 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)) @@ -925,16 +985,27 @@ ti_bandgap_force_single_read(struct ti_bandgap *bgp, int id) /* 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; } @@ -1220,11 +1291,10 @@ int ti_bandgap_probe(struct platform_device *pdev) 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; } diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.h b/drivers/thermal/ti-soc-thermal/ti-bandgap.h index b3adf72f252d..0c52f7afba00 100644 --- a/drivers/thermal/ti-soc-thermal/ti-bandgap.h +++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.h @@ -318,6 +318,10 @@ struct ti_temp_sensor { * TI_BANDGAP_FEATURE_HISTORY_BUFFER - used when the bandgap device features * a history buffer of temperatures. * + * TI_BANDGAP_FEATURE_ERRATA_814 - used to workaorund when the bandgap device + * has Errata 814 + * TI_BANDGAP_FEATURE_ERRATA_813 - used to workaorund when the bandgap device + * has Errata 813 * TI_BANDGAP_HAS(b, f) - macro to check if a bandgap device is capable of a * specific feature (above) or not. Return non-zero, if yes. */ @@ -331,6 +335,8 @@ struct ti_temp_sensor { #define TI_BANDGAP_FEATURE_FREEZE_BIT BIT(7) #define TI_BANDGAP_FEATURE_COUNTER_DELAY BIT(8) #define TI_BANDGAP_FEATURE_HISTORY_BUFFER BIT(9) +#define TI_BANDGAP_FEATURE_ERRATA_814 BIT(10) +#define TI_BANDGAP_FEATURE_ERRATA_813 BIT(11) #define TI_BANDGAP_HAS(b, f) \ ((b)->conf->features & TI_BANDGAP_FEATURE_ ## f) diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c index a38c1756442a..c7c5b3779dac 100644 --- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c +++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c @@ -75,7 +75,7 @@ static inline int ti_thermal_hotspot_temperature(int t, int s, int c) } /* thermal zone ops */ -/* Get temperature callback function for thermal zone*/ +/* Get temperature callback function for thermal zone */ static inline int __ti_thermal_get_temp(void *devdata, long *temp) { struct thermal_zone_device *pcb_tz = NULL; @@ -146,7 +146,8 @@ static int ti_thermal_bind(struct thermal_zone_device *thermal, return thermal_zone_bind_cooling_device(thermal, 0, cdev, /* bind with min and max states defined by cpu_cooling */ THERMAL_NO_LIMIT, - THERMAL_NO_LIMIT); + THERMAL_NO_LIMIT, + THERMAL_WEIGHT_DEFAULT); } /* Unbind callback functions for thermal zone */ |