return &uart->vuart;
}
+static void pl011_tx_stop(struct serial_port *port)
+{
+ struct pl011 *uart = port->uart;
+
+ pl011_write(uart, IMSC, pl011_read(uart, IMSC) & ~(TXI));
+}
+
+static void pl011_tx_start(struct serial_port *port)
+{
+ struct pl011 *uart = port->uart;
+
+ pl011_write(uart, IMSC, pl011_read(uart, IMSC) | (TXI));
+}
+
static struct uart_driver __read_mostly pl011_driver = {
.init_preirq = pl011_init_preirq,
.init_postirq = pl011_init_postirq,
.putc = pl011_putc,
.getc = pl011_getc,
.irq = pl011_irq,
+ .start_tx = pl011_tx_start,
+ .stop_tx = pl011_tx_stop,
.vuart_info = pl011_vuart,
};
static bool_t __read_mostly post_irq;
+static inline void serial_start_tx(struct serial_port *port)
+{
+ if ( port->driver->start_tx != NULL )
+ port->driver->start_tx(port);
+}
+
+static inline void serial_stop_tx(struct serial_port *port)
+{
+ if ( port->driver->stop_tx != NULL )
+ port->driver->stop_tx(port);
+}
+
void serial_rx_interrupt(struct serial_port *port, struct cpu_user_regs *regs)
{
char c;
cpu_relax();
}
+ if ( port->txbufc == port->txbufp )
+ {
+ /* Disable TX. nothing to send */
+ serial_stop_tx(port);
+ spin_unlock(&port->tx_lock);
+ goto out;
+ }
+ else
+ {
+ if ( port->driver->tx_ready(port) )
+ serial_start_tx(port);
+ }
for ( i = 0, n = port->driver->tx_ready(port); i < n; i++ )
{
if ( port->txbufc == port->txbufp )
cpu_relax();
if ( n > 0 )
{
+ /* Enable TX before sending chars */
+ serial_start_tx(port);
while ( n-- )
port->driver->putc(
port,
if ( ((port->txbufp - port->txbufc) == 0) &&
port->driver->tx_ready(port) > 0 )
{
+ /* Enable TX before sending chars */
+ serial_start_tx(port);
/* Buffer and UART FIFO are both empty, and port is available. */
port->driver->putc(port, c);
}
while ( !(n = port->driver->tx_ready(port)) )
cpu_relax();
if ( n > 0 )
+ {
+ /* Enable TX before sending chars */
+ serial_start_tx(port);
port->driver->putc(port, c);
+ }
}
else
{
/* Simple synchronous transmitter. */
+ serial_start_tx(port);
port->driver->putc(port, c);
}
}
/* port is unavailable and might not come up until reenabled by
dom0, we can't really do proper sync */
break;
+ serial_start_tx(port);
port->driver->putc(
port, port->txbuf[mask_serial_txbuf_idx(port->txbufc++)]);
}
int (*getc)(struct serial_port *, char *);
/* Get IRQ number for this port's serial line: returns -1 if none. */
int (*irq)(struct serial_port *);
+ /* Unmask TX interrupt */
+ void (*start_tx)(struct serial_port *);
+ /* Mask TX interrupt */
+ void (*stop_tx)(struct serial_port *);
/* Get serial information */
const struct vuart_info *(*vuart_info)(struct serial_port *);
};