Linux Audio

Check our new training course

Loading...
v6.2
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * udbg for NS16550 compatible serial ports
  4 *
  5 * Copyright (C) 2001-2005 PPC 64 Team, IBM Corp
 
 
 
 
 
  6 */
  7#include <linux/types.h>
  8#include <asm/udbg.h>
  9#include <asm/io.h>
 10#include <asm/reg_a2.h>
 11#include <asm/early_ioremap.h>
 12
 13extern u8 real_readb(volatile u8 __iomem  *addr);
 14extern void real_writeb(u8 data, volatile u8 __iomem *addr);
 15extern u8 real_205_readb(volatile u8 __iomem  *addr);
 16extern void real_205_writeb(u8 data, volatile u8 __iomem *addr);
 17
 18#define UART_RBR	0
 19#define UART_IER	1
 20#define UART_FCR	2
 21#define UART_LCR	3
 22#define UART_MCR	4
 23#define UART_LSR	5
 24#define UART_MSR	6
 25#define UART_SCR	7
 26#define UART_THR	UART_RBR
 27#define UART_IIR	UART_FCR
 28#define UART_DLL	UART_RBR
 29#define UART_DLM	UART_IER
 30#define UART_DLAB	UART_LCR
 
 
 
 
 31
 32#define LSR_DR   0x01  /* Data ready */
 33#define LSR_OE   0x02  /* Overrun */
 34#define LSR_PE   0x04  /* Parity error */
 35#define LSR_FE   0x08  /* Framing error */
 36#define LSR_BI   0x10  /* Break */
 37#define LSR_THRE 0x20  /* Xmit holding register empty */
 38#define LSR_TEMT 0x40  /* Xmitter empty */
 39#define LSR_ERR  0x80  /* Error */
 40
 41#define LCR_DLAB 0x80
 42
 43static u8 (*udbg_uart_in)(unsigned int reg);
 44static void (*udbg_uart_out)(unsigned int reg, u8 data);
 45
 46static void udbg_uart_flush(void)
 47{
 48	if (!udbg_uart_in)
 49		return;
 50
 51	/* wait for idle */
 52	while ((udbg_uart_in(UART_LSR) & LSR_THRE) == 0)
 53		cpu_relax();
 54}
 55
 56static void udbg_uart_putc(char c)
 57{
 58	if (!udbg_uart_out)
 59		return;
 60
 61	if (c == '\n')
 62		udbg_uart_putc('\r');
 63	udbg_uart_flush();
 64	udbg_uart_out(UART_THR, c);
 65}
 66
 67static int udbg_uart_getc_poll(void)
 68{
 69	if (!udbg_uart_in)
 70		return -1;
 71
 72	if (!(udbg_uart_in(UART_LSR) & LSR_DR))
 73		return udbg_uart_in(UART_RBR);
 74
 75	return -1;
 76}
 77
 78static int udbg_uart_getc(void)
 79{
 80	if (!udbg_uart_in)
 81		return -1;
 82	/* wait for char */
 83	while (!(udbg_uart_in(UART_LSR) & LSR_DR))
 84		cpu_relax();
 85	return udbg_uart_in(UART_RBR);
 86}
 87
 88static void __init udbg_use_uart(void)
 89{
 90	udbg_putc = udbg_uart_putc;
 91	udbg_flush = udbg_uart_flush;
 92	udbg_getc = udbg_uart_getc;
 93	udbg_getc_poll = udbg_uart_getc_poll;
 
 
 94}
 95
 96void __init udbg_uart_setup(unsigned int speed, unsigned int clock)
 
 97{
 98	unsigned int dll, base_bauds;
 99
100	if (!udbg_uart_out)
101		return;
102
103	if (clock == 0)
104		clock = 1843200;
105	if (speed == 0)
106		speed = 9600;
107
108	base_bauds = clock / 16;
109	dll = base_bauds / speed;
110
111	udbg_uart_out(UART_LCR, 0x00);
112	udbg_uart_out(UART_IER, 0xff);
113	udbg_uart_out(UART_IER, 0x00);
114	udbg_uart_out(UART_LCR, LCR_DLAB);
115	udbg_uart_out(UART_DLL, dll & 0xff);
116	udbg_uart_out(UART_DLM, dll >> 8);
117	/* 8 data, 1 stop, no parity */
118	udbg_uart_out(UART_LCR, 0x3);
119	/* RTS/DTR */
120	udbg_uart_out(UART_MCR, 0x3);
121	/* Clear & enable FIFOs */
122	udbg_uart_out(UART_FCR, 0x7);
 
 
 
 
 
 
 
123}
124
125unsigned int __init udbg_probe_uart_speed(unsigned int clock)
126{
127	unsigned int dll, dlm, divisor, prescaler, speed;
128	u8 old_lcr;
 
129
130	old_lcr = udbg_uart_in(UART_LCR);
131
132	/* select divisor latch registers.  */
133	udbg_uart_out(UART_LCR, old_lcr | LCR_DLAB);
134
135	/* now, read the divisor */
136	dll = udbg_uart_in(UART_DLL);
137	dlm = udbg_uart_in(UART_DLM);
138	divisor = dlm << 8 | dll;
139
140	/* check prescaling */
141	if (udbg_uart_in(UART_MCR) & 0x80)
142		prescaler = 4;
143	else
144		prescaler = 1;
145
146	/* restore the LCR */
147	udbg_uart_out(UART_LCR, old_lcr);
148
149	/* calculate speed */
150	speed = (clock / prescaler) / (divisor * 16);
151
152	/* sanity check */
153	if (speed > (clock / 16))
154		speed = 9600;
155
156	return speed;
157}
158
159static union {
160	unsigned char __iomem *mmio_base;
161	unsigned long pio_base;
162} udbg_uart;
163
164static unsigned int udbg_uart_stride = 1;
165
166static u8 udbg_uart_in_pio(unsigned int reg)
167{
168	return inb(udbg_uart.pio_base + (reg * udbg_uart_stride));
 
 
 
 
 
 
 
 
 
 
 
 
 
169}
170
171static void udbg_uart_out_pio(unsigned int reg, u8 data)
172{
173	outb(data, udbg_uart.pio_base + (reg * udbg_uart_stride));
174}
175
176void __init udbg_uart_init_pio(unsigned long port, unsigned int stride)
177{
178	if (!port)
179		return;
180	udbg_uart.pio_base = port;
181	udbg_uart_stride = stride;
182	udbg_uart_in = udbg_uart_in_pio;
183	udbg_uart_out = udbg_uart_out_pio;
184	udbg_use_uart();
185}
 
186
187static u8 udbg_uart_in_mmio(unsigned int reg)
 
188{
189	return in_8(udbg_uart.mmio_base + (reg * udbg_uart_stride));
 
 
 
190}
191
192static void udbg_uart_out_mmio(unsigned int reg, u8 data)
193{
194	out_8(udbg_uart.mmio_base + (reg * udbg_uart_stride), data);
 
 
 
 
 
195}
196
197
198void __init udbg_uart_init_mmio(void __iomem *addr, unsigned int stride)
199{
200	if (!addr)
201		return;
202	udbg_uart.mmio_base = addr;
203	udbg_uart_stride = stride;
204	udbg_uart_in = udbg_uart_in_mmio;
205	udbg_uart_out = udbg_uart_out_mmio;
206	udbg_use_uart();
207}
208
209#ifdef CONFIG_PPC_MAPLE
 
 
 
 
 
210
211#define UDBG_UART_MAPLE_ADDR	((void __iomem *)0xf40003f8)
 
212
213static u8 udbg_uart_in_maple(unsigned int reg)
214{
215	return real_readb(UDBG_UART_MAPLE_ADDR + reg);
 
 
 
216}
217
218static void udbg_uart_out_maple(unsigned int reg, u8 val)
219{
220	real_writeb(val, UDBG_UART_MAPLE_ADDR + reg);
 
 
 
 
 
221}
222
223void __init udbg_init_maple_realmode(void)
224{
225	udbg_uart_in = udbg_uart_in_maple;
226	udbg_uart_out = udbg_uart_out_maple;
227	udbg_use_uart();
 
 
 
228}
229
230#endif /* CONFIG_PPC_MAPLE */
231
232#ifdef CONFIG_PPC_PASEMI
233
234#define UDBG_UART_PAS_ADDR	((void __iomem *)0xfcff03f8UL)
235
236static u8 udbg_uart_in_pas(unsigned int reg)
237{
238	return real_205_readb(UDBG_UART_PAS_ADDR + reg);
239}
240
241static void udbg_uart_out_pas(unsigned int reg, u8 val)
242{
243	real_205_writeb(val, UDBG_UART_PAS_ADDR + reg);
244}
 
245
246void __init udbg_init_pas_realmode(void)
 
247{
248	udbg_uart_in = udbg_uart_in_pas;
249	udbg_uart_out = udbg_uart_out_pas;
250	udbg_use_uart();
 
251}
252
253#endif /* CONFIG_PPC_PASEMI */
254
255#ifdef CONFIG_PPC_EARLY_DEBUG_44x
256
257#include <platforms/44x/44x.h>
258
259static u8 udbg_uart_in_44x_as1(unsigned int reg)
260{
261	return as1_readb((void __iomem *)PPC44x_EARLY_DEBUG_VIRTADDR + reg);
 
 
 
 
 
262}
263
264static void udbg_uart_out_44x_as1(unsigned int reg, u8 val)
265{
266	as1_writeb(val, (void __iomem *)PPC44x_EARLY_DEBUG_VIRTADDR + reg);
 
 
 
 
 
267}
268
269void __init udbg_init_44x_as1(void)
270{
271	udbg_uart_in = udbg_uart_in_44x_as1;
272	udbg_uart_out = udbg_uart_out_44x_as1;
273	udbg_use_uart();
274}
275
276#endif /* CONFIG_PPC_EARLY_DEBUG_44x */
277
278#ifdef CONFIG_PPC_EARLY_DEBUG_40x
 
 
 
279
280static u8 udbg_uart_in_40x(unsigned int reg)
 
281{
282	return real_readb((void __iomem *)CONFIG_PPC_EARLY_DEBUG_40x_PHYSADDR
283			  + reg);
 
 
284}
285
286static void udbg_uart_out_40x(unsigned int reg, u8 val)
287{
288	real_writeb(val, (void __iomem *)CONFIG_PPC_EARLY_DEBUG_40x_PHYSADDR
289		    + reg);
 
 
 
 
290}
291
292void __init udbg_init_40x_realmode(void)
293{
294	udbg_uart_in = udbg_uart_in_40x;
295	udbg_uart_out = udbg_uart_out_40x;
296	udbg_use_uart();
 
 
 
297}
298
299#endif /* CONFIG_PPC_EARLY_DEBUG_40x */
300
301#ifdef CONFIG_PPC_EARLY_DEBUG_16550
302
303static void __iomem *udbg_uart_early_addr;
304
305void __init udbg_init_debug_16550(void)
306{
307	udbg_uart_early_addr = early_ioremap(CONFIG_PPC_EARLY_DEBUG_16550_PHYSADDR, 0x1000);
308	udbg_uart_init_mmio(udbg_uart_early_addr, CONFIG_PPC_EARLY_DEBUG_16550_STRIDE);
 
 
309}
310
311static int __init udbg_init_debug_16550_ioremap(void)
312{
313	void __iomem *addr;
314
315	if (!udbg_uart_early_addr)
316		return 0;
317
318	addr = ioremap(CONFIG_PPC_EARLY_DEBUG_16550_PHYSADDR, 0x1000);
319	if (WARN_ON(!addr))
320		return -ENOMEM;
321
322	udbg_uart_init_mmio(addr, CONFIG_PPC_EARLY_DEBUG_16550_STRIDE);
323	early_iounmap(udbg_uart_early_addr, 0x1000);
324	udbg_uart_early_addr = NULL;
325
326	return 0;
327}
328
329early_initcall(udbg_init_debug_16550_ioremap);
330
331#endif /* CONFIG_PPC_EARLY_DEBUG_16550 */
v3.5.6
 
  1/*
  2 * udbg for NS16550 compatible 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/types.h>
 12#include <asm/udbg.h>
 13#include <asm/io.h>
 14#include <asm/reg_a2.h>
 
 15
 16extern u8 real_readb(volatile u8 __iomem  *addr);
 17extern void real_writeb(u8 data, volatile u8 __iomem *addr);
 18extern u8 real_205_readb(volatile u8 __iomem  *addr);
 19extern void real_205_writeb(u8 data, volatile u8 __iomem *addr);
 20
 21struct NS16550 {
 22	/* this struct must be packed */
 23	unsigned char rbr;  /* 0 */
 24	unsigned char ier;  /* 1 */
 25	unsigned char fcr;  /* 2 */
 26	unsigned char lcr;  /* 3 */
 27	unsigned char mcr;  /* 4 */
 28	unsigned char lsr;  /* 5 */
 29	unsigned char msr;  /* 6 */
 30	unsigned char scr;  /* 7 */
 31};
 32
 33#define thr rbr
 34#define iir fcr
 35#define dll rbr
 36#define dlm ier
 37#define dlab lcr
 38
 39#define LSR_DR   0x01  /* Data ready */
 40#define LSR_OE   0x02  /* Overrun */
 41#define LSR_PE   0x04  /* Parity error */
 42#define LSR_FE   0x08  /* Framing error */
 43#define LSR_BI   0x10  /* Break */
 44#define LSR_THRE 0x20  /* Xmit holding register empty */
 45#define LSR_TEMT 0x40  /* Xmitter empty */
 46#define LSR_ERR  0x80  /* Error */
 47
 48#define LCR_DLAB 0x80
 49
 50static struct NS16550 __iomem *udbg_comport;
 
 51
 52static void udbg_550_flush(void)
 53{
 54	if (udbg_comport) {
 55		while ((in_8(&udbg_comport->lsr) & LSR_THRE) == 0)
 56			/* wait for idle */;
 57	}
 
 
 58}
 59
 60static void udbg_550_putc(char c)
 61{
 62	if (udbg_comport) {
 63		if (c == '\n')
 64			udbg_550_putc('\r');
 65		udbg_550_flush();
 66		out_8(&udbg_comport->thr, c);
 67	}
 
 68}
 69
 70static int udbg_550_getc_poll(void)
 71{
 72	if (udbg_comport) {
 73		if ((in_8(&udbg_comport->lsr) & LSR_DR) != 0)
 74			return in_8(&udbg_comport->rbr);
 75		else
 76			return -1;
 77	}
 78	return -1;
 79}
 80
 81static int udbg_550_getc(void)
 
 
 
 
 
 
 
 
 
 
 82{
 83	if (udbg_comport) {
 84		while ((in_8(&udbg_comport->lsr) & LSR_DR) == 0)
 85			/* wait for char */;
 86		return in_8(&udbg_comport->rbr);
 87	}
 88	return -1;
 89}
 90
 91void udbg_init_uart(void __iomem *comport, unsigned int speed,
 92		    unsigned int clock)
 93{
 94	unsigned int dll, base_bauds;
 95
 
 
 
 96	if (clock == 0)
 97		clock = 1843200;
 98	if (speed == 0)
 99		speed = 9600;
100
101	base_bauds = clock / 16;
102	dll = base_bauds / speed;
103
104	if (comport) {
105		udbg_comport = (struct NS16550 __iomem *)comport;
106		out_8(&udbg_comport->lcr, 0x00);
107		out_8(&udbg_comport->ier, 0xff);
108		out_8(&udbg_comport->ier, 0x00);
109		out_8(&udbg_comport->lcr, LCR_DLAB);
110		out_8(&udbg_comport->dll, dll & 0xff);
111		out_8(&udbg_comport->dlm, dll >> 8);
112		/* 8 data, 1 stop, no parity */
113		out_8(&udbg_comport->lcr, 0x03);
114		/* RTS/DTR */
115		out_8(&udbg_comport->mcr, 0x03);
116		/* Clear & enable FIFOs */
117		out_8(&udbg_comport->fcr ,0x07);
118		udbg_putc = udbg_550_putc;
119		udbg_flush = udbg_550_flush;
120		udbg_getc = udbg_550_getc;
121		udbg_getc_poll = udbg_550_getc_poll;
122	}
123}
124
125unsigned int udbg_probe_uart_speed(void __iomem *comport, unsigned int clock)
126{
127	unsigned int dll, dlm, divisor, prescaler, speed;
128	u8 old_lcr;
129	struct NS16550 __iomem *port = comport;
130
131	old_lcr = in_8(&port->lcr);
132
133	/* select divisor latch registers.  */
134	out_8(&port->lcr, LCR_DLAB);
135
136	/* now, read the divisor */
137	dll = in_8(&port->dll);
138	dlm = in_8(&port->dlm);
139	divisor = dlm << 8 | dll;
140
141	/* check prescaling */
142	if (in_8(&port->mcr) & 0x80)
143		prescaler = 4;
144	else
145		prescaler = 1;
146
147	/* restore the LCR */
148	out_8(&port->lcr, old_lcr);
149
150	/* calculate speed */
151	speed = (clock / prescaler) / (divisor * 16);
152
153	/* sanity check */
154	if (speed > (clock / 16))
155		speed = 9600;
156
157	return speed;
158}
159
160#ifdef CONFIG_PPC_MAPLE
161void udbg_maple_real_flush(void)
 
 
 
 
 
 
162{
163	if (udbg_comport) {
164		while ((real_readb(&udbg_comport->lsr) & LSR_THRE) == 0)
165			/* wait for idle */;
166	}
167}
168
169void udbg_maple_real_putc(char c)
170{
171	if (udbg_comport) {
172		if (c == '\n')
173			udbg_maple_real_putc('\r');
174		udbg_maple_real_flush();
175		real_writeb(c, &udbg_comport->thr); eieio();
176	}
177}
178
179void __init udbg_init_maple_realmode(void)
180{
181	udbg_comport = (struct NS16550 __iomem *)0xf40003f8;
 
182
183	udbg_putc = udbg_maple_real_putc;
184	udbg_flush = udbg_maple_real_flush;
185	udbg_getc = NULL;
186	udbg_getc_poll = NULL;
 
 
 
 
 
187}
188#endif /* CONFIG_PPC_MAPLE */
189
190#ifdef CONFIG_PPC_PASEMI
191void udbg_pas_real_flush(void)
192{
193	if (udbg_comport) {
194		while ((real_205_readb(&udbg_comport->lsr) & LSR_THRE) == 0)
195			/* wait for idle */;
196	}
197}
198
199void udbg_pas_real_putc(char c)
200{
201	if (udbg_comport) {
202		if (c == '\n')
203			udbg_pas_real_putc('\r');
204		udbg_pas_real_flush();
205		real_205_writeb(c, &udbg_comport->thr); eieio();
206	}
207}
208
209void udbg_init_pas_realmode(void)
 
210{
211	udbg_comport = (struct NS16550 __iomem *)0xfcff03f8UL;
 
 
 
 
 
 
 
212
213	udbg_putc = udbg_pas_real_putc;
214	udbg_flush = udbg_pas_real_flush;
215	udbg_getc = NULL;
216	udbg_getc_poll = NULL;
217}
218#endif /* CONFIG_PPC_MAPLE */
219
220#ifdef CONFIG_PPC_EARLY_DEBUG_44x
221#include <platforms/44x/44x.h>
222
223static void udbg_44x_as1_flush(void)
224{
225	if (udbg_comport) {
226		while ((as1_readb(&udbg_comport->lsr) & LSR_THRE) == 0)
227			/* wait for idle */;
228	}
229}
230
231static void udbg_44x_as1_putc(char c)
232{
233	if (udbg_comport) {
234		if (c == '\n')
235			udbg_44x_as1_putc('\r');
236		udbg_44x_as1_flush();
237		as1_writeb(c, &udbg_comport->thr); eieio();
238	}
239}
240
241static int udbg_44x_as1_getc(void)
242{
243	if (udbg_comport) {
244		while ((as1_readb(&udbg_comport->lsr) & LSR_DR) == 0)
245			; /* wait for char */
246		return as1_readb(&udbg_comport->rbr);
247	}
248	return -1;
249}
250
251void __init udbg_init_44x_as1(void)
 
 
 
 
 
 
252{
253	udbg_comport =
254		(struct NS16550 __iomem *)PPC44x_EARLY_DEBUG_VIRTADDR;
255
256	udbg_putc = udbg_44x_as1_putc;
257	udbg_flush = udbg_44x_as1_flush;
258	udbg_getc = udbg_44x_as1_getc;
259}
260#endif /* CONFIG_PPC_EARLY_DEBUG_44x */
261
262#ifdef CONFIG_PPC_EARLY_DEBUG_40x
263static void udbg_40x_real_flush(void)
264{
265	if (udbg_comport) {
266		while ((real_readb(&udbg_comport->lsr) & LSR_THRE) == 0)
267			/* wait for idle */;
268	}
269}
270
271static void udbg_40x_real_putc(char c)
 
 
 
 
 
 
272{
273	if (udbg_comport) {
274		if (c == '\n')
275			udbg_40x_real_putc('\r');
276		udbg_40x_real_flush();
277		real_writeb(c, &udbg_comport->thr); eieio();
278	}
279}
280
281static int udbg_40x_real_getc(void)
282{
283	if (udbg_comport) {
284		while ((real_readb(&udbg_comport->lsr) & LSR_DR) == 0)
285			; /* wait for char */
286		return real_readb(&udbg_comport->rbr);
287	}
288	return -1;
289}
290
291void __init udbg_init_40x_realmode(void)
292{
293	udbg_comport = (struct NS16550 __iomem *)
294		CONFIG_PPC_EARLY_DEBUG_40x_PHYSADDR;
 
 
295
296	udbg_putc = udbg_40x_real_putc;
297	udbg_flush = udbg_40x_real_flush;
298	udbg_getc = udbg_40x_real_getc;
299	udbg_getc_poll = NULL;
300}
301#endif /* CONFIG_PPC_EARLY_DEBUG_40x */
302
303#ifdef CONFIG_PPC_EARLY_DEBUG_WSP
304static void udbg_wsp_flush(void)
305{
306	if (udbg_comport) {
307		while ((readb(&udbg_comport->lsr) & LSR_THRE) == 0)
308			/* wait for idle */;
309	}
310}
311
312static void udbg_wsp_putc(char c)
313{
314	if (udbg_comport) {
315		if (c == '\n')
316			udbg_wsp_putc('\r');
317		udbg_wsp_flush();
318		writeb(c, &udbg_comport->thr); eieio();
319	}
320}
321
322static int udbg_wsp_getc(void)
323{
324	if (udbg_comport) {
325		while ((readb(&udbg_comport->lsr) & LSR_DR) == 0)
326			; /* wait for char */
327		return readb(&udbg_comport->rbr);
328	}
329	return -1;
330}
331
332static int udbg_wsp_getc_poll(void)
 
 
 
 
 
 
333{
334	if (udbg_comport)
335		if (readb(&udbg_comport->lsr) & LSR_DR)
336			return readb(&udbg_comport->rbr);
337	return -1;
338}
339
340void __init udbg_init_wsp(void)
341{
342	udbg_comport = (struct NS16550 __iomem *)WSP_UART_VIRT;
 
 
 
343
344	udbg_init_uart(udbg_comport, 57600, 50000000);
 
 
345
346	udbg_putc = udbg_wsp_putc;
347	udbg_flush = udbg_wsp_flush;
348	udbg_getc = udbg_wsp_getc;
349	udbg_getc_poll = udbg_wsp_getc_poll;
 
350}
351#endif /* CONFIG_PPC_EARLY_DEBUG_WSP */