blob: efe19bf0c2da5718454a6b0c8b97ea8c87e24137 [file] [log] [blame]
Amaury Pouly08fb3f62011-05-01 13:02:46 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
Amaury Pouly3f20d132013-09-05 23:12:04 +020010 * Copyright (C) 2011 by Amaury Pouly
Amaury Pouly08fb3f62011-05-01 13:02:46 +000011 *
12 * Based on Rockbox iriver bootloader by Linus Nielsen Feltzing
13 * and the ipodlinux bootloader by Daniel Palffy and Bernard Leach
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
19 *
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
22 *
23 ****************************************************************************/
24
25#include <stdio.h>
26#include <system.h>
27#include <inttypes.h>
28#include "config.h"
Michael Sevakis4ea4cdf2014-08-08 02:28:11 -040029#include "../kernel-internal.h"
Amaury Pouly08fb3f62011-05-01 13:02:46 +000030#include "gcc_extensions.h"
31#include "lcd.h"
32#include "backlight.h"
33#include "button-target.h"
34#include "common.h"
Marcin Bukat0b296912012-03-04 15:34:29 +010035#include "rb-loader.h"
36#include "loader_strerror.h"
Amaury Pouly08fb3f62011-05-01 13:02:46 +000037#include "storage.h"
Michael Sevakis7d1a47c2013-08-05 22:02:45 -040038#include "file_internal.h"
Amaury Pouly08fb3f62011-05-01 13:02:46 +000039#include "disk.h"
40#include "panic.h"
41#include "power.h"
Amaury Poulyc4450b92012-02-28 22:44:57 +010042#include "power-imx233.h"
Amaury Pouly86e8c282011-05-11 22:38:09 +000043#include "system-target.h"
Amaury Pouly5a268112011-07-09 17:14:05 +000044#include "fmradio_i2c.h"
Amaury Pouly0b885f22011-12-26 19:13:29 +000045#include "version.h"
Amaury Poulyda7be392013-11-19 22:12:42 +000046#include "powermgmt-imx233.h"
Amaury Pouly07138ba2012-05-19 13:33:45 +020047#include "partitions-imx233.h"
Amaury Poulye1003b12014-02-10 22:29:31 +010048#include "backlight-target.h"
Amaury Pouly0cb76de2013-11-19 21:28:35 +000049#include "adc.h"
Amaury Pouly2cf33132011-06-17 22:30:58 +000050
51#include "usb.h"
Amaury Pouly7d4fed52011-09-05 11:29:32 +000052
Amaury Poulyd945c362011-09-13 23:38:08 +000053extern char loadaddress[];
54extern char loadaddressend[];
Amaury Pouly7d4fed52011-09-05 11:29:32 +000055
Amaury Pouly7e03dbb2013-09-25 14:11:56 +020056#define MSG(width, short, long) (LCD_WIDTH < (width) ? short : long)
57
Amaury Pouly7d4fed52011-09-05 11:29:32 +000058#ifdef HAVE_BOOTLOADER_USB_MODE
59static void usb_mode(int connect_timeout)
60{
61 int button;
Amaury Pouly2f6c0602013-06-18 21:26:23 +020062
Amaury Pouly7d4fed52011-09-05 11:29:32 +000063 usb_init();
64 usb_start_monitoring();
65
66 /* Wait for threads to connect or cable is pulled */
67 printf("USB: Connecting");
68
69 long end_tick = current_tick + connect_timeout;
70
71 while(1)
72 {
73 button = button_get_w_tmo(HZ/10);
74
75 if(button == SYS_USB_CONNECTED)
76 break; /* Hit */
77
78 if(TIME_AFTER(current_tick, end_tick))
79 {
80 /* Timed out waiting for the connect - will happen when connected
81 * to a charger through the USB port */
82 printf("USB: Timed out");
83 break;
84 }
85
Rafaël Carré2115eac2011-12-31 18:43:59 +000086 if(usb_detect() == USB_EXTRACTED)
Amaury Pouly7d4fed52011-09-05 11:29:32 +000087 break; /* Cable pulled */
88 }
89
90 if(button == SYS_USB_CONNECTED)
91 {
92 /* Got the message - wait for disconnect */
93 printf("Bootloader USB mode");
Amaury Poulya4fd5bf2012-03-15 14:58:15 +010094 /* Enable power management to charge */
95 powermgmt_init();
Amaury Pouly07138ba2012-05-19 13:33:45 +020096 adc_init();
Amaury Pouly7d4fed52011-09-05 11:29:32 +000097
Amaury Pouly246026c2015-01-08 22:18:22 +010098 /* ack the SYS_USB_CONNECTED polled from the button queue */
Amaury Pouly7d4fed52011-09-05 11:29:32 +000099 usb_acknowledge(SYS_USB_CONNECTED_ACK);
100
101 while(1)
102 {
103 button = button_get_w_tmo(HZ/2);
104 if(button == SYS_USB_DISCONNECTED)
105 break;
Amaury Poulya4fd5bf2012-03-15 14:58:15 +0100106 struct imx233_powermgmt_info_t info = imx233_powermgmt_get_info();
Amaury Pouly7e03dbb2013-09-25 14:11:56 +0200107 lcd_putsf(0, 7, "%s: %s", MSG(240, "Status", "Charging status"),
Amaury Poulya4fd5bf2012-03-15 14:58:15 +0100108 info.state == CHARGE_STATE_DISABLED ? "disabled" :
109 info.state == CHARGE_STATE_ERROR ? "error" :
110 info.state == DISCHARGING ? "discharging" :
111 info.state == TRICKLE ? "trickle" :
112 info.state == TOPOFF ? "topoff" :
113 info.state == CHARGING ? "charging" : "<unknown>");
Amaury Pouly27248882012-08-29 16:23:20 +0200114 lcd_putsf(0, 8, "Battery: %d%% (%d mV)", battery_level(), battery_voltage());
Amaury Pouly7e03dbb2013-09-25 14:11:56 +0200115 lcd_putsf(0, 9, "%s: %d 'C [%d, %d]", MSG(240, "Die", "Die temp"),
Amaury Pouly07138ba2012-05-19 13:33:45 +0200116 adc_read(ADC_DIE_TEMP), IMX233_DIE_TEMP_HIGH,
117 IMX233_DIE_TEMP_LOW);
Amaury Poulya4fd5bf2012-03-15 14:58:15 +0100118 lcd_update();
Amaury Pouly7d4fed52011-09-05 11:29:32 +0000119 }
120 }
121
122 /* Put drivers initialized for USB connection into a known state */
123 usb_close();
Amaury Pouly7d4fed52011-09-05 11:29:32 +0000124}
125#else /* !HAVE_BOOTLOADER_USB_MODE */
126static void usb_mode(int connect_timeout)
127{
128 (void) connect_timeout;
129}
130#endif /* HAVE_BOOTLOADER_USB_MODE */
Amaury Pouly08fb3f62011-05-01 13:02:46 +0000131
Amaury Pouly1322b582011-09-23 20:40:52 +0000132void main(uint32_t arg, uint32_t addr) NORETURN_ATTR;
133void main(uint32_t arg, uint32_t addr)
Amaury Pouly08fb3f62011-05-01 13:02:46 +0000134{
135 unsigned char* loadbuffer;
136 int buffer_size;
137 void(*kernel_entry)(void);
138 int ret;
139
140 system_init();
141 kernel_init();
142
Amaury Pouly2f5f2ba2013-09-25 14:12:48 +0200143 /* some ixm233 targets needs this because the cpu and/or memory is clocked
144 * at 24MHz, resulting in terribly slow boots and unusable usb mode.
145 * While we are at it, clock at maximum speed to minimise boot time. */
146 imx233_set_cpu_frequency(CPUFREQ_MAX);
147
Amaury Pouly7d4fed52011-09-05 11:29:32 +0000148 power_init();
Amaury Pouly08fb3f62011-05-01 13:02:46 +0000149 enable_irq();
150
151 lcd_init();
Amaury Pouly82ecc752011-07-02 02:12:10 +0000152 lcd_clear_display();
153 lcd_update();
Amaury Pouly08fb3f62011-05-01 13:02:46 +0000154
155 backlight_init();
156
Amaury Pouly7d4fed52011-09-05 11:29:32 +0000157 button_init();
Amaury Pouly08fb3f62011-05-01 13:02:46 +0000158
Michael Sevakis95a4c3a2014-08-28 10:26:45 -0400159 printf("%s: %s", MSG(240, "Ver", "Boot version"), rbversion);
Amaury Pouly7e03dbb2013-09-25 14:11:56 +0200160 printf("%s: %x ", MSG(240, "Arg", "Boot arg"), arg);
161 printf("%s: %x", MSG(240, "Addr", "Boot addr"), addr);
Amaury Pouly2f6c0602013-06-18 21:26:23 +0200162#if IMX233_SUBTARGET >= 3780
Amaury Pouly7e03dbb2013-09-25 14:11:56 +0200163 printf("Power up source: %x", BF_RD(POWER_STS, PWRUP_SOURCE));
Amaury Pouly2f6c0602013-06-18 21:26:23 +0200164#endif
Amaury Pouly7d4fed52011-09-05 11:29:32 +0000165
Amaury Pouly7d4fed52011-09-05 11:29:32 +0000166 if(arg == 0xfee1dead)
167 {
Amaury Pouly7e03dbb2013-09-25 14:11:56 +0200168 printf("%s", MSG(240, "Disable window", "Disable partitions window"));
Amaury Pouly07138ba2012-05-19 13:33:45 +0200169 imx233_partitions_enable_window(false);
Amaury Pouly7d4fed52011-09-05 11:29:32 +0000170 }
Amaury Pouly86e8c282011-05-11 22:38:09 +0000171
Amaury Pouly08fb3f62011-05-01 13:02:46 +0000172 ret = storage_init();
173 if(ret < 0)
174 error(EATA, ret, true);
175
Michael Sevakis7d1a47c2013-08-05 22:02:45 -0400176 filesystem_init();
Amaury Pouly08fb3f62011-05-01 13:02:46 +0000177
Amaury Poulyefc591e2013-10-20 18:11:24 +0200178 /* NOTE: disk_mount_all to fail since we can do USB after.
179 * We need this order to determine the correct logical sector size */
Amaury Pouly7d4fed52011-09-05 11:29:32 +0000180 if((ret = disk_mount_all()) <= 0)
181 error(EDISK, ret, false);
Amaury Pouly08fb3f62011-05-01 13:02:46 +0000182
Rafaël Carré2115eac2011-12-31 18:43:59 +0000183 if(usb_detect() == USB_INSERTED)
Amaury Pouly25f00602011-09-05 13:58:29 +0000184 usb_mode(HZ);
Amaury Pouly82f70b82011-07-22 15:45:58 +0000185
Amaury Poulyf7531052013-09-26 18:30:36 +0200186 /* dummy read, might be necessary to init things */
187#ifdef HAVE_BUTTON_DATA
188 int data;
189 button_read_device(&data);
190#else
191 button_read_device();
192#endif
193
194#ifdef HAS_BUTTON_HOLD
195 if(button_hold())
196 {
197 printf("Hold switch on");
198 printf("Shutting down...");
199 sleep(HZ);
200 power_off();
201 }
202#endif
203
Amaury Pouly08fb3f62011-05-01 13:02:46 +0000204 printf("Loading firmware");
205
Amaury Poulyd945c362011-09-13 23:38:08 +0000206 loadbuffer = (unsigned char*)loadaddress;
207 buffer_size = (int)(loadaddressend - loadaddress);
Amaury Pouly08fb3f62011-05-01 13:02:46 +0000208
Marcin Bukat0b296912012-03-04 15:34:29 +0100209 while((ret = load_firmware(loadbuffer, BOOTFILE, buffer_size)) <= EFILE_EMPTY)
Amaury Pouly08fb3f62011-05-01 13:02:46 +0000210 {
211 error(EBOOTFILE, ret, true);
212 }
213
214 kernel_entry = (void*) loadbuffer;
Amaury Pouly08fb3f62011-05-01 13:02:46 +0000215 printf("Executing");
Amaury Pouly935c0ad2014-02-10 22:28:46 +0100216 /* stop what was initialized to start from clean state */
217 system_prepare_fw_start();
Amaury Poulye1003b12014-02-10 22:29:31 +0100218 /* if target defines lcd_enable() in bootloader, take this as a hint that
219 * we should use it to properly stop the lcd before moving one, the
Marcin Bukat89ba7e82015-01-09 00:22:40 +0100220 * backlight_hw_off() routine is supposed to disable the lcd at the same time */
Amaury Poulye1003b12014-02-10 22:29:31 +0100221#ifdef HAVE_LCD_ENABLE
Marcin Bukat89ba7e82015-01-09 00:22:40 +0100222 backlight_hw_off();
Amaury Poulye1003b12014-02-10 22:29:31 +0100223#endif
Amaury Poulyd945c362011-09-13 23:38:08 +0000224 disable_interrupt(IRQ_FIQ_STATUS);
225 commit_discard_idcache();
Amaury Pouly08fb3f62011-05-01 13:02:46 +0000226 kernel_entry();
227 printf("ERR: Failed to boot");
228
229 /* never returns */
230 while(1) ;
231}