1 // SPDX-License-Identifier: GPL-2.0+
3 * Serial Port driver for Aspeed VUART device
5 * Copyright (C) 2016 Jeremy Kerr <jk@ozlabs.org>, IBM Corp.
6 * Copyright (C) 2006 Arnd Bergmann <arnd@arndb.de>, IBM Corp.
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>
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
31 #define ASPEED_VUART_DEFAULT_LPC_ADDR 0x3f8
32 #define ASPEED_VUART_DEFAULT_SIRQ 4
33 #define ASPEED_VUART_DEFAULT_SIRQ_POLARITY IRQ_TYPE_LEVEL_LOW
40 struct timer_list unthrottle_timer;
41 struct uart_8250_port *port;
45 * If we fill the tty flip buffers, we throttle the data ready interrupt
46 * to prevent dropped characters. This timeout defines how long we wait
47 * to (conditionally, depending on buffer state) unthrottle.
49 static const int unthrottle_timeout = HZ/10;
52 * The VUART is basically two UART 'front ends' connected by their FIFO
53 * (no actual serial line in between). One is on the BMC side (management
54 * controller) and one is on the host CPU side.
56 * It allows the BMC to provide to the host a "UART" that pipes into
57 * the BMC itself and can then be turned by the BMC into a network console
58 * of some sort for example.
60 * This driver is for the BMC side. The sysfs files allow the BMC
61 * userspace which owns the system configuration policy, to specify
62 * at what IO port and interrupt number the host side will appear
63 * to the host on the Host <-> BMC LPC bus. It could be different on a
64 * different system (though most of them use 3f8/4).
67 static ssize_t lpc_address_show(struct device *dev,
68 struct device_attribute *attr, char *buf)
70 struct aspeed_vuart *vuart = dev_get_drvdata(dev);
73 addr = (readb(vuart->regs + ASPEED_VUART_ADDRH) << 8) |
74 (readb(vuart->regs + ASPEED_VUART_ADDRL));
76 return snprintf(buf, PAGE_SIZE - 1, "0x%x\n", addr);
79 static int aspeed_vuart_set_lpc_address(struct aspeed_vuart *vuart, u32 addr)
84 writeb(addr >> 8, vuart->regs + ASPEED_VUART_ADDRH);
85 writeb(addr >> 0, vuart->regs + ASPEED_VUART_ADDRL);
90 static ssize_t lpc_address_store(struct device *dev,
91 struct device_attribute *attr,
92 const char *buf, size_t count)
94 struct aspeed_vuart *vuart = dev_get_drvdata(dev);
98 err = kstrtou32(buf, 0, &val);
102 err = aspeed_vuart_set_lpc_address(vuart, val);
103 return err ? : count;
106 static DEVICE_ATTR_RW(lpc_address);
108 static ssize_t sirq_show(struct device *dev,
109 struct device_attribute *attr, char *buf)
111 struct aspeed_vuart *vuart = dev_get_drvdata(dev);
114 reg = readb(vuart->regs + ASPEED_VUART_GCRB);
115 reg &= ASPEED_VUART_GCRB_HOST_SIRQ_MASK;
116 reg >>= ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT;
118 return snprintf(buf, PAGE_SIZE - 1, "%u\n", reg);
121 static int aspeed_vuart_set_sirq(struct aspeed_vuart *vuart, u32 sirq)
125 if (sirq > (ASPEED_VUART_GCRB_HOST_SIRQ_MASK >> ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT))
128 sirq <<= ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT;
129 sirq &= ASPEED_VUART_GCRB_HOST_SIRQ_MASK;
131 reg = readb(vuart->regs + ASPEED_VUART_GCRB);
132 reg &= ~ASPEED_VUART_GCRB_HOST_SIRQ_MASK;
134 writeb(reg, vuart->regs + ASPEED_VUART_GCRB);
139 static ssize_t sirq_store(struct device *dev, struct device_attribute *attr,
140 const char *buf, size_t count)
142 struct aspeed_vuart *vuart = dev_get_drvdata(dev);
146 err = kstrtoul(buf, 0, &val);
150 err = aspeed_vuart_set_sirq(vuart, val);
151 return err ? : count;
154 static DEVICE_ATTR_RW(sirq);
156 static ssize_t sirq_polarity_show(struct device *dev,
157 struct device_attribute *attr, char *buf)
159 struct aspeed_vuart *vuart = dev_get_drvdata(dev);
162 reg = readb(vuart->regs + ASPEED_VUART_GCRA);
163 reg &= ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY;
165 return snprintf(buf, PAGE_SIZE - 1, "%u\n", reg ? 1 : 0);
168 static void aspeed_vuart_set_sirq_polarity(struct aspeed_vuart *vuart,
171 u8 reg = readb(vuart->regs + ASPEED_VUART_GCRA);
174 reg |= ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY;
176 reg &= ~ASPEED_VUART_GCRA_HOST_SIRQ_POLARITY;
178 writeb(reg, vuart->regs + ASPEED_VUART_GCRA);
181 static ssize_t sirq_polarity_store(struct device *dev,
182 struct device_attribute *attr,
183 const char *buf, size_t count)
185 struct aspeed_vuart *vuart = dev_get_drvdata(dev);
189 err = kstrtoul(buf, 0, &val);
193 aspeed_vuart_set_sirq_polarity(vuart, val != 0);
198 static DEVICE_ATTR_RW(sirq_polarity);
200 static struct attribute *aspeed_vuart_attrs[] = {
202 &dev_attr_sirq_polarity.attr,
203 &dev_attr_lpc_address.attr,
207 static const struct attribute_group aspeed_vuart_attr_group = {
208 .attrs = aspeed_vuart_attrs,
211 static void aspeed_vuart_set_enabled(struct aspeed_vuart *vuart, bool enabled)
213 u8 reg = readb(vuart->regs + ASPEED_VUART_GCRA);
216 reg |= ASPEED_VUART_GCRA_VUART_EN;
218 reg &= ~ASPEED_VUART_GCRA_VUART_EN;
220 writeb(reg, vuart->regs + ASPEED_VUART_GCRA);
223 static void aspeed_vuart_set_host_tx_discard(struct aspeed_vuart *vuart,
228 reg = readb(vuart->regs + ASPEED_VUART_GCRA);
230 /* If the DISABLE_HOST_TX_DISCARD bit is set, discard is disabled */
232 reg |= ASPEED_VUART_GCRA_DISABLE_HOST_TX_DISCARD;
234 reg &= ~ASPEED_VUART_GCRA_DISABLE_HOST_TX_DISCARD;
236 writeb(reg, vuart->regs + ASPEED_VUART_GCRA);
239 static int aspeed_vuart_startup(struct uart_port *uart_port)
241 struct uart_8250_port *uart_8250_port = up_to_u8250p(uart_port);
242 struct aspeed_vuart *vuart = uart_8250_port->port.private_data;
245 rc = serial8250_do_startup(uart_port);
249 aspeed_vuart_set_host_tx_discard(vuart, false);
254 static void aspeed_vuart_shutdown(struct uart_port *uart_port)
256 struct uart_8250_port *uart_8250_port = up_to_u8250p(uart_port);
257 struct aspeed_vuart *vuart = uart_8250_port->port.private_data;
259 aspeed_vuart_set_host_tx_discard(vuart, true);
261 serial8250_do_shutdown(uart_port);
264 static void __aspeed_vuart_set_throttle(struct uart_8250_port *up,
267 unsigned char irqs = UART_IER_RLSI | UART_IER_RDI;
272 serial_out(up, UART_IER, up->ier);
274 static void aspeed_vuart_set_throttle(struct uart_port *port, bool throttle)
276 struct uart_8250_port *up = up_to_u8250p(port);
279 spin_lock_irqsave(&port->lock, flags);
280 __aspeed_vuart_set_throttle(up, throttle);
281 spin_unlock_irqrestore(&port->lock, flags);
284 static void aspeed_vuart_throttle(struct uart_port *port)
286 aspeed_vuart_set_throttle(port, true);
289 static void aspeed_vuart_unthrottle(struct uart_port *port)
291 aspeed_vuart_set_throttle(port, false);
294 static void aspeed_vuart_unthrottle_exp(struct timer_list *timer)
296 struct aspeed_vuart *vuart = from_timer(vuart, timer, unthrottle_timer);
297 struct uart_8250_port *up = vuart->port;
299 if (!tty_buffer_space_avail(&up->port.state->port)) {
300 mod_timer(&vuart->unthrottle_timer,
301 jiffies + unthrottle_timeout);
305 aspeed_vuart_unthrottle(&up->port);
309 * Custom interrupt handler to manage finer-grained flow control. Although we
310 * have throttle/unthrottle callbacks, we've seen that the VUART device can
311 * deliver characters faster than the ldisc has a chance to check buffer space
312 * against the throttle threshold. This results in dropped characters before
315 * We do this by checking for flip buffer space before RX. If we have no space,
316 * throttle now and schedule an unthrottle for later, once the ldisc has had
317 * a chance to drain the buffers.
319 static int aspeed_vuart_handle_irq(struct uart_port *port)
321 struct uart_8250_port *up = up_to_u8250p(port);
322 unsigned int iir, lsr;
325 iir = serial_port_in(port, UART_IIR);
327 if (iir & UART_IIR_NO_INT)
330 spin_lock(&port->lock);
332 lsr = serial_port_in(port, UART_LSR);
334 if (lsr & (UART_LSR_DR | UART_LSR_BI)) {
335 space = tty_buffer_space_avail(&port->state->port);
338 /* throttle and schedule an unthrottle later */
339 struct aspeed_vuart *vuart = port->private_data;
340 __aspeed_vuart_set_throttle(up, true);
342 if (!timer_pending(&vuart->unthrottle_timer)) {
344 mod_timer(&vuart->unthrottle_timer,
345 jiffies + unthrottle_timeout);
349 count = min(space, 256);
352 serial8250_read_char(up, lsr);
353 lsr = serial_in(up, UART_LSR);
356 } while (lsr & (UART_LSR_DR | UART_LSR_BI));
358 tty_flip_buffer_push(&port->state->port);
362 serial8250_modem_status(up);
363 if (lsr & UART_LSR_THRE)
364 serial8250_tx_chars(up);
366 uart_unlock_and_check_sysrq(port);
371 static void aspeed_vuart_auto_configure_sirq_polarity(
372 struct aspeed_vuart *vuart, struct device_node *syscon_np,
373 u32 reg_offset, u32 reg_mask)
375 struct regmap *regmap;
378 regmap = syscon_node_to_regmap(syscon_np);
379 if (IS_ERR(regmap)) {
381 "could not get regmap for aspeed,sirq-polarity-sense\n");
384 if (regmap_read(regmap, reg_offset, &value)) {
385 dev_warn(vuart->dev, "could not read hw strap table\n");
389 aspeed_vuart_set_sirq_polarity(vuart, (value & reg_mask) == 0);
392 static int aspeed_vuart_map_irq_polarity(u32 dt)
395 case IRQ_TYPE_LEVEL_LOW:
397 case IRQ_TYPE_LEVEL_HIGH:
404 static int aspeed_vuart_probe(struct platform_device *pdev)
406 struct of_phandle_args sirq_polarity_sense_args;
407 struct uart_8250_port port;
408 struct aspeed_vuart *vuart;
409 struct device_node *np;
410 struct resource *res;
411 u32 clk, prop, sirq[2];
412 int rc, sirq_polarity;
414 np = pdev->dev.of_node;
416 vuart = devm_kzalloc(&pdev->dev, sizeof(*vuart), GFP_KERNEL);
420 vuart->dev = &pdev->dev;
421 timer_setup(&vuart->unthrottle_timer, aspeed_vuart_unthrottle_exp, 0);
423 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
424 vuart->regs = devm_ioremap_resource(&pdev->dev, res);
425 if (IS_ERR(vuart->regs))
426 return PTR_ERR(vuart->regs);
428 memset(&port, 0, sizeof(port));
429 port.port.private_data = vuart;
430 port.port.membase = vuart->regs;
431 port.port.mapbase = res->start;
432 port.port.mapsize = resource_size(res);
433 port.port.startup = aspeed_vuart_startup;
434 port.port.shutdown = aspeed_vuart_shutdown;
435 port.port.throttle = aspeed_vuart_throttle;
436 port.port.unthrottle = aspeed_vuart_unthrottle;
437 port.port.status = UPSTAT_SYNC_FIFO;
438 port.port.dev = &pdev->dev;
439 port.port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE);
441 rc = sysfs_create_group(&vuart->dev->kobj, &aspeed_vuart_attr_group);
445 if (of_property_read_u32(np, "clock-frequency", &clk)) {
446 vuart->clk = devm_clk_get(&pdev->dev, NULL);
447 if (IS_ERR(vuart->clk)) {
449 "clk or clock-frequency not defined\n");
450 rc = PTR_ERR(vuart->clk);
451 goto err_sysfs_remove;
454 rc = clk_prepare_enable(vuart->clk);
456 goto err_sysfs_remove;
458 clk = clk_get_rate(vuart->clk);
461 /* If current-speed was set, then try not to change it. */
462 if (of_property_read_u32(np, "current-speed", &prop) == 0)
463 port.port.custom_divisor = clk / (16 * prop);
465 /* Check for shifted address mapping */
466 if (of_property_read_u32(np, "reg-offset", &prop) == 0)
467 port.port.mapbase += prop;
469 /* Check for registers offset within the devices address range */
470 if (of_property_read_u32(np, "reg-shift", &prop) == 0)
471 port.port.regshift = prop;
473 /* Check for fifo size */
474 if (of_property_read_u32(np, "fifo-size", &prop) == 0)
475 port.port.fifosize = prop;
477 /* Check for a fixed line number */
478 rc = of_alias_get_id(np, "serial");
482 port.port.irq = irq_of_parse_and_map(np, 0);
483 port.port.handle_irq = aspeed_vuart_handle_irq;
484 port.port.iotype = UPIO_MEM;
485 port.port.type = PORT_16550A;
486 port.port.uartclk = clk;
487 port.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF
488 | UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_NO_THRE_TEST;
490 if (of_property_read_bool(np, "no-loopback-test"))
491 port.port.flags |= UPF_SKIP_TEST;
493 if (port.port.fifosize)
494 port.capabilities = UART_CAP_FIFO;
496 if (of_property_read_bool(np, "auto-flow-control"))
497 port.capabilities |= UART_CAP_AFE;
499 rc = serial8250_register_8250_port(&port);
501 goto err_clk_disable;
505 rc = of_parse_phandle_with_fixed_args(
506 np, "aspeed,sirq-polarity-sense", 2, 0,
507 &sirq_polarity_sense_args);
510 "aspeed,sirq-polarity-sense property not found\n");
512 aspeed_vuart_auto_configure_sirq_polarity(
513 vuart, sirq_polarity_sense_args.np,
514 sirq_polarity_sense_args.args[0],
515 BIT(sirq_polarity_sense_args.args[1]));
516 of_node_put(sirq_polarity_sense_args.np);
519 rc = of_property_read_u32(np, "aspeed,lpc-io-reg", &prop);
521 prop = ASPEED_VUART_DEFAULT_LPC_ADDR;
523 rc = aspeed_vuart_set_lpc_address(vuart, prop);
525 dev_err(&pdev->dev, "invalid value in aspeed,lpc-io-reg property\n");
526 goto err_clk_disable;
529 rc = of_property_read_u32_array(np, "aspeed,lpc-interrupts", sirq, 2);
531 sirq[0] = ASPEED_VUART_DEFAULT_SIRQ;
532 sirq[1] = ASPEED_VUART_DEFAULT_SIRQ_POLARITY;
535 rc = aspeed_vuart_set_sirq(vuart, sirq[0]);
537 dev_err(&pdev->dev, "invalid sirq number in aspeed,lpc-interrupts property\n");
538 goto err_clk_disable;
541 sirq_polarity = aspeed_vuart_map_irq_polarity(sirq[1]);
542 if (sirq_polarity < 0) {
543 dev_err(&pdev->dev, "invalid sirq polarity in aspeed,lpc-interrupts property\n");
545 goto err_clk_disable;
548 aspeed_vuart_set_sirq_polarity(vuart, sirq_polarity);
550 aspeed_vuart_set_enabled(vuart, true);
551 aspeed_vuart_set_host_tx_discard(vuart, true);
552 platform_set_drvdata(pdev, vuart);
557 clk_disable_unprepare(vuart->clk);
558 irq_dispose_mapping(port.port.irq);
560 sysfs_remove_group(&vuart->dev->kobj, &aspeed_vuart_attr_group);
564 static int aspeed_vuart_remove(struct platform_device *pdev)
566 struct aspeed_vuart *vuart = platform_get_drvdata(pdev);
568 del_timer_sync(&vuart->unthrottle_timer);
569 aspeed_vuart_set_enabled(vuart, false);
570 serial8250_unregister_port(vuart->line);
571 sysfs_remove_group(&vuart->dev->kobj, &aspeed_vuart_attr_group);
572 clk_disable_unprepare(vuart->clk);
577 static const struct of_device_id aspeed_vuart_table[] = {
578 { .compatible = "aspeed,ast2400-vuart" },
579 { .compatible = "aspeed,ast2500-vuart" },
583 static struct platform_driver aspeed_vuart_driver = {
585 .name = "aspeed-vuart",
586 .of_match_table = aspeed_vuart_table,
588 .probe = aspeed_vuart_probe,
589 .remove = aspeed_vuart_remove,
592 module_platform_driver(aspeed_vuart_driver);
594 MODULE_AUTHOR("Jeremy Kerr <jk@ozlabs.org>");
595 MODULE_LICENSE("GPL");
596 MODULE_DESCRIPTION("Driver for Aspeed VUART device");