Commit f3e87ac7e40055c51d0808d4048aab438fb1ec7b

Authored by Ye Li
1 parent 1f3aebcd52

MLK-24192-1 lpuart: Enable IPG clock

Current codes only ennable the PER clock. However on iMX8 the LPUART
also needs IPG clock which is an LPCG. Should not depend on the default
LPCG setting.

Signed-off-by: Ye Li <ye.li@nxp.com>
Reviewed-by: Peng Fan <peng.fan@nxp.com>
(cherry picked from commit aa984f5f4029b743842ea7928d0af8da06b1b25d)

Showing 1 changed file with 13 additions and 1 deletions Inline Diff

drivers/serial/serial_lpuart.c
1 // SPDX-License-Identifier: GPL-2.0+ 1 // SPDX-License-Identifier: GPL-2.0+
2 /* 2 /*
3 * Copyright 2019 NXP 3 * Copyright 2019 NXP
4 * Copyright 2013 Freescale Semiconductor, Inc. 4 * Copyright 2013 Freescale Semiconductor, Inc.
5 */ 5 */
6 6
7 #include <common.h> 7 #include <common.h>
8 #include <clk.h> 8 #include <clk.h>
9 #include <dm.h> 9 #include <dm.h>
10 #include <fsl_lpuart.h> 10 #include <fsl_lpuart.h>
11 #include <watchdog.h> 11 #include <watchdog.h>
12 #include <asm/io.h> 12 #include <asm/io.h>
13 #include <serial.h> 13 #include <serial.h>
14 #include <dm/device_compat.h> 14 #include <dm/device_compat.h>
15 #include <linux/compiler.h> 15 #include <linux/compiler.h>
16 #include <asm/arch/imx-regs.h> 16 #include <asm/arch/imx-regs.h>
17 #include <asm/arch/clock.h> 17 #include <asm/arch/clock.h>
18 18
19 #define US1_TDRE (1 << 7) 19 #define US1_TDRE (1 << 7)
20 #define US1_RDRF (1 << 5) 20 #define US1_RDRF (1 << 5)
21 #define US1_OR (1 << 3) 21 #define US1_OR (1 << 3)
22 #define UC2_TE (1 << 3) 22 #define UC2_TE (1 << 3)
23 #define UC2_RE (1 << 2) 23 #define UC2_RE (1 << 2)
24 #define CFIFO_TXFLUSH (1 << 7) 24 #define CFIFO_TXFLUSH (1 << 7)
25 #define CFIFO_RXFLUSH (1 << 6) 25 #define CFIFO_RXFLUSH (1 << 6)
26 #define SFIFO_RXOF (1 << 2) 26 #define SFIFO_RXOF (1 << 2)
27 #define SFIFO_RXUF (1 << 0) 27 #define SFIFO_RXUF (1 << 0)
28 28
29 #define STAT_LBKDIF (1 << 31) 29 #define STAT_LBKDIF (1 << 31)
30 #define STAT_RXEDGIF (1 << 30) 30 #define STAT_RXEDGIF (1 << 30)
31 #define STAT_TDRE (1 << 23) 31 #define STAT_TDRE (1 << 23)
32 #define STAT_RDRF (1 << 21) 32 #define STAT_RDRF (1 << 21)
33 #define STAT_IDLE (1 << 20) 33 #define STAT_IDLE (1 << 20)
34 #define STAT_OR (1 << 19) 34 #define STAT_OR (1 << 19)
35 #define STAT_NF (1 << 18) 35 #define STAT_NF (1 << 18)
36 #define STAT_FE (1 << 17) 36 #define STAT_FE (1 << 17)
37 #define STAT_PF (1 << 16) 37 #define STAT_PF (1 << 16)
38 #define STAT_MA1F (1 << 15) 38 #define STAT_MA1F (1 << 15)
39 #define STAT_MA2F (1 << 14) 39 #define STAT_MA2F (1 << 14)
40 #define STAT_FLAGS (STAT_LBKDIF | STAT_RXEDGIF | STAT_IDLE | STAT_OR | \ 40 #define STAT_FLAGS (STAT_LBKDIF | STAT_RXEDGIF | STAT_IDLE | STAT_OR | \
41 STAT_NF | STAT_FE | STAT_PF | STAT_MA1F | STAT_MA2F) 41 STAT_NF | STAT_FE | STAT_PF | STAT_MA1F | STAT_MA2F)
42 42
43 #define CTRL_TE (1 << 19) 43 #define CTRL_TE (1 << 19)
44 #define CTRL_RE (1 << 18) 44 #define CTRL_RE (1 << 18)
45 45
46 #define FIFO_RXFLUSH BIT(14) 46 #define FIFO_RXFLUSH BIT(14)
47 #define FIFO_TXFLUSH BIT(15) 47 #define FIFO_TXFLUSH BIT(15)
48 #define FIFO_TXSIZE_MASK 0x70 48 #define FIFO_TXSIZE_MASK 0x70
49 #define FIFO_TXSIZE_OFF 4 49 #define FIFO_TXSIZE_OFF 4
50 #define FIFO_RXSIZE_MASK 0x7 50 #define FIFO_RXSIZE_MASK 0x7
51 #define FIFO_RXSIZE_OFF 0 51 #define FIFO_RXSIZE_OFF 0
52 #define FIFO_TXFE 0x80 52 #define FIFO_TXFE 0x80
53 #if defined(CONFIG_ARCH_IMX8) || defined(CONFIG_ARCH_IMXRT) 53 #if defined(CONFIG_ARCH_IMX8) || defined(CONFIG_ARCH_IMXRT)
54 #define FIFO_RXFE 0x08 54 #define FIFO_RXFE 0x08
55 #else 55 #else
56 #define FIFO_RXFE 0x40 56 #define FIFO_RXFE 0x40
57 #endif 57 #endif
58 58
59 #define WATER_TXWATER_OFF 0 59 #define WATER_TXWATER_OFF 0
60 #define WATER_RXWATER_OFF 16 60 #define WATER_RXWATER_OFF 16
61 61
62 DECLARE_GLOBAL_DATA_PTR; 62 DECLARE_GLOBAL_DATA_PTR;
63 63
64 #define LPUART_FLAG_REGMAP_32BIT_REG BIT(0) 64 #define LPUART_FLAG_REGMAP_32BIT_REG BIT(0)
65 #define LPUART_FLAG_REGMAP_ENDIAN_BIG BIT(1) 65 #define LPUART_FLAG_REGMAP_ENDIAN_BIG BIT(1)
66 66
67 enum lpuart_devtype { 67 enum lpuart_devtype {
68 DEV_VF610 = 1, 68 DEV_VF610 = 1,
69 DEV_LS1021A, 69 DEV_LS1021A,
70 DEV_MX7ULP, 70 DEV_MX7ULP,
71 DEV_IMX8, 71 DEV_IMX8,
72 DEV_IMXRT, 72 DEV_IMXRT,
73 }; 73 };
74 74
75 struct lpuart_serial_platdata { 75 struct lpuart_serial_platdata {
76 void *reg; 76 void *reg;
77 enum lpuart_devtype devtype; 77 enum lpuart_devtype devtype;
78 ulong flags; 78 ulong flags;
79 }; 79 };
80 80
81 static void lpuart_read32(u32 flags, u32 *addr, u32 *val) 81 static void lpuart_read32(u32 flags, u32 *addr, u32 *val)
82 { 82 {
83 if (flags & LPUART_FLAG_REGMAP_32BIT_REG) { 83 if (flags & LPUART_FLAG_REGMAP_32BIT_REG) {
84 if (flags & LPUART_FLAG_REGMAP_ENDIAN_BIG) 84 if (flags & LPUART_FLAG_REGMAP_ENDIAN_BIG)
85 *(u32 *)val = in_be32(addr); 85 *(u32 *)val = in_be32(addr);
86 else 86 else
87 *(u32 *)val = in_le32(addr); 87 *(u32 *)val = in_le32(addr);
88 } 88 }
89 } 89 }
90 90
91 static void lpuart_write32(u32 flags, u32 *addr, u32 val) 91 static void lpuart_write32(u32 flags, u32 *addr, u32 val)
92 { 92 {
93 if (flags & LPUART_FLAG_REGMAP_32BIT_REG) { 93 if (flags & LPUART_FLAG_REGMAP_32BIT_REG) {
94 if (flags & LPUART_FLAG_REGMAP_ENDIAN_BIG) 94 if (flags & LPUART_FLAG_REGMAP_ENDIAN_BIG)
95 out_be32(addr, val); 95 out_be32(addr, val);
96 else 96 else
97 out_le32(addr, val); 97 out_le32(addr, val);
98 } 98 }
99 } 99 }
100 100
101 101
102 #ifndef CONFIG_SYS_CLK_FREQ 102 #ifndef CONFIG_SYS_CLK_FREQ
103 #define CONFIG_SYS_CLK_FREQ 0 103 #define CONFIG_SYS_CLK_FREQ 0
104 #endif 104 #endif
105 105
106 u32 __weak get_lpuart_clk(void) 106 u32 __weak get_lpuart_clk(void)
107 { 107 {
108 return CONFIG_SYS_CLK_FREQ; 108 return CONFIG_SYS_CLK_FREQ;
109 } 109 }
110 110
111 #if CONFIG_IS_ENABLED(CLK) 111 #if CONFIG_IS_ENABLED(CLK)
112 static int get_lpuart_clk_rate(struct udevice *dev, u32 *clk) 112 static int get_lpuart_clk_rate(struct udevice *dev, u32 *clk)
113 { 113 {
114 struct clk per_clk; 114 struct clk per_clk;
115 ulong rate; 115 ulong rate;
116 int ret; 116 int ret;
117 117
118 ret = clk_get_by_name(dev, "per", &per_clk); 118 ret = clk_get_by_name(dev, "per", &per_clk);
119 if (ret) { 119 if (ret) {
120 dev_err(dev, "Failed to get per clk: %d\n", ret); 120 dev_err(dev, "Failed to get per clk: %d\n", ret);
121 return ret; 121 return ret;
122 } 122 }
123 123
124 rate = clk_get_rate(&per_clk); 124 rate = clk_get_rate(&per_clk);
125 if ((long)rate <= 0) { 125 if ((long)rate <= 0) {
126 dev_err(dev, "Failed to get per clk rate: %ld\n", (long)rate); 126 dev_err(dev, "Failed to get per clk rate: %ld\n", (long)rate);
127 return ret; 127 return ret;
128 } 128 }
129 *clk = rate; 129 *clk = rate;
130 return 0; 130 return 0;
131 } 131 }
132 #else 132 #else
133 static inline int get_lpuart_clk_rate(struct udevice *dev, u32 *clk) 133 static inline int get_lpuart_clk_rate(struct udevice *dev, u32 *clk)
134 { return -ENOSYS; } 134 { return -ENOSYS; }
135 #endif 135 #endif
136 136
137 static bool is_lpuart32(struct udevice *dev) 137 static bool is_lpuart32(struct udevice *dev)
138 { 138 {
139 struct lpuart_serial_platdata *plat = dev->platdata; 139 struct lpuart_serial_platdata *plat = dev->platdata;
140 140
141 return plat->flags & LPUART_FLAG_REGMAP_32BIT_REG; 141 return plat->flags & LPUART_FLAG_REGMAP_32BIT_REG;
142 } 142 }
143 143
144 static void _lpuart_serial_setbrg(struct udevice *dev, 144 static void _lpuart_serial_setbrg(struct udevice *dev,
145 int baudrate) 145 int baudrate)
146 { 146 {
147 struct lpuart_serial_platdata *plat = dev_get_platdata(dev); 147 struct lpuart_serial_platdata *plat = dev_get_platdata(dev);
148 struct lpuart_fsl *base = plat->reg; 148 struct lpuart_fsl *base = plat->reg;
149 u32 clk; 149 u32 clk;
150 u16 sbr; 150 u16 sbr;
151 int ret; 151 int ret;
152 152
153 if (CONFIG_IS_ENABLED(CLK)) { 153 if (CONFIG_IS_ENABLED(CLK)) {
154 ret = get_lpuart_clk_rate(dev, &clk); 154 ret = get_lpuart_clk_rate(dev, &clk);
155 if (ret) 155 if (ret)
156 return; 156 return;
157 } else { 157 } else {
158 clk = get_lpuart_clk(); 158 clk = get_lpuart_clk();
159 } 159 }
160 160
161 sbr = (u16)(clk / (16 * baudrate)); 161 sbr = (u16)(clk / (16 * baudrate));
162 162
163 /* place adjustment later - n/32 BRFA */ 163 /* place adjustment later - n/32 BRFA */
164 __raw_writeb(sbr >> 8, &base->ubdh); 164 __raw_writeb(sbr >> 8, &base->ubdh);
165 __raw_writeb(sbr & 0xff, &base->ubdl); 165 __raw_writeb(sbr & 0xff, &base->ubdl);
166 } 166 }
167 167
168 static int _lpuart_serial_getc(struct lpuart_serial_platdata *plat) 168 static int _lpuart_serial_getc(struct lpuart_serial_platdata *plat)
169 { 169 {
170 struct lpuart_fsl *base = plat->reg; 170 struct lpuart_fsl *base = plat->reg;
171 while (!(__raw_readb(&base->us1) & (US1_RDRF | US1_OR))) 171 while (!(__raw_readb(&base->us1) & (US1_RDRF | US1_OR)))
172 WATCHDOG_RESET(); 172 WATCHDOG_RESET();
173 173
174 barrier(); 174 barrier();
175 175
176 return __raw_readb(&base->ud); 176 return __raw_readb(&base->ud);
177 } 177 }
178 178
179 static void _lpuart_serial_putc(struct lpuart_serial_platdata *plat, 179 static void _lpuart_serial_putc(struct lpuart_serial_platdata *plat,
180 const char c) 180 const char c)
181 { 181 {
182 struct lpuart_fsl *base = plat->reg; 182 struct lpuart_fsl *base = plat->reg;
183 183
184 while (!(__raw_readb(&base->us1) & US1_TDRE)) 184 while (!(__raw_readb(&base->us1) & US1_TDRE))
185 WATCHDOG_RESET(); 185 WATCHDOG_RESET();
186 186
187 __raw_writeb(c, &base->ud); 187 __raw_writeb(c, &base->ud);
188 } 188 }
189 189
190 /* Test whether a character is in the RX buffer */ 190 /* Test whether a character is in the RX buffer */
191 static int _lpuart_serial_tstc(struct lpuart_serial_platdata *plat) 191 static int _lpuart_serial_tstc(struct lpuart_serial_platdata *plat)
192 { 192 {
193 struct lpuart_fsl *base = plat->reg; 193 struct lpuart_fsl *base = plat->reg;
194 194
195 if (__raw_readb(&base->urcfifo) == 0) 195 if (__raw_readb(&base->urcfifo) == 0)
196 return 0; 196 return 0;
197 197
198 return 1; 198 return 1;
199 } 199 }
200 200
201 /* 201 /*
202 * Initialise the serial port with the given baudrate. The settings 202 * Initialise the serial port with the given baudrate. The settings
203 * are always 8 data bits, no parity, 1 stop bit, no start bits. 203 * are always 8 data bits, no parity, 1 stop bit, no start bits.
204 */ 204 */
205 static int _lpuart_serial_init(struct udevice *dev) 205 static int _lpuart_serial_init(struct udevice *dev)
206 { 206 {
207 struct lpuart_serial_platdata *plat = dev_get_platdata(dev); 207 struct lpuart_serial_platdata *plat = dev_get_platdata(dev);
208 struct lpuart_fsl *base = (struct lpuart_fsl *)plat->reg; 208 struct lpuart_fsl *base = (struct lpuart_fsl *)plat->reg;
209 u8 ctrl; 209 u8 ctrl;
210 210
211 ctrl = __raw_readb(&base->uc2); 211 ctrl = __raw_readb(&base->uc2);
212 ctrl &= ~UC2_RE; 212 ctrl &= ~UC2_RE;
213 ctrl &= ~UC2_TE; 213 ctrl &= ~UC2_TE;
214 __raw_writeb(ctrl, &base->uc2); 214 __raw_writeb(ctrl, &base->uc2);
215 215
216 __raw_writeb(0, &base->umodem); 216 __raw_writeb(0, &base->umodem);
217 __raw_writeb(0, &base->uc1); 217 __raw_writeb(0, &base->uc1);
218 218
219 /* Disable FIFO and flush buffer */ 219 /* Disable FIFO and flush buffer */
220 __raw_writeb(0x0, &base->upfifo); 220 __raw_writeb(0x0, &base->upfifo);
221 __raw_writeb(0x0, &base->utwfifo); 221 __raw_writeb(0x0, &base->utwfifo);
222 __raw_writeb(0x1, &base->urwfifo); 222 __raw_writeb(0x1, &base->urwfifo);
223 __raw_writeb(CFIFO_TXFLUSH | CFIFO_RXFLUSH, &base->ucfifo); 223 __raw_writeb(CFIFO_TXFLUSH | CFIFO_RXFLUSH, &base->ucfifo);
224 224
225 /* provide data bits, parity, stop bit, etc */ 225 /* provide data bits, parity, stop bit, etc */
226 _lpuart_serial_setbrg(dev, gd->baudrate); 226 _lpuart_serial_setbrg(dev, gd->baudrate);
227 227
228 __raw_writeb(UC2_RE | UC2_TE, &base->uc2); 228 __raw_writeb(UC2_RE | UC2_TE, &base->uc2);
229 229
230 return 0; 230 return 0;
231 } 231 }
232 232
233 static void _lpuart32_serial_setbrg_7ulp(struct udevice *dev, 233 static void _lpuart32_serial_setbrg_7ulp(struct udevice *dev,
234 int baudrate) 234 int baudrate)
235 { 235 {
236 struct lpuart_serial_platdata *plat = dev_get_platdata(dev); 236 struct lpuart_serial_platdata *plat = dev_get_platdata(dev);
237 struct lpuart_fsl_reg32 *base = plat->reg; 237 struct lpuart_fsl_reg32 *base = plat->reg;
238 u32 sbr, osr, baud_diff, tmp_osr, tmp_sbr, tmp_diff, tmp; 238 u32 sbr, osr, baud_diff, tmp_osr, tmp_sbr, tmp_diff, tmp;
239 u32 clk; 239 u32 clk;
240 int ret; 240 int ret;
241 241
242 if (CONFIG_IS_ENABLED(CLK)) { 242 if (CONFIG_IS_ENABLED(CLK)) {
243 ret = get_lpuart_clk_rate(dev, &clk); 243 ret = get_lpuart_clk_rate(dev, &clk);
244 if (ret) 244 if (ret)
245 return; 245 return;
246 } else { 246 } else {
247 clk = get_lpuart_clk(); 247 clk = get_lpuart_clk();
248 } 248 }
249 249
250 baud_diff = baudrate; 250 baud_diff = baudrate;
251 osr = 0; 251 osr = 0;
252 sbr = 0; 252 sbr = 0;
253 253
254 for (tmp_osr = 4; tmp_osr <= 32; tmp_osr++) { 254 for (tmp_osr = 4; tmp_osr <= 32; tmp_osr++) {
255 tmp_sbr = (clk / (baudrate * tmp_osr)); 255 tmp_sbr = (clk / (baudrate * tmp_osr));
256 256
257 if (tmp_sbr == 0) 257 if (tmp_sbr == 0)
258 tmp_sbr = 1; 258 tmp_sbr = 1;
259 259
260 /*calculate difference in actual buad w/ current values */ 260 /*calculate difference in actual buad w/ current values */
261 tmp_diff = (clk / (tmp_osr * tmp_sbr)); 261 tmp_diff = (clk / (tmp_osr * tmp_sbr));
262 tmp_diff = tmp_diff - baudrate; 262 tmp_diff = tmp_diff - baudrate;
263 263
264 /* select best values between sbr and sbr+1 */ 264 /* select best values between sbr and sbr+1 */
265 if (tmp_diff > (baudrate - (clk / (tmp_osr * (tmp_sbr + 1))))) { 265 if (tmp_diff > (baudrate - (clk / (tmp_osr * (tmp_sbr + 1))))) {
266 tmp_diff = baudrate - (clk / (tmp_osr * (tmp_sbr + 1))); 266 tmp_diff = baudrate - (clk / (tmp_osr * (tmp_sbr + 1)));
267 tmp_sbr++; 267 tmp_sbr++;
268 } 268 }
269 269
270 if (tmp_diff <= baud_diff) { 270 if (tmp_diff <= baud_diff) {
271 baud_diff = tmp_diff; 271 baud_diff = tmp_diff;
272 osr = tmp_osr; 272 osr = tmp_osr;
273 sbr = tmp_sbr; 273 sbr = tmp_sbr;
274 } 274 }
275 } 275 }
276 276
277 /* 277 /*
278 * TODO: handle buadrate outside acceptable rate 278 * TODO: handle buadrate outside acceptable rate
279 * if (baudDiff > ((config->baudRate_Bps / 100) * 3)) 279 * if (baudDiff > ((config->baudRate_Bps / 100) * 3))
280 * { 280 * {
281 * Unacceptable baud rate difference of more than 3% 281 * Unacceptable baud rate difference of more than 3%
282 * return kStatus_LPUART_BaudrateNotSupport; 282 * return kStatus_LPUART_BaudrateNotSupport;
283 * } 283 * }
284 */ 284 */
285 tmp = in_le32(&base->baud); 285 tmp = in_le32(&base->baud);
286 286
287 if ((osr > 3) && (osr < 8)) 287 if ((osr > 3) && (osr < 8))
288 tmp |= LPUART_BAUD_BOTHEDGE_MASK; 288 tmp |= LPUART_BAUD_BOTHEDGE_MASK;
289 289
290 tmp &= ~LPUART_BAUD_OSR_MASK; 290 tmp &= ~LPUART_BAUD_OSR_MASK;
291 tmp |= LPUART_BAUD_OSR(osr-1); 291 tmp |= LPUART_BAUD_OSR(osr-1);
292 292
293 tmp &= ~LPUART_BAUD_SBR_MASK; 293 tmp &= ~LPUART_BAUD_SBR_MASK;
294 tmp |= LPUART_BAUD_SBR(sbr); 294 tmp |= LPUART_BAUD_SBR(sbr);
295 295
296 /* explicitly disable 10 bit mode & set 1 stop bit */ 296 /* explicitly disable 10 bit mode & set 1 stop bit */
297 tmp &= ~(LPUART_BAUD_M10_MASK | LPUART_BAUD_SBNS_MASK); 297 tmp &= ~(LPUART_BAUD_M10_MASK | LPUART_BAUD_SBNS_MASK);
298 298
299 out_le32(&base->baud, tmp); 299 out_le32(&base->baud, tmp);
300 } 300 }
301 301
302 static void _lpuart32_serial_setbrg(struct udevice *dev, 302 static void _lpuart32_serial_setbrg(struct udevice *dev,
303 int baudrate) 303 int baudrate)
304 { 304 {
305 struct lpuart_serial_platdata *plat = dev_get_platdata(dev); 305 struct lpuart_serial_platdata *plat = dev_get_platdata(dev);
306 struct lpuart_fsl_reg32 *base = plat->reg; 306 struct lpuart_fsl_reg32 *base = plat->reg;
307 u32 clk; 307 u32 clk;
308 u32 sbr; 308 u32 sbr;
309 int ret; 309 int ret;
310 310
311 if (CONFIG_IS_ENABLED(CLK)) { 311 if (CONFIG_IS_ENABLED(CLK)) {
312 ret = get_lpuart_clk_rate(dev, &clk); 312 ret = get_lpuart_clk_rate(dev, &clk);
313 if (ret) 313 if (ret)
314 return; 314 return;
315 } else { 315 } else {
316 clk = get_lpuart_clk(); 316 clk = get_lpuart_clk();
317 } 317 }
318 318
319 sbr = (clk / (16 * baudrate)); 319 sbr = (clk / (16 * baudrate));
320 320
321 /* place adjustment later - n/32 BRFA */ 321 /* place adjustment later - n/32 BRFA */
322 lpuart_write32(plat->flags, &base->baud, sbr); 322 lpuart_write32(plat->flags, &base->baud, sbr);
323 } 323 }
324 324
325 static int _lpuart32_serial_getc(struct lpuart_serial_platdata *plat) 325 static int _lpuart32_serial_getc(struct lpuart_serial_platdata *plat)
326 { 326 {
327 struct lpuart_fsl_reg32 *base = plat->reg; 327 struct lpuart_fsl_reg32 *base = plat->reg;
328 u32 stat, val; 328 u32 stat, val;
329 329
330 lpuart_read32(plat->flags, &base->stat, &stat); 330 lpuart_read32(plat->flags, &base->stat, &stat);
331 while ((stat & STAT_RDRF) == 0) { 331 while ((stat & STAT_RDRF) == 0) {
332 lpuart_write32(plat->flags, &base->stat, STAT_FLAGS); 332 lpuart_write32(plat->flags, &base->stat, STAT_FLAGS);
333 WATCHDOG_RESET(); 333 WATCHDOG_RESET();
334 lpuart_read32(plat->flags, &base->stat, &stat); 334 lpuart_read32(plat->flags, &base->stat, &stat);
335 } 335 }
336 336
337 lpuart_read32(plat->flags, &base->data, &val); 337 lpuart_read32(plat->flags, &base->data, &val);
338 338
339 lpuart_read32(plat->flags, &base->stat, &stat); 339 lpuart_read32(plat->flags, &base->stat, &stat);
340 if (stat & STAT_OR) 340 if (stat & STAT_OR)
341 lpuart_write32(plat->flags, &base->stat, STAT_OR); 341 lpuart_write32(plat->flags, &base->stat, STAT_OR);
342 342
343 return val & 0x3ff; 343 return val & 0x3ff;
344 } 344 }
345 345
346 static void _lpuart32_serial_putc(struct lpuart_serial_platdata *plat, 346 static void _lpuart32_serial_putc(struct lpuart_serial_platdata *plat,
347 const char c) 347 const char c)
348 { 348 {
349 struct lpuart_fsl_reg32 *base = plat->reg; 349 struct lpuart_fsl_reg32 *base = plat->reg;
350 u32 stat; 350 u32 stat;
351 351
352 if (c == '\n') 352 if (c == '\n')
353 serial_putc('\r'); 353 serial_putc('\r');
354 354
355 while (true) { 355 while (true) {
356 lpuart_read32(plat->flags, &base->stat, &stat); 356 lpuart_read32(plat->flags, &base->stat, &stat);
357 357
358 if ((stat & STAT_TDRE)) 358 if ((stat & STAT_TDRE))
359 break; 359 break;
360 360
361 WATCHDOG_RESET(); 361 WATCHDOG_RESET();
362 } 362 }
363 363
364 lpuart_write32(plat->flags, &base->data, c); 364 lpuart_write32(plat->flags, &base->data, c);
365 } 365 }
366 366
367 /* Test whether a character is in the RX buffer */ 367 /* Test whether a character is in the RX buffer */
368 static int _lpuart32_serial_tstc(struct lpuart_serial_platdata *plat) 368 static int _lpuart32_serial_tstc(struct lpuart_serial_platdata *plat)
369 { 369 {
370 struct lpuart_fsl_reg32 *base = plat->reg; 370 struct lpuart_fsl_reg32 *base = plat->reg;
371 u32 water; 371 u32 water;
372 372
373 lpuart_read32(plat->flags, &base->water, &water); 373 lpuart_read32(plat->flags, &base->water, &water);
374 374
375 if ((water >> 24) == 0) 375 if ((water >> 24) == 0)
376 return 0; 376 return 0;
377 377
378 return 1; 378 return 1;
379 } 379 }
380 380
381 /* 381 /*
382 * Initialise the serial port with the given baudrate. The settings 382 * Initialise the serial port with the given baudrate. The settings
383 * are always 8 data bits, no parity, 1 stop bit, no start bits. 383 * are always 8 data bits, no parity, 1 stop bit, no start bits.
384 */ 384 */
385 static int _lpuart32_serial_init(struct udevice *dev) 385 static int _lpuart32_serial_init(struct udevice *dev)
386 { 386 {
387 struct lpuart_serial_platdata *plat = dev_get_platdata(dev); 387 struct lpuart_serial_platdata *plat = dev_get_platdata(dev);
388 struct lpuart_fsl_reg32 *base = (struct lpuart_fsl_reg32 *)plat->reg; 388 struct lpuart_fsl_reg32 *base = (struct lpuart_fsl_reg32 *)plat->reg;
389 u32 val, tx_fifo_size; 389 u32 val, tx_fifo_size;
390 390
391 lpuart_read32(plat->flags, &base->ctrl, &val); 391 lpuart_read32(plat->flags, &base->ctrl, &val);
392 val &= ~CTRL_RE; 392 val &= ~CTRL_RE;
393 val &= ~CTRL_TE; 393 val &= ~CTRL_TE;
394 lpuart_write32(plat->flags, &base->ctrl, val); 394 lpuart_write32(plat->flags, &base->ctrl, val);
395 395
396 lpuart_write32(plat->flags, &base->modir, 0); 396 lpuart_write32(plat->flags, &base->modir, 0);
397 397
398 lpuart_read32(plat->flags, &base->fifo, &val); 398 lpuart_read32(plat->flags, &base->fifo, &val);
399 tx_fifo_size = (val & FIFO_TXSIZE_MASK) >> FIFO_TXSIZE_OFF; 399 tx_fifo_size = (val & FIFO_TXSIZE_MASK) >> FIFO_TXSIZE_OFF;
400 /* Set the TX water to half of FIFO size */ 400 /* Set the TX water to half of FIFO size */
401 if (tx_fifo_size > 1) 401 if (tx_fifo_size > 1)
402 tx_fifo_size = tx_fifo_size >> 1; 402 tx_fifo_size = tx_fifo_size >> 1;
403 403
404 /* Set RX water to 0, to be triggered by any receive data */ 404 /* Set RX water to 0, to be triggered by any receive data */
405 lpuart_write32(plat->flags, &base->water, 405 lpuart_write32(plat->flags, &base->water,
406 (tx_fifo_size << WATER_TXWATER_OFF)); 406 (tx_fifo_size << WATER_TXWATER_OFF));
407 407
408 /* Enable TX and RX FIFO */ 408 /* Enable TX and RX FIFO */
409 val |= (FIFO_TXFE | FIFO_RXFE | FIFO_TXFLUSH | FIFO_RXFLUSH); 409 val |= (FIFO_TXFE | FIFO_RXFE | FIFO_TXFLUSH | FIFO_RXFLUSH);
410 lpuart_write32(plat->flags, &base->fifo, val); 410 lpuart_write32(plat->flags, &base->fifo, val);
411 411
412 lpuart_write32(plat->flags, &base->match, 0); 412 lpuart_write32(plat->flags, &base->match, 0);
413 413
414 if (plat->devtype == DEV_MX7ULP || plat->devtype == DEV_IMX8 || 414 if (plat->devtype == DEV_MX7ULP || plat->devtype == DEV_IMX8 ||
415 plat->devtype == DEV_IMXRT) { 415 plat->devtype == DEV_IMXRT) {
416 _lpuart32_serial_setbrg_7ulp(dev, gd->baudrate); 416 _lpuart32_serial_setbrg_7ulp(dev, gd->baudrate);
417 } else { 417 } else {
418 /* provide data bits, parity, stop bit, etc */ 418 /* provide data bits, parity, stop bit, etc */
419 _lpuart32_serial_setbrg(dev, gd->baudrate); 419 _lpuart32_serial_setbrg(dev, gd->baudrate);
420 } 420 }
421 421
422 lpuart_write32(plat->flags, &base->ctrl, CTRL_RE | CTRL_TE); 422 lpuart_write32(plat->flags, &base->ctrl, CTRL_RE | CTRL_TE);
423 423
424 return 0; 424 return 0;
425 } 425 }
426 426
427 static int lpuart_serial_setbrg(struct udevice *dev, int baudrate) 427 static int lpuart_serial_setbrg(struct udevice *dev, int baudrate)
428 { 428 {
429 struct lpuart_serial_platdata *plat = dev_get_platdata(dev); 429 struct lpuart_serial_platdata *plat = dev_get_platdata(dev);
430 430
431 if (is_lpuart32(dev)) { 431 if (is_lpuart32(dev)) {
432 if (plat->devtype == DEV_MX7ULP || plat->devtype == DEV_IMX8 || 432 if (plat->devtype == DEV_MX7ULP || plat->devtype == DEV_IMX8 ||
433 plat->devtype == DEV_IMXRT) 433 plat->devtype == DEV_IMXRT)
434 _lpuart32_serial_setbrg_7ulp(dev, baudrate); 434 _lpuart32_serial_setbrg_7ulp(dev, baudrate);
435 else 435 else
436 _lpuart32_serial_setbrg(dev, baudrate); 436 _lpuart32_serial_setbrg(dev, baudrate);
437 } else { 437 } else {
438 _lpuart_serial_setbrg(dev, baudrate); 438 _lpuart_serial_setbrg(dev, baudrate);
439 } 439 }
440 440
441 return 0; 441 return 0;
442 } 442 }
443 443
444 static int lpuart_serial_getc(struct udevice *dev) 444 static int lpuart_serial_getc(struct udevice *dev)
445 { 445 {
446 struct lpuart_serial_platdata *plat = dev->platdata; 446 struct lpuart_serial_platdata *plat = dev->platdata;
447 447
448 if (is_lpuart32(dev)) 448 if (is_lpuart32(dev))
449 return _lpuart32_serial_getc(plat); 449 return _lpuart32_serial_getc(plat);
450 450
451 return _lpuart_serial_getc(plat); 451 return _lpuart_serial_getc(plat);
452 } 452 }
453 453
454 static int lpuart_serial_putc(struct udevice *dev, const char c) 454 static int lpuart_serial_putc(struct udevice *dev, const char c)
455 { 455 {
456 struct lpuart_serial_platdata *plat = dev->platdata; 456 struct lpuart_serial_platdata *plat = dev->platdata;
457 457
458 if (is_lpuart32(dev)) 458 if (is_lpuart32(dev))
459 _lpuart32_serial_putc(plat, c); 459 _lpuart32_serial_putc(plat, c);
460 else 460 else
461 _lpuart_serial_putc(plat, c); 461 _lpuart_serial_putc(plat, c);
462 462
463 return 0; 463 return 0;
464 } 464 }
465 465
466 static int lpuart_serial_pending(struct udevice *dev, bool input) 466 static int lpuart_serial_pending(struct udevice *dev, bool input)
467 { 467 {
468 struct lpuart_serial_platdata *plat = dev->platdata; 468 struct lpuart_serial_platdata *plat = dev->platdata;
469 struct lpuart_fsl *reg = plat->reg; 469 struct lpuart_fsl *reg = plat->reg;
470 struct lpuart_fsl_reg32 *reg32 = plat->reg; 470 struct lpuart_fsl_reg32 *reg32 = plat->reg;
471 u32 stat; 471 u32 stat;
472 472
473 if (is_lpuart32(dev)) { 473 if (is_lpuart32(dev)) {
474 if (input) { 474 if (input) {
475 return _lpuart32_serial_tstc(plat); 475 return _lpuart32_serial_tstc(plat);
476 } else { 476 } else {
477 lpuart_read32(plat->flags, &reg32->stat, &stat); 477 lpuart_read32(plat->flags, &reg32->stat, &stat);
478 return stat & STAT_TDRE ? 0 : 1; 478 return stat & STAT_TDRE ? 0 : 1;
479 } 479 }
480 } 480 }
481 481
482 if (input) 482 if (input)
483 return _lpuart_serial_tstc(plat); 483 return _lpuart_serial_tstc(plat);
484 else 484 else
485 return __raw_readb(&reg->us1) & US1_TDRE ? 0 : 1; 485 return __raw_readb(&reg->us1) & US1_TDRE ? 0 : 1;
486 } 486 }
487 487
488 static int lpuart_serial_probe(struct udevice *dev) 488 static int lpuart_serial_probe(struct udevice *dev)
489 { 489 {
490 #if CONFIG_IS_ENABLED(CLK) 490 #if CONFIG_IS_ENABLED(CLK)
491 struct clk per_clk; 491 struct clk per_clk;
492 struct clk ipg_clk;
492 int ret; 493 int ret;
493 494
494 ret = clk_get_by_name(dev, "per", &per_clk); 495 ret = clk_get_by_name(dev, "per", &per_clk);
495 if (!ret) { 496 if (!ret) {
496 ret = clk_enable(&per_clk); 497 ret = clk_enable(&per_clk);
497 if (ret) { 498 if (ret) {
498 dev_err(dev, "Failed to get per clk: %d\n", ret); 499 dev_err(dev, "Failed to enable per clk: %d\n", ret);
499 return ret; 500 return ret;
500 } 501 }
501 } else { 502 } else {
502 debug("%s: Failed to get per clk: %d\n", __func__, ret); 503 debug("%s: Failed to get per clk: %d\n", __func__, ret);
504 }
505
506 ret = clk_get_by_name(dev, "ipg", &ipg_clk);
507 if (!ret) {
508 ret = clk_enable(&ipg_clk);
509 if (ret) {
510 dev_err(dev, "Failed to enable ipg clk: %d\n", ret);
511 return ret;
512 }
513 } else {
514 debug("%s: Failed to get ipg clk: %d\n", __func__, ret);
503 } 515 }
504 #endif 516 #endif
505 517
506 if (is_lpuart32(dev)) 518 if (is_lpuart32(dev))
507 return _lpuart32_serial_init(dev); 519 return _lpuart32_serial_init(dev);
508 else 520 else
509 return _lpuart_serial_init(dev); 521 return _lpuart_serial_init(dev);
510 } 522 }
511 523
512 static int lpuart_serial_ofdata_to_platdata(struct udevice *dev) 524 static int lpuart_serial_ofdata_to_platdata(struct udevice *dev)
513 { 525 {
514 struct lpuart_serial_platdata *plat = dev->platdata; 526 struct lpuart_serial_platdata *plat = dev->platdata;
515 const void *blob = gd->fdt_blob; 527 const void *blob = gd->fdt_blob;
516 int node = dev_of_offset(dev); 528 int node = dev_of_offset(dev);
517 fdt_addr_t addr; 529 fdt_addr_t addr;
518 530
519 addr = devfdt_get_addr(dev); 531 addr = devfdt_get_addr(dev);
520 if (addr == FDT_ADDR_T_NONE) 532 if (addr == FDT_ADDR_T_NONE)
521 return -EINVAL; 533 return -EINVAL;
522 534
523 plat->reg = (void *)addr; 535 plat->reg = (void *)addr;
524 plat->flags = dev_get_driver_data(dev); 536 plat->flags = dev_get_driver_data(dev);
525 537
526 if (fdtdec_get_bool(blob, node, "little-endian")) 538 if (fdtdec_get_bool(blob, node, "little-endian"))
527 plat->flags &= ~LPUART_FLAG_REGMAP_ENDIAN_BIG; 539 plat->flags &= ~LPUART_FLAG_REGMAP_ENDIAN_BIG;
528 540
529 if (!fdt_node_check_compatible(blob, node, "fsl,ls1021a-lpuart")) 541 if (!fdt_node_check_compatible(blob, node, "fsl,ls1021a-lpuart"))
530 plat->devtype = DEV_LS1021A; 542 plat->devtype = DEV_LS1021A;
531 else if (!fdt_node_check_compatible(blob, node, "fsl,imx7ulp-lpuart")) 543 else if (!fdt_node_check_compatible(blob, node, "fsl,imx7ulp-lpuart"))
532 plat->devtype = DEV_MX7ULP; 544 plat->devtype = DEV_MX7ULP;
533 else if (!fdt_node_check_compatible(blob, node, "fsl,vf610-lpuart")) 545 else if (!fdt_node_check_compatible(blob, node, "fsl,vf610-lpuart"))
534 plat->devtype = DEV_VF610; 546 plat->devtype = DEV_VF610;
535 else if (!fdt_node_check_compatible(blob, node, "fsl,imx8qm-lpuart")) 547 else if (!fdt_node_check_compatible(blob, node, "fsl,imx8qm-lpuart"))
536 plat->devtype = DEV_IMX8; 548 plat->devtype = DEV_IMX8;
537 else if (!fdt_node_check_compatible(blob, node, "fsl,imxrt-lpuart")) 549 else if (!fdt_node_check_compatible(blob, node, "fsl,imxrt-lpuart"))
538 plat->devtype = DEV_IMXRT; 550 plat->devtype = DEV_IMXRT;
539 551
540 return 0; 552 return 0;
541 } 553 }
542 554
543 static const struct dm_serial_ops lpuart_serial_ops = { 555 static const struct dm_serial_ops lpuart_serial_ops = {
544 .putc = lpuart_serial_putc, 556 .putc = lpuart_serial_putc,
545 .pending = lpuart_serial_pending, 557 .pending = lpuart_serial_pending,
546 .getc = lpuart_serial_getc, 558 .getc = lpuart_serial_getc,
547 .setbrg = lpuart_serial_setbrg, 559 .setbrg = lpuart_serial_setbrg,
548 }; 560 };
549 561
550 static const struct udevice_id lpuart_serial_ids[] = { 562 static const struct udevice_id lpuart_serial_ids[] = {
551 { .compatible = "fsl,ls1021a-lpuart", .data = 563 { .compatible = "fsl,ls1021a-lpuart", .data =
552 LPUART_FLAG_REGMAP_32BIT_REG | LPUART_FLAG_REGMAP_ENDIAN_BIG }, 564 LPUART_FLAG_REGMAP_32BIT_REG | LPUART_FLAG_REGMAP_ENDIAN_BIG },
553 { .compatible = "fsl,imx7ulp-lpuart", 565 { .compatible = "fsl,imx7ulp-lpuart",
554 .data = LPUART_FLAG_REGMAP_32BIT_REG }, 566 .data = LPUART_FLAG_REGMAP_32BIT_REG },
555 { .compatible = "fsl,vf610-lpuart"}, 567 { .compatible = "fsl,vf610-lpuart"},
556 { .compatible = "fsl,imx8qm-lpuart", 568 { .compatible = "fsl,imx8qm-lpuart",
557 .data = LPUART_FLAG_REGMAP_32BIT_REG }, 569 .data = LPUART_FLAG_REGMAP_32BIT_REG },
558 { .compatible = "fsl,imxrt-lpuart", 570 { .compatible = "fsl,imxrt-lpuart",
559 .data = LPUART_FLAG_REGMAP_32BIT_REG }, 571 .data = LPUART_FLAG_REGMAP_32BIT_REG },
560 { } 572 { }
561 }; 573 };
562 574
563 U_BOOT_DRIVER(serial_lpuart) = { 575 U_BOOT_DRIVER(serial_lpuart) = {
564 .name = "serial_lpuart", 576 .name = "serial_lpuart",
565 .id = UCLASS_SERIAL, 577 .id = UCLASS_SERIAL,
566 .of_match = lpuart_serial_ids, 578 .of_match = lpuart_serial_ids,
567 .ofdata_to_platdata = lpuart_serial_ofdata_to_platdata, 579 .ofdata_to_platdata = lpuart_serial_ofdata_to_platdata,
568 .platdata_auto_alloc_size = sizeof(struct lpuart_serial_platdata), 580 .platdata_auto_alloc_size = sizeof(struct lpuart_serial_platdata),
569 .probe = lpuart_serial_probe, 581 .probe = lpuart_serial_probe,
570 .ops = &lpuart_serial_ops, 582 .ops = &lpuart_serial_ops,
571 }; 583 };
572 584