1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * Copyright (C) 2007, Guennadi Liakhovetski <lg@denx.de>
4 *
5 * (C) Copyright 2009 Freescale Semiconductor, Inc.
6 */
7
8#include <config.h>
9#include <asm/arch/imx-regs.h>
10#include <generated/asm-offsets.h>
11#include <linux/linkage.h>
12
13.section ".text.init", "x"
14
15.macro init_arm_erratum
16	/* ARM erratum ID #468414 */
17	mrc 15, 0, r1, c1, c0, 1
18	orr r1, r1, #(1 << 5)    /* enable L1NEON bit */
19	mcr 15, 0, r1, c1, c0, 1
20.endm
21
22/*
23 * L2CC Cache setup/invalidation/disable
24 */
25.macro init_l2cc
26	/* explicitly disable L2 cache */
27	mrc 15, 0, r0, c1, c0, 1
28	bic r0, r0, #0x2
29	mcr 15, 0, r0, c1, c0, 1
30
31	/* reconfigure L2 cache aux control reg */
32	ldr r0, =0xC0 |			/* tag RAM */ \
33		 0x4 |			/* data RAM */ \
34		 1 << 24 |		/* disable write allocate delay */ \
35		 1 << 23 |		/* disable write allocate combine */ \
36		 1 << 22		/* disable write allocate */
37
38#if defined(CONFIG_MX51)
39	ldr r3, [r4, #ROM_SI_REV]
40	cmp r3, #0x10
41
42	/* disable write combine for TO 2 and lower revs */
43	orrls r0, r0, #1 << 25
44#endif
45
46	mcr 15, 1, r0, c9, c0, 2
47
48	/* enable L2 cache */
49	mrc 15, 0, r0, c1, c0, 1
50	orr r0, r0, #2
51	mcr 15, 0, r0, c1, c0, 1
52
53.endm /* init_l2cc */
54
55/* AIPS setup - Only setup MPROTx registers.
56 * The PACR default values are good.*/
57.macro init_aips
58	/*
59	 * Set all MPROTx to be non-bufferable, trusted for R/W,
60	 * not forced to user-mode.
61	 */
62	ldr r0, =AIPS1_BASE_ADDR
63	ldr r1, =0x77777777
64	str r1, [r0, #0x0]
65	str r1, [r0, #0x4]
66	ldr r0, =AIPS2_BASE_ADDR
67	str r1, [r0, #0x0]
68	str r1, [r0, #0x4]
69	/*
70	 * Clear the on and off peripheral modules Supervisor Protect bit
71	 * for SDMA to access them. Did not change the AIPS control registers
72	 * (offset 0x20) access type
73	 */
74.endm /* init_aips */
75
76/* M4IF setup */
77.macro init_m4if
78#ifdef CONFIG_MX51
79	/* VPU and IPU given higher priority (0x4)
80	 * IPU accesses with ID=0x1 given highest priority (=0xA)
81	 */
82	ldr r0, =M4IF_BASE_ADDR
83
84	ldr r1, =0x00000203
85	str r1, [r0, #0x40]
86
87	str r4, [r0, #0x44]
88
89	ldr r1, =0x00120125
90	str r1, [r0, #0x9C]
91
92	ldr r1, =0x001901A3
93	str r1, [r0, #0x48]
94
95#endif
96.endm /* init_m4if */
97
98.macro setup_pll pll, freq
99	ldr r0, =\pll
100	adr r2, W_DP_\freq
101	bl setup_pll_func
102.endm
103
104#define W_DP_OP		0
105#define W_DP_MFD	4
106#define W_DP_MFN	8
107
108setup_pll_func:
109	ldr r1, =0x00001232
110	str r1, [r0, #PLL_DP_CTL] /* Set DPLL ON (set UPEN bit): BRMO=1 */
111	mov r1, #0x2
112	str r1, [r0, #PLL_DP_CONFIG] /* Enable auto-restart AREN bit */
113
114	ldr r1, [r2, #W_DP_OP]
115	str r1, [r0, #PLL_DP_OP]
116	str r1, [r0, #PLL_DP_HFS_OP]
117
118	ldr r1, [r2, #W_DP_MFD]
119	str r1, [r0, #PLL_DP_MFD]
120	str r1, [r0, #PLL_DP_HFS_MFD]
121
122	ldr r1, [r2, #W_DP_MFN]
123	str r1, [r0, #PLL_DP_MFN]
124	str r1, [r0, #PLL_DP_HFS_MFN]
125
126	ldr r1, =0x00001232
127	str r1, [r0, #PLL_DP_CTL]
1281:	ldr r1, [r0, #PLL_DP_CTL]
129	ands r1, r1, #0x1
130	beq 1b
131
132	/* r10 saved upper lr */
133	mov pc, lr
134
135.macro setup_pll_errata pll, freq
136	ldr r2, =\pll
137	str r4, [r2, #PLL_DP_CONFIG] /* Disable auto-restart AREN bit */
138	ldr r1, =0x00001236
139	str r1, [r2, #PLL_DP_CTL]    /* Restart PLL with PLM=1 */
1401:	ldr r1, [r2, #PLL_DP_CTL]    /* Wait for lock */
141	ands r1, r1, #0x1
142	beq 1b
143
144	ldr r5, \freq
145	str r5, [r2, #PLL_DP_MFN]    /* Modify MFN value */
146	str r5, [r2, #PLL_DP_HFS_MFN]
147
148	mov r1, #0x1
149	str r1, [r2, #PLL_DP_CONFIG] /* Reload MFN value */
150
1512:	ldr r1, [r2, #PLL_DP_CONFIG]
152	tst r1, #1
153	bne 2b
154
155	ldr r1, =100		     /* Wait at least 4 us */
1563:	subs r1, r1, #1
157	bge 3b
158
159	mov r1, #0x2
160	str r1, [r2, #PLL_DP_CONFIG] /* Enable auto-restart AREN bit */
161.endm
162
163.macro init_clock
164#if defined (CONFIG_MX51)
165	ldr r0, =CCM_BASE_ADDR
166
167	/* Gate of clocks to the peripherals first */
168	ldr r1, =0x3FFFFFFF
169	str r1, [r0, #CLKCTL_CCGR0]
170	str r4, [r0, #CLKCTL_CCGR1]
171	str r4, [r0, #CLKCTL_CCGR2]
172	str r4, [r0, #CLKCTL_CCGR3]
173
174	ldr r1, =0x00030000
175	str r1, [r0, #CLKCTL_CCGR4]
176	ldr r1, =0x00FFF030
177	str r1, [r0, #CLKCTL_CCGR5]
178	ldr r1, =0x00000300
179	str r1, [r0, #CLKCTL_CCGR6]
180
181	/* Disable IPU and HSC dividers */
182	mov r1, #0x60000
183	str r1, [r0, #CLKCTL_CCDR]
184
185	/* Make sure to switch the DDR away from PLL 1 */
186	ldr r1, =0x19239145
187	str r1, [r0, #CLKCTL_CBCDR]
188	/* make sure divider effective */
1891:	ldr r1, [r0, #CLKCTL_CDHIPR]
190	cmp r1, #0x0
191	bne 1b
192
193	/* Switch ARM to step clock */
194	mov r1, #0x4
195	str r1, [r0, #CLKCTL_CCSR]
196
197#if defined(CONFIG_MX51_PLL_ERRATA)
198	setup_pll PLL1_BASE_ADDR, 864
199	setup_pll_errata PLL1_BASE_ADDR, W_DP_MFN_800_DIT
200#else
201	setup_pll PLL1_BASE_ADDR, 800
202#endif
203
204	setup_pll PLL3_BASE_ADDR, 665
205
206	/* Switch peripheral to PLL 3 */
207	ldr r0, =CCM_BASE_ADDR
208	ldr r1, =0x000010C0 | CONFIG_SYS_DDR_CLKSEL
209	str r1, [r0, #CLKCTL_CBCMR]
210	ldr r1, =0x13239145
211	str r1, [r0, #CLKCTL_CBCDR]
212	setup_pll PLL2_BASE_ADDR, 665
213
214	/* Switch peripheral to PLL2 */
215	ldr r0, =CCM_BASE_ADDR
216	ldr r1, =0x19239145
217	str r1, [r0, #CLKCTL_CBCDR]
218	ldr r1, =0x000020C0 | CONFIG_SYS_DDR_CLKSEL
219	str r1, [r0, #CLKCTL_CBCMR]
220
221	setup_pll PLL3_BASE_ADDR, 216
222
223	/* Set the platform clock dividers */
224	ldr r0, =ARM_BASE_ADDR
225	ldr r1, =0x00000725
226	str r1, [r0, #0x14]
227
228	ldr r0, =CCM_BASE_ADDR
229
230	/* Run 3.0 at Full speed, for other TO's wait till we increase VDDGP */
231	ldr r3, [r4, #ROM_SI_REV]
232	cmp r3, #0x10
233	movls r1, #0x1
234	movhi r1, #0
235
236	str r1, [r0, #CLKCTL_CACRR]
237
238	/* Switch ARM back to PLL 1 */
239	str r4, [r0, #CLKCTL_CCSR]
240
241	/* setup the rest */
242	/* Use lp_apm (24MHz) source for perclk */
243	ldr r1, =0x000020C2 | CONFIG_SYS_DDR_CLKSEL
244	str r1, [r0, #CLKCTL_CBCMR]
245	/* ddr clock from PLL 1, all perclk dividers are 1 since using 24MHz */
246	ldr r1, =CONFIG_SYS_CLKTL_CBCDR
247	str r1, [r0, #CLKCTL_CBCDR]
248
249	/* Restore the default values in the Gate registers */
250	ldr r1, =0xFFFFFFFF
251	str r1, [r0, #CLKCTL_CCGR0]
252	str r1, [r0, #CLKCTL_CCGR1]
253	str r1, [r0, #CLKCTL_CCGR2]
254	str r1, [r0, #CLKCTL_CCGR3]
255	str r1, [r0, #CLKCTL_CCGR4]
256	str r1, [r0, #CLKCTL_CCGR5]
257	str r1, [r0, #CLKCTL_CCGR6]
258
259	/* Use PLL 2 for UART's, get 66.5MHz from it */
260	ldr r1, =0xA5A2A020
261	str r1, [r0, #CLKCTL_CSCMR1]
262	ldr r1, =0x00C30321
263	str r1, [r0, #CLKCTL_CSCDR1]
264	/* make sure divider effective */
2651:	ldr r1, [r0, #CLKCTL_CDHIPR]
266	cmp r1, #0x0
267	bne 1b
268
269	str r4, [r0, #CLKCTL_CCDR]
270
271	/* for cko - for ARM div by 8 */
272	mov r1, #0x000A0000
273	add r1, r1, #0x00000F0
274	str r1, [r0, #CLKCTL_CCOSR]
275#else	/* CONFIG_MX53 */
276	ldr r0, =CCM_BASE_ADDR
277
278	/* Gate of clocks to the peripherals first */
279	ldr r1, =0x3FFFFFFF
280	str r1, [r0, #CLKCTL_CCGR0]
281	str r4, [r0, #CLKCTL_CCGR1]
282	str r4, [r0, #CLKCTL_CCGR2]
283	str r4, [r0, #CLKCTL_CCGR3]
284	str r4, [r0, #CLKCTL_CCGR7]
285	ldr r1, =0x00030000
286	str r1, [r0, #CLKCTL_CCGR4]
287	ldr r1, =0x00FFF030
288	str r1, [r0, #CLKCTL_CCGR5]
289	ldr r1, =0x0F00030F
290	str r1, [r0, #CLKCTL_CCGR6]
291
292	/* Switch ARM to step clock */
293	mov r1, #0x4
294	str r1, [r0, #CLKCTL_CCSR]
295
296	setup_pll PLL1_BASE_ADDR, 800
297
298	setup_pll PLL3_BASE_ADDR, 400
299
300	/* Switch peripheral to PLL3 */
301	ldr r0, =CCM_BASE_ADDR
302	ldr r1, =0x00015154
303	str r1, [r0, #CLKCTL_CBCMR]
304	ldr r1, =0x02898945
305	str r1, [r0, #CLKCTL_CBCDR]
306	/* make sure change is effective */
3071:      ldr r1, [r0, #CLKCTL_CDHIPR]
308	cmp r1, #0x0
309	bne 1b
310
311	setup_pll PLL2_BASE_ADDR, 400
312
313	/* Switch peripheral to PLL2 */
314	ldr r0, =CCM_BASE_ADDR
315	ldr r1, =0x00888945
316	str r1, [r0, #CLKCTL_CBCDR]
317
318	ldr r1, =0x00016154
319	str r1, [r0, #CLKCTL_CBCMR]
320
321	/*change uart clk parent to pll2*/
322	ldr r1, [r0, #CLKCTL_CSCMR1]
323	and r1, r1, #0xfcffffff
324	orr r1, r1, #0x01000000
325	str r1, [r0, #CLKCTL_CSCMR1]
326
327	/* make sure change is effective */
3281:      ldr r1, [r0, #CLKCTL_CDHIPR]
329	cmp r1, #0x0
330	bne 1b
331
332	setup_pll PLL3_BASE_ADDR, 216
333
334	setup_pll PLL4_BASE_ADDR, 455
335
336	/* Set the platform clock dividers */
337	ldr r0, =ARM_BASE_ADDR
338	ldr r1, =0x00000124
339	str r1, [r0, #0x14]
340
341	ldr r0, =CCM_BASE_ADDR
342	mov r1, #0
343	str r1, [r0, #CLKCTL_CACRR]
344
345	/* Switch ARM back to PLL 1. */
346	mov r1, #0x0
347	str r1, [r0, #CLKCTL_CCSR]
348
349	/* make uart div=6 */
350	ldr r1, [r0, #CLKCTL_CSCDR1]
351	and r1, r1, #0xffffffc0
352	orr r1, r1, #0x0a
353	str r1, [r0, #CLKCTL_CSCDR1]
354
355	/* Restore the default values in the Gate registers */
356	ldr r1, =0xFFFFFFFF
357	str r1, [r0, #CLKCTL_CCGR0]
358	str r1, [r0, #CLKCTL_CCGR1]
359	str r1, [r0, #CLKCTL_CCGR2]
360	str r1, [r0, #CLKCTL_CCGR3]
361	str r1, [r0, #CLKCTL_CCGR4]
362	str r1, [r0, #CLKCTL_CCGR5]
363	str r1, [r0, #CLKCTL_CCGR6]
364	str r1, [r0, #CLKCTL_CCGR7]
365
366	mov r1, #0x00000
367	str r1, [r0, #CLKCTL_CCDR]
368
369	/* for cko - for ARM div by 8 */
370	mov r1, #0x000A0000
371	add r1, r1, #0x00000F0
372	str r1, [r0, #CLKCTL_CCOSR]
373
374#endif	/* CONFIG_MX53 */
375.endm
376
377ENTRY(lowlevel_init)
378	mov r10, lr
379	mov r4, #0	/* Fix R4 to 0 */
380
381#if defined(CONFIG_SYS_MAIN_PWR_ON)
382	ldr r0, =GPIO1_BASE_ADDR
383	ldr r1, [r0, #0x0]
384	orr r1, r1, #1 << 23
385	str r1, [r0, #0x0]
386	ldr r1, [r0, #0x4]
387	orr r1, r1, #1 << 23
388	str r1, [r0, #0x4]
389#endif
390
391	init_arm_erratum
392
393	init_l2cc
394
395	init_aips
396
397	init_m4if
398
399	init_clock
400
401	mov pc, r10
402ENDPROC(lowlevel_init)
403
404/* Board level setting value */
405#if defined(CONFIG_MX51_PLL_ERRATA)
406W_DP_864:		.word DP_OP_864
407			.word DP_MFD_864
408			.word DP_MFN_864
409W_DP_MFN_800_DIT:	.word DP_MFN_800_DIT
410#else
411W_DP_800:		.word DP_OP_800
412			.word DP_MFD_800
413			.word DP_MFN_800
414#endif
415#if defined(CONFIG_MX51)
416W_DP_665:		.word DP_OP_665
417			.word DP_MFD_665
418			.word DP_MFN_665
419#endif
420W_DP_216:		.word DP_OP_216
421			.word DP_MFD_216
422			.word DP_MFN_216
423W_DP_400:               .word DP_OP_400
424			.word DP_MFD_400
425			.word DP_MFN_400
426W_DP_455:               .word DP_OP_455
427			.word DP_MFD_455
428			.word DP_MFN_455
429