1// SPDX-License-Identifier: GPL-2.0+
2/*
3 *  Serial Port driver for Aspeed VUART device
4 *
5 *    Copyright (C) 2016 Jeremy Kerr <jk@ozlabs.org>, IBM Corp.
6 *    Copyright (C) 2006 Arnd Bergmann <arnd@arndb.de>, IBM Corp.
7 */
8#include <linux/device.h>
9#include <linux/module.h>
10#include <linux/of_address.h>
11#include <linux/of_irq.h>
12#include <linux/of_platform.h>
13#include <linux/regmap.h>
14#include <linux/mfd/syscon.h>
15#include <linux/tty.h>
16#include <linux/tty_flip.h>
17#include <linux/clk.h>
18
19#include "8250.h"
20
21#define ASPEED_VUART_GCRA		0x20
22#define ASPEED_VUART_GCRA_VUART_EN		BIT(0)
23#define ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY	BIT(1)
24#define ASPEED_VUART_GCRA_DISABLE_HOST_TX_DISCARD BIT(5)
25#define ASPEED_VUART_GCRB		0x24
26#define ASPEED_VUART_GCRB_HOST_SIRQ_MASK	GENMASK(7, 4)
27#define ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT	4
28#define ASPEED_VUART_ADDRL		0x28
29#define ASPEED_VUART_ADDRH		0x2c
30
31struct aspeed_vuart {
32	struct device		*dev;
33	void __iomem		*regs;
34	struct clk		*clk;
35	int			line;
36	struct timer_list	unthrottle_timer;
37	struct uart_8250_port	*port;
38};
39
40/*
41 * If we fill the tty flip buffers, we throttle the data ready interrupt
42 * to prevent dropped characters. This timeout defines how long we wait
43 * to (conditionally, depending on buffer state) unthrottle.
44 */
45static const int unthrottle_timeout = HZ/10;
46
47/*
48 * The VUART is basically two UART 'front ends' connected by their FIFO
49 * (no actual serial line in between). One is on the BMC side (management
50 * controller) and one is on the host CPU side.
51 *
52 * It allows the BMC to provide to the host a "UART" that pipes into
53 * the BMC itself and can then be turned by the BMC into a network console
54 * of some sort for example.
55 *
56 * This driver is for the BMC side. The sysfs files allow the BMC
57 * userspace which owns the system configuration policy, to specify
58 * at what IO port and interrupt number the host side will appear
59 * to the host on the Host <-> BMC LPC bus. It could be different on a
60 * different system (though most of them use 3f8/4).
61 */
62
63static ssize_t lpc_address_show(struct device *dev,
64				struct device_attribute *attr, char *buf)
65{
66	struct aspeed_vuart *vuart = dev_get_drvdata(dev);
67	u16 addr;
68
69	addr = (readb(vuart->regs + ASPEED_VUART_ADDRH) << 8) |
70		(readb(vuart->regs + ASPEED_VUART_ADDRL));
71
72	return snprintf(buf, PAGE_SIZE - 1, "0x%x\n", addr);
73}
74
75static ssize_t lpc_address_store(struct device *dev,
76				 struct device_attribute *attr,
77				 const char *buf, size_t count)
78{
79	struct aspeed_vuart *vuart = dev_get_drvdata(dev);
80	unsigned long val;
81	int err;
82
83	err = kstrtoul(buf, 0, &val);
84	if (err)
85		return err;
86
87	writeb(val >> 8, vuart->regs + ASPEED_VUART_ADDRH);
88	writeb(val >> 0, vuart->regs + ASPEED_VUART_ADDRL);
89
90	return count;
91}
92
93static DEVICE_ATTR_RW(lpc_address);
94
95static ssize_t sirq_show(struct device *dev,
96			 struct device_attribute *attr, char *buf)
97{
98	struct aspeed_vuart *vuart = dev_get_drvdata(dev);
99	u8 reg;
100
101	reg = readb(vuart->regs + ASPEED_VUART_GCRB);
102	reg &= ASPEED_VUART_GCRB_HOST_SIRQ_MASK;
103	reg >>= ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT;
104
105	return snprintf(buf, PAGE_SIZE - 1, "%u\n", reg);
106}
107
108static ssize_t sirq_store(struct device *dev, struct device_attribute *attr,
109			  const char *buf, size_t count)
110{
111	struct aspeed_vuart *vuart = dev_get_drvdata(dev);
112	unsigned long val;
113	int err;
114	u8 reg;
115
116	err = kstrtoul(buf, 0, &val);
117	if (err)
118		return err;
119
120	val <<= ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT;
121	val &= ASPEED_VUART_GCRB_HOST_SIRQ_MASK;
122
123	reg = readb(vuart->regs + ASPEED_VUART_GCRB);
124	reg &= ~ASPEED_VUART_GCRB_HOST_SIRQ_MASK;
125	reg |= val;
126	writeb(reg, vuart->regs + ASPEED_VUART_GCRB);
127
128	return count;
129}
130
131static DEVICE_ATTR_RW(sirq);
132
133static ssize_t sirq_polarity_show(struct device *dev,
134				  struct device_attribute *attr, char *buf)
135{
136	struct aspeed_vuart *vuart = dev_get_drvdata(dev);
137	u8 reg;
138
139	reg = readb(vuart->regs + ASPEED_VUART_GCRA);
140	reg &= ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY;
141
142	return snprintf(buf, PAGE_SIZE - 1, "%u\n", reg ? 1 : 0);
143}
144
145static void aspeed_vuart_set_sirq_polarity(struct aspeed_vuart *vuart,
146					   bool polarity)
147{
148	u8 reg = readb(vuart->regs + ASPEED_VUART_GCRA);
149
150	if (polarity)
151		reg |= ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY;
152	else
153		reg &= ~ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY;
154
155	writeb(reg, vuart->regs + ASPEED_VUART_GCRA);
156}
157
158static ssize_t sirq_polarity_store(struct device *dev,
159				   struct device_attribute *attr,
160				   const char *buf, size_t count)
161{
162	struct aspeed_vuart *vuart = dev_get_drvdata(dev);
163	unsigned long val;
164	int err;
165
166	err = kstrtoul(buf, 0, &val);
167	if (err)
168		return err;
169
170	aspeed_vuart_set_sirq_polarity(vuart, val != 0);
171
172	return count;
173}
174
175static DEVICE_ATTR_RW(sirq_polarity);
176
177static struct attribute *aspeed_vuart_attrs[] = {
178	&dev_attr_sirq.attr,
179	&dev_attr_sirq_polarity.attr,
180	&dev_attr_lpc_address.attr,
181	NULL,
182};
183
184static const struct attribute_group aspeed_vuart_attr_group = {
185	.attrs = aspeed_vuart_attrs,
186};
187
188static void aspeed_vuart_set_enabled(struct aspeed_vuart *vuart, bool enabled)
189{
190	u8 reg = readb(vuart->regs + ASPEED_VUART_GCRA);
191
192	if (enabled)
193		reg |= ASPEED_VUART_GCRA_VUART_EN;
194	else
195		reg &= ~ASPEED_VUART_GCRA_VUART_EN;
196
197	writeb(reg, vuart->regs + ASPEED_VUART_GCRA);
198}
199
200static void aspeed_vuart_set_host_tx_discard(struct aspeed_vuart *vuart,
201					     bool discard)
202{
203	u8 reg;
204
205	reg = readb(vuart->regs + ASPEED_VUART_GCRA);
206
207	/* If the DISABLE_HOST_TX_DISCARD bit is set, discard is disabled */
208	if (!discard)
209		reg |= ASPEED_VUART_GCRA_DISABLE_HOST_TX_DISCARD;
210	else
211		reg &= ~ASPEED_VUART_GCRA_DISABLE_HOST_TX_DISCARD;
212
213	writeb(reg, vuart->regs + ASPEED_VUART_GCRA);
214}
215
216static int aspeed_vuart_startup(struct uart_port *uart_port)
217{
218	struct uart_8250_port *uart_8250_port = up_to_u8250p(uart_port);
219	struct aspeed_vuart *vuart = uart_8250_port->port.private_data;
220	int rc;
221
222	rc = serial8250_do_startup(uart_port);
223	if (rc)
224		return rc;
225
226	aspeed_vuart_set_host_tx_discard(vuart, false);
227
228	return 0;
229}
230
231static void aspeed_vuart_shutdown(struct uart_port *uart_port)
232{
233	struct uart_8250_port *uart_8250_port = up_to_u8250p(uart_port);
234	struct aspeed_vuart *vuart = uart_8250_port->port.private_data;
235
236	aspeed_vuart_set_host_tx_discard(vuart, true);
237
238	serial8250_do_shutdown(uart_port);
239}
240
241static void __aspeed_vuart_set_throttle(struct uart_8250_port *up,
242		bool throttle)
243{
244	unsigned char irqs = UART_IER_RLSI | UART_IER_RDI;
245
246	up->ier &= ~irqs;
247	if (!throttle)
248		up->ier |= irqs;
249	serial_out(up, UART_IER, up->ier);
250}
251static void aspeed_vuart_set_throttle(struct uart_port *port, bool throttle)
252{
253	struct uart_8250_port *up = up_to_u8250p(port);
254	unsigned long flags;
255
256	spin_lock_irqsave(&port->lock, flags);
257	__aspeed_vuart_set_throttle(up, throttle);
258	spin_unlock_irqrestore(&port->lock, flags);
259}
260
261static void aspeed_vuart_throttle(struct uart_port *port)
262{
263	aspeed_vuart_set_throttle(port, true);
264}
265
266static void aspeed_vuart_unthrottle(struct uart_port *port)
267{
268	aspeed_vuart_set_throttle(port, false);
269}
270
271static void aspeed_vuart_unthrottle_exp(struct timer_list *timer)
272{
273	struct aspeed_vuart *vuart = from_timer(vuart, timer, unthrottle_timer);
274	struct uart_8250_port *up = vuart->port;
275
276	if (!tty_buffer_space_avail(&up->port.state->port)) {
277		mod_timer(&vuart->unthrottle_timer,
278			  jiffies + unthrottle_timeout);
279		return;
280	}
281
282	aspeed_vuart_unthrottle(&up->port);
283}
284
285/*
286 * Custom interrupt handler to manage finer-grained flow control. Although we
287 * have throttle/unthrottle callbacks, we've seen that the VUART device can
288 * deliver characters faster than the ldisc has a chance to check buffer space
289 * against the throttle threshold. This results in dropped characters before
290 * the throttle.
291 *
292 * We do this by checking for flip buffer space before RX. If we have no space,
293 * throttle now and schedule an unthrottle for later, once the ldisc has had
294 * a chance to drain the buffers.
295 */
296static int aspeed_vuart_handle_irq(struct uart_port *port)
297{
298	struct uart_8250_port *up = up_to_u8250p(port);
299	unsigned int iir, lsr;
300	unsigned long flags;
301	int space, count;
302
303	iir = serial_port_in(port, UART_IIR);
304
305	if (iir & UART_IIR_NO_INT)
306		return 0;
307
308	spin_lock_irqsave(&port->lock, flags);
309
310	lsr = serial_port_in(port, UART_LSR);
311
312	if (lsr & (UART_LSR_DR | UART_LSR_BI)) {
313		space = tty_buffer_space_avail(&port->state->port);
314
315		if (!space) {
316			/* throttle and schedule an unthrottle later */
317			struct aspeed_vuart *vuart = port->private_data;
318			__aspeed_vuart_set_throttle(up, true);
319
320			if (!timer_pending(&vuart->unthrottle_timer)) {
321				vuart->port = up;
322				mod_timer(&vuart->unthrottle_timer,
323					  jiffies + unthrottle_timeout);
324			}
325
326		} else {
327			count = min(space, 256);
328
329			do {
330				serial8250_read_char(up, lsr);
331				lsr = serial_in(up, UART_LSR);
332				if (--count == 0)
333					break;
334			} while (lsr & (UART_LSR_DR | UART_LSR_BI));
335
336			tty_flip_buffer_push(&port->state->port);
337		}
338	}
339
340	serial8250_modem_status(up);
341	if (lsr & UART_LSR_THRE)
342		serial8250_tx_chars(up);
343
344	uart_unlock_and_check_sysrq(port, flags);
345
346	return 1;
347}
348
349static void aspeed_vuart_auto_configure_sirq_polarity(
350	struct aspeed_vuart *vuart, struct device_node *syscon_np,
351	u32 reg_offset, u32 reg_mask)
352{
353	struct regmap *regmap;
354	u32 value;
355
356	regmap = syscon_node_to_regmap(syscon_np);
357	if (IS_ERR(regmap)) {
358		dev_warn(vuart->dev,
359			 "could not get regmap for aspeed,sirq-polarity-sense\n");
360		return;
361	}
362	if (regmap_read(regmap, reg_offset, &value)) {
363		dev_warn(vuart->dev, "could not read hw strap table\n");
364		return;
365	}
366
367	aspeed_vuart_set_sirq_polarity(vuart, (value & reg_mask) == 0);
368}
369
370static int aspeed_vuart_probe(struct platform_device *pdev)
371{
372	struct of_phandle_args sirq_polarity_sense_args;
373	struct uart_8250_port port;
374	struct aspeed_vuart *vuart;
375	struct device_node *np;
376	struct resource *res;
377	u32 clk, prop;
378	int rc;
379
380	np = pdev->dev.of_node;
381
382	vuart = devm_kzalloc(&pdev->dev, sizeof(*vuart), GFP_KERNEL);
383	if (!vuart)
384		return -ENOMEM;
385
386	vuart->dev = &pdev->dev;
387	timer_setup(&vuart->unthrottle_timer, aspeed_vuart_unthrottle_exp, 0);
388
389	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
390	vuart->regs = devm_ioremap_resource(&pdev->dev, res);
391	if (IS_ERR(vuart->regs))
392		return PTR_ERR(vuart->regs);
393
394	memset(&port, 0, sizeof(port));
395	port.port.private_data = vuart;
396	port.port.membase = vuart->regs;
397	port.port.mapbase = res->start;
398	port.port.mapsize = resource_size(res);
399	port.port.startup = aspeed_vuart_startup;
400	port.port.shutdown = aspeed_vuart_shutdown;
401	port.port.throttle = aspeed_vuart_throttle;
402	port.port.unthrottle = aspeed_vuart_unthrottle;
403	port.port.status = UPSTAT_SYNC_FIFO;
404	port.port.dev = &pdev->dev;
405	port.port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE);
406	port.bugs |= UART_BUG_TXRACE;
407
408	rc = sysfs_create_group(&vuart->dev->kobj, &aspeed_vuart_attr_group);
409	if (rc < 0)
410		return rc;
411
412	if (of_property_read_u32(np, "clock-frequency", &clk)) {
413		vuart->clk = devm_clk_get(&pdev->dev, NULL);
414		if (IS_ERR(vuart->clk)) {
415			dev_warn(&pdev->dev,
416				"clk or clock-frequency not defined\n");
417			rc = PTR_ERR(vuart->clk);
418			goto err_sysfs_remove;
419		}
420
421		rc = clk_prepare_enable(vuart->clk);
422		if (rc < 0)
423			goto err_sysfs_remove;
424
425		clk = clk_get_rate(vuart->clk);
426	}
427
428	/* If current-speed was set, then try not to change it. */
429	if (of_property_read_u32(np, "current-speed", &prop) == 0)
430		port.port.custom_divisor = clk / (16 * prop);
431
432	/* Check for shifted address mapping */
433	if (of_property_read_u32(np, "reg-offset", &prop) == 0)
434		port.port.mapbase += prop;
435
436	/* Check for registers offset within the devices address range */
437	if (of_property_read_u32(np, "reg-shift", &prop) == 0)
438		port.port.regshift = prop;
439
440	/* Check for fifo size */
441	if (of_property_read_u32(np, "fifo-size", &prop) == 0)
442		port.port.fifosize = prop;
443
444	/* Check for a fixed line number */
445	rc = of_alias_get_id(np, "serial");
446	if (rc >= 0)
447		port.port.line = rc;
448
449	port.port.irq = irq_of_parse_and_map(np, 0);
450	port.port.handle_irq = aspeed_vuart_handle_irq;
451	port.port.iotype = UPIO_MEM;
452	port.port.type = PORT_16550A;
453	port.port.uartclk = clk;
454	port.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF
455		| UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_NO_THRE_TEST;
456
457	if (of_property_read_bool(np, "no-loopback-test"))
458		port.port.flags |= UPF_SKIP_TEST;
459
460	if (port.port.fifosize)
461		port.capabilities = UART_CAP_FIFO;
462
463	if (of_property_read_bool(np, "auto-flow-control"))
464		port.capabilities |= UART_CAP_AFE;
465
466	rc = serial8250_register_8250_port(&port);
467	if (rc < 0)
468		goto err_clk_disable;
469
470	vuart->line = rc;
471
472	rc = of_parse_phandle_with_fixed_args(
473		np, "aspeed,sirq-polarity-sense", 2, 0,
474		&sirq_polarity_sense_args);
475	if (rc < 0) {
476		dev_dbg(&pdev->dev,
477			"aspeed,sirq-polarity-sense property not found\n");
478	} else {
479		aspeed_vuart_auto_configure_sirq_polarity(
480			vuart, sirq_polarity_sense_args.np,
481			sirq_polarity_sense_args.args[0],
482			BIT(sirq_polarity_sense_args.args[1]));
483		of_node_put(sirq_polarity_sense_args.np);
484	}
485
486	aspeed_vuart_set_enabled(vuart, true);
487	aspeed_vuart_set_host_tx_discard(vuart, true);
488	platform_set_drvdata(pdev, vuart);
489
490	return 0;
491
492err_clk_disable:
493	clk_disable_unprepare(vuart->clk);
494	irq_dispose_mapping(port.port.irq);
495err_sysfs_remove:
496	sysfs_remove_group(&vuart->dev->kobj, &aspeed_vuart_attr_group);
497	return rc;
498}
499
500static int aspeed_vuart_remove(struct platform_device *pdev)
501{
502	struct aspeed_vuart *vuart = platform_get_drvdata(pdev);
503
504	del_timer_sync(&vuart->unthrottle_timer);
505	aspeed_vuart_set_enabled(vuart, false);
506	serial8250_unregister_port(vuart->line);
507	sysfs_remove_group(&vuart->dev->kobj, &aspeed_vuart_attr_group);
508	clk_disable_unprepare(vuart->clk);
509
510	return 0;
511}
512
513static const struct of_device_id aspeed_vuart_table[] = {
514	{ .compatible = "aspeed,ast2400-vuart" },
515	{ .compatible = "aspeed,ast2500-vuart" },
516	{ },
517};
518
519static struct platform_driver aspeed_vuart_driver = {
520	.driver = {
521		.name = "aspeed-vuart",
522		.of_match_table = aspeed_vuart_table,
523	},
524	.probe = aspeed_vuart_probe,
525	.remove = aspeed_vuart_remove,
526};
527
528module_platform_driver(aspeed_vuart_driver);
529
530MODULE_AUTHOR("Jeremy Kerr <jk@ozlabs.org>");
531MODULE_LICENSE("GPL");
532MODULE_DESCRIPTION("Driver for Aspeed VUART device");
533