Commit 8e62d32e authored by Thomas Chou's avatar Thomas Chou Committed by Tom Rini
Browse files

ns16550: add generic binding to unify the drivers

Add generic binding to unify ns16550 drivers. There are
several drivers using almost the same code, such as serial_dw,
serial_keystone, serial_omap, serial_ppc, serial_rockchip,
serial_tegra.c, and serial_x86. But each is platform specific.

The key difference between these drivers is the way to get
input clock frequency. With this unified approach, fixed clock
frequency should be extracted from "clock-frequency" property of
device tree blob. If this property is not available, the macro
CONFIG_SYS_NS16550_CLK will be used. It can be a constant or a
function to get clock, eg, get_serial_clock().
Signed-off-by: Thomas Chou's avatarThomas Chou <>
Reviewed-by: Tom Rini's avatarTom Rini <>
Reviewed-by: Bin Meng's avatarBin Meng <>
Reviewed-by: Heiko Schocher's avatarHeiko Schocher <>
Acked-by: Simon Glass's avatarSimon Glass <>
parent 77d7b5cd
......@@ -195,6 +195,17 @@ config ROCKCHIP_SERIAL
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
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().
bool "Sandbox UART support"
depends on SANDBOX
......@@ -56,6 +56,10 @@ DECLARE_GLOBAL_DATA_PTR;
#ifndef CONFIG_SYS_NS16550_CLK
#define CONFIG_SYS_NS16550_CLK 0
static inline void serial_out_shift(void *addr, int shift, int value)
......@@ -400,6 +404,15 @@ int ns16550_serial_ofdata_to_platdata(struct udevice *dev)
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,
if (!plat->clock) {
debug("ns16550 clock not defined\n");
return -EINVAL;
#endif /* CONFIG_NS16550_SERIAL */
return 0;
......@@ -411,4 +424,35 @@ const struct dm_serial_ops ns16550_serial_ops = {
.getc = ns16550_serial_getc,
.setbrg = ns16550_serial_setbrg,
#ifdef CONFIG_NS16550_SERIAL
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" },
U_BOOT_DRIVER(ns16550_serial) = {
.name = "ns16550_serial",
.of_match = ns16550_serial_ids,
.ofdata_to_platdata = ns16550_serial_ofdata_to_platdata,
.platdata_auto_alloc_size = sizeof(struct ns16550_platdata),
.priv_auto_alloc_size = sizeof(struct NS16550),
.probe = ns16550_serial_probe,
.ops = &ns16550_serial_ops,
#endif /* CONFIG_NS16550_SERIAL */
#endif /* CONFIG_DM_SERIAL */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment