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