|
18 | 18 | * along with this program; if not, write to the Free Software
|
19 | 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
20 | 20 | */
|
21 |
| - |
| 21 | +#include <stddef.h> |
22 | 22 | #include <stdint.h>
|
23 | 23 | #include <string.h>
|
24 | 24 | #include <target.h>
|
25 | 25 | #include "image.h"
|
| 26 | +#include "printf.h" |
26 | 27 | #ifndef ARCH_AARCH64
|
27 | 28 | # error "wolfBoot raspi3 HAL: wrong architecture selected. Please compile with ARCH=AARCH64."
|
28 | 29 | #endif
|
29 | 30 |
|
30 | 31 | #define TEST_ENCRYPT
|
31 | 32 |
|
| 33 | +#if defined(DEBUG_UART) |
| 34 | + #define PRINTF_ENABLED |
| 35 | +#endif |
| 36 | + |
32 | 37 |
|
33 | 38 | #define CORTEXA53_0_CPU_CLK_FREQ_HZ 1099989014
|
34 | 39 | #define CORTEXA53_0_TIMESTAMP_CLK_FREQ 99998999
|
35 | 40 |
|
| 41 | +#define MMIO_BASE 0x3F000000 |
| 42 | + |
| 43 | +#define GPIO_BASE MMIO_BASE + 0x200000 |
| 44 | + |
| 45 | +#define GPFSEL1 ((volatile unsigned int*)(GPIO_BASE+0x04)) |
| 46 | +#define GPPUD ((volatile unsigned int*)(GPIO_BASE+0x94)) |
| 47 | +#define GPPUDCLK0 ((volatile unsigned int*)(GPIO_BASE+0x98)) |
| 48 | + |
| 49 | +/* PL011 UART registers */ |
| 50 | +#define UART0_BASE GPIO_BASE + 0x1000 |
| 51 | +#define UART0_DR ((volatile unsigned int*)(UART0_BASE+0x00)) |
| 52 | +#define UART0_FR ((volatile unsigned int*)(UART0_BASE+0x18)) |
| 53 | +#define UART0_IBRD ((volatile unsigned int*)(UART0_BASE+0x24)) |
| 54 | +#define UART0_FBRD ((volatile unsigned int*)(UART0_BASE+0x28)) |
| 55 | +#define UART0_LCRH ((volatile unsigned int*)(UART0_BASE+0x2C)) |
| 56 | +#define UART0_CR ((volatile unsigned int*)(UART0_BASE+0x30)) |
| 57 | +#define UART0_IMSC ((volatile unsigned int*)(UART0_BASE+0x38)) |
| 58 | +#define UART0_ICR ((volatile unsigned int*)(UART0_BASE+0x44)) |
| 59 | + |
| 60 | +/* mail box message buffer */ |
| 61 | +volatile unsigned int __attribute__((aligned(16))) mbox[36]; |
| 62 | + |
| 63 | +#define VIDEOCORE_MBOX (MMIO_BASE+0x0000B880) |
| 64 | +#define MBOX_READ ((volatile unsigned int*)(VIDEOCORE_MBOX+0x0)) |
| 65 | +#define MBOX_POLL ((volatile unsigned int*)(VIDEOCORE_MBOX+0x10)) |
| 66 | +#define MBOX_SENDER ((volatile unsigned int*)(VIDEOCORE_MBOX+0x14)) |
| 67 | +#define MBOX_STATUS ((volatile unsigned int*)(VIDEOCORE_MBOX+0x18)) |
| 68 | +#define MBOX_CONFIG ((volatile unsigned int*)(VIDEOCORE_MBOX+0x1C)) |
| 69 | +#define MBOX_WRITE ((volatile unsigned int*)(VIDEOCORE_MBOX+0x20)) |
| 70 | +#define MBOX_RESPONSE 0x80000000 |
| 71 | +#define MBOX_FULL 0x80000000 |
| 72 | +#define MBOX_EMPTY 0x40000000 |
| 73 | + |
| 74 | +#define MBOX_REQUEST 0 |
| 75 | + |
| 76 | +/* channels */ |
| 77 | +#define MBOX_CH_POWER 0 |
| 78 | +#define MBOX_CH_FB 1 |
| 79 | +#define MBOX_CH_VUART 2 |
| 80 | +#define MBOX_CH_VCHIQ 3 |
| 81 | +#define MBOX_CH_LEDS 4 |
| 82 | +#define MBOX_CH_BTNS 5 |
| 83 | +#define MBOX_CH_TOUCH 6 |
| 84 | +#define MBOX_CH_COUNT 7 |
| 85 | +#define MBOX_CH_PROP 8 |
| 86 | + |
| 87 | +/* tags */ |
| 88 | +#define MBOX_TAG_GETBRDVERSION 0x10002 |
| 89 | +#define MBOX_TAG_GETSERIAL 0x10004 |
| 90 | +#define MBOX_TAG_GET_CLOCK_RATE 0x30002 |
| 91 | +#define MBOX_TAG_SETCLKRATE 0x38002 |
| 92 | +#define MBOX_TAG_LAST 0 |
| 93 | + |
36 | 94 | /* Fixed addresses */
|
37 | 95 | extern void *kernel_addr, *update_addr, *dts_addr;
|
| 96 | +/* Loop <delay> times */ |
| 97 | +static inline void delay(int32_t count) |
| 98 | +{ |
| 99 | + register unsigned int c; |
| 100 | + c = count; |
| 101 | + while (c--) { |
| 102 | + asm volatile("nop"); |
| 103 | + } |
| 104 | +} |
| 105 | +/** |
| 106 | + * write message to mailbox |
| 107 | + */ |
| 108 | +static void mailbox_write(uint8_t chan) |
| 109 | +{ |
| 110 | + uint32_t ch = (((uint32_t)((unsigned long)&mbox) & ~0xf) |
| 111 | + | (chan & 0xf)); |
| 112 | + |
| 113 | + /* wait until mail box becomes ready to write */ |
| 114 | + while ((*MBOX_STATUS & MBOX_FULL) != 0) { } |
| 115 | + |
| 116 | + /* write the address of the message to mail-box channel */ |
| 117 | + *MBOX_WRITE = ch; |
| 118 | +} |
| 119 | +/** |
| 120 | + * read message from mailbox |
| 121 | + */ |
| 122 | +static int mailbox_read(uint8_t chan) |
| 123 | +{ |
| 124 | + uint32_t ch = (((uint32_t)((unsigned long)&mbox) & ~0xf) |
| 125 | + | (chan & 0xf)); |
| 126 | + /* now wait for the response */ |
| 127 | + while(1) { |
| 128 | + while ((*MBOX_STATUS & MBOX_EMPTY) != 0) { } |
| 129 | + if(ch == *MBOX_READ) |
| 130 | + /* is it a valid successful response */ |
| 131 | + return mbox[1] == MBOX_RESPONSE; |
| 132 | + } |
| 133 | + return 0; |
| 134 | +} |
| 135 | + |
| 136 | +/* UART functions for Raspberry Pi 3 UART */ |
| 137 | +void uart_tx(char c) |
| 138 | +{ |
| 139 | + /* wait until uart channel is ready to send */ |
| 140 | + do{ |
| 141 | + asm volatile("nop"); |
| 142 | + } while(*UART0_FR & 0x20); |
| 143 | + *UART0_DR = c; |
| 144 | +} |
| 145 | + |
| 146 | +char uart_read(void) |
| 147 | +{ |
| 148 | + char c; |
| 149 | + /* wait until data is comming */ |
| 150 | + do{ |
| 151 | + asm volatile("nop"); |
| 152 | + } while(*UART0_FR & 0x10); |
| 153 | + /* read it and return */ |
| 154 | + c = (char)(*UART0_DR); |
| 155 | + /* convert carrige return to newline */ |
| 156 | + if (c == '\r') |
| 157 | + c = '\n'; |
| 158 | + |
| 159 | + return c; |
| 160 | +} |
| 161 | + |
| 162 | +/** |
| 163 | + * Send string to UART |
| 164 | + */ |
| 165 | +void uart_write(const char* buf, uint32_t sz) { |
| 166 | + uint32_t len = sz; |
| 167 | + |
| 168 | + while (len > 0 && *buf) { |
| 169 | + /* convert newline to carrige return + newline */ |
| 170 | + if (*buf == '\n') |
| 171 | + uart_tx('\r'); |
| 172 | + |
| 173 | + uart_tx(*buf++); |
| 174 | + len--; |
| 175 | + } |
| 176 | +} |
| 177 | + |
| 178 | +void uart_init() |
| 179 | +{ |
| 180 | + register unsigned int c; |
| 181 | + |
| 182 | + /* initialize UART. turn off UART 0*/ |
| 183 | + *UART0_CR = 0; |
| 184 | + |
| 185 | + /* set up clock for consistent divisor values */ |
| 186 | + mbox[0] = 9 * 4; |
| 187 | + mbox[1] = MBOX_REQUEST; |
| 188 | + /* tag for setting clock rate */ |
| 189 | + mbox[2] = MBOX_TAG_SETCLKRATE; |
| 190 | + mbox[3] = 12; |
| 191 | + mbox[4] = 8; |
| 192 | + /* specify UART clock channel */ |
| 193 | + mbox[5] = 2; |
| 194 | + /* UART clock rate in hz(4Mhz)*/ |
| 195 | + mbox[6] = 4000000; |
| 196 | + /* not use turbo */ |
| 197 | + mbox[7] = 0; |
| 198 | + mbox[8] = MBOX_TAG_LAST; |
| 199 | + |
| 200 | + mailbox_write(MBOX_CH_PROP); |
| 201 | + mailbox_read(MBOX_CH_PROP); |
| 202 | + |
| 203 | + /* disable pull up/down for all GPIO pins */ |
| 204 | + *GPPUD = 0; |
| 205 | + delay(150); |
| 206 | + /* Disable pull up/down for pin 14 and 15 */ |
| 207 | + *GPPUDCLK0 = (1<<14)|(1<<15); |
| 208 | + delay(150); |
| 209 | + /* flush GPIO setting to make it take effect */ |
| 210 | + *GPPUDCLK0 = 0; |
| 211 | + |
| 212 | + /* clear pending interrupts */ |
| 213 | + *UART0_ICR = 0x7FF; |
| 214 | + /* select 115200 baud rate */ |
| 215 | + /* divider = 4000000 / (16 * 115200) = 2.17 = ~2 */ |
| 216 | + *UART0_IBRD = 2; |
| 217 | + /* Fractional part register = (.17013 * 64) + 0.5 = 11.38 = ~11 */ |
| 218 | + *UART0_FBRD = 0xB; |
| 219 | + /* Enable fifo, 8bit data transmission ( 1stop bit, no parity) */ |
| 220 | + *UART0_LCRH = (1 << 4) | (1 << 5) | (1 << 6); |
| 221 | + /* enable UART0 transfer & receive*/ |
| 222 | + *UART0_CR = (1 << 0) | (1 << 8) | (1 << 9); |
| 223 | +} |
38 | 224 |
|
39 | 225 | void* hal_get_primary_address(void)
|
40 | 226 | {
|
@@ -91,22 +277,88 @@ void qspi_init(uint32_t cpu_clock, uint32_t flash_freq)
|
91 | 277 | {
|
92 | 278 | }
|
93 | 279 |
|
94 |
| - |
95 | 280 | void zynq_init(uint32_t cpu_clock)
|
96 | 281 | {
|
97 | 282 | }
|
98 | 283 |
|
| 284 | +#if defined(DISPLAY_CLOCKS) |
| 285 | +static uint32_t getclocks(uint8_t cid) |
| 286 | +{ |
| 287 | + /* Retrive clock rate */ |
| 288 | + /* length of the message */ |
| 289 | + mbox[0] = 8 * 4; |
| 290 | + mbox[1] = MBOX_REQUEST; |
| 291 | + /* tag for get board version */ |
| 292 | + mbox[2] = MBOX_TAG_GET_CLOCK_RATE; |
| 293 | + /* buffer size */ |
| 294 | + mbox[3] = 8; |
| 295 | + mbox[4] = 8; |
| 296 | + /* clock id CORE*/ |
| 297 | + mbox[5] = cid; |
| 298 | + /* clock frequency */ |
| 299 | + mbox[6] = 0; |
| 300 | + mbox[7] = MBOX_TAG_LAST; |
| 301 | + mailbox_write(MBOX_CH_PROP); |
99 | 302 |
|
| 303 | + if (mailbox_read(MBOX_CH_PROP)) { |
| 304 | + return mbox[6]; |
| 305 | + } |
| 306 | + else { |
| 307 | + return 0; |
| 308 | + } |
| 309 | +} |
| 310 | +#endif /* DISPLAY clocks */ |
100 | 311 |
|
101 | 312 | /* public HAL functions */
|
102 | 313 | void hal_init(void)
|
103 | 314 | {
|
104 | 315 | #if defined(TEST_ENCRYPT) && defined (EXT_ENCRYPTED)
|
105 | 316 | char enc_key[] = "0123456789abcdef0123456789abcdef"
|
106 |
| - "0123456789abcdef"; |
| 317 | + "0123456789abcdef"; |
107 | 318 | wolfBoot_set_encrypt_key((uint8_t *)enc_key,(uint8_t *)(enc_key + 32));
|
108 | 319 | #endif
|
109 | 320 |
|
| 321 | + uart_init(); |
| 322 | + |
| 323 | + /* length of the message */ |
| 324 | + mbox[0] = 7 * 4; |
| 325 | + mbox[1] = MBOX_REQUEST; |
| 326 | + /* tag for get board version */ |
| 327 | + mbox[2] = MBOX_TAG_GETBRDVERSION; |
| 328 | + /* buffer size */ |
| 329 | + mbox[3] = 4; |
| 330 | + mbox[4] = 0; |
| 331 | + mbox[5] = 0; |
| 332 | + mbox[6] = MBOX_TAG_LAST; |
| 333 | + |
| 334 | + /* send the message to the GPU */ |
| 335 | + mailbox_write(MBOX_CH_PROP); |
| 336 | + |
| 337 | + if (mailbox_read(MBOX_CH_PROP)) { |
| 338 | + wolfBoot_printf("My board version is: 0x%08x", mbox[5]); |
| 339 | + wolfBoot_printf("\n"); |
| 340 | + } else { |
| 341 | + wolfBoot_printf("Unable to query board version!\n"); |
| 342 | + } |
| 343 | + |
| 344 | +#if defined(DISPLAY_CLOCKS) && defined(PRINTF_ENABLED) |
| 345 | + /* Get clocks */ |
| 346 | + wolfBoot_printf("\n EMMC clock : %d Hz", getclocks(1)); |
| 347 | + wolfBoot_printf("\n UART clock : %d Hz", getclocks(2)); |
| 348 | + wolfBoot_printf("\n ARM clock : %d Hz", getclocks(3)); |
| 349 | + wolfBoot_printf("\n CORE clock : %d Hz", getclocks(4)); |
| 350 | + wolfBoot_printf("\n V3D clock : %d Hz", getclocks(5)); |
| 351 | + wolfBoot_printf("\n H264 clock : %d Hz", getclocks(6)); |
| 352 | + wolfBoot_printf("\n ISP clock : %d Hz", getclocks(7)); |
| 353 | + wolfBoot_printf("\n SDRAM clock : %d Hz", getclocks(8)); |
| 354 | + wolfBoot_printf("\n PIXEL clock : %d Hz", getclocks(9)); |
| 355 | + wolfBoot_printf("\n PWM clock : %d Hz", getclocks(10)); |
| 356 | + wolfBoot_printf("\n HEVC clock : %d Hz", getclocks(11)); |
| 357 | + wolfBoot_printf("\n EMMC2 clock : %d Hz", getclocks(12)); |
| 358 | + wolfBoot_printf("\n M2MC clock : %d Hz", getclocks(13)); |
| 359 | + wolfBoot_printf("\n PIXEL_BVB clock : %d Hz\n", getclocks(14)); |
| 360 | +#endif |
| 361 | + |
110 | 362 | }
|
111 | 363 |
|
112 | 364 | void hal_prepare_boot(void)
|
|
0 commit comments