Marcin Bukat | 976a169 | 2011-05-30 21:10:37 +0000 | [diff] [blame] | 1 | #include <stdio.h> |
Marcin Bukat | 0263fe3 | 2012-02-28 15:51:36 +0100 | [diff] [blame] | 2 | #include <inttypes.h> |
| 3 | #include "config.h" |
Thomas Martitz | 22a28f9 | 2014-01-05 20:32:09 +0100 | [diff] [blame] | 4 | #include "system.h" |
Michael Sevakis | 4ea4cdf | 2014-08-08 02:28:11 -0400 | [diff] [blame] | 5 | #include "../kernel-internal.h" |
Marcin Bukat | 0263fe3 | 2012-02-28 15:51:36 +0100 | [diff] [blame] | 6 | #include "gcc_extensions.h" |
Marcin Bukat | 976a169 | 2011-05-30 21:10:37 +0000 | [diff] [blame] | 7 | #include "lcd.h" |
Marcin Bukat | 976a169 | 2011-05-30 21:10:37 +0000 | [diff] [blame] | 8 | #include "font.h" |
Marcin Bukat | 0263fe3 | 2012-02-28 15:51:36 +0100 | [diff] [blame] | 9 | #include "backlight.h" |
| 10 | #include "adc.h" |
| 11 | #include "button-target.h" |
| 12 | #include "button.h" |
Marcin Bukat | 976a169 | 2011-05-30 21:10:37 +0000 | [diff] [blame] | 13 | #include "common.h" |
Marcin Bukat | 0263fe3 | 2012-02-28 15:51:36 +0100 | [diff] [blame] | 14 | #include "storage.h" |
Michael Sevakis | 7d1a47c | 2013-08-05 22:02:45 -0400 | [diff] [blame] | 15 | #include "file_internal.h" |
Marcin Bukat | 0263fe3 | 2012-02-28 15:51:36 +0100 | [diff] [blame] | 16 | #include "disk.h" |
| 17 | #include "panic.h" |
| 18 | #include "power.h" |
| 19 | #include "string.h" |
| 20 | #include "file.h" |
| 21 | #include "crc32-rkw.h" |
Marcin Bukat | ecbda69 | 2012-03-04 00:06:20 +0100 | [diff] [blame] | 22 | #include "rkw-loader.h" |
Andrew Ryabinin | a3e3791 | 2012-04-30 17:54:06 +0400 | [diff] [blame] | 23 | #include "version.h" |
Andrew Ryabinin | cdb71c7 | 2013-04-30 15:18:27 +0400 | [diff] [blame] | 24 | #include "i2c-rk27xx.h" |
Marcin Bukat | 0b29691 | 2012-03-04 15:34:29 +0100 | [diff] [blame] | 25 | #include "loader_strerror.h" |
Marcin Bukat | 976a169 | 2011-05-30 21:10:37 +0000 | [diff] [blame] | 26 | |
Marcin Bukat | 79a667d | 2012-04-27 16:19:31 +0200 | [diff] [blame] | 27 | /* beginning of DRAM */ |
Marcin Bukat | 0263fe3 | 2012-02-28 15:51:36 +0100 | [diff] [blame] | 28 | #define DRAM_ORIG 0x60000000 |
Marcin Bukat | 79a667d | 2012-04-27 16:19:31 +0200 | [diff] [blame] | 29 | |
| 30 | /* bootloader code runs from 0x60700000 |
| 31 | * so we cannot load more code to not overwrite ourself |
| 32 | */ |
Marcin Bukat | 0263fe3 | 2012-02-28 15:51:36 +0100 | [diff] [blame] | 33 | #define LOAD_SIZE 0x700000 |
Marcin Bukat | dceceef | 2011-06-05 10:26:06 +0000 | [diff] [blame] | 34 | |
Bertrik Sikken | 7e3a3f4 | 2011-09-08 18:31:15 +0000 | [diff] [blame] | 35 | extern void show_logo( void ); |
Marcin Bukat | dceceef | 2011-06-05 10:26:06 +0000 | [diff] [blame] | 36 | |
Marcin Bukat | 79a667d | 2012-04-27 16:19:31 +0200 | [diff] [blame] | 37 | /* This function setup bare minimum |
| 38 | * and jumps to rom in order to activate |
| 39 | * hardcoded rkusb mode |
| 40 | */ |
| 41 | static void enter_rkusb(void) |
| 42 | { |
| 43 | asm volatile ( |
Marcin Bukat | b43171d | 2012-07-10 09:10:30 +0200 | [diff] [blame] | 44 | /* Turn off cache */ |
Marcin Bukat | 79a667d | 2012-04-27 16:19:31 +0200 | [diff] [blame] | 45 | "ldr r0, =0xefff0000 \n" |
| 46 | "ldrh r1, [r0] \n" |
| 47 | "strh r1, [r0] \n" |
| 48 | |
Marcin Bukat | b43171d | 2012-07-10 09:10:30 +0200 | [diff] [blame] | 49 | /* Turn off interrupts */ |
Marcin Bukat | 79a667d | 2012-04-27 16:19:31 +0200 | [diff] [blame] | 50 | "mrs r0, cpsr \n" |
| 51 | "bic r0, r0, #0x1f \n" |
| 52 | "orr r0, r0, #0xd3 \n" |
| 53 | "msr cpsr, r0 \n" |
| 54 | |
Marcin Bukat | b43171d | 2012-07-10 09:10:30 +0200 | [diff] [blame] | 55 | /* Disable iram remap */ |
Marcin Bukat | 79a667d | 2012-04-27 16:19:31 +0200 | [diff] [blame] | 56 | "mov r0, #0x18000000 \n" |
| 57 | "add r0, r0, #0x1c000 \n" |
| 58 | "mov r1, #0 \n" |
| 59 | "str r1, [r0, #4] \n" |
| 60 | |
Marcin Bukat | b43171d | 2012-07-10 09:10:30 +0200 | [diff] [blame] | 61 | /* Ungate all clocks */ |
| 62 | "str r1, [r0, #0x18] \n" |
| 63 | |
| 64 | /* Read SCU_ID to determine |
| 65 | * which version of bootrom we have |
| 66 | * 2706A has ID 0xa1000604 |
Marcin Bukat | 1ed57aa | 2013-11-23 22:43:19 +0100 | [diff] [blame] | 67 | * 2706B and 2705 have ID 0xa100027b |
Marcin Bukat | 79a667d | 2012-04-27 16:19:31 +0200 | [diff] [blame] | 68 | */ |
Marcin Bukat | b43171d | 2012-07-10 09:10:30 +0200 | [diff] [blame] | 69 | "ldr r1, [r0] \n" |
| 70 | "ldr r2, =0xa1000604 \n" |
| 71 | "cmp r1, r2 \n" |
| 72 | "bne rk27xx_new \n" |
| 73 | |
| 74 | /* Setup stacks in unmapped |
| 75 | * iram just as rom will do. |
| 76 | * |
| 77 | * We know about two versions |
| 78 | * of bootrom which are very similar |
| 79 | * but memory addresses are slightly |
| 80 | * different. |
| 81 | */ |
| 82 | "rk27xx_old: \n" |
| 83 | "ldr r1, =0x18200258 \n" |
| 84 | "ldr r0, =0xaf0 \n" |
| 85 | "b jump_to_rom \n" |
| 86 | |
| 87 | "rk27xx_new: \n" |
Marcin Bukat | 79a667d | 2012-04-27 16:19:31 +0200 | [diff] [blame] | 88 | "ldr r1, =0x18200274 \n" |
Marcin Bukat | b43171d | 2012-07-10 09:10:30 +0200 | [diff] [blame] | 89 | "ldr r0, =0xec0 \n" |
| 90 | |
| 91 | "jump_to_rom: \n" |
| 92 | "msr cpsr, #0xd2 \n" |
Marcin Bukat | 79a667d | 2012-04-27 16:19:31 +0200 | [diff] [blame] | 93 | "add r1, r1, #0x200 \n" |
| 94 | "mov sp, r1 \n" |
| 95 | "msr cpsr, #0xd3 \n" |
| 96 | "add r1, r1, #0x400 \n" |
| 97 | "mov sp, r1 \n" |
| 98 | |
Marcin Bukat | b43171d | 2012-07-10 09:10:30 +0200 | [diff] [blame] | 99 | /* Finaly jump to rkusb handler |
| 100 | * in bootrom. |
Marcin Bukat | 79a667d | 2012-04-27 16:19:31 +0200 | [diff] [blame] | 101 | */ |
Marcin Bukat | 79a667d | 2012-04-27 16:19:31 +0200 | [diff] [blame] | 102 | "bx r0 \n" |
| 103 | ); |
| 104 | } |
| 105 | |
Marcin Bukat | b43171d | 2012-07-10 09:10:30 +0200 | [diff] [blame] | 106 | |
Marcin Bukat | 0263fe3 | 2012-02-28 15:51:36 +0100 | [diff] [blame] | 107 | void main(void) NORETURN_ATTR; |
Marcin Bukat | 976a169 | 2011-05-30 21:10:37 +0000 | [diff] [blame] | 108 | void main(void) |
| 109 | { |
Marcin Bukat | 0263fe3 | 2012-02-28 15:51:36 +0100 | [diff] [blame] | 110 | char filename[MAX_PATH]; |
| 111 | unsigned char* loadbuffer; |
| 112 | void(*kernel_entry)(void); |
| 113 | int ret; |
| 114 | enum {rb, of} boot = rb; |
Marcin Bukat | 976a169 | 2011-05-30 21:10:37 +0000 | [diff] [blame] | 115 | |
Marcin Bukat | 0263fe3 | 2012-02-28 15:51:36 +0100 | [diff] [blame] | 116 | power_init(); |
Marcin Bukat | 976a169 | 2011-05-30 21:10:37 +0000 | [diff] [blame] | 117 | system_init(); |
| 118 | kernel_init(); |
Andrew Ryabinin | 61f9dbc | 2013-04-29 11:04:20 +0400 | [diff] [blame] | 119 | i2c_init(); |
Marcin Bukat | 976a169 | 2011-05-30 21:10:37 +0000 | [diff] [blame] | 120 | enable_irq(); |
| 121 | |
Marcin Bukat | 0263fe3 | 2012-02-28 15:51:36 +0100 | [diff] [blame] | 122 | adc_init(); |
| 123 | lcd_init(); |
| 124 | backlight_init(); |
| 125 | button_init_device(); |
| 126 | |
Marcin Bukat | 976a169 | 2011-05-30 21:10:37 +0000 | [diff] [blame] | 127 | font_init(); |
| 128 | lcd_setfont(FONT_SYSFIXED); |
| 129 | |
| 130 | show_logo(); |
Marcin Bukat | 976a169 | 2011-05-30 21:10:37 +0000 | [diff] [blame] | 131 | |
Marcin Bukat | 0263fe3 | 2012-02-28 15:51:36 +0100 | [diff] [blame] | 132 | int btn = button_read_device(); |
Marcin Bukat | dceceef | 2011-06-05 10:26:06 +0000 | [diff] [blame] | 133 | |
Marcin Bukat | 0263fe3 | 2012-02-28 15:51:36 +0100 | [diff] [blame] | 134 | /* if there is some other button pressed |
| 135 | * besides POWER/PLAY we boot into OF |
| 136 | */ |
| 137 | if ((btn & ~POWEROFF_BUTTON)) |
| 138 | boot = of; |
Marcin Bukat | dceceef | 2011-06-05 10:26:06 +0000 | [diff] [blame] | 139 | |
Marcin Bukat | 0263fe3 | 2012-02-28 15:51:36 +0100 | [diff] [blame] | 140 | /* if we are woken up by USB insert boot into OF */ |
| 141 | if (DEV_INFO & (1<<20)) |
| 142 | boot = of; |
Marcin Bukat | dceceef | 2011-06-05 10:26:06 +0000 | [diff] [blame] | 143 | |
Marcin Bukat | 0263fe3 | 2012-02-28 15:51:36 +0100 | [diff] [blame] | 144 | lcd_clear_display(); |
Marcin Bukat | dceceef | 2011-06-05 10:26:06 +0000 | [diff] [blame] | 145 | |
Marcin Bukat | 0263fe3 | 2012-02-28 15:51:36 +0100 | [diff] [blame] | 146 | ret = storage_init(); |
| 147 | if(ret < 0) |
| 148 | error(EATA, ret, true); |
Marcin Bukat | dceceef | 2011-06-05 10:26:06 +0000 | [diff] [blame] | 149 | |
Michael Sevakis | 7d1a47c | 2013-08-05 22:02:45 -0400 | [diff] [blame] | 150 | filesystem_init(); |
Marcin Bukat | dceceef | 2011-06-05 10:26:06 +0000 | [diff] [blame] | 151 | |
Marcin Bukat | 0263fe3 | 2012-02-28 15:51:36 +0100 | [diff] [blame] | 152 | while((ret = disk_mount_all()) <= 0) |
| 153 | error(EDISK, ret, true); |
Marcin Bukat | dceceef | 2011-06-05 10:26:06 +0000 | [diff] [blame] | 154 | |
Marcin Bukat | 0263fe3 | 2012-02-28 15:51:36 +0100 | [diff] [blame] | 155 | loadbuffer = (unsigned char*)DRAM_ORIG; /* DRAM */ |
| 156 | |
| 157 | if (boot == rb) |
| 158 | snprintf(filename,sizeof(filename), BOOTDIR "/%s", BOOTFILE); |
| 159 | else if (boot == of) |
| 160 | snprintf(filename,sizeof(filename), BOOTDIR "/%s", "BASE.RKW"); |
Marcin Bukat | dceceef | 2011-06-05 10:26:06 +0000 | [diff] [blame] | 161 | |
Michael Sevakis | 95a4c3a | 2014-08-28 10:26:45 -0400 | [diff] [blame] | 162 | printf("Bootloader version: %s", rbversion); |
Marcin Bukat | 0263fe3 | 2012-02-28 15:51:36 +0100 | [diff] [blame] | 163 | printf("Loading: %s", filename); |
Marcin Bukat | dceceef | 2011-06-05 10:26:06 +0000 | [diff] [blame] | 164 | |
Marcin Bukat | 0263fe3 | 2012-02-28 15:51:36 +0100 | [diff] [blame] | 165 | ret = load_rkw(loadbuffer, filename, LOAD_SIZE); |
Marcin Bukat | 0b29691 | 2012-03-04 15:34:29 +0100 | [diff] [blame] | 166 | |
| 167 | if (ret <= EFILE_EMPTY) |
Marcin Bukat | 976a169 | 2011-05-30 21:10:37 +0000 | [diff] [blame] | 168 | { |
Marcin Bukat | 0b29691 | 2012-03-04 15:34:29 +0100 | [diff] [blame] | 169 | error(EBOOTFILE, ret, false); |
Marcin Bukat | 79a667d | 2012-04-27 16:19:31 +0200 | [diff] [blame] | 170 | |
| 171 | /* if we boot rockbox we shutdown on error |
| 172 | * if we boot OF we fall back to rkusb mode on error |
| 173 | */ |
| 174 | if (boot == rb) |
| 175 | { |
| 176 | power_off(); |
| 177 | } |
| 178 | else |
| 179 | { |
| 180 | /* give visual feedback what we are doing */ |
| 181 | printf("Entering rockchip USB mode..."); |
| 182 | lcd_update(); |
| 183 | |
| 184 | enter_rkusb(); |
| 185 | } |
Marcin Bukat | 976a169 | 2011-05-30 21:10:37 +0000 | [diff] [blame] | 186 | } |
Marcin Bukat | 0263fe3 | 2012-02-28 15:51:36 +0100 | [diff] [blame] | 187 | else |
| 188 | { |
Marcin Bukat | 79a667d | 2012-04-27 16:19:31 +0200 | [diff] [blame] | 189 | /* print 'Loading OK' */ |
Marcin Bukat | 0b29691 | 2012-03-04 15:34:29 +0100 | [diff] [blame] | 190 | printf("Loading OK"); |
Marcin Bukat | 0263fe3 | 2012-02-28 15:51:36 +0100 | [diff] [blame] | 191 | sleep(HZ); |
| 192 | } |
| 193 | |
Marcin Bukat | 79a667d | 2012-04-27 16:19:31 +0200 | [diff] [blame] | 194 | /* jump to entrypoint */ |
Marcin Bukat | 0263fe3 | 2012-02-28 15:51:36 +0100 | [diff] [blame] | 195 | kernel_entry = (void*) loadbuffer; |
| 196 | commit_discard_idcache(); |
| 197 | |
| 198 | printf("Executing"); |
| 199 | kernel_entry(); |
| 200 | |
Marcin Bukat | 79a667d | 2012-04-27 16:19:31 +0200 | [diff] [blame] | 201 | /* this should never be reached actually */ |
Marcin Bukat | 0263fe3 | 2012-02-28 15:51:36 +0100 | [diff] [blame] | 202 | printf("ERR: Failed to boot"); |
| 203 | sleep(5*HZ); |
Marcin Bukat | 79a667d | 2012-04-27 16:19:31 +0200 | [diff] [blame] | 204 | |
| 205 | if (boot == rb) |
| 206 | { |
| 207 | power_off(); |
| 208 | } |
| 209 | else |
| 210 | { |
| 211 | /* give visual feedback what we are doing */ |
| 212 | printf("Entering rockchip USB mode..."); |
| 213 | lcd_update(); |
| 214 | |
| 215 | enter_rkusb(); |
| 216 | } |
Marcin Bukat | 0263fe3 | 2012-02-28 15:51:36 +0100 | [diff] [blame] | 217 | |
| 218 | /* hang */ |
| 219 | while(1); |
Marcin Bukat | 976a169 | 2011-05-30 21:10:37 +0000 | [diff] [blame] | 220 | } |