1 /*
2  * xen/drivers/char/scif-uart.c
3  *
4  * Driver for SCIF (Serial communication interface with FIFO)
5  * compatible UART.
6  *
7  * Oleksandr Tyshchenko <oleksandr.tyshchenko@globallogic.com>
8  * Copyright (C) 2014, Globallogic.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  */
20 
21 #include <xen/console.h>
22 #include <xen/errno.h>
23 #include <xen/serial.h>
24 #include <xen/init.h>
25 #include <xen/irq.h>
26 #include <xen/mm.h>
27 #include <xen/delay.h>
28 #include <asm/device.h>
29 #include <asm/scif-uart.h>
30 #include <asm/io.h>
31 
32 #define PARITY_NONE    0
33 #define PARITY_EVEN    1
34 #define PARITY_ODD     2
35 
36 #define scif_readb(uart, off)          readb((uart)->regs + (off))
37 #define scif_writeb(uart, off, val)    writeb((val), (uart)->regs + (off))
38 
39 #define scif_readw(uart, off)          readw((uart)->regs + (off))
40 #define scif_writew(uart, off, val)    writew((val), (uart)->regs + (off))
41 
42 static struct scif_uart {
43     unsigned int irq;
44     char __iomem *regs;
45     struct irqaction irqaction;
46     struct vuart_info vuart;
47 } scif_com = {0};
48 
scif_uart_interrupt(int irq,void * data,struct cpu_user_regs * regs)49 static void scif_uart_interrupt(int irq, void *data, struct cpu_user_regs *regs)
50 {
51     struct serial_port *port = data;
52     struct scif_uart *uart = port->uart;
53     uint16_t status, ctrl;
54 
55     ctrl = scif_readw(uart, SCIF_SCSCR);
56     status = scif_readw(uart, SCIF_SCFSR) & ~SCFSR_TEND;
57     /* Ignore next flag if TX Interrupt is disabled */
58     if ( !(ctrl & SCSCR_TIE) )
59         status &= ~SCFSR_TDFE;
60 
61     while ( status != 0 )
62     {
63         /* TX Interrupt */
64         if ( status & SCFSR_TDFE )
65             serial_tx_interrupt(port, regs);
66 
67         /* RX Interrupt */
68         if ( status & (SCFSR_RDF | SCFSR_DR) )
69             serial_rx_interrupt(port, regs);
70 
71         /* Error Interrupt */
72         if ( status & SCIF_ERRORS )
73             scif_writew(uart, SCIF_SCFSR, ~SCIF_ERRORS);
74         if ( scif_readw(uart, SCIF_SCLSR) & SCLSR_ORER )
75             scif_writew(uart, SCIF_SCLSR, 0);
76 
77         ctrl = scif_readw(uart, SCIF_SCSCR);
78         status = scif_readw(uart, SCIF_SCFSR) & ~SCFSR_TEND;
79         /* Ignore next flag if TX Interrupt is disabled */
80         if ( !(ctrl & SCSCR_TIE) )
81             status &= ~SCFSR_TDFE;
82     }
83 }
84 
scif_uart_init_preirq(struct serial_port * port)85 static void __init scif_uart_init_preirq(struct serial_port *port)
86 {
87     struct scif_uart *uart = port->uart;
88 
89     /*
90      * Wait until last bit has been transmitted. This is needed for a smooth
91      * transition when we come from early printk
92      */
93     while ( !(scif_readw(uart, SCIF_SCFSR) & SCFSR_TEND) );
94 
95     /* Disable TX/RX parts and all interrupts */
96     scif_writew(uart, SCIF_SCSCR, 0);
97 
98     /* Reset TX/RX FIFOs */
99     scif_writew(uart, SCIF_SCFCR, SCFCR_RFRST | SCFCR_TFRST);
100 
101     /* Clear all errors and flags */
102     scif_readw(uart, SCIF_SCFSR);
103     scif_writew(uart, SCIF_SCFSR, 0);
104     scif_readw(uart, SCIF_SCLSR);
105     scif_writew(uart, SCIF_SCLSR, 0);
106 
107     /* Setup trigger level for TX/RX FIFOs */
108     scif_writew(uart, SCIF_SCFCR, SCFCR_RTRG11 | SCFCR_TTRG11);
109 
110     /* Enable TX/RX parts */
111     scif_writew(uart, SCIF_SCSCR, scif_readw(uart, SCIF_SCSCR) |
112                  SCSCR_TE | SCSCR_RE);
113 }
114 
scif_uart_init_postirq(struct serial_port * port)115 static void __init scif_uart_init_postirq(struct serial_port *port)
116 {
117     struct scif_uart *uart = port->uart;
118     int rc;
119 
120     uart->irqaction.handler = scif_uart_interrupt;
121     uart->irqaction.name    = "scif_uart";
122     uart->irqaction.dev_id  = port;
123 
124     if ( (rc = setup_irq(uart->irq, 0, &uart->irqaction)) != 0 )
125         dprintk(XENLOG_ERR, "Failed to allocated scif_uart IRQ %d\n",
126                 uart->irq);
127 
128     /* Clear all errors */
129     if ( scif_readw(uart, SCIF_SCFSR) & SCIF_ERRORS )
130         scif_writew(uart, SCIF_SCFSR, ~SCIF_ERRORS);
131     if ( scif_readw(uart, SCIF_SCLSR) & SCLSR_ORER )
132         scif_writew(uart, SCIF_SCLSR, 0);
133 
134     /* Enable TX/RX and Error Interrupts  */
135     scif_writew(uart, SCIF_SCSCR, scif_readw(uart, SCIF_SCSCR) |
136                  SCSCR_TIE | SCSCR_RIE | SCSCR_REIE);
137 }
138 
scif_uart_suspend(struct serial_port * port)139 static void scif_uart_suspend(struct serial_port *port)
140 {
141     BUG();
142 }
143 
scif_uart_resume(struct serial_port * port)144 static void scif_uart_resume(struct serial_port *port)
145 {
146     BUG();
147 }
148 
scif_uart_tx_ready(struct serial_port * port)149 static int scif_uart_tx_ready(struct serial_port *port)
150 {
151     struct scif_uart *uart = port->uart;
152     uint16_t cnt;
153 
154     /* Check for empty space in TX FIFO */
155     if ( !(scif_readw(uart, SCIF_SCFSR) & SCFSR_TDFE) )
156         return 0;
157 
158      /* Check number of data bytes stored in TX FIFO */
159     cnt = scif_readw(uart, SCIF_SCFDR) >> 8;
160     ASSERT( cnt >= 0 && cnt <= SCIF_FIFO_MAX_SIZE );
161 
162     return (SCIF_FIFO_MAX_SIZE - cnt);
163 }
164 
scif_uart_putc(struct serial_port * port,char c)165 static void scif_uart_putc(struct serial_port *port, char c)
166 {
167     struct scif_uart *uart = port->uart;
168 
169     scif_writeb(uart, SCIF_SCFTDR, c);
170     /* Clear required TX flags */
171     scif_writew(uart, SCIF_SCFSR, scif_readw(uart, SCIF_SCFSR) &
172                  ~(SCFSR_TEND | SCFSR_TDFE));
173 }
174 
scif_uart_getc(struct serial_port * port,char * pc)175 static int scif_uart_getc(struct serial_port *port, char *pc)
176 {
177     struct scif_uart *uart = port->uart;
178 
179     /* Check for available data bytes in RX FIFO */
180     if ( !(scif_readw(uart, SCIF_SCFSR) & (SCFSR_RDF | SCFSR_DR)) )
181         return 0;
182 
183     *pc = scif_readb(uart, SCIF_SCFRDR);
184 
185     /* dummy read */
186     scif_readw(uart, SCIF_SCFSR);
187     /* Clear required RX flags */
188     scif_writew(uart, SCIF_SCFSR, ~(SCFSR_RDF | SCFSR_DR));
189 
190     return 1;
191 }
192 
scif_uart_irq(struct serial_port * port)193 static int __init scif_uart_irq(struct serial_port *port)
194 {
195     struct scif_uart *uart = port->uart;
196 
197     return ((uart->irq > 0) ? uart->irq : -1);
198 }
199 
scif_vuart_info(struct serial_port * port)200 static const struct vuart_info *scif_vuart_info(struct serial_port *port)
201 {
202     struct scif_uart *uart = port->uart;
203 
204     return &uart->vuart;
205 }
206 
scif_uart_start_tx(struct serial_port * port)207 static void scif_uart_start_tx(struct serial_port *port)
208 {
209     struct scif_uart *uart = port->uart;
210 
211     scif_writew(uart, SCIF_SCSCR, scif_readw(uart, SCIF_SCSCR) | SCSCR_TIE);
212 }
213 
scif_uart_stop_tx(struct serial_port * port)214 static void scif_uart_stop_tx(struct serial_port *port)
215 {
216     struct scif_uart *uart = port->uart;
217 
218     scif_writew(uart, SCIF_SCSCR, scif_readw(uart, SCIF_SCSCR) & ~SCSCR_TIE);
219 }
220 
221 static struct uart_driver __read_mostly scif_uart_driver = {
222     .init_preirq  = scif_uart_init_preirq,
223     .init_postirq = scif_uart_init_postirq,
224     .endboot      = NULL,
225     .suspend      = scif_uart_suspend,
226     .resume       = scif_uart_resume,
227     .tx_ready     = scif_uart_tx_ready,
228     .putc         = scif_uart_putc,
229     .getc         = scif_uart_getc,
230     .irq          = scif_uart_irq,
231     .start_tx     = scif_uart_start_tx,
232     .stop_tx      = scif_uart_stop_tx,
233     .vuart_info   = scif_vuart_info,
234 };
235 
scif_uart_init(struct dt_device_node * dev,const void * data)236 static int __init scif_uart_init(struct dt_device_node *dev,
237                                  const void *data)
238 {
239     const char *config = data;
240     struct scif_uart *uart;
241     int res;
242     u64 addr, size;
243 
244     if ( strcmp(config, "") )
245         printk("WARNING: UART configuration is not supported\n");
246 
247     uart = &scif_com;
248 
249     res = dt_device_get_address(dev, 0, &addr, &size);
250     if ( res )
251     {
252         printk("scif-uart: Unable to retrieve the base"
253                      " address of the UART\n");
254         return res;
255     }
256 
257     res = platform_get_irq(dev, 0);
258     if ( res < 0 )
259     {
260         printk("scif-uart: Unable to retrieve the IRQ\n");
261         return res;
262     }
263     uart->irq = res;
264 
265     uart->regs = ioremap_nocache(addr, size);
266     if ( !uart->regs )
267     {
268         printk("scif-uart: Unable to map the UART memory\n");
269         return -ENOMEM;
270     }
271 
272     uart->vuart.base_addr  = addr;
273     uart->vuart.size       = size;
274     uart->vuart.data_off   = SCIF_SCFTDR;
275     uart->vuart.status_off = SCIF_SCFSR;
276     uart->vuart.status     = SCFSR_TDFE;
277 
278     /* Register with generic serial driver */
279     serial_register_uart(SERHND_DTUART, &scif_uart_driver, uart);
280 
281     dt_device_set_used_by(dev, DOMID_XEN);
282 
283     return 0;
284 }
285 
286 static const struct dt_device_match scif_uart_dt_match[] __initconst =
287 {
288     DT_MATCH_COMPATIBLE("renesas,scif"),
289     { /* sentinel */ },
290 };
291 
292 DT_DEVICE_START(scif_uart, "SCIF UART", DEVICE_SERIAL)
293     .dt_match = scif_uart_dt_match,
294     .init = scif_uart_init,
295 DT_DEVICE_END
296 
297 /*
298  * Local variables:
299  * mode: C
300  * c-file-style: "BSD"
301  * c-basic-offset: 4
302  * indent-tabs-mode: nil
303  * End:
304  */
305