diff options
author | Keerthy <j-keerthy@ti.com> | 2012-03-14 14:08:56 +0800 |
---|---|---|
committer | Andy Green <andy.green@linaro.org> | 2012-06-20 10:27:44 +0800 |
commit | e72af8beedaafb7874cb5670246fb87043c4e4e6 (patch) | |
tree | f2926e083d7fbbb3af668587dc5a6ec60c91a61a | |
parent | 3bc1e90ef0ffb710a4f0681eb6b97f8562fac7e5 (diff) |
mfd: OMAP4plus: SCM : Fixed context restoration of OMAP temp sensor
Spurious thermal alert interrupt is generated when restoring the context
of OMAP temperature sensor driver upon a wake-up from CORE OSWRet/OFF modes.
This spurious interrupt is due to the fact that current SW implementation
restores all HW registers without any specific sequence.
Finally, the thermal alert interrupt handler prints error message because
the temperature reported by the sensor is invalid.
This patch applies a SW sequence taking into the HW constraints to avoid
the generation of cold thermal alert.
HW constraints:
- The HW logic decrements the counter and then starts the temperature
measurement.
- An immediate temperature measurement is possible only if counter is set to
low value.
- The HW logic compares the BGAP_TEMP_SENSOR_DTEMP bitfield with threshold as
soon as the clock is enabled.
- To avoid spurious interrupt, it is mandatory to unmask interrupts (cold
and/or hot) when BGAP_TEMP_SENSOR_DTEMP bitfield is different than 0.
New SW implementation:
1/ If all registers have been reset:
- Force immediate temperature measurement and wait until
BGAP_TEMP_SENSOR_DTEMP bitfield is updated before completing the full context
restoration.
- Ensure that the BGAP_TEMPSOFF bit is not set to 1 during context restoration.
- Complete the context restoration (mask bits and counter).
2/ If registers have not been reset:
- Force immediate temperature measurement and wait until
BGAP_TEMP_SENSOR_DTEMP bitfield is different than 0.
Signed-off-by:Sebastien Sabatier <s-sabatier1@ti.com>
Signed-off-by: Keerthy <j-keerthy@ti.com>
-rw-r--r-- | drivers/mfd/omap4plus_scm.c | 81 |
1 files changed, 69 insertions, 12 deletions
diff --git a/drivers/mfd/omap4plus_scm.c b/drivers/mfd/omap4plus_scm.c index 0f08695a773..623783b99b2 100644 --- a/drivers/mfd/omap4plus_scm.c +++ b/drivers/mfd/omap4plus_scm.c @@ -280,23 +280,80 @@ static void omap4plus_scm_save_ctxt(struct scm *scm_ptr) } } +static void omap_temp_sensor_force_single_read(struct scm *scm_ptr, int id) +{ + int temp = 0, counter = 1000; + + /* Select single conversion mode */ + temp = omap4plus_scm_readl(scm_ptr, + scm_ptr->registers[id]->bgap_mode_ctrl); + temp &= ~(1 << __ffs(scm_ptr->registers[id]->mode_ctrl_mask)); + omap4plus_scm_writel(scm_ptr, temp, + scm_ptr->registers[id]->bgap_mode_ctrl); + + /* Start of Conversion = 1 */ + temp = omap4plus_scm_readl(scm_ptr, + scm_ptr->registers[id]->temp_sensor_ctrl); + temp |= 1 << __ffs(scm_ptr->registers[id]->bgap_soc_mask); + omap4plus_scm_writel(scm_ptr, temp, + scm_ptr->registers[id]->temp_sensor_ctrl); + /* Wait until DTEMP is updated */ + temp = omap4plus_scm_readl(scm_ptr, + scm_ptr->registers[id]->temp_sensor_ctrl); + temp &= (scm_ptr->registers[id]->bgap_dtemp_mask); + while ((temp == 0) && --counter) { + temp = omap4plus_scm_readl(scm_ptr, + scm_ptr->registers[id]->temp_sensor_ctrl); + temp &= (scm_ptr->registers[id]->bgap_dtemp_mask); + } + /* Start of Conversion = 0 */ + temp = omap4plus_scm_readl(scm_ptr, + scm_ptr->registers[id]->temp_sensor_ctrl); + temp &= ~(1 << __ffs(scm_ptr->registers[id]->bgap_soc_mask)); + omap4plus_scm_writel(scm_ptr, temp, + scm_ptr->registers[id]->temp_sensor_ctrl); +} + static void omap4plus_scm_restore_ctxt(struct scm *scm_ptr) { - int i; + int i, temp = 0; for (i = 0; i < scm_ptr->cnt; i++) { - omap4plus_scm_writel(scm_ptr, scm_ptr->regval[i]->bg_mode_ctrl, - scm_ptr->registers[i]->bgap_mode_ctrl); - omap4plus_scm_writel(scm_ptr, scm_ptr->regval[i]->bg_ctrl, - scm_ptr->registers[i]->bgap_mask_ctrl); - omap4plus_scm_writel(scm_ptr, scm_ptr->regval[i]->bg_counter, - scm_ptr->registers[i]->bgap_counter); - omap4plus_scm_writel(scm_ptr, scm_ptr->regval[i]->bg_threshold, - scm_ptr->registers[i]->bgap_threshold); - omap4plus_scm_writel(scm_ptr, - scm_ptr->regval[i]->tshut_threshold, + if ((omap4plus_scm_readl(scm_ptr, + scm_ptr->registers[i]->bgap_counter) == 0)) { + omap4plus_scm_writel(scm_ptr, + scm_ptr->regval[i]->bg_threshold, + scm_ptr->registers[i]->bgap_threshold); + omap4plus_scm_writel(scm_ptr, + scm_ptr->regval[i]->tshut_threshold, scm_ptr->registers[i]->tshut_threshold); - + /* Force immediate temperature measurement and update + * of the DTEMP field + */ + omap_temp_sensor_force_single_read(scm_ptr, i); + omap4plus_scm_writel(scm_ptr, + scm_ptr->regval[i]->bg_counter, + scm_ptr->registers[i]->bgap_counter); + omap4plus_scm_writel(scm_ptr, + scm_ptr->regval[i]->bg_mode_ctrl, + scm_ptr->registers[i]->bgap_mode_ctrl); + omap4plus_scm_writel(scm_ptr, + scm_ptr->regval[i]->bg_ctrl, + scm_ptr->registers[i]->bgap_mask_ctrl); + } else { + temp = omap4plus_scm_readl(scm_ptr, + scm_ptr->registers[i]->temp_sensor_ctrl); + temp &= (scm_ptr->registers[i]->bgap_dtemp_mask); + if (temp == 0) { + omap_temp_sensor_force_single_read(scm_ptr, i); + temp = omap4plus_scm_readl(scm_ptr, + scm_ptr->registers[i]->bgap_mask_ctrl); + temp |= 1 << + __ffs(scm_ptr->registers[i]->mode_ctrl_mask); + omap4plus_scm_writel(scm_ptr, temp, + scm_ptr->registers[i]->bgap_mask_ctrl); + } + } } } |