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