| 1 | /* SPDX-License-Identifier: GPL-2.0-only */
|
| 2 | /*
|
| 3 | * ARC CPU startup Code
|
| 4 | *
|
| 5 | * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
|
| 6 | *
|
| 7 | * Vineetg: Dec 2007
|
| 8 | * -Check if we are running on Simulator or on real hardware
|
| 9 | * to skip certain things during boot on simulator
|
| 10 | */
|
| 11 |
|
| 12 | |
| 13 | |
| 14 | |
| 15 | |
| 16 | |
| 17 | |
| 18 | |
| 19 |
|
| 20 | .macro CPU_EARLY_SETUP
|
| 21 |
|
| 22 | ; Setting up Vectror Table (in case exception happens in early boot
|
| 23 | sr @_int_vec_base_lds, [AUX_INTR_VEC_BASE]
|
| 24 |
|
| 25 | ; Disable I-cache/D-cache if kernel so configured
|
| 26 | lr r5, [ARC_REG_IC_BCR]
|
| 27 | breq r5, 0, 1f ; I$ doesn't exist
|
| 28 | lr r5, [ARC_REG_IC_CTRL]
|
| 29 | #ifdef CONFIG_ARC_HAS_ICACHE
|
| 30 | bclr r5, r5, 0 ; 0 - Enable, 1 is Disable
|
| 31 | #else
|
| 32 | bset r5, r5, 0 ; I$ exists, but is not used
|
| 33 | #endif
|
| 34 | sr r5, [ARC_REG_IC_CTRL]
|
| 35 |
|
| 36 | 1:
|
| 37 | lr r5, [ARC_REG_DC_BCR]
|
| 38 | breq r5, 0, 1f ; D$ doesn't exist
|
| 39 | lr r5, [ARC_REG_DC_CTRL]
|
| 40 | bclr r5, r5, 6 ; Invalidate (discard w/o wback)
|
| 41 | |
| 42 | bclr r5, r5, 0 ; Enable (+Inv)
|
| 43 | |
| 44 | bset r5, r5, 0 ; Disable (+Inv)
|
| 45 | |
| 46 | sr r5, [ARC_REG_DC_CTRL]
|
| 47 |
|
| 48 | 1:
|
| 49 |
|
| 50 | |
| 51 | ; Unaligned access is disabled at reset, so re-enable early as
|
| 52 | ; gcc 7.3.1 (ARC GNU 2018.03) onwards generates unaligned access
|
| 53 | ; by default
|
| 54 | lr r5, [status32]
|
| 55 | |
| 56 | bset r5, r5, STATUS_AD_BIT
|
| 57 | |
| 58 | ; Although disabled at reset, bootloader might have enabled it
|
| 59 | bclr r5, r5, STATUS_AD_BIT
|
| 60 | |
| 61 | kflag r5
|
| 62 |
|
| 63 | |
| 64 | lr r5, [ARC_REG_LPB_BUILD]
|
| 65 | breq r5, 0, 1f ; LPB doesn't exist
|
| 66 | mov r5, 1
|
| 67 | sr r5, [ARC_REG_LPB_CTRL]
|
| 68 | 1:
|
| 69 | #endif /* CONFIG_ARC_LPB_DISABLE */
|
| 70 |
|
| 71 | /* On HSDK, CCMs need to remapped super early */
|
| 72 | #ifdef CONFIG_ARC_SOC_HSDK
|
| 73 | mov r6, 0x60000000
|
| 74 | lr r5, [ARC_REG_ICCM_BUILD]
|
| 75 | breq r5, 0, 1f
|
| 76 | sr r6, [ARC_REG_AUX_ICCM]
|
| 77 | 1:
|
| 78 | lr r5, [ARC_REG_DCCM_BUILD]
|
| 79 | breq r5, 0, 2f
|
| 80 | sr r6, [ARC_REG_AUX_DCCM]
|
| 81 | 2:
|
| 82 | #endif /* CONFIG_ARC_SOC_HSDK */
|
| 83 |
|
| 84 | #endif /* CONFIG_ISA_ARCV2 */
|
| 85 |
|
| 86 | ; Config DSP_CTRL properly, so kernel may use integer multiply,
|
| 87 | ; multiply-accumulate, and divide operations
|
| 88 | DSP_EARLY_INIT
|
| 89 | .endm
|
| 90 |
|
| 91 | .section .init.text, "ax",@progbits
|
| 92 |
|
| 93 | ;----------------------------------------------------------------
|
| 94 | ; Default Reset Handler (jumped into from Reset vector)
|
| 95 | ; - Don't clobber r0,r1,r2 as they might have u-boot provided args
|
| 96 | ; - Platforms can override this weak version if needed
|
| 97 | ;----------------------------------------------------------------
|
| 98 | WEAK(res_service)
|
| 99 | j stext
|
| 100 | END(res_service)
|
| 101 |
|
| 102 | ;----------------------------------------------------------------
|
| 103 | ; Kernel Entry point
|
| 104 | ;----------------------------------------------------------------
|
| 105 | ENTRY(stext)
|
| 106 |
|
| 107 | CPU_EARLY_SETUP
|
| 108 |
|
| 109 | |
| 110 | GET_CPU_ID r5
|
| 111 | cmp r5, 0
|
| 112 | mov.nz r0, r5
|
| 113 | bz .Lmaster_proceed
|
| 114 |
|
| 115 | ; Non-Masters wait for Master to boot enough and bring them up
|
| 116 | ; when they resume, tail-call to entry point
|
| 117 | mov blink, @first_lines_of_secondary
|
| 118 | j arc_platform_smp_wait_to_boot
|
| 119 |
|
| 120 | .Lmaster_proceed:
|
| 121 | |
| 122 |
|
| 123 | ; Clear BSS before updating any globals
|
| 124 | ; XXX: use ZOL here
|
| 125 | mov r5, __bss_start
|
| 126 | sub r6, __bss_stop, r5
|
| 127 | lsr.f lp_count, r6, 2
|
| 128 | lpnz 1f
|
| 129 | st.ab 0, [r5, 4]
|
| 130 | 1:
|
| 131 |
|
| 132 | ; Uboot - kernel ABI
|
| 133 | ; r0 = [0] No uboot interaction, [1] cmdline in r2, [2] DTB in r2
|
| 134 | ; r1 = magic number (always zero as of now)
|
| 135 | ; r2 = pointer to uboot provided cmdline or external DTB in mem
|
| 136 | ; These are handled later in handle_uboot_args()
|
| 137 | st r0, [@uboot_tag]
|
| 138 | st r1, [@uboot_magic]
|
| 139 | st r2, [@uboot_arg]
|
| 140 |
|
| 141 | ; setup "current" tsk and optionally cache it in dedicated r25
|
| 142 | mov r9, @init_task
|
| 143 | SET_CURR_TASK_ON_CPU r9, r0 ; r9 = tsk, r0 = scratch
|
| 144 |
|
| 145 | ; setup stack (fp, sp)
|
| 146 | mov fp, 0
|
| 147 |
|
| 148 | ; tsk->thread_info is really a PAGE, whose bottom hoists stack
|
| 149 | GET_TSK_STACK_BASE r9, sp ; r9 = tsk, sp = stack base(output)
|
| 150 |
|
| 151 | j start_kernel ; "C" entry point
|
| 152 | END(stext)
|
| 153 |
|
| 154 | |
| 155 | ;----------------------------------------------------------------
|
| 156 | ; First lines of code run by secondary before jumping to 'C'
|
| 157 | ;----------------------------------------------------------------
|
| 158 | .section .text, "ax",@progbits
|
| 159 | ENTRY(first_lines_of_secondary)
|
| 160 |
|
| 161 | ; setup per-cpu idle task as "current" on this CPU
|
| 162 | ld r0, [@secondary_idle_tsk]
|
| 163 | SET_CURR_TASK_ON_CPU r0, r1
|
| 164 |
|
| 165 | ; setup stack (fp, sp)
|
| 166 | mov fp, 0
|
| 167 |
|
| 168 | ; set its stack base to tsk->thread_info bottom
|
| 169 | GET_TSK_STACK_BASE r0, sp
|
| 170 |
|
| 171 | j start_kernel_secondary
|
| 172 | END(first_lines_of_secondary)
|
| 173 | |