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"
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
61 #define EVENT_USB 0x04
62 #define EVENT_RTC 0x08
66 static const char *bootmenu_options
[] = {
83 /* return true if charger is present */
84 static inline bool _charger_inserted(void)
86 return (GPIO1_READ
& (1<<14)) ? false : true;
89 /* returns true if end of charge condition is reached */
90 static inline bool _battery_full(void)
92 return (GPIO_READ
& (1<<30)) ? true : false;
96 /* returns true if startup is due to RTC alarm */
97 static inline bool _rtc_alarm(void)
99 if ( (GPIO1_READ
& (1<<4)) && (GPIO1_READ
& (1<<5)) )
106 /* Reset the cookie for the crt0 crash check */
107 static inline void __reset_cookie(void)
109 asm(" move.l #0,%d0");
110 asm(" move.l %d0,0x10017ffc");
113 static void start_rockbox(void)
116 asm(" move.w #0x2700,%sr");
118 asm(" move.l %0,%%d0" :: "i"(DRAM_START
));
119 asm(" movec.l %d0,%vbr");
120 asm(" move.l %0,%%sp" :: "m"(*(int *)DRAM_START
));
121 asm(" move.l %0,%%a0" :: "m"(*(int *)(DRAM_START
+4)));
125 static void start_mpio_firmware(void)
127 asm(" move.w #0x2700,%sr");
129 asm(" movec.l %d0,%vbr");
130 asm(" move.l 0,%sp");
134 static void __shutdown(void)
136 if (_charger_inserted())
137 /* if AC power do nothing */
140 /* We need to gracefully spin down the disk to prevent clicks. */
143 /* Make sure ATA has been initialized. */
146 /* And put the disk into sleep immediately. */
157 /* Print the battery voltage (and a warning message). */
158 static void check_battery(void)
161 int battery_voltage
, batt_int
, batt_frac
;
163 battery_voltage
= battery_adc_voltage();
164 batt_int
= battery_voltage
/ 1000;
165 batt_frac
= (battery_voltage
% 1000) / 10;
167 printf("Battery: %d.%02dV", batt_int
, batt_frac
);
169 if (battery_voltage
<= 3500)
171 printf("WARNING! BATTERY LOW!!");
178 static void lcd_putstring_centered(const char *string
)
181 font_getstringsize(string
, &w
, &h
, FONT_SYSFIXED
);
182 lcd_putsxy((LCD_WIDTH
-w
)/2, (LCD_HEIGHT
-h
)/2, string
);
185 /* This function initializes ATA driver, mounts partitions,
186 * loads rockbox image from disk to ram and finally
187 * jumps to entry point in ram
189 static void rb_boot(void)
193 /* boost to speedup rb image loading */
197 printf("Rockbox boot loader");
198 printf("Version " RBVERSION
);
203 printf("ATA error: %d", rc
);
210 rc
= disk_mount_all();
213 printf("No partition found");
218 printf("Loading firmware");
220 rc
= load_firmware((unsigned char *)DRAM_START
,
221 BOOTFILE
, MAX_LOADSIZE
);
226 printf("Can't load " BOOTFILE
": ");
227 printf("Result: %s", strerror(rc
));
236 /* This function prints small bootmenu where
237 * you can choose to boot OF, rockbox or just shutdown
239 static void bootmenu(void)
242 enum option_t option
= rockbox
;
244 const char select
[] = "->";
245 long start_tick
= current_tick
;
247 /* backbone of menu */
249 printf("Rockbox boot loader");
250 printf("Ver: " RBVERSION
);
255 printf("=========================");
257 line
+= BOOTMENU_OPTIONS
+2; /* skip lines */
259 printf("=========================");
261 printf(" [FF] [REW] to move ");
262 printf(" [PLAY] to confirm ");
264 /* content of menu and keys handling */
265 while (TIME_BEFORE(current_tick
,start_tick
+ BOOTMENU_TIMEOUT
))
268 line
= 6; /* move below header */
270 for (i
=0;i
<BOOTMENU_OPTIONS
;i
++)
273 printf(" %s",bootmenu_options
[i
]);
275 printf("%s %s",select
,bootmenu_options
[i
]);
280 printf("Time left: %ds",(BOOTMENU_TIMEOUT
-
281 (current_tick
- start_tick
))/HZ
);
285 button
= BUTTON_NONE
;
286 button
= button_get_w_tmo(HZ
);
294 if (option
> rockbox
)
304 if (option
< shutdown
)
313 case (BUTTON_PLAY
|BUTTON_REC
):
324 start_mpio_firmware();
339 const char usb_connect_msg
[] = "Bootloader USB mode";
340 const char charging_msg
[] = "Charging...";
341 const char complete_msg
[] = "Charging complete";
343 /* helper variable for messages */
344 bool blink_toggle
= false;
348 /* hold status variables
349 * this two must have different
350 * values in the begining
353 bool last_hold
= true;
355 unsigned int event
= EVENT_NONE
;
356 unsigned int last_event
= EVENT_NONE
;
358 /* this is default mode after power_init() */
359 bool high_current_charging
= true;
361 /* setup GPIOs related to power functions */
368 set_cpu_frequency(CPUFREQ_NORMAL
);
370 /* IRQs are needed by button driver */
375 /* setup font system */
377 lcd_setfont(FONT_SYSFIXED
);
379 /* buttons reading init */
386 /* lowlevel init only */
389 /* Handle wakeup event. Possibilities are:
391 * ON button (PLAY or RC_PLAY on HD200)
397 /* check hold status */
398 hold
= button_hold();
400 /* backlight handling
401 * change only on hold toggle */
402 if ( hold
!= last_hold
)
414 button
= button_get_w_tmo(HZ
);
416 if ( (button
& BUTTON_PLAY
)
418 || (button
& BUTTON_RC_PLAY
)
423 if ( usb_detect() == USB_INSERTED
)
426 if ( _charger_inserted() )
438 case (EVENT_RTC
| EVENT_ON
):
439 /* start regardles of buttons state */
444 case (EVENT_ON
| EVENT_AC
):
445 /* hold is handled in button driver */
446 cpu_idle_mode(false);
447 ide_power_enable(true);
449 if (button
& BUTTON_REC
)
458 if (!(last_event
& EVENT_AC
))
460 /* reset charging circuit */
461 and_l(~(1<<23), &GPIO_ENABLE
);
465 if (last_event
& EVENT_USB
)
469 ide_power_enable(false);
476 lcd_putstring_centered(charging_msg
);
478 blink_toggle
= !blink_toggle
;
480 else /* end of charge condition */
482 /* put LTC1733 into shutdown mode */
483 or_l((1<<23), &GPIO_ENABLE
);
485 if (high_current_charging
)
487 /* switch to low current mode */
488 and_l(~(1<<15), &GPIO_OUT
);
490 /* reset charging circuit */
491 and_l(~(1<<23), &GPIO_ENABLE
);
493 high_current_charging
= false;
497 lcd_putstring_centered(complete_msg
);
504 case (EVENT_USB
| EVENT_AC
):
505 /* AC plug in while in USB mode */
506 if (!(last_event
& EVENT_AC
))
508 /* reset charger circuit */
509 and_l(~(1<<23), &GPIO_ENABLE
);
513 if (!(last_event
& EVENT_USB
))
516 ide_power_enable(true);
522 /* display blinking USB indicator */
526 lcd_putstring_centered(usb_connect_msg
);
529 blink_toggle
= !blink_toggle
;
535 if (last_event
& EVENT_USB
)
541 ide_power_enable(false);
545 /* spurious wakeup ?*/
555 /* These functions are present in the firmware library, but we reimplement
556 them here because the originals do a lot more than we want */
557 void screen_dump(void)