[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