diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-26 09:11:09 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-26 09:11:09 -0400 |
commit | efb8d21b2c6db3497655cc6a033ae8a9883e4063 (patch) | |
tree | a14a0dbb9fec3a6db5e542ba7ed4a49681706420 /drivers/tty/serial/atmel_serial.c | |
parent | 3cb603284b3d256ae9ae9e65887cee8416bfef15 (diff) | |
parent | d208a3bf77f902283894f546b6b5383202cf7882 (diff) |
Merge branch 'tty-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
* 'tty-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (79 commits)
TTY: serial_core: Fix crash if DCD drop during suspend
tty/serial: atmel_serial: bootconsole removed from auto-enumerates
Revert "TTY: call tty_driver_lookup_tty unconditionally"
tty/serial: atmel_serial: add device tree support
tty/serial: atmel_serial: auto-enumerate ports
tty/serial: atmel_serial: whitespace and braces modifications
tty/serial: atmel_serial: change platform_data variable name
tty/serial: RS485 bindings for device tree
TTY: call tty_driver_lookup_tty unconditionally
TTY: pty, release tty in all ptmx_open fail paths
TTY: make tty_add_file non-failing
TTY: drop driver reference in tty_open fail path
8250_pci: Fix kernel panic when pch_uart is disabled
h8300: drivers/serial/Kconfig was moved
parport_pc: release IO region properly if unsupported ITE887x card is found
tty: Support compat_ioctl get/set termios_locked
hvc_console: display printk messages on console.
TTY: snyclinkmp: forever loop in tx_load_dma_buffer()
tty/n_gsm: avoid fifo overflow in gsm_dlci_data_output
tty/n_gsm: fix a bug in gsm_dlci_data_output (adaption = 2 case)
...
Fix up Conflicts in:
- drivers/tty/serial/8250_pci.c
Trivial conflict with removed duplicate device ID
- drivers/tty/serial/atmel_serial.c
Annoying silly conflict between "specify the port num via
platform_data" and other changes to atmel_console_init
Diffstat (limited to 'drivers/tty/serial/atmel_serial.c')
-rw-r--r-- | drivers/tty/serial/atmel_serial.c | 128 |
1 files changed, 111 insertions, 17 deletions
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index b922f5d2e61e..9988c0c305c2 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c | |||
@@ -33,6 +33,8 @@ | |||
33 | #include <linux/sysrq.h> | 33 | #include <linux/sysrq.h> |
34 | #include <linux/tty_flip.h> | 34 | #include <linux/tty_flip.h> |
35 | #include <linux/platform_device.h> | 35 | #include <linux/platform_device.h> |
36 | #include <linux/of.h> | ||
37 | #include <linux/of_device.h> | ||
36 | #include <linux/dma-mapping.h> | 38 | #include <linux/dma-mapping.h> |
37 | #include <linux/atmel_pdc.h> | 39 | #include <linux/atmel_pdc.h> |
38 | #include <linux/atmel_serial.h> | 40 | #include <linux/atmel_serial.h> |
@@ -157,11 +159,22 @@ struct atmel_uart_port { | |||
157 | }; | 159 | }; |
158 | 160 | ||
159 | static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART]; | 161 | static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART]; |
162 | static unsigned long atmel_ports_in_use; | ||
160 | 163 | ||
161 | #ifdef SUPPORT_SYSRQ | 164 | #ifdef SUPPORT_SYSRQ |
162 | static struct console atmel_console; | 165 | static struct console atmel_console; |
163 | #endif | 166 | #endif |
164 | 167 | ||
168 | #if defined(CONFIG_OF) | ||
169 | static const struct of_device_id atmel_serial_dt_ids[] = { | ||
170 | { .compatible = "atmel,at91rm9200-usart" }, | ||
171 | { .compatible = "atmel,at91sam9260-usart" }, | ||
172 | { /* sentinel */ } | ||
173 | }; | ||
174 | |||
175 | MODULE_DEVICE_TABLE(of, atmel_serial_dt_ids); | ||
176 | #endif | ||
177 | |||
165 | static inline struct atmel_uart_port * | 178 | static inline struct atmel_uart_port * |
166 | to_atmel_uart_port(struct uart_port *uart) | 179 | to_atmel_uart_port(struct uart_port *uart) |
167 | { | 180 | { |
@@ -339,7 +352,8 @@ static void atmel_stop_tx(struct uart_port *port) | |||
339 | /* Disable interrupts */ | 352 | /* Disable interrupts */ |
340 | UART_PUT_IDR(port, atmel_port->tx_done_mask); | 353 | UART_PUT_IDR(port, atmel_port->tx_done_mask); |
341 | 354 | ||
342 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) | 355 | if ((atmel_port->rs485.flags & SER_RS485_ENABLED) && |
356 | !(atmel_port->rs485.flags & SER_RS485_RX_DURING_TX)) | ||
343 | atmel_start_rx(port); | 357 | atmel_start_rx(port); |
344 | } | 358 | } |
345 | 359 | ||
@@ -356,7 +370,8 @@ static void atmel_start_tx(struct uart_port *port) | |||
356 | really need this.*/ | 370 | really need this.*/ |
357 | return; | 371 | return; |
358 | 372 | ||
359 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) | 373 | if ((atmel_port->rs485.flags & SER_RS485_ENABLED) && |
374 | !(atmel_port->rs485.flags & SER_RS485_RX_DURING_TX)) | ||
360 | atmel_stop_rx(port); | 375 | atmel_stop_rx(port); |
361 | 376 | ||
362 | /* re-enable PDC transmit */ | 377 | /* re-enable PDC transmit */ |
@@ -680,7 +695,8 @@ static void atmel_tx_dma(struct uart_port *port) | |||
680 | /* Enable interrupts */ | 695 | /* Enable interrupts */ |
681 | UART_PUT_IER(port, atmel_port->tx_done_mask); | 696 | UART_PUT_IER(port, atmel_port->tx_done_mask); |
682 | } else { | 697 | } else { |
683 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) { | 698 | if ((atmel_port->rs485.flags & SER_RS485_ENABLED) && |
699 | !(atmel_port->rs485.flags & SER_RS485_RX_DURING_TX)) { | ||
684 | /* DMA done, stop TX, start RX for RS485 */ | 700 | /* DMA done, stop TX, start RX for RS485 */ |
685 | atmel_start_rx(port); | 701 | atmel_start_rx(port); |
686 | } | 702 | } |
@@ -1407,6 +1423,48 @@ static struct uart_ops atmel_pops = { | |||
1407 | #endif | 1423 | #endif |
1408 | }; | 1424 | }; |
1409 | 1425 | ||
1426 | static void __devinit atmel_of_init_port(struct atmel_uart_port *atmel_port, | ||
1427 | struct device_node *np) | ||
1428 | { | ||
1429 | u32 rs485_delay[2]; | ||
1430 | |||
1431 | /* DMA/PDC usage specification */ | ||
1432 | if (of_get_property(np, "atmel,use-dma-rx", NULL)) | ||
1433 | atmel_port->use_dma_rx = 1; | ||
1434 | else | ||
1435 | atmel_port->use_dma_rx = 0; | ||
1436 | if (of_get_property(np, "atmel,use-dma-tx", NULL)) | ||
1437 | atmel_port->use_dma_tx = 1; | ||
1438 | else | ||
1439 | atmel_port->use_dma_tx = 0; | ||
1440 | |||
1441 | /* rs485 properties */ | ||
1442 | if (of_property_read_u32_array(np, "rs485-rts-delay", | ||
1443 | rs485_delay, 2) == 0) { | ||
1444 | struct serial_rs485 *rs485conf = &atmel_port->rs485; | ||
1445 | |||
1446 | rs485conf->delay_rts_before_send = rs485_delay[0]; | ||
1447 | rs485conf->delay_rts_after_send = rs485_delay[1]; | ||
1448 | rs485conf->flags = 0; | ||
1449 | |||
1450 | if (rs485conf->delay_rts_before_send == 0 && | ||
1451 | rs485conf->delay_rts_after_send == 0) { | ||
1452 | rs485conf->flags |= SER_RS485_RTS_ON_SEND; | ||
1453 | } else { | ||
1454 | if (rs485conf->delay_rts_before_send) | ||
1455 | rs485conf->flags |= SER_RS485_RTS_BEFORE_SEND; | ||
1456 | if (rs485conf->delay_rts_after_send) | ||
1457 | rs485conf->flags |= SER_RS485_RTS_AFTER_SEND; | ||
1458 | } | ||
1459 | |||
1460 | if (of_get_property(np, "rs485-rx-during-tx", NULL)) | ||
1461 | rs485conf->flags |= SER_RS485_RX_DURING_TX; | ||
1462 | |||
1463 | if (of_get_property(np, "linux,rs485-enabled-at-boot-time", NULL)) | ||
1464 | rs485conf->flags |= SER_RS485_ENABLED; | ||
1465 | } | ||
1466 | } | ||
1467 | |||
1410 | /* | 1468 | /* |
1411 | * Configure the port from the platform device resource info. | 1469 | * Configure the port from the platform device resource info. |
1412 | */ | 1470 | */ |
@@ -1414,13 +1472,20 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, | |||
1414 | struct platform_device *pdev) | 1472 | struct platform_device *pdev) |
1415 | { | 1473 | { |
1416 | struct uart_port *port = &atmel_port->uart; | 1474 | struct uart_port *port = &atmel_port->uart; |
1417 | struct atmel_uart_data *data = pdev->dev.platform_data; | 1475 | struct atmel_uart_data *pdata = pdev->dev.platform_data; |
1476 | |||
1477 | if (pdev->dev.of_node) { | ||
1478 | atmel_of_init_port(atmel_port, pdev->dev.of_node); | ||
1479 | } else { | ||
1480 | atmel_port->use_dma_rx = pdata->use_dma_rx; | ||
1481 | atmel_port->use_dma_tx = pdata->use_dma_tx; | ||
1482 | atmel_port->rs485 = pdata->rs485; | ||
1483 | } | ||
1418 | 1484 | ||
1419 | port->iotype = UPIO_MEM; | 1485 | port->iotype = UPIO_MEM; |
1420 | port->flags = UPF_BOOT_AUTOCONF; | 1486 | port->flags = UPF_BOOT_AUTOCONF; |
1421 | port->ops = &atmel_pops; | 1487 | port->ops = &atmel_pops; |
1422 | port->fifosize = 1; | 1488 | port->fifosize = 1; |
1423 | port->line = data->num; | ||
1424 | port->dev = &pdev->dev; | 1489 | port->dev = &pdev->dev; |
1425 | port->mapbase = pdev->resource[0].start; | 1490 | port->mapbase = pdev->resource[0].start; |
1426 | port->irq = pdev->resource[1].start; | 1491 | port->irq = pdev->resource[1].start; |
@@ -1430,10 +1495,10 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, | |||
1430 | 1495 | ||
1431 | memset(&atmel_port->rx_ring, 0, sizeof(atmel_port->rx_ring)); | 1496 | memset(&atmel_port->rx_ring, 0, sizeof(atmel_port->rx_ring)); |
1432 | 1497 | ||
1433 | if (data->regs) | 1498 | if (pdata && pdata->regs) { |
1434 | /* Already mapped by setup code */ | 1499 | /* Already mapped by setup code */ |
1435 | port->membase = data->regs; | 1500 | port->membase = pdata->regs; |
1436 | else { | 1501 | } else { |
1437 | port->flags |= UPF_IOREMAP; | 1502 | port->flags |= UPF_IOREMAP; |
1438 | port->membase = NULL; | 1503 | port->membase = NULL; |
1439 | } | 1504 | } |
@@ -1447,9 +1512,6 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, | |||
1447 | /* only enable clock when USART is in use */ | 1512 | /* only enable clock when USART is in use */ |
1448 | } | 1513 | } |
1449 | 1514 | ||
1450 | atmel_port->use_dma_rx = data->use_dma_rx; | ||
1451 | atmel_port->use_dma_tx = data->use_dma_tx; | ||
1452 | atmel_port->rs485 = data->rs485; | ||
1453 | /* Use TXEMPTY for interrupt when rs485 else TXRDY or ENDTX|TXBUFE */ | 1515 | /* Use TXEMPTY for interrupt when rs485 else TXRDY or ENDTX|TXBUFE */ |
1454 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) | 1516 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) |
1455 | atmel_port->tx_done_mask = ATMEL_US_TXEMPTY; | 1517 | atmel_port->tx_done_mask = ATMEL_US_TXEMPTY; |
@@ -1611,10 +1673,14 @@ static int __init atmel_console_init(void) | |||
1611 | if (atmel_default_console_device) { | 1673 | if (atmel_default_console_device) { |
1612 | struct atmel_uart_data *pdata = | 1674 | struct atmel_uart_data *pdata = |
1613 | atmel_default_console_device->dev.platform_data; | 1675 | atmel_default_console_device->dev.platform_data; |
1676 | int id = pdata->num; | ||
1677 | struct atmel_uart_port *port = &atmel_ports[id]; | ||
1678 | |||
1679 | port->backup_imr = 0; | ||
1680 | port->uart.line = id; | ||
1614 | 1681 | ||
1615 | add_preferred_console(ATMEL_DEVICENAME, pdata->num, NULL); | 1682 | add_preferred_console(ATMEL_DEVICENAME, id, NULL); |
1616 | atmel_init_port(&atmel_ports[pdata->num], | 1683 | atmel_init_port(port, atmel_default_console_device); |
1617 | atmel_default_console_device); | ||
1618 | register_console(&atmel_console); | 1684 | register_console(&atmel_console); |
1619 | } | 1685 | } |
1620 | 1686 | ||
@@ -1711,14 +1777,39 @@ static int atmel_serial_resume(struct platform_device *pdev) | |||
1711 | static int __devinit atmel_serial_probe(struct platform_device *pdev) | 1777 | static int __devinit atmel_serial_probe(struct platform_device *pdev) |
1712 | { | 1778 | { |
1713 | struct atmel_uart_port *port; | 1779 | struct atmel_uart_port *port; |
1780 | struct device_node *np = pdev->dev.of_node; | ||
1714 | struct atmel_uart_data *pdata = pdev->dev.platform_data; | 1781 | struct atmel_uart_data *pdata = pdev->dev.platform_data; |
1715 | void *data; | 1782 | void *data; |
1716 | int ret; | 1783 | int ret = -ENODEV; |
1717 | 1784 | ||
1718 | BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1)); | 1785 | BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1)); |
1719 | 1786 | ||
1720 | port = &atmel_ports[pdata->num]; | 1787 | if (np) |
1788 | ret = of_alias_get_id(np, "serial"); | ||
1789 | else | ||
1790 | if (pdata) | ||
1791 | ret = pdata->num; | ||
1792 | |||
1793 | if (ret < 0) | ||
1794 | /* port id not found in platform data nor device-tree aliases: | ||
1795 | * auto-enumerate it */ | ||
1796 | ret = find_first_zero_bit(&atmel_ports_in_use, | ||
1797 | sizeof(atmel_ports_in_use)); | ||
1798 | |||
1799 | if (ret > ATMEL_MAX_UART) { | ||
1800 | ret = -ENODEV; | ||
1801 | goto err; | ||
1802 | } | ||
1803 | |||
1804 | if (test_and_set_bit(ret, &atmel_ports_in_use)) { | ||
1805 | /* port already in use */ | ||
1806 | ret = -EBUSY; | ||
1807 | goto err; | ||
1808 | } | ||
1809 | |||
1810 | port = &atmel_ports[ret]; | ||
1721 | port->backup_imr = 0; | 1811 | port->backup_imr = 0; |
1812 | port->uart.line = ret; | ||
1722 | 1813 | ||
1723 | atmel_init_port(port, pdev); | 1814 | atmel_init_port(port, pdev); |
1724 | 1815 | ||
@@ -1764,7 +1855,7 @@ err_alloc_ring: | |||
1764 | clk_put(port->clk); | 1855 | clk_put(port->clk); |
1765 | port->clk = NULL; | 1856 | port->clk = NULL; |
1766 | } | 1857 | } |
1767 | 1858 | err: | |
1768 | return ret; | 1859 | return ret; |
1769 | } | 1860 | } |
1770 | 1861 | ||
@@ -1784,6 +1875,8 @@ static int __devexit atmel_serial_remove(struct platform_device *pdev) | |||
1784 | 1875 | ||
1785 | /* "port" is allocated statically, so we shouldn't free it */ | 1876 | /* "port" is allocated statically, so we shouldn't free it */ |
1786 | 1877 | ||
1878 | clear_bit(port->line, &atmel_ports_in_use); | ||
1879 | |||
1787 | clk_put(atmel_port->clk); | 1880 | clk_put(atmel_port->clk); |
1788 | 1881 | ||
1789 | return ret; | 1882 | return ret; |
@@ -1797,6 +1890,7 @@ static struct platform_driver atmel_serial_driver = { | |||
1797 | .driver = { | 1890 | .driver = { |
1798 | .name = "atmel_usart", | 1891 | .name = "atmel_usart", |
1799 | .owner = THIS_MODULE, | 1892 | .owner = THIS_MODULE, |
1893 | .of_match_table = of_match_ptr(atmel_serial_dt_ids), | ||
1800 | }, | 1894 | }, |
1801 | }; | 1895 | }; |
1802 | 1896 | ||