diff options
author | Nishanth Menon <nm@ti.com> | 2013-03-16 02:16:43 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-03-25 16:18:12 -0400 |
commit | 25aaacd2834233bbfa2b7ec697bfce42707e35b7 (patch) | |
tree | b8352a0f79151e2255c5c9736fbcdf604bf9895d /drivers/memory | |
parent | 9ea03dec380208bfee015b25f253c2f58aba0071 (diff) |
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 <nm@ti.com>
Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/memory')
-rw-r--r-- | drivers/memory/emif.c | 36 |
1 files changed, 28 insertions, 8 deletions
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) | |||
715 | u32 timeout_perf = EMIF_LP_MODE_TIMEOUT_PERFORMANCE; | 715 | u32 timeout_perf = EMIF_LP_MODE_TIMEOUT_PERFORMANCE; |
716 | u32 timeout_pwr = EMIF_LP_MODE_TIMEOUT_POWER; | 716 | u32 timeout_pwr = EMIF_LP_MODE_TIMEOUT_POWER; |
717 | u32 freq_threshold = EMIF_LP_MODE_FREQ_THRESHOLD; | 717 | u32 freq_threshold = EMIF_LP_MODE_FREQ_THRESHOLD; |
718 | u32 mask; | ||
719 | u8 shift; | ||
718 | 720 | ||
719 | struct emif_custom_configs *cust_cfgs = emif->plat_data->custom_configs; | 721 | struct emif_custom_configs *cust_cfgs = emif->plat_data->custom_configs; |
720 | 722 | ||
@@ -743,27 +745,45 @@ static u32 get_pwr_mgmt_ctrl(u32 freq, struct emif_data *emif, u32 ip_rev) | |||
743 | 745 | ||
744 | switch (lpmode) { | 746 | switch (lpmode) { |
745 | case EMIF_LP_MODE_CLOCK_STOP: | 747 | case EMIF_LP_MODE_CLOCK_STOP: |
746 | pwr_mgmt_ctrl = (timeout << CS_TIM_SHIFT) | | 748 | shift = CS_TIM_SHIFT; |
747 | SR_TIM_MASK | PD_TIM_MASK; | 749 | mask = CS_TIM_MASK; |
748 | break; | 750 | break; |
749 | case EMIF_LP_MODE_SELF_REFRESH: | 751 | case EMIF_LP_MODE_SELF_REFRESH: |
750 | /* Workaround for errata i735 */ | 752 | /* Workaround for errata i735 */ |
751 | if (timeout < 6) | 753 | if (timeout < 6) |
752 | timeout = 6; | 754 | timeout = 6; |
753 | 755 | ||
754 | pwr_mgmt_ctrl = (timeout << SR_TIM_SHIFT) | | 756 | shift = SR_TIM_SHIFT; |
755 | CS_TIM_MASK | PD_TIM_MASK; | 757 | mask = SR_TIM_MASK; |
756 | break; | 758 | break; |
757 | case EMIF_LP_MODE_PWR_DN: | 759 | case EMIF_LP_MODE_PWR_DN: |
758 | pwr_mgmt_ctrl = (timeout << PD_TIM_SHIFT) | | 760 | shift = PD_TIM_SHIFT; |
759 | CS_TIM_MASK | SR_TIM_MASK; | 761 | mask = PD_TIM_MASK; |
760 | break; | 762 | break; |
761 | case EMIF_LP_MODE_DISABLE: | 763 | case EMIF_LP_MODE_DISABLE: |
762 | default: | 764 | default: |
763 | pwr_mgmt_ctrl = CS_TIM_MASK | | 765 | mask = 0; |
764 | PD_TIM_MASK | SR_TIM_MASK; | 766 | shift = 0; |
767 | break; | ||
768 | } | ||
769 | /* Round to maximum in case of overflow, BUT warn! */ | ||
770 | if (lpmode != EMIF_LP_MODE_DISABLE && timeout > mask >> shift) { | ||
771 | pr_err("TIMEOUT Overflow - lpmode=%d perf=%d pwr=%d freq=%d\n", | ||
772 | lpmode, | ||
773 | timeout_perf, | ||
774 | timeout_pwr, | ||
775 | freq_threshold); | ||
776 | WARN(1, "timeout=0x%02x greater than 0x%02x. Using max\n", | ||
777 | timeout, mask >> shift); | ||
778 | timeout = mask >> shift; | ||
765 | } | 779 | } |
766 | 780 | ||
781 | /* Setup required timing */ | ||
782 | pwr_mgmt_ctrl = (timeout << shift) & mask; | ||
783 | /* setup a default mask for rest of the modes */ | ||
784 | pwr_mgmt_ctrl |= (SR_TIM_MASK | CS_TIM_MASK | PD_TIM_MASK) & | ||
785 | ~mask; | ||
786 | |||
767 | /* No CS_TIM in EMIF_4D5 */ | 787 | /* No CS_TIM in EMIF_4D5 */ |
768 | if (ip_rev == EMIF_4D5) | 788 | if (ip_rev == EMIF_4D5) |
769 | pwr_mgmt_ctrl &= ~CS_TIM_MASK; | 789 | pwr_mgmt_ctrl &= ~CS_TIM_MASK; |