1 /* 2 * (C) Copyright 2000 3 * Rob Taylor, Flying Pig Systems. robt@flyingpig.com. 4 * 5 * (C) Copyright 2004 6 * ARM Ltd. 7 * Philippe Robin, <philippe.robin@arm.com> 8 * 9 * SPDX-License-Identifier: GPL-2.0+ 10 */ 11 12 /* Simple U-Boot driver for the PrimeCell PL010/PL011 UARTs */ 13 14 #include <common.h> 15 #include <dm.h> 16 #include <errno.h> 17 #include <watchdog.h> 18 #include <asm/io.h> 19 #include <serial.h> 20 #include <dm/platform_data/serial_pl01x.h> 21 #include <linux/compiler.h> 22 #include "serial_pl01x_internal.h" 23 #include <fdtdec.h> 24 25 DECLARE_GLOBAL_DATA_PTR; 26 27 #ifndef CONFIG_DM_SERIAL 28 29 static volatile unsigned char *const port[] = CONFIG_PL01x_PORTS; 30 static enum pl01x_type pl01x_type __attribute__ ((section(".data"))); 31 static struct pl01x_regs *base_regs __attribute__ ((section(".data"))); 32 #define NUM_PORTS (sizeof(port)/sizeof(port[0])) 33 34 #endif 35 36 static int pl01x_putc(struct pl01x_regs *regs, char c) 37 { 38 /* Wait until there is space in the FIFO */ 39 if (readl(®s->fr) & UART_PL01x_FR_TXFF) 40 return -EAGAIN; 41 42 /* Send the character */ 43 writel(c, ®s->dr); 44 45 return 0; 46 } 47 48 static int pl01x_getc(struct pl01x_regs *regs) 49 { 50 unsigned int data; 51 52 /* Wait until there is data in the FIFO */ 53 if (readl(®s->fr) & UART_PL01x_FR_RXFE) 54 return -EAGAIN; 55 56 data = readl(®s->dr); 57 58 /* Check for an error flag */ 59 if (data & 0xFFFFFF00) { 60 /* Clear the error */ 61 writel(0xFFFFFFFF, ®s->ecr); 62 return -1; 63 } 64 65 return (int) data; 66 } 67 68 static int pl01x_tstc(struct pl01x_regs *regs) 69 { 70 WATCHDOG_RESET(); 71 return !(readl(®s->fr) & UART_PL01x_FR_RXFE); 72 } 73 74 static int pl01x_generic_serial_init(struct pl01x_regs *regs, 75 enum pl01x_type type) 76 { 77 switch (type) { 78 case TYPE_PL010: 79 /* disable everything */ 80 writel(0, ®s->pl010_cr); 81 break; 82 case TYPE_PL011: 83 /* disable everything */ 84 writel(0, ®s->pl011_cr); 85 break; 86 default: 87 return -EINVAL; 88 } 89 90 return 0; 91 } 92 93 static int pl011_set_line_control(struct pl01x_regs *regs) 94 { 95 unsigned int lcr; 96 /* 97 * Internal update of baud rate register require line 98 * control register write 99 */ 100 lcr = UART_PL011_LCRH_WLEN_8 | UART_PL011_LCRH_FEN; 101 writel(lcr, ®s->pl011_lcrh); 102 return 0; 103 } 104 105 static int pl01x_generic_setbrg(struct pl01x_regs *regs, enum pl01x_type type, 106 int clock, int baudrate) 107 { 108 switch (type) { 109 case TYPE_PL010: { 110 unsigned int divisor; 111 112 /* disable everything */ 113 writel(0, ®s->pl010_cr); 114 115 switch (baudrate) { 116 case 9600: 117 divisor = UART_PL010_BAUD_9600; 118 break; 119 case 19200: 120 divisor = UART_PL010_BAUD_19200; 121 break; 122 case 38400: 123 divisor = UART_PL010_BAUD_38400; 124 break; 125 case 57600: 126 divisor = UART_PL010_BAUD_57600; 127 break; 128 case 115200: 129 divisor = UART_PL010_BAUD_115200; 130 break; 131 default: 132 divisor = UART_PL010_BAUD_38400; 133 } 134 135 writel((divisor & 0xf00) >> 8, ®s->pl010_lcrm); 136 writel(divisor & 0xff, ®s->pl010_lcrl); 137 138 /* 139 * Set line control for the PL010 to be 8 bits, 1 stop bit, 140 * no parity, fifo enabled 141 */ 142 writel(UART_PL010_LCRH_WLEN_8 | UART_PL010_LCRH_FEN, 143 ®s->pl010_lcrh); 144 /* Finally, enable the UART */ 145 writel(UART_PL010_CR_UARTEN, ®s->pl010_cr); 146 break; 147 } 148 case TYPE_PL011: { 149 unsigned int temp; 150 unsigned int divider; 151 unsigned int remainder; 152 unsigned int fraction; 153 154 /* 155 * Set baud rate 156 * 157 * IBRD = UART_CLK / (16 * BAUD_RATE) 158 * FBRD = RND((64 * MOD(UART_CLK,(16 * BAUD_RATE))) 159 * / (16 * BAUD_RATE)) 160 */ 161 temp = 16 * baudrate; 162 divider = clock / temp; 163 remainder = clock % temp; 164 temp = (8 * remainder) / baudrate; 165 fraction = (temp >> 1) + (temp & 1); 166 167 writel(divider, ®s->pl011_ibrd); 168 writel(fraction, ®s->pl011_fbrd); 169 170 pl011_set_line_control(regs); 171 /* Finally, enable the UART */ 172 writel(UART_PL011_CR_UARTEN | UART_PL011_CR_TXE | 173 UART_PL011_CR_RXE | UART_PL011_CR_RTS, ®s->pl011_cr); 174 break; 175 } 176 default: 177 return -EINVAL; 178 } 179 180 return 0; 181 } 182 183 #ifndef CONFIG_DM_SERIAL 184 static void pl01x_serial_init_baud(int baudrate) 185 { 186 int clock = 0; 187 188 #if defined(CONFIG_PL010_SERIAL) 189 pl01x_type = TYPE_PL010; 190 #elif defined(CONFIG_PL011_SERIAL) 191 pl01x_type = TYPE_PL011; 192 clock = CONFIG_PL011_CLOCK; 193 #endif 194 base_regs = (struct pl01x_regs *)port[CONFIG_CONS_INDEX]; 195 196 pl01x_generic_serial_init(base_regs, pl01x_type); 197 pl01x_generic_setbrg(base_regs, pl01x_type, clock, baudrate); 198 } 199 200 /* 201 * Integrator AP has two UARTs, we use the first one, at 38400-8-N-1 202 * Integrator CP has two UARTs, use the first one, at 38400-8-N-1 203 * Versatile PB has four UARTs. 204 */ 205 int pl01x_serial_init(void) 206 { 207 pl01x_serial_init_baud(CONFIG_BAUDRATE); 208 209 return 0; 210 } 211 212 static void pl01x_serial_putc(const char c) 213 { 214 if (c == '\n') 215 while (pl01x_putc(base_regs, '\r') == -EAGAIN); 216 217 while (pl01x_putc(base_regs, c) == -EAGAIN); 218 } 219 220 static int pl01x_serial_getc(void) 221 { 222 while (1) { 223 int ch = pl01x_getc(base_regs); 224 225 if (ch == -EAGAIN) { 226 WATCHDOG_RESET(); 227 continue; 228 } 229 230 return ch; 231 } 232 } 233 234 static int pl01x_serial_tstc(void) 235 { 236 return pl01x_tstc(base_regs); 237 } 238 239 static void pl01x_serial_setbrg(void) 240 { 241 /* 242 * Flush FIFO and wait for non-busy before changing baudrate to avoid 243 * crap in console 244 */ 245 while (!(readl(&base_regs->fr) & UART_PL01x_FR_TXFE)) 246 WATCHDOG_RESET(); 247 while (readl(&base_regs->fr) & UART_PL01x_FR_BUSY) 248 WATCHDOG_RESET(); 249 pl01x_serial_init_baud(gd->baudrate); 250 } 251 252 static struct serial_device pl01x_serial_drv = { 253 .name = "pl01x_serial", 254 .start = pl01x_serial_init, 255 .stop = NULL, 256 .setbrg = pl01x_serial_setbrg, 257 .putc = pl01x_serial_putc, 258 .puts = default_serial_puts, 259 .getc = pl01x_serial_getc, 260 .tstc = pl01x_serial_tstc, 261 }; 262 263 void pl01x_serial_initialize(void) 264 { 265 serial_register(&pl01x_serial_drv); 266 } 267 268 __weak struct serial_device *default_serial_console(void) 269 { 270 return &pl01x_serial_drv; 271 } 272 273 #endif /* nCONFIG_DM_SERIAL */ 274 275 #ifdef CONFIG_DM_SERIAL 276 277 struct pl01x_priv { 278 struct pl01x_regs *regs; 279 enum pl01x_type type; 280 }; 281 282 static int pl01x_serial_setbrg(struct udevice *dev, int baudrate) 283 { 284 struct pl01x_serial_platdata *plat = dev_get_platdata(dev); 285 struct pl01x_priv *priv = dev_get_priv(dev); 286 287 if (!plat->skip_init) { 288 pl01x_generic_setbrg(priv->regs, priv->type, plat->clock, 289 baudrate); 290 } 291 292 return 0; 293 } 294 295 static int pl01x_serial_probe(struct udevice *dev) 296 { 297 struct pl01x_serial_platdata *plat = dev_get_platdata(dev); 298 struct pl01x_priv *priv = dev_get_priv(dev); 299 300 priv->regs = (struct pl01x_regs *)plat->base; 301 priv->type = plat->type; 302 if (!plat->skip_init) 303 return pl01x_generic_serial_init(priv->regs, priv->type); 304 else 305 return 0; 306 } 307 308 static int pl01x_serial_getc(struct udevice *dev) 309 { 310 struct pl01x_priv *priv = dev_get_priv(dev); 311 312 return pl01x_getc(priv->regs); 313 } 314 315 static int pl01x_serial_putc(struct udevice *dev, const char ch) 316 { 317 struct pl01x_priv *priv = dev_get_priv(dev); 318 319 return pl01x_putc(priv->regs, ch); 320 } 321 322 static int pl01x_serial_pending(struct udevice *dev, bool input) 323 { 324 struct pl01x_priv *priv = dev_get_priv(dev); 325 unsigned int fr = readl(&priv->regs->fr); 326 327 if (input) 328 return pl01x_tstc(priv->regs); 329 else 330 return fr & UART_PL01x_FR_TXFF ? 0 : 1; 331 } 332 333 static const struct dm_serial_ops pl01x_serial_ops = { 334 .putc = pl01x_serial_putc, 335 .pending = pl01x_serial_pending, 336 .getc = pl01x_serial_getc, 337 .setbrg = pl01x_serial_setbrg, 338 }; 339 340 #if CONFIG_IS_ENABLED(OF_CONTROL) 341 static const struct udevice_id pl01x_serial_id[] ={ 342 {.compatible = "arm,pl011", .data = TYPE_PL011}, 343 {.compatible = "arm,pl010", .data = TYPE_PL010}, 344 {} 345 }; 346 347 static int pl01x_serial_ofdata_to_platdata(struct udevice *dev) 348 { 349 struct pl01x_serial_platdata *plat = dev_get_platdata(dev); 350 fdt_addr_t addr; 351 352 addr = dev_get_addr(dev); 353 if (addr == FDT_ADDR_T_NONE) 354 return -EINVAL; 355 356 plat->base = addr; 357 plat->clock = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "clock", 358 1); 359 plat->type = dev_get_driver_data(dev); 360 plat->skip_init = fdtdec_get_bool(gd->fdt_blob, dev_of_offset(dev), 361 "skip-init"); 362 return 0; 363 } 364 #endif 365 366 U_BOOT_DRIVER(serial_pl01x) = { 367 .name = "serial_pl01x", 368 .id = UCLASS_SERIAL, 369 .of_match = of_match_ptr(pl01x_serial_id), 370 .ofdata_to_platdata = of_match_ptr(pl01x_serial_ofdata_to_platdata), 371 .platdata_auto_alloc_size = sizeof(struct pl01x_serial_platdata), 372 .probe = pl01x_serial_probe, 373 .ops = &pl01x_serial_ops, 374 .flags = DM_FLAG_PRE_RELOC, 375 .priv_auto_alloc_size = sizeof(struct pl01x_priv), 376 }; 377 378 #endif 379 380 #if defined(CONFIG_DEBUG_UART_PL010) || defined(CONFIG_DEBUG_UART_PL011) 381 382 #include <debug_uart.h> 383 384 static void _debug_uart_init(void) 385 { 386 #ifndef CONFIG_DEBUG_UART_SKIP_INIT 387 struct pl01x_regs *regs = (struct pl01x_regs *)CONFIG_DEBUG_UART_BASE; 388 enum pl01x_type type = CONFIG_IS_ENABLED(DEBUG_UART_PL011) ? 389 TYPE_PL011 : TYPE_PL010; 390 391 pl01x_generic_serial_init(regs, type); 392 pl01x_generic_setbrg(regs, type, 393 CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE); 394 #endif 395 } 396 397 static inline void _debug_uart_putc(int ch) 398 { 399 struct pl01x_regs *regs = (struct pl01x_regs *)CONFIG_DEBUG_UART_BASE; 400 401 pl01x_putc(regs, ch); 402 } 403 404 DEBUG_UART_FUNCS 405 406 #endif 407