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