1/*
2 * Copyright 2017, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
8 * See "LICENSE_BSD2.txt" for details.
9 *
10 * @TAG(DATA61_BSD)
11 */
12#include <stdlib.h>
13#include <platsupport/serial.h>
14#include <platsupport/plat/serial.h>
15#include <string.h>
16#include <utils/fence.h>
17
18#include "../../chardev.h"
19
20#define UART_BYTE_MASK  0xff
21
22#define NV_UART_INPUT_CLOCK_FREQ_HZ (408000000)
23
24#define LCR_DLAB        BIT(7)
25#define LCR_SET_BREAK   BIT(6)
26#define LCR_SET_PARITY  BIT(5)  /* Force parity to value of BIT(4) */
27#define LCR_EVEN        BIT(4)  /* even parity? */
28#define LCR_PAR         BIT(3)  /* send parity? */
29#define LCR_STOP        BIT(2)  /* transmit 1 (0) or 2 (1) stop bits */
30#define LCR_WD_SIZE_5   0
31#define LCR_WD_SIZE_6   1
32#define LCR_WD_SIZE_7   2
33#define LCR_WD_SIZE_8   3
34
35#define LSR_THRE_EMPTY  (BIT(5))
36#define LSR_RDR_READY   BIT(0)
37
38#define IER_RHR_ENABLE          BIT(0)
39#define IER_THR_EMPTY_ENABLE    BIT(1)
40#define IER_RX_FIFO_TIMEDOUT    BIT(4)
41#define IER_EO_RECEIVE_DATA     BIT(5)
42
43/* IIR is read-only, FCR is write-only. Both share the same address mapping.
44 * IIR is automatically selected when you do a read-access.
45 * FCR is automatically selected when you do a write-access
46 */
47#define FCR_FIFO_ENABLE                BIT(0)
48#define FCR_DMA_MODE0                  (0)
49#define FCR_DMA_MODE1                  BIT(3)
50#define FCR_RX_TRIG_SHIFT              (6)
51#define FCR_RX_TRIG_MASK               (0x3)
52#define FCR_RX_TRIG_FIFO_GT_1          (0)
53#define FCR_RX_TRIG_FIFO_GT_4          (1)
54#define FCR_RX_TRIG_FIFO_GT_8          (2)
55#define FCR_RX_TRIG_FIFO_GT_16         (3)
56
57#define FCR_TX_TRIG_SHIFT              (4)
58#define FCR_TX_TRIG_MASK               (0x3)
59#define FCR_TX_TRIG_FIFO_GT_1          (3)
60#define FCR_TX_TRIG_FIFO_GT_4          (2)
61#define FCR_TX_TRIG_FIFO_GT_8          (1)
62#define FCR_TX_TRIG_FIFO_GT_16         (0)
63
64#define FCR_TX_FIFO_CLEAR_SHIFT        (2)
65#define FCR_RX_FIFO_CLEAR_SHIFT        (1)
66
67#define IIR_FIFO_MODE_STATUS_SHIFT     (6)
68#define IIR_FIFO_MODE_STATUS_MASK      (0x3)
69
70#define IIR_INT_PENDING                 BIT(0)
71#define IIR_INT_SOURCE_SHIFT            (0)
72#define IIR_INT_SOURCE_MASK             (0xF)
73
74enum iir_int_source {
75    IIR_INT_SOURCE_NO_INTERRUPT             = 0x1,
76    IIR_INT_SOURCE_DATA_ERROR               = 0x6,
77    IIR_INT_SOURCE_RECEIVED_DATA_AVAILABLE  = 0x4,
78    IIR_INT_SOURCE_RECEIVED_DATA_TIMEOUT    = 0xC,
79    IIR_INT_SOURCE_EO_RECEIVED_DATA         = 0x8,
80    IIR_INT_SOURCE_THR_TXRDY                = 0x2,
81    IIR_INT_SOURCE_MODEM_STATUS             = 0x0
82};
83
84#define EXTRACT_BITS(bf,shift,mask)         (((bf) >> (shift)) & (mask))
85#define ENCODE_BITS(bf,shift,mask,v)        (((bf) & ~(((mask) << (shift)))) \
86                                                | (((v) & (mask)) << (shift)))
87struct tk1_uart_regs {
88    uint32_t    thr_dlab;   /* 0x0: tx holding register                     */
89    uint32_t    ier_dlab;   /* 0x4: IER and DLH registers                   */
90    uint32_t    iir_fcr;    /* 0x8: FIFO control; interrupt identification  */
91    uint32_t    lcr;        /* 0xc: line control                            */
92    uint32_t    mcr;        /* 0x10: modem control                          */
93    uint32_t    lsr;        /* 0x14: line status                            */
94    uint32_t    msr;        /* 0x18: modem status                           */
95    uint32_t    spr;        /* 0x1c: scratchpad                             */
96    uint32_t    csr;        /* 0x20: IrDA pulse coding                      */
97    uint32_t    rx_fifo_cfg;/* 0x24:                                        */
98    uint32_t    mie;        /* 0x28: modem interrupt enable                 */
99    uint32_t    asr;        /* 0x3c: auto sense baud                        */
100};
101typedef volatile struct tk1_uart_regs tk1_uart_regs_t;
102
103static inline tk1_uart_regs_t*
104tk1_uart_get_priv(ps_chardevice_t *d)
105{
106    return (tk1_uart_regs_t*)d->vaddr;
107}
108
109static inline bool
110tk1_uart_is_async(ps_chardevice_t *d)
111{
112    /* NV_UART[ABCD] are polling, while NV_UART[ABCD]_ASYNC are asynchronous
113     * versions of the first 4 devices.
114     */
115    return (d->id >= NV_UARTA_ASYNC);
116}
117
118static inline void
119tk1_uart_set_thr_irq(tk1_uart_regs_t *regs, bool enable)
120{
121    uint32_t ier;
122
123    ier = regs->ier_dlab;
124    if (enable) {
125        ier |= IER_THR_EMPTY_ENABLE;
126    } else {
127        ier &= ~IER_THR_EMPTY_ENABLE;
128    }
129    regs->ier_dlab = ier;
130}
131
132static inline void
133tk1_uart_set_rbr_irq(tk1_uart_regs_t *regs, bool enable)
134{
135    uint32_t ier;
136
137    ier = regs->ier_dlab;
138    if (enable) {
139        ier |= IER_RHR_ENABLE;
140        ier |= IER_RX_FIFO_TIMEDOUT;
141    } else {
142        ier &= ~IER_RHR_ENABLE;
143        ier &= ~IER_RX_FIFO_TIMEDOUT;
144    }
145    regs->ier_dlab = ier;
146}
147
148int uart_getchar(ps_chardevice_t *d)
149{
150    tk1_uart_regs_t* regs = tk1_uart_get_priv(d);
151    uint32_t reg = 0;
152    int c = -1;
153
154    if (regs->lsr & LSR_RDR_READY) {
155        reg = regs->thr_dlab;
156        c = reg & UART_BYTE_MASK;
157    }
158    return c;
159}
160
161int uart_putchar(ps_chardevice_t* d, int c)
162{
163    tk1_uart_regs_t* regs = tk1_uart_get_priv(d);
164    uint32_t lsr = regs->lsr;
165
166    if (((lsr & LSR_THRE_EMPTY) == LSR_THRE_EMPTY)) {
167        if (c == '\n' && (d->flags & SERIAL_AUTO_CR)) {
168            uart_putchar(d, '\r');
169        }
170
171        regs->thr_dlab = (uint8_t) c;
172
173        return c;
174    } else {
175        return -1;
176    }
177}
178
179static void
180tk1_uart_invoke_callback(ps_chardevice_t *d, enum chardev_status stat,
181                         size_t n_bytes_xferred,
182                         bool invoke_read, bool invoke_write)
183{
184    tk1_uart_regs_t *regs = tk1_uart_get_priv(d);
185
186    if (!invoke_read && !invoke_write) {
187        ZF_LOGW("invoke_cb called with no indication of what should be done.");
188        return;
189    }
190
191    if (invoke_read) {
192        if (d->read_descriptor.callback != NULL
193            && d->read_descriptor.bytes_requested > 0) {
194            d->read_descriptor.callback(d, stat,
195                                        n_bytes_xferred,
196                                        d->read_descriptor.token);
197
198            /* If the client set bytes_requested to 0 inside of the callback,
199             * that is a signal to us that we should close any asynchronous
200             * reading from the line.
201             */
202            if (d->read_descriptor.bytes_requested == 0) {
203                tk1_uart_set_rbr_irq(regs, false);
204            }
205        }
206    }
207    if (invoke_write) {
208        if (d->write_descriptor.callback != NULL
209            && d->write_descriptor.bytes_requested > 0) {
210            d->write_descriptor.callback(d, stat,
211                                        n_bytes_xferred,
212                                        d->write_descriptor.token);
213
214            /* If the client set bytes_requested to 0 inside of the callback,
215             * that is a signal to us that we should consider the async write
216             * to be closed.
217             */
218            if (d->write_descriptor.bytes_requested == 0) {
219                tk1_uart_set_thr_irq(regs, false);
220            }
221        }
222    }
223}
224
225static void
226uart_handle_irq(ps_chardevice_t* d)
227{
228    tk1_uart_regs_t *regs = tk1_uart_get_priv(d);
229    uintptr_t irq_ident_val;
230
231    /* Determine the cause of the IRQ. */
232    irq_ident_val = regs->iir_fcr;
233    irq_ident_val &= IIR_INT_SOURCE_MASK;
234
235    switch (irq_ident_val) {
236    case IIR_INT_SOURCE_NO_INTERRUPT:
237        break;
238    case IIR_INT_SOURCE_DATA_ERROR:
239
240        ZF_LOGE("Parity, overrun, or framing error.");
241        if (d->read_descriptor.data != NULL) {
242            tk1_uart_invoke_callback(d, CHARDEV_STAT_ERROR, 0, true, false);
243        }
244        break;
245
246    case IIR_INT_SOURCE_RECEIVED_DATA_TIMEOUT:
247    case IIR_INT_SOURCE_EO_RECEIVED_DATA:
248    case IIR_INT_SOURCE_RECEIVED_DATA_AVAILABLE: {
249        uint8_t *client_buff;
250        int c;
251
252        struct chardev_xmit_descriptor *rd = &d->read_descriptor;
253
254        if (irq_ident_val == IIR_INT_SOURCE_EO_RECEIVED_DATA) {
255
256            /* Tegra K1 Mobile Processor TRM, section 23.4.2:
257             *
258             * "EORD (End of Receive Data) Interrupt occurs when the receiver
259             * detects that data stops coming in for more than 4 character
260             * times. This interrupt is useful for determining that the sending
261             * device has completed sending all its data. EORD timeout will not
262             * occur if the receiving data stream is stopped because of hardware
263             * handshaking."
264             *
265             * "To clear the EORD timeout interrupt you must DISABLE the EORD
266             * interrupt enable (IE_EORD)."
267             *
268             * But I assume I have to re-enable it too, because otherwise I
269             * won't get them anymore.
270             */
271            ZF_LOGV("Int reason EO received data.");
272            regs->ier_dlab &= ~IER_EO_RECEIVE_DATA;
273            regs->ier_dlab |= IER_EO_RECEIVE_DATA;
274        }
275
276        if (rd->data == NULL || rd->bytes_requested == 0) {
277            /* Even if there is no rx buffer, or no bytes have been requested,
278             * or some other unusual case has been triggered, we should read the
279             * RBR register and consume the bytes in it.
280             */
281            ZF_LOGW("Draining.");
282            while (uart_getchar(d) != -1) {
283                /* Just read the bytes out to clear the FIFO */
284            }
285            break;
286        }
287
288        /* So everytime a new RX data IRQ comes in, the buffer cursor gets
289         * reset to the beginning of the client-supplied buffer.
290         *
291         * Therefore the client should try to service IRQs as quickly as possible.
292         */
293
294        client_buff = rd->data;
295
296        c = uart_getchar(d);
297        while (c != -1) {
298            /* Don't overrun the client-supplied buffer */
299            if (rd->bytes_transfered >= rd->bytes_requested) {
300                ZF_LOGV("Buffer of %dB will be overrun.", rd->bytes_requested);
301
302                tk1_uart_invoke_callback(d, CHARDEV_STAT_INCOMPLETE,
303                                         rd->bytes_transfered,
304                                         true, false);
305
306                /* We use bytes_requested as a flag to indicate to the this IRQ
307                 * handler that it shouldn't call the callback again.
308                 * If bytes_requested is 0, we won't get here, so this callback
309                 * won't be called repeatedly if there's more data than the
310                 * caller's buffer can hold.
311                 */
312                rd->bytes_requested = 0;
313                break;
314            }
315
316            client_buff[rd->bytes_transfered] = (char)c;
317            rd->bytes_transfered++;
318            c = uart_getchar(d);
319        }
320
321        /* If the loop exits early because the buffer was overrun, "c" will
322         * not be -1, because the UART would have returned a character. We
323         * just didn't have any buffer memory remaining.
324         *
325         * I.e, c will be -1 if the loop exited normally.
326         */
327        if (c == -1 && rd->bytes_transfered > 0) {
328            tk1_uart_invoke_callback(d, CHARDEV_STAT_COMPLETE,
329                                     rd->bytes_transfered,
330                                     true, false);
331        }
332
333        break;
334    }
335
336    case IIR_INT_SOURCE_THR_TXRDY:
337        ZF_LOGV("Int reason THR ready: %d of %d bytes transferred.",
338                d->write_descriptor.bytes_transfered,
339                d->write_descriptor.bytes_requested);
340
341        if (d->write_descriptor.data != NULL) {
342            struct chardev_xmit_descriptor *wd = &d->write_descriptor;
343            uint8_t *client_data;
344            int status;
345
346            client_data = wd->data;
347            while (wd->bytes_transfered < wd->bytes_requested) {
348                status = uart_putchar(d, client_data[wd->bytes_transfered]);
349                if (status == -1) {
350                    ZF_LOGV("One DMA pass finished: written %d of %dB!",
351                           wd->bytes_transfered, wd->bytes_requested);
352                    break;
353                }
354
355                wd->bytes_transfered++;
356            }
357
358            if (wd->bytes_transfered >= wd->bytes_requested) {
359                /* Disable the THR_EMPTY IRQ until a new write request is made. */
360                tk1_uart_set_thr_irq(regs, false);
361
362                tk1_uart_invoke_callback(d, CHARDEV_STAT_COMPLETE,
363                                         wd->bytes_transfered,
364                                         false, true);
365            }
366        } else {
367            /* If there's no input data buffer to read from, disable the
368             * THR_EMPTY IRQ, because it was triggered, for one reason or
369             * another.
370             */
371            tk1_uart_set_thr_irq(regs, false);
372        }
373        break;
374
375    case IIR_INT_SOURCE_MODEM_STATUS:
376        ZF_LOGV("Modem status changed.");
377        break;
378    default:
379        ZF_LOGW("Unknown interrupt reason %d.", irq_ident_val);
380    };
381}
382
383static ssize_t
384tk1_uart_write(ps_chardevice_t* d, const void* vdata,
385                           size_t count, chardev_callback_t rcb,
386                           void* token)
387{
388    struct chardev_xmit_descriptor wd = {
389        .callback = rcb,
390        .token = token,
391        .bytes_transfered = 0,
392        .bytes_requested = count,
393        .data = (void *)vdata
394    };
395
396    d->write_descriptor = wd;
397
398    if (count == 0) {
399        /* Call the callback immediately */
400        if (rcb != NULL) {
401            rcb(d, CHARDEV_STAT_COMPLETE, count, token);
402        }
403        return 0;
404    }
405
406    if (!tk1_uart_is_async(d)) {
407        /* Write the data out over the line synchronously. */
408        for (int i = 0; i < count; i++) {
409            while (uart_putchar(d, ((uint8_t *)vdata)[i]) == -1) {
410            }
411
412            d->write_descriptor.bytes_transfered++;
413        }
414
415        if (rcb != NULL) {
416            rcb(d, CHARDEV_STAT_COMPLETE, d->write_descriptor.bytes_transfered,
417                token);
418        }
419    } else {
420        /* Else enable the THRE IRQ and return. */
421        tk1_uart_set_thr_irq(tk1_uart_get_priv(d), true);
422        THREAD_MEMORY_RELEASE();
423    }
424
425    return d->write_descriptor.bytes_transfered;
426}
427
428static ssize_t
429tk1_uart_read(ps_chardevice_t* d, void* vdata,
430                          size_t count, chardev_callback_t rcb,
431                          void* token)
432{
433    if (count < 1) {
434        count = 0;
435    }
436
437    struct chardev_xmit_descriptor rd = {
438        .callback = rcb,
439        .token = token,
440        .bytes_transfered = 0,
441        .bytes_requested = count,
442        .data = vdata
443    };
444
445    d->read_descriptor = rd;
446
447    if (count == 0 && rcb != NULL) {
448        ZF_LOGV("read call with 0 count.");
449        rcb(d, CHARDEV_STAT_COMPLETE, count, token);
450    }
451
452    if (!tk1_uart_is_async(d)) {
453        int n_chars_read = 0;
454        int c;
455
456        while ((c = uart_getchar(d)) == -1) {
457            /* Ideally we should use a cpu_relax() type of opcode here. */
458        }
459
460        /* Read the data synchronously. */
461        while (c != -1) {
462            ((uint8_t *)vdata)[n_chars_read] = c;
463
464            c = uart_getchar(d);
465            n_chars_read++;
466        }
467
468        d->read_descriptor.bytes_transfered = n_chars_read;
469
470        if (rcb != NULL) {
471            rcb(d, CHARDEV_STAT_COMPLETE, d->read_descriptor.bytes_transfered,
472                token);
473        }
474    }
475
476    return d->read_descriptor.bytes_transfered;
477}
478
479/** Used for debugging. Concats the dlab hi and lo bytes into a 16-bit int.
480 * @param d Pointer to the device whose divisor you want to get.
481 * @return 16-bit divisor.
482 */
483UNUSED static uint16_t
484tk1_uart_get_dlab_divisor(ps_chardevice_t *d)
485{
486    uint16_t ret=0;
487    tk1_uart_regs_t* regs = tk1_uart_get_priv(d);
488
489    regs->lcr |= LCR_DLAB;
490    THREAD_MEMORY_RELEASE();
491    ret = regs->thr_dlab & 0xFF;
492    ret |= (regs->ier_dlab & 0xFF) << 8;
493    THREAD_MEMORY_RELEASE();
494    regs->lcr &= ~LCR_DLAB;
495
496    return ret;
497}
498
499static void
500tk1_uart_set_dlab_divisor(ps_chardevice_t *d, uint16_t divisor)
501{
502    tk1_uart_regs_t* regs = tk1_uart_get_priv(d);
503
504    regs->lcr |= LCR_DLAB;
505    THREAD_MEMORY_RELEASE();
506    regs->thr_dlab = divisor & 0xFF;
507    regs->ier_dlab = (divisor >> 8) & 0xFF;
508    THREAD_MEMORY_RELEASE();
509    regs->lcr &= ~LCR_DLAB;
510}
511
512static int
513tk1_uart_get_divisor_for(int baud)
514{
515    int ret;
516
517    switch (baud) {
518    case 115200:
519    case 57600:
520    case 38400:
521    case 19200:
522    case 9600:
523    case 4800:
524    case 2400:
525    case 1200:
526    case 300:
527        /* Do nothing; This switch is for input validation. */
528        break;
529    default:
530        ZF_LOGE("TK1-uart: Unsupported baud rate %d.",
531                baud);
532        return -1;
533    }
534
535    /* Both we an u-boot program the UARTs to use PllP_out as their input clock,
536     * which is fixed at 408MHz:
537     *
538     *  TegraK1 TRM, Section 5.22, Table 14:
539     *  "pllP_out: This is the PLLP���s output clock which is set to 408 MHz."
540     *
541     * This 408MHz output, is then channeled into the UART-controllers after
542     * being passed through a divider. The divider's default divisor is 17
543     * on hardware #RESET, but u-boot sets the divider's divisor to 0, and so
544     * the UART controller gets the full 408 MHz as its input.
545     *
546     * From there, we just calculate a divisor to put into the UART controller's
547     * DLAB (divisor latch) registers, based on the caller's requested baud
548     * rate, according to the formula:
549     *  Divisor = input_clock_freq / (16 * desired_baud)
550     *
551     * The number "16" comes from the fact that the UART controller takes 16
552     * clock phases to generate one bit of output on the line (TK1 TRM, section
553     * 34.1.1.)
554     */
555    ret = (NV_UART_INPUT_CLOCK_FREQ_HZ / 16) / baud;
556    return ret;
557}
558
559int
560serial_configure(ps_chardevice_t* d, long bps, int char_size, enum serial_parity parity, int stop_bits)
561{
562    tk1_uart_regs_t* regs = tk1_uart_get_priv(d);
563    int divisor;
564    /* line control register */
565    uint32_t lcr = 0;
566
567    /* Disable the receive IRQ while changing line configuration. */
568    tk1_uart_set_rbr_irq(regs, false);
569    THREAD_MEMORY_RELEASE();
570
571    switch (char_size) {
572        case 5:
573            lcr |= LCR_WD_SIZE_5;
574            break;
575        case 6:
576            lcr |= LCR_WD_SIZE_6;
577            break;
578        case 7:
579            lcr |= LCR_WD_SIZE_7;
580            break;
581        case 8:
582            lcr |= LCR_WD_SIZE_8;
583            break;
584        default:
585            return -1;
586    }
587
588    switch (parity) {
589        case PARITY_NONE:
590            break;
591        case PARITY_EVEN:
592            lcr |= LCR_EVEN | LCR_PAR;
593            break;
594        case PARITY_ODD:
595            lcr |= LCR_PAR;
596            break;
597/*
598 * Uncomment if we ever need fixed values for parity bits
599 *
600        case PARITY_ONE:
601            lcr |= LCR_SET_PARITY | LCR_EVEN;
602            break;
603        case PARITY_ZERO:
604            lcr |= LCR_SET_PARITY;
605            break
606*/
607        default:
608            return -1;
609    }
610
611    /* one stop bit */
612    regs->lcr = lcr;
613
614    divisor = tk1_uart_get_divisor_for(bps);
615    if (divisor < 1) {
616        /* Unsupported baud rate. */
617        return -1;
618    }
619
620    tk1_uart_set_dlab_divisor(d, divisor);
621
622    /* Disable hardware flow control for all UARTs other than UARTD,
623     * because UARTD actually has an RS232 pinout port.
624     */
625    if (d->id != NV_UARTD && d->id != NV_UARTD_ASYNC) {
626        uint32_t mcr = regs->mcr;
627
628        /* Clear RTS_EN and CTS_EN. */
629        mcr &= ~(BIT(6) | BIT(5));
630        /* Force RTS and DTR to low (active) */
631        mcr |= (BIT(1) | BIT(0));
632        regs->mcr = mcr;
633    }
634
635    /* Drain the RX buffer when configuring a new set of line options.
636     * By implication, the caller should wait for previous transmissions to be
637     * completed before reconfiguring.
638     */
639    while (uart_getchar(d) != -1) {
640    }
641
642    if (tk1_uart_is_async(d)) {
643        /* Re-enable receive IRQ. */
644        tk1_uart_set_rbr_irq(regs, true);
645    }
646
647    return 0;
648}
649
650/** Initialize a ps_chardevice_t instance.
651 *
652 * Expects an already valid mapping to the TK1 UART MMIO vaddr range.
653 */
654int
655tk1_uart_init_common(const struct dev_defn *defn, void *const uart_mmio_vaddr,
656                     ps_chardevice_t *dev)
657{
658    volatile void *uart_vaddr = 0;
659    tk1_uart_regs_t* regs;
660    uint32_t iir_fcr;
661    struct chardev_xmit_descriptor cxd_zero = {0};
662    ps_io_ops_t ioops_zero = {{0}};
663
664    /* add offsets properly */
665    switch (defn->id) {
666        case NV_UARTA:
667        case NV_UARTA_ASYNC:
668            uart_vaddr = uart_mmio_vaddr;
669            break;
670        case NV_UARTB:
671        case NV_UARTB_ASYNC:
672            uart_vaddr = uart_mmio_vaddr + UARTB_OFFSET;
673            break;
674        case NV_UARTC:
675        case NV_UARTC_ASYNC:
676            uart_vaddr = uart_mmio_vaddr + UARTC_OFFSET;
677            break;
678        case NV_UARTD:
679        case NV_UARTD_ASYNC:
680            uart_vaddr = uart_mmio_vaddr + UARTD_OFFSET;
681            /* The kernel uses UART-D. Recommend not conflicting with it. */
682            break;
683        default:
684            return -1;
685    }
686
687    memset(dev, 0, sizeof(*dev));
688
689    /* Set up all the  device properties. */
690    dev->id         = defn->id;
691    dev->vaddr      = (void*)uart_vaddr;
692    dev->read       = &tk1_uart_read;
693    dev->write      = &tk1_uart_write;
694    dev->handle_irq = &uart_handle_irq;
695    dev->irqs       = defn->irqs;
696    dev->ioops      = ioops_zero;
697    dev->flags      = SERIAL_AUTO_CR;
698
699    /* Zero out the client state. */
700    dev->write_descriptor = cxd_zero;
701    dev->read_descriptor = cxd_zero;
702
703    regs = tk1_uart_get_priv(dev);
704
705    /* Disable IRQs. */
706    tk1_uart_set_rbr_irq(regs, false);
707    tk1_uart_set_thr_irq(regs, false);
708
709    /* Line configuration */
710    serial_configure(dev, 115200, 8, PARITY_NONE, 1);
711
712    /* Set FCR[0] to 1 to enable FIFO mode, and enable DMA mode 1 which will
713     * generate an interrupt only when the buffer has.
714     *
715     * There's no point in doing an R-M-W sequence because reading the FCR
716     * actually returns the values from the IIR, so you can't actually read FCR.
717     */
718    iir_fcr = 0
719        | FCR_FIFO_ENABLE | FCR_DMA_MODE0
720        | ENCODE_BITS(0, FCR_RX_TRIG_SHIFT, FCR_RX_TRIG_MASK, FCR_RX_TRIG_FIFO_GT_16)
721        | ENCODE_BITS(0, FCR_TX_TRIG_SHIFT, FCR_TX_TRIG_MASK, FCR_TX_TRIG_FIFO_GT_16)
722        | BIT(FCR_TX_FIFO_CLEAR_SHIFT)
723        | BIT(FCR_RX_FIFO_CLEAR_SHIFT);
724
725    regs->iir_fcr = iir_fcr;
726
727    /* Read the status bit to ensure the FIFO was enabled. */
728    iir_fcr = regs->iir_fcr;
729    if (EXTRACT_BITS(iir_fcr,
730                     IIR_FIFO_MODE_STATUS_SHIFT,
731                     IIR_FIFO_MODE_STATUS_MASK) != 3) {
732        ZF_LOGE("FIFO mode wasn't enabled.\n");
733        return -1;
734    }
735
736    return 0;
737}
738
739/** Initializes a ps_chardevice_t.
740 *
741 * Expects a viable ps_io_ops_t for mapping the registers.
742 */
743int
744uart_init(const struct dev_defn* defn,
745              const ps_io_ops_t* ops,
746              ps_chardevice_t* dev)
747{
748    static void *vaddr = 0;
749    int ret;
750
751    /* Attempt to map the virtual address, assure this works */
752    if (vaddr == 0) {
753        vaddr = chardev_map(defn, ops);
754
755        if (vaddr == NULL) {
756            return -1;
757        }
758    }
759
760    ret = tk1_uart_init_common(defn, vaddr, dev);
761    dev->ioops = *ops;
762    return ret;
763}
764