staging: omap-thermal: introduze FREEZE_BIT feature
authorEduardo Valentin <eduardo.valentin@ti.com>
Tue, 26 Feb 2013 22:53:33 +0000 (18:53 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 11 Mar 2013 16:48:53 +0000 (09:48 -0700)
For ES2.0 devices, it is not guaranteed that current DTEMP
or DTEMP0 from the history buffer are going to contain
correct values, due to desynchronization between BG clk
and OCP clk.

For this reason, this patch changes the driver to first:
a. consider a feature flag, FREEZE_BIT, in order to check
it is possible to freeze the history buffer or not.
b. whenever reading the temperature, it will fetch from
DTEMP1 instead of DTEMP or DTEMP0.

This WA is applicable only for OMAP5430 ES2.0.

Signed-off-by: Eduardo Valentin <eduardo.valentin@ti.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/omap-thermal/omap-bandgap.c
drivers/staging/omap-thermal/omap-bandgap.h
drivers/staging/omap-thermal/omap5-thermal.c

index 80384edfd7623ac2ce3569d5cd5bad41d717fbad..82ad5dbd7adfc0a1cc0ea4b8cbab695bc83ff9fd 100644 (file)
@@ -75,12 +75,44 @@ static int omap_bandgap_power(struct omap_bandgap *bg_ptr, bool on)
        return 0;
 }
 
+static u32 omap_bandgap_read_temp(struct omap_bandgap *bg_ptr, int id)
+{
+       struct temp_sensor_registers *tsr;
+       u32 temp, ctrl, reg;
+
+       tsr = bg_ptr->conf->sensors[id].registers;
+       reg = tsr->temp_sensor_ctrl;
+
+       if (OMAP_BANDGAP_HAS(bg_ptr, FREEZE_BIT)) {
+               ctrl = omap_bandgap_readl(bg_ptr, tsr->bgap_mask_ctrl);
+               ctrl |= tsr->mask_freeze_mask;
+               omap_bandgap_writel(bg_ptr, ctrl, tsr->bgap_mask_ctrl);
+               /*
+                * In case we cannot read from cur_dtemp / dtemp_0,
+                * then we read from the last valid temp read
+                */
+               reg = tsr->ctrl_dtemp_1;
+       }
+
+       /* read temperature */
+       temp = omap_bandgap_readl(bg_ptr, reg);
+       temp &= tsr->bgap_dtemp_mask;
+
+       if (OMAP_BANDGAP_HAS(bg_ptr, FREEZE_BIT)) {
+               ctrl = omap_bandgap_readl(bg_ptr, tsr->bgap_mask_ctrl);
+               ctrl &= ~tsr->mask_freeze_mask;
+               omap_bandgap_writel(bg_ptr, ctrl, tsr->bgap_mask_ctrl);
+       }
+
+       return temp;
+}
+
 /* This is the Talert handler. Call it only if HAS(TALERT) is set */
 static irqreturn_t talert_irq_handler(int irq, void *data)
 {
        struct omap_bandgap *bg_ptr = data;
        struct temp_sensor_registers *tsr;
-       u32 t_hot = 0, t_cold = 0, temp, ctrl;
+       u32 t_hot = 0, t_cold = 0, ctrl;
        int i;
 
        bg_ptr = data;
@@ -118,10 +150,6 @@ static irqreturn_t talert_irq_handler(int irq, void *data)
                        __func__, bg_ptr->conf->sensors[i].domain,
                        t_hot, t_cold);
 
-               /* read temperature */
-               temp = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl);
-               temp &= tsr->bgap_dtemp_mask;
-
                /* report temperature to whom may concern */
                if (bg_ptr->conf->report_temperature)
                        bg_ptr->conf->report_temperature(bg_ptr, i);
@@ -190,11 +218,11 @@ static int temp_sensor_unmask_interrupts(struct omap_bandgap *bg_ptr, int id,
        u32 temp, reg_val;
 
        /* Read the current on die temperature */
-       tsr = bg_ptr->conf->sensors[id].registers;
-       temp = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl);
-       temp &= tsr->bgap_dtemp_mask;
+       temp = omap_bandgap_read_temp(bg_ptr, id);
 
+       tsr = bg_ptr->conf->sensors[id].registers;
        reg_val = omap_bandgap_readl(bg_ptr, tsr->bgap_mask_ctrl);
+
        if (temp < t_hot)
                reg_val |= tsr->mask_hot_mask;
        else
@@ -625,8 +653,9 @@ int omap_bandgap_read_temperature(struct omap_bandgap *bg_ptr, int id,
                return ret;
 
        tsr = bg_ptr->conf->sensors[id].registers;
-       temp = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl);
-       temp &= tsr->bgap_dtemp_mask;
+       mutex_lock(&bg_ptr->bg_mutex);
+       temp = omap_bandgap_read_temp(bg_ptr, id);
+       mutex_unlock(&bg_ptr->bg_mutex);
 
        ret |= adc_to_temp_conversion(bg_ptr, id, temp, &temp);
        if (ret)
@@ -694,12 +723,11 @@ omap_bandgap_force_single_read(struct omap_bandgap *bg_ptr, int id)
        temp |= 1 << __ffs(tsr->bgap_soc_mask);
        omap_bandgap_writel(bg_ptr, temp, tsr->temp_sensor_ctrl);
        /* Wait until DTEMP is updated */
-       temp = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl);
-       temp &= (tsr->bgap_dtemp_mask);
-       while ((temp == 0) && --counter) {
-               temp = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl);
-               temp &= (tsr->bgap_dtemp_mask);
-       }
+       temp = omap_bandgap_read_temp(bg_ptr, id);
+
+       while ((temp == 0) && --counter)
+               temp = omap_bandgap_read_temp(bg_ptr, id);
+
        /* Start of Conversion = 0 */
        temp = omap_bandgap_readl(bg_ptr, tsr->temp_sensor_ctrl);
        temp &= ~(1 << __ffs(tsr->bgap_soc_mask));
index ef5503d11177c0a43f909b04d5c9ed0101dc057c..59c9ba20c15379c60118fe5b74f521340fcb67f4 100644 (file)
@@ -442,6 +442,7 @@ struct omap_bandgap_data {
 #define OMAP_BANDGAP_FEATURE_COUNTER           (1 << 4)
 #define OMAP_BANDGAP_FEATURE_POWER_SWITCH      (1 << 5)
 #define OMAP_BANDGAP_FEATURE_CLK_CTRL          (1 << 6)
+#define OMAP_BANDGAP_FEATURE_FREEZE_BIT                (1 << 7)
 #define OMAP_BANDGAP_HAS(b, f)                 \
                        ((b)->conf->features & OMAP_BANDGAP_FEATURE_ ## f)
        unsigned int                    features;
index c2bfc65f5d97dba6844e6a6be9a753603df2045d..b20db0c6531870e26f6c070ecc9ee5ba0c8f921d 100644 (file)
@@ -319,6 +319,7 @@ omap5430_adc_to_temp[
 /* TODO : Need to update the slope/constant for ES2.0 silicon */
 const struct omap_bandgap_data omap5430_data = {
        .features = OMAP_BANDGAP_FEATURE_TSHUT_CONFIG |
+                       OMAP_BANDGAP_FEATURE_FREEZE_BIT |
                        OMAP_BANDGAP_FEATURE_TALERT,
        .fclock_name = "l3instr_ts_gclk_div",
        .div_ck_name = "l3instr_ts_gclk_div",