uboot/arch/microblaze/cpu/start.S
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2007 Michal Simek
   3 * (C) Copyright 2004 Atmark Techno, Inc.
   4 *
   5 * Michal  SIMEK <monstr@monstr.eu>
   6 * Yasushi SHOJI <yashi@atmark-techno.com>
   7 *
   8 * SPDX-License-Identifier:     GPL-2.0+
   9 */
  10
  11#include <asm-offsets.h>
  12#include <config.h>
  13
  14        .text
  15        .global _start
  16_start:
  17        /*
  18         * reserve registers:
  19         * r10: Stores little/big endian offset for vectors
  20         * r2: Stores imm opcode
  21         * r3: Stores brai opcode
  22         */
  23
  24        mts     rmsr, r0        /* disable cache */
  25
  26        addi    r8, r0, __end
  27        mts     rslr, r8
  28        /* TODO: Redo this code to call board_init_f_*() */
  29#if defined(CONFIG_SPL_BUILD)
  30        addi    r1, r0, CONFIG_SPL_STACK_ADDR
  31        mts     rshr, r1
  32        addi    r1, r1, -4      /* Decrement SP to top of memory */
  33#else
  34#if defined(CONFIG_SYS_MALLOC_F_LEN)
  35        addi    r1, r0, CONFIG_SYS_INIT_SP_OFFSET - CONFIG_SYS_MALLOC_F_LEN
  36#else
  37        addi    r1, r0, CONFIG_SYS_INIT_SP_OFFSET
  38#endif
  39        mts     rshr, r1
  40        addi    r1, r1, -4      /* Decrement SP to top of memory */
  41
  42        /* Find-out if u-boot is running on BIG/LITTLE endian platform
  43         * There are some steps which is necessary to keep in mind:
  44         * 1. Setup offset value to r6
  45         * 2. Store word offset value to address 0x0
  46         * 3. Load just byte from address 0x0
  47         * 4a) LITTLE endian - r10 contains 0x2 because it is the smallest
  48         *     value that's why is on address 0x0
  49         * 4b) BIG endian - r10 contains 0x0 because 0x2 offset is on addr 0x3
  50         */
  51        addik   r6, r0, 0x2 /* BIG/LITTLE endian offset */
  52        lwi     r7, r0, 0x28
  53        swi     r6, r0, 0x28 /* used first unused MB vector */
  54        lbui    r10, r0, 0x28 /* used first unused MB vector */
  55        swi     r7, r0, 0x28
  56
  57        /* add opcode instruction for 32bit jump - 2 instruction imm & brai */
  58        addi    r2, r0, 0xb0000000      /* hex b000 opcode imm */
  59        addi    r3, r0, 0xb8080000      /* hew b808 opcode brai */
  60
  61#ifdef CONFIG_SYS_RESET_ADDRESS
  62        /* reset address */
  63        swi     r2, r0, 0x0     /* reset address - imm opcode */
  64        swi     r3, r0, 0x4     /* reset address - brai opcode */
  65
  66        addik   r6, r0, CONFIG_SYS_RESET_ADDRESS
  67        sw      r6, r1, r0
  68        lhu     r7, r1, r10
  69        rsubi   r8, r10, 0x2
  70        sh      r7, r0, r8
  71        rsubi   r8, r10, 0x6
  72        sh      r6, r0, r8
  73#endif
  74
  75#ifdef CONFIG_SYS_USR_EXCEP
  76        /* user_vector_exception */
  77        swi     r2, r0, 0x8     /* user vector exception - imm opcode */
  78        swi     r3, r0, 0xC     /* user vector exception - brai opcode */
  79
  80        addik   r6, r0, _exception_handler
  81        sw      r6, r1, r0
  82        /*
  83         * BIG ENDIAN memory map for user exception
  84         * 0x8: 0xB000XXXX
  85         * 0xC: 0xB808XXXX
  86         *
  87         * then it is necessary to count address for storing the most significant
  88         * 16bits from _exception_handler address and copy it to
  89         * 0xa address. Big endian use offset in r10=0 that's why is it just
  90         * 0xa address. The same is done for the least significant 16 bits
  91         * for 0xe address.
  92         *
  93         * LITTLE ENDIAN memory map for user exception
  94         * 0x8: 0xXXXX00B0
  95         * 0xC: 0xXXXX08B8
  96         *
  97         * Offset is for little endian setup to 0x2. rsubi instruction decrease
  98         * address value to ensure that points to proper place which is
  99         * 0x8 for the most significant 16 bits and
 100         * 0xC for the least significant 16 bits
 101         */
 102        lhu     r7, r1, r10
 103        rsubi   r8, r10, 0xa
 104        sh      r7, r0, r8
 105        rsubi   r8, r10, 0xe
 106        sh      r6, r0, r8
 107#endif
 108
 109        /* interrupt_handler */
 110        swi     r2, r0, 0x10    /* interrupt - imm opcode */
 111        swi     r3, r0, 0x14    /* interrupt - brai opcode */
 112
 113        addik   r6, r0, _interrupt_handler
 114        sw      r6, r1, r0
 115        lhu     r7, r1, r10
 116        rsubi   r8, r10, 0x12
 117        sh      r7, r0, r8
 118        rsubi   r8, r10, 0x16
 119        sh      r6, r0, r8
 120
 121        /* hardware exception */
 122        swi     r2, r0, 0x20    /* hardware exception - imm opcode */
 123        swi     r3, r0, 0x24    /* hardware exception - brai opcode */
 124
 125        addik   r6, r0, _hw_exception_handler
 126        sw      r6, r1, r0
 127        lhu     r7, r1, r10
 128        rsubi   r8, r10, 0x22
 129        sh      r7, r0, r8
 130        rsubi   r8, r10, 0x26
 131        sh      r6, r0, r8
 132#endif /* BUILD_SPL */
 133
 134        /* Flush cache before enable cache */
 135        addik   r5, r0, 0
 136        addik   r6, r0, XILINX_DCACHE_BYTE_SIZE
 137        bralid r15, flush_cache
 138        nop
 139
 140        /* enable instruction and data cache */
 141        mfs     r12, rmsr
 142        ori     r12, r12, 0x1a0
 143        mts     rmsr, r12
 144
 145        /* TODO: Redo this code to call board_init_f_*() */
 146clear_bss:
 147        /* clear BSS segments */
 148        addi    r5, r0, __bss_start
 149        addi    r4, r0, __bss_end
 150        cmp     r6, r5, r4
 151        beqi    r6, 3f
 1522:
 153        swi     r0, r5, 0 /* write zero to loc */
 154        addi    r5, r5, 4 /* increment to next loc */
 155        cmp     r6, r5, r4 /* check if we have reach the end */
 156        bnei    r6, 2b
 1573:      /* jumping to board_init */
 158#ifdef CONFIG_DEBUG_UART
 159        bralid  r15, debug_uart_init
 160        nop
 161#endif
 162#ifndef CONFIG_SPL_BUILD
 163        or      r5, r0, r0      /* flags - empty */
 164        addi    r31, r0, _gd
 165#if defined(CONFIG_SYS_MALLOC_F_LEN)
 166        addi    r6, r0, CONFIG_SYS_INIT_SP_OFFSET
 167        swi     r6, r31, GD_MALLOC_BASE
 168#endif
 169        brai    board_init_f
 170#else
 171        addi    r31, r0, _gd
 172#if defined(CONFIG_SYS_MALLOC_F_LEN)
 173        addi    r6, r0, CONFIG_SPL_STACK_ADDR
 174        swi     r6, r31, GD_MALLOC_BASE
 175#endif
 176        brai    board_init_r
 177#endif
 1781:      bri     1b
 179
 180 .section .bss
 181.align 4
 182_gd:
 183         .space  GENERATED_GBL_DATA_SIZE
 184
 185#ifndef CONFIG_SPL_BUILD
 186/*
 187 * Read 16bit little endian
 188 */
 189        .text
 190        .global in16
 191        .ent    in16
 192        .align  2
 193in16:   lhu     r3, r0, r5
 194        bslli   r4, r3, 8
 195        bsrli   r3, r3, 8
 196        andi    r4, r4, 0xffff
 197        or      r3, r3, r4
 198        rtsd    r15, 8
 199        sext16  r3, r3
 200        .end    in16
 201
 202/*
 203 * Write 16bit little endian
 204 * first parameter(r5) - address, second(r6) - short value
 205 */
 206        .text
 207        .global out16
 208        .ent    out16
 209        .align  2
 210out16:  bslli   r3, r6, 8
 211        bsrli   r6, r6, 8
 212        andi    r3, r3, 0xffff
 213        or      r3, r3, r6
 214        sh      r3, r0, r5
 215        rtsd    r15, 8
 216        or      r0, r0, r0
 217        .end    out16
 218
 219/*
 220 * Relocate u-boot
 221 */
 222        .text
 223        .global relocate_code
 224        .ent    relocate_code
 225        .align  2
 226relocate_code:
 227        /*
 228         * r5 - start_addr_sp
 229         * r6 - new_gd
 230         * r7 - reloc_addr
 231         */
 232        addi    r1, r5, 0 /* Start to use new SP */
 233        addi    r31, r6, 0 /* Start to use new GD */
 234
 235        add     r23, r0, r7 /* Move reloc addr to r23 */
 236        /* Relocate text and data - r12 temp value */
 237        addi    r21, r0, _start
 238        addi    r22, r0, __end - 4 /* Include BSS too */
 239
 240        rsub    r6, r21, r22
 241        or      r5, r0, r0
 2421:      lw      r12, r21, r5 /* Load u-boot data */
 243        sw      r12, r23, r5 /* Write zero to loc */
 244        cmp     r12, r5, r6 /* Check if we have reach the end */
 245        bneid   r12, 1b
 246        addi    r5, r5, 4 /* Increment to next loc - relocate code */
 247
 248       /* R23 points to the base address. */
 249        add     r23, r0, r7 /* Move reloc addr to r23 */
 250        addi    r24, r0, CONFIG_SYS_TEXT_BASE /* Get reloc offset */
 251        rsub    r23, r24, r23 /* keep - this is already here gd->reloc_off */
 252
 253        addik   r6, r0, 0x2 /* BIG/LITTLE endian offset */
 254        lwi     r7, r0, 0x28
 255        swi     r6, r0, 0x28 /* used first unused MB vector */
 256        lbui    r10, r0, 0x28 /* used first unused MB vector */
 257        swi     r7, r0, 0x28
 258
 259#ifdef CONFIG_SYS_USR_EXCEP
 260        addik   r6, r0, _exception_handler
 261        addk    r6, r6, r23 /* add offset */
 262        sw      r6, r1, r0
 263        lhu     r7, r1, r10
 264        rsubi   r8, r10, 0xa
 265        sh      r7, r0, r8
 266        rsubi   r8, r10, 0xe
 267        sh      r6, r0, r8
 268#endif
 269        addik   r6, r0, _hw_exception_handler
 270        addk    r6, r6, r23 /* add offset */
 271        sw      r6, r1, r0
 272        lhu     r7, r1, r10
 273        rsubi   r8, r10, 0x22
 274        sh      r7, r0, r8
 275        rsubi   r8, r10, 0x26
 276        sh      r6, r0, r8
 277
 278        addik   r6, r0, _interrupt_handler
 279        addk    r6, r6, r23 /* add offset */
 280        sw      r6, r1, r0
 281        lhu     r7, r1, r10
 282        rsubi   r8, r10, 0x12
 283        sh      r7, r0, r8
 284        rsubi   r8, r10, 0x16
 285        sh      r6, r0, r8
 286
 287        /* Check if GOT exist */
 288        addik   r21, r23, _got_start
 289        addik   r22, r23, _got_end
 290        cmpu    r12, r21, r22
 291        beqi    r12, 2f /* No GOT table - jump over */
 292
 293        /* Skip last 3 entries plus 1 because of loop boundary below */
 294        addik   r22, r22, -0x10
 295
 296        /* Relocate the GOT. */
 2973:      lw      r12, r21, r0 /* Load entry */
 298        addk    r12, r12, r23 /* Add reloc offset */
 299        sw      r12, r21, r0 /* Save entry back */
 300
 301        cmpu    r12, r21, r22 /* Check if this cross boundary */
 302        bneid   r12, 3b
 303        addik   r21. r21, 4
 304
 305        /* Update pointer to GOT */
 306        mfs     r20, rpc
 307        addik   r20, r20, _GLOBAL_OFFSET_TABLE_ + 8
 308        addk    r20, r20, r23
 309
 310        /* Flush caches to ensure consistency */
 311        addik   r5, r0, 0
 312        addik   r6, r0, XILINX_DCACHE_BYTE_SIZE
 313        bralid  r15, flush_cache
 314        nop
 315
 3162:      addi    r5, r31, 0 /* gd is initialized in board_r.c */
 317        addi    r6, r0, CONFIG_SYS_TEXT_BASE
 318        addi    r12, r23, board_init_r
 319        bra     r12 /* Jump to relocated code */
 320
 321        .end    relocate_code
 322#endif
 323