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 #ifndef CONFIG_DM_SERIAL 25 26 static volatile unsigned char *const port[] = CONFIG_PL01x_PORTS; 27 static enum pl01x_type pl01x_type __attribute__ ((section(".data"))); 28 static struct pl01x_regs *base_regs __attribute__ ((section(".data"))); 29 #define NUM_PORTS (sizeof(port)/sizeof(port[0])) 30 31 DECLARE_GLOBAL_DATA_PTR; 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 #ifdef CONFIG_PL011_SERIAL_FLUSH_ON_INIT 82 /* Empty RX fifo if necessary */ 83 if (readl(®s->pl011_cr) & UART_PL011_CR_UARTEN) { 84 while (!(readl(®s->fr) & UART_PL01x_FR_RXFE)) 85 readl(®s->dr); 86 } 87 #endif 88 /* disable everything */ 89 writel(0, ®s->pl011_cr); 90 break; 91 default: 92 return -EINVAL; 93 } 94 95 return 0; 96 } 97 98 static int pl011_set_line_control(struct pl01x_regs *regs) 99 { 100 unsigned int lcr; 101 /* 102 * Internal update of baud rate register require line 103 * control register write 104 */ 105 lcr = UART_PL011_LCRH_WLEN_8 | UART_PL011_LCRH_FEN; 106 #ifdef CONFIG_PL011_SERIAL_RLCR 107 { 108 int i; 109 110 /* 111 * Program receive line control register after waiting 112 * 10 bus cycles. Delay be writing to readonly register 113 * 10 times 114 */ 115 for (i = 0; i < 10; i++) 116 writel(lcr, ®s->fr); 117 118 writel(lcr, ®s->pl011_rlcr); 119 } 120 #endif 121 writel(lcr, ®s->pl011_lcrh); 122 return 0; 123 } 124 125 static int pl01x_generic_setbrg(struct pl01x_regs *regs, enum pl01x_type type, 126 int clock, int baudrate) 127 { 128 switch (type) { 129 case TYPE_PL010: { 130 unsigned int divisor; 131 132 /* disable everything */ 133 writel(0, ®s->pl010_cr); 134 135 switch (baudrate) { 136 case 9600: 137 divisor = UART_PL010_BAUD_9600; 138 break; 139 case 19200: 140 divisor = UART_PL010_BAUD_9600; 141 break; 142 case 38400: 143 divisor = UART_PL010_BAUD_38400; 144 break; 145 case 57600: 146 divisor = UART_PL010_BAUD_57600; 147 break; 148 case 115200: 149 divisor = UART_PL010_BAUD_115200; 150 break; 151 default: 152 divisor = UART_PL010_BAUD_38400; 153 } 154 155 writel((divisor & 0xf00) >> 8, ®s->pl010_lcrm); 156 writel(divisor & 0xff, ®s->pl010_lcrl); 157 158 /* 159 * Set line control for the PL010 to be 8 bits, 1 stop bit, 160 * no parity, fifo enabled 161 */ 162 writel(UART_PL010_LCRH_WLEN_8 | UART_PL010_LCRH_FEN, 163 ®s->pl010_lcrh); 164 /* Finally, enable the UART */ 165 writel(UART_PL010_CR_UARTEN, ®s->pl010_cr); 166 break; 167 } 168 case TYPE_PL011: { 169 unsigned int temp; 170 unsigned int divider; 171 unsigned int remainder; 172 unsigned int fraction; 173 174 /* 175 * Set baud rate 176 * 177 * IBRD = UART_CLK / (16 * BAUD_RATE) 178 * FBRD = RND((64 * MOD(UART_CLK,(16 * BAUD_RATE))) 179 * / (16 * BAUD_RATE)) 180 */ 181 temp = 16 * baudrate; 182 divider = clock / temp; 183 remainder = clock % temp; 184 temp = (8 * remainder) / baudrate; 185 fraction = (temp >> 1) + (temp & 1); 186 187 writel(divider, ®s->pl011_ibrd); 188 writel(fraction, ®s->pl011_fbrd); 189 190 pl011_set_line_control(regs); 191 /* Finally, enable the UART */ 192 writel(UART_PL011_CR_UARTEN | UART_PL011_CR_TXE | 193 UART_PL011_CR_RXE | UART_PL011_CR_RTS, ®s->pl011_cr); 194 break; 195 } 196 default: 197 return -EINVAL; 198 } 199 200 return 0; 201 } 202 203 #ifndef CONFIG_DM_SERIAL 204 static void pl01x_serial_init_baud(int baudrate) 205 { 206 int clock = 0; 207 208 #if defined(CONFIG_PL010_SERIAL) 209 pl01x_type = TYPE_PL010; 210 #elif defined(CONFIG_PL011_SERIAL) 211 pl01x_type = TYPE_PL011; 212 clock = CONFIG_PL011_CLOCK; 213 #endif 214 base_regs = (struct pl01x_regs *)port[CONFIG_CONS_INDEX]; 215 216 pl01x_generic_serial_init(base_regs, pl01x_type); 217 pl01x_generic_setbrg(base_regs, pl01x_type, clock, baudrate); 218 } 219 220 /* 221 * Integrator AP has two UARTs, we use the first one, at 38400-8-N-1 222 * Integrator CP has two UARTs, use the first one, at 38400-8-N-1 223 * Versatile PB has four UARTs. 224 */ 225 int pl01x_serial_init(void) 226 { 227 pl01x_serial_init_baud(CONFIG_BAUDRATE); 228 229 return 0; 230 } 231 232 static void pl01x_serial_putc(const char c) 233 { 234 if (c == '\n') 235 while (pl01x_putc(base_regs, '\r') == -EAGAIN); 236 237 while (pl01x_putc(base_regs, c) == -EAGAIN); 238 } 239 240 static int pl01x_serial_getc(void) 241 { 242 while (1) { 243 int ch = pl01x_getc(base_regs); 244 245 if (ch == -EAGAIN) { 246 WATCHDOG_RESET(); 247 continue; 248 } 249 250 return ch; 251 } 252 } 253 254 static int pl01x_serial_tstc(void) 255 { 256 return pl01x_tstc(base_regs); 257 } 258 259 static void pl01x_serial_setbrg(void) 260 { 261 /* 262 * Flush FIFO and wait for non-busy before changing baudrate to avoid 263 * crap in console 264 */ 265 while (!(readl(&base_regs->fr) & UART_PL01x_FR_TXFE)) 266 WATCHDOG_RESET(); 267 while (readl(&base_regs->fr) & UART_PL01x_FR_BUSY) 268 WATCHDOG_RESET(); 269 pl01x_serial_init_baud(gd->baudrate); 270 } 271 272 static struct serial_device pl01x_serial_drv = { 273 .name = "pl01x_serial", 274 .start = pl01x_serial_init, 275 .stop = NULL, 276 .setbrg = pl01x_serial_setbrg, 277 .putc = pl01x_serial_putc, 278 .puts = default_serial_puts, 279 .getc = pl01x_serial_getc, 280 .tstc = pl01x_serial_tstc, 281 }; 282 283 void pl01x_serial_initialize(void) 284 { 285 serial_register(&pl01x_serial_drv); 286 } 287 288 __weak struct serial_device *default_serial_console(void) 289 { 290 return &pl01x_serial_drv; 291 } 292 293 #endif /* nCONFIG_DM_SERIAL */ 294 295 #ifdef CONFIG_DM_SERIAL 296 297 struct pl01x_priv { 298 struct pl01x_regs *regs; 299 enum pl01x_type type; 300 }; 301 302 static int pl01x_serial_setbrg(struct udevice *dev, int baudrate) 303 { 304 struct pl01x_serial_platdata *plat = dev_get_platdata(dev); 305 struct pl01x_priv *priv = dev_get_priv(dev); 306 307 pl01x_generic_setbrg(priv->regs, priv->type, plat->clock, baudrate); 308 309 return 0; 310 } 311 312 static int pl01x_serial_probe(struct udevice *dev) 313 { 314 struct pl01x_serial_platdata *plat = dev_get_platdata(dev); 315 struct pl01x_priv *priv = dev_get_priv(dev); 316 317 priv->regs = (struct pl01x_regs *)plat->base; 318 priv->type = plat->type; 319 return pl01x_generic_serial_init(priv->regs, priv->type); 320 } 321 322 static int pl01x_serial_getc(struct udevice *dev) 323 { 324 struct pl01x_priv *priv = dev_get_priv(dev); 325 326 return pl01x_getc(priv->regs); 327 } 328 329 static int pl01x_serial_putc(struct udevice *dev, const char ch) 330 { 331 struct pl01x_priv *priv = dev_get_priv(dev); 332 333 return pl01x_putc(priv->regs, ch); 334 } 335 336 static int pl01x_serial_pending(struct udevice *dev, bool input) 337 { 338 struct pl01x_priv *priv = dev_get_priv(dev); 339 unsigned int fr = readl(&priv->regs->fr); 340 341 if (input) 342 return pl01x_tstc(priv->regs); 343 else 344 return fr & UART_PL01x_FR_TXFF ? 0 : 1; 345 } 346 347 static const struct dm_serial_ops pl01x_serial_ops = { 348 .putc = pl01x_serial_putc, 349 .pending = pl01x_serial_pending, 350 .getc = pl01x_serial_getc, 351 .setbrg = pl01x_serial_setbrg, 352 }; 353 354 U_BOOT_DRIVER(serial_pl01x) = { 355 .name = "serial_pl01x", 356 .id = UCLASS_SERIAL, 357 .probe = pl01x_serial_probe, 358 .ops = &pl01x_serial_ops, 359 .flags = DM_FLAG_PRE_RELOC, 360 .priv_auto_alloc_size = sizeof(struct pl01x_priv), 361 }; 362 363 #endif 364