diff options
author | Dominik Riebeling <Dominik.Riebeling@gmail.com> | 2021-12-15 21:04:28 +0100 |
---|---|---|
committer | Dominik Riebeling <Dominik.Riebeling@gmail.com> | 2021-12-24 18:05:53 +0100 |
commit | c876d3bbefe0dc00c27ca0c12d29da5874946962 (patch) | |
tree | 69f468a185a369b01998314bc3ecc19b70f4fcaa /utils/mkimxboot/dualboot | |
parent | 6c6f0757d7a902feb293be165d1490c42bc8e7ad (diff) | |
download | rockbox-c876d3bbefe0dc00c27ca0c12d29da5874946962.tar.gz rockbox-c876d3bbefe0dc00c27ca0c12d29da5874946962.zip |
rbutil: Merge rbutil with utils folder.
rbutil uses several components from the utils folder, and can be
considered part of utils too. Having it in a separate folder is an
arbitrary split that doesn't help anymore these days, so merge them.
This also allows other utils to easily use libtools.make without the
need to navigate to a different folder.
Change-Id: I3fc2f4de19e3e776553efb5dea5f779dfec0dc21
Diffstat (limited to 'utils/mkimxboot/dualboot')
-rw-r--r-- | utils/mkimxboot/dualboot/Makefile | 48 | ||||
-rw-r--r-- | utils/mkimxboot/dualboot/bin2c.c | 140 | ||||
-rw-r--r-- | utils/mkimxboot/dualboot/config.h | 26 | ||||
-rw-r--r-- | utils/mkimxboot/dualboot/dualboot.c | 323 | ||||
-rw-r--r-- | utils/mkimxboot/dualboot/dualboot.lds | 17 |
5 files changed, 554 insertions, 0 deletions
diff --git a/utils/mkimxboot/dualboot/Makefile b/utils/mkimxboot/dualboot/Makefile new file mode 100644 index 0000000000..b80233226a --- /dev/null +++ b/utils/mkimxboot/dualboot/Makefile | |||
@@ -0,0 +1,48 @@ | |||
1 | CC=gcc | ||
2 | LD=ld | ||
3 | OC=objcopy | ||
4 | PREFIX?=arm-elf-eabi- | ||
5 | IMX233_PATH=../../../firmware/target/arm/imx233 | ||
6 | CFLAGS=-mcpu=arm926ej-s -std=gnu99 -I. -I$(IMX233_PATH) -nostdlib -ffreestanding -fomit-frame-pointer -O | ||
7 | # Edit the following variables when adding a new target. | ||
8 | # mkimxboot.c also needs to be edited to refer to these | ||
9 | # To add a new target x you need to: | ||
10 | # 1) add x to the list in TARGETS | ||
11 | # 2) create a variable named OPT_x of the form: | ||
12 | # OPT_x=target specific defines | ||
13 | TARGETS=fuzeplus zenxfi2 zenxfi3 nwze370 nwze360 zenxfistyle | ||
14 | OPT_fuzeplus=-DSANSA_FUZEPLUS -DIMX233_SUBTARGET=3780 | ||
15 | OPT_zenxfi2=-DCREATIVE_ZENXFI2 -DIMX233_SUBTARGET=3780 | ||
16 | OPT_zenxfi3=-DCREATIVE_ZENXFI3 -DIMX233_SUBTARGET=3780 | ||
17 | OPT_nwze370=-DSONY_NWZE370 -DIMX233_SUBTARGET=3780 | ||
18 | OPT_nwze360=-DSONY_NWZE360 -DIMX233_SUBTARGET=3780 | ||
19 | OPT_zenxfistyle=-DCREATIVE_ZENXFISTYLE -DIMX233_SUBTARGET=3780 | ||
20 | |||
21 | BOOTOBJS=$(patsubst %, dualboot_%.o, $(TARGETS)) | ||
22 | BOOTBINS=$(patsubst %, dualboot_%.arm-bin, $(TARGETS)) | ||
23 | BOOTELFS=$(patsubst %, dualboot_%.arm-elf, $(TARGETS)) | ||
24 | |||
25 | all: ../dualboot.h ../dualboot.c $(BOOTELFS) | ||
26 | |||
27 | # Dualboot bootloaders | ||
28 | |||
29 | dualboot_%.o: dualboot.c | ||
30 | $(PREFIX)$(CC) $(CFLAGS) $(OPT_$(@:dualboot_%.o=%)) -c -o $@ $^ | ||
31 | |||
32 | dualboot_%.arm-elf: dualboot_%.o | ||
33 | $(PREFIX)$(LD) $(LDFLAGS) -Tdualboot.lds -o $@ $< | ||
34 | |||
35 | # Rules for the ARM code embedded in mkamsboot - assemble, link, then extract | ||
36 | # the binary code and finally convert to .h for building in mkamsboot | ||
37 | |||
38 | %.arm-bin: %.arm-elf | ||
39 | $(PREFIX)$(OC) -O binary $< $@ | ||
40 | |||
41 | ../dualboot.c ../dualboot.h: $(BOOTBINS) bin2c | ||
42 | ./bin2c ../dualboot $(BOOTBINS) | ||
43 | |||
44 | bin2c: bin2c.c | ||
45 | $(CC) -o bin2c bin2c.c | ||
46 | |||
47 | clean: | ||
48 | rm -f *~ bin2c $(BOOTBINS) $(BOOTOBJS) $(BOOTELFS) | ||
diff --git a/utils/mkimxboot/dualboot/bin2c.c b/utils/mkimxboot/dualboot/bin2c.c new file mode 100644 index 0000000000..b02af88a4d --- /dev/null +++ b/utils/mkimxboot/dualboot/bin2c.c | |||
@@ -0,0 +1,140 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2007 Dave Chapman | ||
11 | * | ||
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. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include <stdio.h> | ||
23 | #include <string.h> | ||
24 | #include <sys/types.h> | ||
25 | #include <sys/stat.h> | ||
26 | #include <unistd.h> | ||
27 | #include <fcntl.h> | ||
28 | #include <stdlib.h> | ||
29 | #include <libgen.h> | ||
30 | |||
31 | #ifndef O_BINARY | ||
32 | #define O_BINARY 0 | ||
33 | #endif | ||
34 | |||
35 | static off_t filesize(int fd) | ||
36 | { | ||
37 | struct stat buf; | ||
38 | |||
39 | fstat(fd,&buf); | ||
40 | return buf.st_size; | ||
41 | } | ||
42 | |||
43 | static void write_cfile(const unsigned char* buf, off_t len, FILE* fp, const char *name) | ||
44 | { | ||
45 | int i; | ||
46 | |||
47 | fprintf(fp,"unsigned char %s[%ld] = {",name,len); | ||
48 | |||
49 | for (i=0;i<len;i++) { | ||
50 | if ((i % 16) == 0) { | ||
51 | fprintf(fp,"\n "); | ||
52 | } | ||
53 | if (i == (len-1)) { | ||
54 | fprintf(fp,"0x%02x",buf[i]); | ||
55 | } else if ((i % 16) == 15) { | ||
56 | fprintf(fp,"0x%02x,",buf[i]); | ||
57 | } else { | ||
58 | fprintf(fp,"0x%02x, ",buf[i]); | ||
59 | } | ||
60 | } | ||
61 | fprintf(fp,"\n};\n"); | ||
62 | } | ||
63 | |||
64 | int main (int argc, char* argv[]) | ||
65 | { | ||
66 | char* cname; | ||
67 | int i; | ||
68 | FILE *cfile, *hfile; | ||
69 | char cfilename[256], hfilename[256]; | ||
70 | |||
71 | if (argc < 3) { | ||
72 | fprintf(stderr,"Usage: bin2c cname file1 [file2 [file3 ...]]\n"); | ||
73 | return 1; | ||
74 | } | ||
75 | |||
76 | cname=argv[1]; | ||
77 | |||
78 | snprintf(cfilename,256,"%s.c",cname); | ||
79 | cfile = fopen(cfilename,"w+"); | ||
80 | if (cfile == NULL) { | ||
81 | fprintf(stderr,"Couldn't open %s\n",cfilename); | ||
82 | return 2; | ||
83 | } | ||
84 | |||
85 | snprintf(hfilename,256,"%s.h",cname); | ||
86 | hfile = fopen(hfilename,"w+"); | ||
87 | if (hfile == NULL) { | ||
88 | fprintf(stderr,"Couldn't open %s\n",hfilename); | ||
89 | fclose(cfile); | ||
90 | return 3; | ||
91 | } | ||
92 | |||
93 | fprintf(cfile,"/* Generated by bin2c */\n\n"); | ||
94 | fprintf(cfile,"#include \"%s\"\n\n", basename(hfilename)); | ||
95 | fprintf(hfile,"/* Generated by bin2c */\n\n"); | ||
96 | |||
97 | for(i=0; i < argc - 2; i++) { | ||
98 | unsigned char* buf; | ||
99 | off_t len; | ||
100 | off_t orig_len; | ||
101 | char *ext; | ||
102 | char *array = argv[2+i]; | ||
103 | |||
104 | int fd = open(array,O_RDONLY|O_BINARY); | ||
105 | if (fd < 0) { | ||
106 | fprintf(stderr,"Can not open %s\n",argv[2+i]); | ||
107 | fclose(cfile); | ||
108 | fclose(hfile); | ||
109 | return 4; | ||
110 | } | ||
111 | |||
112 | orig_len = filesize(fd); | ||
113 | /* pad to 32bit */ | ||
114 | len = (orig_len + 3) & ~3; | ||
115 | |||
116 | buf = malloc(len); | ||
117 | if (read(fd,buf,orig_len) < orig_len) { | ||
118 | fprintf(stderr,"Short read, aborting\n"); | ||
119 | return 5; | ||
120 | } | ||
121 | |||
122 | /* pad to 32bit with zeros */ | ||
123 | if (len > orig_len) | ||
124 | memset(buf+orig_len, 0, len-orig_len); | ||
125 | |||
126 | /* remove file extension */ | ||
127 | ext = strchr (array, '.'); | ||
128 | if (ext != NULL) | ||
129 | *ext = '\0'; | ||
130 | write_cfile (buf, len, cfile, array); | ||
131 | fprintf(hfile,"extern unsigned char %s[%ld];\n",array,len); | ||
132 | |||
133 | close(fd); | ||
134 | } | ||
135 | |||
136 | fclose(cfile); | ||
137 | fclose(hfile); | ||
138 | |||
139 | return 0; | ||
140 | } | ||
diff --git a/utils/mkimxboot/dualboot/config.h b/utils/mkimxboot/dualboot/config.h new file mode 100644 index 0000000000..e9ea8d4a35 --- /dev/null +++ b/utils/mkimxboot/dualboot/config.h | |||
@@ -0,0 +1,26 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2013 by Amaury Pouly | ||
11 | * | ||
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. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | /** mostly empty, used by register files and dualboot */ | ||
23 | #define COMPILE_DUALBOOT_STUB | ||
24 | |||
25 | /* obviously we have the dualboot stub! */ | ||
26 | #define HAVE_DUALBOOT_STUB | ||
diff --git a/utils/mkimxboot/dualboot/dualboot.c b/utils/mkimxboot/dualboot/dualboot.c new file mode 100644 index 0000000000..77b816bf76 --- /dev/null +++ b/utils/mkimxboot/dualboot/dualboot.c | |||
@@ -0,0 +1,323 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2013 by Amaury Pouly | ||
11 | * | ||
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. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #include "regs/pinctrl.h" | ||
22 | #include "regs/power.h" | ||
23 | #include "regs/lradc.h" | ||
24 | #include "regs/digctl.h" | ||
25 | #include "regs/clkctrl.h" | ||
26 | |||
27 | #define BOOT_ROM_CONTINUE 0 /* continue boot */ | ||
28 | #define BOOT_ROM_SECTION 1 /* switch to new section *result_id */ | ||
29 | |||
30 | #define BOOT_ARG_CHARGE ('c' | 'h' << 8 | 'r' << 16 | 'g' << 24) | ||
31 | /** additional defines */ | ||
32 | #define BP_LRADC_CTRL4_LRADCxSELECT(x) (4 * (x)) | ||
33 | #define BM_LRADC_CTRL4_LRADCxSELECT(x) (0xf << (4 * (x))) | ||
34 | |||
35 | typedef unsigned long uint32_t; | ||
36 | |||
37 | /* we include the dualboot rtc code directly */ | ||
38 | #include "dualboot-imx233.h" | ||
39 | #include "dualboot-imx233.c" | ||
40 | |||
41 | // target specific boot context | ||
42 | enum context_t | ||
43 | { | ||
44 | CONTEXT_NORMAL, /* normal boot */ | ||
45 | CONTEXT_USB, /* USB plugged boot */ | ||
46 | CONTEXT_RTC, /* RTC wake up boot */ | ||
47 | }; | ||
48 | // target specific boot decision | ||
49 | enum boot_t | ||
50 | { | ||
51 | BOOT_STOP, /* power down */ | ||
52 | BOOT_ROCK, /* boot to Rockbox */ | ||
53 | BOOT_OF, /* boot to OF */ | ||
54 | }; | ||
55 | |||
56 | /** | ||
57 | * Helper functions | ||
58 | */ | ||
59 | |||
60 | static inline int __attribute__((always_inline)) read_gpio(int bank, int pin) | ||
61 | { | ||
62 | return (HW_PINCTRL_DINn(bank) >> pin) & 1; | ||
63 | } | ||
64 | |||
65 | static inline int __attribute__((always_inline)) read_pswitch(void) | ||
66 | { | ||
67 | #if IMX233_SUBTARGET >= 3700 | ||
68 | return BF_RD(POWER_STS, PSWITCH); | ||
69 | #else | ||
70 | return BF_RD(DIGCTL_STATUS, PSWITCH); | ||
71 | #endif | ||
72 | } | ||
73 | |||
74 | /* only works for channels <=7, always divide by 2, never accumulates */ | ||
75 | static inline void __attribute__((always_inline)) setup_lradc(int src) | ||
76 | { | ||
77 | BF_CLR(LRADC_CTRL0, SFTRST); | ||
78 | BF_CLR(LRADC_CTRL0, CLKGATE); | ||
79 | #if IMX233_SUBTARGET >= 3700 | ||
80 | HW_LRADC_CTRL4_CLR = BM_LRADC_CTRL4_LRADCxSELECT(src); | ||
81 | HW_LRADC_CTRL4_SET = src << BP_LRADC_CTRL4_LRADCxSELECT(src); | ||
82 | #endif | ||
83 | HW_LRADC_CHn_CLR(src) = BM_OR(LRADC_CHn, NUM_SAMPLES, ACCUMULATE); | ||
84 | BF_WR(LRADC_CTRL2_SET, DIVIDE_BY_TWO(1 << src)); | ||
85 | } | ||
86 | |||
87 | #define BP_LRADC_CTRL1_LRADCx_IRQ(x) (x) | ||
88 | #define BM_LRADC_CTRL1_LRADCx_IRQ(x) (1 << (x)) | ||
89 | |||
90 | static inline int __attribute__((always_inline)) read_lradc(int src) | ||
91 | { | ||
92 | BF_CLR(LRADC_CTRL1, LRADCx_IRQ(src)); | ||
93 | BF_WR(LRADC_CTRL0_SET, SCHEDULE(1 << src)); | ||
94 | while(!BF_RD(LRADC_CTRL1, LRADCx_IRQ(src))); | ||
95 | return BF_RD(LRADC_CHn(src), VALUE); | ||
96 | } | ||
97 | |||
98 | static inline void __attribute__((noreturn)) power_down() | ||
99 | { | ||
100 | #ifdef SANSA_FUZEPLUS | ||
101 | /* B0P09: this pin seems to be important to shutdown the hardware properly */ | ||
102 | HW_PINCTRL_MUXSELn_SET(0) = 3 << 18; | ||
103 | HW_PINCTRL_DOEn(0) = 1 << 9; | ||
104 | HW_PINCTRL_DOUTn(0) = 1 << 9; | ||
105 | #endif | ||
106 | /* power down */ | ||
107 | HW_POWER_RESET = BM_OR(POWER_RESET, UNLOCK, PWD); | ||
108 | while(1); | ||
109 | } | ||
110 | |||
111 | /** | ||
112 | * Boot decision functions | ||
113 | */ | ||
114 | |||
115 | #if defined(SANSA_FUZEPLUS) | ||
116 | static enum boot_t boot_decision(enum context_t context) | ||
117 | { | ||
118 | /* if volume down is hold, boot to OF */ | ||
119 | if(!read_gpio(1, 30)) | ||
120 | return BOOT_OF; | ||
121 | /* on normal boot, make sure power button is hold long enough */ | ||
122 | if(context == CONTEXT_NORMAL) | ||
123 | { | ||
124 | // monitor PSWITCH | ||
125 | int count = 0; | ||
126 | for(int i = 0; i < 550000; i++) | ||
127 | if(read_pswitch() == 1) | ||
128 | count++; | ||
129 | if(count < 400000) | ||
130 | return BOOT_STOP; | ||
131 | } | ||
132 | return BOOT_ROCK; | ||
133 | } | ||
134 | #elif defined(CREATIVE_ZENXFI2) | ||
135 | static int boot_decision(int context) | ||
136 | { | ||
137 | /* We are lacking buttons on the Zen X-Fi2 because on USB, the select button | ||
138 | * enters recovery mode ! So we can only use power but power is used to power up | ||
139 | * on normal boots and then select is free ! Thus use a non-uniform scheme: | ||
140 | * - normal boot/RTC: | ||
141 | * - no key: Rockbox | ||
142 | * - select: OF | ||
143 | * - USB boot: | ||
144 | * - no key: Rockbox | ||
145 | * - power: OF | ||
146 | */ | ||
147 | if(context == CONTEXT_USB) | ||
148 | return read_pswitch() == 1 ? BOOT_OF : BOOT_ROCK; | ||
149 | else | ||
150 | return !read_gpio(0, 14) ? BOOT_OF : BOOT_ROCK; | ||
151 | } | ||
152 | #elif defined(CREATIVE_ZENXFI3) | ||
153 | static int boot_decision(int context) | ||
154 | { | ||
155 | /* if volume down is hold, boot to OF */ | ||
156 | return !read_gpio(2, 7) ? BOOT_OF : BOOT_ROCK; | ||
157 | } | ||
158 | #elif defined(SONY_NWZE360) || defined(SONY_NWZE370) | ||
159 | static int local_decision(void) | ||
160 | { | ||
161 | /* read keys and pswitch */ | ||
162 | int val = read_lradc(0); | ||
163 | /* if hold is on, power off | ||
164 | * if back is pressed, boot to OF | ||
165 | * if play is pressed, boot RB | ||
166 | * otherwise power off */ | ||
167 | #ifdef SONY_NWZE360 | ||
168 | if(read_gpio(0, 9) == 0) | ||
169 | return BOOT_STOP; | ||
170 | #endif | ||
171 | if(val >= 1050 && val < 1150) | ||
172 | return BOOT_OF; | ||
173 | if(val >= 1420 && val < 1520) | ||
174 | return BOOT_ROCK; | ||
175 | return BOOT_STOP; | ||
176 | } | ||
177 | |||
178 | static int boot_decision(int context) | ||
179 | { | ||
180 | setup_lradc(0); // setup LRADC channel 0 to read keys | ||
181 | #ifdef SONY_NWZE360 | ||
182 | HW_PINCTRL_PULLn_SET(0) = 1 << 9; // enable pullup on hold key (B0P09) | ||
183 | #endif | ||
184 | /* make a decision */ | ||
185 | int decision = local_decision(); | ||
186 | /* in USB or alarm context, stick to it */ | ||
187 | if(context == CONTEXT_USB || context == CONTEXT_RTC) | ||
188 | { | ||
189 | /* never power down so replace power off decision by rockbox */ | ||
190 | return decision == BOOT_STOP ? BOOT_ROCK : decision; | ||
191 | } | ||
192 | /* otherwise start a 1 second timeout. Any decision change | ||
193 | * will result in power down */ | ||
194 | uint32_t tmo = HW_DIGCTL_MICROSECONDS + 1000000; | ||
195 | while(HW_DIGCTL_MICROSECONDS < tmo) | ||
196 | { | ||
197 | int new_dec = local_decision(); | ||
198 | if(new_dec != decision) | ||
199 | return BOOT_STOP; | ||
200 | } | ||
201 | return decision; | ||
202 | } | ||
203 | #elif defined(CREATIVE_ZENXFISTYLE) | ||
204 | static int boot_decision(int context) | ||
205 | { | ||
206 | setup_lradc(2); // setup LRADC channel 2 to read keys | ||
207 | /* make a decision */ | ||
208 | int val = read_lradc(2); | ||
209 | /* boot to OF if left is hold | ||
210 | * NOTE: VDDIO is set to 3.1V initially and the resistor ladder is wired to | ||
211 | * VDDIO so these values are not the same as in the main binary which is | ||
212 | * calibrated for VDDIO=3.3V */ | ||
213 | if(val >= 815 && val < 915) | ||
214 | return BOOT_OF; | ||
215 | return BOOT_ROCK; | ||
216 | } | ||
217 | #else | ||
218 | #warning You should define a target specific boot decision function | ||
219 | static int boot_decision(int context) | ||
220 | { | ||
221 | return BOOT_ROCK; | ||
222 | } | ||
223 | #endif | ||
224 | |||
225 | /** | ||
226 | * Context functions | ||
227 | */ | ||
228 | static inline enum context_t get_context(void) | ||
229 | { | ||
230 | #if IMX233_SUBTARGET >= 3780 | ||
231 | /* On the imx233 it's easy because we know the power up source */ | ||
232 | unsigned pwrup_src = BF_RD(POWER_STS, PWRUP_SOURCE); | ||
233 | if(pwrup_src & (1 << 5)) | ||
234 | return CONTEXT_USB; | ||
235 | else if(pwrup_src & (1 << 4)) | ||
236 | return CONTEXT_RTC; | ||
237 | else | ||
238 | return CONTEXT_NORMAL; | ||
239 | #else | ||
240 | /* On the other targets, we need to poke a few more registers */ | ||
241 | #endif | ||
242 | } | ||
243 | |||
244 | /** | ||
245 | * Charging function | ||
246 | */ | ||
247 | static inline void do_charge(void) | ||
248 | { | ||
249 | BF_CLR(LRADC_CTRL0, SFTRST); | ||
250 | BF_CLR(LRADC_CTRL0, CLKGATE); | ||
251 | BF_WR(LRADC_DELAYn(0), TRIGGER_LRADCS(0x80)); | ||
252 | BF_WR(LRADC_DELAYn(0), TRIGGER_DELAYS(0x1)); | ||
253 | BF_WR(LRADC_DELAYn(0), DELAY(200)); | ||
254 | BF_SET(LRADC_DELAYn(0), KICK); | ||
255 | BF_SET(LRADC_CONVERSION, AUTOMATIC); | ||
256 | BF_WR(LRADC_CONVERSION, SCALE_FACTOR_V(LI_ION)); | ||
257 | BF_WR(POWER_CHARGE, STOP_ILIMIT(1)); | ||
258 | BF_WR(POWER_CHARGE, BATTCHRG_I(0x10)); | ||
259 | BF_CLR(POWER_CHARGE, PWD_BATTCHRG); | ||
260 | #if IMX233_SUBTARGET >= 3780 | ||
261 | BF_WR(POWER_DCDC4P2, ENABLE_4P2(1)); | ||
262 | BF_CLR(POWER_5VCTRL, PWD_CHARGE_4P2); | ||
263 | BF_WR(POWER_5VCTRL, CHARGE_4P2_ILIMIT(0x10)); | ||
264 | #endif | ||
265 | while(1) | ||
266 | { | ||
267 | BF_WR(CLKCTRL_CPU, INTERRUPT_WAIT(1)); | ||
268 | asm volatile ( | ||
269 | "mcr p15, 0, %0, c7, c0, 4 \n" /* Wait for interrupt */ | ||
270 | "nop\n" /* Datasheet unclear: "The lr sent to handler points here after RTI"*/ | ||
271 | "nop\n" | ||
272 | : : "r"(0) | ||
273 | ); | ||
274 | } | ||
275 | } | ||
276 | |||
277 | static void set_updater_bits(void) | ||
278 | { | ||
279 | /* The OF will continue to updater if we clear 18 of PERSISTENT1. | ||
280 | * See dualboot-imx233.c in firmware/ for more explanation */ | ||
281 | HW_RTC_PERSISTENT1_CLR = 1 << 18; | ||
282 | } | ||
283 | |||
284 | int main(uint32_t arg, uint32_t *result_id) | ||
285 | { | ||
286 | if(arg == BOOT_ARG_CHARGE) | ||
287 | do_charge(); | ||
288 | /* tell rockbox that we can handle boot mode */ | ||
289 | imx233_dualboot_set_field(DUALBOOT_CAP_BOOT, 1); | ||
290 | /* if we were asked to boot in a special mode, do so */ | ||
291 | unsigned boot_mode = imx233_dualboot_get_field(DUALBOOT_BOOT); | ||
292 | /* clear boot mode to avoid any loop */ | ||
293 | imx233_dualboot_set_field(DUALBOOT_BOOT, IMX233_BOOT_NORMAL); | ||
294 | switch(boot_mode) | ||
295 | { | ||
296 | case IMX233_BOOT_UPDATER: | ||
297 | set_updater_bits(); | ||
298 | /* fallthrough */ | ||
299 | case IMX233_BOOT_OF: | ||
300 | /* continue booting */ | ||
301 | return BOOT_ROM_CONTINUE; | ||
302 | case IMX233_BOOT_NORMAL: | ||
303 | default: | ||
304 | break; | ||
305 | } | ||
306 | /* normal boot */ | ||
307 | switch(boot_decision(get_context())) | ||
308 | { | ||
309 | case BOOT_ROCK: | ||
310 | *result_id = arg; | ||
311 | return BOOT_ROM_SECTION; | ||
312 | case BOOT_OF: | ||
313 | return BOOT_ROM_CONTINUE; | ||
314 | case BOOT_STOP: | ||
315 | default: | ||
316 | power_down(); | ||
317 | } | ||
318 | } | ||
319 | |||
320 | int __attribute__((section(".start"))) start(uint32_t arg, uint32_t *result_id) | ||
321 | { | ||
322 | return main(arg, result_id); | ||
323 | } | ||
diff --git a/utils/mkimxboot/dualboot/dualboot.lds b/utils/mkimxboot/dualboot/dualboot.lds new file mode 100644 index 0000000000..09739aee15 --- /dev/null +++ b/utils/mkimxboot/dualboot/dualboot.lds | |||
@@ -0,0 +1,17 @@ | |||
1 | ENTRY(start) | ||
2 | OUTPUT_FORMAT(elf32-littlearm) | ||
3 | OUTPUT_ARCH(arm) | ||
4 | |||
5 | MEMORY | ||
6 | { | ||
7 | OCRAM : ORIGIN = 0, LENGTH = 0x8000 | ||
8 | } | ||
9 | |||
10 | SECTIONS | ||
11 | { | ||
12 | .text 0 : | ||
13 | { | ||
14 | *(.start*) | ||
15 | *(.text*) | ||
16 | } > OCRAM | ||
17 | } | ||