1/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * Memory Setup stuff - taken from blob memsetup.S
4 *
5 * Copyright (C) 2009 Samsung Electronics
6 * Kyungmin Park <kyungmin.park@samsung.com>
7 */
8
9#include <config.h>
10#include <asm/arch/cpu.h>
11#include <asm/arch/clock.h>
12#include <asm/arch/power.h>
13
14/*
15 * Register usages:
16 *
17 * r5 has zero always
18 * r7 has S5PC100 GPIO base, 0xE0300000
19 * r8 has real GPIO base, 0xE0300000, 0xE0200000 at S5PC100, S5PC110 repectively
20 * r9 has Mobile DDR size, 1 means 1GiB, 2 means 2GiB and so on
21 */
22
23	.globl lowlevel_init
24lowlevel_init:
25	mov	r11, lr
26
27	/* r5 has always zero */
28	mov	r5, #0
29
30	ldr	r7, =S5PC100_GPIO_BASE
31	ldr	r8, =S5PC100_GPIO_BASE
32	/* Read CPU ID */
33	ldr	r2, =S5PC110_PRO_ID
34	ldr	r0, [r2]
35	mov	r1, #0x00010000
36	and	r0, r0, r1
37	cmp	r0, r5
38	beq	100f
39	ldr	r8, =S5PC110_GPIO_BASE
40100:
41	/* Turn on KEY_LED_ON [GPJ4(1)] XMSMWEN */
42	cmp	r7, r8
43	beq	skip_check_didle			@ Support C110 only
44
45	ldr	r0, =S5PC110_RST_STAT
46	ldr	r1, [r0]
47	and	r1, r1, #0x000D0000
48	cmp	r1, #(0x1 << 19)			@ DEEPIDLE_WAKEUP
49	beq	didle_wakeup
50	cmp	r7, r8
51
52skip_check_didle:
53	addeq	r0, r8, #0x280				@ S5PC100_GPIO_J4
54	addne	r0, r8, #0x2C0				@ S5PC110_GPIO_J4
55	ldr	r1, [r0, #0x0]				@ GPIO_CON_OFFSET
56	bic	r1, r1, #(0xf << 4)			@ 1 * 4-bit
57	orr	r1, r1, #(0x1 << 4)
58	str	r1, [r0, #0x0]				@ GPIO_CON_OFFSET
59
60	ldr	r1, [r0, #0x4]				@ GPIO_DAT_OFFSET
61	bic	r1, r1, #(1 << 1)
62	str	r1, [r0, #0x4]				@ GPIO_DAT_OFFSET
63
64	/* Don't setup at s5pc100 */
65	beq	100f
66
67	/*
68	 * Initialize Async Register Setting for EVT1
69	 * Because we are setting EVT1 as the default value of EVT0,
70	 * setting EVT0 as well does not make things worse.
71	 * Thus, for the simplicity, we set for EVT0, too
72	 *
73	 * The "Async Registers" are:
74	 *	0xE0F0_0000
75	 *	0xE1F0_0000
76	 *	0xF180_0000
77	 *	0xF190_0000
78	 *	0xF1A0_0000
79	 *	0xF1B0_0000
80	 *	0xF1C0_0000
81	 *	0xF1D0_0000
82	 *	0xF1E0_0000
83	 *	0xF1F0_0000
84	 *	0xFAF0_0000
85	 */
86	ldr     r0, =0xe0f00000
87	ldr     r1, [r0]
88	bic     r1, r1, #0x1
89	str     r1, [r0]
90
91	ldr     r0, =0xe1f00000
92	ldr     r1, [r0]
93	bic     r1, r1, #0x1
94	str     r1, [r0]
95
96	ldr     r0, =0xf1800000
97	ldr     r1, [r0]
98	bic     r1, r1, #0x1
99	str     r1, [r0]
100
101	ldr     r0, =0xf1900000
102	ldr     r1, [r0]
103	bic     r1, r1, #0x1
104	str     r1, [r0]
105
106	ldr     r0, =0xf1a00000
107	ldr     r1, [r0]
108	bic     r1, r1, #0x1
109	str     r1, [r0]
110
111	ldr     r0, =0xf1b00000
112	ldr     r1, [r0]
113	bic     r1, r1, #0x1
114	str     r1, [r0]
115
116	ldr     r0, =0xf1c00000
117	ldr     r1, [r0]
118	bic     r1, r1, #0x1
119	str     r1, [r0]
120
121	ldr     r0, =0xf1d00000
122	ldr     r1, [r0]
123	bic     r1, r1, #0x1
124	str     r1, [r0]
125
126	ldr     r0, =0xf1e00000
127	ldr     r1, [r0]
128	bic     r1, r1, #0x1
129	str     r1, [r0]
130
131	ldr     r0, =0xf1f00000
132	ldr     r1, [r0]
133	bic     r1, r1, #0x1
134	str     r1, [r0]
135
136	ldr     r0, =0xfaf00000
137	ldr     r1, [r0]
138	bic     r1, r1, #0x1
139	str     r1, [r0]
140
141	/*
142	 * Diable ABB block to reduce sleep current at low temperature
143	 * Note that it's hidden register setup don't modify it
144	 */
145	ldr	r0, =0xE010C300
146	ldr	r1, =0x00800000
147	str	r1, [r0]
148
149100:
150	/* IO retension release */
151	ldreq	r0, =S5PC100_OTHERS			@ 0xE0108200
152	ldrne	r0, =S5PC110_OTHERS			@ 0xE010E000
153	ldr	r1, [r0]
154	ldreq	r2, =(1 << 31)				@ IO_RET_REL
155	ldrne	r2, =((1 << 31) | (1 << 30) | (1 << 29) | (1 << 28))
156	orr	r1, r1, r2
157	/* Do not release retention here for S5PC110 */
158	streq	r1, [r0]
159
160	/* Disable Watchdog */
161	ldreq	r0, =S5PC100_WATCHDOG_BASE		@ 0xEA200000
162	ldrne	r0, =S5PC110_WATCHDOG_BASE		@ 0xE2700000
163	str	r5, [r0]
164
165	/* setting SRAM */
166	ldreq	r0, =S5PC100_SROMC_BASE
167	ldrne	r0, =S5PC110_SROMC_BASE
168	ldr	r1, =0x9
169	str	r1, [r0]
170
171	/* S5PC100 has 3 groups of interrupt sources */
172	ldreq	r0, =S5PC100_VIC0_BASE			@ 0xE4000000
173	ldrne	r0, =S5PC110_VIC0_BASE			@ 0xF2000000
174	add	r1, r0, #0x00100000
175	add	r2, r0, #0x00200000
176
177	/* Disable all interrupts (VIC0, VIC1 and VIC2) */
178	mvn	r3, #0x0
179	str	r3, [r0, #0x14]				@ INTENCLEAR
180	str	r3, [r1, #0x14]				@ INTENCLEAR
181	str	r3, [r2, #0x14]				@ INTENCLEAR
182
183	/* Set all interrupts as IRQ */
184	str	r5, [r0, #0xc]				@ INTSELECT
185	str	r5, [r1, #0xc]				@ INTSELECT
186	str	r5, [r2, #0xc]				@ INTSELECT
187
188	/* Pending Interrupt Clear */
189	str	r5, [r0, #0xf00]			@ INTADDRESS
190	str	r5, [r1, #0xf00]			@ INTADDRESS
191	str	r5, [r2, #0xf00]			@ INTADDRESS
192
193	/* for UART */
194	bl	uart_asm_init
195
196	bl	internal_ram_init
197
198	cmp	r7, r8
199	/* Clear wakeup status register */
200	ldreq	r0, =S5PC100_WAKEUP_STAT
201	ldrne	r0, =S5PC110_WAKEUP_STAT
202	ldr	r1, [r0]
203	str	r1, [r0]
204
205	/* IO retension release */
206	ldreq	r0, =S5PC100_OTHERS			@ 0xE0108200
207	ldrne	r0, =S5PC110_OTHERS			@ 0xE010E000
208	ldr	r1, [r0]
209	ldreq	r2, =(1 << 31)				@ IO_RET_REL
210	ldrne	r2, =((1 << 31) | (1 << 30) | (1 << 29) | (1 << 28))
211	orr	r1, r1, r2
212	str	r1, [r0]
213
214	b	1f
215
216didle_wakeup:
217	/* Wait when APLL is locked */
218	ldr	r0, =0xE0100100			@ S5PC110_APLL_CON
219lockloop:
220	ldr	r1, [r0]
221	and	r1, r1, #(1 << 29)
222	cmp	r1, #(1 << 29)
223	bne	lockloop
224
225	ldr	r0, =S5PC110_INFORM0
226	ldr	r1, [r0]
227	mov	pc, r1
228	nop
229	nop
230	nop
231	nop
232	nop
233
2341:
235	mov	lr, r11
236	mov	pc, lr
237
238/*
239 * system_clock_init: Initialize core clock and bus clock.
240 * void system_clock_init(void)
241 */
242system_clock_init:
243	ldr	r0, =S5PC110_CLOCK_BASE		@ 0xE0100000
244
245	/* Check S5PC100 */
246	cmp	r7, r8
247	bne	110f
248100:
249	/* Set Lock Time */
250	ldr	r1, =0xe10			@ Locktime : 0xe10 = 3600
251	str	r1, [r0, #0x000]		@ S5PC100_APLL_LOCK
252	str	r1, [r0, #0x004]		@ S5PC100_MPLL_LOCK
253	str	r1, [r0, #0x008]		@ S5PC100_EPLL_LOCK
254	str	r1, [r0, #0x00C]		@ S5PC100_HPLL_LOCK
255
256	/* S5P_APLL_CON */
257	ldr	r1, =0x81bc0400		@ SDIV 0, PDIV 4, MDIV 444 (1333MHz)
258	str	r1, [r0, #0x100]
259	/* S5P_MPLL_CON */
260	ldr	r1, =0x80590201		@ SDIV 1, PDIV 2, MDIV 89 (267MHz)
261	str	r1, [r0, #0x104]
262	/* S5P_EPLL_CON */
263	ldr	r1, =0x80870303		@ SDIV 3, PDIV 3, MDIV 135 (67.5MHz)
264	str	r1, [r0, #0x108]
265	/* S5P_HPLL_CON */
266	ldr	r1, =0x80600603		@ SDIV 3, PDIV 6, MDIV 96
267	str	r1, [r0, #0x10C]
268
269	ldr     r1, [r0, #0x300]
270	ldr     r2, =0x00003fff
271	bic     r1, r1, r2
272	ldr     r2, =0x00011301
273
274	orr	r1, r1, r2
275	str	r1, [r0, #0x300]
276	ldr     r1, [r0, #0x304]
277	ldr     r2, =0x00011110
278	orr     r1, r1, r2
279	str     r1, [r0, #0x304]
280	ldr     r1, =0x00000001
281	str     r1, [r0, #0x308]
282
283	/* Set Source Clock */
284	ldr	r1, =0x00001111			@ A, M, E, HPLL Muxing
285	str	r1, [r0, #0x200]		@ S5PC1XX_CLK_SRC0
286
287	b	200f
288110:
289	ldr	r0, =0xE010C000			@ S5PC110_PWR_CFG
290
291	/* Set OSC_FREQ value */
292	ldr	r1, =0xf
293	str	r1, [r0, #0x100]		@ S5PC110_OSC_FREQ
294
295	/* Set MTC_STABLE value */
296	ldr	r1, =0xffffffff
297	str	r1, [r0, #0x110]		@ S5PC110_MTC_STABLE
298
299	/* Set CLAMP_STABLE value */
300	ldr	r1, =0x3ff03ff
301	str	r1, [r0, #0x114]		@ S5PC110_CLAMP_STABLE
302
303	ldr	r0, =S5PC110_CLOCK_BASE		@ 0xE0100000
304
305	/* Set Clock divider */
306	ldr	r1, =0x14131330			@ 1:1:4:4, 1:4:5
307	str	r1, [r0, #0x300]
308	ldr	r1, =0x11110111			@ UART[3210]: MMC[3210]
309	str	r1, [r0, #0x310]
310
311	/* Set Lock Time */
312	ldr	r1, =0x2cf			@ Locktime : 30us
313	str	r1, [r0, #0x000]		@ S5PC110_APLL_LOCK
314	ldr	r1, =0xe10			@ Locktime : 0xe10 = 3600
315	str	r1, [r0, #0x008]		@ S5PC110_MPLL_LOCK
316	str	r1, [r0, #0x010]		@ S5PC110_EPLL_LOCK
317	str	r1, [r0, #0x020]		@ S5PC110_VPLL_LOCK
318
319	/* S5PC110_APLL_CON */
320	ldr	r1, =0x80C80601			@ 800MHz
321	str	r1, [r0, #0x100]
322	/* S5PC110_MPLL_CON */
323	ldr	r1, =0x829B0C01			@ 667MHz
324	str	r1, [r0, #0x108]
325	/* S5PC110_EPLL_CON */
326	ldr	r1, =0x80600602			@  96MHz VSEL 0 P 6 M 96 S 2
327	str	r1, [r0, #0x110]
328	/* S5PC110_VPLL_CON */
329	ldr	r1, =0x806C0603			@  54MHz
330	str	r1, [r0, #0x120]
331
332	/* Set Source Clock */
333	ldr	r1, =0x10001111			@ A, M, E, VPLL Muxing
334	str	r1, [r0, #0x200]		@ S5PC1XX_CLK_SRC0
335
336	/* OneDRAM(DMC0) clock setting */
337	ldr	r1, =0x01000000			@ ONEDRAM_SEL[25:24] 1 SCLKMPLL
338	str	r1, [r0, #0x218]		@ S5PC110_CLK_SRC6
339	ldr	r1, =0x30000000			@ ONEDRAM_RATIO[31:28] 3 + 1
340	str	r1, [r0, #0x318]		@ S5PC110_CLK_DIV6
341
342	/* XCLKOUT = XUSBXTI 24MHz */
343	add	r2, r0, #0xE000			@ S5PC110_OTHERS
344	ldr     r1, [r2]
345	orr	r1, r1, #(0x3 << 8)		@ CLKOUT[9:8] 3 XUSBXTI
346	str	r1, [r2]
347
348	/* CLK_IP0 */
349	ldr	r1, =0x8fefeeb			@ DMC[1:0] PDMA0[3] IMEM[5]
350	str	r1, [r0, #0x460]		@ S5PC110_CLK_IP0
351
352	/* CLK_IP1 */
353	ldr	r1, =0xe9fdf0f9			@ FIMD[0] USBOTG[16]
354						@ NANDXL[24]
355	str	r1, [r0, #0x464]		@ S5PC110_CLK_IP1
356
357	/* CLK_IP2 */
358	ldr	r1, =0xf75f7fc			@ CORESIGHT[8] MODEM[9]
359						@ HOSTIF[10] HSMMC0[16]
360						@ HSMMC2[18] VIC[27:24]
361	str	r1, [r0, #0x468]		@ S5PC110_CLK_IP2
362
363	/* CLK_IP3 */
364	ldr	r1, =0x8eff038c			@ I2C[8:6]
365						@ SYSTIMER[16] UART0[17]
366						@ UART1[18] UART2[19]
367						@ UART3[20] WDT[22]
368						@ PWM[23] GPIO[26] SYSCON[27]
369	str	r1, [r0, #0x46c]		@ S5PC110_CLK_IP3
370
371	/* CLK_IP4 */
372	ldr	r1, =0xfffffff1			@ CHIP_ID[0] TZPC[8:5]
373	str	r1, [r0, #0x470]		@ S5PC110_CLK_IP3
374
375200:
376	/* wait at least 200us to stablize all clock */
377	mov	r2, #0x10000
3781:	subs	r2, r2, #1
379	bne	1b
380
381	mov	pc, lr
382
383internal_ram_init:
384	ldreq	r0, =0xE3800000
385	ldrne	r0, =0xF1500000
386	ldr	r1, =0x0
387	str	r1, [r0]
388
389	mov	pc, lr
390
391/*
392 * uart_asm_init: Initialize UART's pins
393 */
394uart_asm_init:
395	/* set GPIO to enable UART0-UART4 */
396	mov	r0, r8
397	ldr	r1, =0x22222222
398	str	r1, [r0, #0x0]			@ S5PC100_GPIO_A0_OFFSET
399	ldr	r1, =0x00002222
400	str	r1, [r0, #0x20]			@ S5PC100_GPIO_A1_OFFSET
401
402	/* Check S5PC100 */
403	cmp	r7, r8
404	bne	110f
405
406	/* UART_SEL GPK0[5] at S5PC100 */
407	add	r0, r8, #0x2A0			@ S5PC100_GPIO_K0_OFFSET
408	ldr	r1, [r0, #0x0]			@ S5PC1XX_GPIO_CON_OFFSET
409	bic	r1, r1, #(0xf << 20)		@ 20 = 5 * 4-bit
410	orr	r1, r1, #(0x1 << 20)		@ Output
411	str	r1, [r0, #0x0]			@ S5PC1XX_GPIO_CON_OFFSET
412
413	ldr	r1, [r0, #0x8]			@ S5PC1XX_GPIO_PULL_OFFSET
414	bic	r1, r1, #(0x3 << 10)		@ 10 = 5 * 2-bit
415	orr	r1, r1, #(0x2 << 10)		@ Pull-up enabled
416	str	r1, [r0, #0x8]			@ S5PC1XX_GPIO_PULL_OFFSET
417
418	ldr	r1, [r0, #0x4]			@ S5PC1XX_GPIO_DAT_OFFSET
419	orr	r1, r1, #(1 << 5)		@ 5 = 5 * 1-bit
420	str	r1, [r0, #0x4]			@ S5PC1XX_GPIO_DAT_OFFSET
421
422	b	200f
423110:
424	/*
425	 * Note that the following address
426	 * 0xE020'0360 is reserved address at S5PC100
427	 */
428	/* UART_SEL MP0_5[7] at S5PC110 */
429	add	r0, r8, #0x360			@ S5PC110_GPIO_MP0_5_OFFSET
430	ldr	r1, [r0, #0x0]			@ S5PC1XX_GPIO_CON_OFFSET
431	bic	r1, r1, #(0xf << 28)		@ 28 = 7 * 4-bit
432	orr	r1, r1, #(0x1 << 28)		@ Output
433	str	r1, [r0, #0x0]			@ S5PC1XX_GPIO_CON_OFFSET
434
435	ldr	r1, [r0, #0x8]			@ S5PC1XX_GPIO_PULL_OFFSET
436	bic	r1, r1, #(0x3 << 14)		@ 14 = 7 * 2-bit
437	orr	r1, r1, #(0x2 << 14)		@ Pull-up enabled
438	str	r1, [r0, #0x8]			@ S5PC1XX_GPIO_PULL_OFFSET
439
440	ldr	r1, [r0, #0x4]			@ S5PC1XX_GPIO_DAT_OFFSET
441	orr	r1, r1, #(1 << 7)		@ 7 = 7 * 1-bit
442	str	r1, [r0, #0x4]			@ S5PC1XX_GPIO_DAT_OFFSET
443200:
444	mov	pc, lr
445