X-Git-Url: http://git.rohieb.name/openwrt.git/blobdiff_plain/c92885c466d11dc3b8e2837a8be1fd3b6b7e2e01..ebd093f2fa1855b10efdc70772e1024dd37b1a4a:/target/linux/sibyte-2.6/patches/000-DUART.patch diff --git a/target/linux/sibyte-2.6/patches/000-DUART.patch b/target/linux/sibyte-2.6/patches/000-DUART.patch index 86b7666da..468d9dfac 100644 --- a/target/linux/sibyte-2.6/patches/000-DUART.patch +++ b/target/linux/sibyte-2.6/patches/000-DUART.patch @@ -1,9 +1,9 @@ -diff -Nur linux-2.6.17/drivers/char/Kconfig linux-2.6.17-owrt/drivers/char/Kconfig ---- linux-2.6.17/drivers/char/Kconfig 2006-06-18 03:49:35.000000000 +0200 -+++ linux-2.6.17-owrt/drivers/char/Kconfig 2006-06-18 12:41:36.000000000 +0200 -@@ -340,6 +340,14 @@ - To compile this driver as a module, choose M here: the - module will be called istallion. +diff -Nur linux-2.6.21.1/drivers/char/Kconfig linux-2.6.21.1-owrt/drivers/char/Kconfig +--- linux-2.6.21.1/drivers/char/Kconfig 2007-04-27 23:49:26.000000000 +0200 ++++ linux-2.6.21.1-owrt/drivers/char/Kconfig 2007-05-24 22:28:54.000000000 +0200 +@@ -386,6 +386,14 @@ + If you have an Alchemy AU1000 processor (MIPS based) and you want + to use a console on a serial port, say Y. Otherwise, say N. +config SIBYTE_SB1250_DUART + bool "Support for BCM1xxx onchip DUART" @@ -13,24 +13,24 @@ diff -Nur linux-2.6.17/drivers/char/Kconfig linux-2.6.17-owrt/drivers/char/Kconf + bool "Console on BCM1xxx DUART" + depends on SIBYTE_SB1250_DUART + - config AU1000_UART - bool "Enable Au1000 UART Support" - depends on SERIAL_NONSTANDARD && MIPS -diff -Nur linux-2.6.17/drivers/char/Makefile linux-2.6.17-owrt/drivers/char/Makefile ---- linux-2.6.17/drivers/char/Makefile 2006-06-18 03:49:35.000000000 +0200 -+++ linux-2.6.17-owrt/drivers/char/Makefile 2006-06-18 12:42:57.000000000 +0200 -@@ -31,6 +31,7 @@ - obj-$(CONFIG_A2232) += ser_a2232.o generic_serial.o + config SERIAL_DEC + bool "DECstation serial support" + depends on MACH_DECSTATION +diff -Nur linux-2.6.21.1/drivers/char/Makefile linux-2.6.21.1-owrt/drivers/char/Makefile +--- linux-2.6.21.1/drivers/char/Makefile 2007-04-27 23:49:26.000000000 +0200 ++++ linux-2.6.21.1-owrt/drivers/char/Makefile 2007-05-24 22:32:31.000000000 +0200 +@@ -32,6 +32,7 @@ obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o obj-$(CONFIG_MOXA_SMARTIO) += mxser.o + obj-$(CONFIG_MOXA_SMARTIO_NEW) += mxser_new.o +obj-$(CONFIG_SIBYTE_SB1250_DUART) += sb1250_duart.o obj-$(CONFIG_COMPUTONE) += ip2/ obj-$(CONFIG_RISCOM8) += riscom8.o obj-$(CONFIG_ISI) += isicom.o -diff -Nur linux-2.6.17/drivers/char/sb1250_duart.c linux-2.6.17-owrt/drivers/char/sb1250_duart.c ---- linux-2.6.17/drivers/char/sb1250_duart.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.17-owrt/drivers/char/sb1250_duart.c 2006-06-18 12:41:36.000000000 +0200 -@@ -0,0 +1,911 @@ +diff -Nur linux-2.6.21.1/drivers/char/sb1250_duart.c linux-2.6.21.1-owrt/drivers/char/sb1250_duart.c +--- linux-2.6.21.1/drivers/char/sb1250_duart.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.21.1-owrt/drivers/char/sb1250_duart.c 2007-05-24 22:10:12.000000000 +0200 +@@ -0,0 +1,979 @@ +/* + * Copyright (C) 2000,2001,2002,2003,2004 Broadcom Corporation + * @@ -43,18 +43,17 @@ diff -Nur linux-2.6.17/drivers/char/sb1250_duart.c linux-2.6.17-owrt/drivers/cha + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. -+ * ++ * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + -+/* ++/* + * Driver support for the on-chip sb1250 dual-channel serial port, + * running in asynchronous mode. Also, support for doing a serial console -+ * on one of those ports ++ * on one of those ports + */ -+#include +#include +#include +#include @@ -115,69 +114,71 @@ diff -Nur linux-2.6.17/drivers/char/sb1250_duart.c linux-2.6.17-owrt/drivers/cha +EXPORT_SYMBOL(sb1250_duart_present); + +/* -+ * Still not sure what the termios structures set up here are for, ++ * In bug 1956, we get glitches that can mess up uart registers. This ++ * "read-mode-reg after any register access" is an accepted workaround. ++ */ ++#if SIBYTE_1956_WAR ++# define SB1_SER1956_WAR { \ ++ u32 ignore; \ ++ ignore = csr_in32(uart_states[line].mode_1); \ ++ ignore = csr_in32(uart_states[line].mode_2); \ ++ } ++#else ++# define SB1_SER1956_WAR ++#endif ++ ++/* ++ * Still not sure what the termios structures set up here are for, + * but we have to supply pointers to them to register the tty driver + */ +static struct tty_driver *sb1250_duart_driver; //, sb1250_duart_callout_driver; + +/* -+ * This lock protects both the open flags for all the uart states as ++ * This lock protects both the open flags for all the uart states as + * well as the reference count for the module + */ +static DEFINE_SPINLOCK(open_lock); + -+typedef struct { -+ unsigned char outp_buf[SERIAL_XMIT_SIZE]; -+ unsigned int outp_head; -+ unsigned int outp_tail; -+ unsigned int outp_count; -+ spinlock_t outp_lock; -+ unsigned int open; -+ unsigned int line; -+ unsigned int last_cflags; -+ unsigned long flags; -+ struct tty_struct *tty; ++typedef struct { ++ unsigned char outp_buf[SERIAL_XMIT_SIZE]; ++ unsigned int outp_head; ++ unsigned int outp_tail; ++ unsigned int outp_count; ++ spinlock_t outp_lock; ++ unsigned int open; ++ unsigned int line; ++ unsigned int last_cflags; ++ unsigned long flags; ++ struct tty_struct *tty; ++ + /* CSR addresses */ -+ volatile u32 *status; -+ volatile u32 *imr; -+ volatile u32 *tx_hold; -+ volatile u32 *rx_hold; -+ volatile u32 *mode_1; -+ volatile u32 *mode_2; -+ volatile u32 *clk_sel; -+ volatile u32 *cmd; ++ unsigned int *status; ++ unsigned int *imr; ++ unsigned int *tx_hold; ++ unsigned int *rx_hold; ++ unsigned int *mode_1; ++ unsigned int *mode_2; ++ unsigned int *clk_sel; ++ unsigned int *cmd; +} uart_state_t; + +static uart_state_t uart_states[DUART_MAX_LINE]; + +/* -+ * Inline functions local to this module ++ * Inline functions local to this module + */ + -+/* -+ * In bug 1956, we get glitches that can mess up uart registers. This -+ * "write-mode-1 after any register access" is the accepted -+ * workaround. -+ */ -+#if SIBYTE_1956_WAR -+static unsigned int last_mode1[DUART_MAX_LINE]; -+#endif -+ +static inline u32 READ_SERCSR(volatile u32 *addr, int line) +{ + u32 val = csr_in32(addr); -+#if SIBYTE_1956_WAR -+ csr_out32(last_mode1[line], uart_states[line].mode_1); -+#endif ++ SB1_SER1956_WAR; + return val; +} + +static inline void WRITE_SERCSR(u32 val, volatile u32 *addr, int line) +{ + csr_out32(val, addr); -+#if SIBYTE_1956_WAR -+ csr_out32(last_mode1[line], uart_states[line].mode_1); -+#endif ++ SB1_SER1956_WAR; +} + +static void init_duart_port(uart_state_t *port, int line) @@ -192,6 +193,8 @@ diff -Nur linux-2.6.17/drivers/char/sb1250_duart.c linux-2.6.17-owrt/drivers/cha + port->mode_2 = IOADDR(UNIT_CHANREG(line, R_DUART_MODE_REG_2)); + port->clk_sel = IOADDR(UNIT_CHANREG(line, R_DUART_CLK_SEL)); + port->cmd = IOADDR(UNIT_CHANREG(line, R_DUART_CMD)); ++ port->last_cflags = DEFAULT_CFLAGS; ++ spin_lock_init(&port->outp_lock); + port->flags |= DUART_INITIALIZED; + } +} @@ -207,7 +210,7 @@ diff -Nur linux-2.6.17/drivers/char/sb1250_duart.c linux-2.6.17-owrt/drivers/cha + WRITE_SERCSR(tmp & ~mask, port->imr, line); +} + -+ ++ +/* Unmask the passed interrupt lines at the duart level */ +static inline void duart_unmask_ints(unsigned int line, unsigned int mask) +{ @@ -247,7 +250,7 @@ diff -Nur linux-2.6.17/drivers/char/sb1250_duart.c linux-2.6.17-owrt/drivers/cha + duart_mask_ints(us->line, M_DUART_IMR_TX); + } + -+ if (us->open && ++ if (us->open && + (us->outp_count < (SERIAL_XMIT_SIZE/2))) { + /* + * We told the discipline at one point that we had no @@ -261,10 +264,10 @@ diff -Nur linux-2.6.17/drivers/char/sb1250_duart.c linux-2.6.17-owrt/drivers/cha + } +} + -+/* ++/* + * Generic interrupt handler for both channels. dev_id is a pointer -+ * to the proper uart_states structure, so from that we can derive -+ * which port interrupted ++ * to the proper uart_states structure, so from that we can derive ++ * which port interrupted + */ + +static irqreturn_t duart_int(int irq, void *dev_id) @@ -324,10 +327,10 @@ diff -Nur linux-2.6.17/drivers/char/sb1250_duart.c linux-2.6.17-owrt/drivers/cha + +/* memcpy the data from src to destination, but take extra care if the + data is coming from user space */ -+static inline int copy_buf(char *dest, const char *src, int size, int from_user) ++static inline int copy_buf(char *dest, const char *src, int size, int from_user) +{ + if (from_user) { -+ (void) copy_from_user(dest, src, size); ++ (void) copy_from_user(dest, src, size); + } else { + memcpy(dest, src, size); + } @@ -350,7 +353,8 @@ diff -Nur linux-2.6.17/drivers/char/sb1250_duart.c linux-2.6.17-owrt/drivers/cha + us = tty->driver_data; + if (!us) return 0; + -+ pr_debug("duart_write called for %i chars by %i (%s)\n", count, current->pid, current->comm); ++ pr_debug("duart_write called for %i chars by %i (%s)\n", count, ++ current->pid, current->comm); + + spin_lock_irqsave(&us->outp_lock, flags); + @@ -376,7 +380,7 @@ diff -Nur linux-2.6.17/drivers/char/sb1250_duart.c linux-2.6.17-owrt/drivers/cha + + spin_unlock_irqrestore(&us->outp_lock, flags); + -+ if (us->outp_count && !tty->stopped && ++ if (us->outp_count && !tty->stopped && + !tty->hw_stopped && !(us->flags & TX_INTEN)) { + us->flags |= TX_INTEN; + duart_unmask_ints(us->line, M_DUART_IMR_TX); @@ -413,11 +417,13 @@ diff -Nur linux-2.6.17/drivers/char/sb1250_duart.c linux-2.6.17-owrt/drivers/cha +{ + uart_state_t *port; + -+ if (!tty) return; ++ if (!tty) ++ return; + + port = tty->driver_data; + -+ if (!port) return; ++ if (!port) ++ return; + + if (port->outp_count <= 0 || tty->stopped || tty->hw_stopped) { + return; @@ -427,7 +433,7 @@ diff -Nur linux-2.6.17/drivers/char/sb1250_duart.c linux-2.6.17-owrt/drivers/cha + duart_unmask_ints(port->line, M_DUART_IMR_TX); +} + -+/* Return the number of characters in the output buffer that have yet to be ++/* Return the number of characters in the output buffer that have yet to be + written */ +static int duart_chars_in_buffer(struct tty_struct *tty) +{ @@ -470,10 +476,10 @@ diff -Nur linux-2.6.17/drivers/char/sb1250_duart.c linux-2.6.17-owrt/drivers/cha + switch (cflag & CSIZE) { + case CS7: + mode_reg1 |= V_DUART_BITS_PER_CHAR_7; -+ ++ + default: -+ /* We don't handle CS5 or CS6...is there a way we're supposed to flag this? -+ right now we just force them to CS8 */ ++ /* We don't handle CS5 or CS6...is there a way we're supposed to ++ * flag this? right now we just force them to CS8 */ + mode_reg1 |= 0x0; + break; + } @@ -486,21 +492,21 @@ diff -Nur linux-2.6.17/drivers/char/sb1250_duart.c linux-2.6.17-owrt/drivers/cha + if (cflag & PARODD) { + mode_reg1 |= M_DUART_PARITY_TYPE_ODD; + } -+ ++ + /* Formula for this is (5000000/baud)-1, but we saturate + at 12 bits, which means we can't actually do anything less + that 1200 baud */ + switch (cflag & CBAUD) { -+ case B200: -+ case B300: ++ case B200: ++ case B300: + case B1200: clk_divisor = 4095; break; + case B1800: clk_divisor = 2776; break; + case B2400: clk_divisor = 2082; break; + case B4800: clk_divisor = 1040; break; -+ default: + case B9600: clk_divisor = 519; break; + case B19200: clk_divisor = 259; break; + case B38400: clk_divisor = 129; break; ++ default: + case B57600: clk_divisor = 85; break; + case B115200: clk_divisor = 42; break; + } @@ -516,25 +522,26 @@ diff -Nur linux-2.6.17/drivers/char/sb1250_duart.c linux-2.6.17-owrt/drivers/cha +{ + uart_state_t *us = (uart_state_t *) tty->driver_data; + -+ pr_debug("duart_set_termios called by %i (%s)\n", current->pid, current->comm); ++ pr_debug("duart_set_termios called by %i (%s)\n", current->pid, ++ current->comm); + if (old && tty->termios->c_cflag == old->c_cflag) + return; + duart_set_cflag(us->line, tty->termios->c_cflag); +} + -+static int get_serial_info(uart_state_t *us, struct serial_struct * retinfo) { -+ ++static int get_serial_info(uart_state_t *us, struct serial_struct * retinfo) ++{ + struct serial_struct tmp; + + memset(&tmp, 0, sizeof(tmp)); + -+ tmp.type=PORT_SB1250; -+ tmp.line=us->line; -+ tmp.port=UNIT_CHANREG(tmp.line,0); -+ tmp.irq=UNIT_INT(tmp.line); -+ tmp.xmit_fifo_size=16; /* fixed by hw */ -+ tmp.baud_base=5000000; -+ tmp.io_type=SERIAL_IO_MEM; ++ tmp.type = PORT_SB1250; ++ tmp.line = us->line; ++ tmp.port = UNIT_CHANREG(tmp.line,0); ++ tmp.irq = UNIT_INT(tmp.line); ++ tmp.xmit_fifo_size = 16; /* fixed by hw */ ++ tmp.baud_base = 5000000; ++ tmp.io_type = SERIAL_IO_MEM; + + if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) + return -EFAULT; @@ -622,10 +629,10 @@ diff -Nur linux-2.6.17/drivers/char/sb1250_duart.c linux-2.6.17-owrt/drivers/cha +} + +/* Not sure on the semantics of this; are we supposed to wait until the stuff -+ already in the hardware FIFO drains, or are we supposed to wait until -+ we've drained the output buffer, too? I'm assuming the former, 'cause thats -+ what the other drivers seem to assume -+*/ ++ * already in the hardware FIFO drains, or are we supposed to wait until ++ * we've drained the output buffer, too? I'm assuming the former, 'cause thats ++ * what the other drivers seem to assume ++ */ + +static void duart_wait_until_sent(struct tty_struct *tty, int timeout) +{ @@ -636,7 +643,7 @@ diff -Nur linux-2.6.17/drivers/char/sb1250_duart.c linux-2.6.17-owrt/drivers/cha + pr_debug("duart_wait_until_sent(%d)+\n", timeout); + while (!(READ_SERCSR(us->status, us->line) & M_DUART_TX_EMT)) { + set_current_state(TASK_INTERRUPTIBLE); -+ schedule_timeout(1); ++ schedule_timeout(1); + if (signal_pending(current)) + break; + if (timeout && time_after(jiffies, orig_jiffies + timeout)) @@ -672,8 +679,8 @@ diff -Nur linux-2.6.17/drivers/char/sb1250_duart.c linux-2.6.17-owrt/drivers/cha + return -ENODEV; + + pr_debug("duart_open called by %i (%s), tty is %p, rw is %p, ww is %p\n", -+ current->pid, current->comm, tty, tty->read_wait, -+ tty->write_wait); ++ current->pid, current->comm, tty, (void *)&tty->read_wait, ++ (void *)&tty->write_wait); + + us = uart_states + line; + tty->driver_data = us; @@ -784,7 +791,7 @@ diff -Nur linux-2.6.17/drivers/char/sb1250_duart.c linux-2.6.17-owrt/drivers/cha + +/* Set up the driver and register it, register the UART interrupts. This + is called from tty_init, or as a part of the module init */ -+static int __init sb1250_duart_init(void) ++static int __init sb1250_duart_init(void) +{ + int i; + @@ -796,7 +803,6 @@ diff -Nur linux-2.6.17/drivers/char/sb1250_duart.c linux-2.6.17-owrt/drivers/cha + + sb1250_duart_driver->owner = THIS_MODULE; + sb1250_duart_driver->name = "duart"; -+ sb1250_duart_driver->devfs_name = "duart/"; + sb1250_duart_driver->major = TTY_MAJOR; + sb1250_duart_driver->minor_start = SB1250_DUART_MINOR_BASE; + sb1250_duart_driver->type = TTY_DRIVER_TYPE_SERIAL; @@ -805,21 +811,29 @@ diff -Nur linux-2.6.17/drivers/char/sb1250_duart.c linux-2.6.17-owrt/drivers/cha + sb1250_duart_driver->flags = TTY_DRIVER_REAL_RAW; + tty_set_operations(sb1250_duart_driver, &duart_ops); + -+ for (i=0; ioutp_lock); + duart_mask_ints(i, M_DUART_IMR_ALL); + if (request_irq(UNIT_INT(i), duart_int, 0, "uart", port)) { + panic("Couldn't get uart0 interrupt line"); + } -+ __raw_writeq(M_DUART_RX_EN|M_DUART_TX_EN, -+ IOADDR(UNIT_CHANREG(i, R_DUART_CMD))); -+ duart_set_cflag(i, DEFAULT_CFLAGS); ++ /* ++ * this generic write to a register does not implement the 1956 ++ * WAR and sometimes output gets corrupted afterwards, ++ * especially if the port was in use as a console. ++ */ ++ __raw_writel(M_DUART_RX_EN|M_DUART_TX_EN, port->cmd); ++ ++ /* ++ * we should really check to see if it's registered as a console ++ * before trashing those settings ++ */ ++ duart_set_cflag(i, port->last_cflags); + } + + /* Interrupts are now active, our ISR can be called. */ @@ -842,7 +856,7 @@ diff -Nur linux-2.6.17/drivers/char/sb1250_duart.c linux-2.6.17-owrt/drivers/cha + tty_unregister_driver(sb1250_duart_driver); + put_tty_driver(sb1250_duart_driver); + -+ for (i=0; iimr, line); +} + @@ -902,25 +916,78 @@ diff -Nur linux-2.6.17/drivers/char/sb1250_duart.c linux-2.6.17-owrt/drivers/cha + + sb1250_duart_init_present_lines(); + -+ for (i=0; imode_1, i); -+ WRITE_SERCSR(M_DUART_STOP_BIT_LEN_1, -+ port->mode_2, i); -+ WRITE_SERCSR(V_DUART_BAUD_RATE(115200), -+ port->clk_sel, i); -+ WRITE_SERCSR(M_DUART_RX_EN|M_DUART_TX_EN, -+ port->cmd, i); ++ if (str) { ++ int speed; ++ char par = 'n'; ++ int cbits = 8; ++ ++ cflags = 0; ++ ++ /* ++ * format is in Documentation/serial_console.txt ++ */ ++ sscanf(str, "%d%c%d", &speed, &par, &cbits); ++ ++ switch (speed) { ++ case 200: ++ case 300: ++ case 1200: ++ cflags |= B1200; ++ break; ++ case 1800: ++ cflags |= B1800; ++ break; ++ case 2400: ++ cflags |= B2400; ++ break; ++ case 4800: ++ cflags |= B4800; ++ break; ++ default: ++ case 9600: ++ cflags |= B9600; ++ break; ++ case 19200: ++ cflags |= B19200; ++ break; ++ case 38400: ++ cflags |= B38400; ++ break; ++ case 57600: ++ cflags |= B57600; ++ break; ++ case 115200: ++ cflags |= B115200; ++ break; ++ } ++ switch (par) { ++ case 'o': ++ cflags |= PARODD; ++ case 'e': ++ cflags |= PARENB; ++ } ++ switch (cbits) { ++ default: // we only do 7 or 8 ++ case 8: ++ cflags |= CS8; ++ break; ++ case 7: ++ cflags |= CS7; ++ break; ++ } ++ } ++ duart_set_cflag(i, cflags); ++ WRITE_SERCSR(M_DUART_RX_EN | M_DUART_TX_EN, port->cmd, i); + } ++ + return 0; +} + @@ -935,6 +1002,7 @@ diff -Nur linux-2.6.17/drivers/char/sb1250_duart.c linux-2.6.17-owrt/drivers/cha + +static int __init sb1250_serial_console_init(void) +{ ++ //add_preferred_console("duart", 0, "57600n8"); + register_console(&sb1250_ser_cons); + return 0; +} @@ -942,9 +1010,9 @@ diff -Nur linux-2.6.17/drivers/char/sb1250_duart.c linux-2.6.17-owrt/drivers/cha +console_initcall(sb1250_serial_console_init); + +#endif /* CONFIG_SIBYTE_SB1250_DUART_CONSOLE */ -diff -Nur linux-2.6.17/include/linux/serial.h linux-2.6.17-owrt/include/linux/serial.h ---- linux-2.6.17/include/linux/serial.h 2006-06-18 03:49:35.000000000 +0200 -+++ linux-2.6.17-owrt/include/linux/serial.h 2006-06-18 12:41:36.000000000 +0200 +diff -Nur linux-2.6.21.1/include/linux/serial.h linux-2.6.21.1-owrt/include/linux/serial.h +--- linux-2.6.21.1/include/linux/serial.h 2007-04-27 23:49:26.000000000 +0200 ++++ linux-2.6.21.1-owrt/include/linux/serial.h 2007-05-24 22:10:29.000000000 +0200 @@ -76,7 +76,8 @@ #define PORT_16654 11 #define PORT_16850 12