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