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