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
13#include <autoconf.h>
14#include <platsupport/gen_config.h>
15
16#include <stdlib.h>
17#include <platsupport/serial.h>
18#include <platsupport/plat/serial.h>
19#include <string.h>
20
21#include "../../../chardev.h"
22
23#ifndef UART_REF_CLK
24#error "UART_REF_CLK undefined"
25#endif
26
27#define UART_SR1_RRDY          BIT( 9)
28#define UART_SR1_TRDY          BIT(13)
29/* CR1 */
30#define UART_CR1_UARTEN        BIT( 0)
31#define UART_CR1_RRDYEN        BIT( 9)
32/* CR2 */
33#define UART_CR2_SRST          BIT( 0)
34#define UART_CR2_RXEN          BIT( 1)
35#define UART_CR2_TXEN          BIT( 2)
36#define UART_CR2_ATEN          BIT( 3)
37#define UART_CR2_RTSEN         BIT( 4)
38#define UART_CR2_WS            BIT( 5)
39#define UART_CR2_STPB          BIT( 6)
40#define UART_CR2_PROE          BIT( 7)
41#define UART_CR2_PREN          BIT( 8)
42#define UART_CR2_RTEC          BIT( 9)
43#define UART_CR2_ESCEN         BIT(11)
44#define UART_CR2_CTS           BIT(12)
45#define UART_CR2_CTSC          BIT(13)
46#define UART_CR2_IRTS          BIT(14)
47#define UART_CR2_ESCI          BIT(15)
48/* CR3 */
49#define UART_CR3_RXDMUXDEL     BIT( 2)
50/* FCR */
51#define UART_FCR_RFDIV(x)      ((x) * BIT(7))
52#define UART_FCR_RFDIV_MASK    UART_FCR_RFDIV(0x7)
53#define UART_FCR_RXTL(x)       ((x) * BIT(0))
54#define UART_FCR_RXTL_MASK     UART_FCR_RXTL(0x1F)
55/* SR2 */
56#define UART_SR2_RXFIFO_RDR    BIT(0)
57#define UART_SR2_TXFIFO_EMPTY  BIT(14)
58/* RXD */
59#define UART_URXD_READY_MASK   BIT(15)
60#define UART_BYTE_MASK         0xFF
61
62struct imx_uart_regs {
63    uint32_t rxd;      /* 0x000 Receiver Register */
64    uint32_t res0[15];
65    uint32_t txd;      /* 0x040 Transmitter Register */
66    uint32_t res1[15];
67    uint32_t cr1;      /* 0x080 Control Register 1 */
68    uint32_t cr2;      /* 0x084 Control Register 2 */
69    uint32_t cr3;      /* 0x088 Control Register 3 */
70    uint32_t cr4;      /* 0x08C Control Register 4 */
71    uint32_t fcr;      /* 0x090 FIFO Control Register */
72    uint32_t sr1;      /* 0x094 Status Register 1 */
73    uint32_t sr2;      /* 0x098 Status Register 2 */
74    uint32_t esc;      /* 0x09c Escape Character Register */
75    uint32_t tim;      /* 0x0a0 Escape Timer Register */
76    uint32_t bir;      /* 0x0a4 BRM Incremental Register */
77    uint32_t bmr;      /* 0x0a8 BRM Modulator Register */
78    uint32_t brc;      /* 0x0ac Baud Rate Counter Register */
79    uint32_t onems;    /* 0x0b0 One Millisecond Register */
80    uint32_t ts;       /* 0x0b4 Test Register */
81};
82typedef volatile struct imx_uart_regs imx_uart_regs_t;
83
84static inline imx_uart_regs_t *imx_uart_get_priv(
85    ps_chardevice_t *d)
86{
87    return (imx_uart_regs_t *)d->vaddr;
88}
89
90int uart_getchar(
91    ps_chardevice_t *d)
92{
93    imx_uart_regs_t *regs = imx_uart_get_priv(d);
94    uint32_t reg = 0;
95    int c = -1;
96
97    if (regs->sr2 & UART_SR2_RXFIFO_RDR) {
98        reg = regs->rxd;
99        if (reg & UART_URXD_READY_MASK) {
100            c = reg & UART_BYTE_MASK;
101        }
102    }
103    return c;
104}
105
106static int internal_is_tx_fifo_busy(
107    imx_uart_regs_t *regs)
108{
109    /* check the TXFE (transmit buffer FIFO empty) flag, which is cleared
110     * automatically when data is written to the TxFIFO. Even though the flag
111     * is set, the actual data transmission via the UART's 32 byte FIFO buffer
112     * might still be in progress.
113     */
114    return (0 == (regs->sr2 & UART_SR2_TXFIFO_EMPTY));
115}
116
117int uart_putchar(
118    ps_chardevice_t *d,
119    int c)
120{
121    imx_uart_regs_t *regs = imx_uart_get_priv(d);
122
123    if (internal_is_tx_fifo_busy(regs)) {
124        return -1;
125    }
126
127    if (c == '\n' && (d->flags & SERIAL_AUTO_CR)) {
128        /* write CR first */
129        regs->txd = '\r';
130        /* if we transform a '\n' (LF) into '\r\n' (CR+LF) this shall become an
131         * atom, ie we don't want CR to be sent and then fail at sending LF
132         * because the TX FIFO is full. Basically there are two options:
133         *   - check if the FIFO can hold CR+LF and either send both or none
134         *   - send CR, then block until the FIFO has space and send LF.
135         * Assuming that if SERIAL_AUTO_CR is set, it's likely this is a serial
136         * console for logging, so blocking seems acceptable in this special
137         * case. The IMX6's TX FIFO size is 32 byte and TXFIFO_EMPTY is cleared
138         * automatically as soon as data is written from regs->txd into the
139         * FIFO. Thus the worst case blocking is roughly the time it takes to
140         * send 1 byte to have room in the FIFO again. At 115200 baud with 8N1
141         * this takes 10 bit-times, which is 10/115200 = 86,8 usec.
142         */
143        while (internal_is_tx_fifo_busy(regs)) {
144            /* busy loop */
145        }
146    }
147
148    regs->txd = c;
149    return c;
150}
151
152static void uart_handle_irq(ps_chardevice_t *d UNUSED)
153{
154    /* TODO */
155}
156
157/*
158 * BaudRate = RefFreq / (16 * (BMR + 1)/(BIR + 1) )
159 * BMR and BIR are 16 bit
160 */
161static void imx_uart_set_baud(
162    ps_chardevice_t *d,
163    long bps)
164{
165    imx_uart_regs_t *regs = imx_uart_get_priv(d);
166    uint32_t bmr, bir, fcr;
167    fcr = regs->fcr;
168    fcr &= ~UART_FCR_RFDIV_MASK;
169    fcr |= UART_FCR_RFDIV(4);
170    bir = 0xf;
171    bmr = UART_REF_CLK / bps - 1;
172    regs->bir = bir;
173    regs->bmr = bmr;
174    regs->fcr = fcr;
175}
176
177int serial_configure(
178    ps_chardevice_t *d,
179    long bps,
180    int char_size,
181    enum serial_parity parity,
182    int stop_bits)
183{
184    imx_uart_regs_t *regs = imx_uart_get_priv(d);
185    uint32_t cr2;
186    /* Character size */
187    cr2 = regs->cr2;
188    if (char_size == 8) {
189        cr2 |= UART_CR2_WS;
190    } else if (char_size == 7) {
191        cr2 &= ~UART_CR2_WS;
192    } else {
193        return -1;
194    }
195    /* Stop bits */
196    if (stop_bits == 2) {
197        cr2 |= UART_CR2_STPB;
198    } else if (stop_bits == 1) {
199        cr2 &= ~UART_CR2_STPB;
200    } else {
201        return -1;
202    }
203    /* Parity */
204    if (parity == PARITY_NONE) {
205        cr2 &= ~UART_CR2_PREN;
206    } else if (parity == PARITY_ODD) {
207        /* ODD */
208        cr2 |= UART_CR2_PREN;
209        cr2 |= UART_CR2_PROE;
210    } else if (parity == PARITY_EVEN) {
211        /* Even */
212        cr2 |= UART_CR2_PREN;
213        cr2 &= ~UART_CR2_PROE;
214    } else {
215        return -1;
216    }
217    /* Apply the changes */
218    regs->cr2 = cr2;
219    /* Now set the board rate */
220    imx_uart_set_baud(d, bps);
221    return 0;
222}
223
224int uart_init(
225    const struct dev_defn *defn,
226    const ps_io_ops_t *ops,
227    ps_chardevice_t *dev)
228{
229    /* Attempt to map the virtual address, assure this works */
230    void *vaddr = chardev_map(defn, ops);
231    if (vaddr == NULL) {
232        return -1;
233    }
234
235    memset(dev, 0, sizeof(*dev));
236
237    /* Set up all the  device properties. */
238    dev->id         = defn->id;
239    dev->vaddr      = (void *)vaddr;
240    dev->read       = &uart_read;
241    dev->write      = &uart_write;
242    dev->handle_irq = &uart_handle_irq;
243    dev->irqs       = defn->irqs;
244    dev->ioops      = *ops;
245    dev->flags      = SERIAL_AUTO_CR;
246
247    imx_uart_regs_t *regs = imx_uart_get_priv(dev);
248
249    /* Software reset */
250    regs->cr2 &= ~UART_CR2_SRST;
251    while (!(regs->cr2 & UART_CR2_SRST));
252
253    /* Line configuration */
254    serial_configure(dev, 115200, 8, PARITY_NONE, 1);
255
256    /* Enable the UART */
257    regs->cr1 |= UART_CR1_UARTEN;                /* Enable The uart.                  */
258    regs->cr2 |= UART_CR2_RXEN | UART_CR2_TXEN;  /* RX/TX enable                      */
259    regs->cr2 |= UART_CR2_IRTS;                  /* Ignore RTS                        */
260    regs->cr3 |= UART_CR3_RXDMUXDEL;             /* Configure the RX MUX              */
261    /* Initialise the receiver interrupt.                                             */
262    regs->cr1 &= ~UART_CR1_RRDYEN;               /* Disable recv interrupt.           */
263    regs->fcr &= ~UART_FCR_RXTL_MASK;            /* Clear the rx trigger level value. */
264    regs->fcr |= UART_FCR_RXTL(1);               /* Set the rx tigger level to 1.     */
265    regs->cr1 |= UART_CR1_RRDYEN;                /* Enable recv interrupt.            */
266
267
268#ifdef CONFIG_PLAT_IMX6
269#include <platsupport/plat/mux.h>
270    /* The UART1 on the IMX6 has the problem that the MUX is not correctly set,
271     * and the RX PIN is not routed correctly.
272     */
273    if ((defn->id == IMX_UART1) && mux_sys_valid(&ops->mux_sys)) {
274        if (mux_feature_enable(&ops->mux_sys, MUX_UART1, 0)) {
275            /* Failed to configure the mux */
276            return -1;
277        }
278    }
279#endif
280
281    return 0;
282}
283