mb/system76/cml-u/dt: Make use of chipset devicetree
[coreboot.git] / src / soc / cavium / cn81xx / bootblock_custom.S
blobb98f3cda6ac265c391617b4029723f73be4e7c7a
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /* Early initialization code for aarch64 (a.k.a. armv8) */
4 #include <arch/asm.h>
5 #include <soc/addressmap.h>
7         .arch           armv8-a+fp
10 ENTRY(_start)
12     .org 0
13      /**
14      * According to the reference manual the first instruction is fetched from
15      * offset 0x100, but at offset 0 a branch instruction is always placed.
16      * Support two entry points for now.
17      * To save memory put the cavium specific init code between those to entry
18      * points.
19      */
20     ic      ialluis
21     fmov    d30, x0     /* Save X0 in FPR for use later */
22      /**
23       * The BDK stores X1 for later use, but it turns out that we don't need
24       * this "feature". The idea is to hide the devicetree somewhere in
25       * flash, that only the ROM will find it and point to it using X1.
26       */
27     adr     x1, _start  /* x1 = _start location based on PC */
28     fmov    d29, x1     /* Save PC in FPR for use later */
30 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
31     /* Change the core to big endian mode for EL3 */
32     mrs     x0, SCTLR_EL3
33     mov     x1, 1<<25       /* Set SCTLR_EL3[ee]=1 */
34     orr     x0, x0, x1
35     msr     SCTLR_EL3, x0
36     #define ENDIAN_CONVERT64(reg) rev reg, reg
37     #define ENDIAN_CONVERT32(reg) rev reg, reg
38     #define ENDIAN_CONVERT16(reg) rev16 reg, reg
39 #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
40     /* Nothing needed, default is little endian */
41     #define ENDIAN_CONVERT64(reg)
42     #define ENDIAN_CONVERT32(reg)
43     #define ENDIAN_CONVERT16(reg)
44 #else
45     #error Unknown endianness
46 #endif
48     mov     x0, (LMC0_PF_BAR0 >> 32)
49     lsl     x0, x0, 32
50     mov     x1, (LMC0_PF_BAR0 & 0xffffffff)
51     orr     x0, x0, x1
53     /* Test if DRAM PLL is running */
54     ldr     x1, [x0, LMC0_DDR_PLL_CTL0]
56     tst     x1, 0x80
58     b.ne     cache_setup_done
60     bl      _setup_car
62 cache_setup_done:
64     /* Check that we're running on the node we're linked for */
65     mrs     x0, MPIDR_EL1
66     ubfx    x0, x0, 16, 8       /* Bits 23:16 are the physical node ID */
67     mov     x1, 0x0
68     cmp     x0, x1
70     b.ne    _wfi
72 node_check_done:
73     /* Get code position */
74     mov     x1, 0x020000
75     mov     x0, BOOTROM_OFFSET
76     add     x1, x0, x1
78     adr     x0, _start
80     /**
81      * Check if IROM has loaded the code to BOOTROM_OFFSET.
82      * In case the offset is wrong, try to relocate.
83      * Ideally the following code is never executed.
84      * FIXME: Add region overlap check.
85      */
86     cmp x0, x1
87     b.eq    after_relocate
89 relocate:
90     /* Get bootblock length */
91     ldr     x2, =_program
92     ldr     x3, =_eprogram
93     sub     x2, x2, x3
94     b       copy_code
96 .align 7
97 copy_code:
98     ldp     q0, q1, [x1], 32    /* Load 32 bytes */
99     subs    w2, w2, 32          /* Subtract 32 from length, setting flags */
100     stp     q0, q1, [x0], 32    /* Store 32 bytes */
101     b.gt    copy_code           /* Repeat if length is still positive */
102     dmb     sy
104     /* Load the actual location we're suppose to be at */
105     adr     x0, after_relocate  /* Relative address */
106     adr     x1, _start          /* Relative address */
107     sub     x0, x0, x1     /* This only works if _start is suppose to be zero */
108     mov     x1, BOOTROM_OFFSET
109     add     x0, x0, x1
110     br      x0             /* Branch to relocated code */
112     ic      ialluis        /* Clear the icache now that all code is correct */
114 after_relocate:
115     /* Allow unaligned memory access as long as MMU is disabled */
116     mrs     x22, s3_0_c11_c0_4
117     orr     x22, x22, # (1 << 37) /* Set DCVA47 */
118     msr     s3_0_c11_c0_4, x22
120     bl      start
122     /* Real entry point */
123     .org 0x100
124     b      _start
125 ENDPROC(_start)
128 ENTRY(_setup_car)
129     mrs     x0, MIDR_EL1
130     ubfx    x0, x0, 4, 12       /* Bits 15:4 are the part number */
131     cmp     x0, 0xb0
132     b.ge    _wfi
134 thunder1_cache_setup:
135    /**
136     * Setup L2 cache to allow secure access to all of the address space
137     * thunder1 compatibility list:
138     * - CN81XX
139     * - CN83XX
140     * - CN88XX
141     */
142     #define REGIONX_START   0x1000
143     #define REGIONX_END     0x1008
144     #define REGIONX_ATTR    0x1010
145     mov     x0, L2C_PF_BAR0 >> 32
146     lsl     x0, x0, 32
147     mov     x1, (L2C_PF_BAR0 & 0xffffffff)
148     orr     x0, x0, x1
149     str     xzr, [x0, REGIONX_START]    /* Start of zero */
150     mov     x1, 0x3fffff00000           /* End of max address */
151     ENDIAN_CONVERT64(x1)
152     str     x1, [x0, REGIONX_END]
153     mov     x1, 2                       /* Secure only access */
154     ENDIAN_CONVERT64(x1)
155     str     x1, [x0, REGIONX_ATTR]
156     /* Update way partition to allow core 0 to write to L2 */
157     #define L2C_WPAR_PP0_OFFSET 0x40000
158     mov     x1, L2C_WPAR_PP0_OFFSET
159     str     xzr, [x0, x1]
160     ldr     xzr, [x0, x1]       /* Read back to make sure done */
161     #undef REGIONX_START
162     #undef REGIONX_END
163     #undef REGIONX_ATTR
164     #undef L2C_WPAR_PP0_OFFSET
166     /**
167      * At this point the whole CAR is readable and writeable, but if
168      * we touch to many cache-lines our code might get flushed out.
169      * We have to lock all cache-lines that are to be used as RAM, which are
170      * the ones marked as SRAM in memlayout.
171      */
172     mrs     x0, CTR_EL0            /* Get cache-line size */
173     /* [19:16] - Indicates (Log2(number of words in cache line) */
174     ubfx    x0, x0, 16, 4
175     mov     x1, 4                  /* Bytes in a word (32-bit) */
176     lsl     x0, x1, x0             /* Number of Bytes in x0 */
178     sub     x1, x0, 1
179     mvn     x1, x1                 /* Place mask in x1 */
181     ldr     x3, =_sram
182     and     x3, x3, x1             /* Align addresses with cache-lines */
183     ldr     x4, =_esram
184     add     x4, x4, x0
185     sub     x4, x4, 1
186     and     x4, x4, x1             /* Align addresses with cache-lines */
187     sub     x2, x4, x3             /* Store sram length in x2 */
189 lock_cache_lines:
190     sys     #0, c11, c1, #4, x3
191     add     x3, x3, x0             /* Increment address by cache-line bytes */
192     subs    w2, w2, w0             /* Subtract cache-line bytes from length */
193     b.gt    lock_cache_lines       /* Repeat if length is still positive */
195     /**
196      * The locked region isn't considered dirty by L2. Do read/write of
197      * each cache line to force each to be dirty. This is needed across the
198      * whole line to make sure the L2 dirty bits are all up to date.
199      * NOTE: If we'd relocate we could memset the whole memory !
200      */
201     ldr     x3, =_sram
202     and     x3, x3, x1             /* Align addresses with cache-lines */
203     ldr     x4, =_esram
204     add     x4, x4, x0
205     sub     x4, x4, 1
206     and     x4, x4, x1             /* Align addresses with cache-lines */
207     sub     x2, x4, x3             /* Store sram length in x2 */
208     mov     x4, x3
209     b       dirty_cache_line
211 .align 7
212 dirty_cache_line:
213     ldp     q0, q1, [x3], 32    /* Load 32 bytes */
214     subs    w2, w2, 32          /* Subtract 32 from length, setting flags */
215     stp     q0, q1, [x4], 32    /* Store 32 bytes */
216     b.gt    dirty_cache_line    /* Repeat if length is still positive */
217     dmb     sy
219 clear_interrupts:
220     /**
221      * As the memory controller isn't running, but we access the DRAM's
222      * address space, some interrupt flags had been set.
223      * Tidy up our mess now on (valid for CN81XX only).
224      */
225     mov     x0, (L2C_TAD0_INT_W1C >> 32)
226     lsl     x0, x0, 32
227     mov     x1, (L2C_TAD0_INT_W1C & 0xffffffff)
228     orr     x0, x0, x1
230     ldr x1, [x0]
231     orr x1, x1, 0x1c00 /* Clear WRDISLMC, RDDISLMC, RDNXM */
232     str x1, [x0]
234     ret
235 ENDPROC(_setup_car)
237 ENTRY(_wfi)
238     wfi
239 ENDPROC(_wfi)
241 ENTRY(start)
242     bl      arm64_init_cpu
244     fmov    x0, d30 /* The original X0, info from previous image */
245     fmov    x1, d29 /* The original PC we were loaded at */
247     /* Call C entry */
248     bl      bootblock_main
250 ENDPROC(start)