diff options
Diffstat (limited to 'drivers/memory/emif.c')
-rw-r--r-- | drivers/memory/emif.c | 141 |
1 files changed, 114 insertions, 27 deletions
diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c index df0873694858..cadf1cc19aaf 100644 --- a/drivers/memory/emif.c +++ b/drivers/memory/emif.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/list.h> | 26 | #include <linux/list.h> |
27 | #include <linux/spinlock.h> | 27 | #include <linux/spinlock.h> |
28 | #include <linux/pm.h> | ||
28 | #include <memory/jedec_ddr.h> | 29 | #include <memory/jedec_ddr.h> |
29 | #include "emif.h" | 30 | #include "emif.h" |
30 | #include "of_memory.h" | 31 | #include "of_memory.h" |
@@ -256,6 +257,41 @@ static void set_lpmode(struct emif_data *emif, u8 lpmode) | |||
256 | u32 temp; | 257 | u32 temp; |
257 | void __iomem *base = emif->base; | 258 | void __iomem *base = emif->base; |
258 | 259 | ||
260 | /* | ||
261 | * Workaround for errata i743 - LPDDR2 Power-Down State is Not | ||
262 | * Efficient | ||
263 | * | ||
264 | * i743 DESCRIPTION: | ||
265 | * The EMIF supports power-down state for low power. The EMIF | ||
266 | * automatically puts the SDRAM into power-down after the memory is | ||
267 | * not accessed for a defined number of cycles and the | ||
268 | * EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE bit field is set to 0x4. | ||
269 | * As the EMIF supports automatic output impedance calibration, a ZQ | ||
270 | * calibration long command is issued every time it exits active | ||
271 | * power-down and precharge power-down modes. The EMIF waits and | ||
272 | * blocks any other command during this calibration. | ||
273 | * The EMIF does not allow selective disabling of ZQ calibration upon | ||
274 | * exit of power-down mode. Due to very short periods of power-down | ||
275 | * cycles, ZQ calibration overhead creates bandwidth issues and | ||
276 | * increases overall system power consumption. On the other hand, | ||
277 | * issuing ZQ calibration long commands when exiting self-refresh is | ||
278 | * still required. | ||
279 | * | ||
280 | * WORKAROUND | ||
281 | * Because there is no power consumption benefit of the power-down due | ||
282 | * to the calibration and there is a performance risk, the guideline | ||
283 | * is to not allow power-down state and, therefore, to not have set | ||
284 | * the EMIF_PWR_MGMT_CTRL[10:8] REG_LP_MODE bit field to 0x4. | ||
285 | */ | ||
286 | if ((emif->plat_data->ip_rev == EMIF_4D) && | ||
287 | (EMIF_LP_MODE_PWR_DN == lpmode)) { | ||
288 | WARN_ONCE(1, | ||
289 | "REG_LP_MODE = LP_MODE_PWR_DN(4) is prohibited by" | ||
290 | "erratum i743 switch to LP_MODE_SELF_REFRESH(2)\n"); | ||
291 | /* rollback LP_MODE to Self-refresh mode */ | ||
292 | lpmode = EMIF_LP_MODE_SELF_REFRESH; | ||
293 | } | ||
294 | |||
259 | temp = readl(base + EMIF_POWER_MANAGEMENT_CONTROL); | 295 | temp = readl(base + EMIF_POWER_MANAGEMENT_CONTROL); |
260 | temp &= ~LP_MODE_MASK; | 296 | temp &= ~LP_MODE_MASK; |
261 | temp |= (lpmode << LP_MODE_SHIFT); | 297 | temp |= (lpmode << LP_MODE_SHIFT); |
@@ -715,6 +751,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; | 751 | u32 timeout_perf = EMIF_LP_MODE_TIMEOUT_PERFORMANCE; |
716 | u32 timeout_pwr = EMIF_LP_MODE_TIMEOUT_POWER; | 752 | u32 timeout_pwr = EMIF_LP_MODE_TIMEOUT_POWER; |
717 | u32 freq_threshold = EMIF_LP_MODE_FREQ_THRESHOLD; | 753 | u32 freq_threshold = EMIF_LP_MODE_FREQ_THRESHOLD; |
754 | u32 mask; | ||
755 | u8 shift; | ||
718 | 756 | ||
719 | struct emif_custom_configs *cust_cfgs = emif->plat_data->custom_configs; | 757 | struct emif_custom_configs *cust_cfgs = emif->plat_data->custom_configs; |
720 | 758 | ||
@@ -728,37 +766,59 @@ static u32 get_pwr_mgmt_ctrl(u32 freq, struct emif_data *emif, u32 ip_rev) | |||
728 | /* Timeout based on DDR frequency */ | 766 | /* Timeout based on DDR frequency */ |
729 | timeout = freq >= freq_threshold ? timeout_perf : timeout_pwr; | 767 | timeout = freq >= freq_threshold ? timeout_perf : timeout_pwr; |
730 | 768 | ||
731 | /* The value to be set in register is "log2(timeout) - 3" */ | 769 | /* |
770 | * The value to be set in register is "log2(timeout) - 3" | ||
771 | * if timeout < 16 load 0 in register | ||
772 | * if timeout is not a power of 2, round to next highest power of 2 | ||
773 | */ | ||
732 | if (timeout < 16) { | 774 | if (timeout < 16) { |
733 | timeout = 0; | 775 | timeout = 0; |
734 | } else { | 776 | } else { |
735 | timeout = __fls(timeout) - 3; | ||
736 | if (timeout & (timeout - 1)) | 777 | if (timeout & (timeout - 1)) |
737 | timeout++; | 778 | timeout <<= 1; |
779 | timeout = __fls(timeout) - 3; | ||
738 | } | 780 | } |
739 | 781 | ||
740 | switch (lpmode) { | 782 | switch (lpmode) { |
741 | case EMIF_LP_MODE_CLOCK_STOP: | 783 | case EMIF_LP_MODE_CLOCK_STOP: |
742 | pwr_mgmt_ctrl = (timeout << CS_TIM_SHIFT) | | 784 | shift = CS_TIM_SHIFT; |
743 | SR_TIM_MASK | PD_TIM_MASK; | 785 | mask = CS_TIM_MASK; |
744 | break; | 786 | break; |
745 | case EMIF_LP_MODE_SELF_REFRESH: | 787 | case EMIF_LP_MODE_SELF_REFRESH: |
746 | /* Workaround for errata i735 */ | 788 | /* Workaround for errata i735 */ |
747 | if (timeout < 6) | 789 | if (timeout < 6) |
748 | timeout = 6; | 790 | timeout = 6; |
749 | 791 | ||
750 | pwr_mgmt_ctrl = (timeout << SR_TIM_SHIFT) | | 792 | shift = SR_TIM_SHIFT; |
751 | CS_TIM_MASK | PD_TIM_MASK; | 793 | mask = SR_TIM_MASK; |
752 | break; | 794 | break; |
753 | case EMIF_LP_MODE_PWR_DN: | 795 | case EMIF_LP_MODE_PWR_DN: |
754 | pwr_mgmt_ctrl = (timeout << PD_TIM_SHIFT) | | 796 | shift = PD_TIM_SHIFT; |
755 | CS_TIM_MASK | SR_TIM_MASK; | 797 | mask = PD_TIM_MASK; |
756 | break; | 798 | break; |
757 | case EMIF_LP_MODE_DISABLE: | 799 | case EMIF_LP_MODE_DISABLE: |
758 | default: | 800 | default: |
759 | pwr_mgmt_ctrl = CS_TIM_MASK | | 801 | mask = 0; |
760 | PD_TIM_MASK | SR_TIM_MASK; | 802 | shift = 0; |
803 | break; | ||
761 | } | 804 | } |
805 | /* Round to maximum in case of overflow, BUT warn! */ | ||
806 | if (lpmode != EMIF_LP_MODE_DISABLE && timeout > mask >> shift) { | ||
807 | pr_err("TIMEOUT Overflow - lpmode=%d perf=%d pwr=%d freq=%d\n", | ||
808 | lpmode, | ||
809 | timeout_perf, | ||
810 | timeout_pwr, | ||
811 | freq_threshold); | ||
812 | WARN(1, "timeout=0x%02x greater than 0x%02x. Using max\n", | ||
813 | timeout, mask >> shift); | ||
814 | timeout = mask >> shift; | ||
815 | } | ||
816 | |||
817 | /* Setup required timing */ | ||
818 | pwr_mgmt_ctrl = (timeout << shift) & mask; | ||
819 | /* setup a default mask for rest of the modes */ | ||
820 | pwr_mgmt_ctrl |= (SR_TIM_MASK | CS_TIM_MASK | PD_TIM_MASK) & | ||
821 | ~mask; | ||
762 | 822 | ||
763 | /* No CS_TIM in EMIF_4D5 */ | 823 | /* No CS_TIM in EMIF_4D5 */ |
764 | if (ip_rev == EMIF_4D5) | 824 | if (ip_rev == EMIF_4D5) |
@@ -815,6 +875,8 @@ static void setup_registers(struct emif_data *emif, struct emif_regs *regs) | |||
815 | 875 | ||
816 | writel(regs->sdram_tim2_shdw, base + EMIF_SDRAM_TIMING_2_SHDW); | 876 | writel(regs->sdram_tim2_shdw, base + EMIF_SDRAM_TIMING_2_SHDW); |
817 | writel(regs->phy_ctrl_1_shdw, base + EMIF_DDR_PHY_CTRL_1_SHDW); | 877 | writel(regs->phy_ctrl_1_shdw, base + EMIF_DDR_PHY_CTRL_1_SHDW); |
878 | writel(regs->pwr_mgmt_ctrl_shdw, | ||
879 | base + EMIF_POWER_MANAGEMENT_CTRL_SHDW); | ||
818 | 880 | ||
819 | /* Settings specific for EMIF4D5 */ | 881 | /* Settings specific for EMIF4D5 */ |
820 | if (emif->plat_data->ip_rev != EMIF_4D5) | 882 | if (emif->plat_data->ip_rev != EMIF_4D5) |
@@ -892,6 +954,7 @@ static irqreturn_t handle_temp_alert(void __iomem *base, struct emif_data *emif) | |||
892 | { | 954 | { |
893 | u32 old_temp_level; | 955 | u32 old_temp_level; |
894 | irqreturn_t ret = IRQ_HANDLED; | 956 | irqreturn_t ret = IRQ_HANDLED; |
957 | struct emif_custom_configs *custom_configs; | ||
895 | 958 | ||
896 | spin_lock_irqsave(&emif_lock, irq_state); | 959 | spin_lock_irqsave(&emif_lock, irq_state); |
897 | old_temp_level = emif->temperature_level; | 960 | old_temp_level = emif->temperature_level; |
@@ -904,6 +967,29 @@ static irqreturn_t handle_temp_alert(void __iomem *base, struct emif_data *emif) | |||
904 | goto out; | 967 | goto out; |
905 | } | 968 | } |
906 | 969 | ||
970 | custom_configs = emif->plat_data->custom_configs; | ||
971 | |||
972 | /* | ||
973 | * IF we detect higher than "nominal rating" from DDR sensor | ||
974 | * on an unsupported DDR part, shutdown system | ||
975 | */ | ||
976 | if (custom_configs && !(custom_configs->mask & | ||
977 | EMIF_CUSTOM_CONFIG_EXTENDED_TEMP_PART)) { | ||
978 | if (emif->temperature_level >= SDRAM_TEMP_HIGH_DERATE_REFRESH) { | ||
979 | dev_err(emif->dev, | ||
980 | "%s:NOT Extended temperature capable memory." | ||
981 | "Converting MR4=0x%02x as shutdown event\n", | ||
982 | __func__, emif->temperature_level); | ||
983 | /* | ||
984 | * Temperature far too high - do kernel_power_off() | ||
985 | * from thread context | ||
986 | */ | ||
987 | emif->temperature_level = SDRAM_TEMP_VERY_HIGH_SHUTDOWN; | ||
988 | ret = IRQ_WAKE_THREAD; | ||
989 | goto out; | ||
990 | } | ||
991 | } | ||
992 | |||
907 | if (emif->temperature_level < old_temp_level || | 993 | if (emif->temperature_level < old_temp_level || |
908 | emif->temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN) { | 994 | emif->temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN) { |
909 | /* | 995 | /* |
@@ -965,7 +1051,14 @@ static irqreturn_t emif_threaded_isr(int irq, void *dev_id) | |||
965 | 1051 | ||
966 | if (emif->temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN) { | 1052 | if (emif->temperature_level == SDRAM_TEMP_VERY_HIGH_SHUTDOWN) { |
967 | dev_emerg(emif->dev, "SDRAM temperature exceeds operating limit.. Needs shut down!!!\n"); | 1053 | dev_emerg(emif->dev, "SDRAM temperature exceeds operating limit.. Needs shut down!!!\n"); |
968 | kernel_power_off(); | 1054 | |
1055 | /* If we have Power OFF ability, use it, else try restarting */ | ||
1056 | if (pm_power_off) { | ||
1057 | kernel_power_off(); | ||
1058 | } else { | ||
1059 | WARN(1, "FIXME: NO pm_power_off!!! trying restart\n"); | ||
1060 | kernel_restart("SDRAM Over-temp Emergency restart"); | ||
1061 | } | ||
969 | return IRQ_HANDLED; | 1062 | return IRQ_HANDLED; |
970 | } | 1063 | } |
971 | 1064 | ||
@@ -1170,7 +1263,7 @@ static void __init_or_module of_get_custom_configs(struct device_node *np_emif, | |||
1170 | { | 1263 | { |
1171 | struct emif_custom_configs *cust_cfgs = NULL; | 1264 | struct emif_custom_configs *cust_cfgs = NULL; |
1172 | int len; | 1265 | int len; |
1173 | const int *lpmode, *poll_intvl; | 1266 | const __be32 *lpmode, *poll_intvl; |
1174 | 1267 | ||
1175 | lpmode = of_get_property(np_emif, "low-power-mode", &len); | 1268 | lpmode = of_get_property(np_emif, "low-power-mode", &len); |
1176 | poll_intvl = of_get_property(np_emif, "temp-alert-poll-interval", &len); | 1269 | poll_intvl = of_get_property(np_emif, "temp-alert-poll-interval", &len); |
@@ -1184,7 +1277,7 @@ static void __init_or_module of_get_custom_configs(struct device_node *np_emif, | |||
1184 | 1277 | ||
1185 | if (lpmode) { | 1278 | if (lpmode) { |
1186 | cust_cfgs->mask |= EMIF_CUSTOM_CONFIG_LPMODE; | 1279 | cust_cfgs->mask |= EMIF_CUSTOM_CONFIG_LPMODE; |
1187 | cust_cfgs->lpmode = *lpmode; | 1280 | cust_cfgs->lpmode = be32_to_cpup(lpmode); |
1188 | of_property_read_u32(np_emif, | 1281 | of_property_read_u32(np_emif, |
1189 | "low-power-mode-timeout-performance", | 1282 | "low-power-mode-timeout-performance", |
1190 | &cust_cfgs->lpmode_timeout_performance); | 1283 | &cust_cfgs->lpmode_timeout_performance); |
@@ -1199,9 +1292,13 @@ static void __init_or_module of_get_custom_configs(struct device_node *np_emif, | |||
1199 | if (poll_intvl) { | 1292 | if (poll_intvl) { |
1200 | cust_cfgs->mask |= | 1293 | cust_cfgs->mask |= |
1201 | EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL; | 1294 | EMIF_CUSTOM_CONFIG_TEMP_ALERT_POLL_INTERVAL; |
1202 | cust_cfgs->temp_alert_poll_interval_ms = *poll_intvl; | 1295 | cust_cfgs->temp_alert_poll_interval_ms = |
1296 | be32_to_cpup(poll_intvl); | ||
1203 | } | 1297 | } |
1204 | 1298 | ||
1299 | if (of_find_property(np_emif, "extended-temp-part", &len)) | ||
1300 | cust_cfgs->mask |= EMIF_CUSTOM_CONFIG_EXTENDED_TEMP_PART; | ||
1301 | |||
1205 | if (!is_custom_config_valid(cust_cfgs, emif->dev)) { | 1302 | if (!is_custom_config_valid(cust_cfgs, emif->dev)) { |
1206 | devm_kfree(emif->dev, cust_cfgs); | 1303 | devm_kfree(emif->dev, cust_cfgs); |
1207 | return; | 1304 | return; |
@@ -1407,7 +1504,7 @@ static struct emif_data *__init_or_module get_device_details( | |||
1407 | if (pd->timings) { | 1504 | if (pd->timings) { |
1408 | temp = devm_kzalloc(dev, size, GFP_KERNEL); | 1505 | temp = devm_kzalloc(dev, size, GFP_KERNEL); |
1409 | if (temp) { | 1506 | if (temp) { |
1410 | memcpy(temp, pd->timings, sizeof(*pd->timings)); | 1507 | memcpy(temp, pd->timings, size); |
1411 | pd->timings = temp; | 1508 | pd->timings = temp; |
1412 | } else { | 1509 | } else { |
1413 | dev_warn(dev, "%s:%d: allocation error\n", __func__, | 1510 | dev_warn(dev, "%s:%d: allocation error\n", __func__, |
@@ -1841,18 +1938,8 @@ static struct platform_driver emif_driver = { | |||
1841 | }, | 1938 | }, |
1842 | }; | 1939 | }; |
1843 | 1940 | ||
1844 | static int __init_or_module emif_register(void) | 1941 | module_platform_driver_probe(emif_driver, emif_probe); |
1845 | { | ||
1846 | return platform_driver_probe(&emif_driver, emif_probe); | ||
1847 | } | ||
1848 | |||
1849 | static void __exit emif_unregister(void) | ||
1850 | { | ||
1851 | platform_driver_unregister(&emif_driver); | ||
1852 | } | ||
1853 | 1942 | ||
1854 | module_init(emif_register); | ||
1855 | module_exit(emif_unregister); | ||
1856 | MODULE_DESCRIPTION("TI EMIF SDRAM Controller Driver"); | 1943 | MODULE_DESCRIPTION("TI EMIF SDRAM Controller Driver"); |
1857 | MODULE_LICENSE("GPL"); | 1944 | MODULE_LICENSE("GPL"); |
1858 | MODULE_ALIAS("platform:emif"); | 1945 | MODULE_ALIAS("platform:emif"); |