static int txx9_sio_kgdb_init(void) { struct uart_port *port = &uart_txx9_port[kgdb_txx9_ttyS]; unsigned int quot, sibgr; if (port->iotype != UPIO_MEM && port->iotype != UPIO_MEM32) return -1; /* Reset the UART. */ sio_out(port, TXX9_SIFCR, TXX9_SIFCR_SWRST); #ifdef CONFIG_CPU_TX49XX /* * TX4925 BUG WORKAROUND. Accessing SIOC register * immediately after soft reset causes bus error. */ iob(); udelay(1); #endif /* Wait until reset is complete. */ while (sio_in(port, TXX9_SIFCR) & TXX9_SIFCR_SWRST); /* Select the frame format and input clock. */ sio_out(port, TXX9_SILCR, TXX9_SILCR_UMODE_8BIT | TXX9_SILCR_USBL_1BIT | ((port->flags & UPF_MAGIC_MULTIPLIER) ? TXX9_SILCR_SCS_SCLK_BG : TXX9_SILCR_SCS_IMCLK_BG)); /* Select the input clock prescaler that fits the baud rate. */ quot = (port->uartclk + 8 * kgdb_txx9_baud) / (16 * kgdb_txx9_baud); if (quot < (256 << 1)) sibgr = (quot >> 1) | TXX9_SIBGR_BCLK_T0; else if (quot < ( 256 << 3))
/* * This is the serial driver's interrupt routine. * * Arjan thinks the old way was overly complex, so it got simplified. * Alan disagrees, saying that need the complexity to handle the weird * nature of ISA shared interrupts. (This is a special exception.) * * In order to handle ISA shared interrupts properly, we need to check * that all ports have been serviced, and therefore the ISA interrupt * line has been de-asserted. * * This means we need to loop through all ports. checking that they * don't have an interrupt pending. */ static irqreturn_t m32r_sio_interrupt(int irq, void *dev_id) { struct irq_info *i = dev_id; struct list_head *l, *end = NULL; int pass_counter = 0; pr_debug("m32r_sio_interrupt(%d)...\n", irq); #ifdef CONFIG_SERIAL_M32R_PLDSIO // if (irq == PLD_IRQ_SIO0_SND) // irq = PLD_IRQ_SIO0_RCV; #else if (irq == M32R_IRQ_SIO0_S) irq = M32R_IRQ_SIO0_R; #endif spin_lock(&i->lock); l = i->head; do { struct uart_sio_port *up; unsigned int sts; up = list_entry(l, struct uart_sio_port, list); sts = sio_in(up, SIOSTS); if (sts & 0x5) { spin_lock(&up->port.lock); m32r_sio_handle_port(up, sts); spin_unlock(&up->port.lock); end = NULL; } else if (end == NULL) end = l; l = l->next; if (l == i->head && pass_counter++ > PASS_LIMIT) { if (sts & 0xe0) sio_error(&sts); break; } } while (l != end); spin_unlock(&i->lock); pr_debug("end.\n"); return IRQ_HANDLED; }
/* * This function is used to handle ports that do not have an interrupt. */ static void m32r_sio_timeout(unsigned long data) { struct uart_sio_port *up = (struct uart_sio_port *)data; unsigned int timeout; unsigned int sts; sts = sio_in(up, SIOSTS); if (sts & 0x5) { spin_lock(&up->port.lock); m32r_sio_handle_port(up, sts); spin_unlock(&up->port.lock); } timeout = up->port.timeout; timeout = timeout > 6 ? (timeout / 2 - 2) : 1; mod_timer(&up->timer, jiffies + timeout); }
/* * Wait for transmitter & holding register to empty */ static void wait_for_xmitr(struct uart_sio_port *up) { unsigned int status, tmout = 10000; /* Wait up to 10ms for the character(s) to be sent. */ do { status = sio_in(up, SIOSTS); if (--tmout == 0) break; udelay(1); } while ((status & UART_EMPTY) != UART_EMPTY); /* Wait up to 1s for flow control if necessary */ if (up->port.flags & UPF_CONS_FLOW) { tmout = 1000000; while (--tmout) udelay(1); } }
/* * Print a string to the serial port trying not to disturb * any possible real use of the port... * * The console_lock must be held when we get here. */ static void m32r_sio_console_write(struct console *co, const char *s, unsigned int count) { struct uart_sio_port *up = &m32r_sio_ports[co->index]; unsigned int ier; /* * First save the UER then disable the interrupts */ ier = sio_in(up, SIOTRCR); sio_out(up, SIOTRCR, 0); uart_console_write(&up->port, s, count, m32r_sio_console_putchar); /* * Finally, wait for transmitter to become empty * and restore the IER */ wait_for_xmitr(up); sio_out(up, SIOTRCR, ier); }
static void receive_chars(struct uart_sio_port *up, int *status) { struct tty_port *port = &up->port.state->port; unsigned char ch; unsigned char flag; int max_count = 256; do { ch = sio_in(up, SIORXB); flag = TTY_NORMAL; up->port.icount.rx++; if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE | UART_LSR_FE | UART_LSR_OE))) { /* * For statistics only */ if (*status & UART_LSR_BI) { *status &= ~(UART_LSR_FE | UART_LSR_PE); up->port.icount.brk++; /* * We do the SysRQ and SAK checking * here because otherwise the break * may get masked by ignore_status_mask * or read_status_mask. */ if (uart_handle_break(&up->port)) goto ignore_char; } else if (*status & UART_LSR_PE) up->port.icount.parity++; else if (*status & UART_LSR_FE) up->port.icount.frame++; if (*status & UART_LSR_OE) up->port.icount.overrun++; /* * Mask off conditions which should be ingored. */ *status &= up->port.read_status_mask; if (*status & UART_LSR_BI) { pr_debug("handling break....\n"); flag = TTY_BREAK; } else if (*status & UART_LSR_PE) flag = TTY_PARITY; else if (*status & UART_LSR_FE) flag = TTY_FRAME; } if (uart_handle_sysrq_char(&up->port, ch)) goto ignore_char; if ((*status & up->port.ignore_status_mask) == 0) tty_insert_flip_char(port, ch, flag); if (*status & UART_LSR_OE) { /* * Overrun is special, since it's reported * immediately, and doesn't affect the current * character. */ tty_insert_flip_char(port, 0, TTY_OVERRUN); } ignore_char: *status = serial_in(up, UART_LSR); } while ((*status & UART_LSR_DR) && (max_count-- > 0)); spin_unlock(&up->port.lock); tty_flip_buffer_push(port); spin_lock(&up->port.lock); }
static inline void sio_set(struct uart_txx9_port *up, int offset, unsigned int value) { sio_out(up, offset, sio_in(up, offset) | value); }