aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@linux-mips.org>2007-07-17 07:03:50 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-17 13:23:03 -0400
commitb45d52797432bd6b5d9786dbda940eb8d0b9ed06 (patch)
tree1bc6d7961c37c5cab006976b90ab084a11f33457
parentf9e86f419073605b4520848021cc042963c227c7 (diff)
sb1250-duart.c: SB1250 DUART serial support
This is a driver for the SB1250 DUART, a dual serial port implementation included in the Broadcom family of SOCs descending from the SiByte SB1250 MIPS64 chip multiprocessor. It is a new implementation replacing the old-fashioned driver currently present in the linux-mips.org tree. It supports all the usual features one would expect from a(n asynchronous) serial driver, including modem line control (as far as hardware supports it -- there is edge detection logic missing from the DCD and RI lines and the driver does not implement polling of these lines at the moment), the serial console, BREAK transmission and reception, including the magic SysRq. The receive FIFO threshold is not maintained though. The driver was tested with a SWARM board which uses a BCM1250 SOC (which is dual MIPS64 CMP) and has both ports of the single DUART implemented wired externally. Both were tested. Testing included using the ports as terminal lines at 1200bps (which is the ports minimum), 115200bps and a couple of random speeds inbetween. The modem lines were verified to operate correctly. No testing was performed with a use as a network interface, like with SLIP or PPP. Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org> Acked-by: Ralf Baechle <ralf@linux-mips.org> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--arch/mips/sibyte/bcm1480/setup.c1
-rw-r--r--arch/mips/sibyte/sb1250/setup.c1
-rw-r--r--drivers/serial/Kconfig28
-rw-r--r--drivers/serial/Makefile1
-rw-r--r--drivers/serial/sb1250-duart.c972
-rw-r--r--include/asm-mips/sibyte/bcm1480_regs.h30
-rw-r--r--include/asm-mips/sibyte/sb1250_regs.h76
-rw-r--r--include/asm-mips/sibyte/sb1250_uart.h7
-rw-r--r--include/linux/serial_core.h3
9 files changed, 1074 insertions, 45 deletions
diff --git a/arch/mips/sibyte/bcm1480/setup.c b/arch/mips/sibyte/bcm1480/setup.c
index bdaac34ae708..89f29233cae1 100644
--- a/arch/mips/sibyte/bcm1480/setup.c
+++ b/arch/mips/sibyte/bcm1480/setup.c
@@ -31,6 +31,7 @@
31unsigned int sb1_pass; 31unsigned int sb1_pass;
32unsigned int soc_pass; 32unsigned int soc_pass;
33unsigned int soc_type; 33unsigned int soc_type;
34EXPORT_SYMBOL(soc_type);
34unsigned int periph_rev; 35unsigned int periph_rev;
35unsigned int zbbus_mhz; 36unsigned int zbbus_mhz;
36 37
diff --git a/arch/mips/sibyte/sb1250/setup.c b/arch/mips/sibyte/sb1250/setup.c
index f4a6169aa0a4..2d5c6d8b41f2 100644
--- a/arch/mips/sibyte/sb1250/setup.c
+++ b/arch/mips/sibyte/sb1250/setup.c
@@ -31,6 +31,7 @@
31unsigned int sb1_pass; 31unsigned int sb1_pass;
32unsigned int soc_pass; 32unsigned int soc_pass;
33unsigned int soc_type; 33unsigned int soc_type;
34EXPORT_SYMBOL(soc_type);
34unsigned int periph_rev; 35unsigned int periph_rev;
35unsigned int zbbus_mhz; 36unsigned int zbbus_mhz;
36EXPORT_SYMBOL(zbbus_mhz); 37EXPORT_SYMBOL(zbbus_mhz);
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index cab42cbd920d..7fa413ddccf5 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -338,6 +338,34 @@ config SERIAL_AMBA_PL011_CONSOLE
338 your boot loader (lilo or loadlin) about how to pass options to the 338 your boot loader (lilo or loadlin) about how to pass options to the
339 kernel at boot time.) 339 kernel at boot time.)
340 340
341config SERIAL_SB1250_DUART
342 tristate "BCM1xxx on-chip DUART serial support"
343 depends on SIBYTE_SB1xxx_SOC=y
344 select SERIAL_CORE
345 default y
346 ---help---
347 Support for the asynchronous serial interface (DUART) included in
348 the BCM1250 and derived System-On-a-Chip (SOC) devices. Note that
349 the letter D in DUART stands for "dual", which is how the device
350 is implemented. Depending on the SOC configuration there may be
351 one or more DUARTs available of which all are handled.
352
353 If unsure, say Y. To compile this driver as a module, choose M here:
354 the module will be called sb1250-duart.
355
356config SERIAL_SB1250_DUART_CONSOLE
357 bool "Support for console on a BCM1xxx DUART serial port"
358 depends on SERIAL_SB1250_DUART=y
359 select SERIAL_CORE_CONSOLE
360 default y
361 ---help---
362 If you say Y here, it will be possible to use a serial port as the
363 system console (the system console is the device which receives all
364 kernel messages and warnings and which allows logins in single user
365 mode).
366
367 If unsure, say Y.
368
341config SERIAL_ATMEL 369config SERIAL_ATMEL
342 bool "AT91 / AT32 on-chip serial port support" 370 bool "AT91 / AT32 on-chip serial port support"
343 depends on (ARM && ARCH_AT91) || AVR32 371 depends on (ARM && ARCH_AT91) || AVR32
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 08ad0d978183..c48cdd61b736 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_SERIAL_MPC52xx) += mpc52xx_uart.o
51obj-$(CONFIG_SERIAL_ICOM) += icom.o 51obj-$(CONFIG_SERIAL_ICOM) += icom.o
52obj-$(CONFIG_SERIAL_M32R_SIO) += m32r_sio.o 52obj-$(CONFIG_SERIAL_M32R_SIO) += m32r_sio.o
53obj-$(CONFIG_SERIAL_MPSC) += mpsc.o 53obj-$(CONFIG_SERIAL_MPSC) += mpsc.o
54obj-$(CONFIG_SERIAL_SB1250_DUART) += sb1250-duart.o
54obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o 55obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o
55obj-$(CONFIG_SERIAL_JSM) += jsm/ 56obj-$(CONFIG_SERIAL_JSM) += jsm/
56obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o 57obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o
diff --git a/drivers/serial/sb1250-duart.c b/drivers/serial/sb1250-duart.c
new file mode 100644
index 000000000000..1d9d7285172a
--- /dev/null
+++ b/drivers/serial/sb1250-duart.c
@@ -0,0 +1,972 @@
1/*
2 * drivers/serial/sb1250-duart.c
3 *
4 * Support for the asynchronous serial interface (DUART) included
5 * in the BCM1250 and derived System-On-a-Chip (SOC) devices.
6 *
7 * Copyright (c) 2007 Maciej W. Rozycki
8 *
9 * Derived from drivers/char/sb1250_duart.c for which the following
10 * copyright applies:
11 *
12 * Copyright (c) 2000, 2001, 2002, 2003, 2004 Broadcom Corporation
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version
17 * 2 of the License, or (at your option) any later version.
18 *
19 * References:
20 *
21 * "BCM1250/BCM1125/BCM1125H User Manual", Broadcom Corporation
22 */
23
24#if defined(CONFIG_SERIAL_SB1250_DUART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
25#define SUPPORT_SYSRQ
26#endif
27
28#include <linux/console.h>
29#include <linux/delay.h>
30#include <linux/errno.h>
31#include <linux/init.h>
32#include <linux/interrupt.h>
33#include <linux/ioport.h>
34#include <linux/kernel.h>
35#include <linux/major.h>
36#include <linux/serial.h>
37#include <linux/serial_core.h>
38#include <linux/spinlock.h>
39#include <linux/sysrq.h>
40#include <linux/tty.h>
41#include <linux/types.h>
42
43#include <asm/atomic.h>
44#include <asm/io.h>
45#include <asm/war.h>
46
47#include <asm/sibyte/sb1250.h>
48#include <asm/sibyte/sb1250_uart.h>
49#include <asm/sibyte/swarm.h>
50
51
52#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
53#include <asm/sibyte/bcm1480_regs.h>
54#include <asm/sibyte/bcm1480_int.h>
55
56#define SBD_CHANREGS(line) A_BCM1480_DUART_CHANREG((line), 0)
57#define SBD_CTRLREGS(line) A_BCM1480_DUART_CTRLREG((line), 0)
58#define SBD_INT(line) (K_BCM1480_INT_UART_0 + (line))
59
60#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
61#include <asm/sibyte/sb1250_regs.h>
62#include <asm/sibyte/sb1250_int.h>
63
64#define SBD_CHANREGS(line) A_DUART_CHANREG((line), 0)
65#define SBD_CTRLREGS(line) A_DUART_CTRLREG(0)
66#define SBD_INT(line) (K_INT_UART_0 + (line))
67
68#else
69#error invalid SB1250 UART configuration
70
71#endif
72
73
74MODULE_AUTHOR("Maciej W. Rozycki <macro@linux-mips.org>");
75MODULE_DESCRIPTION("BCM1xxx on-chip DUART serial driver");
76MODULE_LICENSE("GPL");
77
78
79#define DUART_MAX_CHIP 2
80#define DUART_MAX_SIDE 2
81
82/*
83 * Per-port state.
84 */
85struct sbd_port {
86 struct sbd_duart *duart;
87 struct uart_port port;
88 unsigned char __iomem *memctrl;
89 int tx_stopped;
90 int initialised;
91};
92
93/*
94 * Per-DUART state for the shared register space.
95 */
96struct sbd_duart {
97 struct sbd_port sport[2];
98 unsigned long mapctrl;
99 atomic_t map_guard;
100};
101
102#define to_sport(uport) container_of(uport, struct sbd_port, port)
103
104static struct sbd_duart sbd_duarts[DUART_MAX_CHIP];
105
106#define __unused __attribute__((__unused__))
107
108
109/*
110 * Reading and writing SB1250 DUART registers.
111 *
112 * There are three register spaces: two per-channel ones and
113 * a shared one. We have to define accessors appropriately.
114 * All registers are 64-bit and all but the Baud Rate Clock
115 * registers only define 8 least significant bits. There is
116 * also a workaround to take into account. Raw accessors use
117 * the full register width, but cooked ones truncate it
118 * intentionally so that the rest of the driver does not care.
119 */
120static u64 __read_sbdchn(struct sbd_port *sport, int reg)
121{
122 void __iomem *csr = sport->port.membase + reg;
123
124 return __raw_readq(csr);
125}
126
127static u64 __read_sbdshr(struct sbd_port *sport, int reg)
128{
129 void __iomem *csr = sport->memctrl + reg;
130
131 return __raw_readq(csr);
132}
133
134static void __write_sbdchn(struct sbd_port *sport, int reg, u64 value)
135{
136 void __iomem *csr = sport->port.membase + reg;
137
138 __raw_writeq(value, csr);
139}
140
141static void __write_sbdshr(struct sbd_port *sport, int reg, u64 value)
142{
143 void __iomem *csr = sport->memctrl + reg;
144
145 __raw_writeq(value, csr);
146}
147
148/*
149 * In bug 1956, we get glitches that can mess up uart registers. This
150 * "read-mode-reg after any register access" is an accepted workaround.
151 */
152static void __war_sbd1956(struct sbd_port *sport)
153{
154 __read_sbdchn(sport, R_DUART_MODE_REG_1);
155 __read_sbdchn(sport, R_DUART_MODE_REG_2);
156}
157
158static unsigned char read_sbdchn(struct sbd_port *sport, int reg)
159{
160 unsigned char retval;
161
162 retval = __read_sbdchn(sport, reg);
163 if (SIBYTE_1956_WAR)
164 __war_sbd1956(sport);
165 return retval;
166}
167
168static unsigned char read_sbdshr(struct sbd_port *sport, int reg)
169{
170 unsigned char retval;
171
172 retval = __read_sbdshr(sport, reg);
173 if (SIBYTE_1956_WAR)
174 __war_sbd1956(sport);
175 return retval;
176}
177
178static void write_sbdchn(struct sbd_port *sport, int reg, unsigned int value)
179{
180 __write_sbdchn(sport, reg, value);
181 if (SIBYTE_1956_WAR)
182 __war_sbd1956(sport);
183}
184
185static void write_sbdshr(struct sbd_port *sport, int reg, unsigned int value)
186{
187 __write_sbdshr(sport, reg, value);
188 if (SIBYTE_1956_WAR)
189 __war_sbd1956(sport);
190}
191
192
193static int sbd_receive_ready(struct sbd_port *sport)
194{
195 return read_sbdchn(sport, R_DUART_STATUS) & M_DUART_RX_RDY;
196}
197
198static int sbd_receive_drain(struct sbd_port *sport)
199{
200 int loops = 10000;
201
202 while (sbd_receive_ready(sport) && loops--)
203 read_sbdchn(sport, R_DUART_RX_HOLD);
204 return loops;
205}
206
207static int __unused sbd_transmit_ready(struct sbd_port *sport)
208{
209 return read_sbdchn(sport, R_DUART_STATUS) & M_DUART_TX_RDY;
210}
211
212static int __unused sbd_transmit_drain(struct sbd_port *sport)
213{
214 int loops = 10000;
215
216 while (!sbd_transmit_ready(sport) && loops--)
217 udelay(2);
218 return loops;
219}
220
221static int sbd_transmit_empty(struct sbd_port *sport)
222{
223 return read_sbdchn(sport, R_DUART_STATUS) & M_DUART_TX_EMT;
224}
225
226static int sbd_line_drain(struct sbd_port *sport)
227{
228 int loops = 10000;
229
230 while (!sbd_transmit_empty(sport) && loops--)
231 udelay(2);
232 return loops;
233}
234
235
236static unsigned int sbd_tx_empty(struct uart_port *uport)
237{
238 struct sbd_port *sport = to_sport(uport);
239
240 return sbd_transmit_empty(sport) ? TIOCSER_TEMT : 0;
241}
242
243static unsigned int sbd_get_mctrl(struct uart_port *uport)
244{
245 struct sbd_port *sport = to_sport(uport);
246 unsigned int mctrl, status;
247
248 status = read_sbdshr(sport, R_DUART_IN_PORT);
249 status >>= (uport->line) % 2;
250 mctrl = (!(status & M_DUART_IN_PIN0_VAL) ? TIOCM_CTS : 0) |
251 (!(status & M_DUART_IN_PIN4_VAL) ? TIOCM_CAR : 0) |
252 (!(status & M_DUART_RIN0_PIN) ? TIOCM_RNG : 0) |
253 (!(status & M_DUART_IN_PIN2_VAL) ? TIOCM_DSR : 0);
254 return mctrl;
255}
256
257static void sbd_set_mctrl(struct uart_port *uport, unsigned int mctrl)
258{
259 struct sbd_port *sport = to_sport(uport);
260 unsigned int clr = 0, set = 0, mode2;
261
262 if (mctrl & TIOCM_DTR)
263 set |= M_DUART_SET_OPR2;
264 else
265 clr |= M_DUART_CLR_OPR2;
266 if (mctrl & TIOCM_RTS)
267 set |= M_DUART_SET_OPR0;
268 else
269 clr |= M_DUART_CLR_OPR0;
270 clr <<= (uport->line) % 2;
271 set <<= (uport->line) % 2;
272
273 mode2 = read_sbdchn(sport, R_DUART_MODE_REG_2);
274 mode2 &= ~M_DUART_CHAN_MODE;
275 if (mctrl & TIOCM_LOOP)
276 mode2 |= V_DUART_CHAN_MODE_LCL_LOOP;
277 else
278 mode2 |= V_DUART_CHAN_MODE_NORMAL;
279
280 write_sbdshr(sport, R_DUART_CLEAR_OPR, clr);
281 write_sbdshr(sport, R_DUART_SET_OPR, set);
282 write_sbdchn(sport, R_DUART_MODE_REG_2, mode2);
283}
284
285static void sbd_stop_tx(struct uart_port *uport)
286{
287 struct sbd_port *sport = to_sport(uport);
288
289 write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_DIS);
290 sport->tx_stopped = 1;
291};
292
293static void sbd_start_tx(struct uart_port *uport)
294{
295 struct sbd_port *sport = to_sport(uport);
296 unsigned int mask;
297
298 /* Enable tx interrupts. */
299 mask = read_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2));
300 mask |= M_DUART_IMR_TX;
301 write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2), mask);
302
303 /* Go!, go!, go!... */
304 write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_EN);
305 sport->tx_stopped = 0;
306};
307
308static void sbd_stop_rx(struct uart_port *uport)
309{
310 struct sbd_port *sport = to_sport(uport);
311
312 write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2), 0);
313};
314
315static void sbd_enable_ms(struct uart_port *uport)
316{
317 struct sbd_port *sport = to_sport(uport);
318
319 write_sbdchn(sport, R_DUART_AUXCTL_X,
320 M_DUART_CIN_CHNG_ENA | M_DUART_CTS_CHNG_ENA);
321}
322
323static void sbd_break_ctl(struct uart_port *uport, int break_state)
324{
325 struct sbd_port *sport = to_sport(uport);
326
327 if (break_state == -1)
328 write_sbdchn(sport, R_DUART_CMD, V_DUART_MISC_CMD_START_BREAK);
329 else
330 write_sbdchn(sport, R_DUART_CMD, V_DUART_MISC_CMD_STOP_BREAK);
331}
332
333
334static void sbd_receive_chars(struct sbd_port *sport)
335{
336 struct uart_port *uport = &sport->port;
337 struct uart_icount *icount;
338 unsigned int status, ch, flag;
339 int count;
340
341 for (count = 16; count; count--) {
342 status = read_sbdchn(sport, R_DUART_STATUS);
343 if (!(status & M_DUART_RX_RDY))
344 break;
345
346 ch = read_sbdchn(sport, R_DUART_RX_HOLD);
347
348 flag = TTY_NORMAL;
349
350 icount = &uport->icount;
351 icount->rx++;
352
353 if (unlikely(status &
354 (M_DUART_RCVD_BRK | M_DUART_FRM_ERR |
355 M_DUART_PARITY_ERR | M_DUART_OVRUN_ERR))) {
356 if (status & M_DUART_RCVD_BRK) {
357 icount->brk++;
358 if (uart_handle_break(uport))
359 continue;
360 } else if (status & M_DUART_FRM_ERR)
361 icount->frame++;
362 else if (status & M_DUART_PARITY_ERR)
363 icount->parity++;
364 if (status & M_DUART_OVRUN_ERR)
365 icount->overrun++;
366
367 status &= uport->read_status_mask;
368 if (status & M_DUART_RCVD_BRK)
369 flag = TTY_BREAK;
370 else if (status & M_DUART_FRM_ERR)
371 flag = TTY_FRAME;
372 else if (status & M_DUART_PARITY_ERR)
373 flag = TTY_PARITY;
374 }
375
376 if (uart_handle_sysrq_char(uport, ch))
377 continue;
378
379 uart_insert_char(uport, status, M_DUART_OVRUN_ERR, ch, flag);
380 }
381
382 tty_flip_buffer_push(uport->info->tty);
383}
384
385static void sbd_transmit_chars(struct sbd_port *sport)
386{
387 struct uart_port *uport = &sport->port;
388 struct circ_buf *xmit = &sport->port.info->xmit;
389 unsigned int mask;
390 int stop_tx;
391
392 /* XON/XOFF chars. */
393 if (sport->port.x_char) {
394 write_sbdchn(sport, R_DUART_TX_HOLD, sport->port.x_char);
395 sport->port.icount.tx++;
396 sport->port.x_char = 0;
397 return;
398 }
399
400 /* If nothing to do or stopped or hardware stopped. */
401 stop_tx = (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port));
402
403 /* Send char. */
404 if (!stop_tx) {
405 write_sbdchn(sport, R_DUART_TX_HOLD, xmit->buf[xmit->tail]);
406 xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
407 sport->port.icount.tx++;
408
409 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
410 uart_write_wakeup(&sport->port);
411 }
412
413 /* Are we are done? */
414 if (stop_tx || uart_circ_empty(xmit)) {
415 /* Disable tx interrupts. */
416 mask = read_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2));
417 mask &= ~M_DUART_IMR_TX;
418 write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2), mask);
419 }
420}
421
422static void sbd_status_handle(struct sbd_port *sport)
423{
424 struct uart_port *uport = &sport->port;
425 unsigned int delta;
426
427 delta = read_sbdshr(sport, R_DUART_INCHREG((uport->line) % 2));
428 delta >>= (uport->line) % 2;
429
430 if (delta & (M_DUART_IN_PIN0_VAL << S_DUART_IN_PIN_CHNG))
431 uart_handle_cts_change(uport, !(delta & M_DUART_IN_PIN0_VAL));
432
433 if (delta & (M_DUART_IN_PIN2_VAL << S_DUART_IN_PIN_CHNG))
434 uport->icount.dsr++;
435
436 if (delta & ((M_DUART_IN_PIN2_VAL | M_DUART_IN_PIN0_VAL) <<
437 S_DUART_IN_PIN_CHNG))
438 wake_up_interruptible(&uport->info->delta_msr_wait);
439}
440
441static irqreturn_t sbd_interrupt(int irq, void *dev_id)
442{
443 struct sbd_port *sport = dev_id;
444 struct uart_port *uport = &sport->port;
445 irqreturn_t status = IRQ_NONE;
446 unsigned int intstat;
447 int count;
448
449 for (count = 16; count; count--) {
450 intstat = read_sbdshr(sport,
451 R_DUART_ISRREG((uport->line) % 2));
452 intstat &= read_sbdshr(sport,
453 R_DUART_IMRREG((uport->line) % 2));
454 intstat &= M_DUART_ISR_ALL;
455 if (!intstat)
456 break;
457
458 if (intstat & M_DUART_ISR_RX)
459 sbd_receive_chars(sport);
460 if (intstat & M_DUART_ISR_IN)
461 sbd_status_handle(sport);
462 if (intstat & M_DUART_ISR_TX)
463 sbd_transmit_chars(sport);
464
465 status = IRQ_HANDLED;
466 }
467
468 return status;
469}
470
471
472static int sbd_startup(struct uart_port *uport)
473{
474 struct sbd_port *sport = to_sport(uport);
475 unsigned int mode1;
476 int ret;
477
478 ret = request_irq(sport->port.irq, sbd_interrupt,
479 IRQF_SHARED, "sb1250-duart", sport);
480 if (ret)
481 return ret;
482
483 /* Clear the receive FIFO. */
484 sbd_receive_drain(sport);
485
486 /* Clear the interrupt registers. */
487 write_sbdchn(sport, R_DUART_CMD, V_DUART_MISC_CMD_RESET_BREAK_INT);
488 read_sbdshr(sport, R_DUART_INCHREG((uport->line) % 2));
489
490 /* Set rx/tx interrupt to FIFO available. */
491 mode1 = read_sbdchn(sport, R_DUART_MODE_REG_1);
492 mode1 &= ~(M_DUART_RX_IRQ_SEL_RXFULL | M_DUART_TX_IRQ_SEL_TXEMPT);
493 write_sbdchn(sport, R_DUART_MODE_REG_1, mode1);
494
495 /* Disable tx, enable rx. */
496 write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_DIS | M_DUART_RX_EN);
497 sport->tx_stopped = 1;
498
499 /* Enable interrupts. */
500 write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2),
501 M_DUART_IMR_IN | M_DUART_IMR_RX);
502
503 return 0;
504}
505
506static void sbd_shutdown(struct uart_port *uport)
507{
508 struct sbd_port *sport = to_sport(uport);
509
510 write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_DIS | M_DUART_RX_DIS);
511 sport->tx_stopped = 1;
512 free_irq(sport->port.irq, sport);
513}
514
515
516static void sbd_init_port(struct sbd_port *sport)
517{
518 struct uart_port *uport = &sport->port;
519
520 if (sport->initialised)
521 return;
522
523 /* There is no DUART reset feature, so just set some sane defaults. */
524 write_sbdchn(sport, R_DUART_CMD, V_DUART_MISC_CMD_RESET_TX);
525 write_sbdchn(sport, R_DUART_CMD, V_DUART_MISC_CMD_RESET_RX);
526 write_sbdchn(sport, R_DUART_MODE_REG_1, V_DUART_BITS_PER_CHAR_8);
527 write_sbdchn(sport, R_DUART_MODE_REG_2, 0);
528 write_sbdchn(sport, R_DUART_FULL_CTL,
529 V_DUART_INT_TIME(0) | V_DUART_SIG_FULL(15));
530 write_sbdchn(sport, R_DUART_OPCR_X, 0);
531 write_sbdchn(sport, R_DUART_AUXCTL_X, 0);
532 write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2), 0);
533
534 sport->initialised = 1;
535}
536
537static void sbd_set_termios(struct uart_port *uport, struct ktermios *termios,
538 struct ktermios *old_termios)
539{
540 struct sbd_port *sport = to_sport(uport);
541 unsigned int mode1 = 0, mode2 = 0, aux = 0;
542 unsigned int mode1mask = 0, mode2mask = 0, auxmask = 0;
543 unsigned int oldmode1, oldmode2, oldaux;
544 unsigned int baud, brg;
545 unsigned int command;
546
547 mode1mask |= ~(M_DUART_PARITY_MODE | M_DUART_PARITY_TYPE_ODD |
548 M_DUART_BITS_PER_CHAR);
549 mode2mask |= ~M_DUART_STOP_BIT_LEN_2;
550 auxmask |= ~M_DUART_CTS_CHNG_ENA;
551
552 /* Byte size. */
553 switch (termios->c_cflag & CSIZE) {
554 case CS5:
555 case CS6:
556 /* Unsupported, leave unchanged. */
557 mode1mask |= M_DUART_PARITY_MODE;
558 break;
559 case CS7:
560 mode1 |= V_DUART_BITS_PER_CHAR_7;
561 break;
562 case CS8:
563 default:
564 mode1 |= V_DUART_BITS_PER_CHAR_8;
565 break;
566 }
567
568 /* Parity and stop bits. */
569 if (termios->c_cflag & CSTOPB)
570 mode2 |= M_DUART_STOP_BIT_LEN_2;
571 else
572 mode2 |= M_DUART_STOP_BIT_LEN_1;
573 if (termios->c_cflag & PARENB)
574 mode1 |= V_DUART_PARITY_MODE_ADD;
575 else
576 mode1 |= V_DUART_PARITY_MODE_NONE;
577 if (termios->c_cflag & PARODD)
578 mode1 |= M_DUART_PARITY_TYPE_ODD;
579 else
580 mode1 |= M_DUART_PARITY_TYPE_EVEN;
581
582 baud = uart_get_baud_rate(uport, termios, old_termios, 1200, 5000000);
583 brg = V_DUART_BAUD_RATE(baud);
584 /* The actual lower bound is 1221bps, so compensate. */
585 if (brg > M_DUART_CLK_COUNTER)
586 brg = M_DUART_CLK_COUNTER;
587
588 uart_update_timeout(uport, termios->c_cflag, baud);
589
590 uport->read_status_mask = M_DUART_OVRUN_ERR;
591 if (termios->c_iflag & INPCK)
592 uport->read_status_mask |= M_DUART_FRM_ERR |
593 M_DUART_PARITY_ERR;
594 if (termios->c_iflag & (BRKINT | PARMRK))
595 uport->read_status_mask |= M_DUART_RCVD_BRK;
596
597 uport->ignore_status_mask = 0;
598 if (termios->c_iflag & IGNPAR)
599 uport->ignore_status_mask |= M_DUART_FRM_ERR |
600 M_DUART_PARITY_ERR;
601 if (termios->c_iflag & IGNBRK) {
602 uport->ignore_status_mask |= M_DUART_RCVD_BRK;
603 if (termios->c_iflag & IGNPAR)
604 uport->ignore_status_mask |= M_DUART_OVRUN_ERR;
605 }
606
607 if (termios->c_cflag & CREAD)
608 command = M_DUART_RX_EN;
609 else
610 command = M_DUART_RX_DIS;
611
612 if (termios->c_cflag & CRTSCTS)
613 aux |= M_DUART_CTS_CHNG_ENA;
614 else
615 aux &= ~M_DUART_CTS_CHNG_ENA;
616
617 spin_lock(&uport->lock);
618
619 if (sport->tx_stopped)
620 command |= M_DUART_TX_DIS;
621 else
622 command |= M_DUART_TX_EN;
623
624 oldmode1 = read_sbdchn(sport, R_DUART_MODE_REG_1) & mode1mask;
625 oldmode2 = read_sbdchn(sport, R_DUART_MODE_REG_2) & mode2mask;
626 oldaux = read_sbdchn(sport, R_DUART_AUXCTL_X) & auxmask;
627
628 if (!sport->tx_stopped)
629 sbd_line_drain(sport);
630 write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_DIS | M_DUART_RX_DIS);
631
632 write_sbdchn(sport, R_DUART_MODE_REG_1, mode1 | oldmode1);
633 write_sbdchn(sport, R_DUART_MODE_REG_2, mode2 | oldmode2);
634 write_sbdchn(sport, R_DUART_CLK_SEL, brg);
635 write_sbdchn(sport, R_DUART_AUXCTL_X, aux | oldaux);
636
637 write_sbdchn(sport, R_DUART_CMD, command);
638
639 spin_unlock(&uport->lock);
640}
641
642
643static const char *sbd_type(struct uart_port *uport)
644{
645 return "SB1250 DUART";
646}
647
648static void sbd_release_port(struct uart_port *uport)
649{
650 struct sbd_port *sport = to_sport(uport);
651 struct sbd_duart *duart = sport->duart;
652 int map_guard;
653
654 iounmap(sport->memctrl);
655 sport->memctrl = NULL;
656 iounmap(uport->membase);
657 uport->membase = NULL;
658
659 map_guard = atomic_add_return(-1, &duart->map_guard);
660 if (!map_guard)
661 release_mem_region(duart->mapctrl, DUART_CHANREG_SPACING);
662 release_mem_region(uport->mapbase, DUART_CHANREG_SPACING);
663}
664
665static int sbd_map_port(struct uart_port *uport)
666{
667 static const char *err = KERN_ERR "sbd: Cannot map MMIO\n";
668 struct sbd_port *sport = to_sport(uport);
669 struct sbd_duart *duart = sport->duart;
670
671 if (!uport->membase)
672 uport->membase = ioremap_nocache(uport->mapbase,
673 DUART_CHANREG_SPACING);
674 if (!uport->membase) {
675 printk(err);
676 return -ENOMEM;
677 }
678
679 if (!sport->memctrl)
680 sport->memctrl = ioremap_nocache(duart->mapctrl,
681 DUART_CHANREG_SPACING);
682 if (!sport->memctrl) {
683 printk(err);
684 iounmap(uport->membase);
685 uport->membase = NULL;
686 return -ENOMEM;
687 }
688
689 return 0;
690}
691
692static int sbd_request_port(struct uart_port *uport)
693{
694 static const char *err = KERN_ERR
695 "sbd: Unable to reserve MMIO resource\n";
696 struct sbd_duart *duart = to_sport(uport)->duart;
697 int map_guard;
698 int ret = 0;
699
700 if (!request_mem_region(uport->mapbase, DUART_CHANREG_SPACING,
701 "sb1250-duart")) {
702 printk(err);
703 return -EBUSY;
704 }
705 map_guard = atomic_add_return(1, &duart->map_guard);
706 if (map_guard == 1) {
707 if (!request_mem_region(duart->mapctrl, DUART_CHANREG_SPACING,
708 "sb1250-duart")) {
709 atomic_add(-1, &duart->map_guard);
710 printk(err);
711 ret = -EBUSY;
712 }
713 }
714 if (!ret) {
715 ret = sbd_map_port(uport);
716 if (ret) {
717 map_guard = atomic_add_return(-1, &duart->map_guard);
718 if (!map_guard)
719 release_mem_region(duart->mapctrl,
720 DUART_CHANREG_SPACING);
721 }
722 }
723 if (ret) {
724 release_mem_region(uport->mapbase, DUART_CHANREG_SPACING);
725 return ret;
726 }
727 return 0;
728}
729
730static void sbd_config_port(struct uart_port *uport, int flags)
731{
732 struct sbd_port *sport = to_sport(uport);
733
734 if (flags & UART_CONFIG_TYPE) {
735 if (sbd_request_port(uport))
736 return;
737
738 uport->type = PORT_SB1250_DUART;
739
740 sbd_init_port(sport);
741 }
742}
743
744static int sbd_verify_port(struct uart_port *uport, struct serial_struct *ser)
745{
746 int ret = 0;
747
748 if (ser->type != PORT_UNKNOWN && ser->type != PORT_SB1250_DUART)
749 ret = -EINVAL;
750 if (ser->irq != uport->irq)
751 ret = -EINVAL;
752 if (ser->baud_base != uport->uartclk / 16)
753 ret = -EINVAL;
754 return ret;
755}
756
757
758static struct uart_ops sbd_ops = {
759 .tx_empty = sbd_tx_empty,
760 .set_mctrl = sbd_set_mctrl,
761 .get_mctrl = sbd_get_mctrl,
762 .stop_tx = sbd_stop_tx,
763 .start_tx = sbd_start_tx,
764 .stop_rx = sbd_stop_rx,
765 .enable_ms = sbd_enable_ms,
766 .break_ctl = sbd_break_ctl,
767 .startup = sbd_startup,
768 .shutdown = sbd_shutdown,
769 .set_termios = sbd_set_termios,
770 .type = sbd_type,
771 .release_port = sbd_release_port,
772 .request_port = sbd_request_port,
773 .config_port = sbd_config_port,
774 .verify_port = sbd_verify_port,
775};
776
777/* Initialize SB1250 DUART port structures. */
778static void __init sbd_probe_duarts(void)
779{
780 static int probed;
781 int chip, side;
782 int max_lines, line;
783
784 if (probed)
785 return;
786
787 /* Set the number of available units based on the SOC type. */
788 switch (soc_type) {
789 case K_SYS_SOC_TYPE_BCM1x55:
790 case K_SYS_SOC_TYPE_BCM1x80:
791 max_lines = 4;
792 break;
793 default:
794 /* Assume at least two serial ports at the normal address. */
795 max_lines = 2;
796 break;
797 }
798
799 probed = 1;
800
801 for (chip = 0, line = 0; chip < DUART_MAX_CHIP && line < max_lines;
802 chip++) {
803 sbd_duarts[chip].mapctrl = SBD_CTRLREGS(line);
804
805 for (side = 0; side < DUART_MAX_SIDE && line < max_lines;
806 side++, line++) {
807 struct sbd_port *sport = &sbd_duarts[chip].sport[side];
808 struct uart_port *uport = &sport->port;
809
810 sport->duart = &sbd_duarts[chip];
811
812 uport->irq = SBD_INT(line);
813 uport->uartclk = 100000000 / 20 * 16;
814 uport->fifosize = 16;
815 uport->iotype = UPIO_MEM;
816 uport->flags = UPF_BOOT_AUTOCONF;
817 uport->ops = &sbd_ops;
818 uport->line = line;
819 uport->mapbase = SBD_CHANREGS(line);
820 }
821 }
822}
823
824
825#ifdef CONFIG_SERIAL_SB1250_DUART_CONSOLE
826/*
827 * Serial console stuff. Very basic, polling driver for doing serial
828 * console output. The console_sem is held by the caller, so we
829 * shouldn't be interrupted for more console activity.
830 */
831static void sbd_console_putchar(struct uart_port *uport, int ch)
832{
833 struct sbd_port *sport = to_sport(uport);
834
835 sbd_transmit_drain(sport);
836 write_sbdchn(sport, R_DUART_TX_HOLD, ch);
837}
838
839static void sbd_console_write(struct console *co, const char *s,
840 unsigned int count)
841{
842 int chip = co->index / DUART_MAX_SIDE;
843 int side = co->index % DUART_MAX_SIDE;
844 struct sbd_port *sport = &sbd_duarts[chip].sport[side];
845 struct uart_port *uport = &sport->port;
846 unsigned long flags;
847 unsigned int mask;
848
849 /* Disable transmit interrupts and enable the transmitter. */
850 spin_lock_irqsave(&uport->lock, flags);
851 mask = read_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2));
852 write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2),
853 mask & ~M_DUART_IMR_TX);
854 write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_EN);
855 spin_unlock_irqrestore(&uport->lock, flags);
856
857 uart_console_write(&sport->port, s, count, sbd_console_putchar);
858
859 /* Restore transmit interrupts and the transmitter enable. */
860 spin_lock_irqsave(&uport->lock, flags);
861 sbd_line_drain(sport);
862 if (sport->tx_stopped)
863 write_sbdchn(sport, R_DUART_CMD, M_DUART_TX_DIS);
864 write_sbdshr(sport, R_DUART_IMRREG((uport->line) % 2), mask);
865 spin_unlock_irqrestore(&uport->lock, flags);
866}
867
868static int __init sbd_console_setup(struct console *co, char *options)
869{
870 int chip = co->index / DUART_MAX_SIDE;
871 int side = co->index % DUART_MAX_SIDE;
872 struct sbd_port *sport = &sbd_duarts[chip].sport[side];
873 struct uart_port *uport = &sport->port;
874 int baud = 115200;
875 int bits = 8;
876 int parity = 'n';
877 int flow = 'n';
878 int ret;
879
880 if (!sport->duart)
881 return -ENXIO;
882
883 ret = sbd_map_port(uport);
884 if (ret)
885 return ret;
886
887 sbd_init_port(sport);
888
889 if (options)
890 uart_parse_options(options, &baud, &parity, &bits, &flow);
891 return uart_set_options(uport, co, baud, parity, bits, flow);
892}
893
894static struct uart_driver sbd_reg;
895static struct console sbd_console = {
896 .name = "duart",
897 .write = sbd_console_write,
898 .device = uart_console_device,
899 .setup = sbd_console_setup,
900 .flags = CON_PRINTBUFFER,
901 .index = -1,
902 .data = &sbd_reg
903};
904
905static int __init sbd_serial_console_init(void)
906{
907 sbd_probe_duarts();
908 register_console(&sbd_console);
909
910 return 0;
911}
912
913console_initcall(sbd_serial_console_init);
914
915#define SERIAL_SB1250_DUART_CONSOLE &sbd_console
916#else
917#define SERIAL_SB1250_DUART_CONSOLE NULL
918#endif /* CONFIG_SERIAL_SB1250_DUART_CONSOLE */
919
920
921static struct uart_driver sbd_reg = {
922 .owner = THIS_MODULE,
923 .driver_name = "serial",
924 .dev_name = "duart",
925 .major = TTY_MAJOR,
926 .minor = SB1250_DUART_MINOR_BASE,
927 .nr = DUART_MAX_CHIP * DUART_MAX_SIDE,
928 .cons = SERIAL_SB1250_DUART_CONSOLE,
929};
930
931/* Set up the driver and register it. */
932static int __init sbd_init(void)
933{
934 int i, ret;
935
936 sbd_probe_duarts();
937
938 ret = uart_register_driver(&sbd_reg);
939 if (ret)
940 return ret;
941
942 for (i = 0; i < DUART_MAX_CHIP * DUART_MAX_SIDE; i++) {
943 struct sbd_duart *duart = &sbd_duarts[i / DUART_MAX_SIDE];
944 struct sbd_port *sport = &duart->sport[i % DUART_MAX_SIDE];
945 struct uart_port *uport = &sport->port;
946
947 if (sport->duart)
948 uart_add_one_port(&sbd_reg, uport);
949 }
950
951 return 0;
952}
953
954/* Unload the driver. Unregister stuff, get ready to go away. */
955static void __exit sbd_exit(void)
956{
957 int i;
958
959 for (i = DUART_MAX_CHIP * DUART_MAX_SIDE - 1; i >= 0; i--) {
960 struct sbd_duart *duart = &sbd_duarts[i / DUART_MAX_SIDE];
961 struct sbd_port *sport = &duart->sport[i % DUART_MAX_SIDE];
962 struct uart_port *uport = &sport->port;
963
964 if (sport->duart)
965 uart_remove_one_port(&sbd_reg, uport);
966 }
967
968 uart_unregister_driver(&sbd_reg);
969}
970
971module_init(sbd_init);
972module_exit(sbd_exit);
diff --git a/include/asm-mips/sibyte/bcm1480_regs.h b/include/asm-mips/sibyte/bcm1480_regs.h
index bda391d3af85..2738c1366f66 100644
--- a/include/asm-mips/sibyte/bcm1480_regs.h
+++ b/include/asm-mips/sibyte/bcm1480_regs.h
@@ -220,17 +220,25 @@
220#define A_BCM1480_DUART(chan) ((((chan)&2) == 0)? A_BCM1480_DUART0 : A_BCM1480_DUART1) 220#define A_BCM1480_DUART(chan) ((((chan)&2) == 0)? A_BCM1480_DUART0 : A_BCM1480_DUART1)
221 221
222#define BCM1480_DUART_CHANREG_SPACING 0x100 222#define BCM1480_DUART_CHANREG_SPACING 0x100
223#define A_BCM1480_DUART_CHANREG(chan,reg) (A_BCM1480_DUART(chan) \ 223#define A_BCM1480_DUART_CHANREG(chan, reg) \
224 + BCM1480_DUART_CHANREG_SPACING*((chan)&1) \ 224 (A_BCM1480_DUART(chan) + \
225 + (reg)) 225 BCM1480_DUART_CHANREG_SPACING * (((chan) & 1) + 1) + (reg))
226#define R_BCM1480_DUART_CHANREG(chan,reg) (BCM1480_DUART_CHANREG_SPACING*((chan)&1) + (reg)) 226#define A_BCM1480_DUART_CTRLREG(chan, reg) \
227 227 (A_BCM1480_DUART(chan) + \
228#define R_BCM1480_DUART_IMRREG(chan) (R_DUART_IMR_A + ((chan)&1)*DUART_IMRISR_SPACING) 228 BCM1480_DUART_CHANREG_SPACING * 3 + (reg))
229#define R_BCM1480_DUART_ISRREG(chan) (R_DUART_ISR_A + ((chan)&1)*DUART_IMRISR_SPACING) 229
230 230#define R_BCM1480_DUART_IMRREG(chan) \
231#define A_BCM1480_DUART_IMRREG(chan) (A_BCM1480_DUART(chan) + R_BCM1480_DUART_IMRREG(chan)) 231 (R_DUART_IMR_A + ((chan) & 1) * DUART_IMRISR_SPACING)
232#define A_BCM1480_DUART_ISRREG(chan) (A_BCM1480_DUART(chan) + R_BCM1480_DUART_ISRREG(chan)) 232#define R_BCM1480_DUART_ISRREG(chan) \
233#define A_BCM1480_DUART_IN_PORT(chan) (A_BCM1480_DUART(chan) + R_DUART_INP_ORT) 233 (R_DUART_ISR_A + ((chan) & 1) * DUART_IMRISR_SPACING)
234
235#define A_BCM1480_DUART_IMRREG(chan) \
236 (A_BCM1480_DUART_CTRLREG((chan), R_BCM1480_DUART_IMRREG(chan)))
237#define A_BCM1480_DUART_ISRREG(chan) \
238 (A_BCM1480_DUART_CTRLREG((chan), R_BCM1480_DUART_ISRREG(chan)))
239
240#define A_BCM1480_DUART_IN_PORT(chan) \
241 (A_BCM1480_DUART_CTRLREG((chan), R_DUART_IN_PORT))
234 242
235/* 243/*
236 * These constants are the absolute addresses. 244 * These constants are the absolute addresses.
diff --git a/include/asm-mips/sibyte/sb1250_regs.h b/include/asm-mips/sibyte/sb1250_regs.h
index da7c188993c9..220b7e94f1bf 100644
--- a/include/asm-mips/sibyte/sb1250_regs.h
+++ b/include/asm-mips/sibyte/sb1250_regs.h
@@ -272,59 +272,69 @@
272 ********************************************************************* */ 272 ********************************************************************* */
273 273
274 274
275#if SIBYTE_HDR_FEATURE_1250_112x /* This MC only on 1250 & 112x */ 275#if SIBYTE_HDR_FEATURE_1250_112x /* This MC only on 1250 & 112x */
276#define R_DUART_NUM_PORTS 2 276#define R_DUART_NUM_PORTS 2
277 277
278#define A_DUART 0x0010060000 278#define A_DUART 0x0010060000
279 279
280#define DUART_CHANREG_SPACING 0x100 280#define DUART_CHANREG_SPACING 0x100
281#define A_DUART_CHANREG(chan,reg) (A_DUART + DUART_CHANREG_SPACING*(chan) + (reg)) 281
282#define R_DUART_CHANREG(chan,reg) (DUART_CHANREG_SPACING*(chan) + (reg)) 282#define A_DUART_CHANREG(chan, reg) \
283 (A_DUART + DUART_CHANREG_SPACING * ((chan) + 1) + (reg))
283#endif /* 1250 & 112x */ 284#endif /* 1250 & 112x */
284 285
285#define R_DUART_MODE_REG_1 0x100 286#define R_DUART_MODE_REG_1 0x000
286#define R_DUART_MODE_REG_2 0x110 287#define R_DUART_MODE_REG_2 0x010
287#define R_DUART_STATUS 0x120 288#define R_DUART_STATUS 0x020
288#define R_DUART_CLK_SEL 0x130 289#define R_DUART_CLK_SEL 0x030
289#define R_DUART_CMD 0x150 290#define R_DUART_CMD 0x050
290#define R_DUART_RX_HOLD 0x160 291#define R_DUART_RX_HOLD 0x060
291#define R_DUART_TX_HOLD 0x170 292#define R_DUART_TX_HOLD 0x070
292 293
293#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480) 294#if SIBYTE_HDR_FEATURE(1250, PASS2) || SIBYTE_HDR_FEATURE(112x, PASS1) || SIBYTE_HDR_FEATURE_CHIP(1480)
294#define R_DUART_FULL_CTL 0x140 295#define R_DUART_FULL_CTL 0x040
295#define R_DUART_OPCR_X 0x180 296#define R_DUART_OPCR_X 0x080
296#define R_DUART_AUXCTL_X 0x190 297#define R_DUART_AUXCTL_X 0x090
297#endif /* 1250 PASS2 || 112x PASS1 || 1480*/ 298#endif /* 1250 PASS2 || 112x PASS1 || 1480 */
298 299
299 300
300/* 301/*
301 * The IMR and ISR can't be addressed with A_DUART_CHANREG, 302 * The IMR and ISR can't be addressed with A_DUART_CHANREG,
302 * so use this macro instead. 303 * so use these macros instead.
303 */ 304 */
304 305
305#define R_DUART_AUX_CTRL 0x310 306#if SIBYTE_HDR_FEATURE_1250_112x /* This MC only on 1250 & 112x */
306#define R_DUART_ISR_A 0x320 307#define DUART_IMRISR_SPACING 0x20
307#define R_DUART_IMR_A 0x330 308#define DUART_INCHNG_SPACING 0x10
308#define R_DUART_ISR_B 0x340
309#define R_DUART_IMR_B 0x350
310#define R_DUART_OUT_PORT 0x360
311#define R_DUART_OPCR 0x370
312#define R_DUART_IN_PORT 0x380
313 309
314#define R_DUART_SET_OPR 0x3B0 310#define A_DUART_CTRLREG(reg) \
315#define R_DUART_CLEAR_OPR 0x3C0 311 (A_DUART + DUART_CHANREG_SPACING * 3 + (reg))
316 312
317#define DUART_IMRISR_SPACING 0x20 313#define R_DUART_IMRREG(chan) \
314 (R_DUART_IMR_A + (chan) * DUART_IMRISR_SPACING)
315#define R_DUART_ISRREG(chan) \
316 (R_DUART_ISR_A + (chan) * DUART_IMRISR_SPACING)
317#define R_DUART_INCHREG(chan) \
318 (R_DUART_IN_CHNG_A + (chan) * DUART_INCHNG_SPACING)
318 319
319#if SIBYTE_HDR_FEATURE_1250_112x /* This MC only on 1250 & 112x */ 320#define A_DUART_IMRREG(chan) A_DUART_CTRLREG(R_DUART_IMRREG(chan))
320#define R_DUART_IMRREG(chan) (R_DUART_IMR_A + (chan)*DUART_IMRISR_SPACING) 321#define A_DUART_ISRREG(chan) A_DUART_CTRLREG(R_DUART_ISRREG(chan))
321#define R_DUART_ISRREG(chan) (R_DUART_ISR_A + (chan)*DUART_IMRISR_SPACING) 322#define A_DUART_INCHREG(chan) A_DUART_CTRLREG(R_DUART_INCHREG(chan))
322
323#define A_DUART_IMRREG(chan) (A_DUART + R_DUART_IMRREG(chan))
324#define A_DUART_ISRREG(chan) (A_DUART + R_DUART_ISRREG(chan))
325#endif /* 1250 & 112x */ 323#endif /* 1250 & 112x */
326 324
327 325#define R_DUART_AUX_CTRL 0x010
326#define R_DUART_ISR_A 0x020
327#define R_DUART_IMR_A 0x030
328#define R_DUART_ISR_B 0x040
329#define R_DUART_IMR_B 0x050
330#define R_DUART_OUT_PORT 0x060
331#define R_DUART_OPCR 0x070
332#define R_DUART_IN_PORT 0x080
333
334#define R_DUART_SET_OPR 0x0B0
335#define R_DUART_CLEAR_OPR 0x0C0
336#define R_DUART_IN_CHNG_A 0x0D0
337#define R_DUART_IN_CHNG_B 0x0E0
328 338
329 339
330/* 340/*
diff --git a/include/asm-mips/sibyte/sb1250_uart.h b/include/asm-mips/sibyte/sb1250_uart.h
index e87045e62bf0..cf74fedcbef1 100644
--- a/include/asm-mips/sibyte/sb1250_uart.h
+++ b/include/asm-mips/sibyte/sb1250_uart.h
@@ -75,7 +75,8 @@
75#define V_DUART_PARITY_MODE_ADD_FIXED V_DUART_PARITY_MODE(K_DUART_PARITY_MODE_ADD_FIXED) 75#define V_DUART_PARITY_MODE_ADD_FIXED V_DUART_PARITY_MODE(K_DUART_PARITY_MODE_ADD_FIXED)
76#define V_DUART_PARITY_MODE_NONE V_DUART_PARITY_MODE(K_DUART_PARITY_MODE_NONE) 76#define V_DUART_PARITY_MODE_NONE V_DUART_PARITY_MODE(K_DUART_PARITY_MODE_NONE)
77 77
78#define M_DUART_ERR_MODE _SB_MAKEMASK1(5) /* must be zero */ 78#define M_DUART_TX_IRQ_SEL_TXRDY 0
79#define M_DUART_TX_IRQ_SEL_TXEMPT _SB_MAKEMASK1(5)
79 80
80#define M_DUART_RX_IRQ_SEL_RXRDY 0 81#define M_DUART_RX_IRQ_SEL_RXRDY 0
81#define M_DUART_RX_IRQ_SEL_RXFULL _SB_MAKEMASK1(6) 82#define M_DUART_RX_IRQ_SEL_RXFULL _SB_MAKEMASK1(6)
@@ -246,10 +247,13 @@
246 247
247#define M_DUART_ISR_BRK_A _SB_MAKEMASK1(2) 248#define M_DUART_ISR_BRK_A _SB_MAKEMASK1(2)
248#define M_DUART_ISR_IN_A _SB_MAKEMASK1(3) 249#define M_DUART_ISR_IN_A _SB_MAKEMASK1(3)
250#define M_DUART_ISR_ALL_A _SB_MAKEMASK(4,0)
251
249#define M_DUART_ISR_TX_B _SB_MAKEMASK1(4) 252#define M_DUART_ISR_TX_B _SB_MAKEMASK1(4)
250#define M_DUART_ISR_RX_B _SB_MAKEMASK1(5) 253#define M_DUART_ISR_RX_B _SB_MAKEMASK1(5)
251#define M_DUART_ISR_BRK_B _SB_MAKEMASK1(6) 254#define M_DUART_ISR_BRK_B _SB_MAKEMASK1(6)
252#define M_DUART_ISR_IN_B _SB_MAKEMASK1(7) 255#define M_DUART_ISR_IN_B _SB_MAKEMASK1(7)
256#define M_DUART_ISR_ALL_B _SB_MAKEMASK(4,4)
253 257
254/* 258/*
255 * DUART Channel A Interrupt Status Register (Table 10-17) 259 * DUART Channel A Interrupt Status Register (Table 10-17)
@@ -262,6 +266,7 @@
262#define M_DUART_ISR_RX _SB_MAKEMASK1(1) 266#define M_DUART_ISR_RX _SB_MAKEMASK1(1)
263#define M_DUART_ISR_BRK _SB_MAKEMASK1(2) 267#define M_DUART_ISR_BRK _SB_MAKEMASK1(2)
264#define M_DUART_ISR_IN _SB_MAKEMASK1(3) 268#define M_DUART_ISR_IN _SB_MAKEMASK1(3)
269#define M_DUART_ISR_ALL _SB_MAKEMASK(4,0)
265#define M_DUART_ISR_RESERVED _SB_MAKEMASK(4,4) 270#define M_DUART_ISR_RESERVED _SB_MAKEMASK(4,4)
266 271
267/* 272/*
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 7f2c99d66e9d..9c721cd2c9d6 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -142,6 +142,9 @@
142/* Micrel KS8695 */ 142/* Micrel KS8695 */
143#define PORT_KS8695 76 143#define PORT_KS8695 76
144 144
145/* Broadcom SB1250, etc. SOC */
146#define PORT_SB1250_DUART 77
147
145 148
146#ifdef __KERNEL__ 149#ifdef __KERNEL__
147 150