*/
static void atmel_tx_chars(struct uart_port *port)
{
- struct circ_buf *xmit = &port->info->xmit;
+ struct circ_buf *xmit = &port->state->xmit;
if (port->x_char && UART_GET_CSR(port) & ATMEL_US_TXRDY) {
UART_PUT_CHAR(port, port->x_char);
static void atmel_tx_dma(struct uart_port *port)
{
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
- struct circ_buf *xmit = &port->info->xmit;
+ struct circ_buf *xmit = &port->state->xmit;
struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx;
int count;
/* disable PDC transmit */
UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
- if (!uart_circ_empty(xmit)) {
+ if (!uart_circ_empty(xmit) && !uart_tx_stopped(port)) {
dma_sync_single_for_device(port->dev,
pdc->dma_addr,
pdc->dma_size,
* uart_start(), which takes the lock.
*/
spin_unlock(&port->lock);
- tty_flip_buffer_push(port->info->port.tty);
+ tty_flip_buffer_push(port->state->port.tty);
spin_lock(&port->lock);
}
static void atmel_rx_from_dma(struct uart_port *port)
{
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
- struct tty_struct *tty = port->info->port.tty;
+ struct tty_struct *tty = port->state->port.tty;
struct atmel_dma_buffer *pdc;
int rx_idx = atmel_port->pdc_rx_idx;
unsigned int head;
if (status_change & ATMEL_US_CTS)
uart_handle_cts_change(port, !(status & ATMEL_US_CTS));
- wake_up_interruptible(&port->info->delta_msr_wait);
+ wake_up_interruptible(&port->state->port.delta_msr_wait);
atmel_port->irq_status_prev = status;
}
static int atmel_startup(struct uart_port *port)
{
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
- struct tty_struct *tty = port->info->port.tty;
+ struct tty_struct *tty = port->state->port.tty;
int retval;
/*
}
if (atmel_use_dma_tx(port)) {
struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx;
- struct circ_buf *xmit = &port->info->xmit;
+ struct circ_buf *xmit = &port->state->xmit;
pdc->buf = xmit->buf;
pdc->dma_addr = dma_map_single(port->dev,
}
}
+ /* Save current CSR for comparison in atmel_tasklet_func() */
+ atmel_port->irq_status_prev = UART_GET_CSR(port);
+ atmel_port->irq_status = atmel_port->irq_status_prev;
+
/*
* Finally, enable the serial port
*/
/* Get current mode register */
mode = UART_GET_MR(port) & ~(ATMEL_US_USCLKS | ATMEL_US_CHRL
- | ATMEL_US_NBSTOP | ATMEL_US_PAR);
+ | ATMEL_US_NBSTOP | ATMEL_US_PAR
+ | ATMEL_US_USMODE);
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
quot = uart_get_divisor(port, baud);
} else
mode |= ATMEL_US_PAR_NONE;
+ /* hardware handshake (RTS/CTS) */
+ if (termios->c_cflag & CRTSCTS)
+ mode |= ATMEL_US_USMODE_HWHS;
+ else
+ mode |= ATMEL_US_USMODE_NORMAL;
+
spin_lock_irqsave(&port->lock, flags);
port->read_status_mask = ATMEL_US_OVRE;
/* update the per-port timeout */
uart_update_timeout(port, termios->c_cflag, baud);
- /* save/disable interrupts and drain transmitter */
+ /*
+ * save/disable interrupts. The tty layer will ensure that the
+ * transmitter is empty if requested by the caller, so there's
+ * no need to wait for it here.
+ */
imr = UART_GET_IMR(port);
UART_PUT_IDR(port, -1);
- while (!(UART_GET_CSR(port) & ATMEL_US_TXEMPTY))
- cpu_relax();
/* disable receiver and transmitter */
UART_PUT_CR(port, ATMEL_US_TXDIS | ATMEL_US_RXDIS);
return ret;
}
+#ifdef CONFIG_CONSOLE_POLL
+static int atmel_poll_get_char(struct uart_port *port)
+{
+ while (!(UART_GET_CSR(port) & ATMEL_US_RXRDY))
+ cpu_relax();
+
+ return UART_GET_CHAR(port);
+}
+
+static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
+{
+ while (!(UART_GET_CSR(port) & ATMEL_US_TXRDY))
+ cpu_relax();
+
+ UART_PUT_CHAR(port, ch);
+}
+#endif
+
static struct uart_ops atmel_pops = {
.tx_empty = atmel_tx_empty,
.set_mctrl = atmel_set_mctrl,
.config_port = atmel_config_port,
.verify_port = atmel_verify_port,
.pm = atmel_serial_pm,
+#ifdef CONFIG_CONSOLE_POLL
+ .poll_get_char = atmel_poll_get_char,
+ .poll_put_char = atmel_poll_put_char,
+#endif
};
/*
atmel_port->clk = clk_get(&pdev->dev, "usart");
clk_enable(atmel_port->clk);
port->uartclk = clk_get_rate(atmel_port->clk);
+ clk_disable(atmel_port->clk);
+ /* only enable clock when USART is in use */
}
atmel_port->use_dma_rx = data->use_dma_rx;
return -ENODEV;
}
+ clk_enable(atmel_ports[co->index].clk);
+
UART_PUT_IDR(port, -1);
UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
.data = &atmel_uart,
};
-#define ATMEL_CONSOLE_DEVICE &atmel_console
+#define ATMEL_CONSOLE_DEVICE (&atmel_console)
/*
* Early console initialization (before VM subsystem initialized).
void *data;
int ret;
- BUILD_BUG_ON(!is_power_of_2(ATMEL_SERIAL_RINGSIZE));
+ BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1));
port = &atmel_ports[pdev->id];
port->backup_imr = 0;
if (ret)
goto err_add_port;
+#ifdef CONFIG_SERIAL_ATMEL_CONSOLE
+ if (atmel_is_console_port(&port->uart)
+ && ATMEL_CONSOLE_DEVICE->flags & CON_ENABLED) {
+ /*
+ * The serial core enabled the clock for us, so undo
+ * the clk_enable() in atmel_console_setup()
+ */
+ clk_disable(port->clk);
+ }
+#endif
+
device_init_wakeup(&pdev->dev, 1);
platform_set_drvdata(pdev, port);
port->rx_ring.buf = NULL;
err_alloc_ring:
if (!atmel_is_console_port(&port->uart)) {
- clk_disable(port->clk);
clk_put(port->clk);
port->clk = NULL;
}
/* "port" is allocated statically, so we shouldn't free it */
- clk_disable(atmel_port->clk);
clk_put(atmel_port->clk);
return ret;