120c9226cSAndreas Engel /* 220c9226cSAndreas Engel * (C) Copyright 2000 320c9226cSAndreas Engel * Rob Taylor, Flying Pig Systems. robt@flyingpig.com. 420c9226cSAndreas Engel * 520c9226cSAndreas Engel * (C) Copyright 2004 620c9226cSAndreas Engel * ARM Ltd. 720c9226cSAndreas Engel * Philippe Robin, <philippe.robin@arm.com> 820c9226cSAndreas Engel * 91a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 1020c9226cSAndreas Engel */ 1120c9226cSAndreas Engel 1248d0192fSAndreas Engel /* Simple U-Boot driver for the PrimeCell PL010/PL011 UARTs */ 1320c9226cSAndreas Engel 1420c9226cSAndreas Engel #include <common.h> 158a9cd5adSSimon Glass #include <dm.h> 16aed2fbefSSimon Glass #include <errno.h> 1720c9226cSAndreas Engel #include <watchdog.h> 18249d5219SMatt Waddel #include <asm/io.h> 1939f61477SMarek Vasut #include <serial.h> 2086256b79SMasahiro Yamada #include <dm/platform_data/serial_pl01x.h> 2139f61477SMarek Vasut #include <linux/compiler.h> 22aed2fbefSSimon Glass #include "serial_pl01x_internal.h" 2369751729SVikas Manocha #include <fdtdec.h> 2469751729SVikas Manocha 2569751729SVikas Manocha DECLARE_GLOBAL_DATA_PTR; 2620c9226cSAndreas Engel 278a9cd5adSSimon Glass #ifndef CONFIG_DM_SERIAL 288a9cd5adSSimon Glass 2920c9226cSAndreas Engel static volatile unsigned char *const port[] = CONFIG_PL01x_PORTS; 30aed2fbefSSimon Glass static enum pl01x_type pl01x_type __attribute__ ((section(".data"))); 31aed2fbefSSimon Glass static struct pl01x_regs *base_regs __attribute__ ((section(".data"))); 3220c9226cSAndreas Engel #define NUM_PORTS (sizeof(port)/sizeof(port[0])) 3320c9226cSAndreas Engel 348a9cd5adSSimon Glass #endif 3520c9226cSAndreas Engel 36aed2fbefSSimon Glass static int pl01x_putc(struct pl01x_regs *regs, char c) 3772d5e44cSRabin Vincent { 3820c9226cSAndreas Engel /* Wait until there is space in the FIFO */ 39aed2fbefSSimon Glass if (readl(®s->fr) & UART_PL01x_FR_TXFF) 40aed2fbefSSimon Glass return -EAGAIN; 4120c9226cSAndreas Engel 4220c9226cSAndreas Engel /* Send the character */ 4372d5e44cSRabin Vincent writel(c, ®s->dr); 44aed2fbefSSimon Glass 45aed2fbefSSimon Glass return 0; 4620c9226cSAndreas Engel } 4720c9226cSAndreas Engel 48aed2fbefSSimon Glass static int pl01x_getc(struct pl01x_regs *regs) 4920c9226cSAndreas Engel { 5020c9226cSAndreas Engel unsigned int data; 5120c9226cSAndreas Engel 5220c9226cSAndreas Engel /* Wait until there is data in the FIFO */ 53aed2fbefSSimon Glass if (readl(®s->fr) & UART_PL01x_FR_RXFE) 54aed2fbefSSimon Glass return -EAGAIN; 5520c9226cSAndreas Engel 5672d5e44cSRabin Vincent data = readl(®s->dr); 5720c9226cSAndreas Engel 5820c9226cSAndreas Engel /* Check for an error flag */ 5920c9226cSAndreas Engel if (data & 0xFFFFFF00) { 6020c9226cSAndreas Engel /* Clear the error */ 6172d5e44cSRabin Vincent writel(0xFFFFFFFF, ®s->ecr); 6220c9226cSAndreas Engel return -1; 6320c9226cSAndreas Engel } 6420c9226cSAndreas Engel 6520c9226cSAndreas Engel return (int) data; 6620c9226cSAndreas Engel } 6720c9226cSAndreas Engel 68aed2fbefSSimon Glass static int pl01x_tstc(struct pl01x_regs *regs) 6920c9226cSAndreas Engel { 7020c9226cSAndreas Engel WATCHDOG_RESET(); 7172d5e44cSRabin Vincent return !(readl(®s->fr) & UART_PL01x_FR_RXFE); 7220c9226cSAndreas Engel } 7339f61477SMarek Vasut 74aed2fbefSSimon Glass static int pl01x_generic_serial_init(struct pl01x_regs *regs, 75aed2fbefSSimon Glass enum pl01x_type type) 76aed2fbefSSimon Glass { 77aed2fbefSSimon Glass switch (type) { 78aed2fbefSSimon Glass case TYPE_PL010: 79f7e517b4SVikas Manocha /* disable everything */ 80f7e517b4SVikas Manocha writel(0, ®s->pl010_cr); 81aed2fbefSSimon Glass break; 82d2ca9fd2SVikas Manocha case TYPE_PL011: 83f7e517b4SVikas Manocha /* disable everything */ 84f7e517b4SVikas Manocha writel(0, ®s->pl011_cr); 85d2ca9fd2SVikas Manocha break; 86d2ca9fd2SVikas Manocha default: 87d2ca9fd2SVikas Manocha return -EINVAL; 88d2ca9fd2SVikas Manocha } 89d2ca9fd2SVikas Manocha 90d2ca9fd2SVikas Manocha return 0; 91d2ca9fd2SVikas Manocha } 92d2ca9fd2SVikas Manocha 93d77447fdSLinus Walleij static int pl011_set_line_control(struct pl01x_regs *regs) 94d2ca9fd2SVikas Manocha { 95d2ca9fd2SVikas Manocha unsigned int lcr; 96d2ca9fd2SVikas Manocha /* 97d2ca9fd2SVikas Manocha * Internal update of baud rate register require line 98d2ca9fd2SVikas Manocha * control register write 99d2ca9fd2SVikas Manocha */ 100d2ca9fd2SVikas Manocha lcr = UART_PL011_LCRH_WLEN_8 | UART_PL011_LCRH_FEN; 101d2ca9fd2SVikas Manocha writel(lcr, ®s->pl011_lcrh); 102aed2fbefSSimon Glass return 0; 103aed2fbefSSimon Glass } 104aed2fbefSSimon Glass 105aed2fbefSSimon Glass static int pl01x_generic_setbrg(struct pl01x_regs *regs, enum pl01x_type type, 106aed2fbefSSimon Glass int clock, int baudrate) 107aed2fbefSSimon Glass { 108aed2fbefSSimon Glass switch (type) { 109aed2fbefSSimon Glass case TYPE_PL010: { 110aed2fbefSSimon Glass unsigned int divisor; 111aed2fbefSSimon Glass 112d77447fdSLinus Walleij /* disable everything */ 113d77447fdSLinus Walleij writel(0, ®s->pl010_cr); 114d77447fdSLinus Walleij 115aed2fbefSSimon Glass switch (baudrate) { 116aed2fbefSSimon Glass case 9600: 117aed2fbefSSimon Glass divisor = UART_PL010_BAUD_9600; 118aed2fbefSSimon Glass break; 119aed2fbefSSimon Glass case 19200: 120aed2fbefSSimon Glass divisor = UART_PL010_BAUD_9600; 121aed2fbefSSimon Glass break; 122aed2fbefSSimon Glass case 38400: 123aed2fbefSSimon Glass divisor = UART_PL010_BAUD_38400; 124aed2fbefSSimon Glass break; 125aed2fbefSSimon Glass case 57600: 126aed2fbefSSimon Glass divisor = UART_PL010_BAUD_57600; 127aed2fbefSSimon Glass break; 128aed2fbefSSimon Glass case 115200: 129aed2fbefSSimon Glass divisor = UART_PL010_BAUD_115200; 130aed2fbefSSimon Glass break; 131aed2fbefSSimon Glass default: 132aed2fbefSSimon Glass divisor = UART_PL010_BAUD_38400; 133aed2fbefSSimon Glass } 134aed2fbefSSimon Glass 135aed2fbefSSimon Glass writel((divisor & 0xf00) >> 8, ®s->pl010_lcrm); 136aed2fbefSSimon Glass writel(divisor & 0xff, ®s->pl010_lcrl); 137aed2fbefSSimon Glass 138d77447fdSLinus Walleij /* 139d77447fdSLinus Walleij * Set line control for the PL010 to be 8 bits, 1 stop bit, 140d77447fdSLinus Walleij * no parity, fifo enabled 141d77447fdSLinus Walleij */ 142d77447fdSLinus Walleij writel(UART_PL010_LCRH_WLEN_8 | UART_PL010_LCRH_FEN, 143d77447fdSLinus Walleij ®s->pl010_lcrh); 144aed2fbefSSimon Glass /* Finally, enable the UART */ 145aed2fbefSSimon Glass writel(UART_PL010_CR_UARTEN, ®s->pl010_cr); 146aed2fbefSSimon Glass break; 147aed2fbefSSimon Glass } 148aed2fbefSSimon Glass case TYPE_PL011: { 149aed2fbefSSimon Glass unsigned int temp; 150aed2fbefSSimon Glass unsigned int divider; 151aed2fbefSSimon Glass unsigned int remainder; 152aed2fbefSSimon Glass unsigned int fraction; 153aed2fbefSSimon Glass 154aed2fbefSSimon Glass /* 155aed2fbefSSimon Glass * Set baud rate 156aed2fbefSSimon Glass * 157aed2fbefSSimon Glass * IBRD = UART_CLK / (16 * BAUD_RATE) 158aed2fbefSSimon Glass * FBRD = RND((64 * MOD(UART_CLK,(16 * BAUD_RATE))) 159aed2fbefSSimon Glass * / (16 * BAUD_RATE)) 160aed2fbefSSimon Glass */ 161aed2fbefSSimon Glass temp = 16 * baudrate; 162aed2fbefSSimon Glass divider = clock / temp; 163aed2fbefSSimon Glass remainder = clock % temp; 164aed2fbefSSimon Glass temp = (8 * remainder) / baudrate; 165aed2fbefSSimon Glass fraction = (temp >> 1) + (temp & 1); 166aed2fbefSSimon Glass 167aed2fbefSSimon Glass writel(divider, ®s->pl011_ibrd); 168aed2fbefSSimon Glass writel(fraction, ®s->pl011_fbrd); 169aed2fbefSSimon Glass 170d77447fdSLinus Walleij pl011_set_line_control(regs); 171aed2fbefSSimon Glass /* Finally, enable the UART */ 172aed2fbefSSimon Glass writel(UART_PL011_CR_UARTEN | UART_PL011_CR_TXE | 173aed2fbefSSimon Glass UART_PL011_CR_RXE | UART_PL011_CR_RTS, ®s->pl011_cr); 174aed2fbefSSimon Glass break; 175aed2fbefSSimon Glass } 176aed2fbefSSimon Glass default: 177aed2fbefSSimon Glass return -EINVAL; 178aed2fbefSSimon Glass } 179aed2fbefSSimon Glass 180aed2fbefSSimon Glass return 0; 181aed2fbefSSimon Glass } 182aed2fbefSSimon Glass 183aed2fbefSSimon Glass #ifndef CONFIG_DM_SERIAL 184aed2fbefSSimon Glass static void pl01x_serial_init_baud(int baudrate) 185aed2fbefSSimon Glass { 186aed2fbefSSimon Glass int clock = 0; 187aed2fbefSSimon Glass 188aed2fbefSSimon Glass #if defined(CONFIG_PL010_SERIAL) 189aed2fbefSSimon Glass pl01x_type = TYPE_PL010; 190aed2fbefSSimon Glass #elif defined(CONFIG_PL011_SERIAL) 191aed2fbefSSimon Glass pl01x_type = TYPE_PL011; 192aed2fbefSSimon Glass clock = CONFIG_PL011_CLOCK; 193aed2fbefSSimon Glass #endif 194aed2fbefSSimon Glass base_regs = (struct pl01x_regs *)port[CONFIG_CONS_INDEX]; 195aed2fbefSSimon Glass 196aed2fbefSSimon Glass pl01x_generic_serial_init(base_regs, pl01x_type); 197a7deea69SVikas Manocha pl01x_generic_setbrg(base_regs, pl01x_type, clock, baudrate); 198aed2fbefSSimon Glass } 199aed2fbefSSimon Glass 200aed2fbefSSimon Glass /* 201aed2fbefSSimon Glass * Integrator AP has two UARTs, we use the first one, at 38400-8-N-1 202aed2fbefSSimon Glass * Integrator CP has two UARTs, use the first one, at 38400-8-N-1 203aed2fbefSSimon Glass * Versatile PB has four UARTs. 204aed2fbefSSimon Glass */ 205aed2fbefSSimon Glass int pl01x_serial_init(void) 206aed2fbefSSimon Glass { 207aed2fbefSSimon Glass pl01x_serial_init_baud(CONFIG_BAUDRATE); 208aed2fbefSSimon Glass 209aed2fbefSSimon Glass return 0; 210aed2fbefSSimon Glass } 211aed2fbefSSimon Glass 212aed2fbefSSimon Glass static void pl01x_serial_putc(const char c) 213aed2fbefSSimon Glass { 214aed2fbefSSimon Glass if (c == '\n') 215aed2fbefSSimon Glass while (pl01x_putc(base_regs, '\r') == -EAGAIN); 216aed2fbefSSimon Glass 217aed2fbefSSimon Glass while (pl01x_putc(base_regs, c) == -EAGAIN); 218aed2fbefSSimon Glass } 219aed2fbefSSimon Glass 220aed2fbefSSimon Glass static int pl01x_serial_getc(void) 221aed2fbefSSimon Glass { 222aed2fbefSSimon Glass while (1) { 223aed2fbefSSimon Glass int ch = pl01x_getc(base_regs); 224aed2fbefSSimon Glass 225aed2fbefSSimon Glass if (ch == -EAGAIN) { 226aed2fbefSSimon Glass WATCHDOG_RESET(); 227aed2fbefSSimon Glass continue; 228aed2fbefSSimon Glass } 229aed2fbefSSimon Glass 230aed2fbefSSimon Glass return ch; 231aed2fbefSSimon Glass } 232aed2fbefSSimon Glass } 233aed2fbefSSimon Glass 234aed2fbefSSimon Glass static int pl01x_serial_tstc(void) 235aed2fbefSSimon Glass { 236aed2fbefSSimon Glass return pl01x_tstc(base_regs); 237aed2fbefSSimon Glass } 238aed2fbefSSimon Glass 239aed2fbefSSimon Glass static void pl01x_serial_setbrg(void) 240aed2fbefSSimon Glass { 241aed2fbefSSimon Glass /* 242aed2fbefSSimon Glass * Flush FIFO and wait for non-busy before changing baudrate to avoid 243aed2fbefSSimon Glass * crap in console 244aed2fbefSSimon Glass */ 245aed2fbefSSimon Glass while (!(readl(&base_regs->fr) & UART_PL01x_FR_TXFE)) 246aed2fbefSSimon Glass WATCHDOG_RESET(); 247aed2fbefSSimon Glass while (readl(&base_regs->fr) & UART_PL01x_FR_BUSY) 248aed2fbefSSimon Glass WATCHDOG_RESET(); 249aed2fbefSSimon Glass pl01x_serial_init_baud(gd->baudrate); 250aed2fbefSSimon Glass } 251aed2fbefSSimon Glass 25239f61477SMarek Vasut static struct serial_device pl01x_serial_drv = { 25339f61477SMarek Vasut .name = "pl01x_serial", 25439f61477SMarek Vasut .start = pl01x_serial_init, 25539f61477SMarek Vasut .stop = NULL, 25639f61477SMarek Vasut .setbrg = pl01x_serial_setbrg, 25739f61477SMarek Vasut .putc = pl01x_serial_putc, 258ec3fd689SMarek Vasut .puts = default_serial_puts, 25939f61477SMarek Vasut .getc = pl01x_serial_getc, 26039f61477SMarek Vasut .tstc = pl01x_serial_tstc, 26139f61477SMarek Vasut }; 26239f61477SMarek Vasut 26339f61477SMarek Vasut void pl01x_serial_initialize(void) 26439f61477SMarek Vasut { 26539f61477SMarek Vasut serial_register(&pl01x_serial_drv); 26639f61477SMarek Vasut } 26739f61477SMarek Vasut 26839f61477SMarek Vasut __weak struct serial_device *default_serial_console(void) 26939f61477SMarek Vasut { 27039f61477SMarek Vasut return &pl01x_serial_drv; 27139f61477SMarek Vasut } 272aed2fbefSSimon Glass 273aed2fbefSSimon Glass #endif /* nCONFIG_DM_SERIAL */ 2748a9cd5adSSimon Glass 2758a9cd5adSSimon Glass #ifdef CONFIG_DM_SERIAL 2768a9cd5adSSimon Glass 2778a9cd5adSSimon Glass struct pl01x_priv { 2788a9cd5adSSimon Glass struct pl01x_regs *regs; 2798a9cd5adSSimon Glass enum pl01x_type type; 2808a9cd5adSSimon Glass }; 2818a9cd5adSSimon Glass 2828a9cd5adSSimon Glass static int pl01x_serial_setbrg(struct udevice *dev, int baudrate) 2838a9cd5adSSimon Glass { 2848a9cd5adSSimon Glass struct pl01x_serial_platdata *plat = dev_get_platdata(dev); 2858a9cd5adSSimon Glass struct pl01x_priv *priv = dev_get_priv(dev); 2868a9cd5adSSimon Glass 287*cd0fa5bfSEric Anholt if (!plat->skip_init) { 288*cd0fa5bfSEric Anholt pl01x_generic_setbrg(priv->regs, priv->type, plat->clock, 289*cd0fa5bfSEric Anholt baudrate); 290*cd0fa5bfSEric Anholt } 2918a9cd5adSSimon Glass 2928a9cd5adSSimon Glass return 0; 2938a9cd5adSSimon Glass } 2948a9cd5adSSimon Glass 2958a9cd5adSSimon Glass static int pl01x_serial_probe(struct udevice *dev) 2968a9cd5adSSimon Glass { 2978a9cd5adSSimon Glass struct pl01x_serial_platdata *plat = dev_get_platdata(dev); 2988a9cd5adSSimon Glass struct pl01x_priv *priv = dev_get_priv(dev); 2998a9cd5adSSimon Glass 3008a9cd5adSSimon Glass priv->regs = (struct pl01x_regs *)plat->base; 3018a9cd5adSSimon Glass priv->type = plat->type; 302*cd0fa5bfSEric Anholt if (!plat->skip_init) 3038a9cd5adSSimon Glass return pl01x_generic_serial_init(priv->regs, priv->type); 304*cd0fa5bfSEric Anholt else 305*cd0fa5bfSEric Anholt return 0; 3068a9cd5adSSimon Glass } 3078a9cd5adSSimon Glass 3088a9cd5adSSimon Glass static int pl01x_serial_getc(struct udevice *dev) 3098a9cd5adSSimon Glass { 3108a9cd5adSSimon Glass struct pl01x_priv *priv = dev_get_priv(dev); 3118a9cd5adSSimon Glass 3128a9cd5adSSimon Glass return pl01x_getc(priv->regs); 3138a9cd5adSSimon Glass } 3148a9cd5adSSimon Glass 3158a9cd5adSSimon Glass static int pl01x_serial_putc(struct udevice *dev, const char ch) 3168a9cd5adSSimon Glass { 3178a9cd5adSSimon Glass struct pl01x_priv *priv = dev_get_priv(dev); 3188a9cd5adSSimon Glass 3198a9cd5adSSimon Glass return pl01x_putc(priv->regs, ch); 3208a9cd5adSSimon Glass } 3218a9cd5adSSimon Glass 3228a9cd5adSSimon Glass static int pl01x_serial_pending(struct udevice *dev, bool input) 3238a9cd5adSSimon Glass { 3248a9cd5adSSimon Glass struct pl01x_priv *priv = dev_get_priv(dev); 3258a9cd5adSSimon Glass unsigned int fr = readl(&priv->regs->fr); 3268a9cd5adSSimon Glass 3278a9cd5adSSimon Glass if (input) 3288a9cd5adSSimon Glass return pl01x_tstc(priv->regs); 3298a9cd5adSSimon Glass else 3308a9cd5adSSimon Glass return fr & UART_PL01x_FR_TXFF ? 0 : 1; 3318a9cd5adSSimon Glass } 3328a9cd5adSSimon Glass 3338a9cd5adSSimon Glass static const struct dm_serial_ops pl01x_serial_ops = { 3348a9cd5adSSimon Glass .putc = pl01x_serial_putc, 3358a9cd5adSSimon Glass .pending = pl01x_serial_pending, 3368a9cd5adSSimon Glass .getc = pl01x_serial_getc, 3378a9cd5adSSimon Glass .setbrg = pl01x_serial_setbrg, 3388a9cd5adSSimon Glass }; 3398a9cd5adSSimon Glass 3400f925822SMasahiro Yamada #if CONFIG_IS_ENABLED(OF_CONTROL) 34169751729SVikas Manocha static const struct udevice_id pl01x_serial_id[] ={ 34269751729SVikas Manocha {.compatible = "arm,pl011", .data = TYPE_PL011}, 34369751729SVikas Manocha {.compatible = "arm,pl010", .data = TYPE_PL010}, 34469751729SVikas Manocha {} 34569751729SVikas Manocha }; 34669751729SVikas Manocha 34769751729SVikas Manocha static int pl01x_serial_ofdata_to_platdata(struct udevice *dev) 34869751729SVikas Manocha { 34969751729SVikas Manocha struct pl01x_serial_platdata *plat = dev_get_platdata(dev); 35069751729SVikas Manocha fdt_addr_t addr; 35169751729SVikas Manocha 3524e9838c1SSimon Glass addr = dev_get_addr(dev); 35369751729SVikas Manocha if (addr == FDT_ADDR_T_NONE) 35469751729SVikas Manocha return -EINVAL; 35569751729SVikas Manocha 35669751729SVikas Manocha plat->base = addr; 35769751729SVikas Manocha plat->clock = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "clock", 1); 35869751729SVikas Manocha plat->type = dev_get_driver_data(dev); 35969751729SVikas Manocha return 0; 36069751729SVikas Manocha } 36169751729SVikas Manocha #endif 36269751729SVikas Manocha 3638a9cd5adSSimon Glass U_BOOT_DRIVER(serial_pl01x) = { 3648a9cd5adSSimon Glass .name = "serial_pl01x", 3658a9cd5adSSimon Glass .id = UCLASS_SERIAL, 36669751729SVikas Manocha .of_match = of_match_ptr(pl01x_serial_id), 36769751729SVikas Manocha .ofdata_to_platdata = of_match_ptr(pl01x_serial_ofdata_to_platdata), 36869751729SVikas Manocha .platdata_auto_alloc_size = sizeof(struct pl01x_serial_platdata), 3698a9cd5adSSimon Glass .probe = pl01x_serial_probe, 3708a9cd5adSSimon Glass .ops = &pl01x_serial_ops, 3718a9cd5adSSimon Glass .flags = DM_FLAG_PRE_RELOC, 37259c73d75SSimon Glass .priv_auto_alloc_size = sizeof(struct pl01x_priv), 3738a9cd5adSSimon Glass }; 3748a9cd5adSSimon Glass 3758a9cd5adSSimon Glass #endif 376b81406dbSSergey Temerkhanov 377b81406dbSSergey Temerkhanov #if defined(CONFIG_DEBUG_UART_PL010) || defined(CONFIG_DEBUG_UART_PL011) 378b81406dbSSergey Temerkhanov 379b81406dbSSergey Temerkhanov #include <debug_uart.h> 380b81406dbSSergey Temerkhanov 381b81406dbSSergey Temerkhanov static void _debug_uart_init(void) 382b81406dbSSergey Temerkhanov { 383b81406dbSSergey Temerkhanov #ifndef CONFIG_DEBUG_UART_SKIP_INIT 384b81406dbSSergey Temerkhanov struct pl01x_regs *regs = (struct pl01x_regs *)CONFIG_DEBUG_UART_BASE; 385b81406dbSSergey Temerkhanov enum pl01x_type type = CONFIG_IS_ENABLED(DEBUG_UART_PL011) ? 386b81406dbSSergey Temerkhanov TYPE_PL011 : TYPE_PL010; 387b81406dbSSergey Temerkhanov 388b81406dbSSergey Temerkhanov pl01x_generic_serial_init(regs, type); 389b81406dbSSergey Temerkhanov pl01x_generic_setbrg(regs, type, 390b81406dbSSergey Temerkhanov CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE); 391b81406dbSSergey Temerkhanov #endif 392b81406dbSSergey Temerkhanov } 393b81406dbSSergey Temerkhanov 394b81406dbSSergey Temerkhanov static inline void _debug_uart_putc(int ch) 395b81406dbSSergey Temerkhanov { 396b81406dbSSergey Temerkhanov struct pl01x_regs *regs = (struct pl01x_regs *)CONFIG_DEBUG_UART_BASE; 397b81406dbSSergey Temerkhanov 398b81406dbSSergey Temerkhanov pl01x_putc(regs, ch); 399b81406dbSSergey Temerkhanov } 400b81406dbSSergey Temerkhanov 401b81406dbSSergey Temerkhanov DEBUG_UART_FUNCS 402b81406dbSSergey Temerkhanov 403b81406dbSSergey Temerkhanov #endif 404