1 /*
2  * omap-uart.c
3  * Based on drivers/char/ns16550.c
4  *
5  * Driver for OMAP-UART controller
6  *
7  * Copyright (C) 2013, Chen Baozi <baozich@gmail.com>
8  *
9  * Note: This driver is made separate from 16550-series UART driver as
10  * omap platform has some specific configurations
11  */
12 
13 #include <xen/console.h>
14 #include <xen/serial.h>
15 #include <xen/init.h>
16 #include <xen/irq.h>
17 #include <xen/device_tree.h>
18 #include <asm/device.h>
19 #include <xen/errno.h>
20 #include <xen/mm.h>
21 #include <xen/vmap.h>
22 #include <xen/8250-uart.h>
23 #include <asm/io.h>
24 
25 #define REG_SHIFT 2
26 
27 /* Register offsets */
28 #define UART_OMAP_EFR    0x02   /* Enhanced feature register */
29 #define UART_OMAP_MDR1   0x08   /* Mode definition register 1 */
30 #define UART_OMAP_SCR    0x10   /* Supplementary control register */
31 #define UART_OMAP_SSR    0x11   /* Supplementary status register */
32 #define UART_OMAP_SYSC   0x15   /* System configuration register */
33 #define UART_OMAP_TXFIFO_LVL   0x1A   /* TX FIFO level register */
34 
35 /* Enhanced feature register */
36 #define UART_OMAP_EFR_ECB   0x10   /* Enhanced control bit */
37 
38 /* Mode definition register 1 */
39 #define UART_OMAP_MDR1_16X_MODE   0x00   /* UART 16x mode           */
40 #define UART_OMAP_MDR1_DISABLE    0x07   /* Disable (default state) */
41 
42 /* Supplementary control register bitmasks */
43 #define UART_OMAP_SCR_RX_TRIG_GRANU1_MASK   (1 << 7)
44 
45 /* Supplementary status register bitmasks */
46 #define UART_OMAP_SSR_TX_FIFO_FULL_MASK   (1 << 0)
47 
48 /* System configuration register */
49 #define UART_OMAP_SYSC_DEF_CONF   0x0d   /* autoidle mode, wakeup is enabled */
50 
51 #define omap_read(uart, off)       readl((uart)->regs + (off<<REG_SHIFT))
52 #define omap_write(uart, off, val) writel((val), (uart)->regs + (off<<REG_SHIFT))
53 
54 static struct omap_uart {
55     u32 baud, clock_hz, data_bits, parity, stop_bits, fifo_size;
56     unsigned int irq;
57     char __iomem *regs;
58     struct irqaction irqaction;
59     struct vuart_info vuart;
60 } omap_com = {0};
61 
omap_uart_interrupt(int irq,void * data,struct cpu_user_regs * regs)62 static void omap_uart_interrupt(int irq, void *data, struct cpu_user_regs *regs)
63 {
64     struct serial_port *port = data;
65     struct omap_uart *uart = port->uart;
66     u32 lsr;
67     uint32_t reg;
68 
69     while ( !(omap_read(uart, UART_IIR) & UART_IIR_NOINT) )
70     {
71         lsr = omap_read(uart, UART_LSR) & 0xff;
72 	if ( lsr & UART_LSR_THRE )
73             serial_tx_interrupt(port, regs);
74 	if ( lsr & UART_LSR_DR )
75             serial_rx_interrupt(port, regs);
76 
77         if ( port->txbufc == port->txbufp ) {
78             reg = omap_read(uart, UART_IER);
79             omap_write(uart, UART_IER, reg & (~UART_IER_ETHREI));
80         }
81     };
82 }
83 
baud_protocol_setup(struct omap_uart * uart)84 static void baud_protocol_setup(struct omap_uart *uart)
85 {
86     u32 dll, dlh, efr;
87     unsigned int divisor;
88 
89     divisor = uart->clock_hz / (uart->baud << 4);
90     dll = divisor & 0xff;
91     dlh = divisor >> 8;
92 
93     /*
94      * Switch to register configuration mode B to access the UART_OMAP_EFR
95      * register.
96      */
97     omap_write(uart, UART_LCR, UART_LCR_CONF_MODE_B);
98     /*
99      * Enable access to the UART_IER[7:4] bit field.
100      */
101     efr = omap_read(uart, UART_OMAP_EFR);
102     omap_write(uart, UART_OMAP_EFR, efr|UART_OMAP_EFR_ECB);
103     /*
104      * Switch to register operation mode to access the UART_IER register.
105      */
106     omap_write(uart, UART_LCR, 0);
107     /*
108      * Clear the UART_IER register (set the UART_IER[4] SLEEP_MODE bit
109      * to 0 to change the UART_DLL and UART_DLM register). Set the
110      * UART_IER register value to 0x0000.
111      */
112     omap_write(uart, UART_IER, 0);
113     /*
114      * Switch to register configuartion mode B to access the UART_DLL and
115      * UART_DLM registers.
116      */
117     omap_write(uart, UART_LCR, UART_LCR_CONF_MODE_B);
118     /*
119      * Load divisor value.
120      */
121     omap_write(uart, UART_DLL, dll);
122     omap_write(uart, UART_DLM, dlh);
123     /*
124      * Restore the UART_OMAP_EFR
125      */
126     omap_write(uart, UART_OMAP_EFR, efr);
127     /*
128      * Load the new protocol formatting (parity, stop-bit, character length)
129      * and switch to register operational mode.
130      */
131     omap_write(uart, UART_LCR, (uart->data_bits - 5) |
132                ((uart->stop_bits - 1) << 2) | uart->parity);
133 }
134 
fifo_setup(struct omap_uart * uart)135 static void fifo_setup(struct omap_uart *uart)
136 {
137     u32 lcr, efr, mcr;
138     /*
139      * Switch to register configuration mode B to access the UART_OMAP_EFR
140      * register.
141      */
142     lcr = omap_read(uart, UART_LCR);
143     omap_write(uart, UART_LCR, UART_LCR_CONF_MODE_B);
144     /*
145      * Enable register submode TCR_TLR to access the UART_OMAP_TLR register.
146      */
147     efr = omap_read(uart, UART_OMAP_EFR);
148     omap_write(uart, UART_OMAP_EFR, efr|UART_OMAP_EFR_ECB);
149     /*
150      * Switch to register configuration mode A to access the UART_MCR
151      * register.
152      */
153     omap_write(uart, UART_LCR, UART_LCR_CONF_MODE_A);
154     /*
155      * Enable register submode TCR_TLR to access the UART_OMAP_TLR register
156      */
157     mcr = omap_read(uart, UART_MCR);
158     omap_write(uart, UART_MCR, mcr|UART_MCR_TCRTLR);
159     /*
160      * Enable the FIFO; load the new FIFO trigger and the new DMA mode.
161      */
162     omap_write(uart, UART_FCR, UART_FCR_R_TRIG_01|
163                UART_FCR_T_TRIG_10|UART_FCR_ENABLE);
164     /*
165      * Switch to register configuration mode B to access the UART_EFR
166      * register.
167      */
168     omap_write(uart, UART_LCR, UART_LCR_CONF_MODE_B);
169     /*
170      * Load the new FIFO triggers and the new DMA mode bit.
171      */
172     omap_write(uart, UART_OMAP_SCR, UART_OMAP_SCR_RX_TRIG_GRANU1_MASK);
173     /*
174      * Restore the UART_OMAP_EFR[4] value.
175      */
176     omap_write(uart, UART_OMAP_EFR, efr);
177     /*
178      * Switch to register configuration mode A to access the UART_MCR
179      * register.
180      */
181     omap_write(uart, UART_LCR, UART_LCR_CONF_MODE_A);
182     /*
183      * Restore UART_MCR[6] value.
184      */
185     omap_write(uart, UART_MCR, mcr);
186     /*
187      * Restore UART_LCR value.
188      */
189     omap_write(uart, UART_LCR, lcr);
190 
191     uart->fifo_size = 64;
192 }
193 
omap_uart_init_preirq(struct serial_port * port)194 static void __init omap_uart_init_preirq(struct serial_port *port)
195 {
196     struct omap_uart *uart = port->uart;
197 
198     /*
199      * Clear the FIFO buffers.
200      */
201     omap_write(uart, UART_FCR, UART_FCR_ENABLE);
202     omap_write(uart, UART_FCR, UART_FCR_ENABLE|UART_FCR_CLRX|UART_FCR_CLTX);
203     omap_write(uart, UART_FCR, 0);
204 
205     /*
206      * The TRM says the mode should be disabled while UART_DLL and UART_DHL
207      * are being changed so we disable before setup, then enable.
208      */
209     omap_write(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
210 
211     /* Baud rate & protocol format setup */
212     baud_protocol_setup(uart);
213 
214     /* FIFO setup */
215     fifo_setup(uart);
216 
217     /* No flow control */
218     omap_write(uart, UART_MCR, UART_MCR_DTR|UART_MCR_RTS);
219 
220     omap_write(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_16X_MODE);
221 
222     /* setup idle mode */
223     omap_write(uart, UART_OMAP_SYSC, UART_OMAP_SYSC_DEF_CONF);
224 }
225 
omap_uart_init_postirq(struct serial_port * port)226 static void __init omap_uart_init_postirq(struct serial_port *port)
227 {
228     struct omap_uart *uart = port->uart;
229 
230     uart->irqaction.handler = omap_uart_interrupt;
231     uart->irqaction.name = "omap_uart";
232     uart->irqaction.dev_id = port;
233 
234     if ( setup_irq(uart->irq, 0, &uart->irqaction) != 0 )
235     {
236         dprintk(XENLOG_ERR, "Failed to allocated omap_uart IRQ %d\n",
237                 uart->irq);
238         return;
239     }
240 
241     /* Enable interrupts */
242     omap_write(uart, UART_IER, UART_IER_ERDAI|UART_IER_ETHREI|UART_IER_ELSI);
243 }
244 
omap_uart_suspend(struct serial_port * port)245 static void omap_uart_suspend(struct serial_port *port)
246 {
247     BUG();
248 }
249 
omap_uart_resume(struct serial_port * port)250 static void omap_uart_resume(struct serial_port *port)
251 {
252     BUG();
253 }
254 
omap_uart_tx_ready(struct serial_port * port)255 static int omap_uart_tx_ready(struct serial_port *port)
256 {
257     struct omap_uart *uart = port->uart;
258     uint32_t reg;
259     uint8_t cnt;
260 
261     reg = omap_read(uart, UART_IER);
262     omap_write(uart, UART_IER, reg | UART_IER_ETHREI);
263 
264     /* Check for empty space in TX FIFO */
265     if ( omap_read(uart, UART_OMAP_SSR) & UART_OMAP_SSR_TX_FIFO_FULL_MASK )
266         return 0;
267 
268     /* Check number of data bytes stored in TX FIFO */
269     cnt = omap_read(uart, UART_OMAP_TXFIFO_LVL);
270     ASSERT( cnt >= 0 && cnt <= uart->fifo_size );
271 
272     return (uart->fifo_size - cnt);
273 }
274 
omap_uart_putc(struct serial_port * port,char c)275 static void omap_uart_putc(struct serial_port *port, char c)
276 {
277     struct omap_uart *uart = port->uart;
278 
279     omap_write(uart, UART_THR, (uint32_t)(unsigned char)c);
280 }
281 
omap_uart_getc(struct serial_port * port,char * pc)282 static int omap_uart_getc(struct serial_port *port, char *pc)
283 {
284     struct omap_uart *uart = port->uart;
285 
286     if ( !(omap_read(uart, UART_LSR) & UART_LSR_DR) )
287 	return 0;
288 
289     *pc = omap_read(uart, UART_RBR) & 0xff;
290     return 1;
291 }
292 
omap_uart_irq(struct serial_port * port)293 static int __init omap_uart_irq(struct serial_port *port)
294 {
295     struct omap_uart *uart = port->uart;
296 
297     return ((uart->irq > 0) ? uart->irq : -1);
298 }
299 
omap_vuart_info(struct serial_port * port)300 static const struct vuart_info *omap_vuart_info(struct serial_port *port)
301 {
302     struct omap_uart *uart = port->uart;
303 
304     return &uart->vuart;
305 }
306 
307 static struct uart_driver __read_mostly omap_uart_driver = {
308     .init_preirq = omap_uart_init_preirq,
309     .init_postirq = omap_uart_init_postirq,
310     .endboot = NULL,
311     .suspend = omap_uart_suspend,
312     .resume = omap_uart_resume,
313     .tx_ready = omap_uart_tx_ready,
314     .putc = omap_uart_putc,
315     .getc = omap_uart_getc,
316     .irq = omap_uart_irq,
317     .vuart_info = omap_vuart_info,
318 };
319 
omap_uart_init(struct dt_device_node * dev,const void * data)320 static int __init omap_uart_init(struct dt_device_node *dev,
321                                  const void *data)
322 {
323     const char *config = data;
324     struct omap_uart *uart;
325     u32 clkspec;
326     int res;
327     u64 addr, size;
328 
329     if ( strcmp(config, "") )
330         printk("WARNING: UART configuration is not supported\n");
331 
332     uart = &omap_com;
333 
334     res = dt_property_read_u32(dev, "clock-frequency", &clkspec);
335     if ( !res )
336     {
337         printk("omap-uart: Unable to retrieve the clock frequency\n");
338         return -EINVAL;
339     }
340 
341     uart->clock_hz = clkspec;
342     uart->baud = 115200;
343     uart->data_bits = 8;
344     uart->parity = UART_PARITY_NONE;
345     uart->stop_bits = 1;
346 
347     res = dt_device_get_address(dev, 0, &addr, &size);
348     if ( res )
349     {
350         printk("omap-uart: Unable to retrieve the base"
351                " address of the UART\n");
352         return res;
353     }
354 
355     res = platform_get_irq(dev, 0);
356     if ( res < 0 )
357     {
358         printk("omap-uart: Unable to retrieve the IRQ\n");
359         return -EINVAL;
360     }
361     uart->irq = res;
362 
363     uart->regs = ioremap_nocache(addr, size);
364     if ( !uart->regs )
365     {
366         printk("omap-uart: Unable to map the UART memory\n");
367         return -ENOMEM;
368     }
369 
370 
371     uart->vuart.base_addr = addr;
372     uart->vuart.size = size;
373     uart->vuart.data_off = UART_THR;
374     uart->vuart.status_off = UART_LSR << REG_SHIFT;
375     uart->vuart.status = UART_LSR_THRE;
376 
377     /* Register with generic serial driver */
378     serial_register_uart(SERHND_DTUART, &omap_uart_driver, uart);
379 
380     dt_device_set_used_by(dev, DOMID_XEN);
381 
382     return 0;
383 }
384 
385 static const struct dt_device_match omap_uart_dt_match[] __initconst =
386 {
387     DT_MATCH_COMPATIBLE("ti,omap4-uart"),
388     { /* sentinel */ },
389 };
390 
391 DT_DEVICE_START(omap_uart, "OMAP UART", DEVICE_SERIAL)
392     .dt_match = omap_uart_dt_match,
393     .init = omap_uart_init,
394 DT_DEVICE_END
395 
396 /*
397  * Local variables:
398  * mode: C
399  * c-file-style: "BSD"
400  * c-basic-offset: 4
401  * indent-tabs-mode: nil
402  * End:
403  */
404