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