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 <util.h>
36
37 /* Register definitions */
38 #define URXD 0x0 /* Receiver Register */
39 #define UTXD 0x40 /* Transmitter Register */
40 #define UCR1 0x80 /* Control Register 1 */
41 #define UCR2 0x84 /* Control Register 2 */
42 #define UCR3 0x88 /* Control Register 3 */
43 #define UCR4 0x8c /* Control Register 4 */
44 #define UFCR 0x90 /* FIFO Control Register */
45 #define USR1 0x94 /* Status Register 1 */
46 #define USR2 0x98 /* Status Register 2 */
47 #define UESC 0x9c /* Escape Character Register */
48 #define UTIM 0xa0 /* Escape Timer Register */
49 #define UBIR 0xa4 /* BRM Incremental Register */
50 #define UBMR 0xa8 /* BRM Modulator Register */
51 #define UBRC 0xac /* Baud Rate Count Register */
52 #define UTS 0xb4 /* UART Test Register (mx31) */
53 #define USIZE 0xb8 /* UTS + sizeof(uint32_t) */
54
55 /* UART Control Register Bit Fields.*/
56 #define URXD_CHARRDY (1<<15)
57 #define URXD_ERR (1<<14)
58 #define URXD_OVRRUN (1<<13)
59 #define URXD_FRMERR (1<<12)
60 #define URXD_BRK (1<<11)
61 #define URXD_PRERR (1<<10)
62 #define URXD_RX_DATA (0xFF)
63 #define UCR1_ADEN (1<<15) /* Auto dectect interrupt */
64 #define UCR1_ADBR (1<<14) /* Auto detect baud rate */
65 #define UCR1_TRDYEN (1<<13) /* Transmitter ready interrupt enable */
66 #define UCR1_IDEN (1<<12) /* Idle condition interrupt */
67 #define UCR1_RRDYEN (1<<9) /* Recv ready interrupt enable */
68 #define UCR1_RDMAEN (1<<8) /* Recv ready DMA enable */
69 #define UCR1_IREN (1<<7) /* Infrared interface enable */
70 #define UCR1_TXMPTYEN (1<<6) /* Transimitter empty interrupt enable */
71 #define UCR1_RTSDEN (1<<5) /* RTS delta interrupt enable */
72 #define UCR1_SNDBRK (1<<4) /* Send break */
73 #define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */
74 #define UCR1_UARTCLKEN (1<<2) /* UART clock enabled */
75 #define UCR1_DOZE (1<<1) /* Doze */
76 #define UCR1_UARTEN (1<<0) /* UART enabled */
77
78 #define UTS_FRCPERR (1<<13) /* Force parity error */
79 #define UTS_LOOP (1<<12) /* Loop tx and rx */
80 #define UTS_TXEMPTY (1<<6) /* TxFIFO empty */
81 #define UTS_RXEMPTY (1<<5) /* RxFIFO empty */
82 #define UTS_TXFULL (1<<4) /* TxFIFO full */
83 #define UTS_RXFULL (1<<3) /* RxFIFO full */
84 #define UTS_SOFTRST (1<<0) /* Software reset */
85
chip_to_base(struct serial_chip * chip)86 static vaddr_t chip_to_base(struct serial_chip *chip)
87 {
88 struct imx_uart_data *pd =
89 container_of(chip, struct imx_uart_data, chip);
90
91 return io_pa_or_va(&pd->base, USIZE);
92 }
93
imx_uart_flush(struct serial_chip * chip)94 static void imx_uart_flush(struct serial_chip *chip)
95 {
96 vaddr_t base = chip_to_base(chip);
97
98
99 while (!(io_read32(base + UTS) & UTS_TXEMPTY))
100 if (!(io_read32(base + UCR1) & UCR1_UARTEN))
101 return;
102 }
103
imx_uart_getchar(struct serial_chip * chip)104 static int imx_uart_getchar(struct serial_chip *chip)
105 {
106 vaddr_t base = chip_to_base(chip);
107
108 while (io_read32(base + UTS) & UTS_RXEMPTY)
109 ;
110
111 return (io_read32(base + URXD) & URXD_RX_DATA);
112 }
113
imx_uart_putc(struct serial_chip * chip,int ch)114 static void imx_uart_putc(struct serial_chip *chip, int ch)
115 {
116 vaddr_t base = chip_to_base(chip);
117
118 /* Wait until there's space in the TX FIFO */
119 while (io_read32(base + UTS) & UTS_TXFULL)
120 if (!(io_read32(base + UCR1) & UCR1_UARTEN))
121 return;
122
123 io_write32(base + UTXD, ch);
124 }
125
126 static const struct serial_ops imx_uart_ops = {
127 .flush = imx_uart_flush,
128 .getchar = imx_uart_getchar,
129 .putc = imx_uart_putc,
130 };
131 DECLARE_KEEP_PAGER(imx_uart_ops);
132
imx_uart_init(struct imx_uart_data * pd,paddr_t base)133 void imx_uart_init(struct imx_uart_data *pd, paddr_t base)
134 {
135 pd->base.pa = base;
136 pd->chip.ops = &imx_uart_ops;
137
138 /*
139 * Do nothing, debug uart(uart0) share with normal world,
140 * everything for uart0 initialization is done in bootloader.
141 */
142 }
143
144 #ifdef CFG_DT
imx_uart_dev_alloc(void)145 static struct serial_chip *imx_uart_dev_alloc(void)
146 {
147 struct imx_uart_data *pd = calloc(1, sizeof(*pd));
148
149 if (!pd)
150 return NULL;
151
152 return &pd->chip;
153 }
154
imx_uart_dev_init(struct serial_chip * chip,const void * fdt,int offs,const char * parms)155 static int imx_uart_dev_init(struct serial_chip *chip, const void *fdt,
156 int offs, const char *parms)
157 {
158 struct imx_uart_data *pd =
159 container_of(chip, struct imx_uart_data, chip);
160 vaddr_t vbase = 0;
161 paddr_t pbase = 0;
162 size_t size = 0;
163
164 if (parms && parms[0])
165 IMSG("imx_uart: device parameters ignored (%s)", parms);
166
167 if (dt_map_dev(fdt, offs, &vbase, &size, DT_MAP_AUTO) < 0)
168 return -1;
169
170 pbase = virt_to_phys((void *)vbase);
171 imx_uart_init(pd, pbase);
172
173 return 0;
174 }
175
imx_uart_dev_free(struct serial_chip * chip)176 static void imx_uart_dev_free(struct serial_chip *chip)
177 {
178 struct imx_uart_data *pd =
179 container_of(chip, struct imx_uart_data, chip);
180
181 free(pd);
182 }
183
184 static const struct serial_driver imx_uart_driver = {
185 .dev_alloc = imx_uart_dev_alloc,
186 .dev_init = imx_uart_dev_init,
187 .dev_free = imx_uart_dev_free,
188 };
189
190 static const struct dt_device_match imx_match_table[] = {
191 { .compatible = "fsl,imx6q-uart" },
192 { 0 }
193 };
194
195 DEFINE_DT_DRIVER(imx_dt_driver) = {
196 .name = "imx_uart",
197 .type = DT_DRIVER_UART,
198 .match_table = imx_match_table,
199 .driver = &imx_uart_driver,
200 };
201
202 #endif /* CFG_DT */
203