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