1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (C) 2015 Freescale Semiconductor, Inc.
4 * All rights reserved.
5 * Copyright 2018-2019 NXP.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include <assert.h>
31 #include <drivers/imx_uart.h>
32 #include <io.h>
33 #include <keep.h>
34 #include <kernel/dt.h>
35 #include <kernel/dt_driver.h>
36 #include <util.h>
37
38 /* Register definitions */
39 #define URXD 0x0 /* Receiver Register */
40 #define UTXD 0x40 /* Transmitter Register */
41 #define UCR1 0x80 /* Control Register 1 */
42 #define UCR2 0x84 /* Control Register 2 */
43 #define UCR3 0x88 /* Control Register 3 */
44 #define UCR4 0x8c /* Control Register 4 */
45 #define UFCR 0x90 /* FIFO Control Register */
46 #define USR1 0x94 /* Status Register 1 */
47 #define USR2 0x98 /* Status Register 2 */
48 #define UESC 0x9c /* Escape Character Register */
49 #define UTIM 0xa0 /* Escape Timer Register */
50 #define UBIR 0xa4 /* BRM Incremental Register */
51 #define UBMR 0xa8 /* BRM Modulator Register */
52 #define UBRC 0xac /* Baud Rate Count Register */
53 #define UTS 0xb4 /* UART Test Register (mx31) */
54 #define USIZE 0xb8 /* UTS + sizeof(uint32_t) */
55
56 /* UART Control Register Bit Fields.*/
57 #define URXD_CHARRDY (1<<15)
58 #define URXD_ERR (1<<14)
59 #define URXD_OVRRUN (1<<13)
60 #define URXD_FRMERR (1<<12)
61 #define URXD_BRK (1<<11)
62 #define URXD_PRERR (1<<10)
63 #define URXD_RX_DATA (0xFF)
64 #define UCR1_ADEN (1<<15) /* Auto dectect interrupt */
65 #define UCR1_ADBR (1<<14) /* Auto detect baud rate */
66 #define UCR1_TRDYEN (1<<13) /* Transmitter ready interrupt enable */
67 #define UCR1_IDEN (1<<12) /* Idle condition interrupt */
68 #define UCR1_RRDYEN (1<<9) /* Recv ready interrupt enable */
69 #define UCR1_RDMAEN (1<<8) /* Recv ready DMA enable */
70 #define UCR1_IREN (1<<7) /* Infrared interface enable */
71 #define UCR1_TXMPTYEN (1<<6) /* Transimitter empty interrupt enable */
72 #define UCR1_RTSDEN (1<<5) /* RTS delta interrupt enable */
73 #define UCR1_SNDBRK (1<<4) /* Send break */
74 #define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */
75 #define UCR1_UARTCLKEN (1<<2) /* UART clock enabled */
76 #define UCR1_DOZE (1<<1) /* Doze */
77 #define UCR1_UARTEN (1<<0) /* UART enabled */
78
79 #define UTS_FRCPERR (1<<13) /* Force parity error */
80 #define UTS_LOOP (1<<12) /* Loop tx and rx */
81 #define UTS_TXEMPTY (1<<6) /* TxFIFO empty */
82 #define UTS_RXEMPTY (1<<5) /* RxFIFO empty */
83 #define UTS_TXFULL (1<<4) /* TxFIFO full */
84 #define UTS_RXFULL (1<<3) /* RxFIFO full */
85 #define UTS_SOFTRST (1<<0) /* Software reset */
86
chip_to_base(struct serial_chip * chip)87 static vaddr_t chip_to_base(struct serial_chip *chip)
88 {
89 struct imx_uart_data *pd =
90 container_of(chip, struct imx_uart_data, chip);
91
92 return io_pa_or_va(&pd->base, USIZE);
93 }
94
imx_uart_flush(struct serial_chip * chip)95 static void imx_uart_flush(struct serial_chip *chip)
96 {
97 vaddr_t base = chip_to_base(chip);
98
99
100 while (!(io_read32(base + UTS) & UTS_TXEMPTY))
101 if (!(io_read32(base + UCR1) & UCR1_UARTEN))
102 return;
103 }
104
imx_uart_getchar(struct serial_chip * chip)105 static int imx_uart_getchar(struct serial_chip *chip)
106 {
107 vaddr_t base = chip_to_base(chip);
108
109 while (io_read32(base + UTS) & UTS_RXEMPTY)
110 ;
111
112 return (io_read32(base + URXD) & URXD_RX_DATA);
113 }
114
imx_uart_putc(struct serial_chip * chip,int ch)115 static void imx_uart_putc(struct serial_chip *chip, int ch)
116 {
117 vaddr_t base = chip_to_base(chip);
118
119 /* Wait until there's space in the TX FIFO */
120 while (io_read32(base + UTS) & UTS_TXFULL)
121 if (!(io_read32(base + UCR1) & UCR1_UARTEN))
122 return;
123
124 io_write32(base + UTXD, ch);
125 }
126
127 static const struct serial_ops imx_uart_ops = {
128 .flush = imx_uart_flush,
129 .getchar = imx_uart_getchar,
130 .putc = imx_uart_putc,
131 };
132 DECLARE_KEEP_PAGER(imx_uart_ops);
133
imx_uart_init(struct imx_uart_data * pd,paddr_t base)134 void imx_uart_init(struct imx_uart_data *pd, paddr_t base)
135 {
136 pd->base.pa = base;
137 pd->chip.ops = &imx_uart_ops;
138
139 /*
140 * Do nothing, debug uart(uart0) share with normal world,
141 * everything for uart0 initialization is done in bootloader.
142 */
143 }
144
145 #ifdef CFG_DT
imx_uart_dev_alloc(void)146 static struct serial_chip *imx_uart_dev_alloc(void)
147 {
148 struct imx_uart_data *pd = calloc(1, sizeof(*pd));
149
150 if (!pd)
151 return NULL;
152
153 return &pd->chip;
154 }
155
imx_uart_dev_init(struct serial_chip * chip,const void * fdt,int offs,const char * parms)156 static int imx_uart_dev_init(struct serial_chip *chip, const void *fdt,
157 int offs, const char *parms)
158 {
159 struct imx_uart_data *pd =
160 container_of(chip, struct imx_uart_data, chip);
161 vaddr_t vbase = 0;
162 paddr_t pbase = 0;
163 size_t size = 0;
164
165 if (parms && parms[0])
166 IMSG("imx_uart: device parameters ignored (%s)", parms);
167
168 if (dt_map_dev(fdt, offs, &vbase, &size, DT_MAP_AUTO) < 0)
169 return -1;
170
171 pbase = virt_to_phys((void *)vbase);
172 imx_uart_init(pd, pbase);
173
174 return 0;
175 }
176
imx_uart_dev_free(struct serial_chip * chip)177 static void imx_uart_dev_free(struct serial_chip *chip)
178 {
179 struct imx_uart_data *pd =
180 container_of(chip, struct imx_uart_data, chip);
181
182 free(pd);
183 }
184
185 static const struct serial_driver imx_uart_driver = {
186 .dev_alloc = imx_uart_dev_alloc,
187 .dev_init = imx_uart_dev_init,
188 .dev_free = imx_uart_dev_free,
189 };
190
191 static const struct dt_device_match imx_match_table[] = {
192 { .compatible = "fsl,imx6q-uart" },
193 { 0 }
194 };
195
196 DEFINE_DT_DRIVER(imx_dt_driver) = {
197 .name = "imx_uart",
198 .type = DT_DRIVER_UART,
199 .match_table = imx_match_table,
200 .driver = &imx_uart_driver,
201 };
202
203 #endif /* CFG_DT */
204