blob: 181dbeade360eca6f25c7d229cb6fe61f848b366 [file] [log] [blame]
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 by Linus Nielsen Feltzing
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "config.h"
20
21#include <stdlib.h>
22#include <stdio.h>
23#include "cpu.h"
24#include "system.h"
25#include "lcd.h"
26#include "kernel.h"
27#include "thread.h"
28#include "ata.h"
Linus Nielsen Feltzing01917ec2005-12-06 12:12:29 +000029#include "usb.h"
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +000030#include "disk.h"
31#include "font.h"
32#include "adc.h"
33#include "backlight.h"
Rani Hod78f425d2006-07-29 13:31:43 +000034#ifdef IAUDIO_X5
35#include "backlight-target.h"
36#endif
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +000037#include "button.h"
38#include "panic.h"
39#include "power.h"
40#include "file.h"
Linus Nielsen Feltzingd2ca7fc2005-07-12 05:25:42 +000041#include "uda1380.h"
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +000042
Linus Nielsen Feltzingce6527b2006-03-22 11:45:33 +000043#include "pcf50606.h"
44
45#include <stdarg.h>
46
Linus Nielsen Feltzing62c768c2005-07-09 07:46:42 +000047#define DRAM_START 0x31000000
48
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +000049int line = 0;
50
51int usb_screen(void)
52{
53 return 0;
54}
55
Linus Nielsen Feltzinga2e8cf72005-07-15 07:42:25 +000056char version[] = APPSVERSION;
57
Linus Nielsen Feltzingce6527b2006-03-22 11:45:33 +000058char printfbuf[256];
59
60void printf(const char *format, ...)
61{
62 int len;
63 unsigned char *ptr;
64 va_list ap;
65 va_start(ap, format);
66
67 ptr = printfbuf;
68 len = vsnprintf(ptr, sizeof(printfbuf), format, ap);
69 va_end(ap);
70
71 lcd_puts(0, line++, ptr);
72 lcd_update();
73 if(line >= 16)
74 line = 0;
75}
76
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +000077void start_iriver_fw(void)
78{
79 asm(" move.w #0x2700,%sr");
Linus Nielsen Feltzingf1530d82005-02-04 18:24:58 +000080 /* Reset the cookie for the crt0 crash check */
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +000081 asm(" move.l #0,%d0");
Linus Nielsen Feltzingf1530d82005-02-04 18:24:58 +000082 asm(" move.l %d0,0x10017ffc");
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +000083 asm(" movec.l %d0,%vbr");
84 asm(" move.l 0,%sp");
85 asm(" lea.l 8,%a0");
86 asm(" jmp (%a0)");
87}
88
89int load_firmware(void)
90{
91 int fd;
92 int rc;
93 int len;
94 unsigned long chksum;
Linus Nielsen Feltzinga75f0e52005-07-09 09:04:37 +000095 char model[5];
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +000096 unsigned long sum;
97 int i;
Linus Nielsen Feltzinge82df4e2005-07-08 15:09:44 +000098 unsigned char *buf = (unsigned char *)DRAM_START;
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +000099
Linus Nielsen Feltzingbbe919b2005-11-19 01:33:28 +0000100 fd = open("/.rockbox/" BOOTFILE, O_RDONLY);
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000101 if(fd < 0)
Linus Nielsen Feltzingbbe919b2005-11-19 01:33:28 +0000102 {
103 fd = open("/" BOOTFILE, O_RDONLY);
104 if(fd < 0)
105 return -1;
106 }
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000107
Linus Nielsen Feltzingb8a00d22005-02-10 21:55:48 +0000108 len = filesize(fd) - 8;
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000109
Linus Nielsen Feltzingce6527b2006-03-22 11:45:33 +0000110 printf("Length: %x", len);
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000111 lcd_update();
112
Linus Nielsen Feltzing2a77d3a2005-01-28 13:27:58 +0000113 lseek(fd, FIRMWARE_OFFSET_FILE_CRC, SEEK_SET);
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000114
115 rc = read(fd, &chksum, 4);
116 if(rc < 4)
117 return -2;
118
Linus Nielsen Feltzingce6527b2006-03-22 11:45:33 +0000119 printf("Checksum: %x", chksum);
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000120 lcd_update();
121
Linus Nielsen Feltzinga75f0e52005-07-09 09:04:37 +0000122 rc = read(fd, model, 4);
123 if(rc < 4)
124 return -3;
125
126 model[4] = 0;
127
Linus Nielsen Feltzingce6527b2006-03-22 11:45:33 +0000128 printf("Model name: %s", model);
Linus Nielsen Feltzinga75f0e52005-07-09 09:04:37 +0000129 lcd_update();
130
Linus Nielsen Feltzing2a77d3a2005-01-28 13:27:58 +0000131 lseek(fd, FIRMWARE_OFFSET_FILE_DATA, SEEK_SET);
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000132
133 rc = read(fd, buf, len);
134 if(rc < len)
135 return -4;
136
137 close(fd);
138
Linus Nielsen Feltzinge82df4e2005-07-08 15:09:44 +0000139 sum = MODEL_NUMBER;
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000140
141 for(i = 0;i < len;i++) {
142 sum += buf[i];
143 }
144
Linus Nielsen Feltzingce6527b2006-03-22 11:45:33 +0000145 printf("Sum: %x", sum);
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000146 lcd_update();
147
148 if(sum != chksum)
149 return -5;
150
151 return 0;
152}
153
Linus Nielsen Feltzinge82df4e2005-07-08 15:09:44 +0000154
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000155void start_firmware(void)
156{
157 asm(" move.w #0x2700,%sr");
Linus Nielsen Feltzingf1530d82005-02-04 18:24:58 +0000158 /* Reset the cookie for the crt0 crash check */
159 asm(" move.l #0,%d0");
160 asm(" move.l %d0,0x10017ffc");
Linus Nielsen Feltzinge82df4e2005-07-08 15:09:44 +0000161 asm(" move.l %0,%%d0" :: "i"(DRAM_START));
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000162 asm(" movec.l %d0,%vbr");
Linus Nielsen Feltzinge82df4e2005-07-08 15:09:44 +0000163 asm(" move.l %0,%%sp" :: "m"(*(int *)DRAM_START));
164 asm(" move.l %0,%%a0" :: "m"(*(int *)(DRAM_START+4)));
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000165 asm(" jmp (%a0)");
166}
167
Linus Nielsen Feltzingb8a00d22005-02-10 21:55:48 +0000168void main(void)
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000169{
170 int i;
171 int rc;
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000172 bool rc_on_button = false;
173 bool on_button = false;
174 int data;
Linus Nielsen Feltzingdfa8ecb2005-07-11 14:01:45 +0000175 int adc_battery, battery_voltage, batt_int, batt_frac;
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000176
Linus Nielsen Feltzingce6527b2006-03-22 11:45:33 +0000177#ifdef IAUDIO_X5
178 (void)rc_on_button;
179 (void)on_button;
180 (void)data;
181 power_init();
182
183 system_init();
184 kernel_init();
185
186 set_cpu_frequency(CPUFREQ_NORMAL);
187
188 set_irq_level(0);
189 lcd_init();
Rani Hod78f425d2006-07-29 13:31:43 +0000190 __backlight_on();
Linus Nielsen Feltzingce6527b2006-03-22 11:45:33 +0000191 font_init();
192 adc_init();
193 button_init();
194
195 printf("Rockbox boot loader");
196 printf("Version %s", version);
197 lcd_update();
198
199 adc_battery = adc_read(ADC_BATTERY);
200
201 battery_voltage = (adc_battery * BATTERY_SCALE_FACTOR) / 10000;
202 batt_int = battery_voltage / 100;
203 batt_frac = battery_voltage % 100;
204
205 printf("Batt: %d.%02dV", batt_int, batt_frac);
206 lcd_update();
207
208 rc = ata_init();
209 if(rc)
210 {
211 printf("ATA error: %d", rc);
212 sleep(HZ*5);
213 power_off();
214 }
215
216 disk_init();
217
218 rc = disk_mount_all();
219 if (rc<=0)
220 {
221 printf("No partition found");
222 sleep(HZ*5);
223 power_off();
224 }
225
226 printf("Loading firmware");
227 lcd_update();
228 i = load_firmware();
229 printf("Result: %d", i);
230 lcd_update();
231
232 if(i == 0)
233 start_firmware();
234
235 power_off();
236
237#else
Linus Nielsen Feltzinge628b5c2005-07-19 08:08:33 +0000238 /* We want to read the buttons as early as possible, before the user
239 releases the ON button */
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000240
Linus Nielsen Feltzinge628b5c2005-07-19 08:08:33 +0000241 /* Set GPIO33, GPIO37, GPIO38 and GPIO52 as general purpose inputs
242 (The ON and Hold buttons on the main unit and the remote) */
Linus Nielsen Feltzingd2ca7fc2005-07-12 05:25:42 +0000243 or_l(0x00100062, &GPIO1_FUNCTION);
244 and_l(~0x00100062, &GPIO1_ENABLE);
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000245
246 data = GPIO1_READ;
247 if ((data & 0x20) == 0)
248 on_button = true;
249
250 if ((data & 0x40) == 0)
251 rc_on_button = true;
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000252
Linus Nielsen Feltzinge628b5c2005-07-19 08:08:33 +0000253 /* Set the default state of the hard drive power to OFF */
254 ide_power_enable(false);
255
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000256 power_init();
Linus Nielsen Feltzinge628b5c2005-07-19 08:08:33 +0000257
Linus Nielsen Feltzingbbe919b2005-11-19 01:33:28 +0000258 /* Turn off if neither ON button is pressed */
Linus Nielsen Feltzing54da9242006-01-10 23:11:57 +0000259 if(!(on_button || rc_on_button || usb_detect()))
Linus Nielsen Feltzingbbe919b2005-11-19 01:33:28 +0000260 power_off();
261
262 /* Backlight ON */
263 or_l(0x00020000, &GPIO1_ENABLE);
264 or_l(0x00020000, &GPIO1_FUNCTION);
265 and_l(~0x00020000, &GPIO1_OUT);
266
267 /* Remote backlight ON */
268#ifdef HAVE_REMOTE_LCD
269#ifdef IRIVER_H300_SERIES
270 or_l(0x00000002, &GPIO1_ENABLE);
271 and_l(~0x00000002, &GPIO1_OUT);
272#else
273 or_l(0x00000800, &GPIO_ENABLE);
274 or_l(0x00000800, &GPIO_FUNCTION);
275 and_l(~0x00000800, &GPIO_OUT);
276#endif
277#endif
278
Linus Nielsen Feltzingb68cb9b2005-12-03 00:54:59 +0000279 /* Power on the hard drive early, to speed up the loading.
280 Some H300 don't like this, so we only do it for the H100 */
281#ifndef IRIVER_H300_SERIES
Linus Nielsen Feltzinge628b5c2005-07-19 08:08:33 +0000282 if(!((on_button && button_hold()) ||
283 (rc_on_button && remote_button_hold()))) {
284 ide_power_enable(true);
285 }
Linus Nielsen Feltzingb68cb9b2005-12-03 00:54:59 +0000286#endif
Linus Nielsen Feltzinge628b5c2005-07-19 08:08:33 +0000287
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000288 system_init();
289 kernel_init();
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000290
291#ifdef HAVE_ADJUSTABLE_CPU_FREQ
292 /* Set up waitstates for the peripherals */
293 set_cpu_frequency(0); /* PLL off */
294#endif
Linus Nielsen Feltzingd2ca7fc2005-07-12 05:25:42 +0000295
Linus Nielsen Feltzing2fcd1b02006-02-04 23:09:56 +0000296#ifdef HAVE_UDA1380
Linus Nielsen Feltzingd2ca7fc2005-07-12 05:25:42 +0000297 uda1380_reset();
Linus Nielsen Feltzing2fcd1b02006-02-04 23:09:56 +0000298#endif
Linus Nielsen Feltzingdfa8ecb2005-07-11 14:01:45 +0000299
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000300 backlight_init();
301 set_irq_level(0);
302 lcd_init();
303 font_init();
304 adc_init();
305 button_init();
306
307 lcd_setfont(FONT_SYSFIXED);
308
Linus Nielsen Feltzingce6527b2006-03-22 11:45:33 +0000309 printf("Rockbox boot loader");
310 printf("Version %s", version);
Linus Nielsen Feltzingd1af08f2005-07-09 19:48:22 +0000311 lcd_update();
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000312
Linus Nielsen Feltzingb8a00d22005-02-10 21:55:48 +0000313 sleep(HZ/50); /* Allow the button driver to check the buttons */
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000314
Linus Nielsen Feltzinge628b5c2005-07-19 08:08:33 +0000315 /* Holding REC while starting runs the original firmware */
Linus Nielsen Feltzingd1af08f2005-07-09 19:48:22 +0000316 if(((button_status() & BUTTON_REC) == BUTTON_REC) ||
317 ((button_status() & BUTTON_RC_REC) == BUTTON_RC_REC)) {
Linus Nielsen Feltzingce6527b2006-03-22 11:45:33 +0000318 printf("Starting original firmware...");
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000319 lcd_update();
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000320 start_iriver_fw();
321 }
322
Linus Nielsen Feltzinge628b5c2005-07-19 08:08:33 +0000323 /* Don't start if the Hold button is active on the device you
324 are starting with */
Linus Nielsen Feltzing54da9242006-01-10 23:11:57 +0000325 if(!usb_detect() && ((on_button && button_hold()) ||
326 (rc_on_button && remote_button_hold()))) {
Linus Nielsen Feltzingce6527b2006-03-22 11:45:33 +0000327 printf("HOLD switch on, power off...");
Linus Nielsen Feltzingb8a00d22005-02-10 21:55:48 +0000328 lcd_update();
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000329 sleep(HZ*2);
Linus Nielsen Feltzingbbe919b2005-11-19 01:33:28 +0000330
331 /* Backlight OFF */
332#ifdef HAVE_REMOTE_LCD
333#ifdef IRIVER_H300_SERIES
334 or_l(0x00000002, &GPIO1_OUT);
335#else
336 or_l(0x00000800, &GPIO_OUT);
337#endif
338#endif
Linus Nielsen Feltzingd4ad14c2005-02-11 09:02:46 +0000339 /* Reset the cookie for the crt0 crash check */
340 asm(" move.l #0,%d0");
341 asm(" move.l %d0,0x10017ffc");
Linus Nielsen Feltzingb8a00d22005-02-10 21:55:48 +0000342 power_off();
343 }
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000344
Linus Nielsen Feltzing01917ec2005-12-06 12:12:29 +0000345 usb_init();
346
Linus Nielsen Feltzingdfa8ecb2005-07-11 14:01:45 +0000347 adc_battery = adc_read(ADC_BATTERY);
348
349 battery_voltage = (adc_battery * BATTERY_SCALE_FACTOR) / 10000;
350 batt_int = battery_voltage / 100;
351 batt_frac = battery_voltage % 100;
352
Linus Nielsen Feltzingce6527b2006-03-22 11:45:33 +0000353 printf("Batt: %d.%02dV", batt_int, batt_frac);
Linus Nielsen Feltzingdfa8ecb2005-07-11 14:01:45 +0000354 lcd_update();
355
356 if(battery_voltage <= 300) {
Linus Nielsen Feltzingce6527b2006-03-22 11:45:33 +0000357 printf("WARNING! BATTERY LOW!!");
Linus Nielsen Feltzingdfa8ecb2005-07-11 14:01:45 +0000358 lcd_update();
359 sleep(HZ*2);
360 }
361
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000362 rc = ata_init();
363 if(rc)
364 {
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000365 lcd_clear_display();
Linus Nielsen Feltzingce6527b2006-03-22 11:45:33 +0000366 printf("ATA error: %d", rc);
367 printf("Insert USB cable and press");
368 printf("a button");
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000369 lcd_update();
370 while(!(button_get(true) & BUTTON_REL));
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000371 }
372
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000373 /* A hack to enter USB mode without using the USB thread */
374 if(usb_detect())
375 {
Linus Nielsen Feltzing01917ec2005-12-06 12:12:29 +0000376 const char msg[] = "Bootloader USB mode";
377 int w, h;
378 font_getstringsize(msg, &w, &h, FONT_SYSFIXED);
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000379 lcd_clear_display();
Linus Nielsen Feltzing01917ec2005-12-06 12:12:29 +0000380 lcd_putsxy((LCD_WIDTH-w)/2, (LCD_HEIGHT-h)/2, msg);
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000381 lcd_update();
382
Linus Nielsen Feltzing780cfff2006-01-11 15:37:08 +0000383#ifdef IRIVER_H300_SERIES
384 sleep(HZ);
385#endif
386
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000387 ata_spin();
388 ata_enable(false);
389 usb_enable(true);
Linus Nielsen Feltzing01917ec2005-12-06 12:12:29 +0000390 cpu_idle_mode(true);
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000391 while(usb_detect())
392 {
393 ata_spin(); /* Prevent the drive from spinning down */
394 sleep(HZ);
Linus Nielsen Feltzinge628b5c2005-07-19 08:08:33 +0000395
396 /* Backlight OFF */
397 or_l(0x00020000, &GPIO1_OUT);
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000398 }
399
Linus Nielsen Feltzing01917ec2005-12-06 12:12:29 +0000400 cpu_idle_mode(false);
Linus Nielsen Feltzing13103902005-07-19 11:03:00 +0000401 usb_enable(false);
402 ata_init(); /* Reinitialize ATA and continue booting */
403
404 lcd_clear_display();
405 line = 0;
406 lcd_update();
Linus Nielsen Feltzing8e958b52005-05-20 18:16:45 +0000407 }
408
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000409 disk_init();
410
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000411 rc = disk_mount_all();
412 if (rc<=0)
413 {
414 lcd_clear_display();
Linus Nielsen Feltzingce6527b2006-03-22 11:45:33 +0000415 printf("No partition found");
416 lcd_update();
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000417 while(button_get(true) != SYS_USB_CONNECTED) {};
418 }
419
Linus Nielsen Feltzingce6527b2006-03-22 11:45:33 +0000420 printf("Loading firmware");
Linus Nielsen Feltzing2a3856f2005-02-07 01:47:47 +0000421 lcd_update();
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000422 i = load_firmware();
Linus Nielsen Feltzingce6527b2006-03-22 11:45:33 +0000423 printf("Result: %d", i);
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000424 lcd_update();
425
426 if(i == 0)
427 start_firmware();
428
Linus Nielsen Feltzingb8a00d22005-02-10 21:55:48 +0000429 start_iriver_fw();
Linus Nielsen Feltzingce6527b2006-03-22 11:45:33 +0000430#endif /* IAUDIO_X5 */
Linus Nielsen Feltzingd3971452005-01-28 12:51:10 +0000431}
432
433/* These functions are present in the firmware library, but we reimplement
434 them here because the originals do a lot more than we want */
435
436void reset_poweroff_timer(void)
437{
438}
439
440void screen_dump(void)
441{
442}
443
444int dbg_ports(void)
445{
446 return 0;
447}
448
449void mpeg_stop(void)
450{
451}
452
Linus Nielsen Feltzinge244f7f2005-09-14 09:44:45 +0000453void sys_poweroff(void)
454{
455}