aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc/boot/common
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/ppc/boot/common
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/ppc/boot/common')
-rw-r--r--arch/ppc/boot/common/Makefile13
-rw-r--r--arch/ppc/boot/common/bootinfo.c70
-rw-r--r--arch/ppc/boot/common/crt0.S81
-rw-r--r--arch/ppc/boot/common/misc-common.c553
-rw-r--r--arch/ppc/boot/common/ns16550.c99
-rw-r--r--arch/ppc/boot/common/serial_stub.c23
-rw-r--r--arch/ppc/boot/common/string.S150
-rw-r--r--arch/ppc/boot/common/util.S293
8 files changed, 1282 insertions, 0 deletions
diff --git a/arch/ppc/boot/common/Makefile b/arch/ppc/boot/common/Makefile
new file mode 100644
index 000000000000..f88d647d5dd4
--- /dev/null
+++ b/arch/ppc/boot/common/Makefile
@@ -0,0 +1,13 @@
1#
2# arch/ppc/boot/common/Makefile
3#
4# This file is subject to the terms and conditions of the GNU General Public
5# License. See the file "COPYING" in the main directory of this archive
6# for more details.
7#
8# Tom Rini January 2001
9#
10
11lib-y := string.o util.o misc-common.o \
12 serial_stub.o bootinfo.o
13lib-$(CONFIG_SERIAL_8250_CONSOLE) += ns16550.o
diff --git a/arch/ppc/boot/common/bootinfo.c b/arch/ppc/boot/common/bootinfo.c
new file mode 100644
index 000000000000..9c6e528940e9
--- /dev/null
+++ b/arch/ppc/boot/common/bootinfo.c
@@ -0,0 +1,70 @@
1/*
2 * arch/ppc/common/bootinfo.c
3 *
4 * General bootinfo record utilities
5 * Author: Randy Vinson <rvinson@mvista.com>
6 *
7 * 2002 (c) MontaVista Software, Inc. This file is licensed under the terms
8 * of the GNU General Public License version 2. This program is licensed
9 * "as is" without any warranty of any kind, whether express or implied.
10 */
11
12#include <linux/types.h>
13#include <linux/string.h>
14#include <asm/bootinfo.h>
15
16#include "nonstdio.h"
17
18static struct bi_record * birec = NULL;
19
20static struct bi_record *
21__bootinfo_build(struct bi_record *rec, unsigned long tag, unsigned long size,
22 void *data)
23{
24 /* set the tag */
25 rec->tag = tag;
26
27 /* if the caller has any data, copy it */
28 if (size)
29 memcpy(rec->data, (char *)data, size);
30
31 /* set the record size */
32 rec->size = sizeof(struct bi_record) + size;
33
34 /* advance to the next available space */
35 rec = (struct bi_record *)((unsigned long)rec + rec->size);
36
37 return rec;
38}
39
40void
41bootinfo_init(struct bi_record *rec)
42{
43
44 /* save start of birec area */
45 birec = rec;
46
47 /* create an empty list */
48 rec = __bootinfo_build(rec, BI_FIRST, 0, NULL);
49 (void) __bootinfo_build(rec, BI_LAST, 0, NULL);
50
51}
52
53void
54bootinfo_append(unsigned long tag, unsigned long size, void * data)
55{
56
57 struct bi_record *rec = birec;
58
59 /* paranoia */
60 if ((rec == NULL) || (rec->tag != BI_FIRST))
61 return;
62
63 /* find the last entry in the list */
64 while (rec->tag != BI_LAST)
65 rec = (struct bi_record *)((ulong)rec + rec->size);
66
67 /* overlay BI_LAST record with new one and tag on a new BI_LAST */
68 rec = __bootinfo_build(rec, tag, size, data);
69 (void) __bootinfo_build(rec, BI_LAST, 0, NULL);
70}
diff --git a/arch/ppc/boot/common/crt0.S b/arch/ppc/boot/common/crt0.S
new file mode 100644
index 000000000000..4d31b824bbd1
--- /dev/null
+++ b/arch/ppc/boot/common/crt0.S
@@ -0,0 +1,81 @@
1/* Copyright (c) 1997 Paul Mackerras <paulus@cs.anu.edu.au>
2 * Initial Power Macintosh COFF version.
3 * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
4 * Modifications for IBM PowerPC 400-class processor evaluation
5 * boards.
6 *
7 * Module name: crt0.S
8 *
9 * Description:
10 * Boot loader execution entry point. Clears out .bss section as per
11 * ANSI C requirements. Invalidates and flushes the caches over the
12 * range covered by the boot loader's .text section. Sets up a stack
13 * below the .text section entry point.
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version
18 * 2 of the License, or (at your option) any later version.
19 */
20
21#include <linux/config.h>
22#include <asm/ppc_asm.h>
23
24 .text
25
26 .globl _start
27_start:
28#ifdef XCOFF
29 .long __start,0,0
30
31 .globl __start
32__start:
33#endif
34
35 ## Flush and invalidate the caches for the range in memory covering
36 ## the .text section of the boot loader
37
38 lis r9,_start@h # r9 = &_start
39 lis r8,_etext@ha #
40 addi r8,r8,_etext@l # r8 = &_etext
413: dcbf r0,r9 # Flush the data cache
42 icbi r0,r9 # Invalidate the instruction cache
43 addi r9,r9,0x10 # Increment by one cache line
44 cmplw cr0,r9,r8 # Are we at the end yet?
45 blt 3b # No, keep flushing and invalidating
46 sync # sync ; isync after flushing the icache
47 isync
48
49 ## Clear out the BSS as per ANSI C requirements
50
51 lis r7,_end@ha
52 addi r7,r7,_end@l # r7 = &_end
53 lis r8,__bss_start@ha #
54 addi r8,r8,__bss_start@l # r8 = &_bss_start
55
56 ## Determine how large an area, in number of words, to clear
57
58 subf r7,r8,r7 # r7 = &_end - &_bss_start + 1
59 addi r7,r7,3 # r7 += 3
60 srwi. r7,r7,2 # r7 = size in words.
61 beq 2f # If the size is zero, do not bother
62 addi r8,r8,-4 # r8 -= 4
63 mtctr r7 # SPRN_CTR = number of words to clear
64 li r0,0 # r0 = 0
651: stwu r0,4(r8) # Clear out a word
66 bdnz 1b # If we are not done yet, keep clearing
672:
68
69#ifdef CONFIG_40x
70 ## Set up the stack
71
72 lis r9,_start@h # r9 = &_start (text section entry)
73 ori r9,r9,_start@l
74 subi r1,r9,64 # Start the stack 64 bytes below _start
75 clrrwi r1,r1,4 # Make sure it is aligned on 16 bytes.
76 li r0,0
77 stwu r0,-16(r1)
78 mtlr r9
79#endif
80
81 b start # All done, start the real work.
diff --git a/arch/ppc/boot/common/misc-common.c b/arch/ppc/boot/common/misc-common.c
new file mode 100644
index 000000000000..e79e6b3f276e
--- /dev/null
+++ b/arch/ppc/boot/common/misc-common.c
@@ -0,0 +1,553 @@
1/*
2 * arch/ppc/boot/common/misc-common.c
3 *
4 * Misc. bootloader code (almost) all platforms can use
5 *
6 * Author: Johnnie Peters <jpeters@mvista.com>
7 * Editor: Tom Rini <trini@mvista.com>
8 *
9 * Derived from arch/ppc/boot/prep/misc.c
10 *
11 * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under
12 * the terms of the GNU General Public License version 2. This program
13 * is licensed "as is" without any warranty of any kind, whether express
14 * or implied.
15 */
16
17#include <stdarg.h> /* for va_ bits */
18#include <linux/config.h>
19#include <linux/string.h>
20#include <linux/zlib.h>
21#include "nonstdio.h"
22
23/* If we're on a PReP, assume we have a keyboard controller
24 * Also note, if we're not PReP, we assume you are a serial
25 * console - Tom */
26#if defined(CONFIG_PPC_PREP) && defined(CONFIG_VGA_CONSOLE)
27extern void cursor(int x, int y);
28extern void scroll(void);
29extern char *vidmem;
30extern int lines, cols;
31extern int orig_x, orig_y;
32extern int keyb_present;
33extern int CRT_tstc(void);
34extern int CRT_getc(void);
35#else
36int cursor(int x, int y) {return 0;}
37void scroll(void) {}
38char vidmem[1];
39#define lines 0
40#define cols 0
41int orig_x = 0;
42int orig_y = 0;
43#define keyb_present 0
44int CRT_tstc(void) {return 0;}
45int CRT_getc(void) {return 0;}
46#endif
47
48extern char *avail_ram;
49extern char *end_avail;
50extern char _end[];
51
52void puts(const char *);
53void putc(const char c);
54void puthex(unsigned long val);
55void gunzip(void *, int, unsigned char *, int *);
56static int _cvt(unsigned long val, char *buf, long radix, char *digits);
57
58void _vprintk(void(*putc)(const char), const char *fmt0, va_list ap);
59unsigned char *ISA_io = NULL;
60
61#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
62 || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
63 || defined(CONFIG_SERIAL_MPSC_CONSOLE)
64extern unsigned long com_port;
65
66extern int serial_tstc(unsigned long com_port);
67extern unsigned char serial_getc(unsigned long com_port);
68extern void serial_putc(unsigned long com_port, unsigned char c);
69#endif
70
71void pause(void)
72{
73 puts("pause\n");
74}
75
76void exit(void)
77{
78 puts("exit\n");
79 while(1);
80}
81
82int tstc(void)
83{
84#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
85 || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
86 || defined(CONFIG_SERIAL_MPSC_CONSOLE)
87 if(keyb_present)
88 return (CRT_tstc() || serial_tstc(com_port));
89 else
90 return (serial_tstc(com_port));
91#else
92 return CRT_tstc();
93#endif
94}
95
96int getc(void)
97{
98 while (1) {
99#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
100 || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
101 || defined(CONFIG_SERIAL_MPSC_CONSOLE)
102 if (serial_tstc(com_port))
103 return (serial_getc(com_port));
104#endif /* serial console */
105 if (keyb_present)
106 if(CRT_tstc())
107 return (CRT_getc());
108 }
109}
110
111void
112putc(const char c)
113{
114 int x,y;
115
116#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
117 || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
118 || defined(CONFIG_SERIAL_MPSC_CONSOLE)
119 serial_putc(com_port, c);
120 if ( c == '\n' )
121 serial_putc(com_port, '\r');
122#endif /* serial console */
123
124 x = orig_x;
125 y = orig_y;
126
127 if ( c == '\n' ) {
128 x = 0;
129 if ( ++y >= lines ) {
130 scroll();
131 y--;
132 }
133 } else if (c == '\r') {
134 x = 0;
135 } else if (c == '\b') {
136 if (x > 0) {
137 x--;
138 }
139 } else {
140 vidmem [ ( x + cols * y ) * 2 ] = c;
141 if ( ++x >= cols ) {
142 x = 0;
143 if ( ++y >= lines ) {
144 scroll();
145 y--;
146 }
147 }
148 }
149
150 cursor(x, y);
151
152 orig_x = x;
153 orig_y = y;
154}
155
156void puts(const char *s)
157{
158 int x,y;
159 char c;
160
161 x = orig_x;
162 y = orig_y;
163
164 while ( ( c = *s++ ) != '\0' ) {
165#if defined(CONFIG_SERIAL_CPM_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE) \
166 || defined(CONFIG_SERIAL_MPC52xx_CONSOLE) \
167 || defined(CONFIG_SERIAL_MPSC_CONSOLE)
168 serial_putc(com_port, c);
169 if ( c == '\n' ) serial_putc(com_port, '\r');
170#endif /* serial console */
171
172 if ( c == '\n' ) {
173 x = 0;
174 if ( ++y >= lines ) {
175 scroll();
176 y--;
177 }
178 } else if (c == '\b') {
179 if (x > 0) {
180 x--;
181 }
182 } else {
183 vidmem [ ( x + cols * y ) * 2 ] = c;
184 if ( ++x >= cols ) {
185 x = 0;
186 if ( ++y >= lines ) {
187 scroll();
188 y--;
189 }
190 }
191 }
192 }
193
194 cursor(x, y);
195
196 orig_x = x;
197 orig_y = y;
198}
199
200void error(char *x)
201{
202 puts("\n\n");
203 puts(x);
204 puts("\n\n -- System halted");
205
206 while(1); /* Halt */
207}
208
209static void *zalloc(unsigned size)
210{
211 void *p = avail_ram;
212
213 size = (size + 7) & -8;
214 avail_ram += size;
215 if (avail_ram > end_avail) {
216 puts("oops... out of memory\n");
217 pause();
218 }
219 return p;
220}
221
222#define HEAD_CRC 2
223#define EXTRA_FIELD 4
224#define ORIG_NAME 8
225#define COMMENT 0x10
226#define RESERVED 0xe0
227
228void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
229{
230 z_stream s;
231 int r, i, flags;
232
233 /* skip header */
234 i = 10;
235 flags = src[3];
236 if (src[2] != Z_DEFLATED || (flags & RESERVED) != 0) {
237 puts("bad gzipped data\n");
238 exit();
239 }
240 if ((flags & EXTRA_FIELD) != 0)
241 i = 12 + src[10] + (src[11] << 8);
242 if ((flags & ORIG_NAME) != 0)
243 while (src[i++] != 0)
244 ;
245 if ((flags & COMMENT) != 0)
246 while (src[i++] != 0)
247 ;
248 if ((flags & HEAD_CRC) != 0)
249 i += 2;
250 if (i >= *lenp) {
251 puts("gunzip: ran out of data in header\n");
252 exit();
253 }
254
255 /* Initialize ourself. */
256 s.workspace = zalloc(zlib_inflate_workspacesize());
257 r = zlib_inflateInit2(&s, -MAX_WBITS);
258 if (r != Z_OK) {
259 puts("zlib_inflateInit2 returned "); puthex(r); puts("\n");
260 exit();
261 }
262 s.next_in = src + i;
263 s.avail_in = *lenp - i;
264 s.next_out = dst;
265 s.avail_out = dstlen;
266 r = zlib_inflate(&s, Z_FINISH);
267 if (r != Z_OK && r != Z_STREAM_END) {
268 puts("inflate returned "); puthex(r); puts("\n");
269 exit();
270 }
271 *lenp = s.next_out - (unsigned char *) dst;
272 zlib_inflateEnd(&s);
273}
274
275void
276puthex(unsigned long val)
277{
278
279 unsigned char buf[10];
280 int i;
281 for (i = 7; i >= 0; i--)
282 {
283 buf[i] = "0123456789ABCDEF"[val & 0x0F];
284 val >>= 4;
285 }
286 buf[8] = '\0';
287 puts(buf);
288}
289
290#define FALSE 0
291#define TRUE 1
292
293void
294_printk(char const *fmt, ...)
295{
296 va_list ap;
297
298 va_start(ap, fmt);
299 _vprintk(putc, fmt, ap);
300 va_end(ap);
301 return;
302}
303
304#define is_digit(c) ((c >= '0') && (c <= '9'))
305
306void
307_vprintk(void(*putc)(const char), const char *fmt0, va_list ap)
308{
309 char c, sign, *cp = 0;
310 int left_prec, right_prec, zero_fill, length = 0, pad, pad_on_right;
311 char buf[32];
312 long val;
313 while ((c = *fmt0++))
314 {
315 if (c == '%')
316 {
317 c = *fmt0++;
318 left_prec = right_prec = pad_on_right = 0;
319 if (c == '-')
320 {
321 c = *fmt0++;
322 pad_on_right++;
323 }
324 if (c == '0')
325 {
326 zero_fill = TRUE;
327 c = *fmt0++;
328 } else
329 {
330 zero_fill = FALSE;
331 }
332 while (is_digit(c))
333 {
334 left_prec = (left_prec * 10) + (c - '0');
335 c = *fmt0++;
336 }
337 if (c == '.')
338 {
339 c = *fmt0++;
340 zero_fill++;
341 while (is_digit(c))
342 {
343 right_prec = (right_prec * 10) + (c - '0');
344 c = *fmt0++;
345 }
346 } else
347 {
348 right_prec = left_prec;
349 }
350 sign = '\0';
351 switch (c)
352 {
353 case 'd':
354 case 'x':
355 case 'X':
356 val = va_arg(ap, long);
357 switch (c)
358 {
359 case 'd':
360 if (val < 0)
361 {
362 sign = '-';
363 val = -val;
364 }
365 length = _cvt(val, buf, 10, "0123456789");
366 break;
367 case 'x':
368 length = _cvt(val, buf, 16, "0123456789abcdef");
369 break;
370 case 'X':
371 length = _cvt(val, buf, 16, "0123456789ABCDEF");
372 break;
373 }
374 cp = buf;
375 break;
376 case 's':
377 cp = va_arg(ap, char *);
378 length = strlen(cp);
379 break;
380 case 'c':
381 c = va_arg(ap, long /*char*/);
382 (*putc)(c);
383 continue;
384 default:
385 (*putc)('?');
386 }
387 pad = left_prec - length;
388 if (sign != '\0')
389 {
390 pad--;
391 }
392 if (zero_fill)
393 {
394 c = '0';
395 if (sign != '\0')
396 {
397 (*putc)(sign);
398 sign = '\0';
399 }
400 } else
401 {
402 c = ' ';
403 }
404 if (!pad_on_right)
405 {
406 while (pad-- > 0)
407 {
408 (*putc)(c);
409 }
410 }
411 if (sign != '\0')
412 {
413 (*putc)(sign);
414 }
415 while (length-- > 0)
416 {
417 (*putc)(c = *cp++);
418 if (c == '\n')
419 {
420 (*putc)('\r');
421 }
422 }
423 if (pad_on_right)
424 {
425 while (pad-- > 0)
426 {
427 (*putc)(c);
428 }
429 }
430 } else
431 {
432 (*putc)(c);
433 if (c == '\n')
434 {
435 (*putc)('\r');
436 }
437 }
438 }
439}
440
441int
442_cvt(unsigned long val, char *buf, long radix, char *digits)
443{
444 char temp[80];
445 char *cp = temp;
446 int length = 0;
447 if (val == 0)
448 { /* Special case */
449 *cp++ = '0';
450 } else
451 while (val)
452 {
453 *cp++ = digits[val % radix];
454 val /= radix;
455 }
456 while (cp != temp)
457 {
458 *buf++ = *--cp;
459 length++;
460 }
461 *buf = '\0';
462 return (length);
463}
464
465void
466_dump_buf_with_offset(unsigned char *p, int s, unsigned char *base)
467{
468 int i, c;
469 if ((unsigned int)s > (unsigned int)p)
470 {
471 s = (unsigned int)s - (unsigned int)p;
472 }
473 while (s > 0)
474 {
475 if (base)
476 {
477 _printk("%06X: ", (int)p - (int)base);
478 } else
479 {
480 _printk("%06X: ", p);
481 }
482 for (i = 0; i < 16; i++)
483 {
484 if (i < s)
485 {
486 _printk("%02X", p[i] & 0xFF);
487 } else
488 {
489 _printk(" ");
490 }
491 if ((i % 2) == 1) _printk(" ");
492 if ((i % 8) == 7) _printk(" ");
493 }
494 _printk(" |");
495 for (i = 0; i < 16; i++)
496 {
497 if (i < s)
498 {
499 c = p[i] & 0xFF;
500 if ((c < 0x20) || (c >= 0x7F)) c = '.';
501 } else
502 {
503 c = ' ';
504 }
505 _printk("%c", c);
506 }
507 _printk("|\n");
508 s -= 16;
509 p += 16;
510 }
511}
512
513void
514_dump_buf(unsigned char *p, int s)
515{
516 _printk("\n");
517 _dump_buf_with_offset(p, s, 0);
518}
519
520/* Very simple inb/outb routines. We declare ISA_io to be 0 above, and
521 * then modify it on platforms which need to. We do it like this
522 * because on some platforms we give inb/outb an exact location, and
523 * on others it's an offset from a given location. -- Tom
524 */
525
526void ISA_init(unsigned long base)
527{
528 ISA_io = (unsigned char *)base;
529}
530
531void
532outb(int port, unsigned char val)
533{
534 /* Ensure I/O operations complete */
535 __asm__ volatile("eieio");
536 ISA_io[port] = val;
537}
538
539unsigned char
540inb(int port)
541{
542 /* Ensure I/O operations complete */
543 __asm__ volatile("eieio");
544 return (ISA_io[port]);
545}
546
547/*
548 * Local variables:
549 * c-indent-level: 8
550 * c-basic-offset: 8
551 * tab-width: 8
552 * End:
553 */
diff --git a/arch/ppc/boot/common/ns16550.c b/arch/ppc/boot/common/ns16550.c
new file mode 100644
index 000000000000..9017c547a6f6
--- /dev/null
+++ b/arch/ppc/boot/common/ns16550.c
@@ -0,0 +1,99 @@
1/*
2 * COM1 NS16550 support
3 */
4
5#include <linux/config.h>
6#include <linux/types.h>
7#include <linux/serial.h>
8#include <linux/serial_reg.h>
9#include <asm/serial.h>
10
11#include "nonstdio.h"
12#include "serial.h"
13
14#define SERIAL_BAUD 9600
15
16extern unsigned long ISA_io;
17
18static struct serial_state rs_table[RS_TABLE_SIZE] = {
19 SERIAL_PORT_DFNS /* Defined in <asm/serial.h> */
20};
21
22static int shift;
23
24unsigned long serial_init(int chan, void *ignored)
25{
26 unsigned long com_port;
27 unsigned char lcr, dlm;
28
29 /* We need to find out which type io we're expecting. If it's
30 * 'SERIAL_IO_PORT', we get an offset from the isa_io_base.
31 * If it's 'SERIAL_IO_MEM', we can the exact location. -- Tom */
32 switch (rs_table[chan].io_type) {
33 case SERIAL_IO_PORT:
34 com_port = rs_table[chan].port;
35 break;
36 case SERIAL_IO_MEM:
37 com_port = (unsigned long)rs_table[chan].iomem_base;
38 break;
39 default:
40 /* We can't deal with it. */
41 return -1;
42 }
43
44 /* How far apart the registers are. */
45 shift = rs_table[chan].iomem_reg_shift;
46
47 /* save the LCR */
48 lcr = inb(com_port + (UART_LCR << shift));
49 /* Access baud rate */
50 outb(com_port + (UART_LCR << shift), 0x80);
51 dlm = inb(com_port + (UART_DLM << shift));
52 /*
53 * Test if serial port is unconfigured.
54 * We assume that no-one uses less than 110 baud or
55 * less than 7 bits per character these days.
56 * -- paulus.
57 */
58
59 if ((dlm <= 4) && (lcr & 2))
60 /* port is configured, put the old LCR back */
61 outb(com_port + (UART_LCR << shift), lcr);
62 else {
63 /* Input clock. */
64 outb(com_port + (UART_DLL << shift),
65 (BASE_BAUD / SERIAL_BAUD) & 0xFF);
66 outb(com_port + (UART_DLM << shift),
67 (BASE_BAUD / SERIAL_BAUD) >> 8);
68 /* 8 data, 1 stop, no parity */
69 outb(com_port + (UART_LCR << shift), 0x03);
70 /* RTS/DTR */
71 outb(com_port + (UART_MCR << shift), 0x03);
72 }
73 /* Clear & enable FIFOs */
74 outb(com_port + (UART_FCR << shift), 0x07);
75
76 return (com_port);
77}
78
79void
80serial_putc(unsigned long com_port, unsigned char c)
81{
82 while ((inb(com_port + (UART_LSR << shift)) & UART_LSR_THRE) == 0)
83 ;
84 outb(com_port, c);
85}
86
87unsigned char
88serial_getc(unsigned long com_port)
89{
90 while ((inb(com_port + (UART_LSR << shift)) & UART_LSR_DR) == 0)
91 ;
92 return inb(com_port);
93}
94
95int
96serial_tstc(unsigned long com_port)
97{
98 return ((inb(com_port + (UART_LSR << shift)) & UART_LSR_DR) != 0);
99}
diff --git a/arch/ppc/boot/common/serial_stub.c b/arch/ppc/boot/common/serial_stub.c
new file mode 100644
index 000000000000..03dfaa01fa63
--- /dev/null
+++ b/arch/ppc/boot/common/serial_stub.c
@@ -0,0 +1,23 @@
1/*
2 * arch/ppc/boot/common/serial_stub.c
3 *
4 * This is a few stub routines to make the boot code cleaner looking when
5 * there is no serial port support doesn't need to be closed, for example.
6 *
7 * Author: Tom Rini <trini@mvista.com>
8 *
9 * 2003 (c) MontaVista, Software, Inc. This file is licensed under the terms
10 * of the GNU General Public License version 2. This program is licensed "as
11 * is" without any warranty of any kind, whether express or implied.
12 */
13
14unsigned long __attribute__ ((weak))
15serial_init(int chan, void *ignored)
16{
17 return 0;
18}
19
20void __attribute__ ((weak))
21serial_close(unsigned long com_port)
22{
23}
diff --git a/arch/ppc/boot/common/string.S b/arch/ppc/boot/common/string.S
new file mode 100644
index 000000000000..8016e43c4771
--- /dev/null
+++ b/arch/ppc/boot/common/string.S
@@ -0,0 +1,150 @@
1/*
2 * String handling functions for PowerPC.
3 *
4 * Copyright (C) 1996 Paul Mackerras.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11#define r0 0
12#define r3 3
13#define r4 4
14#define r5 5
15#define r6 6
16#define r7 7
17#define r8 8
18
19 .globl strlen
20strlen:
21 addi r4,r3,-1
221: lbzu r0,1(r4)
23 cmpwi 0,r0,0
24 bne 1b
25 subf r3,r3,r4
26 blr
27
28 .globl memset
29memset:
30 rlwimi r4,r4,8,16,23
31 rlwimi r4,r4,16,0,15
32 addi r6,r3,-4
33 cmplwi 0,r5,4
34 blt 7f
35 stwu r4,4(r6)
36 beqlr
37 andi. r0,r6,3
38 add r5,r0,r5
39 subf r6,r0,r6
40 rlwinm r0,r5,32-2,2,31
41 mtctr r0
42 bdz 6f
431: stwu r4,4(r6)
44 bdnz 1b
456: andi. r5,r5,3
467: cmpwi 0,r5,0
47 beqlr
48 mtctr r5
49 addi r6,r6,3
508: stbu r4,1(r6)
51 bdnz 8b
52 blr
53
54 .globl memmove
55memmove:
56 cmplw 0,r3,r4
57 bgt backwards_memcpy
58 /* fall through */
59
60 .globl memcpy
61memcpy:
62 rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */
63 addi r6,r3,-4
64 addi r4,r4,-4
65 beq 2f /* if less than 8 bytes to do */
66 andi. r0,r6,3 /* get dest word aligned */
67 mtctr r7
68 bne 5f
691: lwz r7,4(r4)
70 lwzu r8,8(r4)
71 stw r7,4(r6)
72 stwu r8,8(r6)
73 bdnz 1b
74 andi. r5,r5,7
752: cmplwi 0,r5,4
76 blt 3f
77 lwzu r0,4(r4)
78 addi r5,r5,-4
79 stwu r0,4(r6)
803: cmpwi 0,r5,0
81 beqlr
82 mtctr r5
83 addi r4,r4,3
84 addi r6,r6,3
854: lbzu r0,1(r4)
86 stbu r0,1(r6)
87 bdnz 4b
88 blr
895: subfic r0,r0,4
90 mtctr r0
916: lbz r7,4(r4)
92 addi r4,r4,1
93 stb r7,4(r6)
94 addi r6,r6,1
95 bdnz 6b
96 subf r5,r0,r5
97 rlwinm. r7,r5,32-3,3,31
98 beq 2b
99 mtctr r7
100 b 1b
101
102 .globl backwards_memcpy
103backwards_memcpy:
104 rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */
105 add r6,r3,r5
106 add r4,r4,r5
107 beq 2f
108 andi. r0,r6,3
109 mtctr r7
110 bne 5f
1111: lwz r7,-4(r4)
112 lwzu r8,-8(r4)
113 stw r7,-4(r6)
114 stwu r8,-8(r6)
115 bdnz 1b
116 andi. r5,r5,7
1172: cmplwi 0,r5,4
118 blt 3f
119 lwzu r0,-4(r4)
120 subi r5,r5,4
121 stwu r0,-4(r6)
1223: cmpwi 0,r5,0
123 beqlr
124 mtctr r5
1254: lbzu r0,-1(r4)
126 stbu r0,-1(r6)
127 bdnz 4b
128 blr
1295: mtctr r0
1306: lbzu r7,-1(r4)
131 stbu r7,-1(r6)
132 bdnz 6b
133 subf r5,r0,r5
134 rlwinm. r7,r5,32-3,3,31
135 beq 2b
136 mtctr r7
137 b 1b
138
139 .globl memcmp
140memcmp:
141 cmpwi 0,r5,0
142 blelr
143 mtctr r5
144 addi r6,r3,-1
145 addi r4,r4,-1
1461: lbzu r3,1(r6)
147 lbzu r0,1(r4)
148 subf. r3,r0,r3
149 bdnzt 2,1b
150 blr
diff --git a/arch/ppc/boot/common/util.S b/arch/ppc/boot/common/util.S
new file mode 100644
index 000000000000..47e641455bc5
--- /dev/null
+++ b/arch/ppc/boot/common/util.S
@@ -0,0 +1,293 @@
1/*
2 * arch/ppc/boot/common/util.S
3 *
4 * Useful bootup functions, which are more easily done in asm than C.
5 *
6 * NOTE: Be very very careful about the registers you use here.
7 * We don't follow any ABI calling convention among the
8 * assembler functions that call each other, especially early
9 * in the initialization. Please preserve at least r3 and r4
10 * for these early functions, as they often contain information
11 * passed from boot roms into the C decompress function.
12 *
13 * Author: Tom Rini
14 * trini@mvista.com
15 * Derived from arch/ppc/boot/prep/head.S (Cort Dougan, many others).
16 *
17 * 2001-2004 (c) MontaVista, Software, Inc. This file is licensed under
18 * the terms of the GNU General Public License version 2. This program
19 * is licensed "as is" without any warranty of any kind, whether express
20 * or implied.
21 */
22
23#include <asm/processor.h>
24#include <asm/cache.h>
25#include <asm/ppc_asm.h>
26
27
28 .text
29
30#ifdef CONFIG_6xx
31 .globl disable_6xx_mmu
32disable_6xx_mmu:
33 /* Establish default MSR value, exception prefix 0xFFF.
34 * If necessary, this function must fix up the LR if we
35 * return to a different address space once the MMU is
36 * disabled.
37 */
38 li r8,MSR_IP|MSR_FP
39 mtmsr r8
40 isync
41
42 /* Test for a 601 */
43 mfpvr r10
44 srwi r10,r10,16
45 cmpwi 0,r10,1 /* 601 ? */
46 beq .clearbats_601
47
48 /* Clear BATs */
49 li r8,0
50 mtspr SPRN_DBAT0U,r8
51 mtspr SPRN_DBAT0L,r8
52 mtspr SPRN_DBAT1U,r8
53 mtspr SPRN_DBAT1L,r8
54 mtspr SPRN_DBAT2U,r8
55 mtspr SPRN_DBAT2L,r8
56 mtspr SPRN_DBAT3U,r8
57 mtspr SPRN_DBAT3L,r8
58.clearbats_601:
59 mtspr SPRN_IBAT0U,r8
60 mtspr SPRN_IBAT0L,r8
61 mtspr SPRN_IBAT1U,r8
62 mtspr SPRN_IBAT1L,r8
63 mtspr SPRN_IBAT2U,r8
64 mtspr SPRN_IBAT2L,r8
65 mtspr SPRN_IBAT3U,r8
66 mtspr SPRN_IBAT3L,r8
67 isync
68 sync
69 sync
70
71 /* Set segment registers */
72 li r8,16 /* load up segment register values */
73 mtctr r8 /* for context 0 */
74 lis r8,0x2000 /* Ku = 1, VSID = 0 */
75 li r10,0
763: mtsrin r8,r10
77 addi r8,r8,0x111 /* increment VSID */
78 addis r10,r10,0x1000 /* address of next segment */
79 bdnz 3b
80 blr
81
82 .globl disable_6xx_l1cache
83disable_6xx_l1cache:
84 /* Enable, invalidate and then disable the L1 icache/dcache. */
85 li r8,0
86 ori r8,r8,(HID0_ICE|HID0_DCE|HID0_ICFI|HID0_DCI)
87 mfspr r11,SPRN_HID0
88 or r11,r11,r8
89 andc r10,r11,r8
90 isync
91 mtspr SPRN_HID0,r8
92 sync
93 isync
94 mtspr SPRN_HID0,r10
95 sync
96 isync
97 blr
98#endif
99
100 .globl _setup_L2CR
101_setup_L2CR:
102/*
103 * We should be skipping this section on CPUs where this results in an
104 * illegal instruction. If not, please send trini@kernel.crashing.org
105 * the PVR of your CPU.
106 */
107 /* Invalidate/disable L2 cache */
108 sync
109 isync
110 mfspr r8,SPRN_L2CR
111 rlwinm r8,r8,0,1,31
112 oris r8,r8,L2CR_L2I@h
113 sync
114 isync
115 mtspr SPRN_L2CR,r8
116 sync
117 isync
118
119 /* Wait for the invalidation to complete */
120 mfspr r8,SPRN_PVR
121 srwi r8,r8,16
122 cmplwi cr0,r8,0x8000 /* 7450 */
123 cmplwi cr1,r8,0x8001 /* 7455 */
124 cmplwi cr2,r8,0x8002 /* 7457 */
125 cror 4*cr0+eq,4*cr0+eq,4*cr1+eq /* Now test if any are true. */
126 cror 4*cr0+eq,4*cr0+eq,4*cr2+eq
127 bne 2f
128
1291: mfspr r8,SPRN_L2CR /* On 745x, poll L2I bit (bit 10) */
130 rlwinm. r9,r8,0,10,10
131 bne 1b
132 b 3f
133
1342: mfspr r8,SPRN_L2CR /* On 75x & 74[01]0, poll L2IP bit (bit 31) */
135 rlwinm. r9,r8,0,31,31
136 bne 2b
137
1383: rlwinm r8,r8,0,11,9 /* Turn off L2I bit */
139 sync
140 isync
141 mtspr SPRN_L2CR,r8
142 sync
143 isync
144 blr
145
146 .globl _setup_L3CR
147_setup_L3CR:
148 /* Invalidate/disable L3 cache */
149 sync
150 isync
151 mfspr r8,SPRN_L3CR
152 rlwinm r8,r8,0,1,31
153 ori r8,r8,L3CR_L3I@l
154 sync
155 isync
156 mtspr SPRN_L3CR,r8
157 sync
158 isync
159
160 /* Wait for the invalidation to complete */
1611: mfspr r8,SPRN_L3CR
162 rlwinm. r9,r8,0,21,21
163 bne 1b
164
165 rlwinm r8,r8,0,22,20 /* Turn off L3I bit */
166 sync
167 isync
168 mtspr SPRN_L3CR,r8
169 sync
170 isync
171 blr
172
173
174/* udelay (on non-601 processors) needs to know the period of the
175 * timebase in nanoseconds. This used to be hardcoded to be 60ns
176 * (period of 66MHz/4). Now a variable is used that is initialized to
177 * 60 for backward compatibility, but it can be overridden as necessary
178 * with code something like this:
179 * extern unsigned long timebase_period_ns;
180 * timebase_period_ns = 1000000000 / bd->bi_tbfreq;
181 */
182 .data
183 .globl timebase_period_ns
184timebase_period_ns:
185 .long 60
186
187 .text
188/*
189 * Delay for a number of microseconds
190 */
191 .globl udelay
192udelay:
193 mfspr r4,SPRN_PVR
194 srwi r4,r4,16
195 cmpwi 0,r4,1 /* 601 ? */
196 bne .udelay_not_601
19700: li r0,86 /* Instructions / microsecond? */
198 mtctr r0
19910: addi r0,r0,0 /* NOP */
200 bdnz 10b
201 subic. r3,r3,1
202 bne 00b
203 blr
204
205.udelay_not_601:
206 mulli r4,r3,1000 /* nanoseconds */
207 /* Change r4 to be the number of ticks using:
208 * (nanoseconds + (timebase_period_ns - 1 )) / timebase_period_ns
209 * timebase_period_ns defaults to 60 (16.6MHz) */
210 lis r5,timebase_period_ns@ha
211 lwz r5,timebase_period_ns@l(r5)
212 add r4,r4,r5
213 addi r4,r4,-1
214 divw r4,r4,r5 /* BUS ticks */
2151: mftbu r5
216 mftb r6
217 mftbu r7
218 cmpw 0,r5,r7
219 bne 1b /* Get [synced] base time */
220 addc r9,r6,r4 /* Compute end time */
221 addze r8,r5
2222: mftbu r5
223 cmpw 0,r5,r8
224 blt 2b
225 bgt 3f
226 mftb r6
227 cmpw 0,r6,r9
228 blt 2b
2293: blr
230
231 .section ".relocate_code","xa"
232/*
233 * Flush and enable instruction cache
234 * First, flush the data cache in case it was enabled and may be
235 * holding instructions for copy back.
236 */
237_GLOBAL(flush_instruction_cache)
238 mflr r6
239 bl flush_data_cache
240
241#ifdef CONFIG_8xx
242 lis r3, IDC_INVALL@h
243 mtspr SPRN_IC_CST, r3
244 lis r3, IDC_ENABLE@h
245 mtspr SPRN_IC_CST, r3
246 lis r3, IDC_DISABLE@h
247 mtspr SPRN_DC_CST, r3
248#elif CONFIG_4xx
249 lis r3,start@h # r9 = &_start
250 lis r4,_etext@ha
251 addi r4,r4,_etext@l # r8 = &_etext
2521: dcbf r0,r3 # Flush the data cache
253 icbi r0,r3 # Invalidate the instruction cache
254 addi r3,r3,0x10 # Increment by one cache line
255 cmplwi cr0,r3,r4 # Are we at the end yet?
256 blt 1b # No, keep flushing and invalidating
257#else
258 /* Enable, invalidate and then disable the L1 icache/dcache. */
259 li r3,0
260 ori r3,r3,(HID0_ICE|HID0_DCE|HID0_ICFI|HID0_DCI)
261 mfspr r4,SPRN_HID0
262 or r5,r4,r3
263 isync
264 mtspr SPRN_HID0,r5
265 sync
266 isync
267 ori r5,r4,HID0_ICE /* Enable cache */
268 mtspr SPRN_HID0,r5
269 sync
270 isync
271#endif
272 mtlr r6
273 blr
274
275#define NUM_CACHE_LINES 128*8
276#define cache_flush_buffer 0x1000
277
278/*
279 * Flush data cache
280 * Do this by just reading lots of stuff into the cache.
281 */
282_GLOBAL(flush_data_cache)
283 lis r3,cache_flush_buffer@h
284 ori r3,r3,cache_flush_buffer@l
285 li r4,NUM_CACHE_LINES
286 mtctr r4
28700: lwz r4,0(r3)
288 addi r3,r3,L1_CACHE_BYTES /* Next line, please */
289 bdnz 00b
29010: blr
291
292 .previous
293