--- zzzz-none-000/linux-2.6.28.10/drivers/serial/8250.c 2009-05-02 18:54:43.000000000 +0000 +++ fusiv-7390-686/linux-2.6.28.10/drivers/serial/8250.c 2012-02-14 14:37:49.000000000 +0000 @@ -17,6 +17,25 @@ * mapbase is the physical address of the IO port. * membase is an 'ioremapped' cookie. */ +/* Copyright 2008, Texas Instruments Incorporated + * + * This program has been modified from its original operation by Texas Instruments + * to do the following: + * 1) Set uartclk in serial8250_resume_port to support arm frequency change in + * Puma5. + * + * THIS MODIFIED SOFTWARE AND DOCUMENTATION ARE PROVIDED + * "AS IS," AND TEXAS INSTRUMENTS MAKES NO REPRESENTATIONS + * OR WARRENTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY + * PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR + * DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, + * COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. + * See The GNU General Public License for more details. + * + * These changes are covered under version 2 of the GNU General Public License, + * dated June 1991. + */ #if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) #define SUPPORT_SYSRQ @@ -48,6 +67,14 @@ #include "suncore.h" #endif +#ifdef CONFIG_FUSIV_VX185 +#include +#endif + +#if defined (CONFIG_FUSIV_VX185) && defined (CONFIG_CPU_MIPSR2_IRQ_VI) +fusiv_irq_params_t serial_fusiv_irq; +#endif + /* * Configuration: * share_irqs - whether we pass IRQF_SHARED to request_irq(). This option @@ -59,10 +86,22 @@ static struct uart_driver serial8250_reg; +#if 0 /* This piece of code is commented to resolve Bug# 24551 & 24334 */ +#if defined (CONFIG_MACH_FUSIV) +extern void fusiv_uart_get_options(struct uart_port *uart, int *baud, + int *parity, int *bits); +#endif +#endif + static int serial_index(struct uart_port *port) { return (serial8250_reg.minor - 64) + port->line; } +#if defined(CONFIG_SERIAL_8250_CONSOLE_MUTE) +static unsigned int avm_serial_mute_flag = 1; +#else /*--- #if defined(CONFIG_SERIAL_8250_CONSOLE_MUTE) ---*/ +static unsigned int avm_serial_mute_flag = 0; +#endif /*--- #else ---*/ /*--- #if defined(CONFIG_SERIAL_8250_CONSOLE_MUTE) ---*/ /* * Debugging. @@ -124,6 +163,28 @@ static unsigned int probe_rsa_count; #endif /* CONFIG_SERIAL_8250_RSA */ +/*------------------------------------------------------------------------------------------*\ +\*------------------------------------------------------------------------------------------*/ +#define USE_TEST_AND_SET +#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 */ @@ -147,6 +208,7 @@ unsigned char lsr_saved_flags; #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA unsigned char msr_saved_flags; + volatile unsigned int tx_busy; /* * We provide a per-port pm hook. @@ -197,6 +259,34 @@ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, .flags = UART_CAP_FIFO, }, + [PORT_PUMA5] = { + .name = "PUMA5_UART", + .fifo_size = 16, + .tx_loadsz = 16, + .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, @@ -855,7 +945,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; /* @@ -955,6 +1049,9 @@ return; } +#ifdef CONFIG_ARCH_PUMA5 + up->port.type = PORT_PUMA5; +#else /*--- #ifdef CONFIG_ARCH_PUMA5 ---*/ /* * Try writing and reading the UART_IER_UUE bit (b6). * If it works, this is probably one of the Xscale platform's @@ -977,6 +1074,7 @@ * We'll leave the UART_IER_UUE bit set to 1 (enabled). */ DEBUG_AUTOCONF("Xscale "); + up->port.type = PORT_XSCALE; up->capabilities |= UART_CAP_UUE; return; @@ -989,6 +1087,7 @@ DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 "); } serial_outp(up, UART_IER, iersave); +#endif /*--- #else ---*/ /*--- #ifdef CONFIG_ARCH_PUMA5 ---*/ } /* @@ -1225,10 +1324,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) @@ -1252,6 +1353,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); @@ -1268,6 +1375,16 @@ transmit_chars(up); } } +#else /*--- #if !defined(USE_TEST_AND_SET) ---*/ + if((avm_serial_mute_flag & 0x01) == 0) { + if(atomic_test_and_set(&up->tx_busy) == 0) { + /*--- gpio_set(0); ---*/ + transmit_chars(up); + } + } else { /*--- wird sowieso verworfen ---*/ + transmit_chars(up); + } +#endif /*--- #else ---*/ /*--- #if !defined(USE_TEST_AND_SET) ---*/ /* * Re-enable the transmitter if we disabled it. @@ -1308,9 +1425,9 @@ char flag; do { - if (likely(lsr & UART_LSR_DR)) + if (likely(lsr & UART_LSR_DR)){ ch = serial_inp(up, UART_RX); - else + } else /* * Intel 82571 has a Serial Over Lan device that will * set UART_LSR_BI without setting UART_LSR_DR when @@ -1378,20 +1495,35 @@ static void transmit_chars(struct uart_8250_port *up) { struct circ_buf *xmit = &up->port.info->xmit; - int count; + if((avm_serial_mute_flag & 0x01) == 0) { + 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); 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; } @@ -1408,9 +1540,26 @@ 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) ---*/ + } else { + if (up->port.x_char) { + up->port.icount.tx++; + up->port.x_char = 0; + } + while(xmit->tail != xmit->head) { + up->port.icount.tx++; + xmit->tail++; + xmit->tail &= (UART_XMIT_SIZE - 1); + } + } } static unsigned int check_modem_status(struct uart_8250_port *up) @@ -1475,7 +1624,11 @@ */ static irqreturn_t serial8250_interrupt(int irq, void *dev_id) { +#if defined (CONFIG_FUSIV_VX185) && defined (CONFIG_CPU_MIPSR2_IRQ_VI) + struct irq_info *i = (struct irq_info *) (((fusiv_irq_params_t *) dev_id)->priv); +#else struct irq_info *i = dev_id; +#endif struct list_head *l, *end = NULL; int pass_counter = 0, handled = 0; @@ -1598,8 +1751,15 @@ i->head = &up->list; spin_unlock_irq(&i->lock); +#if defined (CONFIG_FUSIV_VX185) && defined (CONFIG_CPU_MIPSR2_IRQ_VI) + serial_fusiv_irq.ipc_src = UART1_INT; + serial_fusiv_irq.priv = (void *) i; + ret = request_irq(up->port.irq, serial8250_interrupt, + irq_flags, "serial", &serial_fusiv_irq); +#else ret = request_irq(up->port.irq, serial8250_interrupt, irq_flags, "serial", i); +#endif if (ret < 0) serial_do_unlink(i, up); } @@ -1609,7 +1769,7 @@ static void serial_unlink_irq_chain(struct uart_8250_port *up) { - struct irq_info *i; + struct irq_info *i = NULL; struct hlist_node *n; struct hlist_head *h; @@ -1623,6 +1783,7 @@ break; } + BUG_ON(i == NULL); BUG_ON(n == NULL); BUG_ON(i->head == NULL); @@ -2154,6 +2315,8 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { +/* We commented below piece of code to resolve Bug# 24551 & 24334 */ +#if !defined(CONFIG_MACH_FUSIV) struct uart_8250_port *up = (struct uart_8250_port *)port; unsigned char cval, fcr = 0; unsigned long flags; @@ -2325,6 +2488,7 @@ /* Don't rewrite B0 */ if (tty_termios_baud_rate(termios)) tty_termios_encode_baud_rate(termios, baud, baud); +#endif } static void @@ -2617,7 +2781,12 @@ { struct uart_8250_port *up = (struct uart_8250_port *)port; - wait_for_xmitr(up, UART_LSR_THRE); + +#ifdef CONFIG_ARCH_PUMA5 + wait_for_xmitr(up, BOTH_EMPTY); +#else/*--- #ifdef CONFIG_ARCH_PUMA5 ---*/ + wait_for_xmitr(up, UART_LSR_THRE); +#endif/*--- #else ---*//*--- #ifdef CONFIG_ARCH_PUMA5 ---*/ serial_out(up, UART_TX, ch); } @@ -2682,8 +2851,13 @@ static int __init serial8250_console_setup(struct console *co, char *options) { +#if defined(CONFIG_MACH_FUSIV) || defined(CONFIG_MACH_ADI_FUSIV) || defined(CONFIG_MIPS_FUSIV) /*setup in loader */ + /* use whatever bootloader settting */ + return 0; +#else struct uart_port *port; - int baud = 9600; + /*--- int baud = 9600; ---*/ + int baud = 115200; int bits = 8; int parity = 'n'; int flow = 'n'; @@ -2695,14 +2869,19 @@ */ if (co->index >= nr_uarts) co->index = 0; + port = &serial8250_ports[co->index].port; if (!port->iobase && !port->membase) return -ENODEV; if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); - +#if 0 //defined (CONFIG_MACH_FUSIV) + else + fusiv_uart_get_options(port, &baud, &parity, &bits); +#endif return uart_set_options(port, co, baud, parity, bits, flow); +#endif } static int serial8250_console_early_setup(void) @@ -2810,6 +2989,10 @@ serial_outp(up, UART_LCR, 0); } +#ifdef CONFIG_ARCH_PUMA5 + extern unsigned int avalanche_get_vbus_freq(void); + up->port.uartclk = avalanche_get_vbus_freq (); +#endif uart_resume_port(&serial8250_reg, &up->port); }