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; 781a8d2903SMasahiro Yamada /* fall through */ 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; 104d3a91847SMasahiro Yamada /* fall through */ 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; 1121a8d2903SMasahiro Yamada /* fall through */ 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_of_serial_setup(struct device *dev, struct uart_port *port, 1591a8d2903SMasahiro Yamada struct uniphier8250_priv *priv) 1601a8d2903SMasahiro Yamada { 1611a8d2903SMasahiro Yamada int ret; 1621a8d2903SMasahiro Yamada u32 prop; 1631a8d2903SMasahiro Yamada struct device_node *np = dev->of_node; 1641a8d2903SMasahiro Yamada 1651a8d2903SMasahiro Yamada ret = of_alias_get_id(np, "serial"); 1661a8d2903SMasahiro Yamada if (ret < 0) { 1671a8d2903SMasahiro Yamada dev_err(dev, "failed to get alias id\n"); 1681a8d2903SMasahiro Yamada return ret; 1691a8d2903SMasahiro Yamada } 17039be40ceSMasahiro Yamada port->line = ret; 1711a8d2903SMasahiro Yamada 1721a8d2903SMasahiro Yamada /* Get clk rate through clk driver */ 1731a8d2903SMasahiro Yamada priv->clk = devm_clk_get(dev, NULL); 1741a8d2903SMasahiro Yamada if (IS_ERR(priv->clk)) { 1751a8d2903SMasahiro Yamada dev_err(dev, "failed to get clock\n"); 1761a8d2903SMasahiro Yamada return PTR_ERR(priv->clk); 1771a8d2903SMasahiro Yamada } 1781a8d2903SMasahiro Yamada 1791a8d2903SMasahiro Yamada ret = clk_prepare_enable(priv->clk); 1801a8d2903SMasahiro Yamada if (ret < 0) 1811a8d2903SMasahiro Yamada return ret; 1821a8d2903SMasahiro Yamada 1831a8d2903SMasahiro Yamada port->uartclk = clk_get_rate(priv->clk); 1841a8d2903SMasahiro Yamada 1851a8d2903SMasahiro Yamada return 0; 1861a8d2903SMasahiro Yamada } 1871a8d2903SMasahiro Yamada 1881a8d2903SMasahiro Yamada static int uniphier_uart_probe(struct platform_device *pdev) 1891a8d2903SMasahiro Yamada { 1901a8d2903SMasahiro Yamada struct device *dev = &pdev->dev; 1911a8d2903SMasahiro Yamada struct uart_8250_port up; 1921a8d2903SMasahiro Yamada struct uniphier8250_priv *priv; 1931a8d2903SMasahiro Yamada struct resource *regs; 1941a8d2903SMasahiro Yamada void __iomem *membase; 1951a8d2903SMasahiro Yamada int irq; 1961a8d2903SMasahiro Yamada int ret; 1971a8d2903SMasahiro Yamada 1981a8d2903SMasahiro Yamada regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1991a8d2903SMasahiro Yamada if (!regs) { 2000ead21adSDenys Vlasenko dev_err(dev, "failed to get memory resource\n"); 2011a8d2903SMasahiro Yamada return -EINVAL; 2021a8d2903SMasahiro Yamada } 2031a8d2903SMasahiro Yamada 2041a8d2903SMasahiro Yamada membase = devm_ioremap(dev, regs->start, resource_size(regs)); 2051a8d2903SMasahiro Yamada if (!membase) 2061a8d2903SMasahiro Yamada return -ENOMEM; 2071a8d2903SMasahiro Yamada 2081a8d2903SMasahiro Yamada irq = platform_get_irq(pdev, 0); 2091a8d2903SMasahiro Yamada if (irq < 0) { 2101681d211SMasahiro Yamada dev_err(dev, "failed to get IRQ number\n"); 2111a8d2903SMasahiro Yamada return irq; 2121a8d2903SMasahiro Yamada } 2131a8d2903SMasahiro Yamada 2141a8d2903SMasahiro Yamada priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 2151a8d2903SMasahiro Yamada if (!priv) 2161a8d2903SMasahiro Yamada return -ENOMEM; 2171a8d2903SMasahiro Yamada 2181a8d2903SMasahiro Yamada memset(&up, 0, sizeof(up)); 2191a8d2903SMasahiro Yamada 2201a8d2903SMasahiro Yamada ret = uniphier_of_serial_setup(dev, &up.port, priv); 2211a8d2903SMasahiro Yamada if (ret < 0) 2221a8d2903SMasahiro Yamada return ret; 2231a8d2903SMasahiro Yamada 2241a8d2903SMasahiro Yamada spin_lock_init(&priv->atomic_write_lock); 2251a8d2903SMasahiro Yamada 2261a8d2903SMasahiro Yamada up.port.dev = dev; 2271a8d2903SMasahiro Yamada up.port.private_data = priv; 2281a8d2903SMasahiro Yamada up.port.mapbase = regs->start; 2291a8d2903SMasahiro Yamada up.port.mapsize = resource_size(regs); 2301a8d2903SMasahiro Yamada up.port.membase = membase; 2311a8d2903SMasahiro Yamada up.port.irq = irq; 2321a8d2903SMasahiro Yamada 2331a8d2903SMasahiro Yamada up.port.type = PORT_16550A; 2341a8d2903SMasahiro Yamada up.port.iotype = UPIO_MEM32; 235*2fd8e454SMasahiro Yamada up.port.fifosize = 64; 23694cbb697SMasahiro Yamada up.port.regshift = UNIPHIER_UART_REGSHIFT; 2371a8d2903SMasahiro Yamada up.port.flags = UPF_FIXED_PORT | UPF_FIXED_TYPE; 2381a8d2903SMasahiro Yamada up.capabilities = UART_CAP_FIFO; 2391a8d2903SMasahiro Yamada 2401a8d2903SMasahiro Yamada up.port.serial_in = uniphier_serial_in; 2411a8d2903SMasahiro Yamada up.port.serial_out = uniphier_serial_out; 2421a8d2903SMasahiro Yamada up.dl_read = uniphier_serial_dl_read; 2431a8d2903SMasahiro Yamada up.dl_write = uniphier_serial_dl_write; 2441a8d2903SMasahiro Yamada 2457defa77dSWei Yongjun ret = serial8250_register_8250_port(&up); 2467defa77dSWei Yongjun if (ret < 0) { 2471a8d2903SMasahiro Yamada dev_err(dev, "failed to register 8250 port\n"); 248e70e69bfSMasahiro Yamada clk_disable_unprepare(priv->clk); 2491a8d2903SMasahiro Yamada return ret; 2501a8d2903SMasahiro Yamada } 2517defa77dSWei Yongjun priv->line = ret; 2521a8d2903SMasahiro Yamada 2531a8d2903SMasahiro Yamada platform_set_drvdata(pdev, priv); 2541a8d2903SMasahiro Yamada 2551a8d2903SMasahiro Yamada return 0; 2561a8d2903SMasahiro Yamada } 2571a8d2903SMasahiro Yamada 2581a8d2903SMasahiro Yamada static int uniphier_uart_remove(struct platform_device *pdev) 2591a8d2903SMasahiro Yamada { 2601a8d2903SMasahiro Yamada struct uniphier8250_priv *priv = platform_get_drvdata(pdev); 2611a8d2903SMasahiro Yamada 2621a8d2903SMasahiro Yamada serial8250_unregister_port(priv->line); 2631a8d2903SMasahiro Yamada clk_disable_unprepare(priv->clk); 2641a8d2903SMasahiro Yamada 2651a8d2903SMasahiro Yamada return 0; 2661a8d2903SMasahiro Yamada } 2671a8d2903SMasahiro Yamada 2683d16ddc1SMasahiro Yamada static int __maybe_unused uniphier_uart_suspend(struct device *dev) 2693d16ddc1SMasahiro Yamada { 2703d16ddc1SMasahiro Yamada struct uniphier8250_priv *priv = dev_get_drvdata(dev); 2713d16ddc1SMasahiro Yamada struct uart_8250_port *up = serial8250_get_port(priv->line); 2723d16ddc1SMasahiro Yamada 2733d16ddc1SMasahiro Yamada serial8250_suspend_port(priv->line); 2743d16ddc1SMasahiro Yamada 2753d16ddc1SMasahiro Yamada if (!uart_console(&up->port) || console_suspend_enabled) 2763d16ddc1SMasahiro Yamada clk_disable_unprepare(priv->clk); 2773d16ddc1SMasahiro Yamada 2783d16ddc1SMasahiro Yamada return 0; 2793d16ddc1SMasahiro Yamada } 2803d16ddc1SMasahiro Yamada 2813d16ddc1SMasahiro Yamada static int __maybe_unused uniphier_uart_resume(struct device *dev) 2823d16ddc1SMasahiro Yamada { 2833d16ddc1SMasahiro Yamada struct uniphier8250_priv *priv = dev_get_drvdata(dev); 2843d16ddc1SMasahiro Yamada struct uart_8250_port *up = serial8250_get_port(priv->line); 2853d16ddc1SMasahiro Yamada int ret; 2863d16ddc1SMasahiro Yamada 2873d16ddc1SMasahiro Yamada if (!uart_console(&up->port) || console_suspend_enabled) { 2883d16ddc1SMasahiro Yamada ret = clk_prepare_enable(priv->clk); 2893d16ddc1SMasahiro Yamada if (ret) 2903d16ddc1SMasahiro Yamada return ret; 2913d16ddc1SMasahiro Yamada } 2923d16ddc1SMasahiro Yamada 2933d16ddc1SMasahiro Yamada serial8250_resume_port(priv->line); 2943d16ddc1SMasahiro Yamada 2953d16ddc1SMasahiro Yamada return 0; 2963d16ddc1SMasahiro Yamada } 2973d16ddc1SMasahiro Yamada 2983d16ddc1SMasahiro Yamada static const struct dev_pm_ops uniphier_uart_pm_ops = { 2993d16ddc1SMasahiro Yamada SET_SYSTEM_SLEEP_PM_OPS(uniphier_uart_suspend, uniphier_uart_resume) 3003d16ddc1SMasahiro Yamada }; 3013d16ddc1SMasahiro Yamada 3021a8d2903SMasahiro Yamada static const struct of_device_id uniphier_uart_match[] = { 3031a8d2903SMasahiro Yamada { .compatible = "socionext,uniphier-uart" }, 3041a8d2903SMasahiro Yamada { /* sentinel */ } 3051a8d2903SMasahiro Yamada }; 3061a8d2903SMasahiro Yamada MODULE_DEVICE_TABLE(of, uniphier_uart_match); 3071a8d2903SMasahiro Yamada 3081a8d2903SMasahiro Yamada static struct platform_driver uniphier_uart_platform_driver = { 3091a8d2903SMasahiro Yamada .probe = uniphier_uart_probe, 3101a8d2903SMasahiro Yamada .remove = uniphier_uart_remove, 3111a8d2903SMasahiro Yamada .driver = { 3121a8d2903SMasahiro Yamada .name = "uniphier-uart", 3131a8d2903SMasahiro Yamada .of_match_table = uniphier_uart_match, 3143d16ddc1SMasahiro Yamada .pm = &uniphier_uart_pm_ops, 3151a8d2903SMasahiro Yamada }, 3161a8d2903SMasahiro Yamada }; 3171a8d2903SMasahiro Yamada module_platform_driver(uniphier_uart_platform_driver); 3181a8d2903SMasahiro Yamada 3191a8d2903SMasahiro Yamada MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>"); 3201a8d2903SMasahiro Yamada MODULE_DESCRIPTION("UniPhier UART driver"); 3211a8d2903SMasahiro Yamada MODULE_LICENSE("GPL"); 322