Module Name: src Committed By: jmcneill Date: Fri Oct 10 23:51:28 UTC 2014
Modified Files: src/sys/arch/evbarm/awin: awin_start.S Log Message: A31 SMP support To generate a diff of this commit: cvs rdiff -u -r1.2 -r1.3 src/sys/arch/evbarm/awin/awin_start.S Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/evbarm/awin/awin_start.S diff -u src/sys/arch/evbarm/awin/awin_start.S:1.2 src/sys/arch/evbarm/awin/awin_start.S:1.3 --- src/sys/arch/evbarm/awin/awin_start.S:1.2 Thu Sep 25 07:59:29 2014 +++ src/sys/arch/evbarm/awin/awin_start.S Fri Oct 10 23:51:28 2014 @@ -41,7 +41,7 @@ #include <arm/allwinner/awin_reg.h> #include <evbarm/awin/platform.h> -RCSID("$NetBSD: awin_start.S,v 1.2 2014/09/25 07:59:29 matt Exp $") +RCSID("$NetBSD: awin_start.S,v 1.3 2014/10/10 23:51:28 jmcneill Exp $") #if defined(VERBOSE_INIT_ARM) #define XPUTC(n) mov r0, n; bl xputc @@ -150,7 +150,29 @@ _C_LABEL(awin_start): XPUTC2(#60) // Make sure the cache is flushed out to RAM for the other CPUs bl _C_LABEL(armv7_dcache_wbinv_all) - bl a20_mpinit + + // Read SoC ID + movw r5, #:lower16:(AWIN_CORE_PBASE+AWIN_SRAM_OFFSET) + movt r5, #:upper16:(AWIN_CORE_PBASE+AWIN_SRAM_OFFSET) + ldr r1, [r5, #AWIN_SRAM_VER_REG] + orr r1, r1, AWIN_SRAM_VER_R_EN + str r1, [r5, #AWIN_SRAM_VER_REG] + dsb + ldr r1, [r5, #AWIN_SRAM_VER_REG] + lsr r1, r1, #16 + + // MP init based on SoC ID +#if defined(ALLWINNER_A20) + movw r0, #AWIN_SRAM_VER_KEY_A20 + cmp r1, r0 + bleq a20_mpinit +#endif +#if defined(ALLWINNER_A31) + movw r0, #AWIN_SRAM_VER_KEY_A31 + cmp r1, r0 + bleq a31_mpinit +#endif + XPUTC2(#62) #endif /* MULTIPROCESSOR */ XPUTC2(#13) @@ -178,6 +200,10 @@ a20_mpinit: movw r5, #:lower16:(AWIN_CORE_PBASE+AWIN_CPUCFG_OFFSET) movt r5, #:upper16:(AWIN_CORE_PBASE+AWIN_CPUCFG_OFFSET) + XPUTC2(#65) + XPUTC2(#50) + XPUTC2(#48) + #ifdef __ARMEB__ setend le // everything here is little-endian #endif @@ -258,6 +284,144 @@ ASEND(a20_mpinit) #ifndef KERNEL_BASES_EQUAL .popsection #endif + +#ifndef KERNEL_BASES_EQUAL + .pushsection .text,"ax",%progbits +#endif +a31_mpinit: + mov r4, lr // because we call gtmr_bootdelay + movw r5, #:lower16:(AWIN_CORE_PBASE+AWIN_A31_CPUCFG_OFFSET) + movt r5, #:upper16:(AWIN_CORE_PBASE+AWIN_A31_CPUCFG_OFFSET) + movw r6, #:lower16:(AWIN_CORE_PBASE+AWIN_A31_PRCM_OFFSET) + movt r6, #:upper16:(AWIN_CORE_PBASE+AWIN_A31_PRCM_OFFSET) + + XPUTC2(#65) + XPUTC2(#51) + XPUTC2(#49) + +#ifdef __ARMEB__ + setend le // everything here is little-endian +#endif + + mov r12, #1 // CPU number + +a31_mpinit_cpu: + + XPUTC2(r12) + + /* Set where the other CPU(s) are going to execute */ + movw r1, #:lower16:cortex_mpstart + movt r1, #:upper16:cortex_mpstart + str r1, [r5, #AWIN_CPUCFG_PRIVATE_REG] + dsb + + /* Assert CPU core reset */ + mov r1, #0 + mov r2, #0x40 + mul r7, r12, r2 + add r7, r7, #AWIN_A31_CPUCFG_CPU0_RST_CTRL_REG + str r1, [r5, r7] + dsb + + /* Ensure CPUX reset also invalidates its L1 caches */ + ldr r1, [r5, #AWIN_CPUCFG_GENCTRL_REG] + mov r0, #1 + lsl r0, r0, r12 + bic r1, r1, r0 + str r1, [r5, #AWIN_CPUCFG_GENCTRL_REG] + dsb + + /* Release power clamp */ + mov r1, #0xe7 + mov r2, #0x4 + mul r7, r12, r2 + add r7, r7, #AWIN_A31_PRCM_CPUX_PWR_CLAMP_REG + str r1, [r6, r7] + dsb + + mov r2, #0x40 + mul r7, r12, r2 + add r7, r7, #AWIN_A31_CPUCFG_CPU0_PWR_CLAMP_STATUS_REG +1: + ldr r1, [r5, r7] + cmp r1, #0xe7 + bne 1b + + /* We need to wait (at least) 10ms */ + mov r0, #0x3b000 // 10.06ms + bl _C_LABEL(gtmr_bootdelay) // endian-neutral + + /* Restore power clamp */ + mov r1, #0 + mov r2, #0x4 + mul r7, r12, r2 + add r7, r7, #AWIN_A31_PRCM_CPUX_PWR_CLAMP_REG + str r1, [r6, r7] + dsb + + mov r2, #0x40 + mul r7, r12, r2 + add r7, r7, #AWIN_A31_CPUCFG_CPU0_PWR_CLAMP_STATUS_REG +1: + ldr r1, [r5, r7] + cmp r1, #0 + bne 1b + + /* We need to wait (at least) 10ms */ + mov r0, #0x3b000 // 10.06ms + bl _C_LABEL(gtmr_bootdelay) // endian-neutral + + /* Clear power-off gating */ + ldr r1, [r6, #AWIN_A31_PRCM_PWROFF_GATING_REG] + mov r0, #1 + lsl r0, r0, r12 + bic r1, r1, r0 + str r1, [r6, #AWIN_A31_PRCM_PWROFF_GATING_REG] + dsb + + /* We need to wait (at least) 10ms */ + mov r0, #0x3b000 // 10.06ms + bl _C_LABEL(gtmr_bootdelay) // endian-neutral + + /* Bring CPUX out of reset */ + mov r1, #(AWIN_A31_CPUCFG_RST_CTRL_CPU_RESET|AWIN_A31_CPUCFG_RST_CTRL_CORE_RESET) + mov r2, #0x40 + mul r7, r12, r2 + add r7, r7, #AWIN_A31_CPUCFG_CPU0_RST_CTRL_REG + str r1, [r5, r7] + dsb + + /* If there is another CPU, start it */ + add r12, r12, #1 + cmp r12, #3 + ble a31_mpinit_cpu + +#ifdef __ARMEB__ + setend be // we're done with little endian +#endif + + // + // Wait up a second for CPU1-3 to hatch. + // + movw r6, #:lower16:arm_cpu_hatched + movt r6, #:upper16:arm_cpu_hatched + mov r5, #200 // 200 x 5ms + +1: dmb // memory barrier + ldr r0, [r6] // load hatched + tst r0, #0xe // our bits set yet? + bxne r4 // yes, return + subs r5, r5, #1 // decrement count + bxeq r4 // 0? return + mov r0, #0x1d800 // 5.03ms + bl _C_LABEL(gtmr_bootdelay) + b 1b + +ASEND(a31_mpinit) +#ifndef KERNEL_BASES_EQUAL + .popsection +#endif + #endif /* MULTIPROCESSOR */ .Lmmu_init_table: