Rename bootloader file for MPIO players as it supports both HD200 and HD300.
[kugel-rb.git] / bootloader / mpio_hd200_hd300.c
blob7d6c60885d1d9945e58353dd5a83e0c52ee96b82
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2010 Marcin Bukat
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include "config.h"
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include "inttypes.h"
26 #include "string.h"
27 #include "cpu.h"
28 #include "system.h"
29 #include "lcd.h"
30 #include "kernel.h"
31 #include "thread.h"
32 #include "storage.h"
33 #include "usb.h"
34 #include "disk.h"
35 #include "font.h"
36 #include "adc.h"
37 #include "backlight.h"
38 #include "backlight-target.h"
39 #include "button.h"
40 #include "panic.h"
41 #include "power.h"
42 #include "powermgmt.h"
43 #include "file.h"
45 #include "common.h"
46 #include "version.h"
48 #include <stdarg.h>
50 /* Maximum allowed firmware image size. 10MB is more than enough */
51 #define MAX_LOADSIZE (10*1024*1024)
53 #define DRAM_START 0x31000000
55 #define BOOTMENU_TIMEOUT (10*HZ)
56 #define BOOTMENU_OPTIONS 3
58 #define EVENT_NONE 0x00
59 #define EVENT_ON 0x01
60 #define EVENT_AC 0x02
61 #define EVENT_USB 0x04
63 /* From common.c */
64 extern int line;
65 static const char *bootmenu_options[] = {
66 "Boot rockbox",
67 "Boot MPIO firmware",
68 "Shutdown"
71 enum option_t {
72 rockbox,
73 mpio_firmware,
74 shutdown
77 int usb_screen(void)
79 return 0;
82 static inline bool _charger_inserted(void)
84 return (GPIO1_READ & (1<<14)) ? false : true;
87 static inline bool _battery_full(void)
89 return (GPIO_READ & (1<<30)) ? true : false;
92 /* Reset the cookie for the crt0 crash check */
93 static inline void __reset_cookie(void)
95 asm(" move.l #0,%d0");
96 asm(" move.l %d0,0x10017ffc");
99 static void start_rockbox(void)
101 adc_close();
102 asm(" move.w #0x2700,%sr");
103 __reset_cookie();
104 asm(" move.l %0,%%d0" :: "i"(DRAM_START));
105 asm(" movec.l %d0,%vbr");
106 asm(" move.l %0,%%sp" :: "m"(*(int *)DRAM_START));
107 asm(" move.l %0,%%a0" :: "m"(*(int *)(DRAM_START+4)));
108 asm(" jmp (%a0)");
111 static void start_mpio_firmware(void)
113 asm(" move.w #0x2700,%sr");
114 __reset_cookie();
115 asm(" movec.l %d0,%vbr");
116 asm(" move.l 0,%sp");
117 asm(" jmp 8");
120 static void __shutdown(void)
122 if (_charger_inserted())
123 /* if AC power do nothing */
124 return;
126 /* We need to gracefully spin down the disk to prevent clicks. */
127 if (ide_powered())
129 /* Make sure ATA has been initialized. */
130 storage_init();
132 /* And put the disk into sleep immediately. */
133 storage_sleepnow();
136 /* Backlight OFF */
137 _backlight_off();
138 __reset_cookie();
140 power_off();
143 /* Print the battery voltage (and a warning message). */
144 static void check_battery(void)
147 int battery_voltage, batt_int, batt_frac;
149 battery_voltage = battery_adc_voltage();
150 batt_int = battery_voltage / 1000;
151 batt_frac = (battery_voltage % 1000) / 10;
153 printf("Battery: %d.%02dV", batt_int, batt_frac);
155 if (battery_voltage <= 3500)
157 printf("WARNING! BATTERY LOW!!");
158 sleep(HZ*2);
164 static void lcd_putstring_centered(const char *string)
166 int w,h;
167 font_getstringsize(string, &w, &h, FONT_SYSFIXED);
168 lcd_putsxy((LCD_WIDTH-w)/2, (LCD_HEIGHT-h)/2, string);
171 static void rb_boot(void)
173 int rc;
175 /* boost to speedup rb image loading */
176 cpu_boost(true);
178 printf("Rockbox boot loader");
179 printf("Version " RBVERSION);
181 rc = storage_init();
182 if(rc)
184 printf("ATA error: %d", rc);
185 sleep(HZ*5);
186 return;
189 disk_init();
191 rc = disk_mount_all();
192 if (rc<=0)
194 printf("No partition found");
195 sleep(HZ*5);
196 return;
199 printf("Loading firmware");
201 rc = load_firmware((unsigned char *)DRAM_START,
202 BOOTFILE, MAX_LOADSIZE);
204 if (rc < EOK)
206 printf("Error!");
207 printf("Can't load " BOOTFILE ": ");
208 printf("Result: %s", strerror(rc));
209 sleep(HZ*5);
210 return;
213 cpu_boost(false);
214 start_rockbox();
217 static void bootmenu(void)
219 enum option_t i;
220 enum option_t option = rockbox;
221 int button;
222 const char select[] = "->";
223 long start_tick = current_tick;
225 /* backbone of menu */
226 /* run the loader */
227 printf("Rockbox boot loader");
228 printf("Ver: " RBVERSION);
230 check_battery();
232 printf("");
233 printf("=========================");
235 line += BOOTMENU_OPTIONS+2; /* skip lines */
237 printf("=========================");
238 printf("");
239 printf(" [FF] [REW] to move ");
240 printf(" [PLAY] to confirm ");
242 /* content of menu and keys handling */
243 while (TIME_BEFORE(current_tick,start_tick + BOOTMENU_TIMEOUT))
245 /* Draw the menu. */
246 line = 6; /* move below header */
248 for (i=0;i<BOOTMENU_OPTIONS;i++)
250 if (i != option)
251 printf(" %s",bootmenu_options[i]);
252 else
253 printf("%s %s",select,bootmenu_options[i]);
256 line = 15;
258 printf("Time left: %ds",(BOOTMENU_TIMEOUT -
259 (current_tick - start_tick))/HZ);
261 lcd_update();
263 button = BUTTON_NONE;
264 button = button_get_w_tmo(HZ);
266 switch (button)
268 case BUTTON_REW:
269 #ifdef MPIO_HD200
270 case BUTTON_RC_REW:
271 #endif
272 if (option > rockbox)
273 option--;
274 else
275 option = shutdown;
276 break;
278 case BUTTON_FF:
279 #ifdef MPIO_HD200
280 case BUTTON_RC_FF:
281 #endif
282 if (option < shutdown)
283 option++;
284 else
285 option = rockbox;
286 break;
288 case BUTTON_PLAY:
289 #ifdef MPIO_HD200
290 case BUTTON_RC_PLAY:
291 case (BUTTON_PLAY|BUTTON_REC):
292 #endif
293 reset_screen();
295 switch (option)
297 case rockbox:
298 rb_boot();
299 break;
301 case mpio_firmware:
302 start_mpio_firmware();
303 break;
305 default:
306 return;
307 break;
311 /* timeout */
314 void main(void)
316 /* messages */
317 const char usb_connect_msg[] = "Bootloader USB mode";
318 const char charging_msg[] = "Charging...";
319 const char complete_msg[] = "Charging complete";
321 /* helper variable for messages */
322 bool blink_toggle = false;
324 int button;
325 unsigned int event = EVENT_NONE;
326 unsigned int last_event = EVENT_NONE;
328 /* this is default mode after power_init() */
329 bool high_current_charging = true;
331 /* setup GPIOs related to power functions */
332 power_init();
334 system_init();
335 kernel_init();
337 /* run at 45MHz */
338 set_cpu_frequency(CPUFREQ_NORMAL);
340 /* IRQs are needed by button driver */
341 enable_irq();
343 lcd_init();
345 /* only lowlevel functions no queue init */
346 _backlight_init();
347 _backlight_hw_on();
349 /* setup font system*/
350 font_init();
351 lcd_setfont(FONT_SYSFIXED);
353 /* buttons reading init*/
354 adc_init();
355 button_init();
357 usb_init();
358 cpu_idle_mode(true);
360 /* Handle wakeup event. Possibilities are:
361 * ON button (PLAY)
362 * USB insert
363 * AC charger plug
366 while(1)
368 /* read buttons */
369 event = EVENT_NONE;
370 button = button_get_w_tmo(HZ);
372 if ( (button & BUTTON_PLAY)
373 #ifdef MPIO_HD200
374 || (button & BUTTON_RC_PLAY)
375 #endif
377 event |= EVENT_ON;
379 if ( usb_detect() == USB_INSERTED )
380 event |= EVENT_USB;
382 if ( _charger_inserted() )
383 event |= EVENT_AC;
385 reset_screen();
386 switch (event)
388 case EVENT_ON:
389 case (EVENT_ON | EVENT_AC):
390 /* hold is handled in button driver */
391 cpu_idle_mode(false);
392 ide_power_enable(true);
394 if (button == (BUTTON_PLAY|BUTTON_REC))
395 bootmenu();
396 else
397 rb_boot();
399 break;
401 case EVENT_AC:
402 /* AC plug in */
403 if (!(last_event & EVENT_AC))
405 /* reset charging circuit */
406 and_l(~(1<<23), &GPIO_ENABLE);
409 /* USB unplug */
410 if (last_event & EVENT_USB)
412 usb_enable(false);
413 sleep(HZ);
414 ide_power_enable(false);
415 sleep(HZ);
418 if(!_battery_full())
420 if (blink_toggle)
421 lcd_putstring_centered(charging_msg);
423 blink_toggle = !blink_toggle;
425 else /* end of charge condition */
427 /* put LTC1733 into shutdown mode */
428 or_l((1<<23), &GPIO_ENABLE);
430 if (high_current_charging)
432 /* switch to low current mode */
433 and_l(~(1<<15), &GPIO_OUT);
435 /* reset charging circuit */
436 and_l(~(1<<23), &GPIO_ENABLE);
438 high_current_charging = false;
440 else
442 lcd_putstring_centered(complete_msg);
445 check_battery();
446 break;
448 case EVENT_USB:
449 case (EVENT_USB | EVENT_AC):
450 /* AC plug in while in USB mode */
451 if (!(last_event & EVENT_AC))
453 /* reset charger circuit */
454 and_l(~(1<<23), &GPIO_ENABLE);
457 /* USB plug in */
458 if (!(last_event & EVENT_USB))
460 /* init USB */
461 ide_power_enable(true);
462 sleep(HZ/20);
463 usb_enable(true);
466 /* display blinking USB indicator */
467 line = 0;
469 if (blink_toggle)
470 lcd_putstring_centered(usb_connect_msg);
472 check_battery();
473 blink_toggle = !blink_toggle;
474 storage_spin();
475 break;
477 default:
478 /* USB unplug */
479 if (last_event & EVENT_USB)
481 /* disable USB */
482 usb_enable(false);
483 sleep(HZ);
484 ide_power_enable(false);
485 sleep(HZ);
488 /* spurious wakeup ?*/
489 __shutdown();
490 break;
492 lcd_update();
493 last_event = event;
498 /* These functions are present in the firmware library, but we reimplement
499 them here because the originals do a lot more than we want */
500 void screen_dump(void)