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