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