static void nb85e_uart_tty_enable_tx_interrupts (void *driver_data) { struct nb85e_uart_tty_port *port = driver_data; nb85e_intc_disable_irq (IRQ_INTST (port->chan)); nb85e_uart_tty_tx (port); nb85e_intc_enable_irq (IRQ_INTST (port->chan)); }
static void nb85e_uart_tty_shutdown_port (void *driver_data) { struct nb85e_uart_tty_port *port = driver_data; port->gs.flags &= ~ GS_ACTIVE; /* Disable port interrupts. */ free_irq (IRQ_INTST (port->chan), port); free_irq (IRQ_INTSR (port->chan), port); /* Turn off xmit/recv enable bits. */ NB85E_UART_ASIM (port->chan) &= ~(NB85E_UART_ASIM_TXE | NB85E_UART_ASIM_RXE); /* Then reset the channel. */ NB85E_UART_ASIM (port->chan) = 0; }
void __init mach_sched_init (struct irqaction *timer_action) { /* Select timer interrupt instead of external pin. */ TEG_ISS |= 0x1; /* Start hardware timer. */ v850e_timer_d_configure (0, HZ); /* Install timer interrupt handler. */ setup_irq (IRQ_INTCMD(0), timer_action); } static struct v850e_intc_irq_init irq_inits[] = { { "IRQ", 0, NUM_CPU_IRQS, 1, 7 }, { "CMD", IRQ_INTCMD(0), IRQ_INTCMD_NUM, 1, 5 }, { "SER", IRQ_INTSER(0), IRQ_INTSER_NUM, 1, 3 }, { "SR", IRQ_INTSR(0), IRQ_INTSR_NUM, 1, 4 }, { "ST", IRQ_INTST(0), IRQ_INTST_NUM, 1, 5 }, { 0 } }; #define NUM_IRQ_INITS ((sizeof irq_inits / sizeof irq_inits[0]) - 1) static struct hw_interrupt_type hw_itypes[NUM_IRQ_INITS]; /* Initialize MA chip interrupts. */ void __init teg_init_irqs (void) { v850e_intc_init_irq_types (irq_inits, hw_itypes); } /* Called before configuring an on-chip UART. */ void teg_uart_pre_configure (unsigned chan, unsigned cflags, unsigned baud) {
int nb85e_uart_tty_open (struct tty_struct *tty, struct file *filp) { int err; struct nb85e_uart_tty_port *port; unsigned chan = MINOR (tty->device) - NB85E_UART_MINOR_BASE; if (chan >= NB85E_UART_NUM_CHANNELS) return -ENODEV; port = &nb85e_uart_tty_ports[chan]; tty->driver_data = port; port->gs.tty = tty; port->gs.count++; port->tqueue.routine = gs_do_softint; port->tqueue.data = &port->gs; /* * Start up serial port */ err = gs_init_port (&port->gs); if (err) goto failed_1; port->gs.flags |= GS_ACTIVE; if (port->gs.count == 1) { MOD_INC_USE_COUNT; /* Alloc RX irq. */ err = request_irq (IRQ_INTSR (chan), nb85e_uart_tty_rx_irq, SA_INTERRUPT, "nb85e_uart", port); if (err) goto failed_2; /* Alloc TX irq. */ err = request_irq (IRQ_INTST (chan), nb85e_uart_tty_tx_irq, SA_INTERRUPT, "nb85e_uart", port); if (err) { free_irq (IRQ_INTSR (chan), port); goto failed_2; } } err = gs_block_til_ready (port, filp); if (err) goto failed_3; *tty->termios = port->gs.normal_termios; nb85e_uart_tty_enable_rx_interrupts (port); port->gs.session = current->session; port->gs.pgrp = current->pgrp; return 0; failed_3: free_irq (IRQ_INTST (chan), port); free_irq (IRQ_INTSR (chan), port); failed_2: MOD_DEC_USE_COUNT; failed_1: port->gs.count--; return err; }
static void nb85e_uart_cons_write (struct console *co, const char *s, unsigned count) { if (count > 0) { unsigned chan = co->index; unsigned irq = IRQ_INTST (chan); int irq_was_enabled, irq_was_pending, flags; /* We don't want to get `transmission completed' (INTST) interrupts, since we're busy-waiting, so we disable them while sending (we don't disable interrupts entirely because sending over a serial line is really slow). We save the status of INTST and restore it when we're done so that using printk doesn't interfere with normal serial transmission (other than interleaving the output, of course!). This should work correctly even if this function is interrupted and the interrupt printks something. */ /* Disable interrupts while fiddling with INTST. */ save_flags_cli (flags); /* Get current INTST status. */ irq_was_enabled = nb85e_intc_irq_enabled (irq); irq_was_pending = nb85e_intc_irq_pending (irq); /* Disable INTST if necessary. */ if (irq_was_enabled) nb85e_intc_disable_irq (irq); /* Turn interrupts back on. */ restore_flags (flags); /* Send characters. */ while (count > 0) { int ch = *s++; if (ch == '\n') { /* We don't have the benefit of a tty driver, so translate NL into CR LF. */ nb85e_uart_wait_for_xmit_ok (chan); nb85e_uart_putc (chan, '\r'); } nb85e_uart_wait_for_xmit_ok (chan); nb85e_uart_putc (chan, ch); count--; } /* Restore saved INTST status. */ if (irq_was_enabled) { /* Wait for the last character we sent to be completely transmitted (as we'll get an INTST interrupt at that point). */ nb85e_uart_wait_for_xmit_done (chan); /* Clear pending interrupts received due to our transmission, unless there was already one pending, in which case we want the handler to be called. */ if (! irq_was_pending) nb85e_intc_clear_pending_irq (irq); /* ... and then turn back on handling. */ nb85e_intc_enable_irq (irq); } } }