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/tty.h>
14 #include <linux/tty_flip.h>
15 #include <linux/clk.h>
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
33 struct timer_list unthrottle_timer
;
34 struct uart_8250_port
*port
;
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.
42 static const int unthrottle_timeout
= HZ
/10;
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.
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.
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).
60 static ssize_t
lpc_address_show(struct device
*dev
,
61 struct device_attribute
*attr
, char *buf
)
63 struct aspeed_vuart
*vuart
= dev_get_drvdata(dev
);
66 addr
= (readb(vuart
->regs
+ ASPEED_VUART_ADDRH
) << 8) |
67 (readb(vuart
->regs
+ ASPEED_VUART_ADDRL
));
69 return snprintf(buf
, PAGE_SIZE
- 1, "0x%x\n", addr
);
72 static ssize_t
lpc_address_store(struct device
*dev
,
73 struct device_attribute
*attr
,
74 const char *buf
, size_t count
)
76 struct aspeed_vuart
*vuart
= dev_get_drvdata(dev
);
80 err
= kstrtoul(buf
, 0, &val
);
84 writeb(val
>> 8, vuart
->regs
+ ASPEED_VUART_ADDRH
);
85 writeb(val
>> 0, vuart
->regs
+ ASPEED_VUART_ADDRL
);
90 static DEVICE_ATTR_RW(lpc_address
);
92 static ssize_t
sirq_show(struct device
*dev
,
93 struct device_attribute
*attr
, char *buf
)
95 struct aspeed_vuart
*vuart
= dev_get_drvdata(dev
);
98 reg
= readb(vuart
->regs
+ ASPEED_VUART_GCRB
);
99 reg
&= ASPEED_VUART_GCRB_HOST_SIRQ_MASK
;
100 reg
>>= ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT
;
102 return snprintf(buf
, PAGE_SIZE
- 1, "%u\n", reg
);
105 static ssize_t
sirq_store(struct device
*dev
, struct device_attribute
*attr
,
106 const char *buf
, size_t count
)
108 struct aspeed_vuart
*vuart
= dev_get_drvdata(dev
);
113 err
= kstrtoul(buf
, 0, &val
);
117 val
<<= ASPEED_VUART_GCRB_HOST_SIRQ_SHIFT
;
118 val
&= ASPEED_VUART_GCRB_HOST_SIRQ_MASK
;
120 reg
= readb(vuart
->regs
+ ASPEED_VUART_GCRB
);
121 reg
&= ~ASPEED_VUART_GCRB_HOST_SIRQ_MASK
;
123 writeb(reg
, vuart
->regs
+ ASPEED_VUART_GCRB
);
128 static DEVICE_ATTR_RW(sirq
);
130 static struct attribute
*aspeed_vuart_attrs
[] = {
132 &dev_attr_lpc_address
.attr
,
136 static const struct attribute_group aspeed_vuart_attr_group
= {
137 .attrs
= aspeed_vuart_attrs
,
140 static void aspeed_vuart_set_enabled(struct aspeed_vuart
*vuart
, bool enabled
)
142 u8 reg
= readb(vuart
->regs
+ ASPEED_VUART_GCRA
);
145 reg
|= ASPEED_VUART_GCRA_VUART_EN
;
147 reg
&= ~ASPEED_VUART_GCRA_VUART_EN
;
149 writeb(reg
, vuart
->regs
+ ASPEED_VUART_GCRA
);
152 static void aspeed_vuart_set_host_tx_discard(struct aspeed_vuart
*vuart
,
157 reg
= readb(vuart
->regs
+ ASPEED_VUART_GCRA
);
159 /* If the DISABLE_HOST_TX_DISCARD bit is set, discard is disabled */
161 reg
|= ASPEED_VUART_GCRA_DISABLE_HOST_TX_DISCARD
;
163 reg
&= ~ASPEED_VUART_GCRA_DISABLE_HOST_TX_DISCARD
;
165 writeb(reg
, vuart
->regs
+ ASPEED_VUART_GCRA
);
168 static int aspeed_vuart_startup(struct uart_port
*uart_port
)
170 struct uart_8250_port
*uart_8250_port
= up_to_u8250p(uart_port
);
171 struct aspeed_vuart
*vuart
= uart_8250_port
->port
.private_data
;
174 rc
= serial8250_do_startup(uart_port
);
178 aspeed_vuart_set_host_tx_discard(vuart
, false);
183 static void aspeed_vuart_shutdown(struct uart_port
*uart_port
)
185 struct uart_8250_port
*uart_8250_port
= up_to_u8250p(uart_port
);
186 struct aspeed_vuart
*vuart
= uart_8250_port
->port
.private_data
;
188 aspeed_vuart_set_host_tx_discard(vuart
, true);
190 serial8250_do_shutdown(uart_port
);
193 static void __aspeed_vuart_set_throttle(struct uart_8250_port
*up
,
196 unsigned char irqs
= UART_IER_RLSI
| UART_IER_RDI
;
201 serial_out(up
, UART_IER
, up
->ier
);
203 static void aspeed_vuart_set_throttle(struct uart_port
*port
, bool throttle
)
205 struct uart_8250_port
*up
= up_to_u8250p(port
);
208 spin_lock_irqsave(&port
->lock
, flags
);
209 __aspeed_vuart_set_throttle(up
, throttle
);
210 spin_unlock_irqrestore(&port
->lock
, flags
);
213 static void aspeed_vuart_throttle(struct uart_port
*port
)
215 aspeed_vuart_set_throttle(port
, true);
218 static void aspeed_vuart_unthrottle(struct uart_port
*port
)
220 aspeed_vuart_set_throttle(port
, false);
223 static void aspeed_vuart_unthrottle_exp(struct timer_list
*timer
)
225 struct aspeed_vuart
*vuart
= from_timer(vuart
, timer
, unthrottle_timer
);
226 struct uart_8250_port
*up
= vuart
->port
;
228 if (!tty_buffer_space_avail(&up
->port
.state
->port
)) {
229 mod_timer(&vuart
->unthrottle_timer
,
230 jiffies
+ unthrottle_timeout
);
234 aspeed_vuart_unthrottle(&up
->port
);
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
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.
248 static int aspeed_vuart_handle_irq(struct uart_port
*port
)
250 struct uart_8250_port
*up
= up_to_u8250p(port
);
251 unsigned int iir
, lsr
;
255 iir
= serial_port_in(port
, UART_IIR
);
257 if (iir
& UART_IIR_NO_INT
)
260 spin_lock_irqsave(&port
->lock
, flags
);
262 lsr
= serial_port_in(port
, UART_LSR
);
264 if (lsr
& (UART_LSR_DR
| UART_LSR_BI
)) {
265 space
= tty_buffer_space_avail(&port
->state
->port
);
268 /* throttle and schedule an unthrottle later */
269 struct aspeed_vuart
*vuart
= port
->private_data
;
270 __aspeed_vuart_set_throttle(up
, true);
272 if (!timer_pending(&vuart
->unthrottle_timer
)) {
274 mod_timer(&vuart
->unthrottle_timer
,
275 jiffies
+ unthrottle_timeout
);
279 count
= min(space
, 256);
282 serial8250_read_char(up
, lsr
);
283 lsr
= serial_in(up
, UART_LSR
);
286 } while (lsr
& (UART_LSR_DR
| UART_LSR_BI
));
288 tty_flip_buffer_push(&port
->state
->port
);
292 serial8250_modem_status(up
);
293 if (lsr
& UART_LSR_THRE
)
294 serial8250_tx_chars(up
);
296 spin_unlock_irqrestore(&port
->lock
, flags
);
301 static int aspeed_vuart_probe(struct platform_device
*pdev
)
303 struct uart_8250_port port
;
304 struct aspeed_vuart
*vuart
;
305 struct device_node
*np
;
306 struct resource
*res
;
310 np
= pdev
->dev
.of_node
;
312 vuart
= devm_kzalloc(&pdev
->dev
, sizeof(*vuart
), GFP_KERNEL
);
316 vuart
->dev
= &pdev
->dev
;
317 timer_setup(&vuart
->unthrottle_timer
, aspeed_vuart_unthrottle_exp
, 0);
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
);
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
;
336 rc
= sysfs_create_group(&vuart
->dev
->kobj
, &aspeed_vuart_attr_group
);
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
)) {
344 "clk or clock-frequency not defined\n");
345 rc
= PTR_ERR(vuart
->clk
);
346 goto err_sysfs_remove
;
349 rc
= clk_prepare_enable(vuart
->clk
);
351 goto err_sysfs_remove
;
353 clk
= clk_get_rate(vuart
->clk
);
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
);
360 /* Check for shifted address mapping */
361 if (of_property_read_u32(np
, "reg-offset", &prop
) == 0)
362 port
.port
.mapbase
+= prop
;
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
;
368 /* Check for fifo size */
369 if (of_property_read_u32(np
, "fifo-size", &prop
) == 0)
370 port
.port
.fifosize
= prop
;
372 /* Check for a fixed line number */
373 rc
= of_alias_get_id(np
, "serial");
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
;
386 if (of_property_read_bool(np
, "no-loopback-test"))
387 port
.port
.flags
|= UPF_SKIP_TEST
;
389 if (port
.port
.fifosize
)
390 port
.capabilities
= UART_CAP_FIFO
;
392 if (of_property_read_bool(np
, "auto-flow-control"))
393 port
.capabilities
|= UART_CAP_AFE
;
395 rc
= serial8250_register_8250_port(&port
);
397 goto err_clk_disable
;
401 aspeed_vuart_set_enabled(vuart
, true);
402 aspeed_vuart_set_host_tx_discard(vuart
, true);
403 platform_set_drvdata(pdev
, vuart
);
408 clk_disable_unprepare(vuart
->clk
);
409 irq_dispose_mapping(port
.port
.irq
);
411 sysfs_remove_group(&vuart
->dev
->kobj
, &aspeed_vuart_attr_group
);
415 static int aspeed_vuart_remove(struct platform_device
*pdev
)
417 struct aspeed_vuart
*vuart
= platform_get_drvdata(pdev
);
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
);
428 static const struct of_device_id aspeed_vuart_table
[] = {
429 { .compatible
= "aspeed,ast2400-vuart" },
430 { .compatible
= "aspeed,ast2500-vuart" },
434 static struct platform_driver aspeed_vuart_driver
= {
436 .name
= "aspeed-vuart",
437 .of_match_table
= aspeed_vuart_table
,
439 .probe
= aspeed_vuart_probe
,
440 .remove
= aspeed_vuart_remove
,
443 module_platform_driver(aspeed_vuart_driver
);
445 MODULE_AUTHOR("Jeremy Kerr <jk@ozlabs.org>");
446 MODULE_LICENSE("GPL");
447 MODULE_DESCRIPTION("Driver for Aspeed VUART device");