2 * udbg for NS16550 compatible serial ports
4 * Copyright (C) 2001-2005 PPC 64 Team, IBM Corp
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.
11 #include <linux/types.h>
14 #include <asm/reg_a2.h>
16 extern u8
real_readb(volatile u8 __iomem
*addr
);
17 extern void real_writeb(u8 data
, volatile u8 __iomem
*addr
);
18 extern u8
real_205_readb(volatile u8 __iomem
*addr
);
19 extern void real_205_writeb(u8 data
, volatile u8 __iomem
*addr
);
29 #define UART_THR UART_RBR
30 #define UART_IIR UART_FCR
31 #define UART_DLL UART_RBR
32 #define UART_DLM UART_IER
33 #define UART_DLAB UART_LCR
35 #define LSR_DR 0x01 /* Data ready */
36 #define LSR_OE 0x02 /* Overrun */
37 #define LSR_PE 0x04 /* Parity error */
38 #define LSR_FE 0x08 /* Framing error */
39 #define LSR_BI 0x10 /* Break */
40 #define LSR_THRE 0x20 /* Xmit holding register empty */
41 #define LSR_TEMT 0x40 /* Xmitter empty */
42 #define LSR_ERR 0x80 /* Error */
46 static u8 (*udbg_uart_in
)(unsigned int reg
);
47 static void (*udbg_uart_out
)(unsigned int reg
, u8 data
);
49 static void udbg_uart_flush(void)
55 while ((udbg_uart_in(UART_LSR
) & LSR_THRE
) == 0)
59 static void udbg_uart_putc(char c
)
67 udbg_uart_out(UART_THR
, c
);
70 static int udbg_uart_getc_poll(void)
75 if (!(udbg_uart_in(UART_LSR
) & LSR_DR
))
76 return udbg_uart_in(UART_RBR
);
81 static int udbg_uart_getc(void)
86 while (!(udbg_uart_in(UART_LSR
) & LSR_DR
))
88 return udbg_uart_in(UART_RBR
);
91 static void udbg_use_uart(void)
93 udbg_putc
= udbg_uart_putc
;
94 udbg_flush
= udbg_uart_flush
;
95 udbg_getc
= udbg_uart_getc
;
96 udbg_getc_poll
= udbg_uart_getc_poll
;
99 void udbg_uart_setup(unsigned int speed
, unsigned int clock
)
101 unsigned int dll
, base_bauds
;
111 base_bauds
= clock
/ 16;
112 dll
= base_bauds
/ speed
;
114 udbg_uart_out(UART_LCR
, 0x00);
115 udbg_uart_out(UART_IER
, 0xff);
116 udbg_uart_out(UART_IER
, 0x00);
117 udbg_uart_out(UART_LCR
, LCR_DLAB
);
118 udbg_uart_out(UART_DLL
, dll
& 0xff);
119 udbg_uart_out(UART_DLM
, dll
>> 8);
120 /* 8 data, 1 stop, no parity */
121 udbg_uart_out(UART_LCR
, 0x3);
123 udbg_uart_out(UART_MCR
, 0x3);
124 /* Clear & enable FIFOs */
125 udbg_uart_out(UART_FCR
, 0x7);
128 unsigned int udbg_probe_uart_speed(unsigned int clock
)
130 unsigned int dll
, dlm
, divisor
, prescaler
, speed
;
133 old_lcr
= udbg_uart_in(UART_LCR
);
135 /* select divisor latch registers. */
136 udbg_uart_out(UART_LCR
, old_lcr
| LCR_DLAB
);
138 /* now, read the divisor */
139 dll
= udbg_uart_in(UART_DLL
);
140 dlm
= udbg_uart_in(UART_DLM
);
141 divisor
= dlm
<< 8 | dll
;
143 /* check prescaling */
144 if (udbg_uart_in(UART_MCR
) & 0x80)
149 /* restore the LCR */
150 udbg_uart_out(UART_LCR
, old_lcr
);
152 /* calculate speed */
153 speed
= (clock
/ prescaler
) / (divisor
* 16);
156 if (speed
> (clock
/ 16))
163 unsigned char __iomem
*mmio_base
;
164 unsigned long pio_base
;
167 static unsigned int udbg_uart_stride
= 1;
169 static u8
udbg_uart_in_pio(unsigned int reg
)
171 return inb(udbg_uart
.pio_base
+ (reg
* udbg_uart_stride
));
174 static void udbg_uart_out_pio(unsigned int reg
, u8 data
)
176 outb(data
, udbg_uart
.pio_base
+ (reg
* udbg_uart_stride
));
179 void udbg_uart_init_pio(unsigned long port
, unsigned int stride
)
183 udbg_uart
.pio_base
= port
;
184 udbg_uart_stride
= stride
;
185 udbg_uart_in
= udbg_uart_in_pio
;
186 udbg_uart_out
= udbg_uart_out_pio
;
190 static u8
udbg_uart_in_mmio(unsigned int reg
)
192 return in_8(udbg_uart
.mmio_base
+ (reg
* udbg_uart_stride
));
195 static void udbg_uart_out_mmio(unsigned int reg
, u8 data
)
197 out_8(udbg_uart
.mmio_base
+ (reg
* udbg_uart_stride
), data
);
201 void udbg_uart_init_mmio(void __iomem
*addr
, unsigned int stride
)
205 udbg_uart
.mmio_base
= addr
;
206 udbg_uart_stride
= stride
;
207 udbg_uart_in
= udbg_uart_in_mmio
;
208 udbg_uart_out
= udbg_uart_out_mmio
;
212 #ifdef CONFIG_PPC_MAPLE
214 #define UDBG_UART_MAPLE_ADDR ((void __iomem *)0xf40003f8)
216 static u8
udbg_uart_in_maple(unsigned int reg
)
218 return real_readb(UDBG_UART_MAPLE_ADDR
+ reg
);
221 static void udbg_uart_out_maple(unsigned int reg
, u8 val
)
223 real_writeb(val
, UDBG_UART_MAPLE_ADDR
+ reg
);
226 void __init
udbg_init_maple_realmode(void)
228 udbg_uart_in
= udbg_uart_in_maple
;
229 udbg_uart_out
= udbg_uart_out_maple
;
233 #endif /* CONFIG_PPC_MAPLE */
235 #ifdef CONFIG_PPC_PASEMI
237 #define UDBG_UART_PAS_ADDR ((void __iomem *)0xfcff03f8UL)
239 static u8
udbg_uart_in_pas(unsigned int reg
)
241 return real_205_readb(UDBG_UART_PAS_ADDR
+ reg
);
244 static void udbg_uart_out_pas(unsigned int reg
, u8 val
)
246 real_205_writeb(val
, UDBG_UART_PAS_ADDR
+ reg
);
249 void __init
udbg_init_pas_realmode(void)
251 udbg_uart_in
= udbg_uart_in_pas
;
252 udbg_uart_out
= udbg_uart_out_pas
;
256 #endif /* CONFIG_PPC_PASEMI */
258 #ifdef CONFIG_PPC_EARLY_DEBUG_44x
260 #include <platforms/44x/44x.h>
262 static u8
udbg_uart_in_44x_as1(unsigned int reg
)
264 return as1_readb((void __iomem
*)PPC44x_EARLY_DEBUG_VIRTADDR
+ reg
);
267 static void udbg_uart_out_44x_as1(unsigned int reg
, u8 val
)
269 as1_writeb(val
, (void __iomem
*)PPC44x_EARLY_DEBUG_VIRTADDR
+ reg
);
272 void __init
udbg_init_44x_as1(void)
274 udbg_uart_in
= udbg_uart_in_44x_as1
;
275 udbg_uart_out
= udbg_uart_out_44x_as1
;
279 #endif /* CONFIG_PPC_EARLY_DEBUG_44x */
281 #ifdef CONFIG_PPC_EARLY_DEBUG_40x
283 static u8
udbg_uart_in_40x(unsigned int reg
)
285 return real_readb((void __iomem
*)CONFIG_PPC_EARLY_DEBUG_40x_PHYSADDR
289 static void udbg_uart_out_40x(unsigned int reg
, u8 val
)
291 real_writeb(val
, (void __iomem
*)CONFIG_PPC_EARLY_DEBUG_40x_PHYSADDR
295 void __init
udbg_init_40x_realmode(void)
297 udbg_uart_in
= udbg_uart_in_40x
;
298 udbg_uart_out
= udbg_uart_out_40x
;
302 #endif /* CONFIG_PPC_EARLY_DEBUG_40x */