summaryrefslogtreecommitdiffstats
path: root/drivers/thermal/ti-soc-thermal/ti-bandgap.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-06-26 02:51:55 +0200
committerLinus Torvalds <torvalds@linux-foundation.org>2015-06-26 02:51:55 +0200
commit0db9723cacf4d62bc3685fb15179b39ee4e17679 (patch)
tree7de16280234a3d98d8f7dd95e623ec381fd5af36 /drivers/thermal/ti-soc-thermal/ti-bandgap.c
parentMerge tag 'sound-4.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/ti... (diff)
parentMerge branches 'release' and 'thermal-soc' of .git into next (diff)
downloadlinux-0db9723cacf4d62bc3685fb15179b39ee4e17679.tar.xz
linux-0db9723cacf4d62bc3685fb15179b39ee4e17679.zip
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux
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 ...
Diffstat (limited to 'drivers/thermal/ti-soc-thermal/ti-bandgap.c')
-rw-r--r--drivers/thermal/ti-soc-thermal/ti-bandgap.c104
1 files changed, 50 insertions, 54 deletions
diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.c b/drivers/thermal/ti-soc-thermal/ti-bandgap.c
index bc14dc874594..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,15 @@ 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;
}
/**
@@ -298,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;
}
/**
@@ -330,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])
@@ -350,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;
}
/**
@@ -378,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;
}
@@ -542,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;
}
/**
@@ -585,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;
@@ -603,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;
}
@@ -656,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;
@@ -926,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;
@@ -991,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))
@@ -999,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;
}
@@ -1294,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;
}