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