1e3b3d0f5SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0+ 21a8d2903SMasahiro Yamada /* 31a8d2903SMasahiro Yamada * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com> 41a8d2903SMasahiro Yamada */ 51a8d2903SMasahiro Yamada 61a8d2903SMasahiro Yamada #include <linux/clk.h> 7b8d20e06SMasahiro Yamada #include <linux/console.h> 81a8d2903SMasahiro Yamada #include <linux/io.h> 91a8d2903SMasahiro Yamada #include <linux/module.h> 101a8d2903SMasahiro Yamada #include <linux/of.h> 111a8d2903SMasahiro Yamada #include <linux/platform_device.h> 121a8d2903SMasahiro Yamada 131a8d2903SMasahiro Yamada #include "8250.h" 141a8d2903SMasahiro Yamada 1594cbb697SMasahiro Yamada /* 1694cbb697SMasahiro Yamada * This hardware is similar to 8250, but its register map is a bit different: 1794cbb697SMasahiro Yamada * - MMIO32 (regshift = 2) 1894cbb697SMasahiro Yamada * - FCR is not at 2, but 3 1994cbb697SMasahiro Yamada * - LCR and MCR are not at 3 and 4, they share 4 20d3a91847SMasahiro Yamada * - No SCR (Instead, CHAR can be used as a scratch register) 2194cbb697SMasahiro Yamada * - Divisor latch at 9, no divisor latch access bit 2294cbb697SMasahiro Yamada */ 2394cbb697SMasahiro Yamada 2494cbb697SMasahiro Yamada #define UNIPHIER_UART_REGSHIFT 2 2594cbb697SMasahiro Yamada 26d3a91847SMasahiro Yamada /* bit[15:8] = CHAR, bit[7:0] = FCR */ 2794cbb697SMasahiro Yamada #define UNIPHIER_UART_CHAR_FCR (3 << (UNIPHIER_UART_REGSHIFT)) 2894cbb697SMasahiro Yamada /* bit[15:8] = LCR, bit[7:0] = MCR */ 2994cbb697SMasahiro Yamada #define UNIPHIER_UART_LCR_MCR (4 << (UNIPHIER_UART_REGSHIFT)) 3094cbb697SMasahiro Yamada /* Divisor Latch Register */ 3194cbb697SMasahiro Yamada #define UNIPHIER_UART_DLR (9 << (UNIPHIER_UART_REGSHIFT)) 321a8d2903SMasahiro Yamada 331a8d2903SMasahiro Yamada struct uniphier8250_priv { 341a8d2903SMasahiro Yamada int line; 351a8d2903SMasahiro Yamada struct clk *clk; 361a8d2903SMasahiro Yamada spinlock_t atomic_write_lock; 371a8d2903SMasahiro Yamada }; 381a8d2903SMasahiro Yamada 3968b78059SMasahiro Yamada #ifdef CONFIG_SERIAL_8250_CONSOLE 40b8d20e06SMasahiro Yamada static int __init uniphier_early_console_setup(struct earlycon_device *device, 41b8d20e06SMasahiro Yamada const char *options) 42b8d20e06SMasahiro Yamada { 43b8d20e06SMasahiro Yamada if (!device->port.membase) 44b8d20e06SMasahiro Yamada return -ENODEV; 45b8d20e06SMasahiro Yamada 46b8d20e06SMasahiro Yamada /* This hardware always expects MMIO32 register interface. */ 47b8d20e06SMasahiro Yamada device->port.iotype = UPIO_MEM32; 4894cbb697SMasahiro Yamada device->port.regshift = UNIPHIER_UART_REGSHIFT; 49b8d20e06SMasahiro Yamada 50b8d20e06SMasahiro Yamada /* 51b8d20e06SMasahiro Yamada * Do not touch the divisor register in early_serial8250_setup(); 52b8d20e06SMasahiro Yamada * we assume it has been initialized by a boot loader. 53b8d20e06SMasahiro Yamada */ 54b8d20e06SMasahiro Yamada device->baud = 0; 55b8d20e06SMasahiro Yamada 56b8d20e06SMasahiro Yamada return early_serial8250_setup(device, options); 57b8d20e06SMasahiro Yamada } 58b8d20e06SMasahiro Yamada OF_EARLYCON_DECLARE(uniphier, "socionext,uniphier-uart", 59b8d20e06SMasahiro Yamada uniphier_early_console_setup); 60b8d20e06SMasahiro Yamada #endif 61b8d20e06SMasahiro Yamada 621a8d2903SMasahiro Yamada /* 631a8d2903SMasahiro Yamada * The register map is slightly different from that of 8250. 64d3a91847SMasahiro Yamada * IO callbacks must be overridden for correct access to FCR, LCR, MCR and SCR. 651a8d2903SMasahiro Yamada */ 661a8d2903SMasahiro Yamada static unsigned int uniphier_serial_in(struct uart_port *p, int offset) 671a8d2903SMasahiro Yamada { 681a8d2903SMasahiro Yamada unsigned int valshift = 0; 691a8d2903SMasahiro Yamada 701a8d2903SMasahiro Yamada switch (offset) { 71d3a91847SMasahiro Yamada case UART_SCR: 72d3a91847SMasahiro Yamada /* No SCR for this hardware. Use CHAR as a scratch register */ 73d3a91847SMasahiro Yamada valshift = 8; 74d3a91847SMasahiro Yamada offset = UNIPHIER_UART_CHAR_FCR; 75d3a91847SMasahiro Yamada break; 761a8d2903SMasahiro Yamada case UART_LCR: 7794cbb697SMasahiro Yamada valshift = 8; 78*df561f66SGustavo A. R. Silva fallthrough; 791a8d2903SMasahiro Yamada case UART_MCR: 801a8d2903SMasahiro Yamada offset = UNIPHIER_UART_LCR_MCR; 811a8d2903SMasahiro Yamada break; 821a8d2903SMasahiro Yamada default: 8394cbb697SMasahiro Yamada offset <<= UNIPHIER_UART_REGSHIFT; 841a8d2903SMasahiro Yamada break; 851a8d2903SMasahiro Yamada } 861a8d2903SMasahiro Yamada 871a8d2903SMasahiro Yamada /* 88d3a91847SMasahiro Yamada * The return value must be masked with 0xff because some registers 89d3a91847SMasahiro Yamada * share the same offset that must be accessed by 32-bit write/read. 901a8d2903SMasahiro Yamada * 8 or 16 bit access to this hardware result in unexpected behavior. 911a8d2903SMasahiro Yamada */ 921a8d2903SMasahiro Yamada return (readl(p->membase + offset) >> valshift) & 0xff; 931a8d2903SMasahiro Yamada } 941a8d2903SMasahiro Yamada 951a8d2903SMasahiro Yamada static void uniphier_serial_out(struct uart_port *p, int offset, int value) 961a8d2903SMasahiro Yamada { 971a8d2903SMasahiro Yamada unsigned int valshift = 0; 98d3a91847SMasahiro Yamada bool normal = false; 991a8d2903SMasahiro Yamada 1001a8d2903SMasahiro Yamada switch (offset) { 101d3a91847SMasahiro Yamada case UART_SCR: 102d3a91847SMasahiro Yamada /* No SCR for this hardware. Use CHAR as a scratch register */ 103d3a91847SMasahiro Yamada valshift = 8; 104*df561f66SGustavo A. R. Silva fallthrough; 1051a8d2903SMasahiro Yamada case UART_FCR: 1061a8d2903SMasahiro Yamada offset = UNIPHIER_UART_CHAR_FCR; 1071a8d2903SMasahiro Yamada break; 1081a8d2903SMasahiro Yamada case UART_LCR: 10994cbb697SMasahiro Yamada valshift = 8; 1101a8d2903SMasahiro Yamada /* Divisor latch access bit does not exist. */ 11109065c5fSMasahiro Yamada value &= ~UART_LCR_DLAB; 112*df561f66SGustavo A. R. Silva fallthrough; 1131a8d2903SMasahiro Yamada case UART_MCR: 1141a8d2903SMasahiro Yamada offset = UNIPHIER_UART_LCR_MCR; 1151a8d2903SMasahiro Yamada break; 1161a8d2903SMasahiro Yamada default: 11794cbb697SMasahiro Yamada offset <<= UNIPHIER_UART_REGSHIFT; 118d3a91847SMasahiro Yamada normal = true; 1191a8d2903SMasahiro Yamada break; 1201a8d2903SMasahiro Yamada } 1211a8d2903SMasahiro Yamada 1221a8d2903SMasahiro Yamada if (normal) { 1231a8d2903SMasahiro Yamada writel(value, p->membase + offset); 1241a8d2903SMasahiro Yamada } else { 1251a8d2903SMasahiro Yamada /* 1261a8d2903SMasahiro Yamada * Special case: two registers share the same address that 1271a8d2903SMasahiro Yamada * must be 32-bit accessed. As this is not longer atomic safe, 1281a8d2903SMasahiro Yamada * take a lock just in case. 1291a8d2903SMasahiro Yamada */ 1301a8d2903SMasahiro Yamada struct uniphier8250_priv *priv = p->private_data; 1311a8d2903SMasahiro Yamada unsigned long flags; 1321a8d2903SMasahiro Yamada u32 tmp; 1331a8d2903SMasahiro Yamada 1341a8d2903SMasahiro Yamada spin_lock_irqsave(&priv->atomic_write_lock, flags); 1351a8d2903SMasahiro Yamada tmp = readl(p->membase + offset); 1361a8d2903SMasahiro Yamada tmp &= ~(0xff << valshift); 1371a8d2903SMasahiro Yamada tmp |= value << valshift; 1381a8d2903SMasahiro Yamada writel(tmp, p->membase + offset); 1391a8d2903SMasahiro Yamada spin_unlock_irqrestore(&priv->atomic_write_lock, flags); 1401a8d2903SMasahiro Yamada } 1411a8d2903SMasahiro Yamada } 1421a8d2903SMasahiro Yamada 1431a8d2903SMasahiro Yamada /* 1441a8d2903SMasahiro Yamada * This hardware does not have the divisor latch access bit. 1451a8d2903SMasahiro Yamada * The divisor latch register exists at different address. 1461a8d2903SMasahiro Yamada * Override dl_read/write callbacks. 1471a8d2903SMasahiro Yamada */ 1481a8d2903SMasahiro Yamada static int uniphier_serial_dl_read(struct uart_8250_port *up) 1491a8d2903SMasahiro Yamada { 15094cbb697SMasahiro Yamada return readl(up->port.membase + UNIPHIER_UART_DLR); 1511a8d2903SMasahiro Yamada } 1521a8d2903SMasahiro Yamada 1531a8d2903SMasahiro Yamada static void uniphier_serial_dl_write(struct uart_8250_port *up, int value) 1541a8d2903SMasahiro Yamada { 15594cbb697SMasahiro Yamada writel(value, up->port.membase + UNIPHIER_UART_DLR); 1561a8d2903SMasahiro Yamada } 1571a8d2903SMasahiro Yamada 1581a8d2903SMasahiro Yamada static int uniphier_uart_probe(struct platform_device *pdev) 1591a8d2903SMasahiro Yamada { 1601a8d2903SMasahiro Yamada struct device *dev = &pdev->dev; 1611a8d2903SMasahiro Yamada struct uart_8250_port up; 1621a8d2903SMasahiro Yamada struct uniphier8250_priv *priv; 1631a8d2903SMasahiro Yamada struct resource *regs; 1641a8d2903SMasahiro Yamada void __iomem *membase; 1651a8d2903SMasahiro Yamada int irq; 1661a8d2903SMasahiro Yamada int ret; 1671a8d2903SMasahiro Yamada 1681a8d2903SMasahiro Yamada regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1691a8d2903SMasahiro Yamada if (!regs) { 1700ead21adSDenys Vlasenko dev_err(dev, "failed to get memory resource\n"); 1711a8d2903SMasahiro Yamada return -EINVAL; 1721a8d2903SMasahiro Yamada } 1731a8d2903SMasahiro Yamada 1741a8d2903SMasahiro Yamada membase = devm_ioremap(dev, regs->start, resource_size(regs)); 1751a8d2903SMasahiro Yamada if (!membase) 1761a8d2903SMasahiro Yamada return -ENOMEM; 1771a8d2903SMasahiro Yamada 1781a8d2903SMasahiro Yamada irq = platform_get_irq(pdev, 0); 1791df21786SStephen Boyd if (irq < 0) 1801a8d2903SMasahiro Yamada return irq; 1811a8d2903SMasahiro Yamada 1821a8d2903SMasahiro Yamada priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 1831a8d2903SMasahiro Yamada if (!priv) 1841a8d2903SMasahiro Yamada return -ENOMEM; 1851a8d2903SMasahiro Yamada 1861a8d2903SMasahiro Yamada memset(&up, 0, sizeof(up)); 1871a8d2903SMasahiro Yamada 188aca70d19SMasahiro Yamada ret = of_alias_get_id(dev->of_node, "serial"); 189aca70d19SMasahiro Yamada if (ret < 0) { 190aca70d19SMasahiro Yamada dev_err(dev, "failed to get alias id\n"); 1911a8d2903SMasahiro Yamada return ret; 192aca70d19SMasahiro Yamada } 193aca70d19SMasahiro Yamada up.port.line = ret; 194aca70d19SMasahiro Yamada 195aca70d19SMasahiro Yamada priv->clk = devm_clk_get(dev, NULL); 196aca70d19SMasahiro Yamada if (IS_ERR(priv->clk)) { 197aca70d19SMasahiro Yamada dev_err(dev, "failed to get clock\n"); 198aca70d19SMasahiro Yamada return PTR_ERR(priv->clk); 199aca70d19SMasahiro Yamada } 200aca70d19SMasahiro Yamada 201aca70d19SMasahiro Yamada ret = clk_prepare_enable(priv->clk); 202aca70d19SMasahiro Yamada if (ret) 203aca70d19SMasahiro Yamada return ret; 204aca70d19SMasahiro Yamada 205aca70d19SMasahiro Yamada up.port.uartclk = clk_get_rate(priv->clk); 2061a8d2903SMasahiro Yamada 2071a8d2903SMasahiro Yamada spin_lock_init(&priv->atomic_write_lock); 2081a8d2903SMasahiro Yamada 2091a8d2903SMasahiro Yamada up.port.dev = dev; 2101a8d2903SMasahiro Yamada up.port.private_data = priv; 2111a8d2903SMasahiro Yamada up.port.mapbase = regs->start; 2121a8d2903SMasahiro Yamada up.port.mapsize = resource_size(regs); 2131a8d2903SMasahiro Yamada up.port.membase = membase; 2141a8d2903SMasahiro Yamada up.port.irq = irq; 2151a8d2903SMasahiro Yamada 2161a8d2903SMasahiro Yamada up.port.type = PORT_16550A; 2171a8d2903SMasahiro Yamada up.port.iotype = UPIO_MEM32; 2182fd8e454SMasahiro Yamada up.port.fifosize = 64; 21994cbb697SMasahiro Yamada up.port.regshift = UNIPHIER_UART_REGSHIFT; 2201a8d2903SMasahiro Yamada up.port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE; 2211a8d2903SMasahiro Yamada up.capabilities = UART_CAP_FIFO; 2221a8d2903SMasahiro Yamada 223aad2d495SDai Okamura if (of_property_read_bool(dev->of_node, "auto-flow-control")) 224aad2d495SDai Okamura up.capabilities |= UART_CAP_AFE; 225aad2d495SDai Okamura 2261a8d2903SMasahiro Yamada up.port.serial_in = uniphier_serial_in; 2271a8d2903SMasahiro Yamada up.port.serial_out = uniphier_serial_out; 2281a8d2903SMasahiro Yamada up.dl_read = uniphier_serial_dl_read; 2291a8d2903SMasahiro Yamada up.dl_write = uniphier_serial_dl_write; 2301a8d2903SMasahiro Yamada 2317defa77dSWei Yongjun ret = serial8250_register_8250_port(&up); 2327defa77dSWei Yongjun if (ret < 0) { 2331a8d2903SMasahiro Yamada dev_err(dev, "failed to register 8250 port\n"); 234e70e69bfSMasahiro Yamada clk_disable_unprepare(priv->clk); 2351a8d2903SMasahiro Yamada return ret; 2361a8d2903SMasahiro Yamada } 2377defa77dSWei Yongjun priv->line = ret; 2381a8d2903SMasahiro Yamada 2391a8d2903SMasahiro Yamada platform_set_drvdata(pdev, priv); 2401a8d2903SMasahiro Yamada 2411a8d2903SMasahiro Yamada return 0; 2421a8d2903SMasahiro Yamada } 2431a8d2903SMasahiro Yamada 2441a8d2903SMasahiro Yamada static int uniphier_uart_remove(struct platform_device *pdev) 2451a8d2903SMasahiro Yamada { 2461a8d2903SMasahiro Yamada struct uniphier8250_priv *priv = platform_get_drvdata(pdev); 2471a8d2903SMasahiro Yamada 2481a8d2903SMasahiro Yamada serial8250_unregister_port(priv->line); 2491a8d2903SMasahiro Yamada clk_disable_unprepare(priv->clk); 2501a8d2903SMasahiro Yamada 2511a8d2903SMasahiro Yamada return 0; 2521a8d2903SMasahiro Yamada } 2531a8d2903SMasahiro Yamada 2543d16ddc1SMasahiro Yamada static int __maybe_unused uniphier_uart_suspend(struct device *dev) 2553d16ddc1SMasahiro Yamada { 2563d16ddc1SMasahiro Yamada struct uniphier8250_priv *priv = dev_get_drvdata(dev); 2573d16ddc1SMasahiro Yamada struct uart_8250_port *up = serial8250_get_port(priv->line); 2583d16ddc1SMasahiro Yamada 2593d16ddc1SMasahiro Yamada serial8250_suspend_port(priv->line); 2603d16ddc1SMasahiro Yamada 2613d16ddc1SMasahiro Yamada if (!uart_console(&up->port) || console_suspend_enabled) 2623d16ddc1SMasahiro Yamada clk_disable_unprepare(priv->clk); 2633d16ddc1SMasahiro Yamada 2643d16ddc1SMasahiro Yamada return 0; 2653d16ddc1SMasahiro Yamada } 2663d16ddc1SMasahiro Yamada 2673d16ddc1SMasahiro Yamada static int __maybe_unused uniphier_uart_resume(struct device *dev) 2683d16ddc1SMasahiro Yamada { 2693d16ddc1SMasahiro Yamada struct uniphier8250_priv *priv = dev_get_drvdata(dev); 2703d16ddc1SMasahiro Yamada struct uart_8250_port *up = serial8250_get_port(priv->line); 2713d16ddc1SMasahiro Yamada int ret; 2723d16ddc1SMasahiro Yamada 2733d16ddc1SMasahiro Yamada if (!uart_console(&up->port) || console_suspend_enabled) { 2743d16ddc1SMasahiro Yamada ret = clk_prepare_enable(priv->clk); 2753d16ddc1SMasahiro Yamada if (ret) 2763d16ddc1SMasahiro Yamada return ret; 2773d16ddc1SMasahiro Yamada } 2783d16ddc1SMasahiro Yamada 2793d16ddc1SMasahiro Yamada serial8250_resume_port(priv->line); 2803d16ddc1SMasahiro Yamada 2813d16ddc1SMasahiro Yamada return 0; 2823d16ddc1SMasahiro Yamada } 2833d16ddc1SMasahiro Yamada 2843d16ddc1SMasahiro Yamada static const struct dev_pm_ops uniphier_uart_pm_ops = { 2853d16ddc1SMasahiro Yamada SET_SYSTEM_SLEEP_PM_OPS(uniphier_uart_suspend, uniphier_uart_resume) 2863d16ddc1SMasahiro Yamada }; 2873d16ddc1SMasahiro Yamada 2881a8d2903SMasahiro Yamada static const struct of_device_id uniphier_uart_match[] = { 2891a8d2903SMasahiro Yamada { .compatible = "socionext,uniphier-uart" }, 2901a8d2903SMasahiro Yamada { /* sentinel */ } 2911a8d2903SMasahiro Yamada }; 2921a8d2903SMasahiro Yamada MODULE_DEVICE_TABLE(of, uniphier_uart_match); 2931a8d2903SMasahiro Yamada 2941a8d2903SMasahiro Yamada static struct platform_driver uniphier_uart_platform_driver = { 2951a8d2903SMasahiro Yamada .probe = uniphier_uart_probe, 2961a8d2903SMasahiro Yamada .remove = uniphier_uart_remove, 2971a8d2903SMasahiro Yamada .driver = { 2981a8d2903SMasahiro Yamada .name = "uniphier-uart", 2991a8d2903SMasahiro Yamada .of_match_table = uniphier_uart_match, 3003d16ddc1SMasahiro Yamada .pm = &uniphier_uart_pm_ops, 3011a8d2903SMasahiro Yamada }, 3021a8d2903SMasahiro Yamada }; 3031a8d2903SMasahiro Yamada module_platform_driver(uniphier_uart_platform_driver); 3041a8d2903SMasahiro Yamada 3051a8d2903SMasahiro Yamada MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>"); 3061a8d2903SMasahiro Yamada MODULE_DESCRIPTION("UniPhier UART driver"); 3071a8d2903SMasahiro Yamada MODULE_LICENSE("GPL"); 308