Commit | Line | Data |
---|---|---|
1802d0be | 1 | // SPDX-License-Identifier: GPL-2.0-only |
8428e5ad DG |
2 | /* |
3 | * TI AM33XX SRAM EMIF Driver | |
4 | * | |
5 | * Copyright (C) 2016-2017 Texas Instruments Inc. | |
6 | * Dave Gerlach | |
8428e5ad DG |
7 | */ |
8 | ||
9 | #include <linux/err.h> | |
10 | #include <linux/genalloc.h> | |
11 | #include <linux/io.h> | |
12 | #include <linux/kernel.h> | |
13 | #include <linux/module.h> | |
14 | #include <linux/of.h> | |
15 | #include <linux/of_platform.h> | |
16 | #include <linux/platform_device.h> | |
17 | #include <linux/sram.h> | |
18 | #include <linux/ti-emif-sram.h> | |
19 | ||
20 | #include "emif.h" | |
21 | ||
22 | #define TI_EMIF_SRAM_SYMBOL_OFFSET(sym) ((unsigned long)(sym) - \ | |
23 | (unsigned long)&ti_emif_sram) | |
24 | ||
25 | #define EMIF_POWER_MGMT_WAIT_SELF_REFRESH_8192_CYCLES 0x00a0 | |
26 | ||
27 | struct ti_emif_data { | |
28 | phys_addr_t ti_emif_sram_phys; | |
29 | phys_addr_t ti_emif_sram_data_phys; | |
30 | unsigned long ti_emif_sram_virt; | |
31 | unsigned long ti_emif_sram_data_virt; | |
32 | struct gen_pool *sram_pool_code; | |
33 | struct gen_pool *sram_pool_data; | |
34 | struct ti_emif_pm_data pm_data; | |
35 | struct ti_emif_pm_functions pm_functions; | |
36 | }; | |
37 | ||
38 | static struct ti_emif_data *emif_instance; | |
39 | ||
40 | static u32 sram_suspend_address(struct ti_emif_data *emif_data, | |
41 | unsigned long addr) | |
42 | { | |
43 | return (emif_data->ti_emif_sram_virt + | |
44 | TI_EMIF_SRAM_SYMBOL_OFFSET(addr)); | |
45 | } | |
46 | ||
47 | static phys_addr_t sram_resume_address(struct ti_emif_data *emif_data, | |
48 | unsigned long addr) | |
49 | { | |
50 | return ((unsigned long)emif_data->ti_emif_sram_phys + | |
51 | TI_EMIF_SRAM_SYMBOL_OFFSET(addr)); | |
52 | } | |
53 | ||
54 | static void ti_emif_free_sram(struct ti_emif_data *emif_data) | |
55 | { | |
56 | gen_pool_free(emif_data->sram_pool_code, emif_data->ti_emif_sram_virt, | |
57 | ti_emif_sram_sz); | |
58 | gen_pool_free(emif_data->sram_pool_data, | |
59 | emif_data->ti_emif_sram_data_virt, | |
60 | sizeof(struct emif_regs_amx3)); | |
61 | } | |
62 | ||
63 | static int ti_emif_alloc_sram(struct device *dev, | |
64 | struct ti_emif_data *emif_data) | |
65 | { | |
66 | struct device_node *np = dev->of_node; | |
67 | int ret; | |
68 | ||
69 | emif_data->sram_pool_code = of_gen_pool_get(np, "sram", 0); | |
70 | if (!emif_data->sram_pool_code) { | |
71 | dev_err(dev, "Unable to get sram pool for ocmcram code\n"); | |
72 | return -ENODEV; | |
73 | } | |
74 | ||
75 | emif_data->ti_emif_sram_virt = | |
76 | gen_pool_alloc(emif_data->sram_pool_code, | |
77 | ti_emif_sram_sz); | |
78 | if (!emif_data->ti_emif_sram_virt) { | |
79 | dev_err(dev, "Unable to allocate code memory from ocmcram\n"); | |
80 | return -ENOMEM; | |
81 | } | |
82 | ||
83 | /* Save physical address to calculate resume offset during pm init */ | |
84 | emif_data->ti_emif_sram_phys = | |
85 | gen_pool_virt_to_phys(emif_data->sram_pool_code, | |
86 | emif_data->ti_emif_sram_virt); | |
87 | ||
88 | /* Get sram pool for data section and allocate space */ | |
89 | emif_data->sram_pool_data = of_gen_pool_get(np, "sram", 1); | |
90 | if (!emif_data->sram_pool_data) { | |
91 | dev_err(dev, "Unable to get sram pool for ocmcram data\n"); | |
92 | ret = -ENODEV; | |
93 | goto err_free_sram_code; | |
94 | } | |
95 | ||
96 | emif_data->ti_emif_sram_data_virt = | |
97 | gen_pool_alloc(emif_data->sram_pool_data, | |
98 | sizeof(struct emif_regs_amx3)); | |
99 | if (!emif_data->ti_emif_sram_data_virt) { | |
100 | dev_err(dev, "Unable to allocate data memory from ocmcram\n"); | |
101 | ret = -ENOMEM; | |
102 | goto err_free_sram_code; | |
103 | } | |
104 | ||
105 | /* Save physical address to calculate resume offset during pm init */ | |
106 | emif_data->ti_emif_sram_data_phys = | |
107 | gen_pool_virt_to_phys(emif_data->sram_pool_data, | |
108 | emif_data->ti_emif_sram_data_virt); | |
109 | /* | |
110 | * These functions are called during suspend path while MMU is | |
111 | * still on so add virtual base to offset for absolute address | |
112 | */ | |
113 | emif_data->pm_functions.save_context = | |
114 | sram_suspend_address(emif_data, | |
115 | (unsigned long)ti_emif_save_context); | |
116 | emif_data->pm_functions.enter_sr = | |
117 | sram_suspend_address(emif_data, | |
118 | (unsigned long)ti_emif_enter_sr); | |
119 | emif_data->pm_functions.abort_sr = | |
120 | sram_suspend_address(emif_data, | |
121 | (unsigned long)ti_emif_abort_sr); | |
122 | ||
123 | /* | |
124 | * These are called during resume path when MMU is not enabled | |
125 | * so physical address is used instead | |
126 | */ | |
127 | emif_data->pm_functions.restore_context = | |
128 | sram_resume_address(emif_data, | |
129 | (unsigned long)ti_emif_restore_context); | |
130 | emif_data->pm_functions.exit_sr = | |
131 | sram_resume_address(emif_data, | |
132 | (unsigned long)ti_emif_exit_sr); | |
6c110561 DG |
133 | emif_data->pm_functions.run_hw_leveling = |
134 | sram_resume_address(emif_data, | |
135 | (unsigned long)ti_emif_run_hw_leveling); | |
8428e5ad DG |
136 | |
137 | emif_data->pm_data.regs_virt = | |
138 | (struct emif_regs_amx3 *)emif_data->ti_emif_sram_data_virt; | |
139 | emif_data->pm_data.regs_phys = emif_data->ti_emif_sram_data_phys; | |
140 | ||
141 | return 0; | |
142 | ||
143 | err_free_sram_code: | |
144 | gen_pool_free(emif_data->sram_pool_code, emif_data->ti_emif_sram_virt, | |
145 | ti_emif_sram_sz); | |
146 | return ret; | |
147 | } | |
148 | ||
149 | static int ti_emif_push_sram(struct device *dev, struct ti_emif_data *emif_data) | |
150 | { | |
151 | void *copy_addr; | |
152 | u32 data_addr; | |
153 | ||
154 | copy_addr = sram_exec_copy(emif_data->sram_pool_code, | |
155 | (void *)emif_data->ti_emif_sram_virt, | |
156 | &ti_emif_sram, ti_emif_sram_sz); | |
157 | if (!copy_addr) { | |
158 | dev_err(dev, "Cannot copy emif code to sram\n"); | |
159 | return -ENODEV; | |
160 | } | |
161 | ||
162 | data_addr = sram_suspend_address(emif_data, | |
163 | (unsigned long)&ti_emif_pm_sram_data); | |
164 | copy_addr = sram_exec_copy(emif_data->sram_pool_code, | |
165 | (void *)data_addr, | |
166 | &emif_data->pm_data, | |
167 | sizeof(emif_data->pm_data)); | |
168 | if (!copy_addr) { | |
169 | dev_err(dev, "Cannot copy emif data to code sram\n"); | |
170 | return -ENODEV; | |
171 | } | |
172 | ||
173 | return 0; | |
174 | } | |
175 | ||
176 | /* | |
177 | * Due to Usage Note 3.1.2 "DDR3: JEDEC Compliance for Maximum | |
178 | * Self-Refresh Command Limit" found in AM335x Silicon Errata | |
179 | * (Document SPRZ360F Revised November 2013) we must configure | |
180 | * the self refresh delay timer to 0xA (8192 cycles) to avoid | |
181 | * generating too many refresh command from the EMIF. | |
182 | */ | |
183 | static void ti_emif_configure_sr_delay(struct ti_emif_data *emif_data) | |
184 | { | |
185 | writel(EMIF_POWER_MGMT_WAIT_SELF_REFRESH_8192_CYCLES, | |
186 | (emif_data->pm_data.ti_emif_base_addr_virt + | |
187 | EMIF_POWER_MANAGEMENT_CONTROL)); | |
188 | ||
189 | writel(EMIF_POWER_MGMT_WAIT_SELF_REFRESH_8192_CYCLES, | |
190 | (emif_data->pm_data.ti_emif_base_addr_virt + | |
191 | EMIF_POWER_MANAGEMENT_CTRL_SHDW)); | |
192 | } | |
193 | ||
194 | /** | |
195 | * ti_emif_copy_pm_function_table - copy mapping of pm funcs in sram | |
196 | * @sram_pool: pointer to struct gen_pool where dst resides | |
197 | * @dst: void * to address that table should be copied | |
198 | * | |
199 | * Returns 0 if success other error code if table is not available | |
200 | */ | |
201 | int ti_emif_copy_pm_function_table(struct gen_pool *sram_pool, void *dst) | |
202 | { | |
203 | void *copy_addr; | |
204 | ||
205 | if (!emif_instance) | |
206 | return -ENODEV; | |
207 | ||
208 | copy_addr = sram_exec_copy(sram_pool, dst, | |
209 | &emif_instance->pm_functions, | |
210 | sizeof(emif_instance->pm_functions)); | |
211 | if (!copy_addr) | |
212 | return -ENODEV; | |
213 | ||
214 | return 0; | |
215 | } | |
216 | EXPORT_SYMBOL_GPL(ti_emif_copy_pm_function_table); | |
217 | ||
218 | /** | |
219 | * ti_emif_get_mem_type - return type for memory type in use | |
220 | * | |
221 | * Returns memory type value read from EMIF or error code if fails | |
222 | */ | |
223 | int ti_emif_get_mem_type(void) | |
224 | { | |
225 | unsigned long temp; | |
226 | ||
227 | if (!emif_instance) | |
228 | return -ENODEV; | |
229 | ||
230 | temp = readl(emif_instance->pm_data.ti_emif_base_addr_virt + | |
231 | EMIF_SDRAM_CONFIG); | |
232 | ||
233 | temp = (temp & SDRAM_TYPE_MASK) >> SDRAM_TYPE_SHIFT; | |
234 | return temp; | |
235 | } | |
236 | EXPORT_SYMBOL_GPL(ti_emif_get_mem_type); | |
237 | ||
238 | static const struct of_device_id ti_emif_of_match[] = { | |
239 | { .compatible = "ti,emif-am3352", .data = | |
240 | (void *)EMIF_SRAM_AM33_REG_LAYOUT, }, | |
241 | { .compatible = "ti,emif-am4372", .data = | |
242 | (void *)EMIF_SRAM_AM43_REG_LAYOUT, }, | |
243 | {}, | |
244 | }; | |
245 | MODULE_DEVICE_TABLE(of, ti_emif_of_match); | |
246 | ||
38853979 DG |
247 | #ifdef CONFIG_PM_SLEEP |
248 | static int ti_emif_resume(struct device *dev) | |
249 | { | |
250 | unsigned long tmp = | |
96424aa9 | 251 | __raw_readl((void __iomem *)emif_instance->ti_emif_sram_virt); |
38853979 DG |
252 | |
253 | /* | |
254 | * Check to see if what we are copying is already present in the | |
255 | * first byte at the destination, only copy if it is not which | |
256 | * indicates we have lost context and sram no longer contains | |
257 | * the PM code | |
258 | */ | |
259 | if (tmp != ti_emif_sram) | |
260 | ti_emif_push_sram(dev, emif_instance); | |
261 | ||
262 | return 0; | |
263 | } | |
264 | ||
265 | static int ti_emif_suspend(struct device *dev) | |
266 | { | |
267 | /* | |
268 | * The contents will be present in DDR hence no need to | |
269 | * explicitly save | |
270 | */ | |
271 | return 0; | |
272 | } | |
273 | #endif /* CONFIG_PM_SLEEP */ | |
274 | ||
8428e5ad DG |
275 | static int ti_emif_probe(struct platform_device *pdev) |
276 | { | |
277 | int ret; | |
278 | struct resource *res; | |
279 | struct device *dev = &pdev->dev; | |
8428e5ad DG |
280 | struct ti_emif_data *emif_data; |
281 | ||
282 | emif_data = devm_kzalloc(dev, sizeof(*emif_data), GFP_KERNEL); | |
283 | if (!emif_data) | |
284 | return -ENOMEM; | |
285 | ||
bbaf6624 | 286 | emif_data->pm_data.ti_emif_sram_config = (unsigned long) device_get_match_data(&pdev->dev); |
8428e5ad | 287 | |
8e6a257a KK |
288 | emif_data->pm_data.ti_emif_base_addr_virt = devm_platform_get_and_ioremap_resource(pdev, |
289 | 0, | |
290 | &res); | |
8428e5ad | 291 | if (IS_ERR(emif_data->pm_data.ti_emif_base_addr_virt)) { |
8428e5ad DG |
292 | ret = PTR_ERR(emif_data->pm_data.ti_emif_base_addr_virt); |
293 | return ret; | |
294 | } | |
295 | ||
296 | emif_data->pm_data.ti_emif_base_addr_phys = res->start; | |
297 | ||
298 | ti_emif_configure_sr_delay(emif_data); | |
299 | ||
300 | ret = ti_emif_alloc_sram(dev, emif_data); | |
301 | if (ret) | |
302 | return ret; | |
303 | ||
304 | ret = ti_emif_push_sram(dev, emif_data); | |
305 | if (ret) | |
306 | goto fail_free_sram; | |
307 | ||
308 | emif_instance = emif_data; | |
309 | ||
310 | return 0; | |
311 | ||
312 | fail_free_sram: | |
313 | ti_emif_free_sram(emif_data); | |
314 | ||
315 | return ret; | |
316 | } | |
317 | ||
365fcc03 | 318 | static void ti_emif_remove(struct platform_device *pdev) |
8428e5ad | 319 | { |
8428e5ad DG |
320 | struct ti_emif_data *emif_data = emif_instance; |
321 | ||
322 | emif_instance = NULL; | |
323 | ||
324 | ti_emif_free_sram(emif_data); | |
8428e5ad DG |
325 | } |
326 | ||
38853979 DG |
327 | static const struct dev_pm_ops ti_emif_pm_ops = { |
328 | SET_SYSTEM_SLEEP_PM_OPS(ti_emif_suspend, ti_emif_resume) | |
329 | }; | |
330 | ||
8428e5ad DG |
331 | static struct platform_driver ti_emif_driver = { |
332 | .probe = ti_emif_probe, | |
365fcc03 | 333 | .remove_new = ti_emif_remove, |
8428e5ad DG |
334 | .driver = { |
335 | .name = KBUILD_MODNAME, | |
62c290a6 | 336 | .of_match_table = ti_emif_of_match, |
38853979 | 337 | .pm = &ti_emif_pm_ops, |
8428e5ad DG |
338 | }, |
339 | }; | |
340 | module_platform_driver(ti_emif_driver); | |
341 | ||
342 | MODULE_AUTHOR("Dave Gerlach <d-gerlach@ti.com>"); | |
343 | MODULE_DESCRIPTION("Texas Instruments SRAM EMIF driver"); | |
344 | MODULE_LICENSE("GPL v2"); |