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_t probing, intr_works; */
43     bool sbsa;  /* ARM SBSA generic interface */
44 } pl011_com = {0};
45 
46 /* These parity settings can be ORed directly into the LCR. */
47 #define PARITY_NONE  (0)
48 #define PARITY_ODD   (PEN)
49 #define PARITY_EVEN  (PEN|EPS)
50 #define PARITY_MARK  (PEN|SPS)
51 #define PARITY_SPACE (PEN|EPS|SPS)
52 
53 /* SBSA v2.x document requires, all reads/writes must be 32-bit accesses */
54 #define pl011_read(uart, off)           readl((uart)->regs + (off))
55 #define pl011_write(uart, off,val)      writel((val), (uart)->regs + (off))
56 
pl011_intr_status(struct pl011 * uart)57 static unsigned int pl011_intr_status(struct pl011 *uart)
58 {
59     /* UARTMIS is not documented in SBSA v2.x, so use UARTRIS/UARTIMSC. */
60     return (pl011_read(uart, RIS) & pl011_read(uart, IMSC));
61 }
62 
pl011_interrupt(int irq,void * data,struct cpu_user_regs * regs)63 static void pl011_interrupt(int irq, void *data, struct cpu_user_regs *regs)
64 {
65     struct serial_port *port = data;
66     struct pl011 *uart = port->uart;
67     unsigned int status = pl011_intr_status(uart);
68 
69     if ( status )
70     {
71         do
72         {
73             pl011_write(uart, ICR, status & ~(TXI|RTI|RXI));
74 
75             if ( status & (RTI|RXI) )
76                 serial_rx_interrupt(port, regs);
77 
78             /* TODO
79                 if ( status & (DSRMI|DCDMI|CTSMI|RIMI) )
80                 ...
81             */
82 
83             if ( status & (TXI) )
84                 serial_tx_interrupt(port, regs);
85 
86             status = pl011_intr_status(uart);
87         } while (status != 0);
88     }
89 }
90 
pl011_init_preirq(struct serial_port * port)91 static void __init pl011_init_preirq(struct serial_port *port)
92 {
93     struct pl011 *uart = port->uart;
94     unsigned int cr;
95 
96     /* No interrupts, please. */
97     pl011_write(uart, IMSC, 0);
98 
99     if ( !uart->sbsa )
100     {
101         /* Definitely no DMA */
102         pl011_write(uart, DMACR, 0x0);
103 
104         /* This write must follow FBRD and IBRD writes. */
105         pl011_write(uart, LCR_H, (uart->data_bits - 5) << 5
106                                 | FEN
107                                 | ((uart->stop_bits - 1) << 3)
108                                 | uart->parity);
109     }
110     /* Clear errors */
111     pl011_write(uart, RSR, 0);
112 
113     /* Mask and clear the interrupts */
114     pl011_write(uart, IMSC, 0);
115     pl011_write(uart, ICR, ALLI);
116 
117     if ( !uart->sbsa )
118     {
119         /* Enable the UART for RX and TX; keep RTS and DTR */
120         cr = pl011_read(uart, CR);
121         cr &= RTS | DTR;
122         pl011_write(uart, CR, cr | RXE | TXE | UARTEN);
123     }
124 }
125 
pl011_init_postirq(struct serial_port * port)126 static void __init pl011_init_postirq(struct serial_port *port)
127 {
128     struct pl011 *uart = port->uart;
129     int rc;
130 
131     if ( uart->irq > 0 )
132     {
133         uart->irqaction.handler = pl011_interrupt;
134         uart->irqaction.name    = "pl011";
135         uart->irqaction.dev_id  = port;
136         if ( (rc = setup_irq(uart->irq, 0, &uart->irqaction)) != 0 )
137             printk("ERROR: Failed to allocate pl011 IRQ %d\n", uart->irq);
138     }
139 
140     /* Clear pending error interrupts */
141     pl011_write(uart, ICR, OEI|BEI|PEI|FEI);
142 
143     /* Unmask interrupts */
144     pl011_write(uart, IMSC, RTI|OEI|BEI|PEI|FEI|TXI|RXI);
145 }
146 
pl011_suspend(struct serial_port * port)147 static void pl011_suspend(struct serial_port *port)
148 {
149     BUG(); // XXX
150 }
151 
pl011_resume(struct serial_port * port)152 static void pl011_resume(struct serial_port *port)
153 {
154     BUG(); // XXX
155 }
156 
pl011_tx_ready(struct serial_port * port)157 static int pl011_tx_ready(struct serial_port *port)
158 {
159     struct pl011 *uart = port->uart;
160 
161     return ((pl011_read(uart, FR) & TXFE) ? 16 : 0);
162 }
163 
pl011_putc(struct serial_port * port,char c)164 static void pl011_putc(struct serial_port *port, char c)
165 {
166     struct pl011 *uart = port->uart;
167 
168     pl011_write(uart, DR, (uint32_t)(unsigned char)c);
169 }
170 
pl011_getc(struct serial_port * port,char * pc)171 static int pl011_getc(struct serial_port *port, char *pc)
172 {
173     struct pl011 *uart = port->uart;
174 
175     if ( pl011_read(uart, FR) & RXFE )
176         return 0;
177 
178     *pc = pl011_read(uart, DR) & 0xff;
179     return 1;
180 }
181 
pl011_irq(struct serial_port * port)182 static int __init pl011_irq(struct serial_port *port)
183 {
184     struct pl011 *uart = port->uart;
185 
186     return ((uart->irq > 0) ? uart->irq : -1);
187 }
188 
pl011_vuart(struct serial_port * port)189 static const struct vuart_info *pl011_vuart(struct serial_port *port)
190 {
191     struct pl011 *uart = port->uart;
192 
193     return &uart->vuart;
194 }
195 
pl011_tx_stop(struct serial_port * port)196 static void pl011_tx_stop(struct serial_port *port)
197 {
198     struct pl011 *uart = port->uart;
199 
200     pl011_write(uart, IMSC, pl011_read(uart, IMSC) & ~(TXI));
201 }
202 
pl011_tx_start(struct serial_port * port)203 static void pl011_tx_start(struct serial_port *port)
204 {
205     struct pl011 *uart = port->uart;
206 
207     pl011_write(uart, IMSC, pl011_read(uart, IMSC) | (TXI));
208 }
209 
210 static struct uart_driver __read_mostly pl011_driver = {
211     .init_preirq  = pl011_init_preirq,
212     .init_postirq = pl011_init_postirq,
213     .endboot      = NULL,
214     .suspend      = pl011_suspend,
215     .resume       = pl011_resume,
216     .tx_ready     = pl011_tx_ready,
217     .putc         = pl011_putc,
218     .getc         = pl011_getc,
219     .irq          = pl011_irq,
220     .start_tx     = pl011_tx_start,
221     .stop_tx      = pl011_tx_stop,
222     .vuart_info   = pl011_vuart,
223 };
224 
pl011_uart_init(int irq,u64 addr,u64 size,bool sbsa)225 static int __init pl011_uart_init(int irq, u64 addr, u64 size, bool sbsa)
226 {
227     struct pl011 *uart;
228 
229     uart = &pl011_com;
230     uart->irq       = irq;
231     uart->data_bits = 8;
232     uart->parity    = PARITY_NONE;
233     uart->stop_bits = 1;
234     uart->sbsa      = sbsa;
235 
236     uart->regs = ioremap_nocache(addr, size);
237     if ( !uart->regs )
238     {
239         printk("pl011: Unable to map the UART memory\n");
240         return -ENOMEM;
241     }
242 
243     uart->vuart.base_addr = addr;
244     uart->vuart.size = size;
245     uart->vuart.data_off = DR;
246     uart->vuart.status_off = FR;
247     uart->vuart.status = 0;
248 
249     /* Register with generic serial driver. */
250     serial_register_uart(SERHND_DTUART, &pl011_driver, uart);
251 
252     return 0;
253 }
254 
255 /* TODO: Parse UART config from the command line */
pl011_dt_uart_init(struct dt_device_node * dev,const void * data)256 static int __init pl011_dt_uart_init(struct dt_device_node *dev,
257                                      const void *data)
258 {
259     const char *config = data;
260     int res;
261     u64 addr, size;
262 
263     if ( strcmp(config, "") )
264     {
265         printk("WARNING: UART configuration is not supported\n");
266     }
267 
268     res = dt_device_get_address(dev, 0, &addr, &size);
269     if ( res )
270     {
271         printk("pl011: Unable to retrieve the base"
272                " address of the UART\n");
273         return res;
274     }
275 
276     res = platform_get_irq(dev, 0);
277     if ( res < 0 )
278     {
279         printk("pl011: Unable to retrieve the IRQ\n");
280         return -EINVAL;
281     }
282 
283     res = pl011_uart_init(res, addr, size, false);
284     if ( res < 0 )
285     {
286         printk("pl011: Unable to initialize\n");
287         return res;
288     }
289 
290     dt_device_set_used_by(dev, DOMID_XEN);
291 
292     return 0;
293 }
294 
295 static const struct dt_device_match pl011_dt_match[] __initconst =
296 {
297     DT_MATCH_COMPATIBLE("arm,pl011"),
298     { /* sentinel */ },
299 };
300 
301 DT_DEVICE_START(pl011, "PL011 UART", DEVICE_SERIAL)
302         .dt_match = pl011_dt_match,
303         .init = pl011_dt_uart_init,
304 DT_DEVICE_END
305 
306 #ifdef CONFIG_ACPI
307 #include <xen/acpi.h>
308 
309 static int __init pl011_acpi_uart_init(const void *data)
310 {
311     acpi_status status;
312     struct acpi_table_spcr *spcr = NULL;
313     int res;
314     bool sbsa;
315 
316     status = acpi_get_table(ACPI_SIG_SPCR, 0,
317                             (struct acpi_table_header **)&spcr);
318 
319     if ( ACPI_FAILURE(status) )
320     {
321         printk("pl011: Failed to get SPCR table\n");
322         return -EINVAL;
323     }
324 
325     sbsa = (spcr->interface_type == ACPI_DBG2_SBSA ||
326             spcr->interface_type == ACPI_DBG2_SBSA_32);
327 
328     /* trigger/polarity information is not available in spcr */
329     irq_set_type(spcr->interrupt, IRQ_TYPE_LEVEL_HIGH);
330 
331     res = pl011_uart_init(spcr->interrupt, spcr->serial_port.address,
332                           PAGE_SIZE, sbsa);
333     if ( res < 0 )
334     {
335         printk("pl011: Unable to initialize\n");
336         return res;
337     }
338 
339     return 0;
340 }
341 
342 ACPI_DEVICE_START(apl011, "PL011 UART", DEVICE_SERIAL)
343         .class_type = ACPI_DBG2_PL011,
344         .init = pl011_acpi_uart_init,
345 ACPI_DEVICE_END
346 
347 ACPI_DEVICE_START(asbsa_uart, "SBSA UART", DEVICE_SERIAL)
348     .class_type = ACPI_DBG2_SBSA,
349     .init = pl011_acpi_uart_init,
350 ACPI_DEVICE_END
351 
352 ACPI_DEVICE_START(asbsa32_uart, "SBSA32 UART", DEVICE_SERIAL)
353     .class_type = ACPI_DBG2_SBSA_32,
354     .init = pl011_acpi_uart_init,
355 ACPI_DEVICE_END
356 
357 #endif
358 
359 /*
360  * Local variables:
361  * mode: C
362  * c-file-style: "BSD"
363  * c-basic-offset: 4
364  * indent-tabs-mode: nil
365  * End:
366  */
367