1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * udbg for NS16550 compatible serial ports
5 * Copyright (C) 2001-2005 PPC 64 Team, IBM Corp
7 #include <linux/types.h>
10 #include <asm/reg_a2.h>
12 extern u8
real_readb(volatile u8 __iomem
*addr
);
13 extern void real_writeb(u8 data
, volatile u8 __iomem
*addr
);
14 extern u8
real_205_readb(volatile u8 __iomem
*addr
);
15 extern void real_205_writeb(u8 data
, volatile u8 __iomem
*addr
);
25 #define UART_THR UART_RBR
26 #define UART_IIR UART_FCR
27 #define UART_DLL UART_RBR
28 #define UART_DLM UART_IER
29 #define UART_DLAB UART_LCR
31 #define LSR_DR 0x01 /* Data ready */
32 #define LSR_OE 0x02 /* Overrun */
33 #define LSR_PE 0x04 /* Parity error */
34 #define LSR_FE 0x08 /* Framing error */
35 #define LSR_BI 0x10 /* Break */
36 #define LSR_THRE 0x20 /* Xmit holding register empty */
37 #define LSR_TEMT 0x40 /* Xmitter empty */
38 #define LSR_ERR 0x80 /* Error */
42 static u8 (*udbg_uart_in
)(unsigned int reg
);
43 static void (*udbg_uart_out
)(unsigned int reg
, u8 data
);
45 static void udbg_uart_flush(void)
51 while ((udbg_uart_in(UART_LSR
) & LSR_THRE
) == 0)
55 static void udbg_uart_putc(char c
)
63 udbg_uart_out(UART_THR
, c
);
66 static int udbg_uart_getc_poll(void)
71 if (!(udbg_uart_in(UART_LSR
) & LSR_DR
))
72 return udbg_uart_in(UART_RBR
);
77 static int udbg_uart_getc(void)
82 while (!(udbg_uart_in(UART_LSR
) & LSR_DR
))
84 return udbg_uart_in(UART_RBR
);
87 static void udbg_use_uart(void)
89 udbg_putc
= udbg_uart_putc
;
90 udbg_flush
= udbg_uart_flush
;
91 udbg_getc
= udbg_uart_getc
;
92 udbg_getc_poll
= udbg_uart_getc_poll
;
95 void udbg_uart_setup(unsigned int speed
, unsigned int clock
)
97 unsigned int dll
, base_bauds
;
107 base_bauds
= clock
/ 16;
108 dll
= base_bauds
/ speed
;
110 udbg_uart_out(UART_LCR
, 0x00);
111 udbg_uart_out(UART_IER
, 0xff);
112 udbg_uart_out(UART_IER
, 0x00);
113 udbg_uart_out(UART_LCR
, LCR_DLAB
);
114 udbg_uart_out(UART_DLL
, dll
& 0xff);
115 udbg_uart_out(UART_DLM
, dll
>> 8);
116 /* 8 data, 1 stop, no parity */
117 udbg_uart_out(UART_LCR
, 0x3);
119 udbg_uart_out(UART_MCR
, 0x3);
120 /* Clear & enable FIFOs */
121 udbg_uart_out(UART_FCR
, 0x7);
124 unsigned int udbg_probe_uart_speed(unsigned int clock
)
126 unsigned int dll
, dlm
, divisor
, prescaler
, speed
;
129 old_lcr
= udbg_uart_in(UART_LCR
);
131 /* select divisor latch registers. */
132 udbg_uart_out(UART_LCR
, old_lcr
| LCR_DLAB
);
134 /* now, read the divisor */
135 dll
= udbg_uart_in(UART_DLL
);
136 dlm
= udbg_uart_in(UART_DLM
);
137 divisor
= dlm
<< 8 | dll
;
139 /* check prescaling */
140 if (udbg_uart_in(UART_MCR
) & 0x80)
145 /* restore the LCR */
146 udbg_uart_out(UART_LCR
, old_lcr
);
148 /* calculate speed */
149 speed
= (clock
/ prescaler
) / (divisor
* 16);
152 if (speed
> (clock
/ 16))
159 unsigned char __iomem
*mmio_base
;
160 unsigned long pio_base
;
163 static unsigned int udbg_uart_stride
= 1;
165 static u8
udbg_uart_in_pio(unsigned int reg
)
167 return inb(udbg_uart
.pio_base
+ (reg
* udbg_uart_stride
));
170 static void udbg_uart_out_pio(unsigned int reg
, u8 data
)
172 outb(data
, udbg_uart
.pio_base
+ (reg
* udbg_uart_stride
));
175 void udbg_uart_init_pio(unsigned long port
, unsigned int stride
)
179 udbg_uart
.pio_base
= port
;
180 udbg_uart_stride
= stride
;
181 udbg_uart_in
= udbg_uart_in_pio
;
182 udbg_uart_out
= udbg_uart_out_pio
;
186 static u8
udbg_uart_in_mmio(unsigned int reg
)
188 return in_8(udbg_uart
.mmio_base
+ (reg
* udbg_uart_stride
));
191 static void udbg_uart_out_mmio(unsigned int reg
, u8 data
)
193 out_8(udbg_uart
.mmio_base
+ (reg
* udbg_uart_stride
), data
);
197 void udbg_uart_init_mmio(void __iomem
*addr
, unsigned int stride
)
201 udbg_uart
.mmio_base
= addr
;
202 udbg_uart_stride
= stride
;
203 udbg_uart_in
= udbg_uart_in_mmio
;
204 udbg_uart_out
= udbg_uart_out_mmio
;
208 #ifdef CONFIG_PPC_MAPLE
210 #define UDBG_UART_MAPLE_ADDR ((void __iomem *)0xf40003f8)
212 static u8
udbg_uart_in_maple(unsigned int reg
)
214 return real_readb(UDBG_UART_MAPLE_ADDR
+ reg
);
217 static void udbg_uart_out_maple(unsigned int reg
, u8 val
)
219 real_writeb(val
, UDBG_UART_MAPLE_ADDR
+ reg
);
222 void __init
udbg_init_maple_realmode(void)
224 udbg_uart_in
= udbg_uart_in_maple
;
225 udbg_uart_out
= udbg_uart_out_maple
;
229 #endif /* CONFIG_PPC_MAPLE */
231 #ifdef CONFIG_PPC_PASEMI
233 #define UDBG_UART_PAS_ADDR ((void __iomem *)0xfcff03f8UL)
235 static u8
udbg_uart_in_pas(unsigned int reg
)
237 return real_205_readb(UDBG_UART_PAS_ADDR
+ reg
);
240 static void udbg_uart_out_pas(unsigned int reg
, u8 val
)
242 real_205_writeb(val
, UDBG_UART_PAS_ADDR
+ reg
);
245 void __init
udbg_init_pas_realmode(void)
247 udbg_uart_in
= udbg_uart_in_pas
;
248 udbg_uart_out
= udbg_uart_out_pas
;
252 #endif /* CONFIG_PPC_PASEMI */
254 #ifdef CONFIG_PPC_EARLY_DEBUG_44x
256 #include <platforms/44x/44x.h>
258 static u8
udbg_uart_in_44x_as1(unsigned int reg
)
260 return as1_readb((void __iomem
*)PPC44x_EARLY_DEBUG_VIRTADDR
+ reg
);
263 static void udbg_uart_out_44x_as1(unsigned int reg
, u8 val
)
265 as1_writeb(val
, (void __iomem
*)PPC44x_EARLY_DEBUG_VIRTADDR
+ reg
);
268 void __init
udbg_init_44x_as1(void)
270 udbg_uart_in
= udbg_uart_in_44x_as1
;
271 udbg_uart_out
= udbg_uart_out_44x_as1
;
275 #endif /* CONFIG_PPC_EARLY_DEBUG_44x */
277 #ifdef CONFIG_PPC_EARLY_DEBUG_40x
279 static u8
udbg_uart_in_40x(unsigned int reg
)
281 return real_readb((void __iomem
*)CONFIG_PPC_EARLY_DEBUG_40x_PHYSADDR
285 static void udbg_uart_out_40x(unsigned int reg
, u8 val
)
287 real_writeb(val
, (void __iomem
*)CONFIG_PPC_EARLY_DEBUG_40x_PHYSADDR
291 void __init
udbg_init_40x_realmode(void)
293 udbg_uart_in
= udbg_uart_in_40x
;
294 udbg_uart_out
= udbg_uart_out_40x
;
298 #endif /* CONFIG_PPC_EARLY_DEBUG_40x */