uboot/drivers/serial/ns16550.c
<<
>>
Prefs
   1/*
   2 * COM1 NS16550 support
   3 * originally from linux source (arch/powerpc/boot/ns16550.c)
   4 * modified to use CONFIG_SYS_ISA_MEM and new defines
   5 */
   6
   7#include <clock_legacy.h>
   8#include <common.h>
   9#include <clk.h>
  10#include <dm.h>
  11#include <errno.h>
  12#include <log.h>
  13#include <ns16550.h>
  14#include <reset.h>
  15#include <serial.h>
  16#include <watchdog.h>
  17#include <asm/global_data.h>
  18#include <linux/err.h>
  19#include <linux/types.h>
  20#include <asm/io.h>
  21
  22DECLARE_GLOBAL_DATA_PTR;
  23
  24#define UART_LCRVAL UART_LCR_8N1                /* 8 data, 1 stop, no parity */
  25#define UART_MCRVAL (UART_MCR_DTR | \
  26                     UART_MCR_RTS)              /* RTS/DTR */
  27
  28#if !CONFIG_IS_ENABLED(DM_SERIAL)
  29#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
  30#define serial_out(x, y)        outb(x, (ulong)y)
  31#define serial_in(y)            inb((ulong)y)
  32#elif defined(CONFIG_SYS_NS16550_MEM32) && (CONFIG_SYS_NS16550_REG_SIZE > 0)
  33#define serial_out(x, y)        out_be32(y, x)
  34#define serial_in(y)            in_be32(y)
  35#elif defined(CONFIG_SYS_NS16550_MEM32) && (CONFIG_SYS_NS16550_REG_SIZE < 0)
  36#define serial_out(x, y)        out_le32(y, x)
  37#define serial_in(y)            in_le32(y)
  38#else
  39#define serial_out(x, y)        writeb(x, y)
  40#define serial_in(y)            readb(y)
  41#endif
  42#endif /* !CONFIG_DM_SERIAL */
  43
  44#if defined(CONFIG_ARCH_KEYSTONE)
  45#define UART_REG_VAL_PWREMU_MGMT_UART_DISABLE   0
  46#define UART_REG_VAL_PWREMU_MGMT_UART_ENABLE ((1 << 14) | (1 << 13) | (1 << 0))
  47#undef UART_MCRVAL
  48#ifdef CONFIG_SERIAL_HW_FLOW_CONTROL
  49#define UART_MCRVAL             (UART_MCR_RTS | UART_MCR_AFE)
  50#else
  51#define UART_MCRVAL             (UART_MCR_RTS)
  52#endif
  53#endif
  54
  55#ifndef CONFIG_SYS_NS16550_IER
  56#define CONFIG_SYS_NS16550_IER  0x00
  57#endif /* CONFIG_SYS_NS16550_IER */
  58
  59static inline void serial_out_shift(void *addr, int shift, int value)
  60{
  61#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
  62        outb(value, (ulong)addr);
  63#elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_LITTLE_ENDIAN)
  64        out_le32(addr, value);
  65#elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_BIG_ENDIAN)
  66        out_be32(addr, value);
  67#elif defined(CONFIG_SYS_NS16550_MEM32)
  68        writel(value, addr);
  69#elif defined(CONFIG_SYS_BIG_ENDIAN)
  70        writeb(value, addr + (1 << shift) - 1);
  71#else
  72        writeb(value, addr);
  73#endif
  74}
  75
  76static inline int serial_in_shift(void *addr, int shift)
  77{
  78#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
  79        return inb((ulong)addr);
  80#elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_LITTLE_ENDIAN)
  81        return in_le32(addr);
  82#elif defined(CONFIG_SYS_NS16550_MEM32) && defined(CONFIG_SYS_BIG_ENDIAN)
  83        return in_be32(addr);
  84#elif defined(CONFIG_SYS_NS16550_MEM32)
  85        return readl(addr);
  86#elif defined(CONFIG_SYS_BIG_ENDIAN)
  87        return readb(addr + (1 << shift) - 1);
  88#else
  89        return readb(addr);
  90#endif
  91}
  92
  93#if CONFIG_IS_ENABLED(DM_SERIAL)
  94
  95#ifndef CONFIG_SYS_NS16550_CLK
  96#define CONFIG_SYS_NS16550_CLK  0
  97#endif
  98
  99/*
 100 * Use this #ifdef for now since many platforms don't define in(), out(),
 101 * out_le32(), etc. but we don't have #defines to indicate this.
 102 *
 103 * TODO(sjg@chromium.org): Add CONFIG options to indicate what I/O is available
 104 * on a platform
 105 */
 106#ifdef CONFIG_NS16550_DYNAMIC
 107static void serial_out_dynamic(struct ns16550_plat *plat, u8 *addr,
 108                               int value)
 109{
 110        if (plat->flags & NS16550_FLAG_IO) {
 111                outb(value, addr);
 112        } else if (plat->reg_width == 4) {
 113                if (plat->flags & NS16550_FLAG_ENDIAN) {
 114                        if (plat->flags & NS16550_FLAG_BE)
 115                                out_be32(addr, value);
 116                        else
 117                                out_le32(addr, value);
 118                } else {
 119                        writel(value, addr);
 120                }
 121        } else if (plat->flags & NS16550_FLAG_BE) {
 122                writeb(value, addr + (1 << plat->reg_shift) - 1);
 123        } else {
 124                writeb(value, addr);
 125        }
 126}
 127
 128static int serial_in_dynamic(struct ns16550_plat *plat, u8 *addr)
 129{
 130        if (plat->flags & NS16550_FLAG_IO) {
 131                return inb(addr);
 132        } else if (plat->reg_width == 4) {
 133                if (plat->flags & NS16550_FLAG_ENDIAN) {
 134                        if (plat->flags & NS16550_FLAG_BE)
 135                                return in_be32(addr);
 136                        else
 137                                return in_le32(addr);
 138                } else {
 139                        return readl(addr);
 140                }
 141        } else if (plat->flags & NS16550_FLAG_BE) {
 142                return readb(addr + (1 << plat->reg_shift) - 1);
 143        } else {
 144                return readb(addr);
 145        }
 146}
 147#else
 148static inline void serial_out_dynamic(struct ns16550_plat *plat, u8 *addr,
 149                                      int value)
 150{
 151}
 152
 153static inline int serial_in_dynamic(struct ns16550_plat *plat, u8 *addr)
 154{
 155        return 0;
 156}
 157
 158#endif /* CONFIG_NS16550_DYNAMIC */
 159
 160static void ns16550_writeb(struct ns16550 *port, int offset, int value)
 161{
 162        struct ns16550_plat *plat = port->plat;
 163        unsigned char *addr;
 164
 165        offset *= 1 << plat->reg_shift;
 166        addr = (unsigned char *)plat->base + offset + plat->reg_offset;
 167
 168        if (IS_ENABLED(CONFIG_NS16550_DYNAMIC))
 169                serial_out_dynamic(plat, addr, value);
 170        else
 171                serial_out_shift(addr, plat->reg_shift, value);
 172}
 173
 174static int ns16550_readb(struct ns16550 *port, int offset)
 175{
 176        struct ns16550_plat *plat = port->plat;
 177        unsigned char *addr;
 178
 179        offset *= 1 << plat->reg_shift;
 180        addr = (unsigned char *)plat->base + offset + plat->reg_offset;
 181
 182        if (IS_ENABLED(CONFIG_NS16550_DYNAMIC))
 183                return serial_in_dynamic(plat, addr);
 184        else
 185                return serial_in_shift(addr, plat->reg_shift);
 186}
 187
 188static u32 ns16550_getfcr(struct ns16550 *port)
 189{
 190        struct ns16550_plat *plat = port->plat;
 191
 192        return plat->fcr;
 193}
 194
 195/* We can clean these up once everything is moved to driver model */
 196#define serial_out(value, addr) \
 197        ns16550_writeb(com_port, \
 198                (unsigned char *)addr - (unsigned char *)com_port, value)
 199#define serial_in(addr) \
 200        ns16550_readb(com_port, \
 201                (unsigned char *)addr - (unsigned char *)com_port)
 202#else
 203static u32 ns16550_getfcr(struct ns16550 *port)
 204{
 205        return UART_FCR_DEFVAL;
 206}
 207#endif
 208
 209int ns16550_calc_divisor(struct ns16550 *port, int clock, int baudrate)
 210{
 211        const unsigned int mode_x_div = 16;
 212
 213        return DIV_ROUND_CLOSEST(clock, mode_x_div * baudrate);
 214}
 215
 216static void ns16550_setbrg(struct ns16550 *com_port, int baud_divisor)
 217{
 218        /* to keep serial format, read lcr before writing BKSE */
 219        int lcr_val = serial_in(&com_port->lcr) & ~UART_LCR_BKSE;
 220
 221        serial_out(UART_LCR_BKSE | lcr_val, &com_port->lcr);
 222        serial_out(baud_divisor & 0xff, &com_port->dll);
 223        serial_out((baud_divisor >> 8) & 0xff, &com_port->dlm);
 224        serial_out(lcr_val, &com_port->lcr);
 225}
 226
 227void ns16550_init(struct ns16550 *com_port, int baud_divisor)
 228{
 229#if (defined(CONFIG_SPL_BUILD) && \
 230                (defined(CONFIG_OMAP34XX) || defined(CONFIG_OMAP44XX)))
 231        /*
 232         * On some OMAP3/OMAP4 devices when UART3 is configured for boot mode
 233         * before SPL starts only THRE bit is set. We have to empty the
 234         * transmitter before initialization starts.
 235         */
 236        if ((serial_in(&com_port->lsr) & (UART_LSR_TEMT | UART_LSR_THRE))
 237             == UART_LSR_THRE) {
 238                if (baud_divisor != -1)
 239                        ns16550_setbrg(com_port, baud_divisor);
 240                else {
 241                        // Re-use old baud rate divisor to flush transmit reg.
 242                        const int dll = serial_in(&com_port->dll);
 243                        const int dlm = serial_in(&com_port->dlm);
 244                        const int divisor = dll | (dlm << 8);
 245                        ns16550_setbrg(com_port, divisor);
 246                }
 247                serial_out(0, &com_port->mdr1);
 248        }
 249#endif
 250
 251        while (!(serial_in(&com_port->lsr) & UART_LSR_TEMT))
 252                ;
 253
 254        serial_out(CONFIG_SYS_NS16550_IER, &com_port->ier);
 255#if defined(CONFIG_ARCH_OMAP2PLUS) || defined(CONFIG_OMAP_SERIAL)
 256        serial_out(0x7, &com_port->mdr1);       /* mode select reset TL16C750*/
 257#endif
 258
 259        serial_out(UART_MCRVAL, &com_port->mcr);
 260        serial_out(ns16550_getfcr(com_port), &com_port->fcr);
 261        /* initialize serial config to 8N1 before writing baudrate */
 262        serial_out(UART_LCRVAL, &com_port->lcr);
 263        if (baud_divisor != -1)
 264                ns16550_setbrg(com_port, baud_divisor);
 265#if defined(CONFIG_ARCH_OMAP2PLUS) || defined(CONFIG_SOC_DA8XX) || \
 266        defined(CONFIG_OMAP_SERIAL)
 267        /* /16 is proper to hit 115200 with 48MHz */
 268        serial_out(0, &com_port->mdr1);
 269#endif
 270#if defined(CONFIG_ARCH_KEYSTONE)
 271        serial_out(UART_REG_VAL_PWREMU_MGMT_UART_ENABLE, &com_port->regC);
 272#endif
 273}
 274
 275#ifndef CONFIG_NS16550_MIN_FUNCTIONS
 276void ns16550_reinit(struct ns16550 *com_port, int baud_divisor)
 277{
 278        serial_out(CONFIG_SYS_NS16550_IER, &com_port->ier);
 279        ns16550_setbrg(com_port, 0);
 280        serial_out(UART_MCRVAL, &com_port->mcr);
 281        serial_out(ns16550_getfcr(com_port), &com_port->fcr);
 282        ns16550_setbrg(com_port, baud_divisor);
 283}
 284#endif /* CONFIG_NS16550_MIN_FUNCTIONS */
 285
 286void ns16550_putc(struct ns16550 *com_port, char c)
 287{
 288        while ((serial_in(&com_port->lsr) & UART_LSR_THRE) == 0)
 289                ;
 290        serial_out(c, &com_port->thr);
 291
 292        /*
 293         * Call watchdog_reset() upon newline. This is done here in putc
 294         * since the environment code uses a single puts() to print the complete
 295         * environment upon "printenv". So we can't put this watchdog call
 296         * in puts().
 297         */
 298        if (c == '\n')
 299                WATCHDOG_RESET();
 300}
 301
 302#ifndef CONFIG_NS16550_MIN_FUNCTIONS
 303char ns16550_getc(struct ns16550 *com_port)
 304{
 305        while ((serial_in(&com_port->lsr) & UART_LSR_DR) == 0) {
 306#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_USB_TTY)
 307                extern void usbtty_poll(void);
 308                usbtty_poll();
 309#endif
 310                WATCHDOG_RESET();
 311        }
 312        return serial_in(&com_port->rbr);
 313}
 314
 315int ns16550_tstc(struct ns16550 *com_port)
 316{
 317        return (serial_in(&com_port->lsr) & UART_LSR_DR) != 0;
 318}
 319
 320#endif /* CONFIG_NS16550_MIN_FUNCTIONS */
 321
 322#ifdef CONFIG_DEBUG_UART_NS16550
 323
 324#include <debug_uart.h>
 325
 326static inline void _debug_uart_init(void)
 327{
 328        struct ns16550 *com_port = (struct ns16550 *)CONFIG_DEBUG_UART_BASE;
 329        int baud_divisor;
 330
 331        /*
 332         * We copy the code from above because it is already horribly messy.
 333         * Trying to refactor to nicely remove the duplication doesn't seem
 334         * feasible. The better fix is to move all users of this driver to
 335         * driver model.
 336         */
 337        baud_divisor = ns16550_calc_divisor(com_port, CONFIG_DEBUG_UART_CLOCK,
 338                                            CONFIG_BAUDRATE);
 339        serial_dout(&com_port->ier, CONFIG_SYS_NS16550_IER);
 340        serial_dout(&com_port->mcr, UART_MCRVAL);
 341        serial_dout(&com_port->fcr, UART_FCR_DEFVAL);
 342
 343        serial_dout(&com_port->lcr, UART_LCR_BKSE | UART_LCRVAL);
 344        serial_dout(&com_port->dll, baud_divisor & 0xff);
 345        serial_dout(&com_port->dlm, (baud_divisor >> 8) & 0xff);
 346        serial_dout(&com_port->lcr, UART_LCRVAL);
 347}
 348
 349static inline int NS16550_read_baud_divisor(struct ns16550 *com_port)
 350{
 351        int ret;
 352
 353        serial_dout(&com_port->lcr, UART_LCR_BKSE | UART_LCRVAL);
 354        ret = serial_din(&com_port->dll) & 0xff;
 355        ret |= (serial_din(&com_port->dlm) & 0xff) << 8;
 356        serial_dout(&com_port->lcr, UART_LCRVAL);
 357
 358        return ret;
 359}
 360
 361static inline void _debug_uart_putc(int ch)
 362{
 363        struct ns16550 *com_port = (struct ns16550 *)CONFIG_DEBUG_UART_BASE;
 364
 365        while (!(serial_din(&com_port->lsr) & UART_LSR_THRE)) {
 366#ifdef CONFIG_DEBUG_UART_NS16550_CHECK_ENABLED
 367                if (!NS16550_read_baud_divisor(com_port))
 368                        return;
 369#endif
 370        }
 371        serial_dout(&com_port->thr, ch);
 372}
 373
 374DEBUG_UART_FUNCS
 375
 376#endif
 377
 378#if CONFIG_IS_ENABLED(DM_SERIAL)
 379static int ns16550_serial_putc(struct udevice *dev, const char ch)
 380{
 381        struct ns16550 *const com_port = dev_get_priv(dev);
 382
 383        if (!(serial_in(&com_port->lsr) & UART_LSR_THRE))
 384                return -EAGAIN;
 385        serial_out(ch, &com_port->thr);
 386
 387        /*
 388         * Call watchdog_reset() upon newline. This is done here in putc
 389         * since the environment code uses a single puts() to print the complete
 390         * environment upon "printenv". So we can't put this watchdog call
 391         * in puts().
 392         */
 393        if (ch == '\n')
 394                WATCHDOG_RESET();
 395
 396        return 0;
 397}
 398
 399static int ns16550_serial_pending(struct udevice *dev, bool input)
 400{
 401        struct ns16550 *const com_port = dev_get_priv(dev);
 402
 403        if (input)
 404                return (serial_in(&com_port->lsr) & UART_LSR_DR) ? 1 : 0;
 405        else
 406                return (serial_in(&com_port->lsr) & UART_LSR_THRE) ? 0 : 1;
 407}
 408
 409static int ns16550_serial_getc(struct udevice *dev)
 410{
 411        struct ns16550 *const com_port = dev_get_priv(dev);
 412
 413        if (!(serial_in(&com_port->lsr) & UART_LSR_DR))
 414                return -EAGAIN;
 415
 416        return serial_in(&com_port->rbr);
 417}
 418
 419static int ns16550_serial_setbrg(struct udevice *dev, int baudrate)
 420{
 421        struct ns16550 *const com_port = dev_get_priv(dev);
 422        struct ns16550_plat *plat = com_port->plat;
 423        int clock_divisor;
 424
 425        clock_divisor = ns16550_calc_divisor(com_port, plat->clock, baudrate);
 426
 427        ns16550_setbrg(com_port, clock_divisor);
 428
 429        return 0;
 430}
 431
 432static int ns16550_serial_setconfig(struct udevice *dev, uint serial_config)
 433{
 434        struct ns16550 *const com_port = dev_get_priv(dev);
 435        int lcr_val = UART_LCR_WLS_8;
 436        uint parity = SERIAL_GET_PARITY(serial_config);
 437        uint bits = SERIAL_GET_BITS(serial_config);
 438        uint stop = SERIAL_GET_STOP(serial_config);
 439
 440        /*
 441         * only parity config is implemented, check if other serial settings
 442         * are the default one.
 443         */
 444        if (bits != SERIAL_8_BITS || stop != SERIAL_ONE_STOP)
 445                return -ENOTSUPP; /* not supported in driver*/
 446
 447        switch (parity) {
 448        case SERIAL_PAR_NONE:
 449                /* no bits to add */
 450                break;
 451        case SERIAL_PAR_ODD:
 452                lcr_val |= UART_LCR_PEN;
 453                break;
 454        case SERIAL_PAR_EVEN:
 455                lcr_val |= UART_LCR_PEN | UART_LCR_EPS;
 456                break;
 457        default:
 458                return -ENOTSUPP; /* not supported in driver*/
 459        }
 460
 461        serial_out(lcr_val, &com_port->lcr);
 462        return 0;
 463}
 464
 465static int ns16550_serial_getinfo(struct udevice *dev,
 466                                  struct serial_device_info *info)
 467{
 468        struct ns16550 *const com_port = dev_get_priv(dev);
 469        struct ns16550_plat *plat = com_port->plat;
 470
 471        info->type = SERIAL_CHIP_16550_COMPATIBLE;
 472#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
 473        info->addr_space = SERIAL_ADDRESS_SPACE_IO;
 474#else
 475        info->addr_space = SERIAL_ADDRESS_SPACE_MEMORY;
 476#endif
 477        info->addr = plat->base;
 478        info->reg_width = plat->reg_width;
 479        info->reg_shift = plat->reg_shift;
 480        info->reg_offset = plat->reg_offset;
 481        info->clock = plat->clock;
 482
 483        return 0;
 484}
 485
 486static int ns16550_serial_assign_base(struct ns16550_plat *plat, fdt_addr_t base)
 487{
 488        if (base == FDT_ADDR_T_NONE)
 489                return -EINVAL;
 490
 491#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
 492        plat->base = base;
 493#else
 494        plat->base = (unsigned long)map_physmem(base, 0, MAP_NOCACHE);
 495#endif
 496
 497        return 0;
 498}
 499
 500int ns16550_serial_probe(struct udevice *dev)
 501{
 502        struct ns16550_plat *plat = dev_get_plat(dev);
 503        struct ns16550 *const com_port = dev_get_priv(dev);
 504        struct reset_ctl_bulk reset_bulk;
 505        fdt_addr_t addr;
 506        int ret;
 507
 508        /*
 509         * If we are on PCI bus, either directly attached to a PCI root port,
 510         * or via a PCI bridge, assign plat->base before probing hardware.
 511         */
 512        if (device_is_on_pci_bus(dev)) {
 513                addr = devfdt_get_addr_pci(dev);
 514                ret = ns16550_serial_assign_base(plat, addr);
 515                if (ret)
 516                        return ret;
 517        }
 518
 519        ret = reset_get_bulk(dev, &reset_bulk);
 520        if (!ret)
 521                reset_deassert_bulk(&reset_bulk);
 522
 523        com_port->plat = dev_get_plat(dev);
 524        ns16550_init(com_port, -1);
 525
 526        return 0;
 527}
 528
 529#if CONFIG_IS_ENABLED(OF_CONTROL)
 530enum {
 531        PORT_NS16550 = 0,
 532        PORT_JZ4780,
 533};
 534#endif
 535
 536#if CONFIG_IS_ENABLED(OF_REAL)
 537int ns16550_serial_of_to_plat(struct udevice *dev)
 538{
 539        struct ns16550_plat *plat = dev_get_plat(dev);
 540        const u32 port_type = dev_get_driver_data(dev);
 541        fdt_addr_t addr;
 542        struct clk clk;
 543        int err;
 544
 545        addr = dev_read_addr(dev);
 546        err = ns16550_serial_assign_base(plat, addr);
 547        if (err && !device_is_on_pci_bus(dev))
 548                return err;
 549
 550        plat->reg_offset = dev_read_u32_default(dev, "reg-offset", 0);
 551        plat->reg_shift = dev_read_u32_default(dev, "reg-shift", 0);
 552        plat->reg_width = dev_read_u32_default(dev, "reg-io-width", 1);
 553
 554        err = clk_get_by_index(dev, 0, &clk);
 555        if (!err) {
 556                err = clk_get_rate(&clk);
 557                if (!IS_ERR_VALUE(err))
 558                        plat->clock = err;
 559        } else if (err != -ENOENT && err != -ENODEV && err != -ENOSYS) {
 560                debug("ns16550 failed to get clock\n");
 561                return err;
 562        }
 563
 564        if (!plat->clock)
 565                plat->clock = dev_read_u32_default(dev, "clock-frequency",
 566                                                   CONFIG_SYS_NS16550_CLK);
 567        if (!plat->clock)
 568                plat->clock = CONFIG_SYS_NS16550_CLK;
 569        if (!plat->clock) {
 570                debug("ns16550 clock not defined\n");
 571                return -EINVAL;
 572        }
 573
 574        plat->fcr = UART_FCR_DEFVAL;
 575        if (port_type == PORT_JZ4780)
 576                plat->fcr |= UART_FCR_UME;
 577
 578        return 0;
 579}
 580#endif
 581
 582const struct dm_serial_ops ns16550_serial_ops = {
 583        .putc = ns16550_serial_putc,
 584        .pending = ns16550_serial_pending,
 585        .getc = ns16550_serial_getc,
 586        .setbrg = ns16550_serial_setbrg,
 587        .setconfig = ns16550_serial_setconfig,
 588        .getinfo = ns16550_serial_getinfo,
 589};
 590
 591#if CONFIG_IS_ENABLED(OF_REAL)
 592/*
 593 * Please consider existing compatible strings before adding a new
 594 * one to keep this table compact. Or you may add a generic "ns16550"
 595 * compatible string to your dts.
 596 */
 597static const struct udevice_id ns16550_serial_ids[] = {
 598        { .compatible = "ns16550",              .data = PORT_NS16550 },
 599        { .compatible = "ns16550a",             .data = PORT_NS16550 },
 600        { .compatible = "ingenic,jz4780-uart",  .data = PORT_JZ4780  },
 601        { .compatible = "nvidia,tegra20-uart",  .data = PORT_NS16550 },
 602        { .compatible = "snps,dw-apb-uart",     .data = PORT_NS16550 },
 603        {}
 604};
 605#endif /* OF_REAL */
 606
 607#if CONFIG_IS_ENABLED(SERIAL_PRESENT)
 608
 609/* TODO(sjg@chromium.org): Integrate this into a macro like CONFIG_IS_ENABLED */
 610#if !defined(CONFIG_TPL_BUILD) || defined(CONFIG_TPL_DM_SERIAL)
 611U_BOOT_DRIVER(ns16550_serial) = {
 612        .name   = "ns16550_serial",
 613        .id     = UCLASS_SERIAL,
 614#if CONFIG_IS_ENABLED(OF_REAL)
 615        .of_match = ns16550_serial_ids,
 616        .of_to_plat = ns16550_serial_of_to_plat,
 617        .plat_auto      = sizeof(struct ns16550_plat),
 618#endif
 619        .priv_auto      = sizeof(struct ns16550),
 620        .probe = ns16550_serial_probe,
 621        .ops    = &ns16550_serial_ops,
 622#if !CONFIG_IS_ENABLED(OF_CONTROL)
 623        .flags  = DM_FLAG_PRE_RELOC,
 624#endif
 625};
 626
 627DM_DRIVER_ALIAS(ns16550_serial, rockchip_rk3328_uart)
 628DM_DRIVER_ALIAS(ns16550_serial, rockchip_rk3368_uart)
 629DM_DRIVER_ALIAS(ns16550_serial, ti_da830_uart)
 630#endif
 631#endif /* SERIAL_PRESENT */
 632
 633#endif /* CONFIG_DM_SERIAL */
 634