Re: [RFC PATCH 6/8] misc: emif: add interrupt and temperature handling

2012-02-16 Thread Santosh Shilimkar
On Saturday 04 February 2012 05:46 PM, Aneesh V wrote:
 Add an ISR for EMIF that:
   1. reports details of access errors
   2. takes action on thermal events
 
 On thermal events SDRAM timing parameters are
 adjusted to ensure safe operation
 
 Also clear all interrupts on shut-down. Pending IRQs
 may casue problems during warm-reset.
 
Add some more details like MR4, EMIF polling frequency etc
for better understanding.

 Signed-off-by: Aneesh V ane...@ti.com
 ---
  drivers/misc/emif.c |  209 
 ++-
  1 files changed, 207 insertions(+), 2 deletions(-)
 
 diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c
 index 36ba6f4..5c2b0ae 100644
 --- a/drivers/misc/emif.c
 +++ b/drivers/misc/emif.c
 @@ -500,6 +500,45 @@ static u32 get_pwr_mgmt_ctrl(u32 freq, struct emif_data 
 *emif, u32 ip_rev)
  }
  
  /*
 + * Get the temperature level of the EMIF instance:
 + * Reads the MR4 register of attached SDRAM parts to find out the temperature
 + * level. If there are two parts attached(one on each CS), then the 
 temperature
 + * level for the EMIF instance is the higher of the two temperatures.
 + */
 +static void get_temperature_level(struct emif_data *emif)
 +{
 + u32 temp, temperature_level;
 + unsigned long   irqs;
 + void __iomem*base;
 +
 + base = emif-base;
 +
 + /* Read mode register 4 */
 + writel(DDR_MR4, base + EMIF_LPDDR2_MODE_REG_CONFIG);
 + temperature_level = readl(base + EMIF_LPDDR2_MODE_REG_DATA);
 + temperature_level = (temperature_level  MR4_SDRAM_REF_RATE_MASK) 
 + MR4_SDRAM_REF_RATE_SHIFT;
 +
 + if (emif-plat_data-device_info-cs1_used) {
 + writel(DDR_MR4 | CS_MASK, base + EMIF_LPDDR2_MODE_REG_CONFIG);
 + temp = readl(base + EMIF_LPDDR2_MODE_REG_DATA);
 + temp = (temp  MR4_SDRAM_REF_RATE_MASK)
 +  MR4_SDRAM_REF_RATE_SHIFT;
 + temperature_level = max(temp, temperature_level);
 + }
 +
 + spin_lock_irqsave(emif-lock, irqs);
Add a line here.
 + /* treat everything less than nominal(3) in MR4 as nominal */
 + if (unlikely(temperature_level  SDRAM_TEMP_NOMINAL))
 + temperature_level = SDRAM_TEMP_NOMINAL;
 +
 + /* if we get reserved value in MR4 persist with the existing value */
 + if (likely(temperature_level != SDRAM_TEMP_RESERVED_4))
 + emif-temperature_level = temperature_level;
 + spin_unlock_irqrestore(emif-lock, irqs);
 +}
 +

rest of the patch looks fine to me
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC PATCH 6/8] misc: emif: add interrupt and temperature handling

2012-02-16 Thread Aneesh V

On Thursday 16 February 2012 04:11 PM, Santosh Shilimkar wrote:

On Saturday 04 February 2012 05:46 PM, Aneesh V wrote:

Add an ISR for EMIF that:
1. reports details of access errors
2. takes action on thermal events

On thermal events SDRAM timing parameters are
adjusted to ensure safe operation

Also clear all interrupts on shut-down. Pending IRQs
may casue problems during warm-reset.


Add some more details like MR4, EMIF polling frequency etc
for better understanding.


Will do.






Signed-off-by: Aneesh Vane...@ti.com
---
  drivers/misc/emif.c |  209 ++-
  1 files changed, 207 insertions(+), 2 deletions(-)

diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c
index 36ba6f4..5c2b0ae 100644
--- a/drivers/misc/emif.c
+++ b/drivers/misc/emif.c
@@ -500,6 +500,45 @@ static u32 get_pwr_mgmt_ctrl(u32 freq, struct emif_data 
*emif, u32 ip_rev)
  }

  /*
+ * Get the temperature level of the EMIF instance:
+ * Reads the MR4 register of attached SDRAM parts to find out the temperature
+ * level. If there are two parts attached(one on each CS), then the temperature
+ * level for the EMIF instance is the higher of the two temperatures.
+ */
+static void get_temperature_level(struct emif_data *emif)
+{
+   u32 temp, temperature_level;
+   unsigned long   irqs;
+   void __iomem*base;
+
+   base = emif-base;
+
+   /* Read mode register 4 */
+   writel(DDR_MR4, base + EMIF_LPDDR2_MODE_REG_CONFIG);
+   temperature_level = readl(base + EMIF_LPDDR2_MODE_REG_DATA);
+   temperature_level = (temperature_level  MR4_SDRAM_REF_RATE_MASK)
+   MR4_SDRAM_REF_RATE_SHIFT;
+
+   if (emif-plat_data-device_info-cs1_used) {
+   writel(DDR_MR4 | CS_MASK, base + EMIF_LPDDR2_MODE_REG_CONFIG);
+   temp = readl(base + EMIF_LPDDR2_MODE_REG_DATA);
+   temp = (temp  MR4_SDRAM_REF_RATE_MASK)
+ MR4_SDRAM_REF_RATE_SHIFT;
+   temperature_level = max(temp, temperature_level);
+   }
+
+   spin_lock_irqsave(emif-lock, irqs);

Add a line here.


Will do.


+   /* treat everything less than nominal(3) in MR4 as nominal */
+   if (unlikely(temperature_level  SDRAM_TEMP_NOMINAL))
+   temperature_level = SDRAM_TEMP_NOMINAL;
+
+   /* if we get reserved value in MR4 persist with the existing value */
+   if (likely(temperature_level != SDRAM_TEMP_RESERVED_4))
+   emif-temperature_level = temperature_level;
+   spin_unlock_irqrestore(emif-lock, irqs);
+}
+


rest of the patch looks fine to me


Thanks,
Aneesh
--
To unsubscribe from this list: send the line unsubscribe linux-omap in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC PATCH 6/8] misc: emif: add interrupt and temperature handling

2012-02-04 Thread Aneesh V
Add an ISR for EMIF that:
1. reports details of access errors
2. takes action on thermal events

On thermal events SDRAM timing parameters are
adjusted to ensure safe operation

Also clear all interrupts on shut-down. Pending IRQs
may casue problems during warm-reset.

Signed-off-by: Aneesh V ane...@ti.com
---
 drivers/misc/emif.c |  209 ++-
 1 files changed, 207 insertions(+), 2 deletions(-)

diff --git a/drivers/misc/emif.c b/drivers/misc/emif.c
index 36ba6f4..5c2b0ae 100644
--- a/drivers/misc/emif.c
+++ b/drivers/misc/emif.c
@@ -500,6 +500,45 @@ static u32 get_pwr_mgmt_ctrl(u32 freq, struct emif_data 
*emif, u32 ip_rev)
 }
 
 /*
+ * Get the temperature level of the EMIF instance:
+ * Reads the MR4 register of attached SDRAM parts to find out the temperature
+ * level. If there are two parts attached(one on each CS), then the temperature
+ * level for the EMIF instance is the higher of the two temperatures.
+ */
+static void get_temperature_level(struct emif_data *emif)
+{
+   u32 temp, temperature_level;
+   unsigned long   irqs;
+   void __iomem*base;
+
+   base = emif-base;
+
+   /* Read mode register 4 */
+   writel(DDR_MR4, base + EMIF_LPDDR2_MODE_REG_CONFIG);
+   temperature_level = readl(base + EMIF_LPDDR2_MODE_REG_DATA);
+   temperature_level = (temperature_level  MR4_SDRAM_REF_RATE_MASK) 
+   MR4_SDRAM_REF_RATE_SHIFT;
+
+   if (emif-plat_data-device_info-cs1_used) {
+   writel(DDR_MR4 | CS_MASK, base + EMIF_LPDDR2_MODE_REG_CONFIG);
+   temp = readl(base + EMIF_LPDDR2_MODE_REG_DATA);
+   temp = (temp  MR4_SDRAM_REF_RATE_MASK)
+MR4_SDRAM_REF_RATE_SHIFT;
+   temperature_level = max(temp, temperature_level);
+   }
+
+   spin_lock_irqsave(emif-lock, irqs);
+   /* treat everything less than nominal(3) in MR4 as nominal */
+   if (unlikely(temperature_level  SDRAM_TEMP_NOMINAL))
+   temperature_level = SDRAM_TEMP_NOMINAL;
+
+   /* if we get reserved value in MR4 persist with the existing value */
+   if (likely(temperature_level != SDRAM_TEMP_RESERVED_4))
+   emif-temperature_level = temperature_level;
+   spin_unlock_irqrestore(emif-lock, irqs);
+}
+
+/*
  * Program EMIF shadow registers that are not dependent on temperature
  * or voltage
  */
@@ -553,7 +592,8 @@ static void setup_volt_sensitive_regs(struct emif_data 
*emif,
 static void setup_temperature_sensitive_regs(struct emif_data *emif,
struct emif_regs *regs)
 {
-   u32 tim1, tim3, ref_ctrl, type, irqs;
+   u32 tim1, tim3, ref_ctrl, type;
+   unsigned long   irqs;
void __iomem*base = emif-base;
u32 temperature;
 
@@ -568,7 +608,7 @@ static void setup_temperature_sensitive_regs(struct 
emif_data *emif,
if (type != DDR_TYPE_LPDDR2_S2  type != DDR_TYPE_LPDDR2_S4)
goto out;
 
-   temperature_level = emif-temperature_level;
+   temperature = emif-temperature_level;
if (temperature == SDRAM_TEMP_HIGH_DERATE_REFRESH) {
ref_ctrl = regs-ref_ctrl_shdw_derated;
} else if (temperature == SDRAM_TEMP_HIGH_DERATE_REFRESH_AND_TIMINGS) {
@@ -584,6 +624,153 @@ out:
spin_unlock_irqrestore(emif-lock, irqs);
 }
 
+static irqreturn_t handle_temp_alert(void __iomem *base, struct emif_data 
*emif)
+{
+   u32 old_temp_level;
+
+   old_temp_level = emif-temperature_level;
+   get_temperature_level(emif);
+
+   if (unlikely(emif-temperature_level == old_temp_level))
+   goto handled;
+
+   if (emif-temperature_level  old_temp_level ||
+   emif-temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN) {
+   /*
+* Temperature coming down - defer handling to thread OR
+* Temperature far too high - do kernel_power_off() from
+* thread context
+*/
+   goto thread;
+   } else {
+   /* Temperature is going up - handle immediately */
+   if (!emif-curr_regs) {
+   dev_err(emif-dev, temperature alert before registers 
are calculated, not de-rating timings\n);
+   goto handled;
+   }
+   setup_temperature_sensitive_regs(emif, emif-curr_regs);
+   do_freq_update();
+   }
+
+handled:
+   return IRQ_HANDLED;
+thread:
+   return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t emif_interrupt_handler(int irq, void *dev_id)
+{
+   u32 interrupts;
+   struct emif_data*emif = dev_id;
+   void __iomem*base = emif-base;
+   struct device   *dev = emif-dev;
+   irqreturn_t ret = IRQ_HANDLED;
+
+   /* Save the status and clear it */
+