aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2005-11-11 00:42:12 -0500
committerPaul Mackerras <paulus@samba.org>2005-11-11 06:23:34 -0500
commit35cd8785de39c90a52287d0f041cff8a792eaa74 (patch)
treee45b94be971992d21f06086ef2ae443b90fd621b /arch/powerpc
parenta7df61a0e2b6300d8b8349c1e5e87a4336c0ab38 (diff)
[PATCH] powerpc: Move udbg code to arch/powerpc
Since the udbg code in ppc64 has no ppc32 equivalent, move it straight over into arch/powerpc (and include/asm-powerpc for udbg.h). In time, we probably want to meld the various bits and pieces of 32-bit early debugging code into udbg, but for now only include it on CONFIG_PPC64=y builds. The only change during the move is to standardise the protecting #ifdef/#define in udbg.h, and move its banner comment above the initial #ifdef (which seems to be normal practice). Built and booted on POWER5 LPAR (ARCH=powerpc and ARCH=ppc64). Built for 32bit multiplatform (ARCH=powerpc). Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/kernel/Makefile6
-rw-r--r--arch/powerpc/kernel/udbg.c125
-rw-r--r--arch/powerpc/kernel/udbg_16550.c123
-rw-r--r--arch/powerpc/kernel/udbg_scc.c135
4 files changed, 388 insertions, 1 deletions
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index c04bbd320594..c68eace12a9d 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -16,7 +16,7 @@ obj-y := semaphore.o cputable.o ptrace.o syscalls.o \
16obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ 16obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \
17 signal_64.o ptrace32.o systbl.o \ 17 signal_64.o ptrace32.o systbl.o \
18 paca.o ioctl32.o cpu_setup_power4.o \ 18 paca.o ioctl32.o cpu_setup_power4.o \
19 firmware.o sysfs.o 19 firmware.o sysfs.o udbg.o
20obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o 20obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o
21obj-$(CONFIG_POWER4) += idle_power4.o 21obj-$(CONFIG_POWER4) += idle_power4.o
22obj-$(CONFIG_PPC_OF) += of_device.o 22obj-$(CONFIG_PPC_OF) += of_device.o
@@ -29,6 +29,10 @@ obj-$(CONFIG_RTAS_PROC) += rtas-proc.o
29obj-$(CONFIG_LPARCFG) += lparcfg.o 29obj-$(CONFIG_LPARCFG) += lparcfg.o
30obj-$(CONFIG_IBMVIO) += vio.o 30obj-$(CONFIG_IBMVIO) += vio.o
31obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o 31obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o
32obj-$(CONFIG_PPC_PSERIES) += udbg_16550.o
33obj-$(CONFIG_PPC_MAPLE) += udbg_16550.o
34udbgscc-$(CONFIG_PPC64) := udbg_scc.o
35obj-$(CONFIG_PPC_PMAC) += $(udbgscc-y)
32 36
33ifeq ($(CONFIG_PPC_MERGE),y) 37ifeq ($(CONFIG_PPC_MERGE),y)
34 38
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c
new file mode 100644
index 000000000000..0d878e72fc44
--- /dev/null
+++ b/arch/powerpc/kernel/udbg.c
@@ -0,0 +1,125 @@
1/*
2 * polling mode stateless debugging stuff, originally for NS16550 Serial Ports
3 *
4 * c 2001 PPC 64 Team, IBM Corp
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
12#include <stdarg.h>
13#include <linux/config.h>
14#include <linux/types.h>
15#include <linux/sched.h>
16#include <linux/console.h>
17#include <asm/processor.h>
18
19void (*udbg_putc)(unsigned char c);
20unsigned char (*udbg_getc)(void);
21int (*udbg_getc_poll)(void);
22
23/* udbg library, used by xmon et al */
24void udbg_puts(const char *s)
25{
26 if (udbg_putc) {
27 char c;
28
29 if (s && *s != '\0') {
30 while ((c = *s++) != '\0')
31 udbg_putc(c);
32 }
33 }
34#if 0
35 else {
36 printk("%s", s);
37 }
38#endif
39}
40
41int udbg_write(const char *s, int n)
42{
43 int remain = n;
44 char c;
45
46 if (!udbg_putc)
47 return 0;
48
49 if (s && *s != '\0') {
50 while (((c = *s++) != '\0') && (remain-- > 0)) {
51 udbg_putc(c);
52 }
53 }
54
55 return n - remain;
56}
57
58int udbg_read(char *buf, int buflen)
59{
60 char c, *p = buf;
61 int i;
62
63 if (!udbg_getc)
64 return 0;
65
66 for (i = 0; i < buflen; ++i) {
67 do {
68 c = udbg_getc();
69 } while (c == 0x11 || c == 0x13);
70 if (c == 0)
71 break;
72 *p++ = c;
73 }
74
75 return i;
76}
77
78#define UDBG_BUFSIZE 256
79void udbg_printf(const char *fmt, ...)
80{
81 unsigned char buf[UDBG_BUFSIZE];
82 va_list args;
83
84 va_start(args, fmt);
85 vsnprintf(buf, UDBG_BUFSIZE, fmt, args);
86 udbg_puts(buf);
87 va_end(args);
88}
89
90/*
91 * Early boot console based on udbg
92 */
93static void udbg_console_write(struct console *con, const char *s,
94 unsigned int n)
95{
96 udbg_write(s, n);
97}
98
99static struct console udbg_console = {
100 .name = "udbg",
101 .write = udbg_console_write,
102 .flags = CON_PRINTBUFFER,
103 .index = -1,
104};
105
106static int early_console_initialized;
107
108void __init disable_early_printk(void)
109{
110 if (!early_console_initialized)
111 return;
112 unregister_console(&udbg_console);
113 early_console_initialized = 0;
114}
115
116/* called by setup_system */
117void register_early_udbg_console(void)
118{
119 early_console_initialized = 1;
120 register_console(&udbg_console);
121}
122
123#if 0 /* if you want to use this as a regular output console */
124console_initcall(register_udbg_console);
125#endif
diff --git a/arch/powerpc/kernel/udbg_16550.c b/arch/powerpc/kernel/udbg_16550.c
new file mode 100644
index 000000000000..9313574ab935
--- /dev/null
+++ b/arch/powerpc/kernel/udbg_16550.c
@@ -0,0 +1,123 @@
1/*
2 * udbg for for NS16550 compatable serial ports
3 *
4 * Copyright (C) 2001-2005 PPC 64 Team, IBM Corp
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#include <linux/config.h>
12#include <linux/types.h>
13#include <asm/udbg.h>
14#include <asm/io.h>
15
16extern u8 real_readb(volatile u8 __iomem *addr);
17extern void real_writeb(u8 data, volatile u8 __iomem *addr);
18
19struct NS16550 {
20 /* this struct must be packed */
21 unsigned char rbr; /* 0 */
22 unsigned char ier; /* 1 */
23 unsigned char fcr; /* 2 */
24 unsigned char lcr; /* 3 */
25 unsigned char mcr; /* 4 */
26 unsigned char lsr; /* 5 */
27 unsigned char msr; /* 6 */
28 unsigned char scr; /* 7 */
29};
30
31#define thr rbr
32#define iir fcr
33#define dll rbr
34#define dlm ier
35#define dlab lcr
36
37#define LSR_DR 0x01 /* Data ready */
38#define LSR_OE 0x02 /* Overrun */
39#define LSR_PE 0x04 /* Parity error */
40#define LSR_FE 0x08 /* Framing error */
41#define LSR_BI 0x10 /* Break */
42#define LSR_THRE 0x20 /* Xmit holding register empty */
43#define LSR_TEMT 0x40 /* Xmitter empty */
44#define LSR_ERR 0x80 /* Error */
45
46static volatile struct NS16550 __iomem *udbg_comport;
47
48static void udbg_550_putc(unsigned char c)
49{
50 if (udbg_comport) {
51 while ((in_8(&udbg_comport->lsr) & LSR_THRE) == 0)
52 /* wait for idle */;
53 out_8(&udbg_comport->thr, c);
54 if (c == '\n')
55 udbg_550_putc('\r');
56 }
57}
58
59static int udbg_550_getc_poll(void)
60{
61 if (udbg_comport) {
62 if ((in_8(&udbg_comport->lsr) & LSR_DR) != 0)
63 return in_8(&udbg_comport->rbr);
64 else
65 return -1;
66 }
67 return -1;
68}
69
70static unsigned char udbg_550_getc(void)
71{
72 if (udbg_comport) {
73 while ((in_8(&udbg_comport->lsr) & LSR_DR) == 0)
74 /* wait for char */;
75 return in_8(&udbg_comport->rbr);
76 }
77 return 0;
78}
79
80void udbg_init_uart(void __iomem *comport, unsigned int speed)
81{
82 u16 dll = speed ? (115200 / speed) : 12;
83
84 if (comport) {
85 udbg_comport = (struct NS16550 __iomem *)comport;
86 out_8(&udbg_comport->lcr, 0x00);
87 out_8(&udbg_comport->ier, 0xff);
88 out_8(&udbg_comport->ier, 0x00);
89 out_8(&udbg_comport->lcr, 0x80); /* Access baud rate */
90 out_8(&udbg_comport->dll, dll & 0xff); /* 1 = 115200, 2 = 57600,
91 3 = 38400, 12 = 9600 baud */
92 out_8(&udbg_comport->dlm, dll >> 8); /* dll >> 8 which should be zero
93 for fast rates; */
94 out_8(&udbg_comport->lcr, 0x03); /* 8 data, 1 stop, no parity */
95 out_8(&udbg_comport->mcr, 0x03); /* RTS/DTR */
96 out_8(&udbg_comport->fcr ,0x07); /* Clear & enable FIFOs */
97 udbg_putc = udbg_550_putc;
98 udbg_getc = udbg_550_getc;
99 udbg_getc_poll = udbg_550_getc_poll;
100 }
101}
102
103#ifdef CONFIG_PPC_MAPLE
104void udbg_maple_real_putc(unsigned char c)
105{
106 if (udbg_comport) {
107 while ((real_readb(&udbg_comport->lsr) & LSR_THRE) == 0)
108 /* wait for idle */;
109 real_writeb(c, &udbg_comport->thr); eieio();
110 if (c == '\n')
111 udbg_maple_real_putc('\r');
112 }
113}
114
115void udbg_init_maple_realmode(void)
116{
117 udbg_comport = (volatile struct NS16550 __iomem *)0xf40003f8;
118
119 udbg_putc = udbg_maple_real_putc;
120 udbg_getc = NULL;
121 udbg_getc_poll = NULL;
122}
123#endif /* CONFIG_PPC_MAPLE */
diff --git a/arch/powerpc/kernel/udbg_scc.c b/arch/powerpc/kernel/udbg_scc.c
new file mode 100644
index 000000000000..820c53551507
--- /dev/null
+++ b/arch/powerpc/kernel/udbg_scc.c
@@ -0,0 +1,135 @@
1/*
2 * udbg for for zilog scc ports as found on Apple PowerMacs
3 *
4 * Copyright (C) 2001-2005 PPC 64 Team, IBM Corp
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#include <linux/config.h>
12#include <linux/types.h>
13#include <asm/udbg.h>
14#include <asm/processor.h>
15#include <asm/io.h>
16#include <asm/prom.h>
17#include <asm/pmac_feature.h>
18
19extern u8 real_readb(volatile u8 __iomem *addr);
20extern void real_writeb(u8 data, volatile u8 __iomem *addr);
21
22#define SCC_TXRDY 4
23#define SCC_RXRDY 1
24
25static volatile u8 __iomem *sccc;
26static volatile u8 __iomem *sccd;
27
28static void udbg_scc_putc(unsigned char c)
29{
30 if (sccc) {
31 while ((in_8(sccc) & SCC_TXRDY) == 0)
32 ;
33 out_8(sccd, c);
34 if (c == '\n')
35 udbg_scc_putc('\r');
36 }
37}
38
39static int udbg_scc_getc_poll(void)
40{
41 if (sccc) {
42 if ((in_8(sccc) & SCC_RXRDY) != 0)
43 return in_8(sccd);
44 else
45 return -1;
46 }
47 return -1;
48}
49
50static unsigned char udbg_scc_getc(void)
51{
52 if (sccc) {
53 while ((in_8(sccc) & SCC_RXRDY) == 0)
54 ;
55 return in_8(sccd);
56 }
57 return 0;
58}
59
60static unsigned char scc_inittab[] = {
61 13, 0, /* set baud rate divisor */
62 12, 0,
63 14, 1, /* baud rate gen enable, src=rtxc */
64 11, 0x50, /* clocks = br gen */
65 5, 0xea, /* tx 8 bits, assert DTR & RTS */
66 4, 0x46, /* x16 clock, 1 stop */
67 3, 0xc1, /* rx enable, 8 bits */
68};
69
70void udbg_init_scc(struct device_node *np)
71{
72 u32 *reg;
73 unsigned long addr;
74 int i, x;
75
76 if (np == NULL)
77 np = of_find_node_by_name(NULL, "escc");
78 if (np == NULL || np->parent == NULL)
79 return;
80
81 udbg_printf("found SCC...\n");
82 /* Get address within mac-io ASIC */
83 reg = (u32 *)get_property(np, "reg", NULL);
84 if (reg == NULL)
85 return;
86 addr = reg[0];
87 udbg_printf("local addr: %lx\n", addr);
88 /* Get address of mac-io PCI itself */
89 reg = (u32 *)get_property(np->parent, "assigned-addresses", NULL);
90 if (reg == NULL)
91 return;
92 addr += reg[2];
93 udbg_printf("final addr: %lx\n", addr);
94
95 /* Setup for 57600 8N1 */
96 addr += 0x20;
97 sccc = (volatile u8 * __iomem) ioremap(addr & PAGE_MASK, PAGE_SIZE) ;
98 sccc += addr & ~PAGE_MASK;
99 sccd = sccc + 0x10;
100
101 udbg_printf("ioremap result sccc: %p\n", sccc);
102 mb();
103
104 for (i = 20000; i != 0; --i)
105 x = in_8(sccc);
106 out_8(sccc, 0x09); /* reset A or B side */
107 out_8(sccc, 0xc0);
108 for (i = 0; i < sizeof(scc_inittab); ++i)
109 out_8(sccc, scc_inittab[i]);
110
111 udbg_putc = udbg_scc_putc;
112 udbg_getc = udbg_scc_getc;
113 udbg_getc_poll = udbg_scc_getc_poll;
114
115 udbg_puts("Hello World !\n");
116}
117
118static void udbg_real_scc_putc(unsigned char c)
119{
120 while ((real_readb(sccc) & SCC_TXRDY) == 0)
121 ;
122 real_writeb(c, sccd);
123 if (c == '\n')
124 udbg_real_scc_putc('\r');
125}
126
127void udbg_init_pmac_realmode(void)
128{
129 sccc = (volatile u8 __iomem *)0x80013020ul;
130 sccd = (volatile u8 __iomem *)0x80013030ul;
131
132 udbg_putc = udbg_real_scc_putc;
133 udbg_getc = NULL;
134 udbg_getc_poll = NULL;
135}