| @@ -1,637 +1,638 @@ | | | @@ -1,637 +1,638 @@ |
1 | /*- | | 1 | /*- |
2 | * Copyright (c) 2012 The NetBSD Foundation, Inc. | | 2 | * Copyright (c) 2012 The NetBSD Foundation, Inc. |
3 | * All rights reserved. | | 3 | * All rights reserved. |
4 | * | | 4 | * |
5 | * This code is derived from software contributed to The NetBSD Foundation | | 5 | * This code is derived from software contributed to The NetBSD Foundation |
6 | * by Paul Fleischer <paul@xpg.dk> | | 6 | * by Paul Fleischer <paul@xpg.dk> |
7 | * | | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | | 8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions | | 9 | * modification, are permitted provided that the following conditions |
10 | * are met: | | 10 | * are met: |
11 | * 1. Redistributions of source code must retain the above copyright | | 11 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. | | 12 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright | | 13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the | | 14 | * notice, this list of conditions and the following disclaimer in the |
15 | * documentation and/or other materials provided with the distribution. | | 15 | * documentation and/or other materials provided with the distribution. |
16 | * | | 16 | * |
17 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 17 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
18 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 18 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
19 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 19 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
20 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 20 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 21 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
27 | * POSSIBILITY OF SUCH DAMAGE. | | 27 | * POSSIBILITY OF SUCH DAMAGE. |
28 | */ | | 28 | */ |
29 | #include <sys/types.h> | | 29 | #include <sys/types.h> |
30 | | | 30 | |
31 | #include <arm/armreg.h> | | 31 | #include <arm/armreg.h> |
32 | #include <arm/s3c2xx0/s3c2440reg.h> | | 32 | #include <arm/s3c2xx0/s3c2440reg.h> |
33 | | | 33 | |
34 | #include <netinet/in.h> | | 34 | #include <netinet/in.h> |
35 | #include <netinet/in_systm.h> | | 35 | #include <netinet/in_systm.h> |
36 | | | 36 | |
37 | #include <lib/libkern/libkern.h> | | 37 | #include <lib/libkern/libkern.h> |
38 | #include <lib/libsa/stand.h> | | 38 | #include <lib/libsa/stand.h> |
39 | #include <lib/libsa/loadfile.h> | | 39 | #include <lib/libsa/loadfile.h> |
40 | #include <lib/libsa/iodesc.h> | | 40 | #include <lib/libsa/iodesc.h> |
41 | | | 41 | |
42 | #include <arch/evbarm/mini2440/mini2440_bootinfo.h> | | 42 | #include <arch/evbarm/mini2440/mini2440_bootinfo.h> |
43 | | | 43 | |
44 | #define CSR_READ(reg) \ | | 44 | #define CSR_READ(reg) \ |
45 | *(volatile uint32_t *)(reg) | | 45 | *(volatile uint32_t *)(reg) |
46 | #define CSR_WRITE(reg, val) do { \ | | 46 | #define CSR_WRITE(reg, val) do { \ |
47 | *(volatile uint32_t *)((reg)) = val; \ | | 47 | *(volatile uint32_t *)((reg)) = val; \ |
48 | } while (0) | | 48 | } while (0) |
49 | | | 49 | |
50 | #define UART_BAUDRATE 115200 | | 50 | #define UART_BAUDRATE 115200 |
51 | #define S3C2XX0_XTAL_CLK 12000000 | | 51 | #define S3C2XX0_XTAL_CLK 12000000 |
52 | #define BOOTINFO_ADDR 0x31500000 | | 52 | #define BOOTINFO_ADDR 0x31500000 |
53 | | | 53 | |
54 | /* Macros to turn on/off LEDs. Numbering is 1-4. */ | | 54 | /* Macros to turn on/off LEDs. Numbering is 1-4. */ |
55 | #define LED_REG (volatile uint16_t*)(S3C2440_GPIO_BASE+GPIO_PBDAT) | | 55 | #define LED_REG (volatile uint16_t*)(S3C2440_GPIO_BASE+GPIO_PBDAT) |
56 | #define CLEAR_LEDS() *LED_REG = *LED_REG | 0x1e0 | | 56 | #define CLEAR_LEDS() *LED_REG = *LED_REG | 0x1e0 |
57 | #define LED_ON(led) *LED_REG = *LED_REG & ( ~(1<<(led+4)) & 0x1E0 ) | | 57 | #define LED_ON(led) *LED_REG = *LED_REG & ( ~(1<<(led+4)) & 0x1E0 ) |
58 | #define LED_OFF(led) *LED_REG = *LED_REG | ( ~(1<<(led+4)) & 0x1E0 ) | | 58 | #define LED_OFF(led) *LED_REG = *LED_REG | ( ~(1<<(led+4)) & 0x1E0 ) |
59 | | | 59 | |
60 | /* Local variables */ | | 60 | /* Local variables */ |
61 | static time_t wallclock = 0; | | 61 | static time_t wallclock = 0; |
62 | static uint32_t timer_inc_rate; | | 62 | static uint32_t timer_inc_rate; |
63 | void *bootinfo; | | 63 | void *bootinfo; |
64 | int bi_size; | | 64 | int bi_size; |
65 | char *bi_next; | | 65 | char *bi_next; |
66 | | | 66 | |
67 | #define STR_EXPAND(tok) #tok | | 67 | #define STR_EXPAND(tok) #tok |
68 | #define STR(tok) STR_EXPAND(tok) | | 68 | #define STR(tok) STR_EXPAND(tok) |
69 | | | 69 | |
70 | #if defined(DEFAULT_BOOTFILE) | | 70 | #if defined(DEFAULT_BOOTFILE) |
71 | static char *default_boot=STR(DEFAULT_BOOTFILE); | | 71 | static char *default_boot=STR(DEFAULT_BOOTFILE); |
72 | #else | | 72 | #else |
73 | static char *default_boot="net:"; | | 73 | static char *default_boot="net:"; |
74 | #endif | | 74 | #endif |
75 | | | 75 | |
76 | time_t getsecs(); | | 76 | time_t getsecs(); |
77 | time_t getusecs(); | | 77 | time_t getusecs(); |
78 | | | 78 | |
79 | /* Local functions */ | | 79 | /* Local functions */ |
80 | static void s3c24x0_clock_freq2(vaddr_t clkman_base, int *fclk, int *hclk, | | 80 | static void s3c24x0_clock_freq2(vaddr_t clkman_base, int *fclk, int *hclk, |
81 | int *pclk); | | 81 | int *pclk); |
82 | static void uart_init(uint32_t pclk); | | 82 | static void uart_init(uint32_t pclk); |
83 | static void time_init(uint32_t pclk); | | 83 | static void time_init(uint32_t pclk); |
84 | static void bi_init(void *addr); | | 84 | static void bi_init(void *addr); |
85 | static void bi_add(void *new, int type, int size); | | 85 | static void bi_add(void *new, int type, int size); |
86 | static void parse_mac_address(const char *str, uint8_t *enaddr); | | 86 | static void parse_mac_address(const char *str, uint8_t *enaddr); |
87 | static void brdsetup(void); | | 87 | static void brdsetup(void); |
88 | static void iomux(int, const char *); | | 88 | static void iomux(int, const char *); |
89 | | | 89 | |
90 | extern void* dm9k_init(unsigned int tag, void *macaddr); | | 90 | extern void* dm9k_init(unsigned int tag, void *macaddr); |
91 | | | 91 | |
92 | /* External variables */ | | 92 | /* External variables */ |
93 | extern char bootprog_name[], bootprog_rev[]; | | 93 | extern char bootprog_name[], bootprog_rev[]; |
94 | | | 94 | |
95 | /* External functions */ | | 95 | /* External functions */ |
96 | extern void netif_match(unsigned int tag, uint8_t *macaddr); | | 96 | extern void netif_match(unsigned int tag, uint8_t *macaddr); |
97 | /* extern int sdif_init(unsigned int tag);*/ | | 97 | /* extern int sdif_init(unsigned int tag);*/ |
98 | | | 98 | |
99 | /* Global variables */ | | 99 | /* Global variables */ |
100 | uint32_t socmodel; | | 100 | uint32_t socmodel; |
101 | int pclk; | | 101 | int pclk; |
102 | struct btinfo_rootdevice bi_rdev; | | 102 | struct btinfo_rootdevice bi_rdev; |
103 | | | 103 | |
104 | /* This is not very flexible, as only one net device is allowed */ | | 104 | /* This is not very flexible, as only one net device is allowed */ |
105 | struct btinfo_net bi_net; | | 105 | struct btinfo_net bi_net; |
106 | | | 106 | |
107 | struct btinfo_bootpath bi_path; | | 107 | struct btinfo_bootpath bi_path; |
108 | | | 108 | |
109 | void | | 109 | void |
110 | main(int argc, char *argv[]) | | 110 | main(int argc, char *argv[]) |
111 | { | | 111 | { |
112 | int fclk, hclk; | | 112 | int fclk, hclk; |
113 | int fd; | | 113 | int fd; |
114 | unsigned long marks[MARK_MAX]; | | 114 | unsigned long marks[MARK_MAX]; |
115 | unsigned char hdr[0x26]; | | 115 | unsigned char hdr[0x26]; |
116 | void (*entry)(void*); | | 116 | void (*entry)(void*); |
117 | unsigned elfpriv; | | 117 | unsigned elfpriv; |
118 | char *bootfile; | | 118 | char *bootfile; |
119 | char *bf; | | 119 | char *bf; |
120 | bool kernel_loaded; | | 120 | bool kernel_loaded; |
121 | uint8_t enaddr[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | | 121 | uint8_t enaddr[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; |
122 | | | 122 | |
123 | socmodel = CSR_READ(S3C2440_GPIO_BASE + GPIO_GSTATUS1); | | 123 | socmodel = CSR_READ(S3C2440_GPIO_BASE + GPIO_GSTATUS1); |
124 | | | 124 | |
125 | brdsetup(); | | 125 | brdsetup(); |
126 | | | 126 | |
127 | /* Give some indication that main() has been reached */ | | 127 | /* Give some indication that main() has been reached */ |
128 | CLEAR_LEDS(); | | 128 | CLEAR_LEDS(); |
129 | LED_ON(4); | | 129 | LED_ON(4); |
130 | | | 130 | |
131 | /* Next, we setup the clock of the S3C2440 such that we are not | | 131 | /* Next, we setup the clock of the S3C2440 such that we are not |
132 | dependent on any other bootloader in this regard. | | 132 | dependent on any other bootloader in this regard. |
133 | Target FCLK is 405MHz, and we assume an input crystal of 12MHz | | 133 | Target FCLK is 405MHz, and we assume an input crystal of 12MHz |
134 | */ | | 134 | */ |
135 | *(volatile uint32_t*)(S3C2440_CLKMAN_BASE+CLKMAN_MPLLCON) = | | 135 | *(volatile uint32_t*)(S3C2440_CLKMAN_BASE+CLKMAN_MPLLCON) = |
136 | ((0x7F << PLLCON_MDIV_SHIFT) & PLLCON_MDIV_MASK) | | | 136 | ((0x7F << PLLCON_MDIV_SHIFT) & PLLCON_MDIV_MASK) | |
137 | ((2 << PLLCON_PDIV_SHIFT) & PLLCON_PDIV_MASK) | | | 137 | ((2 << PLLCON_PDIV_SHIFT) & PLLCON_PDIV_MASK) | |
138 | ((1 << PLLCON_SDIV_SHIFT) & PLLCON_SDIV_MASK); | | 138 | ((1 << PLLCON_SDIV_SHIFT) & PLLCON_SDIV_MASK); |
139 | *(volatile uint32_t*)(S3C2440_CLKMAN_BASE+CLKMAN_UPLLCON) = | | 139 | *(volatile uint32_t*)(S3C2440_CLKMAN_BASE+CLKMAN_UPLLCON) = |
140 | ((0x38 << PLLCON_MDIV_SHIFT) & PLLCON_MDIV_MASK) | | | 140 | ((0x38 << PLLCON_MDIV_SHIFT) & PLLCON_MDIV_MASK) | |
141 | ((2 << PLLCON_PDIV_SHIFT) & PLLCON_PDIV_MASK) | | | 141 | ((2 << PLLCON_PDIV_SHIFT) & PLLCON_PDIV_MASK) | |
142 | ((2 << PLLCON_SDIV_SHIFT) & PLLCON_SDIV_MASK); | | 142 | ((2 << PLLCON_SDIV_SHIFT) & PLLCON_SDIV_MASK); |
143 | | | 143 | |
144 | LED_ON(1); | | 144 | LED_ON(1); |
145 | | | 145 | |
146 | s3c24x0_clock_freq2(S3C2440_CLKMAN_BASE, &fclk, &hclk, &pclk); | | 146 | s3c24x0_clock_freq2(S3C2440_CLKMAN_BASE, &fclk, &hclk, &pclk); |
147 | | | 147 | |
148 | uart_init(pclk); | | 148 | uart_init(pclk); |
149 | time_init(pclk); | | 149 | time_init(pclk); |
150 | | | 150 | |
151 | /* Let the user know we are alive */ | | 151 | /* Let the user know we are alive */ |
152 | printf("\n"); | | 152 | printf("\n"); |
153 | printf(">> %s boot2440, revision %s\n", bootprog_name, bootprog_rev); | | 153 | printf(">> %s boot2440, revision %s\n", bootprog_name, bootprog_rev); |
154 | printf("SoC model:"); | | 154 | printf("SoC model:"); |
155 | switch (socmodel) { | | 155 | switch (socmodel) { |
156 | case 0x32440000: | | 156 | case 0x32440000: |
157 | printf(" S3C2440"); break; | | 157 | printf(" S3C2440"); break; |
158 | case 0x32440001: | | 158 | case 0x32440001: |
159 | printf(" S3C2440A"); break; | | 159 | printf(" S3C2440A"); break; |
160 | } | | 160 | } |
161 | printf(" (chipid %08x)\n", socmodel); | | 161 | printf(" (chipid %08x)\n", socmodel); |
162 | | | 162 | |
163 | bootinfo = (void*) BOOTINFO_ADDR; | | 163 | bootinfo = (void*) BOOTINFO_ADDR; |
164 | bi_init(bootinfo); | | 164 | bi_init(bootinfo); |
165 | | | 165 | |
166 | bi_net.devname[0] = 0; | | 166 | bi_net.devname[0] = 0; |
167 | bi_path.bootpath[0] = 0; | | 167 | bi_path.bootpath[0] = 0; |
168 | | | 168 | |
169 | /* Try to get boot arguments from any previous boot-loader */ | | 169 | /* Try to get boot arguments from any previous boot-loader */ |
170 | { | | 170 | { |
171 | struct btinfo_bootstring ba; | | 171 | struct btinfo_bootstring ba; |
172 | int j, i; | | 172 | int j, i; |
173 | | | 173 | |
174 | j = 0; | | 174 | j = 0; |
175 | for (i = 0; i < argc; i++) { | | 175 | for (i = 0; i < argc; i++) { |
176 | if (j == MAX_BOOT_STRING-1) { | | 176 | if (j == MAX_BOOT_STRING-1) { |
177 | ba.bootstring[j] = '\0'; | | 177 | ba.bootstring[j] = '\0'; |
178 | continue; | | 178 | continue; |
179 | } | | 179 | } |
180 | if (strncmp(argv[i], "mac=", 4) == 0) { | | 180 | if (strncmp(argv[i], "mac=", 4) == 0) { |
181 | parse_mac_address(argv[i]+4, enaddr); | | 181 | parse_mac_address(argv[i]+4, enaddr); |
182 | } else { | | 182 | } else { |
183 | if (j != 0) | | 183 | if (j != 0) |
184 | ba.bootstring[j++] = ' '; | | 184 | ba.bootstring[j++] = ' '; |
185 | | | 185 | |
186 | strncpy(ba.bootstring+j, argv[i], MAX_BOOT_STRING-j); | | 186 | strncpy(ba.bootstring+j, argv[i], MAX_BOOT_STRING-j); |
187 | j += strlen(argv[i]); | | 187 | j += strlen(argv[i]); |
188 | } | | 188 | } |
189 | } | | 189 | } |
190 | bi_add(&ba, BTINFO_BOOTSTRING, sizeof(ba)); | | 190 | bi_add(&ba, BTINFO_BOOTSTRING, sizeof(ba)); |
191 | } | | 191 | } |
192 | | | 192 | |
193 | LED_ON(3); | | 193 | LED_ON(3); |
194 | | | 194 | |
195 | if (argc > 1) { | | 195 | if (argc > 1) { |
196 | bf = argv[argc-1]; | | 196 | bf = argv[argc-1]; |
197 | } else { | | 197 | } else { |
198 | bf = default_boot; | | 198 | bf = default_boot; |
199 | } | | 199 | } |
200 | | | 200 | |
201 | /* Detect networking devices */ | | 201 | /* Detect networking devices */ |
202 | netif_match(0, enaddr); | | 202 | netif_match(0, enaddr); |
203 | | | 203 | |
204 | kernel_loaded = FALSE; | | 204 | kernel_loaded = FALSE; |
205 | do { | | 205 | do { |
206 | bootfile = strsep(&bf, ";"); | | 206 | bootfile = strsep(&bf, ";"); |
207 | printf("Trying \"%s\"...\n", bootfile); | | 207 | printf("Trying \"%s\"...\n", bootfile); |
208 | fd = open(bootfile, 0); | | 208 | fd = open(bootfile, 0); |
209 | if (fd < 0) { | | 209 | if (fd < 0) { |
210 | printf("Failed: %d\n", errno); | | 210 | printf("Failed: %d\n", errno); |
211 | close(fd); | | 211 | close(fd); |
212 | continue; | | 212 | continue; |
213 | } | | 213 | } |
214 | | | 214 | |
215 | if (fdloadfile(fd, marks, LOAD_ALL) == 0) { | | 215 | if (fdloadfile(fd, marks, LOAD_ALL) == 0) { |
216 | kernel_loaded = TRUE; | | 216 | kernel_loaded = TRUE; |
217 | break; | | 217 | break; |
218 | } | | 218 | } |
219 | } while(bf != NULL); | | 219 | } while(bf != NULL); |
220 | | | 220 | |
221 | if (!kernel_loaded) { | | 221 | if (!kernel_loaded) { |
222 | panic("Failed to load kernel\n"); | | 222 | panic("Failed to load kernel\n"); |
223 | _rtt(); | | 223 | _rtt(); |
224 | } | | 224 | } |
225 | | | 225 | |
226 | #if 1 | | 226 | #if 1 |
227 | /* Set MAC address of the 'dme' net device, if | | 227 | /* Set MAC address of the 'dme' net device, if |
228 | * it isn't set already */ | | 228 | * it isn't set already */ |
229 | if (bi_net.devname[0] == 0) { | | 229 | if (bi_net.devname[0] == 0) { |
230 | uint8_t en[6] = {DM9000MAC}; | | 230 | uint8_t en[6] = {DM9000MAC}; |
231 | snprintf(bi_net.devname, sizeof(bi_net.devname), "dme"); | | 231 | snprintf(bi_net.devname, sizeof(bi_net.devname), "dme"); |
232 | bi_net.cookie = 0; | | 232 | bi_net.cookie = 0; |
233 | | | 233 | |
234 | memcpy(bi_net.mac_address, en, sizeof(bi_net.mac_address)); | | 234 | memcpy(bi_net.mac_address, en, sizeof(bi_net.mac_address)); |
235 | } | | 235 | } |
236 | #endif | | 236 | #endif |
237 | /* | | 237 | /* |
238 | * ARM ELF header has a distinctive value in "private flags" | | 238 | * ARM ELF header has a distinctive value in "private flags" |
239 | * field of offset [0x24:25]; | | 239 | * field of offset [0x24:25]; |
240 | * - NetBSD 02 06 | | 240 | * - NetBSD 02 06 |
241 | * - Linux 02 00 (2.4) or 02 02 (2.6) | | 241 | * - Linux 02 00 (2.4) or 02 02 (2.6) |
242 | */ | | 242 | */ |
243 | lseek(fd, (off_t)0, SEEK_SET); | | 243 | lseek(fd, (off_t)0, SEEK_SET); |
244 | read(fd, &hdr, sizeof(hdr)); | | 244 | read(fd, &hdr, sizeof(hdr)); |
245 | memcpy(&elfpriv, &hdr[0x24], sizeof(elfpriv)); | | 245 | memcpy(&elfpriv, &hdr[0x24], sizeof(elfpriv)); |
246 | | | 246 | |
247 | entry = (void *)marks[MARK_ENTRY]; | | 247 | entry = (void *)marks[MARK_ENTRY]; |
248 | if (elfpriv == 0x0602) { | | 248 | if (elfpriv == 0x0602) { |
249 | struct btinfo_symtab bi_syms; | | 249 | struct btinfo_symtab bi_syms; |
250 | | | 250 | |
251 | bi_syms.nsym = marks[MARK_NSYM]; | | 251 | bi_syms.nsym = marks[MARK_NSYM]; |
252 | bi_syms.ssym = (void*)marks[MARK_SYM]; | | 252 | bi_syms.ssym = (void*)marks[MARK_SYM]; |
253 | bi_syms.esym = (void*)marks[MARK_END]; | | 253 | bi_syms.esym = (void*)marks[MARK_END]; |
254 | bi_add(&bi_syms, BTINFO_SYMTAB, sizeof(bi_syms)); | | 254 | bi_add(&bi_syms, BTINFO_SYMTAB, sizeof(bi_syms)); |
255 | if (bi_path.bootpath[0] != 0) | | 255 | if (bi_path.bootpath[0] != 0) |
256 | bi_add(&bi_path, BTINFO_BOOTPATH, sizeof(bi_path)); | | 256 | bi_add(&bi_path, BTINFO_BOOTPATH, sizeof(bi_path)); |
257 | bi_add(&bi_rdev, BTINFO_ROOTDEVICE, sizeof(bi_rdev)); | | 257 | bi_add(&bi_rdev, BTINFO_ROOTDEVICE, sizeof(bi_rdev)); |
258 | if (bi_net.devname[0] != 0 ) | | 258 | if (bi_net.devname[0] != 0 ) |
259 | bi_add(&bi_net, BTINFO_NET, sizeof(bi_net)); | | 259 | bi_add(&bi_net, BTINFO_NET, sizeof(bi_net)); |
260 | } else { | | 260 | } else { |
261 | printf("Loaded object is not NetBSD ARM ELF"); | | 261 | printf("Loaded object is not NetBSD ARM ELF"); |
262 | _rtt(); | | 262 | _rtt(); |
263 | } | | 263 | } |
264 | | | 264 | |
265 | printf("entry=%p, nsym=%lu, ssym=%p, esym=%p\n", | | 265 | printf("entry=%p, nsym=%lu, ssym=%p, esym=%p\n", |
266 | (void *)marks[MARK_ENTRY], | | 266 | (void *)marks[MARK_ENTRY], |
267 | marks[MARK_NSYM], | | 267 | marks[MARK_NSYM], |
268 | (void *)marks[MARK_SYM], | | 268 | (void *)marks[MARK_SYM], |
269 | (void *)marks[MARK_END]); | | 269 | (void *)marks[MARK_END]); |
270 | (*entry)(bootinfo); | | 270 | (*entry)(bootinfo); |
271 | | | 271 | |
272 | printf("exec returned, restarting...\n"); | | 272 | printf("exec returned, restarting...\n"); |
273 | _rtt(); | | 273 | _rtt(); |
274 | } | | 274 | } |
275 | | | 275 | |
276 | void | | 276 | void |
277 | uart_init(uint32_t pclk) | | 277 | uart_init(uint32_t pclk) |
278 | { | | 278 | { |
279 | /* Setup UART0 clocking: Use PCLK */ | | 279 | /* Setup UART0 clocking: Use PCLK */ |
280 | *(volatile uint32_t*)(S3C2440_UART_BASE(0)+SSCOM_UBRDIV) = | | 280 | *(volatile uint32_t*)(S3C2440_UART_BASE(0)+SSCOM_UBRDIV) = |
281 | (pclk/(UART_BAUDRATE*16)) - 1; | | 281 | (pclk/(UART_BAUDRATE*16)) - 1; |
282 | | | 282 | |
283 | *(volatile uint32_t*)(S3C2440_UART_BASE(0)+SSCOM_UCON) = | | 283 | *(volatile uint32_t*)(S3C2440_UART_BASE(0)+SSCOM_UCON) = |
284 | UCON_TXMODE_INT | UCON_RXMODE_INT; | | 284 | UCON_TXMODE_INT | UCON_RXMODE_INT; |
285 | | | 285 | |
286 | *(volatile uint32_t*)(S3C2440_UART_BASE(0)+SSCOM_ULCON) = | | 286 | *(volatile uint32_t*)(S3C2440_UART_BASE(0)+SSCOM_ULCON) = |
287 | ULCON_PARITY_NONE | ULCON_LENGTH_8; | | 287 | ULCON_PARITY_NONE | ULCON_LENGTH_8; |
288 | | | 288 | |
289 | *(volatile uint32_t*)(S3C2440_UART_BASE(0)+SSCOM_UFCON) = | | 289 | *(volatile uint32_t*)(S3C2440_UART_BASE(0)+SSCOM_UFCON) = |
290 | UFCON_TXTRIGGER_0 | UFCON_TXFIFO_RESET | UFCON_FIFO_ENABLE; | | 290 | UFCON_TXTRIGGER_0 | UFCON_TXFIFO_RESET | UFCON_FIFO_ENABLE; |
291 | } | | 291 | } |
292 | | | 292 | |
293 | static uint32_t countdown_duration; | | 293 | static uint32_t countdown_duration; |
294 | | | 294 | |
295 | static | | 295 | static |
296 | void time_init(uint32_t pclk) | | 296 | void time_init(uint32_t pclk) |
297 | { | | 297 | { |
298 | /* Configure timer0 to be as slow as possible: | | 298 | /* Configure timer0 to be as slow as possible: |
299 | Prescaler = 255 | | 299 | Prescaler = 255 |
300 | Divider = 16 | | 300 | Divider = 16 |
301 | */ | | 301 | */ |
302 | | | 302 | |
303 | /* First, configure the prescaler */ | | 303 | /* First, configure the prescaler */ |
304 | *(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCFG0) = 0xff; | | 304 | *(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCFG0) = 0xff; |
305 | | | 305 | |
306 | /* Next, the divider */ | | 306 | /* Next, the divider */ |
307 | *(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCFG1) |= | | 307 | *(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCFG1) |= |
308 | (TCFG1_MUX_DIV16 <<TCFG1_MUX_SHIFT(0)) & TCFG1_MUX_MASK(0); | | 308 | (TCFG1_MUX_DIV16 <<TCFG1_MUX_SHIFT(0)) & TCFG1_MUX_MASK(0); |
309 | | | 309 | |
310 | *(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCON) = | | 310 | *(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCON) = |
311 | TCON_MANUALUPDATE(0); | | 311 | TCON_MANUALUPDATE(0); |
312 | *(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCNTB(0)) = | | 312 | *(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCNTB(0)) = |
313 | 0xffff; | | 313 | 0xffff; |
314 | *(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCON) = | | 314 | *(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCON) = |
315 | TCON_START(0); | | 315 | TCON_START(0); |
316 | | | 316 | |
317 | | | 317 | |
318 | /* Timer count down duration */ | | 318 | /* Timer count down duration */ |
319 | countdown_duration = 65535/(pclk/256/16); | | 319 | countdown_duration = 65535/(pclk/256/16); |
320 | timer_inc_rate = pclk/256/16; | | 320 | timer_inc_rate = pclk/256/16; |
321 | // printf("Countdown duration is: %ds\n", countdown_duration); | | 321 | // printf("Countdown duration is: %ds\n", countdown_duration); |
322 | #if 0 | | 322 | #if 0 |
323 | { | | 323 | { |
324 | /* Timer test */ | | 324 | /* Timer test */ |
325 | time_t time, old_time; | | 325 | time_t time, old_time; |
326 | | | 326 | |
327 | while(1) { | | 327 | while(1) { |
328 | time = old_time = getsecs(); | | 328 | time = old_time = getsecs(); |
329 | do { | | 329 | do { |
330 | time = getsecs(); | | 330 | time = getsecs(); |
331 | } while(time == old_time); | | 331 | } while(time == old_time); |
332 | printf("Count %u\n", (int)time); | | 332 | printf("Count %u\n", (int)time); |
333 | } | | 333 | } |
334 | } | | 334 | } |
335 | #endif | | 335 | #endif |
336 | } | | 336 | } |
337 | | | 337 | |
338 | time_t | | 338 | time_t |
339 | getsecs() | | 339 | getsecs() |
340 | { | | 340 | { |
341 | time_t secs = getusecs()/1000000; | | 341 | time_t secs = getusecs()/1000000; |
342 | return secs; | | 342 | return secs; |
343 | } | | 343 | } |
344 | | | 344 | |
345 | time_t | | 345 | time_t |
346 | getusecs() { | | 346 | getusecs() { |
347 | uint32_t count; | | 347 | uint32_t count; |
348 | //do { | | 348 | //do { |
349 | count = *(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCNTO(0)); | | 349 | count = *(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCNTO(0)); |
350 | //} while( count > 65500); | | 350 | //} while( count > 65500); |
351 | | | 351 | |
352 | *(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCON) = | | 352 | *(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCON) = |
353 | TCON_MANUALUPDATE(0); | | 353 | TCON_MANUALUPDATE(0); |
354 | *(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCNTB(0)) = | | 354 | *(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCNTB(0)) = |
355 | 0xffff; | | 355 | 0xffff; |
356 | *(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCON) = | | 356 | *(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCON) = |
357 | TCON_START(0); | | 357 | TCON_START(0); |
358 | | | 358 | |
359 | wallclock += ((65535-count)*1000000) / timer_inc_rate; | | 359 | wallclock += ((65535-count)*1000000) / timer_inc_rate; |
360 | | | 360 | |
361 | return wallclock; | | 361 | return wallclock; |
362 | } | | 362 | } |
363 | | | 363 | |
364 | void | | 364 | void |
365 | usleep(int us) { | | 365 | usleep(int us) { |
366 | uint32_t count; | | 366 | uint32_t count; |
367 | uint32_t target_clock = wallclock+us; | | 367 | uint32_t target_clock = wallclock+us; |
368 | | | 368 | |
369 | while( wallclock < target_clock) { | | 369 | while( wallclock < target_clock) { |
370 | do { | | 370 | do { |
371 | count = *(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCNTO(0)); | | 371 | count = *(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCNTO(0)); |
372 | } while( count > 65500); | | 372 | } while( count > 65500); |
373 | | | 373 | |
374 | *(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCON) = | | 374 | *(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCON) = |
375 | TCON_MANUALUPDATE(0); | | 375 | TCON_MANUALUPDATE(0); |
376 | *(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCNTB(0)) = | | 376 | *(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCNTB(0)) = |
377 | 0xffff; | | 377 | 0xffff; |
378 | *(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCON) = | | 378 | *(volatile uint32_t*)(S3C2440_TIMER_BASE+TIMER_TCON) = |
379 | TCON_START(0); | | 379 | TCON_START(0); |
380 | | | 380 | |
381 | wallclock += ((65535-count)*1000000) / timer_inc_rate; | | 381 | wallclock += ((65535-count)*1000000) / timer_inc_rate; |
382 | } | | 382 | } |
383 | } | | 383 | } |
384 | | | 384 | |
385 | | | 385 | |
386 | void | | 386 | void |
387 | mini2440_panic() | | 387 | mini2440_panic() |
388 | { | | 388 | { |
389 | int i, l; | | 389 | int i, l; |
390 | int v; | | 390 | int v; |
391 | while(1) { | | 391 | while(1) { |
392 | CLEAR_LEDS(); | | 392 | CLEAR_LEDS(); |
393 | for(l=0; l<0xffffff; l++) { | | 393 | for(l=0; l<0xffffff; l++) { |
394 | v = *((int*)(S3C2440_TIMER_BASE+TIMER_TCNTO(0))); | | 394 | v = *((int*)(S3C2440_TIMER_BASE+TIMER_TCNTO(0))); |
395 | } | | 395 | } |
396 | for(i=1; i<=4; i++) { | | 396 | for(i=1; i<=4; i++) { |
397 | LED_ON(i); | | 397 | LED_ON(i); |
398 | } | | 398 | } |
399 | for(l=0; l<0xffffff; l++) { | | 399 | for(l=0; l<0xffffff; l++) { |
400 | v = *((int*)(S3C2440_TIMER_BASE+TIMER_TCNTO(0))); | | 400 | v = *((int*)(S3C2440_TIMER_BASE+TIMER_TCNTO(0))); |
401 | } | | 401 | } |
402 | __USE(v); | | 402 | __USE(v); |
403 | } | | 403 | } |
404 | } | | 404 | } |
405 | | | 405 | |
406 | void | | 406 | void |
407 | s3c24x0_clock_freq2(vaddr_t clkman_base, int *fclk, int *hclk, int *pclk) | | 407 | s3c24x0_clock_freq2(vaddr_t clkman_base, int *fclk, int *hclk, int *pclk) |
408 | { | | 408 | { |
409 | uint32_t pllcon, divn, camdivn; | | 409 | uint32_t pllcon, divn, camdivn; |
410 | int mdiv, pdiv, sdiv; | | 410 | int mdiv, pdiv, sdiv; |
411 | uint32_t f, h, p; | | 411 | uint32_t f, h, p; |
412 | | | 412 | |
413 | pllcon = *(volatile uint32_t *)(clkman_base + CLKMAN_MPLLCON); | | 413 | pllcon = *(volatile uint32_t *)(clkman_base + CLKMAN_MPLLCON); |
414 | divn = *(volatile uint32_t *)(clkman_base + CLKMAN_CLKDIVN); | | 414 | divn = *(volatile uint32_t *)(clkman_base + CLKMAN_CLKDIVN); |
415 | camdivn = *(volatile uint32_t *)(clkman_base + CLKMAN_CAMDIVN); | | 415 | camdivn = *(volatile uint32_t *)(clkman_base + CLKMAN_CAMDIVN); |
416 | | | 416 | |
417 | mdiv = (pllcon & PLLCON_MDIV_MASK) >> PLLCON_MDIV_SHIFT; | | 417 | mdiv = (pllcon & PLLCON_MDIV_MASK) >> PLLCON_MDIV_SHIFT; |
418 | pdiv = (pllcon & PLLCON_PDIV_MASK) >> PLLCON_PDIV_SHIFT; | | 418 | pdiv = (pllcon & PLLCON_PDIV_MASK) >> PLLCON_PDIV_SHIFT; |
419 | sdiv = (pllcon & PLLCON_SDIV_MASK) >> PLLCON_SDIV_SHIFT; | | 419 | sdiv = (pllcon & PLLCON_SDIV_MASK) >> PLLCON_SDIV_SHIFT; |
420 | | | 420 | |
421 | f = ((mdiv + 8) * S3C2XX0_XTAL_CLK) / ((pdiv + 2) * (1 << sdiv)) * 2; | | 421 | f = ((mdiv + 8) * S3C2XX0_XTAL_CLK) / ((pdiv + 2) * (1 << sdiv)) * 2; |
422 | h = f; | | 422 | h = f; |
423 | | | 423 | |
424 | /* HDIVN of CLKDIVN can have 4 distinct values */ | | 424 | /* HDIVN of CLKDIVN can have 4 distinct values */ |
425 | switch( (divn & CLKDIVN_HDIVN_MASK) >> CLKDIVN_HDIVN_SHIFT ) | | 425 | switch( (divn & CLKDIVN_HDIVN_MASK) >> CLKDIVN_HDIVN_SHIFT ) |
426 | { | | 426 | { |
427 | case 0: | | 427 | case 0: |
428 | /* 00b: HCLK = FCLK/1*/ | | 428 | /* 00b: HCLK = FCLK/1*/ |
429 | break; | | 429 | break; |
430 | case 1: | | 430 | case 1: |
431 | /* 01b: HCLK = FCLK/2*/ | | 431 | /* 01b: HCLK = FCLK/2*/ |
432 | h /= 2; | | 432 | h /= 2; |
433 | break; | | 433 | break; |
434 | case 2: | | 434 | case 2: |
435 | /* 10b: HCLK = FCLK/4 when CAMDIVN[9] (HCLK4_HALF) = 0 | | 435 | /* 10b: HCLK = FCLK/4 when CAMDIVN[9] (HCLK4_HALF) = 0 |
436 | * HCLK = FCLK/8 when CAMDIVN[9] (HCLK4_HALF) = 1 */ | | 436 | * HCLK = FCLK/8 when CAMDIVN[9] (HCLK4_HALF) = 1 */ |
437 | if( camdivn & CLKCAMDIVN_HCLK4_HALF ) | | 437 | if( camdivn & CLKCAMDIVN_HCLK4_HALF ) |
438 | h /= 8; | | 438 | h /= 8; |
439 | else | | 439 | else |
440 | h /= 4; | | 440 | h /= 4; |
441 | break; | | 441 | break; |
442 | case 3: | | 442 | case 3: |
443 | /* 11b: HCLK = FCLK/3 when CAMDIVN[8] (HCLK3_HALF) = 0 | | 443 | /* 11b: HCLK = FCLK/3 when CAMDIVN[8] (HCLK3_HALF) = 0 |
444 | * HCLK = FCLK/6 when CAMDIVN[8] (HCLK3_HALF) = 1 */ | | 444 | * HCLK = FCLK/6 when CAMDIVN[8] (HCLK3_HALF) = 1 */ |
445 | if( camdivn & CLKCAMDIVN_HCLK3_HALF ) | | 445 | if( camdivn & CLKCAMDIVN_HCLK3_HALF ) |
446 | h /= 6; | | 446 | h /= 6; |
447 | else | | 447 | else |
448 | h /= 3; | | 448 | h /= 3; |
449 | break; | | 449 | break; |
450 | } | | 450 | } |
451 | | | 451 | |
452 | p = h; | | 452 | p = h; |
453 | | | 453 | |
454 | if (divn & CLKDIVN_PDIVN) | | 454 | if (divn & CLKDIVN_PDIVN) |
455 | p /= 2; | | 455 | p /= 2; |
456 | | | 456 | |
457 | if (fclk) *fclk = f; | | 457 | if (fclk) *fclk = f; |
458 | if (hclk) *hclk = h; | | 458 | if (hclk) *hclk = h; |
459 | if (pclk) *pclk = p; | | 459 | if (pclk) *pclk = p; |
460 | } | | 460 | } |
461 | | | 461 | |
462 | void | | 462 | void |
463 | putchar(int c) | | 463 | putchar(int c) |
464 | { | | 464 | { |
465 | uint32_t stat; | | 465 | uint32_t stat; |
466 | | | 466 | |
467 | if (c == '\n') | | 467 | if (c == '\n') |
468 | putchar('\r'); | | 468 | putchar('\r'); |
469 | | | 469 | |
470 | do { | | 470 | do { |
471 | stat = CSR_READ(S3C2440_UART_BASE(0) + SSCOM_UTRSTAT); | | 471 | stat = CSR_READ(S3C2440_UART_BASE(0) + SSCOM_UTRSTAT); |
472 | } while ((stat & UTRSTAT_TXEMPTY) == 0); | | 472 | } while ((stat & UTRSTAT_TXEMPTY) == 0); |
473 | | | 473 | |
474 | CSR_WRITE(S3C2440_UART_BASE(0) + SSCOM_UTXH, c); | | 474 | CSR_WRITE(S3C2440_UART_BASE(0) + SSCOM_UTXH, c); |
475 | } | | 475 | } |
476 | | | 476 | |
477 | void | | 477 | void |
478 | _rtt() | | 478 | _rtt() |
479 | { | | 479 | { |
480 | int cpsr_save, tmp; | | 480 | int cpsr_save, tmp; |
481 | /* Disable interrupts */ | | 481 | /* Disable interrupts */ |
482 | __asm volatile("mrs %0, cpsr;" | | 482 | __asm volatile("mrs %0, cpsr;" |
483 | "orr %1, %0, %2;" | | 483 | "orr %1, %0, %2;" |
484 | "msr cpsr_c, %1;" | | 484 | "msr cpsr_c, %1;" |
485 | : "=r" (cpsr_save), "=r" (tmp) | | 485 | : "=r" (cpsr_save), "=r" (tmp) |
486 | : "I" (I32_bit) | | 486 | : "I" (I32_bit) |
487 | ); | | 487 | ); |
488 | | | 488 | |
489 | /* Disable MMU */ | | 489 | /* Disable MMU */ |
490 | __asm volatile("mrc p15, 0, %0, c1, c0, 0;" | | 490 | __asm volatile("mrc p15, 0, %0, c1, c0, 0;" |
491 | "bic %0, %0, %1;" | | 491 | "bic %0, %0, %1;" |
492 | "mcr p15, 0, %0, c1, c0, 0;" | | 492 | "mcr p15, 0, %0, c1, c0, 0;" |
493 | : "=r" (tmp) | | 493 | : "=r" (tmp) |
494 | : "I" (CPU_CONTROL_MMU_ENABLE) | | 494 | : "I" (CPU_CONTROL_MMU_ENABLE) |
495 | ); | | 495 | ); |
496 | | | 496 | |
497 | /* Configure watchdog to fire now */ | | 497 | /* Configure watchdog to fire now */ |
498 | *(volatile uint32_t *)(S3C2440_WDT_BASE + WDT_WTCON) = | | 498 | *(volatile uint32_t *)(S3C2440_WDT_BASE + WDT_WTCON) = |
499 | (0 << WTCON_PRESCALE_SHIFT) | WTCON_ENABLE | | | 499 | (0 << WTCON_PRESCALE_SHIFT) | WTCON_ENABLE | |
500 | WTCON_CLKSEL_16 | WTCON_ENRST; | | 500 | WTCON_CLKSEL_16 | WTCON_ENRST; |
| | | 501 | __builtin_unreachable(); |
501 | } | | 502 | } |
502 | | | 503 | |
503 | void | | 504 | void |
504 | bi_init(void *addr) | | 505 | bi_init(void *addr) |
505 | { | | 506 | { |
506 | struct btinfo_magic bi_magic; | | 507 | struct btinfo_magic bi_magic; |
507 | | | 508 | |
508 | memset(addr, 0, BOOTINFO_MAXSIZE); | | 509 | memset(addr, 0, BOOTINFO_MAXSIZE); |
509 | bi_next = (char*) addr; | | 510 | bi_next = (char*) addr; |
510 | bi_size = 0; | | 511 | bi_size = 0; |
511 | | | 512 | |
512 | bi_magic.magic = BOOTINFO_MAGIC; | | 513 | bi_magic.magic = BOOTINFO_MAGIC; |
513 | bi_add(&bi_magic, BTINFO_MAGIC, sizeof(bi_magic)); | | 514 | bi_add(&bi_magic, BTINFO_MAGIC, sizeof(bi_magic)); |
514 | } | | 515 | } |
515 | | | 516 | |
516 | | | 517 | |
517 | void | | 518 | void |
518 | bi_add(void *new, int type, int size) | | 519 | bi_add(void *new, int type, int size) |
519 | { | | 520 | { |
520 | struct btinfo_common *bi; | | 521 | struct btinfo_common *bi; |
521 | | | 522 | |
522 | if (bi_size + size > BOOTINFO_MAXSIZE) | | 523 | if (bi_size + size > BOOTINFO_MAXSIZE) |
523 | return; | | 524 | return; |
524 | | | 525 | |
525 | bi = new; | | 526 | bi = new; |
526 | bi->next = size; | | 527 | bi->next = size; |
527 | bi->type = type; | | 528 | bi->type = type; |
528 | memcpy(bi_next, new, size); | | 529 | memcpy(bi_next, new, size); |
529 | bi_next += size; | | 530 | bi_next += size; |
530 | } | | 531 | } |
531 | | | 532 | |
532 | static void | | 533 | static void |
533 | parse_mac_address(const char *str, uint8_t *enaddr) | | 534 | parse_mac_address(const char *str, uint8_t *enaddr) |
534 | { | | 535 | { |
535 | int i; | | 536 | int i; |
536 | char *next = (char*)str; | | 537 | char *next = (char*)str; |
537 | | | 538 | |
538 | for(i=0;i<6;i++) { | | 539 | for(i=0;i<6;i++) { |
539 | str = next; | | 540 | str = next; |
540 | enaddr[i] = (unsigned char)strtoll(str, &next, 16); | | 541 | enaddr[i] = (unsigned char)strtoll(str, &next, 16); |
541 | if( *next == ':' ) { | | 542 | if( *next == ':' ) { |
542 | next++; | | 543 | next++; |
543 | } else { | | 544 | } else { |
544 | break; | | 545 | break; |
545 | } | | 546 | } |
546 | } | | 547 | } |
547 | } | | 548 | } |
548 | | | 549 | |
549 | static void | | 550 | static void |
550 | brdsetup(void) | | 551 | brdsetup(void) |
551 | { | | 552 | { |
552 | /* | | 553 | /* |
553 | * MINI2440 pin usage summary | | 554 | * MINI2440 pin usage summary |
554 | * | | 555 | * |
555 | * B5 output LED1 control | | 556 | * B5 output LED1 control |
556 | * B6 output LED2 control | | 557 | * B6 output LED2 control |
557 | * B7 output LED3 control | | 558 | * B7 output LED3 control |
558 | * B8 output LED4 control | | 559 | * B8 output LED4 control |
559 | * G0 EINT8 K1 button | | 560 | * G0 EINT8 K1 button |
560 | * G3 EINT11 K2 button | | 561 | * G3 EINT11 K2 button |
561 | * G5 EINT13 K3 button | | 562 | * G5 EINT13 K3 button |
562 | * G6 EINT14 K4 button | | 563 | * G6 EINT14 K4 button |
563 | * G7 EINT15 K5 button | | 564 | * G7 EINT15 K5 button |
564 | * G11 EINT19 K6 button | | 565 | * G11 EINT19 K6 button |
565 | * F7 EINT7 DM9000 interrupt | | 566 | * F7 EINT7 DM9000 interrupt |
566 | * G12 EINT20 camera interrupt | | 567 | * G12 EINT20 camera interrupt |
567 | * G8 input SD card presense detect | | 568 | * G8 input SD card presense detect |
568 | * H8 input SD write protect sense | | 569 | * H8 input SD write protect sense |
569 | * B0 TOUT0 buzzer PWM | | 570 | * B0 TOUT0 buzzer PWM |
570 | * B1 TOUT1 LCD backlight PWM | | 571 | * B1 TOUT1 LCD backlight PWM |
571 | * B2 output UDA1341 audio L3MODE | | 572 | * B2 output UDA1341 audio L3MODE |
572 | * B3 output UDA1341 audio L3DATA | | 573 | * B3 output UDA1341 audio L3DATA |
573 | * B4 output UDA1341 audio L3LOCK | | 574 | * B4 output UDA1341 audio L3LOCK |
574 | * | | 575 | * |
575 | * A21, A11, G15, G14, G13: not used. | | 576 | * A21, A11, G15, G14, G13: not used. |
576 | * | | 577 | * |
577 | * i input sense | | 578 | * i input sense |
578 | * o output control | | 579 | * o output control |
579 | * 2 function 2 | | 580 | * 2 function 2 |
580 | * 3 function 3 | | 581 | * 3 function 3 |
581 | * 0 output control (A only) | | 582 | * 0 output control (A only) |
582 | * 1 function 1 (A only) | | 583 | * 1 function 1 (A only) |
583 | * ./x no function, not connected or don't-care | | 584 | * ./x no function, not connected or don't-care |
584 | * | | 585 | * |
585 | * A ........ .1x11111 1111x111 11111111 | | 586 | * A ........ .1x11111 1111x111 11111111 |
586 | * B .....22o ooooooo2 | | 587 | * B .....22o ooooooo2 |
587 | * C 22222222 22222222 | | 588 | * C 22222222 22222222 |
588 | * D 22222222 22222222 | | 589 | * D 22222222 22222222 |
589 | * E 22222222 22222222 | | 590 | * E 22222222 22222222 |
590 | * F ........ 22222222 | | 591 | * F ........ 22222222 |
591 | * G xxx2222i 22232322 | | 592 | * G xxx2222i 22232322 |
592 | * H .....22i 22222222 | | 593 | * H .....22i 22222222 |
593 | * J ...22222 22222222 | | 594 | * J ...22222 22222222 |
594 | */ | | 595 | */ |
595 | iomux('A', "........ .1x11111 1111x111 11111111"); | | 596 | iomux('A', "........ .1x11111 1111x111 11111111"); |
596 | iomux('B', ".....22o ooooooo2"); | | 597 | iomux('B', ".....22o ooooooo2"); |
597 | iomux('C', "22222222 22222222"); | | 598 | iomux('C', "22222222 22222222"); |
598 | iomux('D', "22222222 22222222"); | | 599 | iomux('D', "22222222 22222222"); |
599 | iomux('E', "22222222 22222222"); | | 600 | iomux('E', "22222222 22222222"); |
600 | iomux('F', "........ 22222222"); | | 601 | iomux('F', "........ 22222222"); |
601 | iomux('G', "xxx2222i 22232322"); | | 602 | iomux('G', "xxx2222i 22232322"); |
602 | iomux('H', ".....22i 22222222"); | | 603 | iomux('H', ".....22i 22222222"); |
603 | iomux('J', "...22222 22222222"); | | 604 | iomux('J', "...22222 22222222"); |
604 | | | 605 | |
605 | /* mask all possible external interrupt source [23:3] */ | | 606 | /* mask all possible external interrupt source [23:3] */ |
606 | CSR_WRITE(S3C2440_GPIO_BASE + GPIO_EINTMASK, ~0); | | 607 | CSR_WRITE(S3C2440_GPIO_BASE + GPIO_EINTMASK, ~0); |
607 | } | | 608 | } |
608 | | | 609 | |
609 | static void | | 610 | static void |
610 | iomux(int grp, const char *cnf) | | 611 | iomux(int grp, const char *cnf) |
611 | { | | 612 | { |
612 | uint32_t con; | | 613 | uint32_t con; |
613 | int sft, i, v; | | 614 | int sft, i, v; |
614 | | | 615 | |
615 | con = v = 0; | | 616 | con = v = 0; |
616 | sft = (grp != 'A') ? 2 : 1; | | 617 | sft = (grp != 'A') ? 2 : 1; |
617 | for (i = 0; cnf[i] != '\0'; i++) { | | 618 | for (i = 0; cnf[i] != '\0'; i++) { |
618 | switch (cnf[i]) { | | 619 | switch (cnf[i]) { |
619 | case 'i': | | 620 | case 'i': |
620 | case '0': | | 621 | case '0': |
621 | case '.': | | 622 | case '.': |
622 | case 'x': | | 623 | case 'x': |
623 | v = 0; break; | | 624 | v = 0; break; |
624 | case 'o': | | 625 | case 'o': |
625 | case '1': | | 626 | case '1': |
626 | v = 1; break; | | 627 | v = 1; break; |
627 | case '2': | | 628 | case '2': |
628 | v = 2; break; | | 629 | v = 2; break; |
629 | case '3': | | 630 | case '3': |
630 | v = 3; break; | | 631 | v = 3; break; |
631 | default: | | 632 | default: |
632 | continue; | | 633 | continue; |
633 | } | | 634 | } |
634 | con = (con << sft) | v; | | 635 | con = (con << sft) | v; |
635 | } | | 636 | } |
636 | CSR_WRITE(S3C2440_GPIO_BASE + 0x10 * (grp - 'A'), con); | | 637 | CSR_WRITE(S3C2440_GPIO_BASE + 0x10 * (grp - 'A'), con); |
637 | } | | 638 | } |