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 <linux/linkage.h>
18#include <asm/assembler.h>
19#include <asm/memory.h>
20
21#include "emif.h"
22#include "ti-emif-asm-offsets.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_SDCFG_TYPE_DDR3				0x3 << SDRAM_TYPE_SHIFT
31#define EMIF_STATUS_READY				0x4
32
33#define AM43XX_EMIF_PHY_CTRL_REG_COUNT                  0x120
34
35#define EMIF_AM437X_REGISTERS				0x1
36
37	.arm
38	.align 3
39
40ENTRY(ti_emif_sram)
41
42/*
43 * void ti_emif_save_context(void)
44 *
45 * Used during suspend to save the context of all required EMIF registers
46 * to local memory if the EMIF is going to lose context during the sleep
47 * transition. Operates on the VIRTUAL address of the EMIF.
48 */
49ENTRY(ti_emif_save_context)
50	stmfd   sp!, {r4 - r11, lr}     @ save registers on stack
51
52	adr	r4, ti_emif_pm_sram_data
53	ldr	r0, [r4, #EMIF_PM_BASE_ADDR_VIRT_OFFSET]
54	ldr	r2, [r4, #EMIF_PM_REGS_VIRT_OFFSET]
55
56	/* Save EMIF configuration */
57	ldr	r1, [r0, #EMIF_SDRAM_CONFIG]
58	str	r1, [r2, #EMIF_SDCFG_VAL_OFFSET]
59
60	ldr	r1, [r0, #EMIF_SDRAM_REFRESH_CONTROL]
61	str	r1, [r2, #EMIF_REF_CTRL_VAL_OFFSET]
62
63	ldr	r1, [r0, #EMIF_SDRAM_TIMING_1]
64	str     r1, [r2, #EMIF_TIMING1_VAL_OFFSET]
65
66	ldr	r1, [r0, #EMIF_SDRAM_TIMING_2]
67	str     r1, [r2, #EMIF_TIMING2_VAL_OFFSET]
68
69	ldr	r1, [r0, #EMIF_SDRAM_TIMING_3]
70	str     r1, [r2, #EMIF_TIMING3_VAL_OFFSET]
71
72	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
73	str     r1, [r2, #EMIF_PMCR_VAL_OFFSET]
74
75	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
76	str     r1, [r2, #EMIF_PMCR_SHDW_VAL_OFFSET]
77
78	ldr	r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG]
79	str     r1, [r2, #EMIF_ZQCFG_VAL_OFFSET]
80
81	ldr	r1, [r0, #EMIF_DDR_PHY_CTRL_1]
82	str     r1, [r2, #EMIF_DDR_PHY_CTLR_1_OFFSET]
83
84	ldr	r1, [r0, #EMIF_COS_CONFIG]
85	str     r1, [r2, #EMIF_COS_CONFIG_OFFSET]
86
87	ldr	r1, [r0, #EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING]
88	str     r1, [r2, #EMIF_PRIORITY_TO_COS_MAPPING_OFFSET]
89
90	ldr	r1, [r0, #EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING]
91	str     r1, [r2, #EMIF_CONNECT_ID_SERV_1_MAP_OFFSET]
92
93	ldr	r1, [r0, #EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING]
94	str     r1, [r2, #EMIF_CONNECT_ID_SERV_2_MAP_OFFSET]
95
96	ldr	r1, [r0, #EMIF_OCP_CONFIG]
97	str     r1, [r2, #EMIF_OCP_CONFIG_VAL_OFFSET]
98
99	ldr	r5, [r4, #EMIF_PM_CONFIG_OFFSET]
100	cmp	r5, #EMIF_SRAM_AM43_REG_LAYOUT
101	bne	emif_skip_save_extra_regs
102
103	ldr	r1, [r0, #EMIF_READ_WRITE_LEVELING_RAMP_CONTROL]
104	str     r1, [r2, #EMIF_RD_WR_LEVEL_RAMP_CTRL_OFFSET]
105
106	ldr	r1, [r0, #EMIF_READ_WRITE_EXECUTION_THRESHOLD]
107	str     r1, [r2, #EMIF_RD_WR_EXEC_THRESH_OFFSET]
108
109	ldr	r1, [r0, #EMIF_LPDDR2_NVM_TIMING]
110	str     r1, [r2, #EMIF_LPDDR2_NVM_TIM_OFFSET]
111
112	ldr	r1, [r0, #EMIF_LPDDR2_NVM_TIMING_SHDW]
113	str     r1, [r2, #EMIF_LPDDR2_NVM_TIM_SHDW_OFFSET]
114
115	ldr	r1, [r0, #EMIF_DLL_CALIB_CTRL]
116	str     r1, [r2, #EMIF_DLL_CALIB_CTRL_VAL_OFFSET]
117
118	ldr	r1, [r0, #EMIF_DLL_CALIB_CTRL_SHDW]
119	str     r1, [r2, #EMIF_DLL_CALIB_CTRL_VAL_SHDW_OFFSET]
120
121	/* Loop and save entire block of emif phy regs */
122	mov	r5, #0x0
123	add	r4, r2, #EMIF_EXT_PHY_CTRL_VALS_OFFSET
124	add	r3, r0, #EMIF_EXT_PHY_CTRL_1
125ddr_phy_ctrl_save:
126	ldr	r1, [r3, r5]
127	str	r1, [r4, r5]
128	add	r5, r5, #0x4
129	cmp	r5, #AM43XX_EMIF_PHY_CTRL_REG_COUNT
130	bne	ddr_phy_ctrl_save
131
132emif_skip_save_extra_regs:
133	ldmfd	sp!, {r4 - r11, pc}	@ restore regs and return
134ENDPROC(ti_emif_save_context)
135
136/*
137 * void ti_emif_restore_context(void)
138 *
139 * Used during resume to restore the context of all required EMIF registers
140 * from local memory after the EMIF has lost context during a sleep transition.
141 * Operates on the PHYSICAL address of the EMIF.
142 */
143ENTRY(ti_emif_restore_context)
144	adr	r4, ti_emif_pm_sram_data
145	ldr	r0, [r4, #EMIF_PM_BASE_ADDR_PHYS_OFFSET]
146	ldr	r2, [r4, #EMIF_PM_REGS_PHYS_OFFSET]
147
148	/* Config EMIF Timings */
149	ldr     r1, [r2, #EMIF_DDR_PHY_CTLR_1_OFFSET]
150	str	r1, [r0, #EMIF_DDR_PHY_CTRL_1]
151	str	r1, [r0, #EMIF_DDR_PHY_CTRL_1_SHDW]
152
153	ldr     r1, [r2, #EMIF_TIMING1_VAL_OFFSET]
154	str	r1, [r0, #EMIF_SDRAM_TIMING_1]
155	str	r1, [r0, #EMIF_SDRAM_TIMING_1_SHDW]
156
157	ldr     r1, [r2, #EMIF_TIMING2_VAL_OFFSET]
158	str	r1, [r0, #EMIF_SDRAM_TIMING_2]
159	str	r1, [r0, #EMIF_SDRAM_TIMING_2_SHDW]
160
161	ldr     r1, [r2, #EMIF_TIMING3_VAL_OFFSET]
162	str	r1, [r0, #EMIF_SDRAM_TIMING_3]
163	str	r1, [r0, #EMIF_SDRAM_TIMING_3_SHDW]
164
165	ldr     r1, [r2, #EMIF_REF_CTRL_VAL_OFFSET]
166	str	r1, [r0, #EMIF_SDRAM_REFRESH_CONTROL]
167	str	r1, [r0, #EMIF_SDRAM_REFRESH_CTRL_SHDW]
168
169	ldr     r1, [r2, #EMIF_PMCR_VAL_OFFSET]
170	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
171
172	ldr     r1, [r2, #EMIF_PMCR_SHDW_VAL_OFFSET]
173	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CTRL_SHDW]
174
175	ldr     r1, [r2, #EMIF_COS_CONFIG_OFFSET]
176	str	r1, [r0, #EMIF_COS_CONFIG]
177
178	ldr     r1, [r2, #EMIF_PRIORITY_TO_COS_MAPPING_OFFSET]
179	str	r1, [r0, #EMIF_PRIORITY_TO_CLASS_OF_SERVICE_MAPPING]
180
181	ldr	r1, [r2, #EMIF_CONNECT_ID_SERV_1_MAP_OFFSET]
182	str	r1, [r0, #EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_1_MAPPING]
183
184	ldr     r1, [r2, #EMIF_CONNECT_ID_SERV_2_MAP_OFFSET]
185	str	r1, [r0, #EMIF_CONNECTION_ID_TO_CLASS_OF_SERVICE_2_MAPPING]
186
187	ldr     r1, [r2, #EMIF_OCP_CONFIG_VAL_OFFSET]
188	str	r1, [r0, #EMIF_OCP_CONFIG]
189
190	ldr	r5, [r4, #EMIF_PM_CONFIG_OFFSET]
191	cmp	r5, #EMIF_SRAM_AM43_REG_LAYOUT
192	bne	emif_skip_restore_extra_regs
193
194	ldr     r1, [r2, #EMIF_RD_WR_LEVEL_RAMP_CTRL_OFFSET]
195	str	r1, [r0, #EMIF_READ_WRITE_LEVELING_RAMP_CONTROL]
196
197	ldr     r1, [r2, #EMIF_RD_WR_EXEC_THRESH_OFFSET]
198	str	r1, [r0, #EMIF_READ_WRITE_EXECUTION_THRESHOLD]
199
200	ldr     r1, [r2, #EMIF_LPDDR2_NVM_TIM_OFFSET]
201	str	r1, [r0, #EMIF_LPDDR2_NVM_TIMING]
202
203	ldr     r1, [r2, #EMIF_LPDDR2_NVM_TIM_SHDW_OFFSET]
204	str	r1, [r0, #EMIF_LPDDR2_NVM_TIMING_SHDW]
205
206	ldr     r1, [r2, #EMIF_DLL_CALIB_CTRL_VAL_OFFSET]
207	str	r1, [r0, #EMIF_DLL_CALIB_CTRL]
208
209	ldr     r1, [r2, #EMIF_DLL_CALIB_CTRL_VAL_SHDW_OFFSET]
210	str	r1, [r0, #EMIF_DLL_CALIB_CTRL_SHDW]
211
212	ldr     r1, [r2, #EMIF_ZQCFG_VAL_OFFSET]
213	str	r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG]
214
215	/* Loop and restore entire block of emif phy regs */
216	mov	r5, #0x0
217	/* Load ti_emif_regs_amx3 + EMIF_EXT_PHY_CTRL_VALS_OFFSET for address
218	 * to phy register save space
219	 */
220	add	r3, r2, #EMIF_EXT_PHY_CTRL_VALS_OFFSET
221	add	r4, r0, #EMIF_EXT_PHY_CTRL_1
222ddr_phy_ctrl_restore:
223	ldr	r1, [r3, r5]
224	str	r1, [r4, r5]
225	add	r5, r5, #0x4
226	cmp	r5, #AM43XX_EMIF_PHY_CTRL_REG_COUNT
227	bne	ddr_phy_ctrl_restore
228
229emif_skip_restore_extra_regs:
230	/*
231	 * Output impedence calib needed only for DDR3
232	 * but since the initial state of this will be
233	 * disabled for DDR2 no harm in restoring the
234	 * old configuration
235	 */
236	ldr     r1, [r2, #EMIF_ZQCFG_VAL_OFFSET]
237	str	r1, [r0, #EMIF_SDRAM_OUTPUT_IMPEDANCE_CALIBRATION_CONFIG]
238
239	/* Write to sdcfg last for DDR2 only */
240	ldr	r1, [r2, #EMIF_SDCFG_VAL_OFFSET]
241	and	r2, r1, #SDRAM_TYPE_MASK
242	cmp	r2, #EMIF_SDCFG_TYPE_DDR2
243	streq	r1, [r0, #EMIF_SDRAM_CONFIG]
244
245	mov	pc, lr
246ENDPROC(ti_emif_restore_context)
247
248/*
249 * void ti_emif_run_hw_leveling(void)
250 *
251 * Used during resume to run hardware leveling again and restore the
252 * configuration of the EMIF PHY, only for DDR3.
253 */
254ENTRY(ti_emif_run_hw_leveling)
255	adr	r4, ti_emif_pm_sram_data
256	ldr	r0, [r4, #EMIF_PM_BASE_ADDR_PHYS_OFFSET]
257
258	ldr	r3, [r0, #EMIF_READ_WRITE_LEVELING_CONTROL]
259	orr	r3, r3, #RDWRLVLFULL_START
260	ldr	r2, [r0, #EMIF_SDRAM_CONFIG]
261	and	r2, r2, #SDRAM_TYPE_MASK
262	cmp	r2, #EMIF_SDCFG_TYPE_DDR3
263	bne	skip_hwlvl
264
265	str	r3, [r0, #EMIF_READ_WRITE_LEVELING_CONTROL]
266
267	/*
268	 * If EMIF registers are touched during initial stage of HW
269	 * leveling sequence there will be an L3 NOC timeout error issued
270	 * as the EMIF will not respond, which is not fatal, but it is
271	 * avoidable. This small wait loop is enough time for this condition
272	 * to clear, even at worst case of CPU running at max speed of 1Ghz.
273	 */
274	mov	r2, #0x2000
2751:
276	subs	r2, r2, #0x1
277	bne	1b
278
279	/* Bit clears when operation is complete */
2802:	ldr     r1, [r0, #EMIF_READ_WRITE_LEVELING_CONTROL]
281	tst     r1, #RDWRLVLFULL_START
282	bne     2b
283
284skip_hwlvl:
285	mov	pc, lr
286ENDPROC(ti_emif_run_hw_leveling)
287
288/*
289 * void ti_emif_enter_sr(void)
290 *
291 * Programs the EMIF to tell the SDRAM to enter into self-refresh
292 * mode during a sleep transition. Operates on the VIRTUAL address
293 * of the EMIF.
294 */
295ENTRY(ti_emif_enter_sr)
296	stmfd   sp!, {r4 - r11, lr}     @ save registers on stack
297
298	adr	r4, ti_emif_pm_sram_data
299	ldr	r0, [r4, #EMIF_PM_BASE_ADDR_VIRT_OFFSET]
300	ldr	r2, [r4, #EMIF_PM_REGS_VIRT_OFFSET]
301
302	ldr	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
303	bic	r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK
304	orr	r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE
305	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
306
307	ldmfd	sp!, {r4 - r11, pc}	@ restore regs and return
308ENDPROC(ti_emif_enter_sr)
309
310/*
311 * void ti_emif_exit_sr(void)
312 *
313 * Programs the EMIF to tell the SDRAM to exit self-refresh mode
314 * after a sleep transition. Operates on the PHYSICAL address of
315 * the EMIF.
316 */
317ENTRY(ti_emif_exit_sr)
318	adr	r4, ti_emif_pm_sram_data
319	ldr	r0, [r4, #EMIF_PM_BASE_ADDR_PHYS_OFFSET]
320	ldr	r2, [r4, #EMIF_PM_REGS_PHYS_OFFSET]
321
322	/*
323	 * Toggle EMIF to exit refresh mode:
324	 * if EMIF lost context, PWR_MGT_CTRL is currently 0, writing disable
325	 *   (0x0), wont do diddly squat! so do a toggle from SR(0x2) to disable
326	 *   (0x0) here.
327	 * *If* EMIF did not lose context, nothing broken as we write the same
328	 *   value(0x2) to reg before we write a disable (0x0).
329	 */
330	ldr	r1, [r2, #EMIF_PMCR_VAL_OFFSET]
331	bic	r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK
332	orr	r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE
333	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
334	bic	r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK
335	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
336
337        /* Wait for EMIF to become ready */
3381:	ldr     r1, [r0, #EMIF_STATUS]
339	tst     r1, #EMIF_STATUS_READY
340	beq     1b
341
342	mov	pc, lr
343ENDPROC(ti_emif_exit_sr)
344
345/*
346 * void ti_emif_abort_sr(void)
347 *
348 * Disables self-refresh after a failed transition to a low-power
349 * state so the kernel can jump back to DDR and follow abort path.
350 * Operates on the VIRTUAL address of the EMIF.
351 */
352ENTRY(ti_emif_abort_sr)
353	stmfd   sp!, {r4 - r11, lr}     @ save registers on stack
354
355	adr	r4, ti_emif_pm_sram_data
356	ldr	r0, [r4, #EMIF_PM_BASE_ADDR_VIRT_OFFSET]
357	ldr	r2, [r4, #EMIF_PM_REGS_VIRT_OFFSET]
358
359	ldr	r1, [r2, #EMIF_PMCR_VAL_OFFSET]
360	bic	r1, r1, #EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK
361	str	r1, [r0, #EMIF_POWER_MANAGEMENT_CONTROL]
362
363	/* Wait for EMIF to become ready */
3641:	ldr     r1, [r0, #EMIF_STATUS]
365	tst     r1, #EMIF_STATUS_READY
366	beq     1b
367
368	ldmfd	sp!, {r4 - r11, pc}	@ restore regs and return
369ENDPROC(ti_emif_abort_sr)
370
371	.align 3
372ENTRY(ti_emif_pm_sram_data)
373	.space EMIF_PM_DATA_SIZE
374ENTRY(ti_emif_sram_sz)
375        .word   . - ti_emif_save_context
376