1 /*
2  * xen/drivers/char/pl011.c
3  *
4  * Driver for ARM PrimeCell PL011 UART.
5  *
6  * Tim Deegan <tim@xen.org>
7  * Copyright (c) 2011 Citrix Systems.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  */
19 
20 #include <xen/console.h>
21 #include <xen/serial.h>
22 #include <xen/init.h>
23 #include <xen/irq.h>
24 #include <xen/device_tree.h>
25 #include <xen/errno.h>
26 #include <asm/device.h>
27 #include <xen/mm.h>
28 #include <xen/vmap.h>
29 #include <asm/pl011-uart.h>
30 #include <asm/io.h>
31 
32 static struct pl011 {
33     unsigned int data_bits, parity, stop_bits;
34     unsigned int irq;
35     void __iomem *regs;
36     /* UART with IRQ line: interrupt-driven I/O. */
37     struct irqaction irqaction;
38     struct vuart_info vuart;
39     /* /\* UART with no IRQ line: periodically-polled I/O. *\/ */
40     /* struct timer timer; */
41     /* unsigned int timeout_ms; */
42     /* bool probing, intr_works; */
43     bool sbsa;  /* ARM SBSA generic interface */
44     bool mmio32; /* 32-bit only MMIO */
45 } pl011_com = {0};
46 
47 /* These parity settings can be ORed directly into the LCR. */
48 #define PARITY_NONE  (0)
49 #define PARITY_ODD   (PEN)
50 #define PARITY_EVEN  (PEN|EPS)
51 #define PARITY_MARK  (PEN|SPS)
52 #define PARITY_SPACE (PEN|EPS|SPS)
53 
54 /*
55  * By default, PL011 accesses shall be done using 8/16-bit accessors to
56  * support legacy devices that cannot cope with 32-bit. On the other hand,
57  * there are implementations of PL011 that can only handle 32-bit MMIO. Also,
58  * SBSA v2.x requires 32-bit accesses. Note that for default case, we use
59  * largest-common accessors (i.e. 16-bit) not to end up using different ones
60  * depending on the actual register size.
61  */
62 static inline void
pl011_write(struct pl011 * uart,unsigned int offset,unsigned int val)63 pl011_write(struct pl011 *uart, unsigned int offset, unsigned int val)
64 {
65     if ( uart->mmio32 )
66         writel(val, uart->regs + offset);
67     else
68         writew(val, uart->regs + offset);
69 }
70 
pl011_read(struct pl011 * uart,unsigned int offset)71 static inline unsigned int pl011_read(struct pl011 *uart, unsigned int offset)
72 {
73     if ( uart->mmio32 )
74         return readl(uart->regs + offset);
75 
76     return readw(uart->regs + offset);
77 }
78 
pl011_intr_status(struct pl011 * uart)79 static unsigned int pl011_intr_status(struct pl011 *uart)
80 {
81     /* UARTMIS is not documented in SBSA v2.x, so use UARTRIS/UARTIMSC. */
82     return (pl011_read(uart, RIS) & pl011_read(uart, IMSC));
83 }
84 
pl011_interrupt(int irq,void * data)85 static void pl011_interrupt(int irq, void *data)
86 {
87     struct serial_port *port = data;
88     struct pl011 *uart = port->uart;
89     unsigned int status = pl011_intr_status(uart);
90 
91     if ( status )
92     {
93         do
94         {
95             pl011_write(uart, ICR, status & ~(TXI|RTI|RXI));
96 
97             if ( status & (RTI|RXI) )
98                 serial_rx_interrupt(port);
99 
100             /* TODO
101                 if ( status & (DSRMI|DCDMI|CTSMI|RIMI) )
102                 ...
103             */
104 
105             if ( status & (TXI) )
106                 serial_tx_interrupt(port);
107 
108             status = pl011_intr_status(uart);
109         } while (status != 0);
110     }
111 }
112 
pl011_init_preirq(struct serial_port * port)113 static void __init pl011_init_preirq(struct serial_port *port)
114 {
115     struct pl011 *uart = port->uart;
116     unsigned int cr;
117 
118     /* No interrupts, please. */
119     pl011_write(uart, IMSC, 0);
120 
121     if ( !uart->sbsa )
122     {
123         /* Definitely no DMA */
124         pl011_write(uart, DMACR, 0x0);
125 
126         /* This write must follow FBRD and IBRD writes. */
127         pl011_write(uart, LCR_H, (uart->data_bits - 5) << 5
128                                 | FEN
129                                 | ((uart->stop_bits - 1) << 3)
130                                 | uart->parity);
131     }
132     /* Clear errors */
133     pl011_write(uart, RSR, 0);
134 
135     /* Mask and clear the interrupts */
136     pl011_write(uart, IMSC, 0);
137     pl011_write(uart, ICR, ALLI);
138 
139     if ( !uart->sbsa )
140     {
141         /* Enable the UART for RX and TX; keep RTS and DTR */
142         cr = pl011_read(uart, CR);
143         cr &= RTS | DTR;
144         pl011_write(uart, CR, cr | RXE | TXE | UARTEN);
145     }
146 }
147 
pl011_init_postirq(struct serial_port * port)148 static void __init pl011_init_postirq(struct serial_port *port)
149 {
150     struct pl011 *uart = port->uart;
151     int rc;
152 
153     if ( uart->irq > 0 )
154     {
155         uart->irqaction.handler = pl011_interrupt;
156         uart->irqaction.name    = "pl011";
157         uart->irqaction.dev_id  = port;
158         if ( (rc = setup_irq(uart->irq, 0, &uart->irqaction)) != 0 )
159             printk("ERROR: Failed to allocate pl011 IRQ %d\n", uart->irq);
160     }
161 
162     /* Clear pending error interrupts */
163     pl011_write(uart, ICR, OEI|BEI|PEI|FEI);
164 
165     /* Unmask interrupts */
166     pl011_write(uart, IMSC, RTI|OEI|BEI|PEI|FEI|TXI|RXI);
167 }
168 
pl011_tx_ready(struct serial_port * port)169 static int pl011_tx_ready(struct serial_port *port)
170 {
171     struct pl011 *uart = port->uart;
172 
173     return ((pl011_read(uart, FR) & TXFE) ? 16 : 0);
174 }
175 
pl011_putc(struct serial_port * port,char c)176 static void pl011_putc(struct serial_port *port, char c)
177 {
178     struct pl011 *uart = port->uart;
179 
180     pl011_write(uart, DR, (uint32_t)(unsigned char)c);
181 }
182 
pl011_getc(struct serial_port * port,char * pc)183 static int pl011_getc(struct serial_port *port, char *pc)
184 {
185     struct pl011 *uart = port->uart;
186 
187     if ( pl011_read(uart, FR) & RXFE )
188         return 0;
189 
190     *pc = pl011_read(uart, DR) & 0xff;
191     return 1;
192 }
193 
pl011_irq(struct serial_port * port)194 static int __init pl011_irq(struct serial_port *port)
195 {
196     struct pl011 *uart = port->uart;
197 
198     return ((uart->irq > 0) ? uart->irq : -1);
199 }
200 
pl011_vuart(struct serial_port * port)201 static const struct vuart_info *pl011_vuart(struct serial_port *port)
202 {
203     struct pl011 *uart = port->uart;
204 
205     return &uart->vuart;
206 }
207 
pl011_tx_stop(struct serial_port * port)208 static void pl011_tx_stop(struct serial_port *port)
209 {
210     struct pl011 *uart = port->uart;
211 
212     pl011_write(uart, IMSC, pl011_read(uart, IMSC) & ~(TXI));
213 }
214 
pl011_tx_start(struct serial_port * port)215 static void pl011_tx_start(struct serial_port *port)
216 {
217     struct pl011 *uart = port->uart;
218 
219     pl011_write(uart, IMSC, pl011_read(uart, IMSC) | (TXI));
220 }
221 
222 static struct uart_driver __read_mostly pl011_driver = {
223     .init_preirq  = pl011_init_preirq,
224     .init_postirq = pl011_init_postirq,
225     .tx_ready     = pl011_tx_ready,
226     .putc         = pl011_putc,
227     .getc         = pl011_getc,
228     .irq          = pl011_irq,
229     .start_tx     = pl011_tx_start,
230     .stop_tx      = pl011_tx_stop,
231     .vuart_info   = pl011_vuart,
232 };
233 
234 static int __init
pl011_uart_init(int irq,paddr_t addr,paddr_t size,bool sbsa,bool mmio32)235 pl011_uart_init(int irq, paddr_t addr, paddr_t size, bool sbsa, bool mmio32)
236 {
237     struct pl011 *uart;
238 
239     uart = &pl011_com;
240     uart->irq       = irq;
241     uart->data_bits = 8;
242     uart->parity    = PARITY_NONE;
243     uart->stop_bits = 1;
244     uart->sbsa      = sbsa;
245 
246     /* Set 32-bit MMIO also for SBSA since v2.x requires it */
247     uart->mmio32 = (mmio32 || sbsa);
248 
249     uart->regs = ioremap_nocache(addr, size);
250     if ( !uart->regs )
251     {
252         printk("pl011: Unable to map the UART memory\n");
253         return -ENOMEM;
254     }
255 
256     uart->vuart.base_addr = addr;
257     uart->vuart.size = size;
258     uart->vuart.data_off = DR;
259     uart->vuart.status_off = FR;
260     uart->vuart.status = 0;
261 
262     /* Register with generic serial driver. */
263     serial_register_uart(SERHND_DTUART, &pl011_driver, uart);
264 
265     return 0;
266 }
267 
268 /* TODO: Parse UART config from the command line */
pl011_dt_uart_init(struct dt_device_node * dev,const void * data)269 static int __init pl011_dt_uart_init(struct dt_device_node *dev,
270                                      const void *data)
271 {
272     const char *config = data;
273     int res;
274     paddr_t addr, size;
275     uint32_t io_width;
276     bool mmio32 = false, sbsa;
277 
278     if ( strcmp(config, "") )
279     {
280         printk("WARNING: UART configuration is not supported\n");
281     }
282 
283     res = dt_device_get_paddr(dev, 0, &addr, &size);
284     if ( res )
285     {
286         printk("pl011: Unable to retrieve the base"
287                " address of the UART\n");
288         return res;
289     }
290 
291     res = platform_get_irq(dev, 0);
292     if ( res < 0 )
293     {
294         printk("pl011: Unable to retrieve the IRQ\n");
295         return -EINVAL;
296     }
297 
298     /* See linux Documentation/devicetree/bindings/serial/pl011.yaml */
299     if ( dt_property_read_u32(dev, "reg-io-width", &io_width) )
300     {
301         if ( io_width == 4 )
302             mmio32 = true;
303         else if ( io_width != 1 )
304         {
305             printk("pl011: Unsupported reg-io-width (%"PRIu32")\n", io_width);
306             return -EINVAL;
307         }
308     }
309 
310     sbsa = dt_device_is_compatible(dev, "arm,sbsa-uart");
311 
312     res = pl011_uart_init(res, addr, size, sbsa, mmio32);
313     if ( res < 0 )
314     {
315         printk("pl011: Unable to initialize\n");
316         return res;
317     }
318 
319     dt_device_set_used_by(dev, DOMID_XEN);
320 
321     return 0;
322 }
323 
324 static const struct dt_device_match pl011_dt_match[] __initconst =
325 {
326     DT_MATCH_COMPATIBLE("arm,pl011"),
327     /* No need for a separate struct as SBSA UART is a subset of PL011 */
328     DT_MATCH_COMPATIBLE("arm,sbsa-uart"),
329     { /* sentinel */ },
330 };
331 
332 DT_DEVICE_START(pl011, "PL011 UART", DEVICE_SERIAL)
333         .dt_match = pl011_dt_match,
334         .init = pl011_dt_uart_init,
335 DT_DEVICE_END
336 
337 #ifdef CONFIG_ACPI
338 #include <xen/acpi.h>
339 
340 static int __init pl011_acpi_uart_init(const void *data)
341 {
342     acpi_status status;
343     struct acpi_table_spcr *spcr = NULL;
344     int res;
345     bool sbsa;
346 
347     status = acpi_get_table(ACPI_SIG_SPCR, 0,
348                             (struct acpi_table_header **)&spcr);
349 
350     if ( ACPI_FAILURE(status) )
351     {
352         printk("pl011: Failed to get SPCR table\n");
353         return -EINVAL;
354     }
355 
356     sbsa = (spcr->interface_type == ACPI_DBG2_SBSA ||
357             spcr->interface_type == ACPI_DBG2_SBSA_32);
358 
359     /* trigger/polarity information is not available in spcr */
360     irq_set_type(spcr->interrupt, IRQ_TYPE_LEVEL_HIGH);
361 
362     /* TODO - mmio32 proper handling (for now set to true) */
363     res = pl011_uart_init(spcr->interrupt, spcr->serial_port.address,
364                           PAGE_SIZE, sbsa, true);
365     if ( res < 0 )
366     {
367         printk("pl011: Unable to initialize\n");
368         return res;
369     }
370 
371     return 0;
372 }
373 
374 ACPI_DEVICE_START(apl011, "PL011 UART", DEVICE_SERIAL)
375         .class_type = ACPI_DBG2_PL011,
376         .init = pl011_acpi_uart_init,
377 ACPI_DEVICE_END
378 
379 ACPI_DEVICE_START(asbsa_uart, "SBSA UART", DEVICE_SERIAL)
380     .class_type = ACPI_DBG2_SBSA,
381     .init = pl011_acpi_uart_init,
382 ACPI_DEVICE_END
383 
384 ACPI_DEVICE_START(asbsa32_uart, "SBSA32 UART", DEVICE_SERIAL)
385     .class_type = ACPI_DBG2_SBSA_32,
386     .init = pl011_acpi_uart_init,
387 ACPI_DEVICE_END
388 
389 #endif
390 
391 /*
392  * Local variables:
393  * mode: C
394  * c-file-style: "BSD"
395  * c-basic-offset: 4
396  * indent-tabs-mode: nil
397  * End:
398  */
399