diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 0900cc8acb7f681d49bce1a0e016443ee5fff51c..c0ec2ec2e4d03577fbcde4eddb6ae6a1ff374a45 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -376,6 +376,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 8ba15ce028e87e9d9e979440d0640cc388d35844..4382cf93297b25a4ae35044bbd1dd31e813f795c 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 0000000000000000000000000000000000000000..777c09d6d247a6d7e7c105fb5b7176cc9c61470e --- /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, +};