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