1*21b30c00SFlorian Fainelli 2*21b30c00SFlorian Fainelli/* 3*21b30c00SFlorian Fainelli * This file is subject to the terms and conditions of the GNU General Public 4*21b30c00SFlorian Fainelli * License. See the file "COPYING" in the main directory of this archive 5*21b30c00SFlorian Fainelli * for more details. 6*21b30c00SFlorian Fainelli * 7*21b30c00SFlorian Fainelli * Copyright (C) 2011-2012 by Broadcom Corporation 8*21b30c00SFlorian Fainelli * 9*21b30c00SFlorian Fainelli * Init for bmips 5000. 10*21b30c00SFlorian Fainelli * Used to init second core in dual core 5000's. 11*21b30c00SFlorian Fainelli */ 12*21b30c00SFlorian Fainelli 13*21b30c00SFlorian Fainelli#include <linux/init.h> 14*21b30c00SFlorian Fainelli 15*21b30c00SFlorian Fainelli#include <asm/asm.h> 16*21b30c00SFlorian Fainelli#include <asm/asmmacro.h> 17*21b30c00SFlorian Fainelli#include <asm/cacheops.h> 18*21b30c00SFlorian Fainelli#include <asm/regdef.h> 19*21b30c00SFlorian Fainelli#include <asm/mipsregs.h> 20*21b30c00SFlorian Fainelli#include <asm/stackframe.h> 21*21b30c00SFlorian Fainelli#include <asm/addrspace.h> 22*21b30c00SFlorian Fainelli#include <asm/hazards.h> 23*21b30c00SFlorian Fainelli#include <asm/bmips.h> 24*21b30c00SFlorian Fainelli 25*21b30c00SFlorian Fainelli#ifdef CONFIG_CPU_BMIPS5000 26*21b30c00SFlorian Fainelli 27*21b30c00SFlorian Fainelli 28*21b30c00SFlorian Fainelli#define cacheop(kva, size, linesize, op) \ 29*21b30c00SFlorian Fainelli .set noreorder ; \ 30*21b30c00SFlorian Fainelli addu t1, kva, size ; \ 31*21b30c00SFlorian Fainelli subu t2, linesize, 1 ; \ 32*21b30c00SFlorian Fainelli not t2 ; \ 33*21b30c00SFlorian Fainelli and t0, kva, t2 ; \ 34*21b30c00SFlorian Fainelli addiu t1, t1, -1 ; \ 35*21b30c00SFlorian Fainelli and t1, t2 ; \ 36*21b30c00SFlorian Fainelli9: cache op, 0(t0) ; \ 37*21b30c00SFlorian Fainelli bne t0, t1, 9b ; \ 38*21b30c00SFlorian Fainelli addu t0, linesize ; \ 39*21b30c00SFlorian Fainelli .set reorder ; 40*21b30c00SFlorian Fainelli 41*21b30c00SFlorian Fainelli 42*21b30c00SFlorian Fainelli 43*21b30c00SFlorian Fainelli#define IS_SHIFT 22 44*21b30c00SFlorian Fainelli#define IL_SHIFT 19 45*21b30c00SFlorian Fainelli#define IA_SHIFT 16 46*21b30c00SFlorian Fainelli#define DS_SHIFT 13 47*21b30c00SFlorian Fainelli#define DL_SHIFT 10 48*21b30c00SFlorian Fainelli#define DA_SHIFT 7 49*21b30c00SFlorian Fainelli#define IS_MASK 7 50*21b30c00SFlorian Fainelli#define IL_MASK 7 51*21b30c00SFlorian Fainelli#define IA_MASK 7 52*21b30c00SFlorian Fainelli#define DS_MASK 7 53*21b30c00SFlorian Fainelli#define DL_MASK 7 54*21b30c00SFlorian Fainelli#define DA_MASK 7 55*21b30c00SFlorian Fainelli#define ICE_MASK 0x80000000 56*21b30c00SFlorian Fainelli#define DCE_MASK 0x40000000 57*21b30c00SFlorian Fainelli 58*21b30c00SFlorian Fainelli#define CP0_BRCM_CONFIG0 $22, 0 59*21b30c00SFlorian Fainelli#define CP0_BRCM_MODE $22, 1 60*21b30c00SFlorian Fainelli#define CP0_CONFIG_K0_MASK 7 61*21b30c00SFlorian Fainelli 62*21b30c00SFlorian Fainelli#define CP0_ICACHE_TAG_LO $28 63*21b30c00SFlorian Fainelli#define CP0_ICACHE_DATA_LO $28, 1 64*21b30c00SFlorian Fainelli#define CP0_DCACHE_TAG_LO $28, 2 65*21b30c00SFlorian Fainelli#define CP0_D_SEC_CACHE_DATA_LO $28, 3 66*21b30c00SFlorian Fainelli#define CP0_ICACHE_TAG_HI $29 67*21b30c00SFlorian Fainelli#define CP0_ICACHE_DATA_HI $29, 1 68*21b30c00SFlorian Fainelli#define CP0_DCACHE_TAG_HI $29, 2 69*21b30c00SFlorian Fainelli 70*21b30c00SFlorian Fainelli#define CP0_BRCM_MODE_Luc_MASK (1 << 11) 71*21b30c00SFlorian Fainelli#define CP0_BRCM_CONFIG0_CWF_MASK (1 << 20) 72*21b30c00SFlorian Fainelli#define CP0_BRCM_CONFIG0_TSE_MASK (1 << 19) 73*21b30c00SFlorian Fainelli#define CP0_BRCM_MODE_SET_MASK (1 << 7) 74*21b30c00SFlorian Fainelli#define CP0_BRCM_MODE_ClkRATIO_MASK (7 << 4) 75*21b30c00SFlorian Fainelli#define CP0_BRCM_MODE_BrPRED_MASK (3 << 24) 76*21b30c00SFlorian Fainelli#define CP0_BRCM_MODE_BrPRED_SHIFT 24 77*21b30c00SFlorian Fainelli#define CP0_BRCM_MODE_BrHIST_MASK (0x1f << 20) 78*21b30c00SFlorian Fainelli#define CP0_BRCM_MODE_BrHIST_SHIFT 20 79*21b30c00SFlorian Fainelli 80*21b30c00SFlorian Fainelli/* ZSC L2 Cache Register Access Register Definitions */ 81*21b30c00SFlorian Fainelli#define BRCM_ZSC_ALL_REGS_SELECT 0x7 << 24 82*21b30c00SFlorian Fainelli 83*21b30c00SFlorian Fainelli#define BRCM_ZSC_CONFIG_REG 0 << 3 84*21b30c00SFlorian Fainelli#define BRCM_ZSC_REQ_BUFFER_REG 2 << 3 85*21b30c00SFlorian Fainelli#define BRCM_ZSC_RBUS_ADDR_MAPPING_REG0 4 << 3 86*21b30c00SFlorian Fainelli#define BRCM_ZSC_RBUS_ADDR_MAPPING_REG1 6 << 3 87*21b30c00SFlorian Fainelli#define BRCM_ZSC_RBUS_ADDR_MAPPING_REG2 8 << 3 88*21b30c00SFlorian Fainelli 89*21b30c00SFlorian Fainelli#define BRCM_ZSC_SCB0_ADDR_MAPPING_REG0 0xa << 3 90*21b30c00SFlorian Fainelli#define BRCM_ZSC_SCB0_ADDR_MAPPING_REG1 0xc << 3 91*21b30c00SFlorian Fainelli 92*21b30c00SFlorian Fainelli#define BRCM_ZSC_SCB1_ADDR_MAPPING_REG0 0xe << 3 93*21b30c00SFlorian Fainelli#define BRCM_ZSC_SCB1_ADDR_MAPPING_REG1 0x10 << 3 94*21b30c00SFlorian Fainelli 95*21b30c00SFlorian Fainelli#define BRCM_ZSC_CONFIG_LMB1En 1 << (15) 96*21b30c00SFlorian Fainelli#define BRCM_ZSC_CONFIG_LMB0En 1 << (14) 97*21b30c00SFlorian Fainelli 98*21b30c00SFlorian Fainelli/* branch predition values */ 99*21b30c00SFlorian Fainelli 100*21b30c00SFlorian Fainelli#define BRCM_BrPRED_ALL_TAKEN (0x0) 101*21b30c00SFlorian Fainelli#define BRCM_BrPRED_ALL_NOT_TAKEN (0x1) 102*21b30c00SFlorian Fainelli#define BRCM_BrPRED_BHT_ENABLE (0x2) 103*21b30c00SFlorian Fainelli#define BRCM_BrPRED_PREDICT_BACKWARD (0x3) 104*21b30c00SFlorian Fainelli 105*21b30c00SFlorian Fainelli 106*21b30c00SFlorian Fainelli 107*21b30c00SFlorian Fainelli.align 2 108*21b30c00SFlorian Fainelli/* 109*21b30c00SFlorian Fainelli * Function: size_i_cache 110*21b30c00SFlorian Fainelli * Arguments: None 111*21b30c00SFlorian Fainelli * Returns: v0 = i cache size, v1 = I cache line size 112*21b30c00SFlorian Fainelli * Description: compute the I-cache size and I-cache line size 113*21b30c00SFlorian Fainelli * Trashes: v0, v1, a0, t0 114*21b30c00SFlorian Fainelli * 115*21b30c00SFlorian Fainelli * pseudo code: 116*21b30c00SFlorian Fainelli * 117*21b30c00SFlorian Fainelli */ 118*21b30c00SFlorian Fainelli 119*21b30c00SFlorian FainelliLEAF(size_i_cache) 120*21b30c00SFlorian Fainelli .set noreorder 121*21b30c00SFlorian Fainelli 122*21b30c00SFlorian Fainelli mfc0 a0, CP0_CONFIG, 1 123*21b30c00SFlorian Fainelli move t0, a0 124*21b30c00SFlorian Fainelli 125*21b30c00SFlorian Fainelli /* 126*21b30c00SFlorian Fainelli * Determine sets per way: IS 127*21b30c00SFlorian Fainelli * 128*21b30c00SFlorian Fainelli * This field contains the number of sets (i.e., indices) per way of 129*21b30c00SFlorian Fainelli * the instruction cache: 130*21b30c00SFlorian Fainelli * i) 0x0: 64, ii) 0x1: 128, iii) 0x2: 256, iv) 0x3: 512, v) 0x4: 1k 131*21b30c00SFlorian Fainelli * vi) 0x5 - 0x7: Reserved. 132*21b30c00SFlorian Fainelli */ 133*21b30c00SFlorian Fainelli 134*21b30c00SFlorian Fainelli srl a0, a0, IS_SHIFT 135*21b30c00SFlorian Fainelli and a0, a0, IS_MASK 136*21b30c00SFlorian Fainelli 137*21b30c00SFlorian Fainelli /* sets per way = (64<<IS) */ 138*21b30c00SFlorian Fainelli 139*21b30c00SFlorian Fainelli li v0, 0x40 140*21b30c00SFlorian Fainelli sllv v0, v0, a0 141*21b30c00SFlorian Fainelli 142*21b30c00SFlorian Fainelli /* 143*21b30c00SFlorian Fainelli * Determine line size 144*21b30c00SFlorian Fainelli * 145*21b30c00SFlorian Fainelli * This field contains the line size of the instruction cache: 146*21b30c00SFlorian Fainelli * i) 0x0: No I-cache present, i) 0x3: 16 bytes, ii) 0x4: 32 bytes, iii) 147*21b30c00SFlorian Fainelli * 0x5: 64 bytes, iv) the rest: Reserved. 148*21b30c00SFlorian Fainelli */ 149*21b30c00SFlorian Fainelli 150*21b30c00SFlorian Fainelli move a0, t0 151*21b30c00SFlorian Fainelli 152*21b30c00SFlorian Fainelli srl a0, a0, IL_SHIFT 153*21b30c00SFlorian Fainelli and a0, a0, IL_MASK 154*21b30c00SFlorian Fainelli 155*21b30c00SFlorian Fainelli beqz a0, no_i_cache 156*21b30c00SFlorian Fainelli nop 157*21b30c00SFlorian Fainelli 158*21b30c00SFlorian Fainelli /* line size = 2 ^ (IL+1) */ 159*21b30c00SFlorian Fainelli 160*21b30c00SFlorian Fainelli addi a0, a0, 1 161*21b30c00SFlorian Fainelli li v1, 1 162*21b30c00SFlorian Fainelli sll v1, v1, a0 163*21b30c00SFlorian Fainelli 164*21b30c00SFlorian Fainelli /* v0 now have sets per way, multiply it by line size now 165*21b30c00SFlorian Fainelli * that will give the set size 166*21b30c00SFlorian Fainelli */ 167*21b30c00SFlorian Fainelli 168*21b30c00SFlorian Fainelli sll v0, v0, a0 169*21b30c00SFlorian Fainelli 170*21b30c00SFlorian Fainelli /* 171*21b30c00SFlorian Fainelli * Determine set associativity 172*21b30c00SFlorian Fainelli * 173*21b30c00SFlorian Fainelli * This field contains the set associativity of the instruction cache. 174*21b30c00SFlorian Fainelli * i) 0x0: Direct mapped, ii) 0x1: 2-way, iii) 0x2: 3-way, iv) 0x3: 175*21b30c00SFlorian Fainelli * 4-way, v) 0x4 - 0x7: Reserved. 176*21b30c00SFlorian Fainelli */ 177*21b30c00SFlorian Fainelli 178*21b30c00SFlorian Fainelli move a0, t0 179*21b30c00SFlorian Fainelli 180*21b30c00SFlorian Fainelli srl a0, a0, IA_SHIFT 181*21b30c00SFlorian Fainelli and a0, a0, IA_MASK 182*21b30c00SFlorian Fainelli addi a0, a0, 0x1 183*21b30c00SFlorian Fainelli 184*21b30c00SFlorian Fainelli /* v0 has the set size, multiply it by 185*21b30c00SFlorian Fainelli * set associativiy, to get the cache size 186*21b30c00SFlorian Fainelli */ 187*21b30c00SFlorian Fainelli 188*21b30c00SFlorian Fainelli multu v0, a0 /*multu is interlocked, so no need to insert nops */ 189*21b30c00SFlorian Fainelli mflo v0 190*21b30c00SFlorian Fainelli b 1f 191*21b30c00SFlorian Fainelli nop 192*21b30c00SFlorian Fainelli 193*21b30c00SFlorian Fainellino_i_cache: 194*21b30c00SFlorian Fainelli move v0, zero 195*21b30c00SFlorian Fainelli move v1, zero 196*21b30c00SFlorian Fainelli1: 197*21b30c00SFlorian Fainelli jr ra 198*21b30c00SFlorian Fainelli nop 199*21b30c00SFlorian Fainelli .set reorder 200*21b30c00SFlorian Fainelli 201*21b30c00SFlorian FainelliEND(size_i_cache) 202*21b30c00SFlorian Fainelli 203*21b30c00SFlorian Fainelli/* 204*21b30c00SFlorian Fainelli * Function: size_d_cache 205*21b30c00SFlorian Fainelli * Arguments: None 206*21b30c00SFlorian Fainelli * Returns: v0 = d cache size, v1 = d cache line size 207*21b30c00SFlorian Fainelli * Description: compute the D-cache size and D-cache line size. 208*21b30c00SFlorian Fainelli * Trashes: v0, v1, a0, t0 209*21b30c00SFlorian Fainelli * 210*21b30c00SFlorian Fainelli */ 211*21b30c00SFlorian Fainelli 212*21b30c00SFlorian FainelliLEAF(size_d_cache) 213*21b30c00SFlorian Fainelli .set noreorder 214*21b30c00SFlorian Fainelli 215*21b30c00SFlorian Fainelli mfc0 a0, CP0_CONFIG, 1 216*21b30c00SFlorian Fainelli move t0, a0 217*21b30c00SFlorian Fainelli 218*21b30c00SFlorian Fainelli /* 219*21b30c00SFlorian Fainelli * Determine sets per way: IS 220*21b30c00SFlorian Fainelli * 221*21b30c00SFlorian Fainelli * This field contains the number of sets (i.e., indices) per way of 222*21b30c00SFlorian Fainelli * the instruction cache: 223*21b30c00SFlorian Fainelli * i) 0x0: 64, ii) 0x1: 128, iii) 0x2: 256, iv) 0x3: 512, v) 0x4: 1k 224*21b30c00SFlorian Fainelli * vi) 0x5 - 0x7: Reserved. 225*21b30c00SFlorian Fainelli */ 226*21b30c00SFlorian Fainelli 227*21b30c00SFlorian Fainelli srl a0, a0, DS_SHIFT 228*21b30c00SFlorian Fainelli and a0, a0, DS_MASK 229*21b30c00SFlorian Fainelli 230*21b30c00SFlorian Fainelli /* sets per way = (64<<IS) */ 231*21b30c00SFlorian Fainelli 232*21b30c00SFlorian Fainelli li v0, 0x40 233*21b30c00SFlorian Fainelli sllv v0, v0, a0 234*21b30c00SFlorian Fainelli 235*21b30c00SFlorian Fainelli /* 236*21b30c00SFlorian Fainelli * Determine line size 237*21b30c00SFlorian Fainelli * 238*21b30c00SFlorian Fainelli * This field contains the line size of the instruction cache: 239*21b30c00SFlorian Fainelli * i) 0x0: No I-cache present, i) 0x3: 16 bytes, ii) 0x4: 32 bytes, iii) 240*21b30c00SFlorian Fainelli * 0x5: 64 bytes, iv) the rest: Reserved. 241*21b30c00SFlorian Fainelli */ 242*21b30c00SFlorian Fainelli move a0, t0 243*21b30c00SFlorian Fainelli 244*21b30c00SFlorian Fainelli srl a0, a0, DL_SHIFT 245*21b30c00SFlorian Fainelli and a0, a0, DL_MASK 246*21b30c00SFlorian Fainelli 247*21b30c00SFlorian Fainelli beqz a0, no_d_cache 248*21b30c00SFlorian Fainelli nop 249*21b30c00SFlorian Fainelli 250*21b30c00SFlorian Fainelli /* line size = 2 ^ (IL+1) */ 251*21b30c00SFlorian Fainelli 252*21b30c00SFlorian Fainelli addi a0, a0, 1 253*21b30c00SFlorian Fainelli li v1, 1 254*21b30c00SFlorian Fainelli sll v1, v1, a0 255*21b30c00SFlorian Fainelli 256*21b30c00SFlorian Fainelli /* v0 now have sets per way, multiply it by line size now 257*21b30c00SFlorian Fainelli * that will give the set size 258*21b30c00SFlorian Fainelli */ 259*21b30c00SFlorian Fainelli 260*21b30c00SFlorian Fainelli sll v0, v0, a0 261*21b30c00SFlorian Fainelli 262*21b30c00SFlorian Fainelli /* determine set associativity 263*21b30c00SFlorian Fainelli * 264*21b30c00SFlorian Fainelli * This field contains the set associativity of the instruction cache. 265*21b30c00SFlorian Fainelli * i) 0x0: Direct mapped, ii) 0x1: 2-way, iii) 0x2: 3-way, iv) 0x3: 266*21b30c00SFlorian Fainelli * 4-way, v) 0x4 - 0x7: Reserved. 267*21b30c00SFlorian Fainelli */ 268*21b30c00SFlorian Fainelli 269*21b30c00SFlorian Fainelli move a0, t0 270*21b30c00SFlorian Fainelli 271*21b30c00SFlorian Fainelli srl a0, a0, DA_SHIFT 272*21b30c00SFlorian Fainelli and a0, a0, DA_MASK 273*21b30c00SFlorian Fainelli addi a0, a0, 0x1 274*21b30c00SFlorian Fainelli 275*21b30c00SFlorian Fainelli /* v0 has the set size, multiply it by 276*21b30c00SFlorian Fainelli * set associativiy, to get the cache size 277*21b30c00SFlorian Fainelli */ 278*21b30c00SFlorian Fainelli 279*21b30c00SFlorian Fainelli multu v0, a0 /*multu is interlocked, so no need to insert nops */ 280*21b30c00SFlorian Fainelli mflo v0 281*21b30c00SFlorian Fainelli 282*21b30c00SFlorian Fainelli b 1f 283*21b30c00SFlorian Fainelli nop 284*21b30c00SFlorian Fainelli 285*21b30c00SFlorian Fainellino_d_cache: 286*21b30c00SFlorian Fainelli move v0, zero 287*21b30c00SFlorian Fainelli move v1, zero 288*21b30c00SFlorian Fainelli1: 289*21b30c00SFlorian Fainelli jr ra 290*21b30c00SFlorian Fainelli nop 291*21b30c00SFlorian Fainelli .set reorder 292*21b30c00SFlorian Fainelli 293*21b30c00SFlorian FainelliEND(size_d_cache) 294*21b30c00SFlorian Fainelli 295*21b30c00SFlorian Fainelli 296*21b30c00SFlorian Fainelli/* 297*21b30c00SFlorian Fainelli * Function: enable_ID 298*21b30c00SFlorian Fainelli * Arguments: None 299*21b30c00SFlorian Fainelli * Returns: None 300*21b30c00SFlorian Fainelli * Description: Enable I and D caches, initialize I and D-caches, also set 301*21b30c00SFlorian Fainelli * hardware delay for d-cache (TP0). 302*21b30c00SFlorian Fainelli * Trashes: t0 303*21b30c00SFlorian Fainelli * 304*21b30c00SFlorian Fainelli */ 305*21b30c00SFlorian Fainelli .global enable_ID 306*21b30c00SFlorian Fainelli .ent enable_ID 307*21b30c00SFlorian Fainelli .set noreorder 308*21b30c00SFlorian Fainellienable_ID: 309*21b30c00SFlorian Fainelli mfc0 t0, CP0_BRCM_CONFIG0 310*21b30c00SFlorian Fainelli or t0, t0, (ICE_MASK | DCE_MASK) 311*21b30c00SFlorian Fainelli mtc0 t0, CP0_BRCM_CONFIG0 312*21b30c00SFlorian Fainelli jr ra 313*21b30c00SFlorian Fainelli nop 314*21b30c00SFlorian Fainelli 315*21b30c00SFlorian Fainelli .end enable_ID 316*21b30c00SFlorian Fainelli .set reorder 317*21b30c00SFlorian Fainelli 318*21b30c00SFlorian Fainelli 319*21b30c00SFlorian Fainelli/* 320*21b30c00SFlorian Fainelli * Function: l1_init 321*21b30c00SFlorian Fainelli * Arguments: None 322*21b30c00SFlorian Fainelli * Returns: None 323*21b30c00SFlorian Fainelli * Description: Enable I and D caches, and initialize I and D-caches 324*21b30c00SFlorian Fainelli * Trashes: a0, v0, v1, t0, t1, t2, t8 325*21b30c00SFlorian Fainelli * 326*21b30c00SFlorian Fainelli */ 327*21b30c00SFlorian Fainelli .globl l1_init 328*21b30c00SFlorian Fainelli .ent l1_init 329*21b30c00SFlorian Fainelli .set noreorder 330*21b30c00SFlorian Fainellil1_init: 331*21b30c00SFlorian Fainelli 332*21b30c00SFlorian Fainelli /* save return address */ 333*21b30c00SFlorian Fainelli move t8, ra 334*21b30c00SFlorian Fainelli 335*21b30c00SFlorian Fainelli 336*21b30c00SFlorian Fainelli /* initialize I and D cache Data and Tag registers. */ 337*21b30c00SFlorian Fainelli mtc0 zero, CP0_ICACHE_TAG_LO 338*21b30c00SFlorian Fainelli mtc0 zero, CP0_ICACHE_TAG_HI 339*21b30c00SFlorian Fainelli mtc0 zero, CP0_ICACHE_DATA_LO 340*21b30c00SFlorian Fainelli mtc0 zero, CP0_ICACHE_DATA_HI 341*21b30c00SFlorian Fainelli mtc0 zero, CP0_DCACHE_TAG_LO 342*21b30c00SFlorian Fainelli mtc0 zero, CP0_DCACHE_TAG_HI 343*21b30c00SFlorian Fainelli 344*21b30c00SFlorian Fainelli /* Enable Caches before Clearing. If the caches are disabled 345*21b30c00SFlorian Fainelli * then the cache operations to clear the cache will be ignored 346*21b30c00SFlorian Fainelli */ 347*21b30c00SFlorian Fainelli 348*21b30c00SFlorian Fainelli jal enable_ID 349*21b30c00SFlorian Fainelli nop 350*21b30c00SFlorian Fainelli 351*21b30c00SFlorian Fainelli jal size_i_cache /* v0 = i-cache size, v1 = i-cache line size */ 352*21b30c00SFlorian Fainelli nop 353*21b30c00SFlorian Fainelli 354*21b30c00SFlorian Fainelli /* run uncached in kseg 1 */ 355*21b30c00SFlorian Fainelli la k0, 1f 356*21b30c00SFlorian Fainelli lui k1, 0x2000 357*21b30c00SFlorian Fainelli or k0, k1, k0 358*21b30c00SFlorian Fainelli jr k0 359*21b30c00SFlorian Fainelli nop 360*21b30c00SFlorian Fainelli1: 361*21b30c00SFlorian Fainelli 362*21b30c00SFlorian Fainelli /* 363*21b30c00SFlorian Fainelli * set K0 cache mode 364*21b30c00SFlorian Fainelli */ 365*21b30c00SFlorian Fainelli 366*21b30c00SFlorian Fainelli mfc0 t0, CP0_CONFIG 367*21b30c00SFlorian Fainelli and t0, t0, ~CP0_CONFIG_K0_MASK 368*21b30c00SFlorian Fainelli or t0, t0, 3 /* Write Back mode */ 369*21b30c00SFlorian Fainelli mtc0 t0, CP0_CONFIG 370*21b30c00SFlorian Fainelli 371*21b30c00SFlorian Fainelli /* 372*21b30c00SFlorian Fainelli * Initialize instruction cache. 373*21b30c00SFlorian Fainelli */ 374*21b30c00SFlorian Fainelli 375*21b30c00SFlorian Fainelli li a0, KSEG0 376*21b30c00SFlorian Fainelli cacheop(a0, v0, v1, Index_Store_Tag_I) 377*21b30c00SFlorian Fainelli 378*21b30c00SFlorian Fainelli /* 379*21b30c00SFlorian Fainelli * Now we can run from I-$, kseg 0 380*21b30c00SFlorian Fainelli */ 381*21b30c00SFlorian Fainelli la k0, 1f 382*21b30c00SFlorian Fainelli lui k1, 0x2000 383*21b30c00SFlorian Fainelli or k0, k1, k0 384*21b30c00SFlorian Fainelli xor k0, k1, k0 385*21b30c00SFlorian Fainelli jr k0 386*21b30c00SFlorian Fainelli nop 387*21b30c00SFlorian Fainelli1: 388*21b30c00SFlorian Fainelli /* 389*21b30c00SFlorian Fainelli * Initialize data cache. 390*21b30c00SFlorian Fainelli */ 391*21b30c00SFlorian Fainelli 392*21b30c00SFlorian Fainelli jal size_d_cache /* v0 = d-cache size, v1 = d-cache line size */ 393*21b30c00SFlorian Fainelli nop 394*21b30c00SFlorian Fainelli 395*21b30c00SFlorian Fainelli 396*21b30c00SFlorian Fainelli li a0, KSEG0 397*21b30c00SFlorian Fainelli cacheop(a0, v0, v1, Index_Store_Tag_D) 398*21b30c00SFlorian Fainelli 399*21b30c00SFlorian Fainelli jr t8 400*21b30c00SFlorian Fainelli nop 401*21b30c00SFlorian Fainelli 402*21b30c00SFlorian Fainelli .end l1_init 403*21b30c00SFlorian Fainelli .set reorder 404*21b30c00SFlorian Fainelli 405*21b30c00SFlorian Fainelli 406*21b30c00SFlorian Fainelli/* 407*21b30c00SFlorian Fainelli * Function: set_other_config 408*21b30c00SFlorian Fainelli * Arguments: none 409*21b30c00SFlorian Fainelli * Returns: None 410*21b30c00SFlorian Fainelli * Description: initialize other remainder configuration to defaults. 411*21b30c00SFlorian Fainelli * Trashes: t0, t1 412*21b30c00SFlorian Fainelli * 413*21b30c00SFlorian Fainelli * pseudo code: 414*21b30c00SFlorian Fainelli * 415*21b30c00SFlorian Fainelli */ 416*21b30c00SFlorian FainelliLEAF(set_other_config) 417*21b30c00SFlorian Fainelli .set noreorder 418*21b30c00SFlorian Fainelli 419*21b30c00SFlorian Fainelli /* enable Bus error for I-fetch */ 420*21b30c00SFlorian Fainelli mfc0 t0, CP0_CACHEERR, 0 421*21b30c00SFlorian Fainelli li t1, 0x4 422*21b30c00SFlorian Fainelli or t0, t1 423*21b30c00SFlorian Fainelli mtc0 t0, CP0_CACHEERR, 0 424*21b30c00SFlorian Fainelli 425*21b30c00SFlorian Fainelli /* enable Bus error for Load */ 426*21b30c00SFlorian Fainelli mfc0 t0, CP0_CACHEERR, 1 427*21b30c00SFlorian Fainelli li t1, 0x4 428*21b30c00SFlorian Fainelli or t0, t1 429*21b30c00SFlorian Fainelli mtc0 t0, CP0_CACHEERR, 1 430*21b30c00SFlorian Fainelli 431*21b30c00SFlorian Fainelli /* enable Bus Error for Store */ 432*21b30c00SFlorian Fainelli mfc0 t0, CP0_CACHEERR, 2 433*21b30c00SFlorian Fainelli li t1, 0x4 434*21b30c00SFlorian Fainelli or t0, t1 435*21b30c00SFlorian Fainelli mtc0 t0, CP0_CACHEERR, 2 436*21b30c00SFlorian Fainelli 437*21b30c00SFlorian Fainelli jr ra 438*21b30c00SFlorian Fainelli nop 439*21b30c00SFlorian Fainelli .set reorder 440*21b30c00SFlorian FainelliEND(set_other_config) 441*21b30c00SFlorian Fainelli 442*21b30c00SFlorian Fainelli/* 443*21b30c00SFlorian Fainelli * Function: set_branch_pred 444*21b30c00SFlorian Fainelli * Arguments: none 445*21b30c00SFlorian Fainelli * Returns: None 446*21b30c00SFlorian Fainelli * Description: 447*21b30c00SFlorian Fainelli * Trashes: t0, t1 448*21b30c00SFlorian Fainelli * 449*21b30c00SFlorian Fainelli * pseudo code: 450*21b30c00SFlorian Fainelli * 451*21b30c00SFlorian Fainelli */ 452*21b30c00SFlorian Fainelli 453*21b30c00SFlorian FainelliLEAF(set_branch_pred) 454*21b30c00SFlorian Fainelli .set noreorder 455*21b30c00SFlorian Fainelli mfc0 t0, CP0_BRCM_MODE 456*21b30c00SFlorian Fainelli li t1, ~(CP0_BRCM_MODE_BrPRED_MASK | CP0_BRCM_MODE_BrHIST_MASK ) 457*21b30c00SFlorian Fainelli and t0, t0, t1 458*21b30c00SFlorian Fainelli 459*21b30c00SFlorian Fainelli /* enable Branch prediction */ 460*21b30c00SFlorian Fainelli li t1, BRCM_BrPRED_BHT_ENABLE 461*21b30c00SFlorian Fainelli sll t1, CP0_BRCM_MODE_BrPRED_SHIFT 462*21b30c00SFlorian Fainelli or t0, t0, t1 463*21b30c00SFlorian Fainelli 464*21b30c00SFlorian Fainelli /* set history count to 8 */ 465*21b30c00SFlorian Fainelli li t1, 8 466*21b30c00SFlorian Fainelli sll t1, CP0_BRCM_MODE_BrHIST_SHIFT 467*21b30c00SFlorian Fainelli or t0, t0, t1 468*21b30c00SFlorian Fainelli 469*21b30c00SFlorian Fainelli mtc0 t0, CP0_BRCM_MODE 470*21b30c00SFlorian Fainelli jr ra 471*21b30c00SFlorian Fainelli nop 472*21b30c00SFlorian Fainelli .set reorder 473*21b30c00SFlorian FainelliEND(set_branch_pred) 474*21b30c00SFlorian Fainelli 475*21b30c00SFlorian Fainelli 476*21b30c00SFlorian Fainelli/* 477*21b30c00SFlorian Fainelli * Function: set_luc 478*21b30c00SFlorian Fainelli * Arguments: set link uncached. 479*21b30c00SFlorian Fainelli * Returns: None 480*21b30c00SFlorian Fainelli * Description: 481*21b30c00SFlorian Fainelli * Trashes: t0, t1 482*21b30c00SFlorian Fainelli * 483*21b30c00SFlorian Fainelli */ 484*21b30c00SFlorian FainelliLEAF(set_luc) 485*21b30c00SFlorian Fainelli .set noreorder 486*21b30c00SFlorian Fainelli mfc0 t0, CP0_BRCM_MODE 487*21b30c00SFlorian Fainelli li t1, ~(CP0_BRCM_MODE_Luc_MASK) 488*21b30c00SFlorian Fainelli and t0, t0, t1 489*21b30c00SFlorian Fainelli 490*21b30c00SFlorian Fainelli /* set Luc */ 491*21b30c00SFlorian Fainelli ori t0, t0, CP0_BRCM_MODE_Luc_MASK 492*21b30c00SFlorian Fainelli 493*21b30c00SFlorian Fainelli mtc0 t0, CP0_BRCM_MODE 494*21b30c00SFlorian Fainelli jr ra 495*21b30c00SFlorian Fainelli nop 496*21b30c00SFlorian Fainelli .set reorder 497*21b30c00SFlorian FainelliEND(set_luc) 498*21b30c00SFlorian Fainelli 499*21b30c00SFlorian Fainelli/* 500*21b30c00SFlorian Fainelli * Function: set_cwf_tse 501*21b30c00SFlorian Fainelli * Arguments: set CWF and TSE bits 502*21b30c00SFlorian Fainelli * Returns: None 503*21b30c00SFlorian Fainelli * Description: 504*21b30c00SFlorian Fainelli * Trashes: t0, t1 505*21b30c00SFlorian Fainelli * 506*21b30c00SFlorian Fainelli */ 507*21b30c00SFlorian FainelliLEAF(set_cwf_tse) 508*21b30c00SFlorian Fainelli .set noreorder 509*21b30c00SFlorian Fainelli mfc0 t0, CP0_BRCM_CONFIG0 510*21b30c00SFlorian Fainelli li t1, (CP0_BRCM_CONFIG0_CWF_MASK | CP0_BRCM_CONFIG0_TSE_MASK) 511*21b30c00SFlorian Fainelli or t0, t0, t1 512*21b30c00SFlorian Fainelli 513*21b30c00SFlorian Fainelli mtc0 t0, CP0_BRCM_CONFIG0 514*21b30c00SFlorian Fainelli jr ra 515*21b30c00SFlorian Fainelli nop 516*21b30c00SFlorian Fainelli .set reorder 517*21b30c00SFlorian FainelliEND(set_cwf_tse) 518*21b30c00SFlorian Fainelli 519*21b30c00SFlorian Fainelli/* 520*21b30c00SFlorian Fainelli * Function: set_clock_ratio 521*21b30c00SFlorian Fainelli * Arguments: set clock ratio specified by a0 522*21b30c00SFlorian Fainelli * Returns: None 523*21b30c00SFlorian Fainelli * Description: 524*21b30c00SFlorian Fainelli * Trashes: v0, v1, a0, a1 525*21b30c00SFlorian Fainelli * 526*21b30c00SFlorian Fainelli * pseudo code: 527*21b30c00SFlorian Fainelli * 528*21b30c00SFlorian Fainelli */ 529*21b30c00SFlorian FainelliLEAF(set_clock_ratio) 530*21b30c00SFlorian Fainelli .set noreorder 531*21b30c00SFlorian Fainelli 532*21b30c00SFlorian Fainelli mfc0 t0, CP0_BRCM_MODE 533*21b30c00SFlorian Fainelli li t1, ~(CP0_BRCM_MODE_SET_MASK | CP0_BRCM_MODE_ClkRATIO_MASK) 534*21b30c00SFlorian Fainelli and t0, t0, t1 535*21b30c00SFlorian Fainelli li t1, CP0_BRCM_MODE_SET_MASK 536*21b30c00SFlorian Fainelli or t0, t0, t1 537*21b30c00SFlorian Fainelli or t0, t0, a0 538*21b30c00SFlorian Fainelli mtc0 t0, CP0_BRCM_MODE 539*21b30c00SFlorian Fainelli jr ra 540*21b30c00SFlorian Fainelli nop 541*21b30c00SFlorian Fainelli .set reorder 542*21b30c00SFlorian FainelliEND(set_clock_ratio) 543*21b30c00SFlorian Fainelli/* 544*21b30c00SFlorian Fainelli * Function: set_zephyr 545*21b30c00SFlorian Fainelli * Arguments: None 546*21b30c00SFlorian Fainelli * Returns: None 547*21b30c00SFlorian Fainelli * Description: Set any zephyr bits 548*21b30c00SFlorian Fainelli * Trashes: t0 & t1 549*21b30c00SFlorian Fainelli * 550*21b30c00SFlorian Fainelli */ 551*21b30c00SFlorian FainelliLEAF(set_zephyr) 552*21b30c00SFlorian Fainelli .set noreorder 553*21b30c00SFlorian Fainelli 554*21b30c00SFlorian Fainelli /* enable read/write of CP0 #22 sel. 8 */ 555*21b30c00SFlorian Fainelli li t0, 0x5a455048 556*21b30c00SFlorian Fainelli .word 0x4088b00f /* mtc0 t0, $22, 15 */ 557*21b30c00SFlorian Fainelli 558*21b30c00SFlorian Fainelli .word 0x4008b008 /* mfc0 t0, $22, 8 */ 559*21b30c00SFlorian Fainelli li t1, 0x09008000 /* turn off pref, jtb */ 560*21b30c00SFlorian Fainelli or t0, t0, t1 561*21b30c00SFlorian Fainelli .word 0x4088b008 /* mtc0 t0, $22, 8 */ 562*21b30c00SFlorian Fainelli sync 563*21b30c00SFlorian Fainelli 564*21b30c00SFlorian Fainelli /* disable read/write of CP0 #22 sel 8 */ 565*21b30c00SFlorian Fainelli li t0, 0x0 566*21b30c00SFlorian Fainelli .word 0x4088b00f /* mtc0 t0, $22, 15 */ 567*21b30c00SFlorian Fainelli 568*21b30c00SFlorian Fainelli 569*21b30c00SFlorian Fainelli jr ra 570*21b30c00SFlorian Fainelli nop 571*21b30c00SFlorian Fainelli .set reorder 572*21b30c00SFlorian Fainelli 573*21b30c00SFlorian FainelliEND(set_zephyr) 574*21b30c00SFlorian Fainelli 575*21b30c00SFlorian Fainelli 576*21b30c00SFlorian Fainelli/* 577*21b30c00SFlorian Fainelli * Function: set_llmb 578*21b30c00SFlorian Fainelli * Arguments: a0=0 disable llmb, a0=1 enables llmb 579*21b30c00SFlorian Fainelli * Returns: None 580*21b30c00SFlorian Fainelli * Description: 581*21b30c00SFlorian Fainelli * Trashes: t0, t1, t2 582*21b30c00SFlorian Fainelli * 583*21b30c00SFlorian Fainelli * pseudo code: 584*21b30c00SFlorian Fainelli * 585*21b30c00SFlorian Fainelli */ 586*21b30c00SFlorian FainelliLEAF(set_llmb) 587*21b30c00SFlorian Fainelli .set noreorder 588*21b30c00SFlorian Fainelli 589*21b30c00SFlorian Fainelli li t2, 0x90000000 | BRCM_ZSC_ALL_REGS_SELECT | BRCM_ZSC_CONFIG_REG 590*21b30c00SFlorian Fainelli sync 591*21b30c00SFlorian Fainelli cache 0x7, 0x0(t2) 592*21b30c00SFlorian Fainelli sync 593*21b30c00SFlorian Fainelli mfc0 t0, CP0_D_SEC_CACHE_DATA_LO 594*21b30c00SFlorian Fainelli li t1, ~(BRCM_ZSC_CONFIG_LMB1En | BRCM_ZSC_CONFIG_LMB0En) 595*21b30c00SFlorian Fainelli and t0, t0, t1 596*21b30c00SFlorian Fainelli 597*21b30c00SFlorian Fainelli beqz a0, svlmb 598*21b30c00SFlorian Fainelli nop 599*21b30c00SFlorian Fainelli 600*21b30c00SFlorian Fainellienable_lmb: 601*21b30c00SFlorian Fainelli li t1, (BRCM_ZSC_CONFIG_LMB1En | BRCM_ZSC_CONFIG_LMB0En) 602*21b30c00SFlorian Fainelli or t0, t0, t1 603*21b30c00SFlorian Fainelli 604*21b30c00SFlorian Fainellisvlmb: 605*21b30c00SFlorian Fainelli mtc0 t0, CP0_D_SEC_CACHE_DATA_LO 606*21b30c00SFlorian Fainelli sync 607*21b30c00SFlorian Fainelli cache 0xb, 0x0(t2) 608*21b30c00SFlorian Fainelli sync 609*21b30c00SFlorian Fainelli 610*21b30c00SFlorian Fainelli jr ra 611*21b30c00SFlorian Fainelli nop 612*21b30c00SFlorian Fainelli .set reorder 613*21b30c00SFlorian Fainelli 614*21b30c00SFlorian FainelliEND(set_llmb) 615*21b30c00SFlorian Fainelli/* 616*21b30c00SFlorian Fainelli * Function: core_init 617*21b30c00SFlorian Fainelli * Arguments: none 618*21b30c00SFlorian Fainelli * Returns: None 619*21b30c00SFlorian Fainelli * Description: initialize core related configuration 620*21b30c00SFlorian Fainelli * Trashes: v0,v1,a0,a1,t8 621*21b30c00SFlorian Fainelli * 622*21b30c00SFlorian Fainelli * pseudo code: 623*21b30c00SFlorian Fainelli * 624*21b30c00SFlorian Fainelli */ 625*21b30c00SFlorian Fainelli .globl core_init 626*21b30c00SFlorian Fainelli .ent core_init 627*21b30c00SFlorian Fainelli .set noreorder 628*21b30c00SFlorian Fainellicore_init: 629*21b30c00SFlorian Fainelli move t8, ra 630*21b30c00SFlorian Fainelli 631*21b30c00SFlorian Fainelli /* set Zephyr bits. */ 632*21b30c00SFlorian Fainelli bal set_zephyr 633*21b30c00SFlorian Fainelli nop 634*21b30c00SFlorian Fainelli 635*21b30c00SFlorian Fainelli /* set low latency memory bus */ 636*21b30c00SFlorian Fainelli li a0, 1 637*21b30c00SFlorian Fainelli bal set_llmb 638*21b30c00SFlorian Fainelli nop 639*21b30c00SFlorian Fainelli 640*21b30c00SFlorian Fainelli /* set branch prediction (TP0 only) */ 641*21b30c00SFlorian Fainelli bal set_branch_pred 642*21b30c00SFlorian Fainelli nop 643*21b30c00SFlorian Fainelli 644*21b30c00SFlorian Fainelli /* set link uncached */ 645*21b30c00SFlorian Fainelli bal set_luc 646*21b30c00SFlorian Fainelli nop 647*21b30c00SFlorian Fainelli 648*21b30c00SFlorian Fainelli /* set CWF and TSE */ 649*21b30c00SFlorian Fainelli bal set_cwf_tse 650*21b30c00SFlorian Fainelli nop 651*21b30c00SFlorian Fainelli 652*21b30c00SFlorian Fainelli /* 653*21b30c00SFlorian Fainelli *set clock ratio by setting 1 to 'set' 654*21b30c00SFlorian Fainelli * and 0 to ClkRatio, (TP0 only) 655*21b30c00SFlorian Fainelli */ 656*21b30c00SFlorian Fainelli li a0, 0 657*21b30c00SFlorian Fainelli bal set_clock_ratio 658*21b30c00SFlorian Fainelli nop 659*21b30c00SFlorian Fainelli 660*21b30c00SFlorian Fainelli /* set other configuration to defaults */ 661*21b30c00SFlorian Fainelli bal set_other_config 662*21b30c00SFlorian Fainelli nop 663*21b30c00SFlorian Fainelli 664*21b30c00SFlorian Fainelli move ra, t8 665*21b30c00SFlorian Fainelli jr ra 666*21b30c00SFlorian Fainelli nop 667*21b30c00SFlorian Fainelli 668*21b30c00SFlorian Fainelli .set reorder 669*21b30c00SFlorian Fainelli .end core_init 670*21b30c00SFlorian Fainelli 671*21b30c00SFlorian Fainelli/* 672*21b30c00SFlorian Fainelli * Function: clear_jump_target_buffer 673*21b30c00SFlorian Fainelli * Arguments: None 674*21b30c00SFlorian Fainelli * Returns: None 675*21b30c00SFlorian Fainelli * Description: 676*21b30c00SFlorian Fainelli * Trashes: t0, t1, t2 677*21b30c00SFlorian Fainelli * 678*21b30c00SFlorian Fainelli */ 679*21b30c00SFlorian Fainelli#define RESET_CALL_RETURN_STACK_THIS_THREAD (0x06<<16) 680*21b30c00SFlorian Fainelli#define RESET_JUMP_TARGET_BUFFER_THIS_THREAD (0x04<<16) 681*21b30c00SFlorian Fainelli#define JTB_CS_CNTL_MASK (0xFF<<16) 682*21b30c00SFlorian Fainelli 683*21b30c00SFlorian Fainelli .globl clear_jump_target_buffer 684*21b30c00SFlorian Fainelli .ent clear_jump_target_buffer 685*21b30c00SFlorian Fainelli .set noreorder 686*21b30c00SFlorian Fainelliclear_jump_target_buffer: 687*21b30c00SFlorian Fainelli 688*21b30c00SFlorian Fainelli mfc0 t0, $22, 2 689*21b30c00SFlorian Fainelli nop 690*21b30c00SFlorian Fainelli nop 691*21b30c00SFlorian Fainelli 692*21b30c00SFlorian Fainelli li t1, ~JTB_CS_CNTL_MASK 693*21b30c00SFlorian Fainelli and t0, t0, t1 694*21b30c00SFlorian Fainelli li t2, RESET_CALL_RETURN_STACK_THIS_THREAD 695*21b30c00SFlorian Fainelli or t0, t0, t2 696*21b30c00SFlorian Fainelli mtc0 t0, $22, 2 697*21b30c00SFlorian Fainelli nop 698*21b30c00SFlorian Fainelli nop 699*21b30c00SFlorian Fainelli 700*21b30c00SFlorian Fainelli and t0, t0, t1 701*21b30c00SFlorian Fainelli li t2, RESET_JUMP_TARGET_BUFFER_THIS_THREAD 702*21b30c00SFlorian Fainelli or t0, t0, t2 703*21b30c00SFlorian Fainelli mtc0 t0, $22, 2 704*21b30c00SFlorian Fainelli nop 705*21b30c00SFlorian Fainelli nop 706*21b30c00SFlorian Fainelli jr ra 707*21b30c00SFlorian Fainelli nop 708*21b30c00SFlorian Fainelli 709*21b30c00SFlorian Fainelli .end clear_jump_target_buffer 710*21b30c00SFlorian Fainelli .set reorder 711*21b30c00SFlorian Fainelli/* 712*21b30c00SFlorian Fainelli * Function: bmips_cache_init 713*21b30c00SFlorian Fainelli * Arguments: None 714*21b30c00SFlorian Fainelli * Returns: None 715*21b30c00SFlorian Fainelli * Description: Enable I and D caches, and initialize I and D-caches 716*21b30c00SFlorian Fainelli * Trashes: v0, v1, t0, t1, t2, t5, t7, t8 717*21b30c00SFlorian Fainelli * 718*21b30c00SFlorian Fainelli */ 719*21b30c00SFlorian Fainelli .globl bmips_5xxx_init 720*21b30c00SFlorian Fainelli .ent bmips_5xxx_init 721*21b30c00SFlorian Fainelli .set noreorder 722*21b30c00SFlorian Fainellibmips_5xxx_init: 723*21b30c00SFlorian Fainelli 724*21b30c00SFlorian Fainelli /* save return address and A0 */ 725*21b30c00SFlorian Fainelli move t7, ra 726*21b30c00SFlorian Fainelli move t5, a0 727*21b30c00SFlorian Fainelli 728*21b30c00SFlorian Fainelli jal l1_init 729*21b30c00SFlorian Fainelli nop 730*21b30c00SFlorian Fainelli 731*21b30c00SFlorian Fainelli jal core_init 732*21b30c00SFlorian Fainelli nop 733*21b30c00SFlorian Fainelli 734*21b30c00SFlorian Fainelli jal clear_jump_target_buffer 735*21b30c00SFlorian Fainelli nop 736*21b30c00SFlorian Fainelli 737*21b30c00SFlorian Fainelli mtc0 zero, CP0_CAUSE 738*21b30c00SFlorian Fainelli 739*21b30c00SFlorian Fainelli move a0, t5 740*21b30c00SFlorian Fainelli jr t7 741*21b30c00SFlorian Fainelli nop 742*21b30c00SFlorian Fainelli 743*21b30c00SFlorian Fainelli .end bmips_5xxx_init 744*21b30c00SFlorian Fainelli .set reorder 745*21b30c00SFlorian Fainelli 746*21b30c00SFlorian Fainelli 747*21b30c00SFlorian Fainelli#endif 748