From 83cac9f3b45ba8e99c5305be42c67f1c83adf0aa Mon Sep 17 00:00:00 2001 From: Bernhard Roth Date: Wed, 24 Aug 2011 09:48:23 +0200 Subject: atmel_serial: RS485: receiving enabled when sending data By default the atmel_serial driver in RS485 mode disables receiving data until all data in the send buffer has been sent. This flag allows to receive data even whilst sending data. Signed-off-by: Bernhard Roth Signed-off-by: Claudio Scordino Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/tty/serial/atmel_serial.c') diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index af9b781..c7232a9 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -339,7 +339,8 @@ static void atmel_stop_tx(struct uart_port *port) /* Disable interrupts */ UART_PUT_IDR(port, atmel_port->tx_done_mask); - if (atmel_port->rs485.flags & SER_RS485_ENABLED) + if ((atmel_port->rs485.flags & SER_RS485_ENABLED) && + !(atmel_port->rs485.flags & SER_RS485_RX_DURING_TX)) atmel_start_rx(port); } @@ -356,7 +357,8 @@ static void atmel_start_tx(struct uart_port *port) really need this.*/ return; - if (atmel_port->rs485.flags & SER_RS485_ENABLED) + if ((atmel_port->rs485.flags & SER_RS485_ENABLED) && + !(atmel_port->rs485.flags & SER_RS485_RX_DURING_TX)) atmel_stop_rx(port); /* re-enable PDC transmit */ @@ -680,7 +682,8 @@ static void atmel_tx_dma(struct uart_port *port) /* Enable interrupts */ UART_PUT_IER(port, atmel_port->tx_done_mask); } else { - if (atmel_port->rs485.flags & SER_RS485_ENABLED) { + if ((atmel_port->rs485.flags & SER_RS485_ENABLED) && + !(atmel_port->rs485.flags & SER_RS485_RX_DURING_TX)) { /* DMA done, stop TX, start RX for RS485 */ atmel_start_rx(port); } -- cgit v1.1 From 1acfc7eca664783ee20d951683ed229eaa64f573 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Wed, 12 Oct 2011 18:06:57 +0200 Subject: tty/serial: atmel_serial: change platform_data variable name Easier to follow if platform_data name is pdata. Signed-off-by: Nicolas Ferre Acked-by: Grant Likely Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/tty/serial/atmel_serial.c') diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index c7232a9..a507daa 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -1417,13 +1417,13 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, struct platform_device *pdev) { struct uart_port *port = &atmel_port->uart; - struct atmel_uart_data *data = pdev->dev.platform_data; + struct atmel_uart_data *pdata = pdev->dev.platform_data; port->iotype = UPIO_MEM; port->flags = UPF_BOOT_AUTOCONF; port->ops = &atmel_pops; port->fifosize = 1; - port->line = data->num; + port->line = pdata->num; port->dev = &pdev->dev; port->mapbase = pdev->resource[0].start; port->irq = pdev->resource[1].start; @@ -1433,9 +1433,9 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, memset(&atmel_port->rx_ring, 0, sizeof(atmel_port->rx_ring)); - if (data->regs) + if (pdata->regs) /* Already mapped by setup code */ - port->membase = data->regs; + port->membase = pdata->regs; else { port->flags |= UPF_IOREMAP; port->membase = NULL; @@ -1450,9 +1450,9 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, /* only enable clock when USART is in use */ } - atmel_port->use_dma_rx = data->use_dma_rx; - atmel_port->use_dma_tx = data->use_dma_tx; - atmel_port->rs485 = data->rs485; + atmel_port->use_dma_rx = pdata->use_dma_rx; + atmel_port->use_dma_tx = pdata->use_dma_tx; + atmel_port->rs485 = pdata->rs485; /* Use TXEMPTY for interrupt when rs485 else TXRDY or ENDTX|TXBUFE */ if (atmel_port->rs485.flags & SER_RS485_ENABLED) atmel_port->tx_done_mask = ATMEL_US_TXEMPTY; -- cgit v1.1 From 588edbf3b8948d94a52da5d6b45c9bb7307d1f01 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Wed, 12 Oct 2011 18:06:58 +0200 Subject: tty/serial: atmel_serial: whitespace and braces modifications Signed-off-by: Nicolas Ferre Acked-by: Grant Likely Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/tty/serial/atmel_serial.c') diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index a507daa..bb72354 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -1433,10 +1433,10 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, memset(&atmel_port->rx_ring, 0, sizeof(atmel_port->rx_ring)); - if (pdata->regs) + if (pdata->regs) { /* Already mapped by setup code */ port->membase = pdata->regs; - else { + } else { port->flags |= UPF_IOREMAP; port->membase = NULL; } @@ -1450,9 +1450,10 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, /* only enable clock when USART is in use */ } - atmel_port->use_dma_rx = pdata->use_dma_rx; - atmel_port->use_dma_tx = pdata->use_dma_tx; + atmel_port->use_dma_rx = pdata->use_dma_rx; + atmel_port->use_dma_tx = pdata->use_dma_tx; atmel_port->rs485 = pdata->rs485; + /* Use TXEMPTY for interrupt when rs485 else TXRDY or ENDTX|TXBUFE */ if (atmel_port->rs485.flags & SER_RS485_ENABLED) atmel_port->tx_done_mask = ATMEL_US_TXEMPTY; -- cgit v1.1 From 4cbf9f4864bd4fb2e64d555aacb93c24478e4e8d Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Wed, 12 Oct 2011 18:06:59 +0200 Subject: tty/serial: atmel_serial: auto-enumerate ports If no platform data provided to enumerate ports, use a bit field to choose port number and check if port is already initialized. Use this mechanism for both console and plain serial ports. Signed-off-by: Nicolas Ferre Acked-by: Grant Likely Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 44 ++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 8 deletions(-) (limited to 'drivers/tty/serial/atmel_serial.c') diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index bb72354..1074329 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -157,6 +157,7 @@ struct atmel_uart_port { }; static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART]; +static unsigned long atmel_ports_in_use; #ifdef SUPPORT_SYSRQ static struct console atmel_console; @@ -1423,7 +1424,6 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, port->flags = UPF_BOOT_AUTOCONF; port->ops = &atmel_pops; port->fifosize = 1; - port->line = pdata->num; port->dev = &pdev->dev; port->mapbase = pdev->resource[0].start; port->irq = pdev->resource[1].start; @@ -1613,10 +1613,15 @@ static struct console atmel_console = { static int __init atmel_console_init(void) { if (atmel_default_console_device) { - add_preferred_console(ATMEL_DEVICENAME, - atmel_default_console_device->id, NULL); - atmel_init_port(&atmel_ports[atmel_default_console_device->id], - atmel_default_console_device); + int id = atmel_default_console_device->id; + struct atmel_uart_port *port = &atmel_ports[id]; + + set_bit(id, &atmel_ports_in_use); + port->backup_imr = 0; + port->uart.line = id; + + add_preferred_console(ATMEL_DEVICENAME, id, NULL); + atmel_init_port(port, atmel_default_console_device); register_console(&atmel_console); } @@ -1715,12 +1720,33 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev) struct atmel_uart_port *port; struct atmel_uart_data *pdata = pdev->dev.platform_data; void *data; - int ret; + int ret = -ENODEV; BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1)); - port = &atmel_ports[pdata->num]; + if (pdata) + ret = pdata->num; + + if (ret < 0) + /* port id not found in platform data: + * auto-enumerate it */ + ret = find_first_zero_bit(&atmel_ports_in_use, + sizeof(atmel_ports_in_use)); + + if (ret > ATMEL_MAX_UART) { + ret = -ENODEV; + goto err; + } + + if (test_and_set_bit(ret, &atmel_ports_in_use)) { + /* port already in use */ + ret = -EBUSY; + goto err; + } + + port = &atmel_ports[ret]; port->backup_imr = 0; + port->uart.line = ret; atmel_init_port(port, pdev); @@ -1766,7 +1792,7 @@ err_alloc_ring: clk_put(port->clk); port->clk = NULL; } - +err: return ret; } @@ -1786,6 +1812,8 @@ static int __devexit atmel_serial_remove(struct platform_device *pdev) /* "port" is allocated statically, so we shouldn't free it */ + clear_bit(port->line, &atmel_ports_in_use); + clk_put(atmel_port->clk); return ret; -- cgit v1.1 From 5fbe46b67680c27aeb56228dab8cfe25f8f8f83d Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Wed, 12 Oct 2011 18:07:00 +0200 Subject: tty/serial: atmel_serial: add device tree support Will use aliases to enumerate ports, if available. Signed-off-by: Nicolas Ferre Acked-by: Grant Likely Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 79 +++++++++++++++++++++++++++++++++++---- 1 file changed, 71 insertions(+), 8 deletions(-) (limited to 'drivers/tty/serial/atmel_serial.c') diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 1074329..fc4081e 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -33,6 +33,8 @@ #include #include #include +#include +#include #include #include #include @@ -163,6 +165,16 @@ static unsigned long atmel_ports_in_use; static struct console atmel_console; #endif +#if defined(CONFIG_OF) +static const struct of_device_id atmel_serial_dt_ids[] = { + { .compatible = "atmel,at91rm9200-usart" }, + { .compatible = "atmel,at91sam9260-usart" }, + { /* sentinel */ } +}; + +MODULE_DEVICE_TABLE(of, atmel_serial_dt_ids); +#endif + static inline struct atmel_uart_port * to_atmel_uart_port(struct uart_port *uart) { @@ -1411,6 +1423,48 @@ static struct uart_ops atmel_pops = { #endif }; +static void __devinit atmel_of_init_port(struct atmel_uart_port *atmel_port, + struct device_node *np) +{ + u32 rs485_delay[2]; + + /* DMA/PDC usage specification */ + if (of_get_property(np, "atmel,use-dma-rx", NULL)) + atmel_port->use_dma_rx = 1; + else + atmel_port->use_dma_rx = 0; + if (of_get_property(np, "atmel,use-dma-tx", NULL)) + atmel_port->use_dma_tx = 1; + else + atmel_port->use_dma_tx = 0; + + /* rs485 properties */ + if (of_property_read_u32_array(np, "rs485-rts-delay", + rs485_delay, 2) == 0) { + struct serial_rs485 *rs485conf = &atmel_port->rs485; + + rs485conf->delay_rts_before_send = rs485_delay[0]; + rs485conf->delay_rts_after_send = rs485_delay[1]; + rs485conf->flags = 0; + + if (rs485conf->delay_rts_before_send == 0 && + rs485conf->delay_rts_after_send == 0) { + rs485conf->flags |= SER_RS485_RTS_ON_SEND; + } else { + if (rs485conf->delay_rts_before_send) + rs485conf->flags |= SER_RS485_RTS_BEFORE_SEND; + if (rs485conf->delay_rts_after_send) + rs485conf->flags |= SER_RS485_RTS_AFTER_SEND; + } + + if (of_get_property(np, "rs485-rx-during-tx", NULL)) + rs485conf->flags |= SER_RS485_RX_DURING_TX; + + if (of_get_property(np, "linux,rs485-enabled-at-boot-time", NULL)) + rs485conf->flags |= SER_RS485_ENABLED; + } +} + /* * Configure the port from the platform device resource info. */ @@ -1420,6 +1474,14 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, struct uart_port *port = &atmel_port->uart; struct atmel_uart_data *pdata = pdev->dev.platform_data; + if (pdev->dev.of_node) { + atmel_of_init_port(atmel_port, pdev->dev.of_node); + } else { + atmel_port->use_dma_rx = pdata->use_dma_rx; + atmel_port->use_dma_tx = pdata->use_dma_tx; + atmel_port->rs485 = pdata->rs485; + } + port->iotype = UPIO_MEM; port->flags = UPF_BOOT_AUTOCONF; port->ops = &atmel_pops; @@ -1433,7 +1495,7 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, memset(&atmel_port->rx_ring, 0, sizeof(atmel_port->rx_ring)); - if (pdata->regs) { + if (pdata && pdata->regs) { /* Already mapped by setup code */ port->membase = pdata->regs; } else { @@ -1450,10 +1512,6 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, /* only enable clock when USART is in use */ } - atmel_port->use_dma_rx = pdata->use_dma_rx; - atmel_port->use_dma_tx = pdata->use_dma_tx; - atmel_port->rs485 = pdata->rs485; - /* Use TXEMPTY for interrupt when rs485 else TXRDY or ENDTX|TXBUFE */ if (atmel_port->rs485.flags & SER_RS485_ENABLED) atmel_port->tx_done_mask = ATMEL_US_TXEMPTY; @@ -1718,17 +1776,21 @@ static int atmel_serial_resume(struct platform_device *pdev) static int __devinit atmel_serial_probe(struct platform_device *pdev) { struct atmel_uart_port *port; + struct device_node *np = pdev->dev.of_node; struct atmel_uart_data *pdata = pdev->dev.platform_data; void *data; int ret = -ENODEV; BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1)); - if (pdata) - ret = pdata->num; + if (np) + ret = of_alias_get_id(np, "serial"); + else + if (pdata) + ret = pdata->num; if (ret < 0) - /* port id not found in platform data: + /* port id not found in platform data nor device-tree aliases: * auto-enumerate it */ ret = find_first_zero_bit(&atmel_ports_in_use, sizeof(atmel_ports_in_use)); @@ -1827,6 +1889,7 @@ static struct platform_driver atmel_serial_driver = { .driver = { .name = "atmel_usart", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(atmel_serial_dt_ids), }, }; -- cgit v1.1 From 32cffe537c7d426cfe33647fed403d409ea3f686 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Wed, 19 Oct 2011 11:36:20 +0200 Subject: tty/serial: atmel_serial: bootconsole removed from auto-enumerates Auto-enumerate mechanism conflicts with bootconsoles: remove the usage counter for this type of consoles. Signed-off-by: Nicolas Ferre Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/atmel_serial.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/tty/serial/atmel_serial.c') diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index fc4081e..358bbb2 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -1674,7 +1674,6 @@ static int __init atmel_console_init(void) int id = atmel_default_console_device->id; struct atmel_uart_port *port = &atmel_ports[id]; - set_bit(id, &atmel_ports_in_use); port->backup_imr = 0; port->uart.line = id; -- cgit v1.1