Linux-libre 4.19.116-gnu
[librecmc/linux-libre.git] / drivers / tty / serial / 8250 / 8250_aspeed_vuart.c
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.handle_irq = aspeed_vuart_handle_irq;
379         port.port.iotype = UPIO_MEM;
380         port.port.type = PORT_16550A;
381         port.port.uartclk = clk;
382         port.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF
383                 | UPF_FIXED_PORT | UPF_FIXED_TYPE | UPF_NO_THRE_TEST;
384
385         if (of_property_read_bool(np, "no-loopback-test"))
386                 port.port.flags |= UPF_SKIP_TEST;
387
388         if (port.port.fifosize)
389                 port.capabilities = UART_CAP_FIFO;
390
391         if (of_property_read_bool(np, "auto-flow-control"))
392                 port.capabilities |= UART_CAP_AFE;
393
394         rc = serial8250_register_8250_port(&port);
395         if (rc < 0)
396                 goto err_clk_disable;
397
398         vuart->line = rc;
399
400         aspeed_vuart_set_enabled(vuart, true);
401         aspeed_vuart_set_host_tx_discard(vuart, true);
402         platform_set_drvdata(pdev, vuart);
403
404         return 0;
405
406 err_clk_disable:
407         clk_disable_unprepare(vuart->clk);
408         irq_dispose_mapping(port.port.irq);
409 err_sysfs_remove:
410         sysfs_remove_group(&vuart->dev->kobj, &aspeed_vuart_attr_group);
411         return rc;
412 }
413
414 static int aspeed_vuart_remove(struct platform_device *pdev)
415 {
416         struct aspeed_vuart *vuart = platform_get_drvdata(pdev);
417
418         del_timer_sync(&vuart->unthrottle_timer);
419         aspeed_vuart_set_enabled(vuart, false);
420         serial8250_unregister_port(vuart->line);
421         sysfs_remove_group(&vuart->dev->kobj, &aspeed_vuart_attr_group);
422         clk_disable_unprepare(vuart->clk);
423
424         return 0;
425 }
426
427 static const struct of_device_id aspeed_vuart_table[] = {
428         { .compatible = "aspeed,ast2400-vuart" },
429         { .compatible = "aspeed,ast2500-vuart" },
430         { },
431 };
432
433 static struct platform_driver aspeed_vuart_driver = {
434         .driver = {
435                 .name = "aspeed-vuart",
436                 .of_match_table = aspeed_vuart_table,
437         },
438         .probe = aspeed_vuart_probe,
439         .remove = aspeed_vuart_remove,
440 };
441
442 module_platform_driver(aspeed_vuart_driver);
443
444 MODULE_AUTHOR("Jeremy Kerr <jk@ozlabs.org>");
445 MODULE_LICENSE("GPL");
446 MODULE_DESCRIPTION("Driver for Aspeed VUART device");