xref: /linux/drivers/tty/serial/8250/8250_aspeed_vuart.c (revision 95298d63c67673c654c08952672d016212b26054)
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 
31 struct 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  */
45 static 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 
63 static 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 
75 static 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 
93 static DEVICE_ATTR_RW(lpc_address);
94 
95 static 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 
108 static 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 
131 static DEVICE_ATTR_RW(sirq);
132 
133 static 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 
145 static 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 
158 static 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 
175 static DEVICE_ATTR_RW(sirq_polarity);
176 
177 static 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 
184 static const struct attribute_group aspeed_vuart_attr_group = {
185 	.attrs = aspeed_vuart_attrs,
186 };
187 
188 static 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 
200 static 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 
216 static 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 
231 static 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 
241 static 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 }
251 static 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 
261 static void aspeed_vuart_throttle(struct uart_port *port)
262 {
263 	aspeed_vuart_set_throttle(port, true);
264 }
265 
266 static void aspeed_vuart_unthrottle(struct uart_port *port)
267 {
268 	aspeed_vuart_set_throttle(port, false);
269 }
270 
271 static 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  */
296 static 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 
349 static 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 
370 static 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 
407 	rc = sysfs_create_group(&vuart->dev->kobj, &aspeed_vuart_attr_group);
408 	if (rc < 0)
409 		return rc;
410 
411 	if (of_property_read_u32(np, "clock-frequency", &clk)) {
412 		vuart->clk = devm_clk_get(&pdev->dev, NULL);
413 		if (IS_ERR(vuart->clk)) {
414 			dev_warn(&pdev->dev,
415 				"clk or clock-frequency not defined\n");
416 			rc = PTR_ERR(vuart->clk);
417 			goto err_sysfs_remove;
418 		}
419 
420 		rc = clk_prepare_enable(vuart->clk);
421 		if (rc < 0)
422 			goto err_sysfs_remove;
423 
424 		clk = clk_get_rate(vuart->clk);
425 	}
426 
427 	/* If current-speed was set, then try not to change it. */
428 	if (of_property_read_u32(np, "current-speed", &prop) == 0)
429 		port.port.custom_divisor = clk / (16 * prop);
430 
431 	/* Check for shifted address mapping */
432 	if (of_property_read_u32(np, "reg-offset", &prop) == 0)
433 		port.port.mapbase += prop;
434 
435 	/* Check for registers offset within the devices address range */
436 	if (of_property_read_u32(np, "reg-shift", &prop) == 0)
437 		port.port.regshift = prop;
438 
439 	/* Check for fifo size */
440 	if (of_property_read_u32(np, "fifo-size", &prop) == 0)
441 		port.port.fifosize = prop;
442 
443 	/* Check for a fixed line number */
444 	rc = of_alias_get_id(np, "serial");
445 	if (rc >= 0)
446 		port.port.line = rc;
447 
448 	port.port.irq = irq_of_parse_and_map(np, 0);
449 	port.port.handle_irq = aspeed_vuart_handle_irq;
450 	port.port.iotype = UPIO_MEM;
451 	port.port.type = PORT_16550A;
452 	port.port.uartclk = clk;
453 	port.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF
454 		| UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_NO_THRE_TEST;
455 
456 	if (of_property_read_bool(np, "no-loopback-test"))
457 		port.port.flags |= UPF_SKIP_TEST;
458 
459 	if (port.port.fifosize)
460 		port.capabilities = UART_CAP_FIFO;
461 
462 	if (of_property_read_bool(np, "auto-flow-control"))
463 		port.capabilities |= UART_CAP_AFE;
464 
465 	rc = serial8250_register_8250_port(&port);
466 	if (rc < 0)
467 		goto err_clk_disable;
468 
469 	vuart->line = rc;
470 
471 	rc = of_parse_phandle_with_fixed_args(
472 		np, "aspeed,sirq-polarity-sense", 2, 0,
473 		&sirq_polarity_sense_args);
474 	if (rc < 0) {
475 		dev_dbg(&pdev->dev,
476 			"aspeed,sirq-polarity-sense property not found\n");
477 	} else {
478 		aspeed_vuart_auto_configure_sirq_polarity(
479 			vuart, sirq_polarity_sense_args.np,
480 			sirq_polarity_sense_args.args[0],
481 			BIT(sirq_polarity_sense_args.args[1]));
482 		of_node_put(sirq_polarity_sense_args.np);
483 	}
484 
485 	aspeed_vuart_set_enabled(vuart, true);
486 	aspeed_vuart_set_host_tx_discard(vuart, true);
487 	platform_set_drvdata(pdev, vuart);
488 
489 	return 0;
490 
491 err_clk_disable:
492 	clk_disable_unprepare(vuart->clk);
493 	irq_dispose_mapping(port.port.irq);
494 err_sysfs_remove:
495 	sysfs_remove_group(&vuart->dev->kobj, &aspeed_vuart_attr_group);
496 	return rc;
497 }
498 
499 static int aspeed_vuart_remove(struct platform_device *pdev)
500 {
501 	struct aspeed_vuart *vuart = platform_get_drvdata(pdev);
502 
503 	del_timer_sync(&vuart->unthrottle_timer);
504 	aspeed_vuart_set_enabled(vuart, false);
505 	serial8250_unregister_port(vuart->line);
506 	sysfs_remove_group(&vuart->dev->kobj, &aspeed_vuart_attr_group);
507 	clk_disable_unprepare(vuart->clk);
508 
509 	return 0;
510 }
511 
512 static const struct of_device_id aspeed_vuart_table[] = {
513 	{ .compatible = "aspeed,ast2400-vuart" },
514 	{ .compatible = "aspeed,ast2500-vuart" },
515 	{ },
516 };
517 
518 static struct platform_driver aspeed_vuart_driver = {
519 	.driver = {
520 		.name = "aspeed-vuart",
521 		.of_match_table = aspeed_vuart_table,
522 	},
523 	.probe = aspeed_vuart_probe,
524 	.remove = aspeed_vuart_remove,
525 };
526 
527 module_platform_driver(aspeed_vuart_driver);
528 
529 MODULE_AUTHOR("Jeremy Kerr <jk@ozlabs.org>");
530 MODULE_LICENSE("GPL");
531 MODULE_DESCRIPTION("Driver for Aspeed VUART device");
532