]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/ppc64/kernel/udbg.c
b531583b88d71589066be26cee2ccbc780d88a77
[linux-2.6-omap-h63xx.git] / arch / ppc64 / kernel / udbg.c
1 /*
2  * NS16550 Serial Port (uart) debugging stuff.
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 #define WANT_PPCDBG_TAB /* Only defined here */
14 #include <linux/config.h>
15 #include <linux/types.h>
16 #include <asm/ppcdebug.h>
17 #include <asm/processor.h>
18 #include <asm/uaccess.h>
19 #include <asm/machdep.h>
20 #include <asm/io.h>
21 #include <asm/prom.h>
22 #include <asm/pmac_feature.h>
23
24 extern u8 real_readb(volatile u8 __iomem  *addr);
25 extern void real_writeb(u8 data, volatile u8 __iomem *addr);
26
27 struct NS16550 {
28         /* this struct must be packed */
29         unsigned char rbr;  /* 0 */
30         unsigned char ier;  /* 1 */
31         unsigned char fcr;  /* 2 */
32         unsigned char lcr;  /* 3 */
33         unsigned char mcr;  /* 4 */
34         unsigned char lsr;  /* 5 */
35         unsigned char msr;  /* 6 */
36         unsigned char scr;  /* 7 */
37 };
38
39 #define thr rbr
40 #define iir fcr
41 #define dll rbr
42 #define dlm ier
43 #define dlab lcr
44
45 #define LSR_DR   0x01  /* Data ready */
46 #define LSR_OE   0x02  /* Overrun */
47 #define LSR_PE   0x04  /* Parity error */
48 #define LSR_FE   0x08  /* Framing error */
49 #define LSR_BI   0x10  /* Break */
50 #define LSR_THRE 0x20  /* Xmit holding register empty */
51 #define LSR_TEMT 0x40  /* Xmitter empty */
52 #define LSR_ERR  0x80  /* Error */
53
54 static volatile struct NS16550 __iomem *udbg_comport;
55
56 void udbg_init_uart(void __iomem *comport, unsigned int speed)
57 {
58         u16 dll = speed ? (115200 / speed) : 12;
59
60         if (comport) {
61                 udbg_comport = (struct NS16550 __iomem *)comport;
62                 out_8(&udbg_comport->lcr, 0x00);
63                 out_8(&udbg_comport->ier, 0xff);
64                 out_8(&udbg_comport->ier, 0x00);
65                 out_8(&udbg_comport->lcr, 0x80);        /* Access baud rate */
66                 out_8(&udbg_comport->dll, dll & 0xff);  /* 1 = 115200,  2 = 57600,
67                                                            3 = 38400, 12 = 9600 baud */
68                 out_8(&udbg_comport->dlm, dll >> 8);    /* dll >> 8 which should be zero
69                                                            for fast rates; */
70                 out_8(&udbg_comport->lcr, 0x03);        /* 8 data, 1 stop, no parity */
71                 out_8(&udbg_comport->mcr, 0x03);        /* RTS/DTR */
72                 out_8(&udbg_comport->fcr ,0x07);        /* Clear & enable FIFOs */
73                 ppc_md.udbg_putc = udbg_putc;           /* set access methods */
74                 ppc_md.udbg_getc = udbg_getc;
75                 ppc_md.udbg_getc_poll = udbg_getc_poll;
76         }
77 }
78
79 #ifdef CONFIG_PPC_PMAC
80
81 #define SCC_TXRDY       4
82 #define SCC_RXRDY       1
83
84 static volatile u8 __iomem *sccc;
85 static volatile u8 __iomem *sccd;
86
87 static unsigned char scc_inittab[] = {
88     13, 0,              /* set baud rate divisor */
89     12, 0,
90     14, 1,              /* baud rate gen enable, src=rtxc */
91     11, 0x50,           /* clocks = br gen */
92     5,  0xea,           /* tx 8 bits, assert DTR & RTS */
93     4,  0x46,           /* x16 clock, 1 stop */
94     3,  0xc1,           /* rx enable, 8 bits */
95 };
96
97 void udbg_init_scc(struct device_node *np)
98 {
99         u32 *reg;
100         unsigned long addr;
101         int i, x;
102
103         if (np == NULL)
104                 np = of_find_node_by_name(NULL, "escc");
105         if (np == NULL || np->parent == NULL)
106                 return;
107
108         udbg_printf("found SCC...\n");
109         /* Get address within mac-io ASIC */ 
110         reg = (u32 *)get_property(np, "reg", NULL);
111         if (reg == NULL)
112                 return;
113         addr = reg[0];
114         udbg_printf("local addr: %lx\n", addr);
115         /* Get address of mac-io PCI itself */
116         reg = (u32 *)get_property(np->parent, "assigned-addresses", NULL);
117         if (reg == NULL)
118                 return;
119         addr += reg[2];
120         udbg_printf("final addr: %lx\n", addr);
121
122         /* Setup for 57600 8N1 */
123         addr += 0x20;
124         sccc = (volatile u8 * __iomem) ioremap(addr & PAGE_MASK, PAGE_SIZE) ;
125         sccc += addr & ~PAGE_MASK;
126         sccd = sccc + 0x10;
127
128         udbg_printf("ioremap result sccc: %p\n", sccc);
129         mb();
130
131         for (i = 20000; i != 0; --i)
132                 x = in_8(sccc);
133         out_8(sccc, 0x09);              /* reset A or B side */
134         out_8(sccc, 0xc0);
135         for (i = 0; i < sizeof(scc_inittab); ++i)
136                 out_8(sccc, scc_inittab[i]);
137
138         ppc_md.udbg_putc = udbg_putc;
139         ppc_md.udbg_getc = udbg_getc;
140         ppc_md.udbg_getc_poll = udbg_getc_poll;
141
142         udbg_puts("Hello World !\n");
143 }
144
145 #endif /* CONFIG_PPC_PMAC */
146
147 #ifdef CONFIG_PPC_PMAC
148 static void udbg_real_putc(unsigned char c)
149 {
150         while ((real_readb(sccc) & SCC_TXRDY) == 0)
151                 ;
152         real_writeb(c, sccd);
153         if (c == '\n')
154                 udbg_real_putc('\r');
155 }
156
157 void udbg_init_pmac_realmode(void)
158 {
159         sccc = (volatile u8 __iomem *)0x80013020ul;
160         sccd = (volatile u8 __iomem *)0x80013030ul;
161
162         ppc_md.udbg_putc = udbg_real_putc;
163         ppc_md.udbg_getc = NULL;
164         ppc_md.udbg_getc_poll = NULL;
165 }
166 #endif /* CONFIG_PPC_PMAC */
167
168 #ifdef CONFIG_PPC_MAPLE
169 void udbg_maple_real_putc(unsigned char c)
170 {
171         if (udbg_comport) {
172                 while ((real_readb(&udbg_comport->lsr) & LSR_THRE) == 0)
173                         /* wait for idle */;
174                 real_writeb(c, &udbg_comport->thr); eieio();
175                 if (c == '\n')
176                         udbg_maple_real_putc('\r');
177         }
178 }
179
180 void udbg_init_maple_realmode(void)
181 {
182         udbg_comport = (volatile struct NS16550 __iomem *)0xf40003f8;
183
184         ppc_md.udbg_putc = udbg_maple_real_putc;
185         ppc_md.udbg_getc = NULL;
186         ppc_md.udbg_getc_poll = NULL;
187 }
188 #endif /* CONFIG_PPC_MAPLE */
189
190 void udbg_putc(unsigned char c)
191 {
192         if (udbg_comport) {
193                 while ((in_8(&udbg_comport->lsr) & LSR_THRE) == 0)
194                         /* wait for idle */;
195                 out_8(&udbg_comport->thr, c);
196                 if (c == '\n')
197                         udbg_putc('\r');
198         }
199 #ifdef CONFIG_PPC_PMAC
200         else if (sccc) {
201                 while ((in_8(sccc) & SCC_TXRDY) == 0)
202                         ;
203                 out_8(sccd,  c);                
204                 if (c == '\n')
205                         udbg_putc('\r');
206         }
207 #endif /* CONFIG_PPC_PMAC */
208 }
209
210 int udbg_getc_poll(void)
211 {
212         if (udbg_comport) {
213                 if ((in_8(&udbg_comport->lsr) & LSR_DR) != 0)
214                         return in_8(&udbg_comport->rbr);
215                 else
216                         return -1;
217         }
218 #ifdef CONFIG_PPC_PMAC
219         else if (sccc) {
220                 if ((in_8(sccc) & SCC_RXRDY) != 0)
221                         return in_8(sccd);
222                 else
223                         return -1;
224         }
225 #endif /* CONFIG_PPC_PMAC */
226         return -1;
227 }
228
229 unsigned char udbg_getc(void)
230 {
231         if (udbg_comport) {
232                 while ((in_8(&udbg_comport->lsr) & LSR_DR) == 0)
233                         /* wait for char */;
234                 return in_8(&udbg_comport->rbr);
235         }
236 #ifdef CONFIG_PPC_PMAC
237         else if (sccc) {
238                 while ((in_8(sccc) & SCC_RXRDY) == 0)
239                         ;
240                 return in_8(sccd);
241         }
242 #endif /* CONFIG_PPC_PMAC */
243         return 0;
244 }
245
246 void udbg_puts(const char *s)
247 {
248         if (ppc_md.udbg_putc) {
249                 char c;
250
251                 if (s && *s != '\0') {
252                         while ((c = *s++) != '\0')
253                                 ppc_md.udbg_putc(c);
254                 }
255         }
256 #if 0
257         else {
258                 printk("%s", s);
259         }
260 #endif
261 }
262
263 int udbg_write(const char *s, int n)
264 {
265         int remain = n;
266         char c;
267
268         if (!ppc_md.udbg_putc)
269                 return 0;
270
271         if (s && *s != '\0') {
272                 while (((c = *s++) != '\0') && (remain-- > 0)) {
273                         ppc_md.udbg_putc(c);
274                 }
275         }
276
277         return n - remain;
278 }
279
280 int udbg_read(char *buf, int buflen)
281 {
282         char c, *p = buf;
283         int i;
284
285         if (!ppc_md.udbg_getc)
286                 return 0;
287
288         for (i = 0; i < buflen; ++i) {
289                 do {
290                         c = ppc_md.udbg_getc();
291                 } while (c == 0x11 || c == 0x13);
292                 if (c == 0)
293                         break;
294                 *p++ = c;
295         }
296
297         return i;
298 }
299
300 void udbg_console_write(struct console *con, const char *s, unsigned int n)
301 {
302         udbg_write(s, n);
303 }
304
305 #define UDBG_BUFSIZE 256
306 void udbg_printf(const char *fmt, ...)
307 {
308         unsigned char buf[UDBG_BUFSIZE];
309         va_list args;
310
311         va_start(args, fmt);
312         vsnprintf(buf, UDBG_BUFSIZE, fmt, args);
313         udbg_puts(buf);
314         va_end(args);
315 }
316
317 /* Special print used by PPCDBG() macro */
318 void udbg_ppcdbg(unsigned long debug_flags, const char *fmt, ...)
319 {
320         unsigned long active_debugs = debug_flags & ppc64_debug_switch;
321
322         if (active_debugs) {
323                 va_list ap;
324                 unsigned char buf[UDBG_BUFSIZE];
325                 unsigned long i, len = 0;
326
327                 for (i=0; i < PPCDBG_NUM_FLAGS; i++) {
328                         if (((1U << i) & active_debugs) && 
329                             trace_names[i]) {
330                                 len += strlen(trace_names[i]); 
331                                 udbg_puts(trace_names[i]);
332                                 break;
333                         }
334                 }
335
336                 snprintf(buf, UDBG_BUFSIZE, " [%s]: ", current->comm);
337                 len += strlen(buf); 
338                 udbg_puts(buf);
339
340                 while (len < 18) {
341                         udbg_puts(" ");
342                         len++;
343                 }
344
345                 va_start(ap, fmt);
346                 vsnprintf(buf, UDBG_BUFSIZE, fmt, ap);
347                 udbg_puts(buf);
348                 va_end(ap);
349         }
350 }
351
352 unsigned long udbg_ifdebug(unsigned long flags)
353 {
354         return (flags & ppc64_debug_switch);
355 }