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