1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
37 #include "backlight.h"
38 #include "backlight-target.h"
42 #include "powermgmt.h"
49 /* Maximum allowed firmware image size. 10MB is more than enough */
50 #define MAX_LOADSIZE (10*1024*1024)
52 #define DRAM_START 0x31000000
54 #define BOOTMENU_TIMEOUT (10*HZ)
55 #define BOOTMENU_OPTIONS 3
59 static const char *bootmenu_options
[] = {
76 char version
[] = APPSVERSION
;
78 bool _charger_inserted(void)
80 return (GPIO1_READ
& (1<<14)) ? false : true;
83 bool _battery_full(void)
85 return (GPIO_READ
& (1<<30)) ? true : false;
88 /* Reset the cookie for the crt0 crash check */
89 inline void __reset_cookie(void)
91 asm(" move.l #0,%d0");
92 asm(" move.l %d0,0x10017ffc");
95 void start_rockbox(void)
98 asm(" move.w #0x2700,%sr");
100 asm(" move.l %0,%%d0" :: "i"(DRAM_START
));
101 asm(" movec.l %d0,%vbr");
102 asm(" move.l %0,%%sp" :: "m"(*(int *)DRAM_START
));
103 asm(" move.l %0,%%a0" :: "m"(*(int *)(DRAM_START
+4)));
107 void start_mpio_firmware(void)
109 asm(" move.w #0x2700,%sr");
111 asm(" movec.l %d0,%vbr");
112 asm(" move.l 0,%sp");
118 asm(" move.w #0x2700,%sr");
120 asm(" movec.l %d0,%vbr");
121 asm(" move.l (0), %sp");
122 asm(" movea.l (4),%a0");
126 void __shutdown(void)
128 /* We need to gracefully spin down the disk to prevent clicks. */
131 /* Make sure ATA has been initialized. */
134 /* And put the disk into sleep immediately. */
142 if (_charger_inserted())
144 /* reset instead of power_off() */
153 /* Print the battery voltage (and a warning message). */
154 void check_battery(void)
157 int battery_voltage
, batt_int
, batt_frac
;
159 battery_voltage
= battery_adc_voltage();
160 batt_int
= battery_voltage
/ 1000;
161 batt_frac
= (battery_voltage
% 1000) / 10;
163 printf("Battery: %d.%02dV", batt_int
, batt_frac
);
165 if (battery_voltage
<= 3500)
167 printf("WARNING! BATTERY LOW!!");
174 void lcd_putstring_centered(const char *string
)
177 font_getstringsize(string
, &w
, &h
, FONT_SYSFIXED
);
178 lcd_putsxy((LCD_WIDTH
-w
)/2, (LCD_HEIGHT
-h
)/2, string
);
185 enum option_t option
= rockbox
;
187 const char select
[] = "->";
188 long start_tick
= current_tick
;
190 /* backbone of menu */
192 printf("Rockbox boot loader");
193 printf("Ver: %s", version
);
198 printf("=========================");
200 line
+= BOOTMENU_OPTIONS
+2; /* skip lines */
202 printf("=========================");
204 printf(" [FF] [PREV] to move ");
205 printf(" [PLAY] to confirm ");
207 /* content of menu and keys handling */
208 while (TIME_BEFORE(current_tick
,start_tick
+ BOOTMENU_TIMEOUT
))
211 line
= 6; /* move below header */
213 for (i
=0;i
<BOOTMENU_OPTIONS
;i
++)
216 printf(" %s",bootmenu_options
[i
]);
218 printf("%s %s",select
,bootmenu_options
[i
]);
223 printf("Time left: %ds",(BOOTMENU_TIMEOUT
-
224 (current_tick
- start_tick
))/HZ
);
228 button
= button_get_w_tmo(HZ
);
233 if (option
> rockbox
)
240 if (option
< shutdown
)
247 case (BUTTON_PLAY
|BUTTON_REC
):
256 printf("ATA error: %d", rc
);
263 rc
= disk_mount_all();
266 printf("No partition found");
271 printf("Loading firmware");
272 rc
= load_firmware((unsigned char *)DRAM_START
,
273 BOOTFILE
, MAX_LOADSIZE
);
274 printf("Result: %s", strerror(rc
));
279 printf("Can't load " BOOTFILE
": ");
280 printf(strerror(rc
));
292 start_mpio_firmware();
308 const char usb_connect_msg
[] = "Bootloader USB mode";
309 const char charging_msg
[] = "Charging...";
310 const char complete_msg
[] = "Charging complete";
311 const char hold_msg
[] = "Hold switch on";
312 const char shutdown_msg
[] = "Shutting down...";
314 /* helper variables for messages */
315 bool blink_toggle
= false;
318 bool on_button
= false;
321 /* We want to read the buttons as early as possible, before the user
322 releases the ON button */
324 or_l( ((1<<24)|(1<<4)), &GPIO1_FUNCTION
); /* main Hold & Play */
325 and_l( ~((1<<24)|(1<<4)), &GPIO1_ENABLE
); /* HiZ */
327 if (GPIO1_READ
& (1<<24))
335 set_cpu_frequency(CPUFREQ_NORMAL
);
336 coldfire_set_pllcr_audio_bits(DEFAULT_PLLCR_AUDIO_BITS
);
343 lcd_setfont(FONT_SYSFIXED
);
349 /* handle charging */
350 if( _charger_inserted())
352 or_l((1<<15),&GPIO_OUT
);
356 while( _charger_inserted() &&
357 usb_detect() != USB_INSERTED
&&
360 button
= button_get_w_tmo(HZ
);
369 case BUTTON_NONE
: /* Timeout */
373 /* To be replaced with a nice animation */
374 blink_toggle
= !blink_toggle
;
385 lcd_putstring_centered(msg
);
392 cpu_idle_mode(false);
395 /* handle USB in bootloader */
396 if (usb_detect() == USB_INSERTED
)
398 ide_power_enable(true);
403 while (usb_detect() == USB_INSERTED
)
411 lcd_putstring_centered(usb_connect_msg
);
415 blink_toggle
= !blink_toggle
;
417 storage_spin(); /* Prevent the drive from spinning down */
421 cpu_idle_mode(false);
429 /* handle ON button press */
433 !_charger_inserted() &&
434 usb_detect() != USB_INSERTED
)
436 lcd_putstring_centered(hold_msg
);
445 lcd_putstring_centered(shutdown_msg
);
455 /* These functions are present in the firmware library, but we reimplement
456 them here because the originals do a lot more than we want */
457 void screen_dump(void)