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 struct lpuart_serial_platdata { 56 void *reg; 57 ulong flags; 58 }; 59 60 static void lpuart_read32(u32 flags, u32 *addr, u32 *val) 61 { 62 if (flags & LPUART_FLAG_REGMAP_32BIT_REG) { 63 if (flags & LPUART_FLAG_REGMAP_ENDIAN_BIG) 64 *(u32 *)val = in_be32(addr); 65 else 66 *(u32 *)val = in_le32(addr); 67 } 68 } 69 70 static void lpuart_write32(u32 flags, u32 *addr, u32 val) 71 { 72 if (flags & LPUART_FLAG_REGMAP_32BIT_REG) { 73 if (flags & LPUART_FLAG_REGMAP_ENDIAN_BIG) 74 out_be32(addr, val); 75 else 76 out_le32(addr, val); 77 } 78 } 79 80 81 #ifndef CONFIG_SYS_CLK_FREQ 82 #define CONFIG_SYS_CLK_FREQ 0 83 #endif 84 85 u32 __weak get_lpuart_clk(void) 86 { 87 return CONFIG_SYS_CLK_FREQ; 88 } 89 90 static bool is_lpuart32(struct udevice *dev) 91 { 92 struct lpuart_serial_platdata *plat = dev->platdata; 93 94 return plat->flags & LPUART_FLAG_REGMAP_32BIT_REG; 95 } 96 97 static void _lpuart_serial_setbrg(struct lpuart_serial_platdata *plat, 98 int baudrate) 99 { 100 struct lpuart_fsl *base = plat->reg; 101 u32 clk = get_lpuart_clk(); 102 u16 sbr; 103 104 sbr = (u16)(clk / (16 * baudrate)); 105 106 /* place adjustment later - n/32 BRFA */ 107 __raw_writeb(sbr >> 8, &base->ubdh); 108 __raw_writeb(sbr & 0xff, &base->ubdl); 109 } 110 111 static int _lpuart_serial_getc(struct lpuart_serial_platdata *plat) 112 { 113 struct lpuart_fsl *base = plat->reg; 114 while (!(__raw_readb(&base->us1) & (US1_RDRF | US1_OR))) 115 WATCHDOG_RESET(); 116 117 barrier(); 118 119 return __raw_readb(&base->ud); 120 } 121 122 static void _lpuart_serial_putc(struct lpuart_serial_platdata *plat, 123 const char c) 124 { 125 struct lpuart_fsl *base = plat->reg; 126 127 while (!(__raw_readb(&base->us1) & US1_TDRE)) 128 WATCHDOG_RESET(); 129 130 __raw_writeb(c, &base->ud); 131 } 132 133 /* Test whether a character is in the RX buffer */ 134 static int _lpuart_serial_tstc(struct lpuart_serial_platdata *plat) 135 { 136 struct lpuart_fsl *base = plat->reg; 137 138 if (__raw_readb(&base->urcfifo) == 0) 139 return 0; 140 141 return 1; 142 } 143 144 /* 145 * Initialise the serial port with the given baudrate. The settings 146 * are always 8 data bits, no parity, 1 stop bit, no start bits. 147 */ 148 static int _lpuart_serial_init(struct lpuart_serial_platdata *plat) 149 { 150 struct lpuart_fsl *base = (struct lpuart_fsl *)plat->reg; 151 u8 ctrl; 152 153 ctrl = __raw_readb(&base->uc2); 154 ctrl &= ~UC2_RE; 155 ctrl &= ~UC2_TE; 156 __raw_writeb(ctrl, &base->uc2); 157 158 __raw_writeb(0, &base->umodem); 159 __raw_writeb(0, &base->uc1); 160 161 /* Disable FIFO and flush buffer */ 162 __raw_writeb(0x0, &base->upfifo); 163 __raw_writeb(0x0, &base->utwfifo); 164 __raw_writeb(0x1, &base->urwfifo); 165 __raw_writeb(CFIFO_TXFLUSH | CFIFO_RXFLUSH, &base->ucfifo); 166 167 /* provide data bits, parity, stop bit, etc */ 168 _lpuart_serial_setbrg(plat, gd->baudrate); 169 170 __raw_writeb(UC2_RE | UC2_TE, &base->uc2); 171 172 return 0; 173 } 174 175 static void _lpuart32_serial_setbrg(struct lpuart_serial_platdata *plat, 176 int baudrate) 177 { 178 struct lpuart_fsl_reg32 *base = plat->reg; 179 u32 clk = get_lpuart_clk(); 180 u32 sbr; 181 182 sbr = (clk / (16 * baudrate)); 183 184 /* place adjustment later - n/32 BRFA */ 185 lpuart_write32(plat->flags, &base->baud, sbr); 186 } 187 188 static int _lpuart32_serial_getc(struct lpuart_serial_platdata *plat) 189 { 190 struct lpuart_fsl_reg32 *base = plat->reg; 191 u32 stat; 192 193 lpuart_read32(plat->flags, &base->stat, &stat); 194 while ((stat & STAT_RDRF) == 0) { 195 lpuart_write32(plat->flags, &base->stat, STAT_FLAGS); 196 WATCHDOG_RESET(); 197 lpuart_read32(plat->flags, &base->stat, &stat); 198 } 199 200 /* Reuse stat */ 201 lpuart_read32(plat->flags, &base->data, &stat); 202 203 return stat & 0x3ff; 204 } 205 206 static void _lpuart32_serial_putc(struct lpuart_serial_platdata *plat, 207 const char c) 208 { 209 struct lpuart_fsl_reg32 *base = plat->reg; 210 u32 stat; 211 212 while (true) { 213 lpuart_read32(plat->flags, &base->stat, &stat); 214 215 if ((stat & STAT_TDRE)) 216 break; 217 218 WATCHDOG_RESET(); 219 } 220 221 lpuart_write32(plat->flags, &base->data, c); 222 } 223 224 /* Test whether a character is in the RX buffer */ 225 static int _lpuart32_serial_tstc(struct lpuart_serial_platdata *plat) 226 { 227 struct lpuart_fsl_reg32 *base = plat->reg; 228 u32 water; 229 230 lpuart_read32(plat->flags, &base->water, &water); 231 232 if ((water >> 24) == 0) 233 return 0; 234 235 return 1; 236 } 237 238 /* 239 * Initialise the serial port with the given baudrate. The settings 240 * are always 8 data bits, no parity, 1 stop bit, no start bits. 241 */ 242 static int _lpuart32_serial_init(struct lpuart_serial_platdata *plat) 243 { 244 struct lpuart_fsl_reg32 *base = (struct lpuart_fsl_reg32 *)plat->reg; 245 u32 ctrl; 246 247 lpuart_read32(plat->flags, &base->ctrl, &ctrl); 248 ctrl &= ~CTRL_RE; 249 ctrl &= ~CTRL_TE; 250 lpuart_write32(plat->flags, &base->ctrl, ctrl); 251 252 lpuart_write32(plat->flags, &base->modir, 0); 253 lpuart_write32(plat->flags, &base->fifo, ~(FIFO_TXFE | FIFO_RXFE)); 254 255 lpuart_write32(plat->flags, &base->match, 0); 256 257 /* provide data bits, parity, stop bit, etc */ 258 _lpuart32_serial_setbrg(plat, gd->baudrate); 259 260 lpuart_write32(plat->flags, &base->ctrl, CTRL_RE | CTRL_TE); 261 262 return 0; 263 } 264 265 static int lpuart_serial_setbrg(struct udevice *dev, int baudrate) 266 { 267 struct lpuart_serial_platdata *plat = dev->platdata; 268 269 if (is_lpuart32(dev)) 270 _lpuart32_serial_setbrg(plat, baudrate); 271 else 272 _lpuart_serial_setbrg(plat, baudrate); 273 274 return 0; 275 } 276 277 static int lpuart_serial_getc(struct udevice *dev) 278 { 279 struct lpuart_serial_platdata *plat = dev->platdata; 280 281 if (is_lpuart32(dev)) 282 return _lpuart32_serial_getc(plat); 283 284 return _lpuart_serial_getc(plat); 285 } 286 287 static int lpuart_serial_putc(struct udevice *dev, const char c) 288 { 289 struct lpuart_serial_platdata *plat = dev->platdata; 290 291 if (is_lpuart32(dev)) 292 _lpuart32_serial_putc(plat, c); 293 else 294 _lpuart_serial_putc(plat, c); 295 296 return 0; 297 } 298 299 static int lpuart_serial_pending(struct udevice *dev, bool input) 300 { 301 struct lpuart_serial_platdata *plat = dev->platdata; 302 struct lpuart_fsl *reg = plat->reg; 303 struct lpuart_fsl_reg32 *reg32 = plat->reg; 304 u32 stat; 305 306 if (is_lpuart32(dev)) { 307 if (input) { 308 return _lpuart32_serial_tstc(plat); 309 } else { 310 lpuart_read32(plat->flags, ®32->stat, &stat); 311 return stat & STAT_TDRE ? 0 : 1; 312 } 313 } 314 315 if (input) 316 return _lpuart_serial_tstc(plat); 317 else 318 return __raw_readb(®->us1) & US1_TDRE ? 0 : 1; 319 } 320 321 static int lpuart_serial_probe(struct udevice *dev) 322 { 323 struct lpuart_serial_platdata *plat = dev->platdata; 324 325 if (is_lpuart32(dev)) 326 return _lpuart32_serial_init(plat); 327 else 328 return _lpuart_serial_init(plat); 329 } 330 331 static int lpuart_serial_ofdata_to_platdata(struct udevice *dev) 332 { 333 struct lpuart_serial_platdata *plat = dev->platdata; 334 fdt_addr_t addr; 335 336 addr = dev_get_addr(dev); 337 if (addr == FDT_ADDR_T_NONE) 338 return -EINVAL; 339 340 plat->reg = (void *)addr; 341 plat->flags = dev_get_driver_data(dev); 342 343 return 0; 344 } 345 346 static const struct dm_serial_ops lpuart_serial_ops = { 347 .putc = lpuart_serial_putc, 348 .pending = lpuart_serial_pending, 349 .getc = lpuart_serial_getc, 350 .setbrg = lpuart_serial_setbrg, 351 }; 352 353 static const struct udevice_id lpuart_serial_ids[] = { 354 { .compatible = "fsl,ls1021a-lpuart", .data = 355 LPUART_FLAG_REGMAP_32BIT_REG | LPUART_FLAG_REGMAP_ENDIAN_BIG }, 356 { .compatible = "fsl,vf610-lpuart"}, 357 { } 358 }; 359 360 U_BOOT_DRIVER(serial_lpuart) = { 361 .name = "serial_lpuart", 362 .id = UCLASS_SERIAL, 363 .of_match = lpuart_serial_ids, 364 .ofdata_to_platdata = lpuart_serial_ofdata_to_platdata, 365 .platdata_auto_alloc_size = sizeof(struct lpuart_serial_platdata), 366 .probe = lpuart_serial_probe, 367 .ops = &lpuart_serial_ops, 368 .flags = DM_FLAG_PRE_RELOC, 369 }; 370