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