diff options
Diffstat (limited to 'drivers/tty/serial/xilinx_uartps.c')
-rw-r--r-- | drivers/tty/serial/xilinx_uartps.c | 108 |
1 files changed, 42 insertions, 66 deletions
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index bd72dd843338..8a3e34234e98 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c | |||
@@ -1097,45 +1097,6 @@ static const struct uart_ops cdns_uart_ops = { | |||
1097 | #endif | 1097 | #endif |
1098 | }; | 1098 | }; |
1099 | 1099 | ||
1100 | static struct uart_port cdns_uart_port[CDNS_UART_NR_PORTS]; | ||
1101 | |||
1102 | /** | ||
1103 | * cdns_uart_get_port - Configure the port from platform device resource info | ||
1104 | * @id: Port id | ||
1105 | * | ||
1106 | * Return: a pointer to a uart_port or NULL for failure | ||
1107 | */ | ||
1108 | static struct uart_port *cdns_uart_get_port(int id) | ||
1109 | { | ||
1110 | struct uart_port *port; | ||
1111 | |||
1112 | /* Try the given port id if failed use default method */ | ||
1113 | if (id < CDNS_UART_NR_PORTS && cdns_uart_port[id].mapbase != 0) { | ||
1114 | /* Find the next unused port */ | ||
1115 | for (id = 0; id < CDNS_UART_NR_PORTS; id++) | ||
1116 | if (cdns_uart_port[id].mapbase == 0) | ||
1117 | break; | ||
1118 | } | ||
1119 | |||
1120 | if (id >= CDNS_UART_NR_PORTS) | ||
1121 | return NULL; | ||
1122 | |||
1123 | port = &cdns_uart_port[id]; | ||
1124 | |||
1125 | /* At this point, we've got an empty uart_port struct, initialize it */ | ||
1126 | spin_lock_init(&port->lock); | ||
1127 | port->membase = NULL; | ||
1128 | port->irq = 0; | ||
1129 | port->type = PORT_UNKNOWN; | ||
1130 | port->iotype = UPIO_MEM32; | ||
1131 | port->flags = UPF_BOOT_AUTOCONF; | ||
1132 | port->ops = &cdns_uart_ops; | ||
1133 | port->fifosize = CDNS_UART_FIFO_SIZE; | ||
1134 | port->line = id; | ||
1135 | port->dev = NULL; | ||
1136 | return port; | ||
1137 | } | ||
1138 | |||
1139 | #ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE | 1100 | #ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE |
1140 | /** | 1101 | /** |
1141 | * cdns_uart_console_wait_tx - Wait for the TX to be full | 1102 | * cdns_uart_console_wait_tx - Wait for the TX to be full |
@@ -1206,6 +1167,10 @@ OF_EARLYCON_DECLARE(cdns, "cdns,uart-r1p8", cdns_early_console_setup); | |||
1206 | OF_EARLYCON_DECLARE(cdns, "cdns,uart-r1p12", cdns_early_console_setup); | 1167 | OF_EARLYCON_DECLARE(cdns, "cdns,uart-r1p12", cdns_early_console_setup); |
1207 | OF_EARLYCON_DECLARE(cdns, "xlnx,zynqmp-uart", cdns_early_console_setup); | 1168 | OF_EARLYCON_DECLARE(cdns, "xlnx,zynqmp-uart", cdns_early_console_setup); |
1208 | 1169 | ||
1170 | |||
1171 | /* Static pointer to console port */ | ||
1172 | static struct uart_port *console_port; | ||
1173 | |||
1209 | /** | 1174 | /** |
1210 | * cdns_uart_console_write - perform write operation | 1175 | * cdns_uart_console_write - perform write operation |
1211 | * @co: Console handle | 1176 | * @co: Console handle |
@@ -1215,7 +1180,7 @@ OF_EARLYCON_DECLARE(cdns, "xlnx,zynqmp-uart", cdns_early_console_setup); | |||
1215 | static void cdns_uart_console_write(struct console *co, const char *s, | 1180 | static void cdns_uart_console_write(struct console *co, const char *s, |
1216 | unsigned int count) | 1181 | unsigned int count) |
1217 | { | 1182 | { |
1218 | struct uart_port *port = &cdns_uart_port[co->index]; | 1183 | struct uart_port *port = console_port; |
1219 | unsigned long flags; | 1184 | unsigned long flags; |
1220 | unsigned int imr, ctrl; | 1185 | unsigned int imr, ctrl; |
1221 | int locked = 1; | 1186 | int locked = 1; |
@@ -1261,15 +1226,13 @@ static void cdns_uart_console_write(struct console *co, const char *s, | |||
1261 | */ | 1226 | */ |
1262 | static int __init cdns_uart_console_setup(struct console *co, char *options) | 1227 | static int __init cdns_uart_console_setup(struct console *co, char *options) |
1263 | { | 1228 | { |
1264 | struct uart_port *port = &cdns_uart_port[co->index]; | 1229 | struct uart_port *port = console_port; |
1230 | |||
1265 | int baud = 9600; | 1231 | int baud = 9600; |
1266 | int bits = 8; | 1232 | int bits = 8; |
1267 | int parity = 'n'; | 1233 | int parity = 'n'; |
1268 | int flow = 'n'; | 1234 | int flow = 'n'; |
1269 | 1235 | ||
1270 | if (co->index < 0 || co->index >= CDNS_UART_NR_PORTS) | ||
1271 | return -EINVAL; | ||
1272 | |||
1273 | if (!port->membase) { | 1236 | if (!port->membase) { |
1274 | pr_debug("console on " CDNS_UART_TTY_NAME "%i not present\n", | 1237 | pr_debug("console on " CDNS_UART_TTY_NAME "%i not present\n", |
1275 | co->index); | 1238 | co->index); |
@@ -1293,20 +1256,6 @@ static struct console cdns_uart_console = { | |||
1293 | .index = -1, /* Specified on the cmdline (e.g. console=ttyPS ) */ | 1256 | .index = -1, /* Specified on the cmdline (e.g. console=ttyPS ) */ |
1294 | .data = &cdns_uart_uart_driver, | 1257 | .data = &cdns_uart_uart_driver, |
1295 | }; | 1258 | }; |
1296 | |||
1297 | /** | ||
1298 | * cdns_uart_console_init - Initialization call | ||
1299 | * | ||
1300 | * Return: 0 on success, negative errno otherwise | ||
1301 | */ | ||
1302 | static int __init cdns_uart_console_init(void) | ||
1303 | { | ||
1304 | register_console(&cdns_uart_console); | ||
1305 | return 0; | ||
1306 | } | ||
1307 | |||
1308 | console_initcall(cdns_uart_console_init); | ||
1309 | |||
1310 | #endif /* CONFIG_SERIAL_XILINX_PS_UART_CONSOLE */ | 1259 | #endif /* CONFIG_SERIAL_XILINX_PS_UART_CONSOLE */ |
1311 | 1260 | ||
1312 | static struct uart_driver cdns_uart_uart_driver = { | 1261 | static struct uart_driver cdns_uart_uart_driver = { |
@@ -1430,8 +1379,7 @@ static int cdns_uart_resume(struct device *device) | |||
1430 | #endif /* ! CONFIG_PM_SLEEP */ | 1379 | #endif /* ! CONFIG_PM_SLEEP */ |
1431 | static int __maybe_unused cdns_runtime_suspend(struct device *dev) | 1380 | static int __maybe_unused cdns_runtime_suspend(struct device *dev) |
1432 | { | 1381 | { |
1433 | struct platform_device *pdev = to_platform_device(dev); | 1382 | struct uart_port *port = dev_get_drvdata(dev); |
1434 | struct uart_port *port = platform_get_drvdata(pdev); | ||
1435 | struct cdns_uart *cdns_uart = port->private_data; | 1383 | struct cdns_uart *cdns_uart = port->private_data; |
1436 | 1384 | ||
1437 | clk_disable(cdns_uart->uartclk); | 1385 | clk_disable(cdns_uart->uartclk); |
@@ -1441,8 +1389,7 @@ static int __maybe_unused cdns_runtime_suspend(struct device *dev) | |||
1441 | 1389 | ||
1442 | static int __maybe_unused cdns_runtime_resume(struct device *dev) | 1390 | static int __maybe_unused cdns_runtime_resume(struct device *dev) |
1443 | { | 1391 | { |
1444 | struct platform_device *pdev = to_platform_device(dev); | 1392 | struct uart_port *port = dev_get_drvdata(dev); |
1445 | struct uart_port *port = platform_get_drvdata(pdev); | ||
1446 | struct cdns_uart *cdns_uart = port->private_data; | 1393 | struct cdns_uart *cdns_uart = port->private_data; |
1447 | 1394 | ||
1448 | clk_enable(cdns_uart->pclk); | 1395 | clk_enable(cdns_uart->pclk); |
@@ -1487,6 +1434,9 @@ static int cdns_uart_probe(struct platform_device *pdev) | |||
1487 | GFP_KERNEL); | 1434 | GFP_KERNEL); |
1488 | if (!cdns_uart_data) | 1435 | if (!cdns_uart_data) |
1489 | return -ENOMEM; | 1436 | return -ENOMEM; |
1437 | port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL); | ||
1438 | if (!port) | ||
1439 | return -ENOMEM; | ||
1490 | 1440 | ||
1491 | match = of_match_node(cdns_uart_of_match, pdev->dev.of_node); | 1441 | match = of_match_node(cdns_uart_of_match, pdev->dev.of_node); |
1492 | if (match && match->data) { | 1442 | if (match && match->data) { |
@@ -1552,15 +1502,24 @@ static int cdns_uart_probe(struct platform_device *pdev) | |||
1552 | if (id < 0) | 1502 | if (id < 0) |
1553 | id = 0; | 1503 | id = 0; |
1554 | 1504 | ||
1555 | /* Initialize the port structure */ | 1505 | if (id >= CDNS_UART_NR_PORTS) { |
1556 | port = cdns_uart_get_port(id); | ||
1557 | |||
1558 | if (!port) { | ||
1559 | dev_err(&pdev->dev, "Cannot get uart_port structure\n"); | 1506 | dev_err(&pdev->dev, "Cannot get uart_port structure\n"); |
1560 | rc = -ENODEV; | 1507 | rc = -ENODEV; |
1561 | goto err_out_notif_unreg; | 1508 | goto err_out_notif_unreg; |
1562 | } | 1509 | } |
1563 | 1510 | ||
1511 | /* At this point, we've got an empty uart_port struct, initialize it */ | ||
1512 | spin_lock_init(&port->lock); | ||
1513 | port->membase = NULL; | ||
1514 | port->irq = 0; | ||
1515 | port->type = PORT_UNKNOWN; | ||
1516 | port->iotype = UPIO_MEM32; | ||
1517 | port->flags = UPF_BOOT_AUTOCONF; | ||
1518 | port->ops = &cdns_uart_ops; | ||
1519 | port->fifosize = CDNS_UART_FIFO_SIZE; | ||
1520 | port->line = id; | ||
1521 | port->dev = NULL; | ||
1522 | |||
1564 | /* | 1523 | /* |
1565 | * Register the port. | 1524 | * Register the port. |
1566 | * This function also registers this device with the tty layer | 1525 | * This function also registers this device with the tty layer |
@@ -1579,6 +1538,17 @@ static int cdns_uart_probe(struct platform_device *pdev) | |||
1579 | pm_runtime_set_active(&pdev->dev); | 1538 | pm_runtime_set_active(&pdev->dev); |
1580 | pm_runtime_enable(&pdev->dev); | 1539 | pm_runtime_enable(&pdev->dev); |
1581 | 1540 | ||
1541 | #ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE | ||
1542 | /* | ||
1543 | * If console hasn't been found yet try to assign this port | ||
1544 | * because it is required to be assigned for console setup function. | ||
1545 | * If register_console() don't assign value, then console_port pointer | ||
1546 | * is cleanup. | ||
1547 | */ | ||
1548 | if (cdns_uart_uart_driver.cons->index == -1) | ||
1549 | console_port = port; | ||
1550 | #endif | ||
1551 | |||
1582 | rc = uart_add_one_port(&cdns_uart_uart_driver, port); | 1552 | rc = uart_add_one_port(&cdns_uart_uart_driver, port); |
1583 | if (rc) { | 1553 | if (rc) { |
1584 | dev_err(&pdev->dev, | 1554 | dev_err(&pdev->dev, |
@@ -1586,6 +1556,12 @@ static int cdns_uart_probe(struct platform_device *pdev) | |||
1586 | goto err_out_pm_disable; | 1556 | goto err_out_pm_disable; |
1587 | } | 1557 | } |
1588 | 1558 | ||
1559 | #ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE | ||
1560 | /* This is not port which is used for console that's why clean it up */ | ||
1561 | if (cdns_uart_uart_driver.cons->index == -1) | ||
1562 | console_port = NULL; | ||
1563 | #endif | ||
1564 | |||
1589 | return 0; | 1565 | return 0; |
1590 | 1566 | ||
1591 | err_out_pm_disable: | 1567 | err_out_pm_disable: |