diff options
Diffstat (limited to 'drivers/tty/serial/amba-pl011.c')
-rw-r--r-- | drivers/tty/serial/amba-pl011.c | 89 |
1 files changed, 57 insertions, 32 deletions
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index d3553b5d3fca..cede93876649 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c | |||
@@ -52,6 +52,8 @@ | |||
52 | #include <linux/scatterlist.h> | 52 | #include <linux/scatterlist.h> |
53 | #include <linux/delay.h> | 53 | #include <linux/delay.h> |
54 | #include <linux/types.h> | 54 | #include <linux/types.h> |
55 | #include <linux/of.h> | ||
56 | #include <linux/of_device.h> | ||
55 | #include <linux/pinctrl/consumer.h> | 57 | #include <linux/pinctrl/consumer.h> |
56 | #include <linux/sizes.h> | 58 | #include <linux/sizes.h> |
57 | 59 | ||
@@ -75,7 +77,6 @@ struct vendor_data { | |||
75 | unsigned int lcrh_tx; | 77 | unsigned int lcrh_tx; |
76 | unsigned int lcrh_rx; | 78 | unsigned int lcrh_rx; |
77 | bool oversampling; | 79 | bool oversampling; |
78 | bool interrupt_may_hang; /* vendor-specific */ | ||
79 | bool dma_threshold; | 80 | bool dma_threshold; |
80 | bool cts_event_workaround; | 81 | bool cts_event_workaround; |
81 | }; | 82 | }; |
@@ -96,7 +97,6 @@ static struct vendor_data vendor_st = { | |||
96 | .lcrh_tx = ST_UART011_LCRH_TX, | 97 | .lcrh_tx = ST_UART011_LCRH_TX, |
97 | .lcrh_rx = ST_UART011_LCRH_RX, | 98 | .lcrh_rx = ST_UART011_LCRH_RX, |
98 | .oversampling = true, | 99 | .oversampling = true, |
99 | .interrupt_may_hang = true, | ||
100 | .dma_threshold = true, | 100 | .dma_threshold = true, |
101 | .cts_event_workaround = true, | 101 | .cts_event_workaround = true, |
102 | }; | 102 | }; |
@@ -147,7 +147,6 @@ struct uart_amba_port { | |||
147 | unsigned int old_cr; /* state during shutdown */ | 147 | unsigned int old_cr; /* state during shutdown */ |
148 | bool autorts; | 148 | bool autorts; |
149 | char type[12]; | 149 | char type[12]; |
150 | bool interrupt_may_hang; /* vendor-specific */ | ||
151 | #ifdef CONFIG_DMA_ENGINE | 150 | #ifdef CONFIG_DMA_ENGINE |
152 | /* DMA stuff */ | 151 | /* DMA stuff */ |
153 | bool using_tx_dma; | 152 | bool using_tx_dma; |
@@ -1215,14 +1214,14 @@ static irqreturn_t pl011_int(int irq, void *dev_id) | |||
1215 | return IRQ_RETVAL(handled); | 1214 | return IRQ_RETVAL(handled); |
1216 | } | 1215 | } |
1217 | 1216 | ||
1218 | static unsigned int pl01x_tx_empty(struct uart_port *port) | 1217 | static unsigned int pl011_tx_empty(struct uart_port *port) |
1219 | { | 1218 | { |
1220 | struct uart_amba_port *uap = (struct uart_amba_port *)port; | 1219 | struct uart_amba_port *uap = (struct uart_amba_port *)port; |
1221 | unsigned int status = readw(uap->port.membase + UART01x_FR); | 1220 | unsigned int status = readw(uap->port.membase + UART01x_FR); |
1222 | return status & (UART01x_FR_BUSY|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT; | 1221 | return status & (UART01x_FR_BUSY|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT; |
1223 | } | 1222 | } |
1224 | 1223 | ||
1225 | static unsigned int pl01x_get_mctrl(struct uart_port *port) | 1224 | static unsigned int pl011_get_mctrl(struct uart_port *port) |
1226 | { | 1225 | { |
1227 | struct uart_amba_port *uap = (struct uart_amba_port *)port; | 1226 | struct uart_amba_port *uap = (struct uart_amba_port *)port; |
1228 | unsigned int result = 0; | 1227 | unsigned int result = 0; |
@@ -1285,7 +1284,7 @@ static void pl011_break_ctl(struct uart_port *port, int break_state) | |||
1285 | } | 1284 | } |
1286 | 1285 | ||
1287 | #ifdef CONFIG_CONSOLE_POLL | 1286 | #ifdef CONFIG_CONSOLE_POLL |
1288 | static int pl010_get_poll_char(struct uart_port *port) | 1287 | static int pl011_get_poll_char(struct uart_port *port) |
1289 | { | 1288 | { |
1290 | struct uart_amba_port *uap = (struct uart_amba_port *)port; | 1289 | struct uart_amba_port *uap = (struct uart_amba_port *)port; |
1291 | unsigned int status; | 1290 | unsigned int status; |
@@ -1297,7 +1296,7 @@ static int pl010_get_poll_char(struct uart_port *port) | |||
1297 | return readw(uap->port.membase + UART01x_DR); | 1296 | return readw(uap->port.membase + UART01x_DR); |
1298 | } | 1297 | } |
1299 | 1298 | ||
1300 | static void pl010_put_poll_char(struct uart_port *port, | 1299 | static void pl011_put_poll_char(struct uart_port *port, |
1301 | unsigned char ch) | 1300 | unsigned char ch) |
1302 | { | 1301 | { |
1303 | struct uart_amba_port *uap = (struct uart_amba_port *)port; | 1302 | struct uart_amba_port *uap = (struct uart_amba_port *)port; |
@@ -1324,16 +1323,12 @@ static int pl011_startup(struct uart_port *port) | |||
1324 | "could not set default pins\n"); | 1323 | "could not set default pins\n"); |
1325 | } | 1324 | } |
1326 | 1325 | ||
1327 | retval = clk_prepare(uap->clk); | ||
1328 | if (retval) | ||
1329 | goto out; | ||
1330 | |||
1331 | /* | 1326 | /* |
1332 | * Try to enable the clock producer. | 1327 | * Try to enable the clock producer. |
1333 | */ | 1328 | */ |
1334 | retval = clk_enable(uap->clk); | 1329 | retval = clk_prepare_enable(uap->clk); |
1335 | if (retval) | 1330 | if (retval) |
1336 | goto clk_unprep; | 1331 | goto out; |
1337 | 1332 | ||
1338 | uap->port.uartclk = clk_get_rate(uap->clk); | 1333 | uap->port.uartclk = clk_get_rate(uap->clk); |
1339 | 1334 | ||
@@ -1411,9 +1406,7 @@ static int pl011_startup(struct uart_port *port) | |||
1411 | return 0; | 1406 | return 0; |
1412 | 1407 | ||
1413 | clk_dis: | 1408 | clk_dis: |
1414 | clk_disable(uap->clk); | 1409 | clk_disable_unprepare(uap->clk); |
1415 | clk_unprep: | ||
1416 | clk_unprepare(uap->clk); | ||
1417 | out: | 1410 | out: |
1418 | return retval; | 1411 | return retval; |
1419 | } | 1412 | } |
@@ -1473,8 +1466,7 @@ static void pl011_shutdown(struct uart_port *port) | |||
1473 | /* | 1466 | /* |
1474 | * Shut down the clock producer | 1467 | * Shut down the clock producer |
1475 | */ | 1468 | */ |
1476 | clk_disable(uap->clk); | 1469 | clk_disable_unprepare(uap->clk); |
1477 | clk_unprepare(uap->clk); | ||
1478 | /* Optionally let pins go into sleep states */ | 1470 | /* Optionally let pins go into sleep states */ |
1479 | if (!IS_ERR(uap->pins_sleep)) { | 1471 | if (!IS_ERR(uap->pins_sleep)) { |
1480 | retval = pinctrl_select_state(uap->pinctrl, uap->pins_sleep); | 1472 | retval = pinctrl_select_state(uap->pinctrl, uap->pins_sleep); |
@@ -1637,7 +1629,7 @@ static const char *pl011_type(struct uart_port *port) | |||
1637 | /* | 1629 | /* |
1638 | * Release the memory region(s) being used by 'port' | 1630 | * Release the memory region(s) being used by 'port' |
1639 | */ | 1631 | */ |
1640 | static void pl010_release_port(struct uart_port *port) | 1632 | static void pl011_release_port(struct uart_port *port) |
1641 | { | 1633 | { |
1642 | release_mem_region(port->mapbase, SZ_4K); | 1634 | release_mem_region(port->mapbase, SZ_4K); |
1643 | } | 1635 | } |
@@ -1645,7 +1637,7 @@ static void pl010_release_port(struct uart_port *port) | |||
1645 | /* | 1637 | /* |
1646 | * Request the memory region(s) being used by 'port' | 1638 | * Request the memory region(s) being used by 'port' |
1647 | */ | 1639 | */ |
1648 | static int pl010_request_port(struct uart_port *port) | 1640 | static int pl011_request_port(struct uart_port *port) |
1649 | { | 1641 | { |
1650 | return request_mem_region(port->mapbase, SZ_4K, "uart-pl011") | 1642 | return request_mem_region(port->mapbase, SZ_4K, "uart-pl011") |
1651 | != NULL ? 0 : -EBUSY; | 1643 | != NULL ? 0 : -EBUSY; |
@@ -1654,18 +1646,18 @@ static int pl010_request_port(struct uart_port *port) | |||
1654 | /* | 1646 | /* |
1655 | * Configure/autoconfigure the port. | 1647 | * Configure/autoconfigure the port. |
1656 | */ | 1648 | */ |
1657 | static void pl010_config_port(struct uart_port *port, int flags) | 1649 | static void pl011_config_port(struct uart_port *port, int flags) |
1658 | { | 1650 | { |
1659 | if (flags & UART_CONFIG_TYPE) { | 1651 | if (flags & UART_CONFIG_TYPE) { |
1660 | port->type = PORT_AMBA; | 1652 | port->type = PORT_AMBA; |
1661 | pl010_request_port(port); | 1653 | pl011_request_port(port); |
1662 | } | 1654 | } |
1663 | } | 1655 | } |
1664 | 1656 | ||
1665 | /* | 1657 | /* |
1666 | * verify the new serial_struct (for TIOCSSERIAL). | 1658 | * verify the new serial_struct (for TIOCSSERIAL). |
1667 | */ | 1659 | */ |
1668 | static int pl010_verify_port(struct uart_port *port, struct serial_struct *ser) | 1660 | static int pl011_verify_port(struct uart_port *port, struct serial_struct *ser) |
1669 | { | 1661 | { |
1670 | int ret = 0; | 1662 | int ret = 0; |
1671 | if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA) | 1663 | if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA) |
@@ -1678,9 +1670,9 @@ static int pl010_verify_port(struct uart_port *port, struct serial_struct *ser) | |||
1678 | } | 1670 | } |
1679 | 1671 | ||
1680 | static struct uart_ops amba_pl011_pops = { | 1672 | static struct uart_ops amba_pl011_pops = { |
1681 | .tx_empty = pl01x_tx_empty, | 1673 | .tx_empty = pl011_tx_empty, |
1682 | .set_mctrl = pl011_set_mctrl, | 1674 | .set_mctrl = pl011_set_mctrl, |
1683 | .get_mctrl = pl01x_get_mctrl, | 1675 | .get_mctrl = pl011_get_mctrl, |
1684 | .stop_tx = pl011_stop_tx, | 1676 | .stop_tx = pl011_stop_tx, |
1685 | .start_tx = pl011_start_tx, | 1677 | .start_tx = pl011_start_tx, |
1686 | .stop_rx = pl011_stop_rx, | 1678 | .stop_rx = pl011_stop_rx, |
@@ -1691,13 +1683,13 @@ static struct uart_ops amba_pl011_pops = { | |||
1691 | .flush_buffer = pl011_dma_flush_buffer, | 1683 | .flush_buffer = pl011_dma_flush_buffer, |
1692 | .set_termios = pl011_set_termios, | 1684 | .set_termios = pl011_set_termios, |
1693 | .type = pl011_type, | 1685 | .type = pl011_type, |
1694 | .release_port = pl010_release_port, | 1686 | .release_port = pl011_release_port, |
1695 | .request_port = pl010_request_port, | 1687 | .request_port = pl011_request_port, |
1696 | .config_port = pl010_config_port, | 1688 | .config_port = pl011_config_port, |
1697 | .verify_port = pl010_verify_port, | 1689 | .verify_port = pl011_verify_port, |
1698 | #ifdef CONFIG_CONSOLE_POLL | 1690 | #ifdef CONFIG_CONSOLE_POLL |
1699 | .poll_get_char = pl010_get_poll_char, | 1691 | .poll_get_char = pl011_get_poll_char, |
1700 | .poll_put_char = pl010_put_poll_char, | 1692 | .poll_put_char = pl011_put_poll_char, |
1701 | #endif | 1693 | #endif |
1702 | }; | 1694 | }; |
1703 | 1695 | ||
@@ -1869,6 +1861,38 @@ static struct uart_driver amba_reg = { | |||
1869 | .cons = AMBA_CONSOLE, | 1861 | .cons = AMBA_CONSOLE, |
1870 | }; | 1862 | }; |
1871 | 1863 | ||
1864 | static int pl011_probe_dt_alias(int index, struct device *dev) | ||
1865 | { | ||
1866 | struct device_node *np; | ||
1867 | static bool seen_dev_with_alias = false; | ||
1868 | static bool seen_dev_without_alias = false; | ||
1869 | int ret = index; | ||
1870 | |||
1871 | if (!IS_ENABLED(CONFIG_OF)) | ||
1872 | return ret; | ||
1873 | |||
1874 | np = dev->of_node; | ||
1875 | if (!np) | ||
1876 | return ret; | ||
1877 | |||
1878 | ret = of_alias_get_id(np, "serial"); | ||
1879 | if (IS_ERR_VALUE(ret)) { | ||
1880 | seen_dev_without_alias = true; | ||
1881 | ret = index; | ||
1882 | } else { | ||
1883 | seen_dev_with_alias = true; | ||
1884 | if (ret >= ARRAY_SIZE(amba_ports) || amba_ports[ret] != NULL) { | ||
1885 | dev_warn(dev, "requested serial port %d not available.\n", ret); | ||
1886 | ret = index; | ||
1887 | } | ||
1888 | } | ||
1889 | |||
1890 | if (seen_dev_with_alias && seen_dev_without_alias) | ||
1891 | dev_warn(dev, "aliased and non-aliased serial devices found in device tree. Serial port enumeration may be unpredictable.\n"); | ||
1892 | |||
1893 | return ret; | ||
1894 | } | ||
1895 | |||
1872 | static int pl011_probe(struct amba_device *dev, const struct amba_id *id) | 1896 | static int pl011_probe(struct amba_device *dev, const struct amba_id *id) |
1873 | { | 1897 | { |
1874 | struct uart_amba_port *uap; | 1898 | struct uart_amba_port *uap; |
@@ -1891,6 +1915,8 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) | |||
1891 | goto out; | 1915 | goto out; |
1892 | } | 1916 | } |
1893 | 1917 | ||
1918 | i = pl011_probe_dt_alias(i, &dev->dev); | ||
1919 | |||
1894 | base = ioremap(dev->res.start, resource_size(&dev->res)); | 1920 | base = ioremap(dev->res.start, resource_size(&dev->res)); |
1895 | if (!base) { | 1921 | if (!base) { |
1896 | ret = -ENOMEM; | 1922 | ret = -ENOMEM; |
@@ -1923,7 +1949,6 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) | |||
1923 | uap->lcrh_tx = vendor->lcrh_tx; | 1949 | uap->lcrh_tx = vendor->lcrh_tx; |
1924 | uap->old_cr = 0; | 1950 | uap->old_cr = 0; |
1925 | uap->fifosize = vendor->fifosize; | 1951 | uap->fifosize = vendor->fifosize; |
1926 | uap->interrupt_may_hang = vendor->interrupt_may_hang; | ||
1927 | uap->port.dev = &dev->dev; | 1952 | uap->port.dev = &dev->dev; |
1928 | uap->port.mapbase = dev->res.start; | 1953 | uap->port.mapbase = dev->res.start; |
1929 | uap->port.membase = base; | 1954 | uap->port.membase = base; |