diff options
author | Olof Johansson <olof@lixom.net> | 2018-01-05 02:12:57 -0500 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2018-01-05 02:12:57 -0500 |
commit | 11077e9bf7fef8b1081221b482260a6bfa2b6d5f (patch) | |
tree | 9867459628434bb88338cdade7fb58ee2ec3a378 /drivers/memory | |
parent | 8102324d862f50360646da6391019b8d0ccaf76c (diff) | |
parent | aefc5818553680c50c9f6840e47c01b80edd9b3a (diff) |
Merge tag 'keystone_driver_soc_for_4.16' of git://git.kernel.org/pub/scm/linux/kernel/git/ssantosh/linux-keystone into next/drivers
SOC: Keystone Soc driver updates for 4.16
- TI EMIF-SRAM driver
- TI SCI print format fix
- Navigator strndup lenth fix
* tag 'keystone_driver_soc_for_4.16' of git://git.kernel.org/pub/scm/linux/kernel/git/ssantosh/linux-keystone:
soc: ti: fix max dup length for kstrndup
firmware: ti_sci: Use %zu for size_t print format
memory: ti-emif-sram: remove unused variable
memory: ti-emif-sram: introduce relocatable suspend/resume handlers
Documentation: dt: Update ti,emif bindings
Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'drivers/memory')
-rw-r--r-- | drivers/memory/Kconfig | 10 | ||||
-rw-r--r-- | drivers/memory/Makefile | 8 | ||||
-rw-r--r-- | drivers/memory/Makefile.asm-offsets | 5 | ||||
-rw-r--r-- | drivers/memory/emif-asm-offsets.c | 92 | ||||
-rw-r--r-- | drivers/memory/emif.h | 17 | ||||
-rw-r--r-- | drivers/memory/ti-emif-pm.c | 324 | ||||
-rw-r--r-- | drivers/memory/ti-emif-sram-pm.S | 334 |
7 files changed, 790 insertions, 0 deletions
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig index ffc350258041..19a0e83f260d 100644 --- a/drivers/memory/Kconfig +++ b/drivers/memory/Kconfig | |||
@@ -84,6 +84,16 @@ config OMAP_GPMC_DEBUG | |||
84 | bootloader or else the GPMC timings won't be identical with the | 84 | bootloader or else the GPMC timings won't be identical with the |
85 | bootloader timings. | 85 | bootloader timings. |
86 | 86 | ||
87 | config TI_EMIF_SRAM | ||
88 | tristate "Texas Instruments EMIF SRAM driver" | ||
89 | depends on (SOC_AM33XX || SOC_AM43XX) && SRAM | ||
90 | help | ||
91 | This driver is for the EMIF module available on Texas Instruments | ||
92 | AM33XX and AM43XX SoCs and is required for PM. Certain parts of | ||
93 | the EMIF PM code must run from on-chip SRAM late in the suspend | ||
94 | sequence so this driver provides several relocatable PM functions | ||
95 | for the SoC PM code to use. | ||
96 | |||
87 | config MVEBU_DEVBUS | 97 | config MVEBU_DEVBUS |
88 | bool "Marvell EBU Device Bus Controller" | 98 | bool "Marvell EBU Device Bus Controller" |
89 | default y | 99 | default y |
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile index 929a601d4cd1..66f55240830e 100644 --- a/drivers/memory/Makefile +++ b/drivers/memory/Makefile | |||
@@ -23,3 +23,11 @@ obj-$(CONFIG_DA8XX_DDRCTL) += da8xx-ddrctl.o | |||
23 | 23 | ||
24 | obj-$(CONFIG_SAMSUNG_MC) += samsung/ | 24 | obj-$(CONFIG_SAMSUNG_MC) += samsung/ |
25 | obj-$(CONFIG_TEGRA_MC) += tegra/ | 25 | obj-$(CONFIG_TEGRA_MC) += tegra/ |
26 | obj-$(CONFIG_TI_EMIF_SRAM) += ti-emif-sram.o | ||
27 | ti-emif-sram-objs := ti-emif-pm.o ti-emif-sram-pm.o | ||
28 | |||
29 | AFLAGS_ti-emif-sram-pm.o :=-Wa,-march=armv7-a | ||
30 | |||
31 | include drivers/memory/Makefile.asm-offsets | ||
32 | |||
33 | drivers/memory/ti-emif-sram-pm.o: include/generated/ti-emif-asm-offsets.h | ||
diff --git a/drivers/memory/Makefile.asm-offsets b/drivers/memory/Makefile.asm-offsets new file mode 100644 index 000000000000..843ff60ccb5a --- /dev/null +++ b/drivers/memory/Makefile.asm-offsets | |||
@@ -0,0 +1,5 @@ | |||
1 | drivers/memory/emif-asm-offsets.s: drivers/memory/emif-asm-offsets.c | ||
2 | $(call if_changed_dep,cc_s_c) | ||
3 | |||
4 | include/generated/ti-emif-asm-offsets.h: drivers/memory/emif-asm-offsets.s FORCE | ||
5 | $(call filechk,offsets,__TI_EMIF_ASM_OFFSETS_H__) | ||
diff --git a/drivers/memory/emif-asm-offsets.c b/drivers/memory/emif-asm-offsets.c new file mode 100644 index 000000000000..71a89d5d3efd --- /dev/null +++ b/drivers/memory/emif-asm-offsets.c | |||
@@ -0,0 +1,92 @@ | |||
1 | /* | ||
2 | * TI AM33XX EMIF PM Assembly Offsets | ||
3 | * | ||
4 | * Copyright (C) 2016-2017 Texas Instruments Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation version 2. | ||
9 | * | ||
10 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
11 | * kind, whether express or implied; without even the implied warranty | ||
12 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | #include <linux/ti-emif-sram.h> | ||
16 | |||
17 | int main(void) | ||
18 | { | ||
19 | DEFINE(EMIF_SDCFG_VAL_OFFSET, | ||
20 | offsetof(struct emif_regs_amx3, emif_sdcfg_val)); | ||
21 | DEFINE(EMIF_TIMING1_VAL_OFFSET, | ||
22 | offsetof(struct emif_regs_amx3, emif_timing1_val)); | ||
23 | DEFINE(EMIF_TIMING2_VAL_OFFSET, | ||
24 | offsetof(struct emif_regs_amx3, emif_timing2_val)); | ||
25 | DEFINE(EMIF_TIMING3_VAL_OFFSET, | ||
26 | offsetof(struct emif_regs_amx3, emif_timing3_val)); | ||
27 | DEFINE(EMIF_REF_CTRL_VAL_OFFSET, | ||
28 | offsetof(struct emif_regs_amx3, emif_ref_ctrl_val)); | ||
29 | DEFINE(EMIF_ZQCFG_VAL_OFFSET, | ||
30 | offsetof(struct emif_regs_amx3, emif_zqcfg_val)); | ||
31 | DEFINE(EMIF_PMCR_VAL_OFFSET, | ||
32 | offsetof(struct emif_regs_amx3, emif_pmcr_val)); | ||
33 | DEFINE(EMIF_PMCR_SHDW_VAL_OFFSET, | ||
34 | offsetof(struct emif_regs_amx3, emif_pmcr_shdw_val)); | ||
35 | DEFINE(EMIF_RD_WR_LEVEL_RAMP_CTRL_OFFSET, | ||
36 | offsetof(struct emif_regs_amx3, emif_rd_wr_level_ramp_ctrl)); | ||
37 | DEFINE(EMIF_RD_WR_EXEC_THRESH_OFFSET, | ||
38 | offsetof(struct emif_regs_amx3, emif_rd_wr_exec_thresh)); | ||
39 | DEFINE(EMIF_COS_CONFIG_OFFSET, | ||
40 | offsetof(struct emif_regs_amx3, emif_cos_config)); | ||
41 | DEFINE(EMIF_PRIORITY_TO_COS_MAPPING_OFFSET, | ||
42 | offsetof(struct emif_regs_amx3, emif_priority_to_cos_mapping)); | ||
43 | DEFINE(EMIF_CONNECT_ID_SERV_1_MAP_OFFSET, | ||
44 | offsetof(struct emif_regs_amx3, emif_connect_id_serv_1_map)); | ||
45 | DEFINE(EMIF_CONNECT_ID_SERV_2_MAP_OFFSET, | ||
46 | offsetof(struct emif_regs_amx3, emif_connect_id_serv_2_map)); | ||
47 | DEFINE(EMIF_OCP_CONFIG_VAL_OFFSET, | ||
48 | offsetof(struct emif_regs_amx3, emif_ocp_config_val)); | ||
49 | DEFINE(EMIF_LPDDR2_NVM_TIM_OFFSET, | ||
50 | offsetof(struct emif_regs_amx3, emif_lpddr2_nvm_tim)); | ||
51 | DEFINE(EMIF_LPDDR2_NVM_TIM_SHDW_OFFSET, | ||
52 | offsetof(struct emif_regs_amx3, emif_lpddr2_nvm_tim_shdw)); | ||
53 | DEFINE(EMIF_DLL_CALIB_CTRL_VAL_OFFSET, | ||
54 | offsetof(struct emif_regs_amx3, emif_dll_calib_ctrl_val)); | ||
55 | DEFINE(EMIF_DLL_CALIB_CTRL_VAL_SHDW_OFFSET, | ||
56 | offsetof(struct emif_regs_amx3, emif_dll_calib_ctrl_val_shdw)); | ||
57 | DEFINE(EMIF_DDR_PHY_CTLR_1_OFFSET, | ||
58 | offsetof(struct emif_regs_amx3, emif_ddr_phy_ctlr_1)); | ||
59 | DEFINE(EMIF_EXT_PHY_CTRL_VALS_OFFSET, | ||
60 | offsetof(struct emif_regs_amx3, emif_ext_phy_ctrl_vals)); | ||
61 | DEFINE(EMIF_REGS_AMX3_SIZE, sizeof(struct emif_regs_amx3)); | ||
62 | |||
63 | BLANK(); | ||
64 | |||
65 | DEFINE(EMIF_PM_BASE_ADDR_VIRT_OFFSET, | ||
66 | offsetof(struct ti_emif_pm_data, ti_emif_base_addr_virt)); | ||
67 | DEFINE(EMIF_PM_BASE_ADDR_PHYS_OFFSET, | ||
68 | offsetof(struct ti_emif_pm_data, ti_emif_base_addr_phys)); | ||
69 | DEFINE(EMIF_PM_CONFIG_OFFSET, | ||
70 | offsetof(struct ti_emif_pm_data, ti_emif_sram_config)); | ||
71 | DEFINE(EMIF_PM_REGS_VIRT_OFFSET, | ||
72 | offsetof(struct ti_emif_pm_data, regs_virt)); | ||
73 | DEFINE(EMIF_PM_REGS_PHYS_OFFSET, | ||
74 | offsetof(struct ti_emif_pm_data, regs_phys)); | ||
75 | DEFINE(EMIF_PM_DATA_SIZE, sizeof(struct ti_emif_pm_data)); | ||
76 | |||
77 | BLANK(); | ||
78 | |||
79 | DEFINE(EMIF_PM_SAVE_CONTEXT_OFFSET, | ||
80 | offsetof(struct ti_emif_pm_functions, save_context)); | ||
81 | DEFINE(EMIF_PM_RESTORE_CONTEXT_OFFSET, | ||
82 | offsetof(struct ti_emif_pm_functions, restore_context)); | ||
83 | DEFINE(EMIF_PM_ENTER_SR_OFFSET, | ||
84 | offsetof(struct ti_emif_pm_functions, enter_sr)); | ||
85 | DEFINE(EMIF_PM_EXIT_SR_OFFSET, | ||
86 | offsetof(struct ti_emif_pm_functions, exit_sr)); | ||
87 | DEFINE(EMIF_PM_ABORT_SR_OFFSET, | ||
88 | offsetof(struct ti_emif_pm_functions, abort_sr)); | ||
89 | DEFINE(EMIF_PM_FUNCTIONS_SIZE, sizeof(struct ti_emif_pm_functions)); | ||
90 | |||
91 | return 0; | ||
92 | } | ||
diff --git a/drivers/memory/emif.h b/drivers/memory/emif.h index bfe08bae961a..9e9f8037955d 100644 --- a/drivers/memory/emif.h +++ b/drivers/memory/emif.h | |||
@@ -555,6 +555,9 @@ | |||
555 | #define READ_LATENCY_SHDW_SHIFT 0 | 555 | #define READ_LATENCY_SHDW_SHIFT 0 |
556 | #define READ_LATENCY_SHDW_MASK (0x1f << 0) | 556 | #define READ_LATENCY_SHDW_MASK (0x1f << 0) |
557 | 557 | ||
558 | #define EMIF_SRAM_AM33_REG_LAYOUT 0x00000000 | ||
559 | #define EMIF_SRAM_AM43_REG_LAYOUT 0x00000001 | ||
560 | |||
558 | #ifndef __ASSEMBLY__ | 561 | #ifndef __ASSEMBLY__ |
559 | /* | 562 | /* |
560 | * Structure containing shadow of important registers in EMIF | 563 | * Structure containing shadow of important registers in EMIF |
@@ -585,5 +588,19 @@ struct emif_regs { | |||
585 | u32 ext_phy_ctrl_3_shdw; | 588 | u32 ext_phy_ctrl_3_shdw; |
586 | u32 ext_phy_ctrl_4_shdw; | 589 | u32 ext_phy_ctrl_4_shdw; |
587 | }; | 590 | }; |
591 | |||
592 | struct ti_emif_pm_functions; | ||
593 | |||
594 | extern unsigned int ti_emif_sram; | ||
595 | extern unsigned int ti_emif_sram_sz; | ||
596 | extern struct ti_emif_pm_data ti_emif_pm_sram_data; | ||
597 | extern struct emif_regs_amx3 ti_emif_regs_amx3; | ||
598 | |||
599 | void ti_emif_save_context(void); | ||
600 | void ti_emif_restore_context(void); | ||
601 | void ti_emif_enter_sr(void); | ||
602 | void ti_emif_exit_sr(void); | ||
603 | void ti_emif_abort_sr(void); | ||
604 | |||
588 | #endif /* __ASSEMBLY__ */ | 605 | #endif /* __ASSEMBLY__ */ |
589 | #endif /* __EMIF_H */ | 606 | #endif /* __EMIF_H */ |
diff --git a/drivers/memory/ti-emif-pm.c b/drivers/memory/ti-emif-pm.c new file mode 100644 index 000000000000..62a86c4bcd0b --- /dev/null +++ b/drivers/memory/ti-emif-pm.c | |||
@@ -0,0 +1,324 @@ | |||
1 | /* | ||
2 | * TI AM33XX SRAM EMIF Driver | ||
3 | * | ||
4 | * Copyright (C) 2016-2017 Texas Instruments Inc. | ||
5 | * Dave Gerlach | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * version 2 as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #include <linux/err.h> | ||
18 | #include <linux/genalloc.h> | ||
19 | #include <linux/io.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/of.h> | ||
23 | #include <linux/of_platform.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <linux/sram.h> | ||
26 | #include <linux/ti-emif-sram.h> | ||
27 | |||
28 | #include "emif.h" | ||
29 | |||
30 | #define TI_EMIF_SRAM_SYMBOL_OFFSET(sym) ((unsigned long)(sym) - \ | ||
31 | (unsigned long)&ti_emif_sram) | ||
32 | |||
33 | #define EMIF_POWER_MGMT_WAIT_SELF_REFRESH_8192_CYCLES 0x00a0 | ||
34 | |||
35 | struct ti_emif_data { | ||
36 | phys_addr_t ti_emif_sram_phys; | ||
37 | phys_addr_t ti_emif_sram_data_phys; | ||
38 | unsigned long ti_emif_sram_virt; | ||
39 | unsigned long ti_emif_sram_data_virt; | ||
40 | struct gen_pool *sram_pool_code; | ||
41 | struct gen_pool *sram_pool_data; | ||
42 | struct ti_emif_pm_data pm_data; | ||
43 | struct ti_emif_pm_functions pm_functions; | ||
44 | }; | ||
45 | |||
46 | static struct ti_emif_data *emif_instance; | ||
47 | |||
48 | static u32 sram_suspend_address(struct ti_emif_data *emif_data, | ||
49 | unsigned long addr) | ||
50 | { | ||
51 | return (emif_data->ti_emif_sram_virt + | ||
52 | TI_EMIF_SRAM_SYMBOL_OFFSET(addr)); | ||
53 | } | ||
54 | |||
55 | static phys_addr_t sram_resume_address(struct ti_emif_data *emif_data, | ||
56 | unsigned long addr) | ||
57 | { | ||
58 | return ((unsigned long)emif_data->ti_emif_sram_phys + | ||
59 | TI_EMIF_SRAM_SYMBOL_OFFSET(addr)); | ||
60 | } | ||
61 | |||
62 | static void ti_emif_free_sram(struct ti_emif_data *emif_data) | ||
63 | { | ||
64 | gen_pool_free(emif_data->sram_pool_code, emif_data->ti_emif_sram_virt, | ||
65 | ti_emif_sram_sz); | ||
66 | gen_pool_free(emif_data->sram_pool_data, | ||
67 | emif_data->ti_emif_sram_data_virt, | ||
68 | sizeof(struct emif_regs_amx3)); | ||
69 | } | ||
70 | |||
71 | static int ti_emif_alloc_sram(struct device *dev, | ||
72 | struct ti_emif_data *emif_data) | ||
73 | { | ||
74 | struct device_node *np = dev->of_node; | ||
75 | int ret; | ||
76 | |||
77 | emif_data->sram_pool_code = of_gen_pool_get(np, "sram", 0); | ||
78 | if (!emif_data->sram_pool_code) { | ||
79 | dev_err(dev, "Unable to get sram pool for ocmcram code\n"); | ||
80 | return -ENODEV; | ||
81 | } | ||
82 | |||
83 | emif_data->ti_emif_sram_virt = | ||
84 | gen_pool_alloc(emif_data->sram_pool_code, | ||
85 | ti_emif_sram_sz); | ||
86 | if (!emif_data->ti_emif_sram_virt) { | ||
87 | dev_err(dev, "Unable to allocate code memory from ocmcram\n"); | ||
88 | return -ENOMEM; | ||
89 | } | ||
90 | |||
91 | /* Save physical address to calculate resume offset during pm init */ | ||
92 | emif_data->ti_emif_sram_phys = | ||
93 | gen_pool_virt_to_phys(emif_data->sram_pool_code, | ||
94 | emif_data->ti_emif_sram_virt); | ||
95 | |||
96 | /* Get sram pool for data section and allocate space */ | ||
97 | emif_data->sram_pool_data = of_gen_pool_get(np, "sram", 1); | ||
98 | if (!emif_data->sram_pool_data) { | ||
99 | dev_err(dev, "Unable to get sram pool for ocmcram data\n"); | ||
100 | ret = -ENODEV; | ||
101 | goto err_free_sram_code; | ||
102 | } | ||
103 | |||
104 | emif_data->ti_emif_sram_data_virt = | ||
105 | gen_pool_alloc(emif_data->sram_pool_data, | ||
106 | sizeof(struct emif_regs_amx3)); | ||
107 | if (!emif_data->ti_emif_sram_data_virt) { | ||
108 | dev_err(dev, "Unable to allocate data memory from ocmcram\n"); | ||
109 | ret = -ENOMEM; | ||
110 | goto err_free_sram_code; | ||
111 | } | ||
112 | |||
113 | /* Save physical address to calculate resume offset during pm init */ | ||
114 | emif_data->ti_emif_sram_data_phys = | ||
115 | gen_pool_virt_to_phys(emif_data->sram_pool_data, | ||
116 | emif_data->ti_emif_sram_data_virt); | ||
117 | /* | ||
118 | * These functions are called during suspend path while MMU is | ||
119 | * still on so add virtual base to offset for absolute address | ||
120 | */ | ||
121 | emif_data->pm_functions.save_context = | ||
122 | sram_suspend_address(emif_data, | ||
123 | (unsigned long)ti_emif_save_context); | ||
124 | emif_data->pm_functions.enter_sr = | ||
125 | sram_suspend_address(emif_data, | ||
126 | (unsigned long)ti_emif_enter_sr); | ||
127 | emif_data->pm_functions.abort_sr = | ||
128 | sram_suspend_address(emif_data, | ||
129 | (unsigned long)ti_emif_abort_sr); | ||
130 | |||
131 | /* | ||
132 | * These are called during resume path when MMU is not enabled | ||
133 | * so physical address is used instead | ||
134 | */ | ||
135 | emif_data->pm_functions.restore_context = | ||
136 | sram_resume_address(emif_data, | ||
137 | (unsigned long)ti_emif_restore_context); | ||
138 | emif_data->pm_functions.exit_sr = | ||
139 | sram_resume_address(emif_data, | ||
140 | (unsigned long)ti_emif_exit_sr); | ||
141 | |||
142 | emif_data->pm_data.regs_virt = | ||
143 | (struct emif_regs_amx3 *)emif_data->ti_emif_sram_data_virt; | ||
144 | emif_data->pm_data.regs_phys = emif_data->ti_emif_sram_data_phys; | ||
145 | |||
146 | return 0; | ||
147 | |||
148 | err_free_sram_code: | ||
149 | gen_pool_free(emif_data->sram_pool_code, emif_data->ti_emif_sram_virt, | ||
150 | ti_emif_sram_sz); | ||
151 | return ret; | ||
152 | } | ||
153 | |||
154 | static int ti_emif_push_sram(struct device *dev, struct ti_emif_data *emif_data) | ||
155 | { | ||
156 | void *copy_addr; | ||
157 | u32 data_addr; | ||
158 | |||
159 | copy_addr = sram_exec_copy(emif_data->sram_pool_code, | ||
160 | (void *)emif_data->ti_emif_sram_virt, | ||
161 | &ti_emif_sram, ti_emif_sram_sz); | ||
162 | if (!copy_addr) { | ||
163 | dev_err(dev, "Cannot copy emif code to sram\n"); | ||
164 | return -ENODEV; | ||
165 | } | ||
166 | |||
167 | data_addr = sram_suspend_address(emif_data, | ||
168 | (unsigned long)&ti_emif_pm_sram_data); | ||
169 | copy_addr = sram_exec_copy(emif_data->sram_pool_code, | ||
170 | (void *)data_addr, | ||
171 | &emif_data->pm_data, | ||
172 | sizeof(emif_data->pm_data)); | ||
173 | if (!copy_addr) { | ||
174 | dev_err(dev, "Cannot copy emif data to code sram\n"); | ||
175 | return -ENODEV; | ||
176 | } | ||
177 | |||
178 | return 0; | ||
179 | } | ||
180 | |||
181 | /* | ||
182 | * Due to Usage Note 3.1.2 "DDR3: JEDEC Compliance for Maximum | ||
183 | * Self-Refresh Command Limit" found in AM335x Silicon Errata | ||
184 | * (Document SPRZ360F Revised November 2013) we must configure | ||
185 | * the self refresh delay timer to 0xA (8192 cycles) to avoid | ||
186 | * generating too many refresh command from the EMIF. | ||
187 | */ | ||
188 | static void ti_emif_configure_sr_delay(struct ti_emif_data *emif_data) | ||
189 | { | ||
190 | writel(EMIF_POWER_MGMT_WAIT_SELF_REFRESH_8192_CYCLES, | ||
191 | (emif_data->pm_data.ti_emif_base_addr_virt + | ||
192 | EMIF_POWER_MANAGEMENT_CONTROL)); | ||
193 | |||
194 | writel(EMIF_POWER_MGMT_WAIT_SELF_REFRESH_8192_CYCLES, | ||
195 | (emif_data->pm_data.ti_emif_base_addr_virt + | ||
196 | EMIF_POWER_MANAGEMENT_CTRL_SHDW)); | ||
197 | } | ||
198 | |||
199 | /** | ||
200 | * ti_emif_copy_pm_function_table - copy mapping of pm funcs in sram | ||
201 | * @sram_pool: pointer to struct gen_pool where dst resides | ||
202 | * @dst: void * to address that table should be copied | ||
203 | * | ||
204 | * Returns 0 if success other error code if table is not available | ||
205 | */ | ||
206 | int ti_emif_copy_pm_function_table(struct gen_pool *sram_pool, void *dst) | ||
207 | { | ||
208 | void *copy_addr; | ||
209 | |||
210 | if (!emif_instance) | ||
211 | return -ENODEV; | ||
212 | |||
213 | copy_addr = sram_exec_copy(sram_pool, dst, | ||
214 | &emif_instance->pm_functions, | ||
215 | sizeof(emif_instance->pm_functions)); | ||
216 | if (!copy_addr) | ||
217 | return -ENODEV; | ||
218 | |||
219 | return 0; | ||
220 | } | ||
221 | EXPORT_SYMBOL_GPL(ti_emif_copy_pm_function_table); | ||
222 | |||
223 | /** | ||
224 | * ti_emif_get_mem_type - return type for memory type in use | ||
225 | * | ||
226 | * Returns memory type value read from EMIF or error code if fails | ||
227 | */ | ||
228 | int ti_emif_get_mem_type(void) | ||
229 | { | ||
230 | unsigned long temp; | ||
231 | |||
232 | if (!emif_instance) | ||
233 | return -ENODEV; | ||
234 | |||
235 | temp = readl(emif_instance->pm_data.ti_emif_base_addr_virt + | ||
236 | EMIF_SDRAM_CONFIG); | ||
237 | |||
238 | temp = (temp & SDRAM_TYPE_MASK) >> SDRAM_TYPE_SHIFT; | ||
239 | return temp; | ||
240 | } | ||
241 | EXPORT_SYMBOL_GPL(ti_emif_get_mem_type); | ||
242 | |||
243 | static const struct of_device_id ti_emif_of_match[] = { | ||
244 | { .compatible = "ti,emif-am3352", .data = | ||
245 | (void *)EMIF_SRAM_AM33_REG_LAYOUT, }, | ||
246 | { .compatible = "ti,emif-am4372", .data = | ||
247 | (void *)EMIF_SRAM_AM43_REG_LAYOUT, }, | ||
248 | {}, | ||
249 | }; | ||
250 | MODULE_DEVICE_TABLE(of, ti_emif_of_match); | ||
251 | |||
252 | static int ti_emif_probe(struct platform_device *pdev) | ||
253 | { | ||
254 | int ret; | ||
255 | struct resource *res; | ||
256 | struct device *dev = &pdev->dev; | ||
257 | const struct of_device_id *match; | ||
258 | struct ti_emif_data *emif_data; | ||
259 | |||
260 | emif_data = devm_kzalloc(dev, sizeof(*emif_data), GFP_KERNEL); | ||
261 | if (!emif_data) | ||
262 | return -ENOMEM; | ||
263 | |||
264 | match = of_match_device(ti_emif_of_match, &pdev->dev); | ||
265 | if (!match) | ||
266 | return -ENODEV; | ||
267 | |||
268 | emif_data->pm_data.ti_emif_sram_config = (unsigned long)match->data; | ||
269 | |||
270 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
271 | emif_data->pm_data.ti_emif_base_addr_virt = devm_ioremap_resource(dev, | ||
272 | res); | ||
273 | if (IS_ERR(emif_data->pm_data.ti_emif_base_addr_virt)) { | ||
274 | dev_err(dev, "could not ioremap emif mem\n"); | ||
275 | ret = PTR_ERR(emif_data->pm_data.ti_emif_base_addr_virt); | ||
276 | return ret; | ||
277 | } | ||
278 | |||
279 | emif_data->pm_data.ti_emif_base_addr_phys = res->start; | ||
280 | |||
281 | ti_emif_configure_sr_delay(emif_data); | ||
282 | |||
283 | ret = ti_emif_alloc_sram(dev, emif_data); | ||
284 | if (ret) | ||
285 | return ret; | ||
286 | |||
287 | ret = ti_emif_push_sram(dev, emif_data); | ||
288 | if (ret) | ||
289 | goto fail_free_sram; | ||
290 | |||
291 | emif_instance = emif_data; | ||
292 | |||
293 | return 0; | ||
294 | |||
295 | fail_free_sram: | ||
296 | ti_emif_free_sram(emif_data); | ||
297 | |||
298 | return ret; | ||
299 | } | ||
300 | |||
301 | static int ti_emif_remove(struct platform_device *pdev) | ||
302 | { | ||
303 | struct ti_emif_data *emif_data = emif_instance; | ||
304 | |||
305 | emif_instance = NULL; | ||
306 | |||
307 | ti_emif_free_sram(emif_data); | ||
308 | |||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | static struct platform_driver ti_emif_driver = { | ||
313 | .probe = ti_emif_probe, | ||
314 | .remove = ti_emif_remove, | ||
315 | .driver = { | ||
316 | .name = KBUILD_MODNAME, | ||
317 | .of_match_table = of_match_ptr(ti_emif_of_match), | ||
318 | }, | ||
319 | }; | ||
320 | module_platform_driver(ti_emif_driver); | ||
321 | |||
322 | MODULE_AUTHOR("Dave Gerlach <d-gerlach@ti.com>"); | ||
323 | MODULE_DESCRIPTION("Texas Instruments SRAM EMIF driver"); | ||
324 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/memory/ti-emif-sram-pm.S b/drivers/memory/ti-emif-sram-pm.S new file mode 100644 index 000000000000..a5369181e5c2 --- /dev/null +++ b/drivers/memory/ti-emif-sram-pm.S | |||
@@ -0,0 +1,334 @@ | |||
1 | /* | ||
2 | * Low level PM code for TI EMIF | ||
3 | * | ||
4 | * Copyright (C) 2016-2017 Texas Instruments Incorporated - http://www.ti.com/ | ||
5 | * Dave Gerlach | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License as | ||
9 | * published by the Free Software Foundation version 2. | ||
10 | * | ||
11 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
12 | * kind, whether express or implied; without even the implied warranty | ||
13 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #include <generated/ti-emif-asm-offsets.h> | ||
18 | #include <linux/linkage.h> | ||
19 | #include <asm/assembler.h> | ||
20 | #include <asm/memory.h> | ||
21 | |||
22 | #include "emif.h" | ||
23 | |||
24 | #define EMIF_POWER_MGMT_WAIT_SELF_REFRESH_8192_CYCLES 0x00a0 | ||
25 | #define EMIF_POWER_MGMT_SR_TIMER_MASK 0x00f0 | ||
26 | #define EMIF_POWER_MGMT_SELF_REFRESH_MODE 0x0200 | ||
27 | #define EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK 0x0700 | ||
28 | |||
29 | #define EMIF_SDCFG_TYPE_DDR2 0x2 << SDRAM_TYPE_SHIFT | ||
30 | #define EMIF_STATUS_READY 0x4 | ||
31 | |||
32 | #define AM43XX_EMIF_PHY_CTRL_REG_COUNT 0x120 | ||
33 | |||
34 | #define EMIF_AM437X_REGISTERS 0x1 | ||
35 | |||
36 | .arm | ||
37 | .align 3 | ||
38 | |||
39 | ENTRY(ti_emif_sram) | ||
40 | |||
41 | /* | ||
42 | * void ti_emif_save_context(void) | ||
43 | * | ||
44 | * Used during suspend to save the context of all required EMIF registers | ||
45 | * to local memory if the EMIF is going to lose context during the sleep | ||
46 | * transition. Operates on the VIRTUAL address of the EMIF. | ||
47 | */ | ||
48 | ENTRY(ti_emif_save_context) | ||
49 | stmfd sp!, {r4 - r11, lr} @ save registers on stack | ||
50 | |||
51 | adr r4, ti_emif_pm_sram_data | ||
52 | ldr r0, [r4, #EMIF_PM_BASE_ADDR_VIRT_OFFSET] | ||
53 | ldr r2, [r4, #EMIF_PM_REGS_VIRT_OFFSET] | ||
54 | |||
55 | /* Save EMIF configuration */ | ||
56 | ldr r1, [r0, #EMIF_SDRAM_CONFIG] | ||
57 | str r1, [r2, #EMIF_SDCFG_VAL_OFFSET] | ||
58 | |||
59 | ldr r1, [r0, #EMIF_SDRAM_REFRESH_CONTROL] | ||
60 | str r1, [r2, #EMIF_REF_CTRL_VAL_OFFSET] | ||
61 | |||
62 | ldr r1, [r0, #EMIF_SDRAM_TIMING_1] | ||
63 | str r1, [r2, #EMIF_TIMING1_VAL_OFFSET] | ||
64 | |||
65 | ldr r1, [r0, #EMIF_SDRAM_TIMING_2] | ||
66 | str r1, [r2, #EMIF_TIMING2_VAL_OFFSET] | ||
67 | |||
68 | ldr r1, [r0, #EMIF_SDRAM_TIMING_3] | ||
69 | str r1, [r2, #EMIF_TIMING3_VAL_OFFSET] | ||
70 | |||
71 | ldr r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL] | ||
72 | str r1, [r2, #EMIF_PMCR_VAL_OFFSET] | ||
73 | |||
74 | ldr r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW] | ||
75 | str r1, [r2, #EMIF_PMCR_SHDW_VAL_OFFSET] | ||
76 | |||
77 | ldr r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG] | ||
78 | str r1, [r2, #EMIF_ZQCFG_VAL_OFFSET] | ||
79 | |||
80 | ldr r1, [r0, #EMIF_DDR_PHY_CTRL_1] | ||
81 | str r1, [r2, #EMIF_DDR_PHY_CTLR_1_OFFSET] | ||
82 | |||
83 | ldr r1, [r0, #EMIF_COS_CONFIG] | ||
84 | str r1, [r2, #EMIF_COS_CONFIG_OFFSET] | ||
85 | |||
86 | ldr r1, [r0, #EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING] | ||
87 | str r1, [r2, #EMIF_PRIORITY_TO_COS_MAPPING_OFFSET] | ||
88 | |||
89 | ldr r1, [r0, #EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING] | ||
90 | str r1, [r2, #EMIF_CONNECT_ID_SERV_1_MAP_OFFSET] | ||
91 | |||
92 | ldr r1, [r0, #EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING] | ||
93 | str r1, [r2, #EMIF_CONNECT_ID_SERV_2_MAP_OFFSET] | ||
94 | |||
95 | ldr r1, [r0, #EMIF_OCP_CONFIG] | ||
96 | str r1, [r2, #EMIF_OCP_CONFIG_VAL_OFFSET] | ||
97 | |||
98 | ldr r5, [r4, #EMIF_PM_CONFIG_OFFSET] | ||
99 | cmp r5, #EMIF_SRAM_AM43_REG_LAYOUT | ||
100 | bne emif_skip_save_extra_regs | ||
101 | |||
102 | ldr r1, [r0, #EMIF_READ_WRITE_LEVELING_RAMP_CONTROL] | ||
103 | str r1, [r2, #EMIF_RD_WR_LEVEL_RAMP_CTRL_OFFSET] | ||
104 | |||
105 | ldr r1, [r0, #EMIF_READ_WRITE_EXECUTION_THRESHOLD] | ||
106 | str r1, [r2, #EMIF_RD_WR_EXEC_THRESH_OFFSET] | ||
107 | |||
108 | ldr r1, [r0, #EMIF_LPDDR2_NVM_TIMING] | ||
109 | str r1, [r2, #EMIF_LPDDR2_NVM_TIM_OFFSET] | ||
110 | |||
111 | ldr r1, [r0, #EMIF_LPDDR2_NVM_TIMING_SHDW] | ||
112 | str r1, [r2, #EMIF_LPDDR2_NVM_TIM_SHDW_OFFSET] | ||
113 | |||
114 | ldr r1, [r0, #EMIF_DLL_CALIB_CTRL] | ||
115 | str r1, [r2, #EMIF_DLL_CALIB_CTRL_VAL_OFFSET] | ||
116 | |||
117 | ldr r1, [r0, #EMIF_DLL_CALIB_CTRL_SHDW] | ||
118 | str r1, [r2, #EMIF_DLL_CALIB_CTRL_VAL_SHDW_OFFSET] | ||
119 | |||
120 | /* Loop and save entire block of emif phy regs */ | ||
121 | mov r5, #0x0 | ||
122 | add r4, r2, #EMIF_EXT_PHY_CTRL_VALS_OFFSET | ||
123 | add r3, r0, #EMIF_EXT_PHY_CTRL_1 | ||
124 | ddr_phy_ctrl_save: | ||
125 | ldr r1, [r3, r5] | ||
126 | str r1, [r4, r5] | ||
127 | add r5, r5, #0x4 | ||
128 | cmp r5, #AM43XX_EMIF_PHY_CTRL_REG_COUNT | ||
129 | bne ddr_phy_ctrl_save | ||
130 | |||
131 | emif_skip_save_extra_regs: | ||
132 | ldmfd sp!, {r4 - r11, pc} @ restore regs and return | ||
133 | ENDPROC(ti_emif_save_context) | ||
134 | |||
135 | /* | ||
136 | * void ti_emif_restore_context(void) | ||
137 | * | ||
138 | * Used during resume to restore the context of all required EMIF registers | ||
139 | * from local memory after the EMIF has lost context during a sleep transition. | ||
140 | * Operates on the PHYSICAL address of the EMIF. | ||
141 | */ | ||
142 | ENTRY(ti_emif_restore_context) | ||
143 | adr r4, ti_emif_pm_sram_data | ||
144 | ldr r0, [r4, #EMIF_PM_BASE_ADDR_PHYS_OFFSET] | ||
145 | ldr r2, [r4, #EMIF_PM_REGS_PHYS_OFFSET] | ||
146 | |||
147 | /* Config EMIF Timings */ | ||
148 | ldr r1, [r2, #EMIF_DDR_PHY_CTLR_1_OFFSET] | ||
149 | str r1, [r0, #EMIF_DDR_PHY_CTRL_1] | ||
150 | str r1, [r0, #EMIF_DDR_PHY_CTRL_1_SHDW] | ||
151 | |||
152 | ldr r1, [r2, #EMIF_TIMING1_VAL_OFFSET] | ||
153 | str r1, [r0, #EMIF_SDRAM_TIMING_1] | ||
154 | str r1, [r0, #EMIF_SDRAM_TIMING_1_SHDW] | ||
155 | |||
156 | ldr r1, [r2, #EMIF_TIMING2_VAL_OFFSET] | ||
157 | str r1, [r0, #EMIF_SDRAM_TIMING_2] | ||
158 | str r1, [r0, #EMIF_SDRAM_TIMING_2_SHDW] | ||
159 | |||
160 | ldr r1, [r2, #EMIF_TIMING3_VAL_OFFSET] | ||
161 | str r1, [r0, #EMIF_SDRAM_TIMING_3] | ||
162 | str r1, [r0, #EMIF_SDRAM_TIMING_3_SHDW] | ||
163 | |||
164 | ldr r1, [r2, #EMIF_REF_CTRL_VAL_OFFSET] | ||
165 | str r1, [r0, #EMIF_SDRAM_REFRESH_CONTROL] | ||
166 | str r1, [r0, #EMIF_SDRAM_REFRESH_CTRL_SHDW] | ||
167 | |||
168 | ldr r1, [r2, #EMIF_PMCR_VAL_OFFSET] | ||
169 | str r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL] | ||
170 | |||
171 | ldr r1, [r2, #EMIF_PMCR_SHDW_VAL_OFFSET] | ||
172 | str r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW] | ||
173 | |||
174 | ldr r1, [r2, #EMIF_COS_CONFIG_OFFSET] | ||
175 | str r1, [r0, #EMIF_COS_CONFIG] | ||
176 | |||
177 | ldr r1, [r2, #EMIF_PRIORITY_TO_COS_MAPPING_OFFSET] | ||
178 | str r1, [r0, #EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING] | ||
179 | |||
180 | ldr r1, [r2, #EMIF_CONNECT_ID_SERV_1_MAP_OFFSET] | ||
181 | str r1, [r0, #EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING] | ||
182 | |||
183 | ldr r1, [r2, #EMIF_CONNECT_ID_SERV_2_MAP_OFFSET] | ||
184 | str r1, [r0, #EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING] | ||
185 | |||
186 | ldr r1, [r2, #EMIF_OCP_CONFIG_VAL_OFFSET] | ||
187 | str r1, [r0, #EMIF_OCP_CONFIG] | ||
188 | |||
189 | ldr r5, [r4, #EMIF_PM_CONFIG_OFFSET] | ||
190 | cmp r5, #EMIF_SRAM_AM43_REG_LAYOUT | ||
191 | bne emif_skip_restore_extra_regs | ||
192 | |||
193 | ldr r1, [r2, #EMIF_RD_WR_LEVEL_RAMP_CTRL_OFFSET] | ||
194 | str r1, [r0, #EMIF_READ_WRITE_LEVELING_RAMP_CONTROL] | ||
195 | |||
196 | ldr r1, [r2, #EMIF_RD_WR_EXEC_THRESH_OFFSET] | ||
197 | str r1, [r0, #EMIF_READ_WRITE_EXECUTION_THRESHOLD] | ||
198 | |||
199 | ldr r1, [r2, #EMIF_LPDDR2_NVM_TIM_OFFSET] | ||
200 | str r1, [r0, #EMIF_LPDDR2_NVM_TIMING] | ||
201 | |||
202 | ldr r1, [r2, #EMIF_LPDDR2_NVM_TIM_SHDW_OFFSET] | ||
203 | str r1, [r0, #EMIF_LPDDR2_NVM_TIMING_SHDW] | ||
204 | |||
205 | ldr r1, [r2, #EMIF_DLL_CALIB_CTRL_VAL_OFFSET] | ||
206 | str r1, [r0, #EMIF_DLL_CALIB_CTRL] | ||
207 | |||
208 | ldr r1, [r2, #EMIF_DLL_CALIB_CTRL_VAL_SHDW_OFFSET] | ||
209 | str r1, [r0, #EMIF_DLL_CALIB_CTRL_SHDW] | ||
210 | |||
211 | ldr r1, [r2, #EMIF_ZQCFG_VAL_OFFSET] | ||
212 | str r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG] | ||
213 | |||
214 | /* Loop and restore entire block of emif phy regs */ | ||
215 | mov r5, #0x0 | ||
216 | /* Load ti_emif_regs_amx3 + EMIF_EXT_PHY_CTRL_VALS_OFFSET for address | ||
217 | * to phy register save space | ||
218 | */ | ||
219 | add r3, r2, #EMIF_EXT_PHY_CTRL_VALS_OFFSET | ||
220 | add r4, r0, #EMIF_EXT_PHY_CTRL_1 | ||
221 | ddr_phy_ctrl_restore: | ||
222 | ldr r1, [r3, r5] | ||
223 | str r1, [r4, r5] | ||
224 | add r5, r5, #0x4 | ||
225 | cmp r5, #AM43XX_EMIF_PHY_CTRL_REG_COUNT | ||
226 | bne ddr_phy_ctrl_restore | ||
227 | |||
228 | emif_skip_restore_extra_regs: | ||
229 | /* | ||
230 | * Output impedence calib needed only for DDR3 | ||
231 | * but since the initial state of this will be | ||
232 | * disabled for DDR2 no harm in restoring the | ||
233 | * old configuration | ||
234 | */ | ||
235 | ldr r1, [r2, #EMIF_ZQCFG_VAL_OFFSET] | ||
236 | str r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG] | ||
237 | |||
238 | /* Write to sdcfg last for DDR2 only */ | ||
239 | ldr r1, [r2, #EMIF_SDCFG_VAL_OFFSET] | ||
240 | and r2, r1, #SDRAM_TYPE_MASK | ||
241 | cmp r2, #EMIF_SDCFG_TYPE_DDR2 | ||
242 | streq r1, [r0, #EMIF_SDRAM_CONFIG] | ||
243 | |||
244 | mov pc, lr | ||
245 | ENDPROC(ti_emif_restore_context) | ||
246 | |||
247 | /* | ||
248 | * void ti_emif_enter_sr(void) | ||
249 | * | ||
250 | * Programs the EMIF to tell the SDRAM to enter into self-refresh | ||
251 | * mode during a sleep transition. Operates on the VIRTUAL address | ||
252 | * of the EMIF. | ||
253 | */ | ||
254 | ENTRY(ti_emif_enter_sr) | ||
255 | stmfd sp!, {r4 - r11, lr} @ save registers on stack | ||
256 | |||
257 | adr r4, ti_emif_pm_sram_data | ||
258 | ldr r0, [r4, #EMIF_PM_BASE_ADDR_VIRT_OFFSET] | ||
259 | ldr r2, [r4, #EMIF_PM_REGS_VIRT_OFFSET] | ||
260 | |||
261 | ldr r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL] | ||
262 | bic r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK | ||
263 | orr r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE | ||
264 | str r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL] | ||
265 | |||
266 | ldmfd sp!, {r4 - r11, pc} @ restore regs and return | ||
267 | ENDPROC(ti_emif_enter_sr) | ||
268 | |||
269 | /* | ||
270 | * void ti_emif_exit_sr(void) | ||
271 | * | ||
272 | * Programs the EMIF to tell the SDRAM to exit self-refresh mode | ||
273 | * after a sleep transition. Operates on the PHYSICAL address of | ||
274 | * the EMIF. | ||
275 | */ | ||
276 | ENTRY(ti_emif_exit_sr) | ||
277 | adr r4, ti_emif_pm_sram_data | ||
278 | ldr r0, [r4, #EMIF_PM_BASE_ADDR_PHYS_OFFSET] | ||
279 | ldr r2, [r4, #EMIF_PM_REGS_PHYS_OFFSET] | ||
280 | |||
281 | /* | ||
282 | * Toggle EMIF to exit refresh mode: | ||
283 | * if EMIF lost context, PWR_MGT_CTRL is currently 0, writing disable | ||
284 | * (0x0), wont do diddly squat! so do a toggle from SR(0x2) to disable | ||
285 | * (0x0) here. | ||
286 | * *If* EMIF did not lose context, nothing broken as we write the same | ||
287 | * value(0x2) to reg before we write a disable (0x0). | ||
288 | */ | ||
289 | ldr r1, [r2, #EMIF_PMCR_VAL_OFFSET] | ||
290 | bic r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK | ||
291 | orr r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE | ||
292 | str r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL] | ||
293 | bic r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK | ||
294 | str r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL] | ||
295 | |||
296 | /* Wait for EMIF to become ready */ | ||
297 | 1: ldr r1, [r0, #EMIF_STATUS] | ||
298 | tst r1, #EMIF_STATUS_READY | ||
299 | beq 1b | ||
300 | |||
301 | mov pc, lr | ||
302 | ENDPROC(ti_emif_exit_sr) | ||
303 | |||
304 | /* | ||
305 | * void ti_emif_abort_sr(void) | ||
306 | * | ||
307 | * Disables self-refresh after a failed transition to a low-power | ||
308 | * state so the kernel can jump back to DDR and follow abort path. | ||
309 | * Operates on the VIRTUAL address of the EMIF. | ||
310 | */ | ||
311 | ENTRY(ti_emif_abort_sr) | ||
312 | stmfd sp!, {r4 - r11, lr} @ save registers on stack | ||
313 | |||
314 | adr r4, ti_emif_pm_sram_data | ||
315 | ldr r0, [r4, #EMIF_PM_BASE_ADDR_VIRT_OFFSET] | ||
316 | ldr r2, [r4, #EMIF_PM_REGS_VIRT_OFFSET] | ||
317 | |||
318 | ldr r1, [r2, #EMIF_PMCR_VAL_OFFSET] | ||
319 | bic r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK | ||
320 | str r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL] | ||
321 | |||
322 | /* Wait for EMIF to become ready */ | ||
323 | 1: ldr r1, [r0, #EMIF_STATUS] | ||
324 | tst r1, #EMIF_STATUS_READY | ||
325 | beq 1b | ||
326 | |||
327 | ldmfd sp!, {r4 - r11, pc} @ restore regs and return | ||
328 | ENDPROC(ti_emif_abort_sr) | ||
329 | |||
330 | .align 3 | ||
331 | ENTRY(ti_emif_pm_sram_data) | ||
332 | .space EMIF_PM_DATA_SIZE | ||
333 | ENTRY(ti_emif_sram_sz) | ||
334 | .word . - ti_emif_save_context | ||