blob: 57e5868a876ac812ee91c4b63236f4669fcdb1b5 [file] [log] [blame]
Marcin Bukat976a1692011-05-30 21:10:37 +00001#include <stdio.h>
Marcin Bukat0263fe32012-02-28 15:51:36 +01002#include <inttypes.h>
3#include "config.h"
Thomas Martitz22a28f92014-01-05 20:32:09 +01004#include "system.h"
Michael Sevakis4ea4cdf2014-08-08 02:28:11 -04005#include "../kernel-internal.h"
Marcin Bukat0263fe32012-02-28 15:51:36 +01006#include "gcc_extensions.h"
Marcin Bukat976a1692011-05-30 21:10:37 +00007#include "lcd.h"
Marcin Bukat976a1692011-05-30 21:10:37 +00008#include "font.h"
Marcin Bukat0263fe32012-02-28 15:51:36 +01009#include "backlight.h"
10#include "adc.h"
11#include "button-target.h"
12#include "button.h"
Marcin Bukat976a1692011-05-30 21:10:37 +000013#include "common.h"
Marcin Bukat0263fe32012-02-28 15:51:36 +010014#include "storage.h"
Michael Sevakis7d1a47c2013-08-05 22:02:45 -040015#include "file_internal.h"
Marcin Bukat0263fe32012-02-28 15:51:36 +010016#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 Bukatecbda692012-03-04 00:06:20 +010022#include "rkw-loader.h"
Andrew Ryabinina3e37912012-04-30 17:54:06 +040023#include "version.h"
Andrew Ryabinincdb71c72013-04-30 15:18:27 +040024#include "i2c-rk27xx.h"
Marcin Bukat0b296912012-03-04 15:34:29 +010025#include "loader_strerror.h"
Marcin Bukat976a1692011-05-30 21:10:37 +000026
Marcin Bukat79a667d2012-04-27 16:19:31 +020027/* beginning of DRAM */
Marcin Bukat0263fe32012-02-28 15:51:36 +010028#define DRAM_ORIG 0x60000000
Marcin Bukat79a667d2012-04-27 16:19:31 +020029
30/* bootloader code runs from 0x60700000
31 * so we cannot load more code to not overwrite ourself
32 */
Marcin Bukat0263fe32012-02-28 15:51:36 +010033#define LOAD_SIZE 0x700000
Marcin Bukatdceceef2011-06-05 10:26:06 +000034
Bertrik Sikken7e3a3f42011-09-08 18:31:15 +000035extern void show_logo( void );
Marcin Bukatdceceef2011-06-05 10:26:06 +000036
Marcin Bukat79a667d2012-04-27 16:19:31 +020037/* This function setup bare minimum
38 * and jumps to rom in order to activate
39 * hardcoded rkusb mode
40 */
41static void enter_rkusb(void)
42{
43 asm volatile (
Marcin Bukatb43171d2012-07-10 09:10:30 +020044 /* Turn off cache */
Marcin Bukat79a667d2012-04-27 16:19:31 +020045 "ldr r0, =0xefff0000 \n"
46 "ldrh r1, [r0] \n"
47 "strh r1, [r0] \n"
48
Marcin Bukatb43171d2012-07-10 09:10:30 +020049 /* Turn off interrupts */
Marcin Bukat79a667d2012-04-27 16:19:31 +020050 "mrs r0, cpsr \n"
51 "bic r0, r0, #0x1f \n"
52 "orr r0, r0, #0xd3 \n"
53 "msr cpsr, r0 \n"
54
Marcin Bukatb43171d2012-07-10 09:10:30 +020055 /* Disable iram remap */
Marcin Bukat79a667d2012-04-27 16:19:31 +020056 "mov r0, #0x18000000 \n"
57 "add r0, r0, #0x1c000 \n"
58 "mov r1, #0 \n"
59 "str r1, [r0, #4] \n"
60
Marcin Bukatb43171d2012-07-10 09:10:30 +020061 /* 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 Bukat1ed57aa2013-11-23 22:43:19 +010067 * 2706B and 2705 have ID 0xa100027b
Marcin Bukat79a667d2012-04-27 16:19:31 +020068 */
Marcin Bukatb43171d2012-07-10 09:10:30 +020069 "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 Bukat79a667d2012-04-27 16:19:31 +020088 "ldr r1, =0x18200274 \n"
Marcin Bukatb43171d2012-07-10 09:10:30 +020089 "ldr r0, =0xec0 \n"
90
91 "jump_to_rom: \n"
92 "msr cpsr, #0xd2 \n"
Marcin Bukat79a667d2012-04-27 16:19:31 +020093 "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 Bukatb43171d2012-07-10 09:10:30 +020099 /* Finaly jump to rkusb handler
100 * in bootrom.
Marcin Bukat79a667d2012-04-27 16:19:31 +0200101 */
Marcin Bukat79a667d2012-04-27 16:19:31 +0200102 "bx r0 \n"
103 );
104}
105
Marcin Bukatb43171d2012-07-10 09:10:30 +0200106
Marcin Bukat0263fe32012-02-28 15:51:36 +0100107void main(void) NORETURN_ATTR;
Marcin Bukat976a1692011-05-30 21:10:37 +0000108void main(void)
109{
Marcin Bukat0263fe32012-02-28 15:51:36 +0100110 char filename[MAX_PATH];
111 unsigned char* loadbuffer;
112 void(*kernel_entry)(void);
113 int ret;
114 enum {rb, of} boot = rb;
Marcin Bukat976a1692011-05-30 21:10:37 +0000115
Marcin Bukat0263fe32012-02-28 15:51:36 +0100116 power_init();
Marcin Bukat976a1692011-05-30 21:10:37 +0000117 system_init();
118 kernel_init();
Andrew Ryabinin61f9dbc2013-04-29 11:04:20 +0400119 i2c_init();
Marcin Bukat976a1692011-05-30 21:10:37 +0000120 enable_irq();
121
Marcin Bukat0263fe32012-02-28 15:51:36 +0100122 adc_init();
123 lcd_init();
124 backlight_init();
125 button_init_device();
126
Marcin Bukat976a1692011-05-30 21:10:37 +0000127 font_init();
128 lcd_setfont(FONT_SYSFIXED);
129
130 show_logo();
Marcin Bukat976a1692011-05-30 21:10:37 +0000131
Marcin Bukat0263fe32012-02-28 15:51:36 +0100132 int btn = button_read_device();
Marcin Bukatdceceef2011-06-05 10:26:06 +0000133
Marcin Bukat0263fe32012-02-28 15:51:36 +0100134 /* 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 Bukatdceceef2011-06-05 10:26:06 +0000139
Marcin Bukat0263fe32012-02-28 15:51:36 +0100140 /* if we are woken up by USB insert boot into OF */
141 if (DEV_INFO & (1<<20))
142 boot = of;
Marcin Bukatdceceef2011-06-05 10:26:06 +0000143
Marcin Bukat0263fe32012-02-28 15:51:36 +0100144 lcd_clear_display();
Marcin Bukatdceceef2011-06-05 10:26:06 +0000145
Marcin Bukat0263fe32012-02-28 15:51:36 +0100146 ret = storage_init();
147 if(ret < 0)
148 error(EATA, ret, true);
Marcin Bukatdceceef2011-06-05 10:26:06 +0000149
Michael Sevakis7d1a47c2013-08-05 22:02:45 -0400150 filesystem_init();
Marcin Bukatdceceef2011-06-05 10:26:06 +0000151
Marcin Bukat0263fe32012-02-28 15:51:36 +0100152 while((ret = disk_mount_all()) <= 0)
153 error(EDISK, ret, true);
Marcin Bukatdceceef2011-06-05 10:26:06 +0000154
Marcin Bukat0263fe32012-02-28 15:51:36 +0100155 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 Bukatdceceef2011-06-05 10:26:06 +0000161
Michael Sevakis95a4c3a2014-08-28 10:26:45 -0400162 printf("Bootloader version: %s", rbversion);
Marcin Bukat0263fe32012-02-28 15:51:36 +0100163 printf("Loading: %s", filename);
Marcin Bukatdceceef2011-06-05 10:26:06 +0000164
Marcin Bukat0263fe32012-02-28 15:51:36 +0100165 ret = load_rkw(loadbuffer, filename, LOAD_SIZE);
Marcin Bukat0b296912012-03-04 15:34:29 +0100166
167 if (ret <= EFILE_EMPTY)
Marcin Bukat976a1692011-05-30 21:10:37 +0000168 {
Marcin Bukat0b296912012-03-04 15:34:29 +0100169 error(EBOOTFILE, ret, false);
Marcin Bukat79a667d2012-04-27 16:19:31 +0200170
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 Bukat976a1692011-05-30 21:10:37 +0000186 }
Marcin Bukat0263fe32012-02-28 15:51:36 +0100187 else
188 {
Marcin Bukat79a667d2012-04-27 16:19:31 +0200189 /* print 'Loading OK' */
Marcin Bukat0b296912012-03-04 15:34:29 +0100190 printf("Loading OK");
Marcin Bukat0263fe32012-02-28 15:51:36 +0100191 sleep(HZ);
192 }
193
Marcin Bukat79a667d2012-04-27 16:19:31 +0200194 /* jump to entrypoint */
Marcin Bukat0263fe32012-02-28 15:51:36 +0100195 kernel_entry = (void*) loadbuffer;
196 commit_discard_idcache();
197
198 printf("Executing");
199 kernel_entry();
200
Marcin Bukat79a667d2012-04-27 16:19:31 +0200201 /* this should never be reached actually */
Marcin Bukat0263fe32012-02-28 15:51:36 +0100202 printf("ERR: Failed to boot");
203 sleep(5*HZ);
Marcin Bukat79a667d2012-04-27 16:19:31 +0200204
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 Bukat0263fe32012-02-28 15:51:36 +0100217
218 /* hang */
219 while(1);
Marcin Bukat976a1692011-05-30 21:10:37 +0000220}