xref: /openbmc/u-boot/arch/mips/mach-ath79/ar933x/lowlevel_init.S (revision 83d290c56fab2d38cd1ab4c4cc7099559c1d5046)
1*83d290c5STom Rini/* SPDX-License-Identifier: GPL-2.0+ */
2ee7bb5beSWills Wang/*
3ee7bb5beSWills Wang * Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com>
4ee7bb5beSWills Wang * Based on Atheros LSDK/QSDK and u-boot_mod project
5ee7bb5beSWills Wang */
6ee7bb5beSWills Wang
7ee7bb5beSWills Wang#include <config.h>
8ee7bb5beSWills Wang#include <asm/asm.h>
9ee7bb5beSWills Wang#include <asm/regdef.h>
10ee7bb5beSWills Wang#include <asm/mipsregs.h>
11ee7bb5beSWills Wang#include <asm/addrspace.h>
12ee7bb5beSWills Wang#include <mach/ar71xx_regs.h>
13ee7bb5beSWills Wang
14ee7bb5beSWills Wang#define SET_BIT(val, bit)   ((val) | (1 << (bit)))
15ee7bb5beSWills Wang#define SET_PLL_PD(val)     SET_BIT(val, 30)
16ee7bb5beSWills Wang#define AHB_DIV_TO_4(val)   SET_BIT(SET_BIT(val, 15), 16)
17ee7bb5beSWills Wang#define PLL_BYPASS(val)     SET_BIT(val, 2)
18ee7bb5beSWills Wang
19ee7bb5beSWills Wang#define MK_PLL_CONF(divint, refdiv, range, outdiv) \
20ee7bb5beSWills Wang     (((0x3F & divint) << 10) | \
21ee7bb5beSWills Wang     ((0x1F & refdiv) << 16) | \
22ee7bb5beSWills Wang     ((0x1 & range)   << 21) | \
23ee7bb5beSWills Wang     ((0x7 & outdiv)  << 23) )
24ee7bb5beSWills Wang
25ee7bb5beSWills Wang#define MK_CLK_CNTL(cpudiv, ddrdiv, ahbdiv) \
26ee7bb5beSWills Wang    (((0x3 & (cpudiv - 1)) << 5)  | \
27ee7bb5beSWills Wang    ((0x3 & (ddrdiv - 1)) << 10) | \
28ee7bb5beSWills Wang    ((0x3 & (ahbdiv - 1)) << 15) )
29ee7bb5beSWills Wang
30ee7bb5beSWills Wang/*
31ee7bb5beSWills Wang * PLL_CPU_CONFIG_VAL
32ee7bb5beSWills Wang *
33ee7bb5beSWills Wang * Bit30 is set (CPU_PLLPWD = 1 -> power down control for CPU PLL)
34ee7bb5beSWills Wang * After PLL configuration we need to clear this bit
35ee7bb5beSWills Wang *
36ee7bb5beSWills Wang * Values written into CPU PLL Configuration (CPU_PLL_CONFIG)
37ee7bb5beSWills Wang *
38ee7bb5beSWills Wang * bits 10..15  (6bit)  DIV_INT (Integer part of the DIV to CPU PLL)
39ee7bb5beSWills Wang *                      =>  32  (0x20)  VCOOUT = XTAL * DIV_INT
40ee7bb5beSWills Wang * bits 16..20  (5bit)  REFDIV  (Reference clock divider)
41ee7bb5beSWills Wang *                      =>  1   (0x1)   [Must start at values 1]
42ee7bb5beSWills Wang * bits 21      (1bit)  RANGE   (VCO frequency range of the CPU PLL)
43ee7bb5beSWills Wang *                      =>  0   (0x0)   [Doesn't impact clock values]
44ee7bb5beSWills Wang * bits 23..25  (3bit)  OUTDIV  (Ratio between VCO and PLL output)
45ee7bb5beSWills Wang *                      =>  1   (0x1)   [0 is illegal!]
46ee7bb5beSWills Wang *                              PLLOUT = VCOOUT * (1/2^OUTDIV)
47ee7bb5beSWills Wang */
48ee7bb5beSWills Wang/* DIV_INT=32 (25MHz*32/2=400MHz), REFDIV=1, RANGE=0, OUTDIV=1 */
49ee7bb5beSWills Wang#define PLL_CPU_CONFIG_VAL_40M  MK_PLL_CONF(20, 1, 0, 1)
50ee7bb5beSWills Wang/* DIV_INT=20 (40MHz*20/2=400MHz), REFDIV=1, RANGE=0, OUTDIV=1 */
51ee7bb5beSWills Wang#define PLL_CPU_CONFIG_VAL_25M  MK_PLL_CONF(32, 1, 0, 1)
52ee7bb5beSWills Wang
53ee7bb5beSWills Wang/*
54ee7bb5beSWills Wang * PLL_CLK_CONTROL_VAL
55ee7bb5beSWills Wang *
56ee7bb5beSWills Wang * In PLL_CLK_CONTROL_VAL bit 2 is set (BYPASS = 1 -> bypass PLL)
57ee7bb5beSWills Wang * After PLL configuration we need to clear this bit
58ee7bb5beSWills Wang *
59ee7bb5beSWills Wang * Values written into CPU Clock Control Register CLOCK_CONTROL
60ee7bb5beSWills Wang *
61ee7bb5beSWills Wang * bits 2       (1bit)  BYPASS (Bypass PLL. This defaults to 1 for test.
62ee7bb5beSWills Wang *                      Software must enable the CPU PLL for normal and
63ee7bb5beSWills Wang *                      then set this bit to 0)
64ee7bb5beSWills Wang * bits 5..6    (2bit)  CPU_POST_DIV    =>  0   (DEFAULT, Ratio = 1)
65ee7bb5beSWills Wang *                      CPU_CLK = PLLOUT / CPU_POST_DIV
66ee7bb5beSWills Wang * bits 10..11  (2bit)  DDR_POST_DIV    =>  0   (DEFAULT, Ratio = 1)
67ee7bb5beSWills Wang *                      DDR_CLK = PLLOUT / DDR_POST_DIV
68ee7bb5beSWills Wang * bits 15..16  (2bit)  AHB_POST_DIV    =>  1   (DEFAULT, Ratio = 2)
69ee7bb5beSWills Wang *                      AHB_CLK = PLLOUT / AHB_POST_DIV
70ee7bb5beSWills Wang *
71ee7bb5beSWills Wang */
72ee7bb5beSWills Wang#define PLL_CLK_CONTROL_VAL MK_CLK_CNTL(1, 1, 2)
73ee7bb5beSWills Wang
74ee7bb5beSWills Wang    .text
75ee7bb5beSWills Wang    .set noreorder
76ee7bb5beSWills Wang
77ee7bb5beSWills WangLEAF(lowlevel_init)
78ee7bb5beSWills Wang	/* These three WLAN_RESET will avoid original issue */
79ee7bb5beSWills Wang	li      t3, 0x03
80ee7bb5beSWills Wang1:
81ee7bb5beSWills Wang	li      t0, CKSEG1ADDR(AR71XX_RESET_BASE)
82ee7bb5beSWills Wang	lw      t1, AR933X_RESET_REG_RESET_MODULE(t0)
83ee7bb5beSWills Wang	ori     t1, t1, 0x0800
84ee7bb5beSWills Wang	sw      t1, AR933X_RESET_REG_RESET_MODULE(t0)
85ee7bb5beSWills Wang	nop
86ee7bb5beSWills Wang	lw      t1, AR933X_RESET_REG_RESET_MODULE(t0)
87ee7bb5beSWills Wang	li      t2, 0xfffff7ff
88ee7bb5beSWills Wang	and     t1, t1, t2
89ee7bb5beSWills Wang	sw      t1, AR933X_RESET_REG_RESET_MODULE(t0)
90ee7bb5beSWills Wang	nop
91ee7bb5beSWills Wang	addi    t3, t3, -1
92ee7bb5beSWills Wang	bnez    t3, 1b
93ee7bb5beSWills Wang	nop
94ee7bb5beSWills Wang
95ee7bb5beSWills Wang	li      t2, 0x20
96ee7bb5beSWills Wang2:
97ee7bb5beSWills Wang	beqz    t2, 1b
98ee7bb5beSWills Wang	nop
99ee7bb5beSWills Wang	addi    t2, t2, -1
100ee7bb5beSWills Wang	lw      t5, AR933X_RESET_REG_BOOTSTRAP(t0)
101ee7bb5beSWills Wang	andi    t1, t5, 0x10
102ee7bb5beSWills Wang	bnez    t1, 2b
103ee7bb5beSWills Wang	nop
104ee7bb5beSWills Wang
105ee7bb5beSWills Wang	li      t1, 0x02110E
106ee7bb5beSWills Wang	sw      t1, AR933X_RESET_REG_BOOTSTRAP(t0)
107ee7bb5beSWills Wang	nop
108ee7bb5beSWills Wang
109ee7bb5beSWills Wang	/* RTC Force Wake */
110ee7bb5beSWills Wang	li      t0, CKSEG1ADDR(AR933X_RTC_BASE)
111ee7bb5beSWills Wang	li      t1, 0x03
112ee7bb5beSWills Wang	sw      t1, AR933X_RTC_REG_FORCE_WAKE(t0)
113ee7bb5beSWills Wang	nop
114ee7bb5beSWills Wang	nop
115ee7bb5beSWills Wang
116ee7bb5beSWills Wang	/* RTC Reset */
117ee7bb5beSWills Wang	li      t1, 0x00
118ee7bb5beSWills Wang	sw      t1, AR933X_RTC_REG_RESET(t0)
119ee7bb5beSWills Wang	nop
120ee7bb5beSWills Wang	nop
121ee7bb5beSWills Wang
122ee7bb5beSWills Wang	li      t1, 0x01
123ee7bb5beSWills Wang	sw      t1, AR933X_RTC_REG_RESET(t0)
124ee7bb5beSWills Wang	nop
125ee7bb5beSWills Wang	nop
126ee7bb5beSWills Wang
127ee7bb5beSWills Wang	/* Wait for RTC in on state */
128ee7bb5beSWills Wang1:
129ee7bb5beSWills Wang	lw      t1, AR933X_RTC_REG_STATUS(t0)
130ee7bb5beSWills Wang	andi    t1, t1, 0x02
131ee7bb5beSWills Wang	beqz    t1, 1b
132ee7bb5beSWills Wang	nop
133ee7bb5beSWills Wang
134ee7bb5beSWills Wang	/* Program ki/kd */
135ee7bb5beSWills Wang	li      t0, CKSEG1ADDR(AR933X_SRIF_BASE)
136ee7bb5beSWills Wang	andi    t1, t5, 0x01            # t5 BOOT_STRAP
137ee7bb5beSWills Wang	bnez    t1, 1f
138ee7bb5beSWills Wang	nop
139ee7bb5beSWills Wang	li      t1, 0x19e82f01
140ee7bb5beSWills Wang	b       2f
141ee7bb5beSWills Wang	nop
142ee7bb5beSWills Wang1:
143ee7bb5beSWills Wang	li      t1, 0x18e82f01
144ee7bb5beSWills Wang2:
145ee7bb5beSWills Wang	sw      t1, AR933X_SRIF_DDR_DPLL2_REG(t0)
146ee7bb5beSWills Wang
147ee7bb5beSWills Wang	/* Program phase shift */
148ee7bb5beSWills Wang	lw      t1, AR933X_SRIF_DDR_DPLL3_REG(t0)
149ee7bb5beSWills Wang	li      t2, 0xc07fffff
150ee7bb5beSWills Wang	and     t1, t1, t2
151ee7bb5beSWills Wang	li      t2, 0x800000
152ee7bb5beSWills Wang	or      t1, t1, t2
153ee7bb5beSWills Wang	sw      t1, AR933X_SRIF_DDR_DPLL3_REG(t0)
154ee7bb5beSWills Wang	nop
155ee7bb5beSWills Wang
156ee7bb5beSWills Wang	/* in some cases, the SoC doesn't start with higher clock on AHB */
157ee7bb5beSWills Wang	li      t0, CKSEG1ADDR(AR71XX_PLL_BASE)
158ee7bb5beSWills Wang	li      t1, AHB_DIV_TO_4(PLL_BYPASS(PLL_CLK_CONTROL_VAL))
159ee7bb5beSWills Wang	sw      t1, AR933X_PLL_CLK_CTRL_REG(t0)
160ee7bb5beSWills Wang	nop
161ee7bb5beSWills Wang
162ee7bb5beSWills Wang	/* Set SETTLE_TIME in CPU PLL */
163ee7bb5beSWills Wang	andi    t1, t5, 0x01            # t5 BOOT_STRAP
164ee7bb5beSWills Wang	bnez    t1, 1f
165ee7bb5beSWills Wang	nop
166ee7bb5beSWills Wang	li      t1, 0x0352
167ee7bb5beSWills Wang	b       2f
168ee7bb5beSWills Wang	nop
169ee7bb5beSWills Wang1:
170ee7bb5beSWills Wang	li      t1, 0x0550
171ee7bb5beSWills Wang2:
172ee7bb5beSWills Wang	sw      t1, AR71XX_PLL_REG_SEC_CONFIG(t0)
173ee7bb5beSWills Wang	nop
174ee7bb5beSWills Wang
175ee7bb5beSWills Wang	/* Set nint, frac, refdiv, outdiv, range according to xtal */
176ee7bb5beSWills Wang0:
177ee7bb5beSWills Wang	andi    t1, t5, 0x01            # t5 BOOT_STRAP
178ee7bb5beSWills Wang	bnez    t1, 1f
179ee7bb5beSWills Wang	nop
180ee7bb5beSWills Wang	li      t1, SET_PLL_PD(PLL_CPU_CONFIG_VAL_25M)
181ee7bb5beSWills Wang	b       2f
182ee7bb5beSWills Wang	nop
183ee7bb5beSWills Wang1:
184ee7bb5beSWills Wang	li      t1, SET_PLL_PD(PLL_CPU_CONFIG_VAL_40M)
185ee7bb5beSWills Wang2:
186ee7bb5beSWills Wang	sw      t1, AR933X_PLL_CPU_CONFIG_REG(t0)
187ee7bb5beSWills Wang	nop
188ee7bb5beSWills Wang1:
189ee7bb5beSWills Wang	lw      t1, AR933X_PLL_CPU_CONFIG_REG(t0)
190ee7bb5beSWills Wang	li      t2, 0x80000000
191ee7bb5beSWills Wang	and     t1, t1, t2
192ee7bb5beSWills Wang	bnez    t1, 1b
193ee7bb5beSWills Wang	nop
194ee7bb5beSWills Wang
195ee7bb5beSWills Wang	/* Put frac bit19:10 configuration */
196ee7bb5beSWills Wang	li      t1, 0x1003E8
197ee7bb5beSWills Wang	sw      t1, AR933X_PLL_DITHER_FRAC_REG(t0)
198ee7bb5beSWills Wang	nop
199ee7bb5beSWills Wang
200ee7bb5beSWills Wang	/* Clear PLL power down bit in CPU PLL configuration */
201ee7bb5beSWills Wang	andi    t1, t5, 0x01            # t5 BOOT_STRAP
202ee7bb5beSWills Wang	bnez    t1, 1f
203ee7bb5beSWills Wang	nop
204ee7bb5beSWills Wang	li      t1, PLL_CPU_CONFIG_VAL_25M
205ee7bb5beSWills Wang	b       2f
206ee7bb5beSWills Wang	nop
207ee7bb5beSWills Wang1:
208ee7bb5beSWills Wang	li      t1, PLL_CPU_CONFIG_VAL_40M
209ee7bb5beSWills Wang2:
210ee7bb5beSWills Wang	sw      t1, AR933X_PLL_CPU_CONFIG_REG(t0)
211ee7bb5beSWills Wang	nop
212ee7bb5beSWills Wang
213ee7bb5beSWills Wang	/* Wait for PLL update -> bit 31 in CPU_PLL_CONFIG should be 0 */
214ee7bb5beSWills Wang1:
215ee7bb5beSWills Wang	lw      t1, AR933X_PLL_CPU_CONFIG_REG(t0)
216ee7bb5beSWills Wang	li      t2, 0x80000000
217ee7bb5beSWills Wang	and     t1, t1, t2
218ee7bb5beSWills Wang	bnez    t1, 1b
219ee7bb5beSWills Wang	nop
220ee7bb5beSWills Wang
221ee7bb5beSWills Wang	/* Confirm DDR PLL lock */
222ee7bb5beSWills Wang	li      t3, 100
223ee7bb5beSWills Wang	li      t4, 0
224ee7bb5beSWills Wang
225ee7bb5beSWills Wang2:
226ee7bb5beSWills Wang	addi    t4, t4, 1
227ee7bb5beSWills Wang	bgt     t4, t3, 0b
228ee7bb5beSWills Wang	nop
229ee7bb5beSWills Wang
230ee7bb5beSWills Wang	li      t3, 5
231ee7bb5beSWills Wang3:
232ee7bb5beSWills Wang	/* Clear do_meas */
233ee7bb5beSWills Wang	li      t0, CKSEG1ADDR(AR933X_SRIF_BASE)
234ee7bb5beSWills Wang	lw      t1, AR933X_SRIF_DDR_DPLL3_REG(t0)
235ee7bb5beSWills Wang	li      t2, 0xBFFFFFFF
236ee7bb5beSWills Wang	and     t1, t1, t2
237ee7bb5beSWills Wang	sw      t1, AR933X_SRIF_DDR_DPLL3_REG(t0)
238ee7bb5beSWills Wang	nop
239ee7bb5beSWills Wang
240ee7bb5beSWills Wang	li      t2, 10
241ee7bb5beSWills Wang1:
242ee7bb5beSWills Wang	subu    t2, t2, 1
243ee7bb5beSWills Wang	bnez    t2, 1b
244ee7bb5beSWills Wang	nop
245ee7bb5beSWills Wang
246ee7bb5beSWills Wang	/* Set do_meas */
247ee7bb5beSWills Wang	li      t2, 0x40000000
248ee7bb5beSWills Wang	or      t1, t1, t2
249ee7bb5beSWills Wang	sw      t1, AR933X_SRIF_DDR_DPLL3_REG(t0)
250ee7bb5beSWills Wang	nop
251ee7bb5beSWills Wang
252ee7bb5beSWills Wang	/* Check meas_done */
253ee7bb5beSWills Wang1:
254ee7bb5beSWills Wang	lw      t1, AR933X_SRIF_DDR_DPLL4_REG(t0)
255ee7bb5beSWills Wang	andi    t1, t1, 0x8
256ee7bb5beSWills Wang	beqz    t1, 1b
257ee7bb5beSWills Wang	nop
258ee7bb5beSWills Wang
259ee7bb5beSWills Wang	lw      t1, AR933X_SRIF_DDR_DPLL3_REG(t0)
260ee7bb5beSWills Wang	li      t2, 0x007FFFF8
261ee7bb5beSWills Wang	and     t1, t1, t2
262ee7bb5beSWills Wang	srl     t1, t1, 3
263ee7bb5beSWills Wang	li      t2, 0x4000
264ee7bb5beSWills Wang	bgt     t1, t2, 2b
265ee7bb5beSWills Wang	nop
266ee7bb5beSWills Wang	addi    t3, t3, -1
267ee7bb5beSWills Wang	bnez    t3, 3b
268ee7bb5beSWills Wang	nop
269ee7bb5beSWills Wang
270ee7bb5beSWills Wang	/* clear PLL bypass (bit 2) in CPU CLOCK CONTROL register */
271ee7bb5beSWills Wang	li      t0, CKSEG1ADDR(AR71XX_PLL_BASE)
272ee7bb5beSWills Wang	li      t1, PLL_CLK_CONTROL_VAL
273ee7bb5beSWills Wang	sw      t1, AR933X_PLL_CLK_CTRL_REG(t0)
274ee7bb5beSWills Wang	nop
275ee7bb5beSWills Wang
276ee7bb5beSWills Wang	nop
277ee7bb5beSWills Wang	jr ra
278ee7bb5beSWills Wang	nop
279ee7bb5beSWills Wang    END(lowlevel_init)
280