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 #if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
12 #include <linux/device.h>
13 #include <linux/module.h>
14 #include <linux/of_address.h>
15 #include <linux/of_irq.h>
16 #include <linux/of_platform.h>
17 #include <linux/tty.h>
18 #include <linux/tty_flip.h>
19 #include <linux/clk.h>
23 #define ASPEED_VUART_GCRA 0x20
24 #define ASPEED_VUART_GCRA_VUART_EN BIT(0)
25 #define ASPEED_VUART_GCRA_DISABLE_HOST_TX_DISCARD BIT(5)
26 #define ASPEED_VUART_GCRB 0x24
27 #define ASPEED_VUART_GCRB_HOST_SIRQ_MASK GENMASK(7, 4)
28 #define ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT 4
29 #define ASPEED_VUART_ADDRL 0x28
30 #define ASPEED_VUART_ADDRH 0x2c
37 struct timer_list unthrottle_timer
;
38 struct uart_8250_port
*port
;
42 * If we fill the tty flip buffers, we throttle the data ready interrupt
43 * to prevent dropped characters. This timeout defines how long we wait
44 * to (conditionally, depending on buffer state) unthrottle.
46 static const int unthrottle_timeout
= HZ
/10;
49 * The VUART is basically two UART 'front ends' connected by their FIFO
50 * (no actual serial line in between). One is on the BMC side (management
51 * controller) and one is on the host CPU side.
53 * It allows the BMC to provide to the host a "UART" that pipes into
54 * the BMC itself and can then be turned by the BMC into a network console
55 * of some sort for example.
57 * This driver is for the BMC side. The sysfs files allow the BMC
58 * userspace which owns the system configuration policy, to specify
59 * at what IO port and interrupt number the host side will appear
60 * to the host on the Host <-> BMC LPC bus. It could be different on a
61 * different system (though most of them use 3f8/4).
64 static ssize_t
lpc_address_show(struct device
*dev
,
65 struct device_attribute
*attr
, char *buf
)
67 struct aspeed_vuart
*vuart
= dev_get_drvdata(dev
);
70 addr
= (readb(vuart
->regs
+ ASPEED_VUART_ADDRH
) << 8) |
71 (readb(vuart
->regs
+ ASPEED_VUART_ADDRL
));
73 return snprintf(buf
, PAGE_SIZE
- 1, "0x%x\n", addr
);
76 static ssize_t
lpc_address_store(struct device
*dev
,
77 struct device_attribute
*attr
,
78 const char *buf
, size_t count
)
80 struct aspeed_vuart
*vuart
= dev_get_drvdata(dev
);
84 err
= kstrtoul(buf
, 0, &val
);
88 writeb(val
>> 8, vuart
->regs
+ ASPEED_VUART_ADDRH
);
89 writeb(val
>> 0, vuart
->regs
+ ASPEED_VUART_ADDRL
);
94 static DEVICE_ATTR_RW(lpc_address
);
96 static ssize_t
sirq_show(struct device
*dev
,
97 struct device_attribute
*attr
, char *buf
)
99 struct aspeed_vuart
*vuart
= dev_get_drvdata(dev
);
102 reg
= readb(vuart
->regs
+ ASPEED_VUART_GCRB
);
103 reg
&= ASPEED_VUART_GCRB_HOST_SIRQ_MASK
;
104 reg
>>= ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT
;
106 return snprintf(buf
, PAGE_SIZE
- 1, "%u\n", reg
);
109 static ssize_t
sirq_store(struct device
*dev
, struct device_attribute
*attr
,
110 const char *buf
, size_t count
)
112 struct aspeed_vuart
*vuart
= dev_get_drvdata(dev
);
117 err
= kstrtoul(buf
, 0, &val
);
121 val
<<= ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT
;
122 val
&= ASPEED_VUART_GCRB_HOST_SIRQ_MASK
;
124 reg
= readb(vuart
->regs
+ ASPEED_VUART_GCRB
);
125 reg
&= ~ASPEED_VUART_GCRB_HOST_SIRQ_MASK
;
127 writeb(reg
, vuart
->regs
+ ASPEED_VUART_GCRB
);
132 static DEVICE_ATTR_RW(sirq
);
134 static struct attribute
*aspeed_vuart_attrs
[] = {
136 &dev_attr_lpc_address
.attr
,
140 static const struct attribute_group aspeed_vuart_attr_group
= {
141 .attrs
= aspeed_vuart_attrs
,
144 static void aspeed_vuart_set_enabled(struct aspeed_vuart
*vuart
, bool enabled
)
146 u8 reg
= readb(vuart
->regs
+ ASPEED_VUART_GCRA
);
149 reg
|= ASPEED_VUART_GCRA_VUART_EN
;
151 reg
&= ~ASPEED_VUART_GCRA_VUART_EN
;
153 writeb(reg
, vuart
->regs
+ ASPEED_VUART_GCRA
);
156 static void aspeed_vuart_set_host_tx_discard(struct aspeed_vuart
*vuart
,
161 reg
= readb(vuart
->regs
+ ASPEED_VUART_GCRA
);
163 /* If the DISABLE_HOST_TX_DISCARD bit is set, discard is disabled */
165 reg
|= ASPEED_VUART_GCRA_DISABLE_HOST_TX_DISCARD
;
167 reg
&= ~ASPEED_VUART_GCRA_DISABLE_HOST_TX_DISCARD
;
169 writeb(reg
, vuart
->regs
+ ASPEED_VUART_GCRA
);
172 static int aspeed_vuart_startup(struct uart_port
*uart_port
)
174 struct uart_8250_port
*uart_8250_port
= up_to_u8250p(uart_port
);
175 struct aspeed_vuart
*vuart
= uart_8250_port
->port
.private_data
;
178 rc
= serial8250_do_startup(uart_port
);
182 aspeed_vuart_set_host_tx_discard(vuart
, false);
187 static void aspeed_vuart_shutdown(struct uart_port
*uart_port
)
189 struct uart_8250_port
*uart_8250_port
= up_to_u8250p(uart_port
);
190 struct aspeed_vuart
*vuart
= uart_8250_port
->port
.private_data
;
192 aspeed_vuart_set_host_tx_discard(vuart
, true);
194 serial8250_do_shutdown(uart_port
);
197 static void __aspeed_vuart_set_throttle(struct uart_8250_port
*up
,
200 unsigned char irqs
= UART_IER_RLSI
| UART_IER_RDI
;
205 serial_out(up
, UART_IER
, up
->ier
);
207 static void aspeed_vuart_set_throttle(struct uart_port
*port
, bool throttle
)
209 struct uart_8250_port
*up
= up_to_u8250p(port
);
212 spin_lock_irqsave(&port
->lock
, flags
);
213 __aspeed_vuart_set_throttle(up
, throttle
);
214 spin_unlock_irqrestore(&port
->lock
, flags
);
217 static void aspeed_vuart_throttle(struct uart_port
*port
)
219 aspeed_vuart_set_throttle(port
, true);
222 static void aspeed_vuart_unthrottle(struct uart_port
*port
)
224 aspeed_vuart_set_throttle(port
, false);
227 static void aspeed_vuart_unthrottle_exp(struct timer_list
*timer
)
229 struct aspeed_vuart
*vuart
= from_timer(vuart
, timer
, unthrottle_timer
);
230 struct uart_8250_port
*up
= vuart
->port
;
232 if (!tty_buffer_space_avail(&up
->port
.state
->port
)) {
233 mod_timer(&vuart
->unthrottle_timer
,
234 jiffies
+ unthrottle_timeout
);
238 aspeed_vuart_unthrottle(&up
->port
);
242 * Custom interrupt handler to manage finer-grained flow control. Although we
243 * have throttle/unthrottle callbacks, we've seen that the VUART device can
244 * deliver characters faster than the ldisc has a chance to check buffer space
245 * against the throttle threshold. This results in dropped characters before
248 * We do this by checking for flip buffer space before RX. If we have no space,
249 * throttle now and schedule an unthrottle for later, once the ldisc has had
250 * a chance to drain the buffers.
252 static int aspeed_vuart_handle_irq(struct uart_port
*port
)
254 struct uart_8250_port
*up
= up_to_u8250p(port
);
255 unsigned int iir
, lsr
;
259 iir
= serial_port_in(port
, UART_IIR
);
261 if (iir
& UART_IIR_NO_INT
)
264 spin_lock_irqsave(&port
->lock
, flags
);
266 lsr
= serial_port_in(port
, UART_LSR
);
268 if (lsr
& (UART_LSR_DR
| UART_LSR_BI
)) {
269 space
= tty_buffer_space_avail(&port
->state
->port
);
272 /* throttle and schedule an unthrottle later */
273 struct aspeed_vuart
*vuart
= port
->private_data
;
274 __aspeed_vuart_set_throttle(up
, true);
276 if (!timer_pending(&vuart
->unthrottle_timer
)) {
278 mod_timer(&vuart
->unthrottle_timer
,
279 jiffies
+ unthrottle_timeout
);
283 count
= min(space
, 256);
286 serial8250_read_char(up
, lsr
);
287 lsr
= serial_in(up
, UART_LSR
);
290 } while (lsr
& (UART_LSR_DR
| UART_LSR_BI
));
292 tty_flip_buffer_push(&port
->state
->port
);
296 serial8250_modem_status(up
);
297 if (lsr
& UART_LSR_THRE
)
298 serial8250_tx_chars(up
);
300 uart_unlock_and_check_sysrq(port
, flags
);
305 static int aspeed_vuart_probe(struct platform_device
*pdev
)
307 struct uart_8250_port port
;
308 struct aspeed_vuart
*vuart
;
309 struct device_node
*np
;
310 struct resource
*res
;
314 np
= pdev
->dev
.of_node
;
316 vuart
= devm_kzalloc(&pdev
->dev
, sizeof(*vuart
), GFP_KERNEL
);
320 vuart
->dev
= &pdev
->dev
;
321 timer_setup(&vuart
->unthrottle_timer
, aspeed_vuart_unthrottle_exp
, 0);
323 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
324 vuart
->regs
= devm_ioremap_resource(&pdev
->dev
, res
);
325 if (IS_ERR(vuart
->regs
))
326 return PTR_ERR(vuart
->regs
);
328 memset(&port
, 0, sizeof(port
));
329 port
.port
.private_data
= vuart
;
330 port
.port
.membase
= vuart
->regs
;
331 port
.port
.mapbase
= res
->start
;
332 port
.port
.mapsize
= resource_size(res
);
333 port
.port
.startup
= aspeed_vuart_startup
;
334 port
.port
.shutdown
= aspeed_vuart_shutdown
;
335 port
.port
.throttle
= aspeed_vuart_throttle
;
336 port
.port
.unthrottle
= aspeed_vuart_unthrottle
;
337 port
.port
.status
= UPSTAT_SYNC_FIFO
;
338 port
.port
.dev
= &pdev
->dev
;
340 rc
= sysfs_create_group(&vuart
->dev
->kobj
, &aspeed_vuart_attr_group
);
344 if (of_property_read_u32(np
, "clock-frequency", &clk
)) {
345 vuart
->clk
= devm_clk_get(&pdev
->dev
, NULL
);
346 if (IS_ERR(vuart
->clk
)) {
348 "clk or clock-frequency not defined\n");
349 rc
= PTR_ERR(vuart
->clk
);
350 goto err_sysfs_remove
;
353 rc
= clk_prepare_enable(vuart
->clk
);
355 goto err_sysfs_remove
;
357 clk
= clk_get_rate(vuart
->clk
);
360 /* If current-speed was set, then try not to change it. */
361 if (of_property_read_u32(np
, "current-speed", &prop
) == 0)
362 port
.port
.custom_divisor
= clk
/ (16 * prop
);
364 /* Check for shifted address mapping */
365 if (of_property_read_u32(np
, "reg-offset", &prop
) == 0)
366 port
.port
.mapbase
+= prop
;
368 /* Check for registers offset within the devices address range */
369 if (of_property_read_u32(np
, "reg-shift", &prop
) == 0)
370 port
.port
.regshift
= prop
;
372 /* Check for fifo size */
373 if (of_property_read_u32(np
, "fifo-size", &prop
) == 0)
374 port
.port
.fifosize
= prop
;
376 /* Check for a fixed line number */
377 rc
= of_alias_get_id(np
, "serial");
381 port
.port
.irq
= irq_of_parse_and_map(np
, 0);
382 port
.port
.irqflags
= IRQF_SHARED
;
383 port
.port
.handle_irq
= aspeed_vuart_handle_irq
;
384 port
.port
.iotype
= UPIO_MEM
;
385 port
.port
.type
= PORT_16550A
;
386 port
.port
.uartclk
= clk
;
387 port
.port
.flags
= UPF_SHARE_IRQ
| UPF_BOOT_AUTOCONF
388 | UPF_FIXED_PORT
| UPF_FIXED_TYPE
| UPF_NO_THRE_TEST
;
390 if (of_property_read_bool(np
, "no-loopback-test"))
391 port
.port
.flags
|= UPF_SKIP_TEST
;
393 if (port
.port
.fifosize
)
394 port
.capabilities
= UART_CAP_FIFO
;
396 if (of_property_read_bool(np
, "auto-flow-control"))
397 port
.capabilities
|= UART_CAP_AFE
;
399 rc
= serial8250_register_8250_port(&port
);
401 goto err_clk_disable
;
405 aspeed_vuart_set_enabled(vuart
, true);
406 aspeed_vuart_set_host_tx_discard(vuart
, true);
407 platform_set_drvdata(pdev
, vuart
);
412 clk_disable_unprepare(vuart
->clk
);
413 irq_dispose_mapping(port
.port
.irq
);
415 sysfs_remove_group(&vuart
->dev
->kobj
, &aspeed_vuart_attr_group
);
419 static int aspeed_vuart_remove(struct platform_device
*pdev
)
421 struct aspeed_vuart
*vuart
= platform_get_drvdata(pdev
);
423 del_timer_sync(&vuart
->unthrottle_timer
);
424 aspeed_vuart_set_enabled(vuart
, false);
425 serial8250_unregister_port(vuart
->line
);
426 sysfs_remove_group(&vuart
->dev
->kobj
, &aspeed_vuart_attr_group
);
427 clk_disable_unprepare(vuart
->clk
);
432 static const struct of_device_id aspeed_vuart_table
[] = {
433 { .compatible
= "aspeed,ast2400-vuart" },
434 { .compatible
= "aspeed,ast2500-vuart" },
438 static struct platform_driver aspeed_vuart_driver
= {
440 .name
= "aspeed-vuart",
441 .of_match_table
= aspeed_vuart_table
,
443 .probe
= aspeed_vuart_probe
,
444 .remove
= aspeed_vuart_remove
,
447 module_platform_driver(aspeed_vuart_driver
);
449 MODULE_AUTHOR("Jeremy Kerr <jk@ozlabs.org>");
450 MODULE_LICENSE("GPL");
451 MODULE_DESCRIPTION("Driver for Aspeed VUART device");