--- zzzz-none-000/linux-2.6.19.2/drivers/serial/8250.c 2007-01-10 19:10:37.000000000 +0000 +++ davinci-8020-5505/linux-2.6.19.2/drivers/serial/8250.c 2008-06-26 12:46:33.000000000 +0000 @@ -116,6 +116,31 @@ static unsigned int probe_rsa_count; #endif /* CONFIG_SERIAL_8250_RSA */ + +/*------------------------------------------------------------------------------------------*\ +\*------------------------------------------------------------------------------------------*/ +/*--- #if defined(CONFIG_ARM) ---*/ +#define USE_TEST_AND_SET +/*--- #endif ---*/ /*--- #if CONFIG_ARM ---*/ +#if defined(USE_TEST_AND_SET) +#if defined(CONFIG_ARM) +#include +#endif /*--- #if defined(CONFIG_ARM) ---*/ +#include +/*--- #include ---*/ + +int atomic_test_and_set(volatile unsigned int *ptr) { + unsigned long flags; + unsigned int old; + raw_local_irq_save(flags); + old = *ptr; + *ptr = 1; + raw_local_irq_restore(flags); + return old; +} + +#endif /*--- #if defined(USE_TEST_AND_SET) ---*/ + struct uart_8250_port { struct uart_port port; struct timer_list timer; /* "no irq" timer */ @@ -130,6 +155,7 @@ unsigned char mcr_mask; /* mask of user bits */ unsigned char mcr_force; /* mask of forced bits */ unsigned char lsr_break_flag; + volatile unsigned int tx_busy; /* * We provide a per-port pm hook. @@ -176,6 +202,27 @@ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, .flags = UART_CAP_FIFO, }, + [PORT_OHIO] = { + .name = "OHIO_UART", + .fifo_size = 16, + .tx_loadsz = 16, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00, + .flags = UART_CAP_FIFO, + }, + [PORT_UR8] = { + .name = "UR8_UART", + .fifo_size = 16, + .tx_loadsz = 16, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00, + .flags = UART_CAP_FIFO, + }, + [PORT_DAVINCI] = { + .name = "DAVINCI_UART", + .fifo_size = 16, + .tx_loadsz = 16, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00 | UART_FCR_DMA_SELECT, + .flags = UART_CAP_FIFO, + }, [PORT_CIRRUS] = { .name = "Cirrus", .fifo_size = 1, @@ -566,6 +613,7 @@ serial_dl_write(up, old_dl); serial_outp(up, UART_LCR, old_lcr); + return count; } @@ -736,7 +784,11 @@ unsigned char status1, status2; unsigned int iersave; +#ifdef CONFIG_ARCH_DAVINCI + up->port.type = PORT_DAVINCI; +#else /*--- #ifdef CONFIG_ARCH_DAVINCI ---*/ up->port.type = PORT_16550A; +#endif /*--- #else ---*/ /*--- #ifdef CONFIG_ARCH_DAVINCI ---*/ up->capabilities |= UART_CAP_FIFO; /* @@ -1104,10 +1156,12 @@ static inline void __stop_tx(struct uart_8250_port *p) { +#if !defined(USE_TEST_AND_SET) if (p->ier & UART_IER_THRI) { p->ier &= ~UART_IER_THRI; serial_out(p, UART_IER, p->ier); } +#endif /*--- #if !defined(USE_TEST_AND_SET) ---*/ } static void serial8250_stop_tx(struct uart_port *port) @@ -1131,6 +1185,12 @@ { struct uart_8250_port *up = (struct uart_8250_port *)port; +#if defined(CONFIG_DAVINCI_DRM_KUNDENVERSION) /*--- keine Ausgaben auf der seriellen ---*/ + if (port->irq == IRQ_UARTINT0) + return; +#endif + +#if !defined(USE_TEST_AND_SET) if (!(up->ier & UART_IER_THRI)) { up->ier |= UART_IER_THRI; serial_out(up, UART_IER, up->ier); @@ -1139,10 +1199,16 @@ unsigned char lsr, iir; lsr = serial_in(up, UART_LSR); iir = serial_in(up, UART_IIR); - if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) + if ((lsr & UART_LSR_TEMT) && (iir & UART_IIR_NO_INT)) transmit_chars(up); } } +#else /*--- #if !defined(USE_TEST_AND_SET) ---*/ + if(atomic_test_and_set(&up->tx_busy) == 0) { + /*--- gpio_set(0); ---*/ + transmit_chars(up); + } +#endif /*--- #else ---*/ /*--- #if !defined(USE_TEST_AND_SET) ---*/ /* * Re-enable the transmitter if we disabled it. @@ -1197,8 +1263,7 @@ } #endif - if (unlikely(lsr & (UART_LSR_BI | UART_LSR_PE | - UART_LSR_FE | UART_LSR_OE))) { + if (unlikely(lsr & (UART_LSR_BI | UART_LSR_PE | UART_LSR_FE | UART_LSR_OE))) { /* * For statistics only */ @@ -1252,24 +1317,42 @@ struct circ_buf *xmit = &up->port.info->xmit; int count; +#if defined(USE_TEST_AND_SET) + up->ier &= ~UART_IER_THRI; + serial_out(up, UART_IER, up->ier); +#endif /*--- #if defined(USE_TEST_AND_SET) ---*/ + if (up->port.x_char) { - serial_outp(up, UART_TX, up->port.x_char); +#if !defined(CONFIG_SERIAL_8250_CONSOLE_MUTE) + serial_outp(up, UART_TX, up->port.x_char); +#endif up->port.icount.tx++; up->port.x_char = 0; +#if defined(USE_TEST_AND_SET) + up->ier |= UART_IER_THRI; + serial_out(up, UART_IER, up->ier); +#endif /*--- #if defined(USE_TEST_AND_SET) ---*/ return; } if (uart_tx_stopped(&up->port)) { serial8250_stop_tx(&up->port); + printk("??? stoped ????\n"); return; } if (uart_circ_empty(xmit)) { __stop_tx(up); +#if defined(USE_TEST_AND_SET) + /*--- gpio_clear(0); ---*/ + up->tx_busy = 0; +#endif /*--- #if defined(USE_TEST_AND_SET) ---*/ return; } count = up->tx_loadsz; do { - serial_out(up, UART_TX, xmit->buf[xmit->tail]); +#if !defined(CONFIG_SERIAL_8250_CONSOLE_MUTE) + serial_out(up, UART_TX, xmit->buf[xmit->tail]); +#endif xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); up->port.icount.tx++; if (uart_circ_empty(xmit)) @@ -1280,9 +1363,15 @@ uart_write_wakeup(&up->port); DEBUG_INTR("THRE..."); + /*--- printk("[THRE] ..."); ---*/ if (uart_circ_empty(xmit)) __stop_tx(up); + +#if defined(USE_TEST_AND_SET) + up->ier |= UART_IER_THRI; + serial_out(up, UART_IER, up->ier); +#endif /*--- #if defined(USE_TEST_AND_SET) ---*/ } static unsigned int check_modem_status(struct uart_8250_port *up) @@ -1321,6 +1410,10 @@ if (status & UART_LSR_DR) receive_chars(up, &status); +#if defined(CONFIG_MIPS_OHIO) || defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_UR8) + if (status & UART_LSR_BI) + receive_chars(up, &status); +#endif /*--- #if defined(CONFIG_MIPS_OHIO) || defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_UR8) ---*/ check_modem_status(up); if (status & UART_LSR_THRE) transmit_chars(up); @@ -1383,7 +1476,11 @@ DEBUG_INTR("end.\n"); +#ifdef CONFIG_ARCH_OMAP15XX + return IRQ_HANDLED; /* FIXME: iir status not ready on 1510 */ +#else return IRQ_RETVAL(handled); +#endif } /* @@ -1426,8 +1523,7 @@ i->head = &up->list; spin_unlock_irq(&i->lock); - ret = request_irq(up->port.irq, serial8250_interrupt, - irq_flags, "serial", i); + ret = request_irq(up->port.irq, serial8250_interrupt, irq_flags, "serial", i); if (ret < 0) serial_do_unlink(i, up); } @@ -1654,7 +1750,7 @@ iir = serial_in(up, UART_IIR); serial_outp(up, UART_IER, 0); - if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) { + if ((lsr & UART_LSR_TEMT) && (iir & UART_IIR_NO_INT)) { if (!(up->bugs & UART_BUG_TXEN)) { up->bugs |= UART_BUG_TXEN; pr_debug("ttyS%d - enabling bad tx status workarounds\n", @@ -1798,6 +1894,10 @@ cval |= UART_LCR_SPAR; #endif +#if defined(CONFIG_MIPS_OHIO) || defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_UR8) + /*--- es wird kein autoconfig verwendet! ---*/ + up->capabilities = uart_config[up->port.type].flags; +#endif/*--- #if defined(CONFIG_MIPS_OHIO) || defined(CONFIG_MIPS_AR7) || defined(CONFIG_MIPS_UR8) ---*/ /* * Ask the core to calculate the divisor for us. */ @@ -1880,6 +1980,8 @@ if (up->capabilities & UART_CAP_UUE) up->ier |= UART_IER_UUE | UART_IER_RTOIE; + up->ier &= ~(UART_IER_MSI | 0); + serial_out(up, UART_IER, up->ier); if (up->capabilities & UART_CAP_EFR) { @@ -1930,6 +2032,19 @@ /* emulated UARTs (Lucent Venus 167x) need two steps */ serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); } + + /* Note that we need to set ECB to access write water mark + * bits. First allow FCR tx fifo write, then set fcr with + * possible TX fifo settings. */ + if (uart_config[up->port.type].flags & UART_CAP_EFR) { + serial_outp(up, UART_LCR, 0xbf); /* Access EFR */ + serial_outp(up, UART_EFR, UART_EFR_ECB); + serial_outp(up, UART_LCR, 0x0); /* Access FCR */ + serial_outp(up, UART_FCR, fcr); + serial_outp(up, UART_LCR, 0xbf); /* Access EFR */ + serial_outp(up, UART_EFR, 0); + serial_outp(up, UART_LCR, cval); /* Access FCR */ + } else serial_outp(up, UART_FCR, fcr); /* set fcr */ } serial8250_set_mctrl(&up->port, up->port.mctrl); @@ -1956,6 +2071,11 @@ unsigned int size = 8 << up->port.regshift; int ret = 0; +#ifdef CONFIG_ARCH_OMAP + if (is_omap_port((unsigned int)up->port.membase)) + size = 0x16 << up->port.regshift; +#endif + switch (up->port.iotype) { case UPIO_AU: size = 0x100000; @@ -2153,10 +2273,12 @@ static int first = 1; int i; + if (!first) return; first = 0; + for (i = 0; i < nr_uarts; i++) { struct uart_8250_port *up = &serial8250_ports[i]; @@ -2244,7 +2366,10 @@ struct uart_8250_port *up = (struct uart_8250_port *)port; wait_for_xmitr(up, UART_LSR_THRE); + +#if !defined(CONFIG_SERIAL_8250_CONSOLE_MUTE) serial_out(up, UART_TX, ch); +#endif } /* @@ -2299,7 +2424,8 @@ static int serial8250_console_setup(struct console *co, char *options) { struct uart_port *port; - int baud = 9600; + /*--- int baud = 9600; ---*/ + int baud = 115200; int bits = 8; int parity = 'n'; int flow = 'n'; @@ -2311,6 +2437,7 @@ */ if (co->index >= nr_uarts) co->index = 0; + port = &serial8250_ports[co->index].port; if (!port->iobase && !port->membase) return -ENODEV; @@ -2380,11 +2507,11 @@ static struct uart_driver serial8250_reg = { .owner = THIS_MODULE, - .driver_name = "serial", + .driver_name = "serial", .dev_name = "ttyS", .major = TTY_MAJOR, .minor = 64, - .nr = UART_NR, + .nr = UART_NR, .cons = SERIAL8250_CONSOLE, }; @@ -2602,6 +2729,7 @@ if (port->dev) uart->port.dev = port->dev; + ret = uart_add_one_port(&serial8250_reg, &uart->port); if (ret == 0) ret = uart->port.line; @@ -2637,7 +2765,10 @@ } EXPORT_SYMBOL(serial8250_unregister_port); -static int __init serial8250_init(void) +#if !defined(CONFIG_MIPS_OHIO) && !defined(CONFIG_MIPS_AR7) && !defined(CONFIG_ARCH_DAVINCI) && !defined(CONFIG_MIPS_UR8) +static +#endif /*--- #if !defined(CONFIG_MIPS_OHIO) && !defined(CONFIG_MIPS_AR7) && !defined(CONFIG_ARCH_DAVINCI) && !defined(CONFIG_MIPS_UR8) ---*/ +int __init serial8250_init(void) { int ret, i;