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 lpuart_read32(plat->flags, &base->stat, &stat); 269 if (stat & STAT_OR) 270 lpuart_write32(plat->flags, &base->stat, STAT_OR); 271 272 return val & 0x3ff; 273 } 274 275 static void _lpuart32_serial_putc(struct lpuart_serial_platdata *plat, 276 const char c) 277 { 278 struct lpuart_fsl_reg32 *base = plat->reg; 279 u32 stat; 280 281 if (c == '\n') 282 serial_putc('\r'); 283 284 while (true) { 285 lpuart_read32(plat->flags, &base->stat, &stat); 286 287 if ((stat & STAT_TDRE)) 288 break; 289 290 WATCHDOG_RESET(); 291 } 292 293 lpuart_write32(plat->flags, &base->data, c); 294 } 295 296 /* Test whether a character is in the RX buffer */ 297 static int _lpuart32_serial_tstc(struct lpuart_serial_platdata *plat) 298 { 299 struct lpuart_fsl_reg32 *base = plat->reg; 300 u32 water; 301 302 lpuart_read32(plat->flags, &base->water, &water); 303 304 if ((water >> 24) == 0) 305 return 0; 306 307 return 1; 308 } 309 310 /* 311 * Initialise the serial port with the given baudrate. The settings 312 * are always 8 data bits, no parity, 1 stop bit, no start bits. 313 */ 314 static int _lpuart32_serial_init(struct lpuart_serial_platdata *plat) 315 { 316 struct lpuart_fsl_reg32 *base = (struct lpuart_fsl_reg32 *)plat->reg; 317 u32 ctrl; 318 319 lpuart_read32(plat->flags, &base->ctrl, &ctrl); 320 ctrl &= ~CTRL_RE; 321 ctrl &= ~CTRL_TE; 322 lpuart_write32(plat->flags, &base->ctrl, ctrl); 323 324 lpuart_write32(plat->flags, &base->modir, 0); 325 lpuart_write32(plat->flags, &base->fifo, ~(FIFO_TXFE | FIFO_RXFE)); 326 327 lpuart_write32(plat->flags, &base->match, 0); 328 329 if (plat->devtype == DEV_MX7ULP) { 330 _lpuart32_serial_setbrg_7ulp(plat, gd->baudrate); 331 } else { 332 /* provide data bits, parity, stop bit, etc */ 333 _lpuart32_serial_setbrg(plat, gd->baudrate); 334 } 335 336 lpuart_write32(plat->flags, &base->ctrl, CTRL_RE | CTRL_TE); 337 338 return 0; 339 } 340 341 static int lpuart_serial_setbrg(struct udevice *dev, int baudrate) 342 { 343 struct lpuart_serial_platdata *plat = dev->platdata; 344 345 if (is_lpuart32(dev)) { 346 if (plat->devtype == DEV_MX7ULP) 347 _lpuart32_serial_setbrg_7ulp(plat, baudrate); 348 else 349 _lpuart32_serial_setbrg(plat, baudrate); 350 } else { 351 _lpuart_serial_setbrg(plat, baudrate); 352 } 353 354 return 0; 355 } 356 357 static int lpuart_serial_getc(struct udevice *dev) 358 { 359 struct lpuart_serial_platdata *plat = dev->platdata; 360 361 if (is_lpuart32(dev)) 362 return _lpuart32_serial_getc(plat); 363 364 return _lpuart_serial_getc(plat); 365 } 366 367 static int lpuart_serial_putc(struct udevice *dev, const char c) 368 { 369 struct lpuart_serial_platdata *plat = dev->platdata; 370 371 if (is_lpuart32(dev)) 372 _lpuart32_serial_putc(plat, c); 373 else 374 _lpuart_serial_putc(plat, c); 375 376 return 0; 377 } 378 379 static int lpuart_serial_pending(struct udevice *dev, bool input) 380 { 381 struct lpuart_serial_platdata *plat = dev->platdata; 382 struct lpuart_fsl *reg = plat->reg; 383 struct lpuart_fsl_reg32 *reg32 = plat->reg; 384 u32 stat; 385 386 if (is_lpuart32(dev)) { 387 if (input) { 388 return _lpuart32_serial_tstc(plat); 389 } else { 390 lpuart_read32(plat->flags, ®32->stat, &stat); 391 return stat & STAT_TDRE ? 0 : 1; 392 } 393 } 394 395 if (input) 396 return _lpuart_serial_tstc(plat); 397 else 398 return __raw_readb(®->us1) & US1_TDRE ? 0 : 1; 399 } 400 401 static int lpuart_serial_probe(struct udevice *dev) 402 { 403 struct lpuart_serial_platdata *plat = dev->platdata; 404 405 if (is_lpuart32(dev)) 406 return _lpuart32_serial_init(plat); 407 else 408 return _lpuart_serial_init(plat); 409 } 410 411 static int lpuart_serial_ofdata_to_platdata(struct udevice *dev) 412 { 413 struct lpuart_serial_platdata *plat = dev->platdata; 414 const void *blob = gd->fdt_blob; 415 int node = dev_of_offset(dev); 416 fdt_addr_t addr; 417 418 addr = devfdt_get_addr(dev); 419 if (addr == FDT_ADDR_T_NONE) 420 return -EINVAL; 421 422 plat->reg = (void *)addr; 423 plat->flags = dev_get_driver_data(dev); 424 425 if (!fdt_node_check_compatible(blob, node, "fsl,ls1021a-lpuart")) 426 plat->devtype = DEV_LS1021A; 427 else if (!fdt_node_check_compatible(blob, node, "fsl,imx7ulp-lpuart")) 428 plat->devtype = DEV_MX7ULP; 429 else if (!fdt_node_check_compatible(blob, node, "fsl,vf610-lpuart")) 430 plat->devtype = DEV_VF610; 431 432 return 0; 433 } 434 435 static const struct dm_serial_ops lpuart_serial_ops = { 436 .putc = lpuart_serial_putc, 437 .pending = lpuart_serial_pending, 438 .getc = lpuart_serial_getc, 439 .setbrg = lpuart_serial_setbrg, 440 }; 441 442 static const struct udevice_id lpuart_serial_ids[] = { 443 { .compatible = "fsl,ls1021a-lpuart", .data = 444 LPUART_FLAG_REGMAP_32BIT_REG | LPUART_FLAG_REGMAP_ENDIAN_BIG }, 445 { .compatible = "fsl,imx7ulp-lpuart", 446 .data = LPUART_FLAG_REGMAP_32BIT_REG }, 447 { .compatible = "fsl,vf610-lpuart"}, 448 { } 449 }; 450 451 U_BOOT_DRIVER(serial_lpuart) = { 452 .name = "serial_lpuart", 453 .id = UCLASS_SERIAL, 454 .of_match = lpuart_serial_ids, 455 .ofdata_to_platdata = lpuart_serial_ofdata_to_platdata, 456 .platdata_auto_alloc_size = sizeof(struct lpuart_serial_platdata), 457 .probe = lpuart_serial_probe, 458 .ops = &lpuart_serial_ops, 459 .flags = DM_FLAG_PRE_RELOC, 460 }; 461