xref: /linux/drivers/tty/serial/8250/8250_uniphier.c (revision 4b4193256c8d3bc3a5397b5cd9494c2ad386317d)
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