|
@@ -118,6 +118,37 @@ 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);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* ti_bandgap_read_temp() - helper function to read sensor temperature
|
|
|
* @bgp: pointer to ti_bandgap structure
|
|
@@ -148,7 +179,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))
|
|
@@ -410,7 +445,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 +477,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;
|