[U-Boot] [PATCH 1/2] serial: Introduce linflex uart support
Bin Meng
bmeng.cn at gmail.com
Mon Apr 4 05:22:48 CEST 2016
On Sun, Apr 3, 2016 at 8:10 AM, Eddy Petrișor <eddy.petrisor at gmail.com> wrote:
> From: Stoica Cosmin-Stefan <cosminstefan.stoica at freescale.com>
>
> The Linflex module is integrated on some NXP automotive SoCs part of the former
> Freescale portfolio, like S32V234, an SoC for Advanced Driver Assistance
> Systems.
>
> Signed-off-by: Stoica Cosmin-Stefan <cosminstefan.stoica at freescale.com>
> Signed-off-by: Chircu Bogdan <Bogdan.Chircu at freescale.com>
> Signed-off-by: Depons Eric <eric.depons at freescale.com>
> Signed-off-by: Eddy Petrișor <eddy.petrisor at gmail.com>
> ---
> drivers/serial/Makefile | 1 +
> drivers/serial/serial_linflexuart.c | 147 ++++++++++++++++++++++++++++++++++++
> 2 files changed, 148 insertions(+)
> create mode 100644 drivers/serial/serial_linflexuart.c
>
> diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
> index ee7147a..b009478 100644
> --- a/drivers/serial/Makefile
> +++ b/drivers/serial/Makefile
> @@ -33,6 +33,7 @@ obj-$(CONFIG_SCIF_CONSOLE) += serial_sh.o
> obj-$(CONFIG_ZYNQ_SERIAL) += serial_zynq.o
> obj-$(CONFIG_BFIN_SERIAL) += serial_bfin.o
> obj-$(CONFIG_FSL_LPUART) += serial_lpuart.o
> +obj-$(CONFIG_FSL_LINFLEXUART) += serial_linflexuart.o
> obj-$(CONFIG_ARC_SERIAL) += serial_arc.o
> obj-$(CONFIG_UNIPHIER_SERIAL) += serial_uniphier.o
> obj-$(CONFIG_STM32_SERIAL) += serial_stm32.o
> diff --git a/drivers/serial/serial_linflexuart.c b/drivers/serial/serial_linflexuart.c
> new file mode 100644
> index 0000000..3c619ce
> --- /dev/null
> +++ b/drivers/serial/serial_linflexuart.c
> @@ -0,0 +1,147 @@
> +/*
> + * (C) Copyright 2013-2016 Freescale Semiconductor, Inc.
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <watchdog.h>
> +#include <asm/io.h>
> +#include <serial.h>
> +#include <linux/compiler.h>
> +#include <asm/arch/imx-regs.h>
> +#include <asm/arch/clock.h>
> +
> +#define US1_TDRE (1 << 7)
> +#define US1_RDRF (1 << 5)
> +#define UC2_TE (1 << 3)
> +#define LINCR1_INIT (1 << 0)
> +#define LINCR1_MME (1 << 4)
> +#define LINCR1_BF (1 << 7)
> +#define LINSR_LINS_INITMODE (0x00001000)
> +#define LINSR_LINS_MASK (0x0000F000)
> +#define UARTCR_UART (1 << 0)
> +#define UARTCR_WL0 (1 << 1)
> +#define UARTCR_PCE (1 << 2)
> +#define UARTCR_PC0 (1 << 3)
> +#define UARTCR_TXEN (1 << 4)
> +#define UARTCR_RXEN (1 << 5)
> +#define UARTCR_PC1 (1 << 6)
> +#define UARTSR_DTF (1 << 1)
> +#define UARTSR_DRF (1 << 2)
> +#define UARTSR_RMB (1 << 9)
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +struct linflex_fsl *base = (struct linflex_fsl *)LINFLEXUART_BASE;
> +
> +static void linflex_serial_setbrg(void)
> +{
> + u32 clk = mxc_get_clock(MXC_UART_CLK);
> + u32 ibr, fbr;
> +
> + if (!gd->baudrate)
> + gd->baudrate = CONFIG_BAUDRATE;
> +
> + ibr = (u32) (clk / (16 * gd->baudrate));
> + fbr = (u32) (clk % (16 * gd->baudrate)) * 16;
> +
> + __raw_writel(ibr, &base->linibrr);
> + __raw_writel(fbr, &base->linfbrr);
> +}
> +
> +static int linflex_serial_getc(void)
> +{
> + char c;
> +
> + /* waiting for data reception complete - TODO: add a timeout */
> + while ((__raw_readb(&base->uartsr) & UARTSR_DRF) != UARTSR_DRF);
> +
> + /* waiting for data buffer to be ready - TODO: add a timeout */
> +
> + while ((__raw_readl(&base->uartsr) & UARTSR_RMB) != UARTSR_RMB);
> +
> + c = __raw_readl(&base->bdrm);
> + __raw_writeb((__raw_readb(&base->uartsr) | (UARTSR_DRF | UARTSR_RMB)),
> + &base->uartsr);
> + return c;
> +}
> +
> +static void linflex_serial_putc(const char c)
> +{
> + if (c == '\n')
> + serial_putc('\r');
Please remove this \n \r handling.
> +
> + __raw_writeb(c, &base->bdrl);
> +
> + /* waiting for data transmission completed - TODO: add a timeout */
> + while ((__raw_readb(&base->uartsr) & UARTSR_DTF) != UARTSR_DTF);
> +
> + __raw_writeb((__raw_readb(&base->uartsr) | UARTSR_DTF), &base->uartsr);
> +}
> +
> +/*
> + * Test whether a character is in the RX buffer
> + */
> +static int linflex_serial_tstc(void)
> +{
> + return 0;
> +}
> +
> +/*
> + * Initialise the serial port with the given baudrate. The settings
> + * are always 8 data bits, no parity, 1 stop bit, no start bits.
> + */
> +static int linflex_serial_init(void)
> +{
> + volatile u32 ctrl;
> +
> + /* set the Linflex in master mode amd activate by-pass filter */
> + ctrl = LINCR1_BF | LINCR1_MME;
> + __raw_writel(ctrl, &base->lincr1);
> +
> + /* init mode */
> + ctrl |= LINCR1_INIT;
> + __raw_writel(ctrl, &base->lincr1);
> +
> + /* waiting for init mode entry - TODO: add a timeout */
> + while ((__raw_readl(&base->linsr) & LINSR_LINS_MASK) !=
> + LINSR_LINS_INITMODE);
> +
> + /* set UART bit to allow writing other bits */
> + __raw_writel(UARTCR_UART, &base->uartcr);
> +
> + /* provide data bits, parity, stop bit, etc */
> + serial_setbrg();
> +
> + /* 8 bit data, no parity, Tx and Rx enabled, UART mode */
> + __raw_writel(UARTCR_PC1 | UARTCR_RXEN | UARTCR_TXEN | UARTCR_PC0
> + | UARTCR_WL0 | UARTCR_UART, &base->uartcr);
> +
> + ctrl = __raw_readl(&base->lincr1);
> + ctrl &= ~LINCR1_INIT;
> + __raw_writel(ctrl, &base->lincr1); /* end init mode */
> +
> + return 0;
> +}
> +
> +static struct serial_device linflex_serial_drv = {
> + .name = "linflex_serial",
> + .start = linflex_serial_init,
> + .stop = NULL,
> + .setbrg = linflex_serial_setbrg,
> + .putc = linflex_serial_putc,
> + .puts = default_serial_puts,
> + .getc = linflex_serial_getc,
> + .tstc = linflex_serial_tstc,
> +};
> +
> +void linflex_serial_initialize(void)
> +{
> + serial_register(&linflex_serial_drv);
> +}
> +
> +__weak struct serial_device *default_serial_console(void)
> +{
> + return &linflex_serial_drv;
> +}
> --
You should really start creating DM serial driver. Non-DM serial
driver is not going to be accepted.
Regards,
Bin
More information about the U-Boot
mailing list