summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeerthy <j-keerthy@ti.com>2012-03-14 14:08:56 +0800
committerAndy Green <andy.green@linaro.org>2012-06-20 10:27:44 +0800
commite72af8beedaafb7874cb5670246fb87043c4e4e6 (patch)
treef2926e083d7fbbb3af668587dc5a6ec60c91a61a
parent3bc1e90ef0ffb710a4f0681eb6b97f8562fac7e5 (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.c81
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);
+ }
+ }
}
}