From 9f7345b7a7cbf4c78a8161cba21de1772d5ad56e Mon Sep 17 00:00:00 2001 From: Hiroshi Doyu Date: Thu, 14 Mar 2013 11:12:10 +0200 Subject: memory: tegra30: Fix build error w/o PM Make this depend on CONFIG_PM. Signed-off-by: Hiroshi Doyu Reviewed-by: Thierry Reding Signed-off-by: Greg Kroah-Hartman --- drivers/memory/tegra30-mc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/memory') diff --git a/drivers/memory/tegra30-mc.c b/drivers/memory/tegra30-mc.c index 0b975986777d..f4ae074badc3 100644 --- a/drivers/memory/tegra30-mc.c +++ b/drivers/memory/tegra30-mc.c @@ -268,6 +268,7 @@ static const u32 tegra30_mc_ctx[] = { MC_INTMASK, }; +#ifdef CONFIG_PM static int tegra30_mc_suspend(struct device *dev) { int i; @@ -291,6 +292,7 @@ static int tegra30_mc_resume(struct device *dev) mc_readl(mc, MC_TIMING_CONTROL); return 0; } +#endif static UNIVERSAL_DEV_PM_OPS(tegra30_mc_pm, tegra30_mc_suspend, -- cgit v1.2.3 From 7a4541a6591d8b0f6d095ffd94c8ebae75ea57d7 Mon Sep 17 00:00:00 2001 From: Fabio Porcedda Date: Thu, 14 Mar 2013 18:09:35 +0100 Subject: drivers: memory: use module_platform_driver_probe() This patch converts the drivers to use the module_platform_driver_probe() macro which makes the code smaller and a bit simpler. Signed-off-by: Fabio Porcedda Cc: Benoit Cousson Cc: Aneesh V Signed-off-by: Greg Kroah-Hartman --- drivers/memory/emif.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'drivers/memory') diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c index df0873694858..ecbc1a996eb6 100644 --- a/drivers/memory/emif.c +++ b/drivers/memory/emif.c @@ -1841,18 +1841,8 @@ static struct platform_driver emif_driver = { }, }; -static int __init_or_module emif_register(void) -{ - return platform_driver_probe(&emif_driver, emif_probe); -} - -static void __exit emif_unregister(void) -{ - platform_driver_unregister(&emif_driver); -} +module_platform_driver_probe(emif_driver, emif_probe); -module_init(emif_register); -module_exit(emif_unregister); MODULE_DESCRIPTION("TI EMIF SDRAM Controller Driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:emif"); -- cgit v1.2.3 From 0a5f19cf303ea9cc9bf89a42960a69db4ea3c35b Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Sat, 16 Mar 2013 11:46:41 +0530 Subject: memory: emif: Fix the lpmode timeout calculation The driver tries to round up the specified timeout cycles to the next power of 2 value. This should be done defore updating timeout variable. Correcting this here. Reported-by: Nishanth Menon Signed-off-by: Lokesh Vutla Acked-by: Santosh Shilimkar Signed-off-by: Greg Kroah-Hartman --- drivers/memory/emif.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/memory') diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c index ecbc1a996eb6..897c39a8db86 100644 --- a/drivers/memory/emif.c +++ b/drivers/memory/emif.c @@ -728,13 +728,17 @@ static u32 get_pwr_mgmt_ctrl(u32 freq, struct emif_data *emif, u32 ip_rev) /* Timeout based on DDR frequency */ timeout = freq >= freq_threshold ? timeout_perf : timeout_pwr; - /* The value to be set in register is "log2(timeout) - 3" */ + /* + * The value to be set in register is "log2(timeout) - 3" + * if timeout < 16 load 0 in register + * if timeout is not a power of 2, round to next highest power of 2 + */ if (timeout < 16) { timeout = 0; } else { - timeout = __fls(timeout) - 3; if (timeout & (timeout - 1)) - timeout++; + timeout <<= 1; + timeout = __fls(timeout) - 3; } switch (lpmode) { -- cgit v1.2.3 From 9ea03dec380208bfee015b25f253c2f58aba0071 Mon Sep 17 00:00:00 2001 From: Ambresh K Date: Sat, 16 Mar 2013 11:46:42 +0530 Subject: memory: emif: setup LP settings on freq update Program the power management shadow register on freq update Else the concept of threshold frequencies dont really matter as the system always uses the performance mode timing for LP which is programmed in at init time. Signed-off-by: Nishanth Menon Signed-off-by: Ambresh K Signed-off-by: Lokesh Vutla Acked-by: Santosh Shilimkar Signed-off-by: Greg Kroah-Hartman --- drivers/memory/emif.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/memory') diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c index 897c39a8db86..bda11ebb25cd 100644 --- a/drivers/memory/emif.c +++ b/drivers/memory/emif.c @@ -819,6 +819,8 @@ static void setup_registers(struct emif_data *emif, struct emif_regs *regs) writel(regs->sdram_tim2_shdw, base + EMIF_SDRAM_TIMING_2_SHDW); writel(regs->phy_ctrl_1_shdw, base + EMIF_DDR_PHY_CTRL_1_SHDW); + writel(regs->pwr_mgmt_ctrl_shdw, + base + EMIF_POWER_MANAGEMENT_CTRL_SHDW); /* Settings specific for EMIF4D5 */ if (emif->plat_data->ip_rev != EMIF_4D5) -- cgit v1.2.3 From 25aaacd2834233bbfa2b7ec697bfce42707e35b7 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Sat, 16 Mar 2013 11:46:43 +0530 Subject: memory: emif: handle overflow for timing for LP mode In case the custom timings provide values which overflow the maximum possible field value, warn and use maximum permissible value. Signed-off-by: Nishanth Menon Signed-off-by: Lokesh Vutla Acked-by: Santosh Shilimkar Signed-off-by: Greg Kroah-Hartman --- drivers/memory/emif.c | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) (limited to 'drivers/memory') diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c index bda11ebb25cd..249222905c94 100644 --- a/drivers/memory/emif.c +++ b/drivers/memory/emif.c @@ -715,6 +715,8 @@ static u32 get_pwr_mgmt_ctrl(u32 freq, struct emif_data *emif, u32 ip_rev) u32 timeout_perf = EMIF_LP_MODE_TIMEOUT_PERFORMANCE; u32 timeout_pwr = EMIF_LP_MODE_TIMEOUT_POWER; u32 freq_threshold = EMIF_LP_MODE_FREQ_THRESHOLD; + u32 mask; + u8 shift; struct emif_custom_configs *cust_cfgs = emif->plat_data->custom_configs; @@ -743,27 +745,45 @@ static u32 get_pwr_mgmt_ctrl(u32 freq, struct emif_data *emif, u32 ip_rev) switch (lpmode) { case EMIF_LP_MODE_CLOCK_STOP: - pwr_mgmt_ctrl = (timeout << CS_TIM_SHIFT) | - SR_TIM_MASK | PD_TIM_MASK; + shift = CS_TIM_SHIFT; + mask = CS_TIM_MASK; break; case EMIF_LP_MODE_SELF_REFRESH: /* Workaround for errata i735 */ if (timeout < 6) timeout = 6; - pwr_mgmt_ctrl = (timeout << SR_TIM_SHIFT) | - CS_TIM_MASK | PD_TIM_MASK; + shift = SR_TIM_SHIFT; + mask = SR_TIM_MASK; break; case EMIF_LP_MODE_PWR_DN: - pwr_mgmt_ctrl = (timeout << PD_TIM_SHIFT) | - CS_TIM_MASK | SR_TIM_MASK; + shift = PD_TIM_SHIFT; + mask = PD_TIM_MASK; break; case EMIF_LP_MODE_DISABLE: default: - pwr_mgmt_ctrl = CS_TIM_MASK | - PD_TIM_MASK | SR_TIM_MASK; + mask = 0; + shift = 0; + break; + } + /* Round to maximum in case of overflow, BUT warn! */ + if (lpmode != EMIF_LP_MODE_DISABLE && timeout > mask >> shift) { + pr_err("TIMEOUT Overflow - lpmode=%d perf=%d pwr=%d freq=%d\n", + lpmode, + timeout_perf, + timeout_pwr, + freq_threshold); + WARN(1, "timeout=0x%02x greater than 0x%02x. Using max\n", + timeout, mask >> shift); + timeout = mask >> shift; } + /* Setup required timing */ + pwr_mgmt_ctrl = (timeout << shift) & mask; + /* setup a default mask for rest of the modes */ + pwr_mgmt_ctrl |= (SR_TIM_MASK | CS_TIM_MASK | PD_TIM_MASK) & + ~mask; + /* No CS_TIM in EMIF_4D5 */ if (ip_rev == EMIF_4D5) pwr_mgmt_ctrl &= ~CS_TIM_MASK; -- cgit v1.2.3 From f91a595d0b813c3a2f3b848c165e865ca4c5b8cc Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Sat, 16 Mar 2013 11:46:44 +0530 Subject: memory: emif: Handle devices which are not rated for >85C As per JESD209-2E specification for LPDDR2, http://www.jedec.org/standards-documents/results/jesd209-2E Table 73, LPDDR2 memories come in two flavors - Standard and Extended. The Standard types can operate from -25C to +85C However, beyond that and upto +105C can only be supported by Extended types. Unfortunately, it seems there is no info in MR0(device info) or MR[1,2](device feature) for run time detection of this capability as far as seen on the spec. Hence, we provide a custom_config flag to be populated by platforms which have these "extended" type memories. For the "Standard" memories, we need to consider MR4 notifications of temperature triggers >85C as equivalent to thermal shutdown events (equivalent to Spec specified thermal shutdown events for "extended" parts). Reported-by: Richard Woodruff Signed-off-by: Nishanth Menon Signed-off-by: Lokesh Vutla Acked-by: Santosh Shilimkar Signed-off-by: Greg Kroah-Hartman --- drivers/memory/emif.c | 27 +++++++++++++++++++++++++++ include/linux/platform_data/emif_plat.h | 1 + 2 files changed, 28 insertions(+) (limited to 'drivers/memory') diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c index 249222905c94..96add5b9ce5d 100644 --- a/drivers/memory/emif.c +++ b/drivers/memory/emif.c @@ -918,6 +918,7 @@ static irqreturn_t handle_temp_alert(void __iomem *base, struct emif_data *emif) { u32 old_temp_level; irqreturn_t ret = IRQ_HANDLED; + struct emif_custom_configs *custom_configs; spin_lock_irqsave(&emif_lock, irq_state); old_temp_level = emif->temperature_level; @@ -930,6 +931,29 @@ static irqreturn_t handle_temp_alert(void __iomem *base, struct emif_data *emif) goto out; } + custom_configs = emif->plat_data->custom_configs; + + /* + * IF we detect higher than "nominal rating" from DDR sensor + * on an unsupported DDR part, shutdown system + */ + if (custom_configs && !(custom_configs->mask & + EMIF_CUSTOM_CONFIG_EXTENDED_TEMP_PART)) { + if (emif->temperature_level >= SDRAM_TEMP_HIGH_DERATE_REFRESH) { + dev_err(emif->dev, + "%s:NOT Extended temperature capable memory." + "Converting MR4=0x%02x as shutdown event\n", + __func__, emif->temperature_level); + /* + * Temperature far too high - do kernel_power_off() + * from thread context + */ + emif->temperature_level = SDRAM_TEMP_VERY_HIGH_SHUTDOWN; + ret = IRQ_WAKE_THREAD; + goto out; + } + } + if (emif->temperature_level < old_temp_level || emif->temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN) { /* @@ -1228,6 +1252,9 @@ static void __init_or_module of_get_custom_configs(struct device_node *np_emif, cust_cfgs->temp_alert_poll_interval_ms = *poll_intvl; } + if (of_find_property(np_emif, "extended-temp-part", &len)) + cust_cfgs->mask |= EMIF_CUSTOM_CONFIG_EXTENDED_TEMP_PART; + if (!is_custom_config_valid(cust_cfgs, emif->dev)) { devm_kfree(emif->dev, cust_cfgs); return; diff --git a/include/linux/platform_data/emif_plat.h b/include/linux/platform_data/emif_plat.h index 03378ca84061..5c19a2a647c4 100644 --- a/include/linux/platform_data/emif_plat.h +++ b/include/linux/platform_data/emif_plat.h @@ -40,6 +40,7 @@ /* Custom config requests */ #define EMIF_CUSTOM_CONFIG_LPMODE 0x00000001 #define EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL 0x00000002 +#define EMIF_CUSTOM_CONFIG_EXTENDED_TEMP_PART 0x00000004 #ifndef __ASSEMBLY__ /** -- cgit v1.2.3 From 2553e32ae200210801dd3e3f58dd23169356c9d6 Mon Sep 17 00:00:00 2001 From: Nishanth Menon Date: Sat, 16 Mar 2013 11:46:45 +0530 Subject: memory: emif: use restart if power_off not present when out of spec Some machine or kernel variants might have missed implementation of power off handlers. We DONOT want to let the system be in "out of spec" state in this condition. So, WARN and attempt a machine restart in the hopes of clearing the out-of-spec temperature condition. NOTE: This is not the safest option, but safer than leaving the system in unstable conditions. Signed-off-by: Nishanth Menon Signed-off-by: Lokesh Vutla Acked-by: Santosh Shilimkar Signed-off-by: Greg Kroah-Hartman --- drivers/memory/emif.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers/memory') diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c index 96add5b9ce5d..b2bb27261c73 100644 --- a/drivers/memory/emif.c +++ b/drivers/memory/emif.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include "emif.h" #include "of_memory.h" @@ -1015,7 +1016,14 @@ static irqreturn_t emif_threaded_isr(int irq, void *dev_id) if (emif->temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN) { dev_emerg(emif->dev, "SDRAM temperature exceeds operating limit.. Needs shut down!!!\n"); - kernel_power_off(); + + /* If we have Power OFF ability, use it, else try restarting */ + if (pm_power_off) { + kernel_power_off(); + } else { + WARN(1, "FIXME: NO pm_power_off!!! trying restart\n"); + kernel_restart("SDRAM Over-temp Emergency restart"); + } return IRQ_HANDLED; } -- cgit v1.2.3 From 36caf3e525b24556f649aecd097cad73bde6f035 Mon Sep 17 00:00:00 2001 From: Oleksandr Dmytryshyn Date: Sat, 16 Mar 2013 11:46:46 +0530 Subject: memory: emif: Fix the incorrect 'size' parameter in memcpy The issue was that only the first timings table was added to the emif platform data at the emif driver registration. All other timings tables was filled with zeros. Now all emif timings table are added to the platform data. Signed-off-by: Oleksandr Dmytryshyn Signed-off-by: Lokesh Vutla Acked-by: Santosh Shilimkar Signed-off-by: Greg Kroah-Hartman --- drivers/memory/emif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/memory') diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c index b2bb27261c73..9335339ebfdf 100644 --- a/drivers/memory/emif.c +++ b/drivers/memory/emif.c @@ -1468,7 +1468,7 @@ static struct emif_data *__init_or_module get_device_details( if (pd->timings) { temp = devm_kzalloc(dev, size, GFP_KERNEL); if (temp) { - memcpy(temp, pd->timings, sizeof(*pd->timings)); + memcpy(temp, pd->timings, size); pd->timings = temp; } else { dev_warn(dev, "%s:%d: allocation error\n", __func__, -- cgit v1.2.3 From f02503b2ff73d3b09ca27335304611a206d2b54a Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Sat, 16 Mar 2013 11:46:47 +0530 Subject: memory: emif: errata i743: Prohibit usage of Power-Down mode ERRATA DESCRIPTION : The EMIF supports power-down state for low power. The EMIF automatically puts the SDRAM into power-down after the memory is not accessed for a defined number of cycles and the EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE bit field is set to 0x4. As the EMIF supports automatic output impedance calibration, a ZQ calibration long command is issued every time it exits active power-down and precharge power-down modes. The EMIF waits and blocks any other command during this calibration. The EMIF does not allow selective disabling of ZQ calibration upon exit of power-down mode. Due to very short periods of power-down cycles, ZQ calibration overhead creates bandwidth issues and increases overall system power consumption. On the other hand, issuing ZQ calibration long commands when exiting self-refresh is still required. WORKAROUND : Because there is no power consumption benefit of the power-down due to the calibration and there is a performance risk, the guideline is to not allow power-down state and, therefore, to not have set the EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE bit field to 0x4. This is applicable only for EMIF4D IP used in OMAP4 Soc's. Signed-off-by: Grygorii Strashko Signed-off-by: Vitaly Chernooky Signed-off-by: Oleksandr Dmytryshyn Signed-off-by: Lokesh Vutla Acked-by: Santosh Shilimkar Signed-off-by: Greg Kroah-Hartman --- drivers/memory/emif.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'drivers/memory') diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c index 9335339ebfdf..bd223c7c3e72 100644 --- a/drivers/memory/emif.c +++ b/drivers/memory/emif.c @@ -257,6 +257,41 @@ static void set_lpmode(struct emif_data *emif, u8 lpmode) u32 temp; void __iomem *base = emif->base; + /* + * Workaround for errata i743 - LPDDR2 Power-Down State is Not + * Efficient + * + * i743 DESCRIPTION: + * The EMIF supports power-down state for low power. The EMIF + * automatically puts the SDRAM into power-down after the memory is + * not accessed for a defined number of cycles and the + * EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE bit field is set to 0x4. + * As the EMIF supports automatic output impedance calibration, a ZQ + * calibration long command is issued every time it exits active + * power-down and precharge power-down modes. The EMIF waits and + * blocks any other command during this calibration. + * The EMIF does not allow selective disabling of ZQ calibration upon + * exit of power-down mode. Due to very short periods of power-down + * cycles, ZQ calibration overhead creates bandwidth issues and + * increases overall system power consumption. On the other hand, + * issuing ZQ calibration long commands when exiting self-refresh is + * still required. + * + * WORKAROUND + * Because there is no power consumption benefit of the power-down due + * to the calibration and there is a performance risk, the guideline + * is to not allow power-down state and, therefore, to not have set + * the EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE bit field to 0x4. + */ + if ((emif->plat_data->ip_rev == EMIF_4D) && + (EMIF_LP_MODE_PWR_DN == lpmode)) { + WARN_ONCE(1, + "REG_LP_MODE = LP_MODE_PWR_DN(4) is prohibited by" + "erratum i743 switch to LP_MODE_SELF_REFRESH(2)\n"); + /* rollback LP_MODE to Self-refresh mode */ + lpmode = EMIF_LP_MODE_SELF_REFRESH; + } + temp = readl(base + EMIF_POWER_MANAGEMENT_CONTROL); temp &= ~LP_MODE_MASK; temp |= (lpmode << LP_MODE_SHIFT); -- cgit v1.2.3 From f57f27bc6ed7106276004dd224aaeeb160a5b4b8 Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Sat, 16 Mar 2013 11:46:48 +0530 Subject: memory: emif: Load the correct custom config values from dt of_get_property returns value in Big Endian format. Before using this value it should be converted to little endian using be32_to_cpup(). Custom configs of emif are read from dt using of_get_property, but these are not converted to litte endian format. Correcting the same here. Signed-off-by: Lokesh Vutla Acked-by: Santosh Shilimkar Signed-off-by: Greg Kroah-Hartman --- drivers/memory/emif.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/memory') diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c index bd223c7c3e72..cadf1cc19aaf 100644 --- a/drivers/memory/emif.c +++ b/drivers/memory/emif.c @@ -1263,7 +1263,7 @@ static void __init_or_module of_get_custom_configs(struct device_node *np_emif, { struct emif_custom_configs *cust_cfgs = NULL; int len; - const int *lpmode, *poll_intvl; + const __be32 *lpmode, *poll_intvl; lpmode = of_get_property(np_emif, "low-power-mode", &len); poll_intvl = of_get_property(np_emif, "temp-alert-poll-interval", &len); @@ -1277,7 +1277,7 @@ static void __init_or_module of_get_custom_configs(struct device_node *np_emif, if (lpmode) { cust_cfgs->mask |= EMIF_CUSTOM_CONFIG_LPMODE; - cust_cfgs->lpmode = *lpmode; + cust_cfgs->lpmode = be32_to_cpup(lpmode); of_property_read_u32(np_emif, "low-power-mode-timeout-performance", &cust_cfgs->lpmode_timeout_performance); @@ -1292,7 +1292,8 @@ static void __init_or_module of_get_custom_configs(struct device_node *np_emif, if (poll_intvl) { cust_cfgs->mask |= EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL; - cust_cfgs->temp_alert_poll_interval_ms = *poll_intvl; + cust_cfgs->temp_alert_poll_interval_ms = + be32_to_cpup(poll_intvl); } if (of_find_property(np_emif, "extended-temp-part", &len)) -- cgit v1.2.3