your board config header. The clock input is automatically set to
          use the oscillator (24MHz).
 
+config NS16550_SERIAL
+       bool "NS16550 UART or compatible"
+       depends on DM_SERIAL
+       help
+         Support NS16550 UART or compatible with driver model. This can be
+         enabled in the device tree with the correct input clock frequency.
+         If the input clock frequency is not defined in the device tree,
+         the macro CONFIG_SYS_NS16550_CLK defined in a legacy board header
+         file will be used. It can be a constant or a function to get clock,
+         eg, get_serial_clock().
+
 config SANDBOX_SERIAL
        bool "Sandbox UART support"
        depends on SANDBOX
 
 
 #ifdef CONFIG_DM_SERIAL
 
+#ifndef CONFIG_SYS_NS16550_CLK
+#define CONFIG_SYS_NS16550_CLK  0
+#endif
+
 static inline void serial_out_shift(void *addr, int shift, int value)
 {
 #ifdef CONFIG_SYS_NS16550_PORT_MAPPED
        plat->base = addr;
        plat->reg_shift = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
                                         "reg-shift", 1);
+#ifdef CONFIG_NS16550_SERIAL
+       plat->clock = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+                                    "clock-frequency",
+                                    CONFIG_SYS_NS16550_CLK);
+       if (!plat->clock) {
+               debug("ns16550 clock not defined\n");
+               return -EINVAL;
+       }
+#endif /* CONFIG_NS16550_SERIAL */
 
        return 0;
 }
        .getc = ns16550_serial_getc,
        .setbrg = ns16550_serial_setbrg,
 };
+
+#ifdef CONFIG_NS16550_SERIAL
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+static const struct udevice_id ns16550_serial_ids[] = {
+       { .compatible = "ns16550" },
+       { .compatible = "ns16550a" },
+       { .compatible = "nvidia,tegra20-uart" },
+       { .compatible = "snps,dw-apb-uart" },
+       { .compatible = "ti,omap2-uart" },
+       { .compatible = "ti,omap3-uart" },
+       { .compatible = "ti,omap4-uart" },
+       { .compatible = "ti,am3352-uart" },
+       { .compatible = "ti,am4372-uart" },
+       { .compatible = "ti,dra742-uart" },
+       {}
+};
+#endif
+
+U_BOOT_DRIVER(ns16550_serial) = {
+       .name   = "ns16550_serial",
+       .id     = UCLASS_SERIAL,
+#if CONFIG_IS_ENABLED(OF_CONTROL)
+       .of_match = ns16550_serial_ids,
+       .ofdata_to_platdata = ns16550_serial_ofdata_to_platdata,
+       .platdata_auto_alloc_size = sizeof(struct ns16550_platdata),
+#endif
+       .priv_auto_alloc_size = sizeof(struct NS16550),
+       .probe = ns16550_serial_probe,
+       .ops    = &ns16550_serial_ops,
+};
+#endif /* CONFIG_NS16550_SERIAL */
 #endif /* CONFIG_DM_SERIAL */