From mboxrd@z Thu Jan 1 00:00:00 1970 From: Kever Yang Date: Fri, 03 Mar 2017 18:31:46 +0800 Subject: [U-Boot] [PATCH v3] serial: Add serial driver for Intel MID In-Reply-To: <20170228120410.10669-1-andriy.shevchenko@linux.intel.com> References: <20170228120410.10669-1-andriy.shevchenko@linux.intel.com> Message-ID: <58B94612.8020802@rock-chips.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Hi Andy, On 02/28/2017 08:04 PM, Andy Shevchenko wrote: > Add a specific serial driver for Intel MID platforms. > > It has special fractional divider which can be programmed via UART_PS, > UART_MUL, and UART_DIV registers. > > The UART clock is calculated as > > UART clock = XTAL * UART_MUL / UART_DIV > > The baudrate is calculated as > > baud rate = UART clock / UART_PS / DLAB > > Initialize fractional divider correctly for Intel Edison platform. > > For backward compatibility we have to set initial DLAB value to 16 > and speed to 115200 baud, where initial frequency is 29491200Hz, and > XTAL frequency is 38.4MHz. > > Signed-off-by: Andy Shevchenko > --- > drivers/serial/Kconfig | 9 +++++ > drivers/serial/Makefile | 1 + > drivers/serial/serial_intel_mid.c | 69 +++++++++++++++++++++++++++++++++++++++ > 3 files changed, 79 insertions(+) > create mode 100644 drivers/serial/serial_intel_mid.c > > diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig > index b11f3ff89e..99dcdeb00d 100644 > --- a/drivers/serial/Kconfig > +++ b/drivers/serial/Kconfig > @@ -347,6 +347,15 @@ config SYS_NS16550 > be used. It can be a constant or a function to get clock, eg, > get_serial_clock(). > > +config INTEL_MID_SERIAL > + bool "Intel MID platform UART support" > + depends on DM_SERIAL && OF_CONTROL > + depends on INTEL_MID > + select SYS_NS16550 > + help > + Select this to enable a UART for Intel MID platforms. > + This uses the ns16550 driver as a library. > + > config ROCKCHIP_SERIAL > bool "Rockchip on-chip UART support" > depends on DM_SERIAL && SPL_OF_PLATDATA > diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile > index 8430668bf9..abd9dea4dc 100644 > --- a/drivers/serial/Makefile > +++ b/drivers/serial/Makefile > @@ -28,6 +28,7 @@ obj-$(CONFIG_S5P) += serial_s5p.o > obj-$(CONFIG_MXC_UART) += serial_mxc.o > obj-$(CONFIG_PXA_SERIAL) += serial_pxa.o > obj-$(CONFIG_MESON_SERIAL) += serial_meson.o > +obj-$(CONFIG_INTEL_MID_SERIAL) += serial_intel_mid.o > ifdef CONFIG_SPL_BUILD > obj-$(CONFIG_ROCKCHIP_SERIAL) += serial_rockchip.o > endif > diff --git a/drivers/serial/serial_intel_mid.c b/drivers/serial/serial_intel_mid.c > new file mode 100644 > index 0000000000..777c09d6d2 > --- /dev/null > +++ b/drivers/serial/serial_intel_mid.c > @@ -0,0 +1,69 @@ > +/* > + * Copyright (c) 2017 Intel Corporation > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include > +#include > +#include > +#include > + > +/* > + * The UART clock is calculated as > + * > + * UART clock = XTAL * UART_MUL / UART_DIV > + * > + * The baudrate is calculated as > + * > + * baud rate = UART clock / UART_PS / DLAB > + */ > +#define UART_PS 0x30 > +#define UART_MUL 0x34 > +#define UART_DIV 0x38 > + > +static void mid_writel(struct ns16550_platdata *plat, int offset, int value) > +{ > + unsigned char *addr; > + > + offset *= 1 << plat->reg_shift; > + addr = (unsigned char *)plat->base + offset; > + > + writel(value, addr + plat->reg_offset); > +} > + > +static int mid_serial_probe(struct udevice *dev) > +{ > + struct ns16550_platdata *plat = dev_get_platdata(dev); > + > + /* > + * Initialize fractional divider correctly for Intel Edison > + * platform. > + * > + * For backward compatibility we have to set initial DLAB value > + * to 16 and speed to 115200 baud, where initial frequency is > + * 29491200Hz, and XTAL frequency is 38.4MHz. > + */ > + mid_writel(plat, UART_MUL, 96); > + mid_writel(plat, UART_DIV, 125); > + mid_writel(plat, UART_PS, 16); > + > + return ns16550_serial_probe(dev); > +} > + > +static const struct udevice_id mid_serial_ids[] = { > + { .compatible = "intel,mid-uart" }, > + {} > +}; > + > +U_BOOT_DRIVER(serial_intel_mid) = { > + .name = "serial_intel_mid", > + .id = UCLASS_SERIAL, > + .of_match = mid_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 = mid_serial_probe, > + .ops = &ns16550_serial_ops, > + .flags = DM_FLAG_PRE_RELOC, > +}; Reviewed-by: Kever Yang Thanks, - Kever