On 27/12/2016 11:04, Peng Fan wrote: > Drop CONFIG_LPUART_32B_REG. > Move the register structure to a common file include/fsl_lpuart.h > Define lpuart_serial_platdata structure which includes the reg base and flags. > For 32Bit register access, use lpuart_read32/lpuart_write32 which handles > big/little endian. > For 8Bit register access, still use the orignal code. > > Signed-off-by: Peng Fan <peng....@nxp.com> > Cc: Stefano Babic <sba...@denx.de> > Cc: Bhuvanchandra DV <bhuvanchandra...@toradex.com> > Cc: York Sun <york....@nxp.com> > Cc: Shaohui Xie <shaohui....@nxp.com> > Cc: Alison Wang <b18...@freescale.com> > --- > > V2: > New. I do not have vf610 and LSx board, please help test if you have the > board. > > arch/arm/cpu/armv7/vf610/generic.c | 5 + > .../arm/include/asm/arch-fsl-layerscape/imx-regs.h | 42 ---- > arch/arm/include/asm/arch-ls102xa/imx-regs.h | 40 --- > arch/arm/include/asm/arch-vf610/clock.h | 1 + > arch/arm/include/asm/arch-vf610/imx-regs.h | 28 --- > drivers/serial/serial_lpuart.c | 267 > +++++++++++---------- > 6 files changed, 148 insertions(+), 235 deletions(-) > > diff --git a/arch/arm/cpu/armv7/vf610/generic.c > b/arch/arm/cpu/armv7/vf610/generic.c > index 50eb0c6..0328096 100644 > --- a/arch/arm/cpu/armv7/vf610/generic.c > +++ b/arch/arm/cpu/armv7/vf610/generic.c > @@ -204,6 +204,11 @@ static u32 get_dspi_clk(void) > return get_ipg_clk(); > } > > +u32 get_lpuart_clk(void) > +{ > + return get_uart_clk(); > +} > + > unsigned int mxc_get_clock(enum mxc_clock clk) > { > switch (clk) { > diff --git a/arch/arm/include/asm/arch-fsl-layerscape/imx-regs.h > b/arch/arm/include/asm/arch-fsl-layerscape/imx-regs.h > index 57e417b..b0e58ca 100644 > --- a/arch/arm/include/asm/arch-fsl-layerscape/imx-regs.h > +++ b/arch/arm/include/asm/arch-fsl-layerscape/imx-regs.h > @@ -10,46 +10,4 @@ > > #define I2C_QUIRK_REG /* enable 8-bit driver */ > > -#ifdef CONFIG_FSL_LPUART > -#ifdef CONFIG_LPUART_32B_REG > -struct lpuart_fsl { > - u32 baud; > - u32 stat; > - u32 ctrl; > - u32 data; > - u32 match; > - u32 modir; > - u32 fifo; > - u32 water; > -}; > -#else > -struct lpuart_fsl { > - u8 ubdh; > - u8 ubdl; > - u8 uc1; > - u8 uc2; > - u8 us1; > - u8 us2; > - u8 uc3; > - u8 ud; > - u8 uma1; > - u8 uma2; > - u8 uc4; > - u8 uc5; > - u8 ued; > - u8 umodem; > - u8 uir; > - u8 reserved; > - u8 upfifo; > - u8 ucfifo; > - u8 usfifo; > - u8 utwfifo; > - u8 utcfifo; > - u8 urwfifo; > - u8 urcfifo; > - u8 rsvd[28]; > -}; > -#endif > -#endif /* CONFIG_FSL_LPUART */ > - > #endif /* __ASM_ARCH_FSL_LAYERSCAPE_IMX_REGS_H__ */ > diff --git a/arch/arm/include/asm/arch-ls102xa/imx-regs.h > b/arch/arm/include/asm/arch-ls102xa/imx-regs.h > index f9cd75b..7190f3d 100644 > --- a/arch/arm/include/asm/arch-ls102xa/imx-regs.h > +++ b/arch/arm/include/asm/arch-ls102xa/imx-regs.h > @@ -10,44 +10,4 @@ > > #define I2C_QUIRK_REG /* enable 8-bit driver */ > > -#ifdef CONFIG_LPUART_32B_REG > -struct lpuart_fsl { > - u32 baud; > - u32 stat; > - u32 ctrl; > - u32 data; > - u32 match; > - u32 modir; > - u32 fifo; > - u32 water; > -}; > -#else > -struct lpuart_fsl { > - u8 ubdh; > - u8 ubdl; > - u8 uc1; > - u8 uc2; > - u8 us1; > - u8 us2; > - u8 uc3; > - u8 ud; > - u8 uma1; > - u8 uma2; > - u8 uc4; > - u8 uc5; > - u8 ued; > - u8 umodem; > - u8 uir; > - u8 reserved; > - u8 upfifo; > - u8 ucfifo; > - u8 usfifo; > - u8 utwfifo; > - u8 utcfifo; > - u8 urwfifo; > - u8 urcfifo; > - u8 rsvd[28]; > -}; > -#endif > - > #endif /* __ASM_ARCH_IMX_REGS_H__ */ > diff --git a/arch/arm/include/asm/arch-vf610/clock.h > b/arch/arm/include/asm/arch-vf610/clock.h > index e5a5c6d..c5ba240 100644 > --- a/arch/arm/include/asm/arch-vf610/clock.h > +++ b/arch/arm/include/asm/arch-vf610/clock.h > @@ -22,6 +22,7 @@ enum mxc_clock { > > void enable_ocotp_clk(unsigned char enable); > unsigned int mxc_get_clock(enum mxc_clock clk); > +u32 get_lpuart_clk(void); > > #define imx_get_fecclk() mxc_get_clock(MXC_FEC_CLK) > > diff --git a/arch/arm/include/asm/arch-vf610/imx-regs.h > b/arch/arm/include/asm/arch-vf610/imx-regs.h > index 9758323..cac68ef 100644 > --- a/arch/arm/include/asm/arch-vf610/imx-regs.h > +++ b/arch/arm/include/asm/arch-vf610/imx-regs.h > @@ -429,34 +429,6 @@ struct fuse_bank4_regs { > u32 rsvd7[3]; > }; > > -/* UART */ > -struct lpuart_fsl { > - u8 ubdh; > - u8 ubdl; > - u8 uc1; > - u8 uc2; > - u8 us1; > - u8 us2; > - u8 uc3; > - u8 ud; > - u8 uma1; > - u8 uma2; > - u8 uc4; > - u8 uc5; > - u8 ued; > - u8 umodem; > - u8 uir; > - u8 reserved; > - u8 upfifo; > - u8 ucfifo; > - u8 usfifo; > - u8 utwfifo; > - u8 utcfifo; > - u8 urwfifo; > - u8 urcfifo; > - u8 rsvd[28]; > -}; > - > /* MSCM Interrupt Router */ > struct mscm_ir { > u32 ircp0ir; > diff --git a/drivers/serial/serial_lpuart.c b/drivers/serial/serial_lpuart.c > index beb4243..3f030a6 100644 > --- a/drivers/serial/serial_lpuart.c > +++ b/drivers/serial/serial_lpuart.c > @@ -6,6 +6,7 @@ > > #include <common.h> > #include <dm.h> > +#include <fsl_lpuart.h> > #include <watchdog.h> > #include <asm/io.h> > #include <serial.h> > @@ -48,14 +49,56 @@ > > DECLARE_GLOBAL_DATA_PTR; > > +#define LPUART_FLAG_REGMAP_32BIT_REG BIT(0) > +#define LPUART_FLAG_REGMAP_ENDIAN_BIG BIT(1) > + > struct lpuart_serial_platdata { > - struct lpuart_fsl *reg; > + void *reg; > + ulong flags; > }; > > -#ifndef CONFIG_LPUART_32B_REG > -static void _lpuart_serial_setbrg(struct lpuart_fsl *base, int baudrate) > +static void lpuart_read32(u32 flags, u32 *addr, u32 *val) > +{ > + if (flags & LPUART_FLAG_REGMAP_32BIT_REG) { > + if (flags & LPUART_FLAG_REGMAP_ENDIAN_BIG) > + *(u32 *)val = in_be32(addr); > + else > + *(u32 *)val = in_le32(addr); > + } > +} > + > +static void lpuart_write32(u32 flags, u32 *addr, u32 val) > +{ > + if (flags & LPUART_FLAG_REGMAP_32BIT_REG) { > + if (flags & LPUART_FLAG_REGMAP_ENDIAN_BIG) > + out_be32(addr, val); > + else > + out_le32(addr, val); > + } > +} > + > + > +#ifndef CONFIG_SYS_CLK_FREQ > +#define CONFIG_SYS_CLK_FREQ 0 > +#endif > + > +u32 __weak get_lpuart_clk(void) > { > - u32 clk = mxc_get_clock(MXC_UART_CLK); > + return CONFIG_SYS_CLK_FREQ; > +} > + > +static bool is_lpuart32(struct udevice *dev) > +{ > + struct lpuart_serial_platdata *plat = dev->platdata; > + > + return plat->flags & LPUART_FLAG_REGMAP_32BIT_REG; > +} > + > +static void _lpuart_serial_setbrg(struct lpuart_serial_platdata *plat, > + int baudrate) > +{ > + struct lpuart_fsl *base = plat->reg; > + u32 clk = get_lpuart_clk(); > u16 sbr; > > sbr = (u16)(clk / (16 * baudrate)); > @@ -65,8 +108,9 @@ static void _lpuart_serial_setbrg(struct lpuart_fsl *base, > int baudrate) > __raw_writeb(sbr & 0xff, &base->ubdl); > } > > -static int _lpuart_serial_getc(struct lpuart_fsl *base) > +static int _lpuart_serial_getc(struct lpuart_serial_platdata *plat) > { > + struct lpuart_fsl *base = plat->reg; > while (!(__raw_readb(&base->us1) & (US1_RDRF | US1_OR))) > WATCHDOG_RESET(); > > @@ -75,8 +119,11 @@ static int _lpuart_serial_getc(struct lpuart_fsl *base) > return __raw_readb(&base->ud); > } > > -static void _lpuart_serial_putc(struct lpuart_fsl *base, const char c) > +static void _lpuart_serial_putc(struct lpuart_serial_platdata *plat, > + const char c) > { > + struct lpuart_fsl *base = plat->reg; > + > while (!(__raw_readb(&base->us1) & US1_TDRE)) > WATCHDOG_RESET(); > > @@ -84,8 +131,10 @@ static void _lpuart_serial_putc(struct lpuart_fsl *base, > const char c) > } > > /* Test whether a character is in the RX buffer */ > -static int _lpuart_serial_tstc(struct lpuart_fsl *base) > +static int _lpuart_serial_tstc(struct lpuart_serial_platdata *plat) > { > + struct lpuart_fsl *base = plat->reg; > + > if (__raw_readb(&base->urcfifo) == 0) > return 0; > > @@ -96,8 +145,9 @@ static int _lpuart_serial_tstc(struct lpuart_fsl *base) > * 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 _lpuart_serial_init(struct lpuart_fsl *base) > +static int _lpuart_serial_init(struct lpuart_serial_platdata *plat) > { > + struct lpuart_fsl *base = (struct lpuart_fsl *)plat->reg; > u8 ctrl; > > ctrl = __raw_readb(&base->uc2); > @@ -115,101 +165,71 @@ static int _lpuart_serial_init(struct lpuart_fsl *base) > __raw_writeb(CFIFO_TXFLUSH | CFIFO_RXFLUSH, &base->ucfifo); > > /* provide data bits, parity, stop bit, etc */ > - _lpuart_serial_setbrg(base, gd->baudrate); > + _lpuart_serial_setbrg(plat, gd->baudrate); > > __raw_writeb(UC2_RE | UC2_TE, &base->uc2); > > return 0; > } > > -static int lpuart_serial_setbrg(struct udevice *dev, int baudrate) > -{ > - struct lpuart_serial_platdata *plat = dev->platdata; > - struct lpuart_fsl *reg = plat->reg; > - > - _lpuart_serial_setbrg(reg, baudrate); > - > - return 0; > -} > - > -static int lpuart_serial_getc(struct udevice *dev) > -{ > - struct lpuart_serial_platdata *plat = dev->platdata; > - struct lpuart_fsl *reg = plat->reg; > - > - return _lpuart_serial_getc(reg); > -} > - > -static int lpuart_serial_putc(struct udevice *dev, const char c) > -{ > - struct lpuart_serial_platdata *plat = dev->platdata; > - struct lpuart_fsl *reg = plat->reg; > - > - _lpuart_serial_putc(reg, c); > - > - return 0; > -} > - > -static int lpuart_serial_pending(struct udevice *dev, bool input) > -{ > - struct lpuart_serial_platdata *plat = dev->platdata; > - struct lpuart_fsl *reg = plat->reg; > - > - if (input) > - return _lpuart_serial_tstc(reg); > - else > - return __raw_readb(®->us1) & US1_TDRE ? 0 : 1; > -} > - > -static int lpuart_serial_probe(struct udevice *dev) > -{ > - struct lpuart_serial_platdata *plat = dev->platdata; > - struct lpuart_fsl *reg = plat->reg; > - > - return _lpuart_serial_init(reg); > -} > -#else > - > -u32 __weak get_lpuart_clk(void) > -{ > - return CONFIG_SYS_CLK_FREQ; > -} > - > -static void _lpuart32_serial_setbrg(struct lpuart_fsl *base, int baudrate) > +static void _lpuart32_serial_setbrg(struct lpuart_serial_platdata *plat, > + int baudrate) > { > + struct lpuart_fsl_reg32 *base = plat->reg; > u32 clk = get_lpuart_clk(); > u32 sbr; > > sbr = (clk / (16 * baudrate)); > > /* place adjustment later - n/32 BRFA */ > - out_be32(&base->baud, sbr); > + lpuart_write32(plat->flags, &base->baud, sbr); > } > > -static int _lpuart32_serial_getc(struct lpuart_fsl *base) > +static int _lpuart32_serial_getc(struct lpuart_serial_platdata *plat) > { > + struct lpuart_fsl_reg32 *base = plat->reg; > u32 stat; > > - while (((stat = in_be32(&base->stat)) & STAT_RDRF) == 0) { > - out_be32(&base->stat, STAT_FLAGS); > + lpuart_read32(plat->flags, &base->stat, &stat); > + while ((stat & STAT_RDRF) == 0) { > + lpuart_write32(plat->flags, &base->stat, STAT_FLAGS); > WATCHDOG_RESET(); > + lpuart_read32(plat->flags, &base->stat, &stat); > } > > - return in_be32(&base->data) & 0x3ff; > + /* Reuse stat */ > + lpuart_read32(plat->flags, &base->data, &stat); > + > + return stat & 0x3ff; > } > > -static void _lpuart32_serial_putc(struct lpuart_fsl *base, const char c) > +static void _lpuart32_serial_putc(struct lpuart_serial_platdata *plat, > + const char c) > { > - while (!(in_be32(&base->stat) & STAT_TDRE)) > + struct lpuart_fsl_reg32 *base = plat->reg; > + u32 stat; > + > + while (true) { > + lpuart_read32(plat->flags, &base->stat, &stat); > + > + if ((stat & STAT_TDRE)) > + break; > + > WATCHDOG_RESET(); > + } > > - out_be32(&base->data, c); > + lpuart_write32(plat->flags, &base->data, c); > } > > /* Test whether a character is in the RX buffer */ > -static int _lpuart32_serial_tstc(struct lpuart_fsl *base) > +static int _lpuart32_serial_tstc(struct lpuart_serial_platdata *plat) > { > - if ((in_be32(&base->water) >> 24) == 0) > + struct lpuart_fsl_reg32 *base = plat->reg; > + u32 water; > + > + lpuart_read32(plat->flags, &base->water, &water); > + > + if ((water >> 24) == 0) > return 0; > > return 1; > @@ -219,75 +239,94 @@ static int _lpuart32_serial_tstc(struct lpuart_fsl > *base) > * 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 _lpuart32_serial_init(struct lpuart_fsl *base) > +static int _lpuart32_serial_init(struct lpuart_serial_platdata *plat) > { > - u8 ctrl; > + struct lpuart_fsl_reg32 *base = (struct lpuart_fsl_reg32 *)plat->reg; > + u32 ctrl; > > - ctrl = in_be32(&base->ctrl); > + lpuart_read32(plat->flags, &base->ctrl, &ctrl); > ctrl &= ~CTRL_RE; > ctrl &= ~CTRL_TE; > - out_be32(&base->ctrl, ctrl); > + lpuart_write32(plat->flags, &base->ctrl, ctrl); > > - out_be32(&base->modir, 0); > - out_be32(&base->fifo, ~(FIFO_TXFE | FIFO_RXFE)); > + lpuart_write32(plat->flags, &base->modir, 0); > + lpuart_write32(plat->flags, &base->fifo, ~(FIFO_TXFE | FIFO_RXFE)); > > - out_be32(&base->match, 0); > + lpuart_write32(plat->flags, &base->match, 0); > > /* provide data bits, parity, stop bit, etc */ > - _lpuart32_serial_setbrg(base, gd->baudrate); > + _lpuart32_serial_setbrg(plat, gd->baudrate); > > - out_be32(&base->ctrl, CTRL_RE | CTRL_TE); > + lpuart_write32(plat->flags, &base->ctrl, CTRL_RE | CTRL_TE); > > return 0; > } > > -static int lpuart32_serial_setbrg(struct udevice *dev, int baudrate) > +static int lpuart_serial_setbrg(struct udevice *dev, int baudrate) > { > struct lpuart_serial_platdata *plat = dev->platdata; > - struct lpuart_fsl *reg = plat->reg; > > - _lpuart32_serial_setbrg(reg, baudrate); > + if (is_lpuart32(dev)) > + _lpuart32_serial_setbrg(plat, baudrate); > + else > + _lpuart_serial_setbrg(plat, baudrate); > > return 0; > } > > -static int lpuart32_serial_getc(struct udevice *dev) > +static int lpuart_serial_getc(struct udevice *dev) > { > struct lpuart_serial_platdata *plat = dev->platdata; > - struct lpuart_fsl *reg = plat->reg; > > - return _lpuart32_serial_getc(reg); > + if (is_lpuart32(dev)) > + return _lpuart32_serial_getc(plat); > + > + return _lpuart_serial_getc(plat); > } > > -static int lpuart32_serial_putc(struct udevice *dev, const char c) > +static int lpuart_serial_putc(struct udevice *dev, const char c) > { > struct lpuart_serial_platdata *plat = dev->platdata; > - struct lpuart_fsl *reg = plat->reg; > > - _lpuart32_serial_putc(reg, c); > + if (is_lpuart32(dev)) > + _lpuart32_serial_putc(plat, c); > + else > + _lpuart_serial_putc(plat, c); > > return 0; > } > > -static int lpuart32_serial_pending(struct udevice *dev, bool input) > +static int lpuart_serial_pending(struct udevice *dev, bool input) > { > struct lpuart_serial_platdata *plat = dev->platdata; > struct lpuart_fsl *reg = plat->reg; > + struct lpuart_fsl_reg32 *reg32 = plat->reg; > + u32 stat; > + > + if (is_lpuart32(dev)) { > + if (input) { > + return _lpuart32_serial_tstc(plat); > + } else { > + lpuart_read32(plat->flags, ®32->stat, &stat); > + return stat & STAT_TDRE ? 0 : 1; > + } > + } > > if (input) > - return _lpuart32_serial_tstc(reg); > + return _lpuart_serial_tstc(plat); > else > - return in_be32(®->stat) & STAT_TDRE ? 0 : 1; > + return __raw_readb(®->us1) & US1_TDRE ? 0 : 1; > } > > -static int lpuart32_serial_probe(struct udevice *dev) > +static int lpuart_serial_probe(struct udevice *dev) > { > struct lpuart_serial_platdata *plat = dev->platdata; > - struct lpuart_fsl *reg = plat->reg; > > - return _lpuart32_serial_init(reg); > + if (is_lpuart32(dev)) > + return _lpuart32_serial_init(plat); > + else > + return _lpuart_serial_init(plat); > } > -#endif /* CONFIG_LPUART_32B_REG */ > > static int lpuart_serial_ofdata_to_platdata(struct udevice *dev) > { > @@ -298,12 +337,12 @@ static int lpuart_serial_ofdata_to_platdata(struct > udevice *dev) > if (addr == FDT_ADDR_T_NONE) > return -EINVAL; > > - plat->reg = (struct lpuart_fsl *)addr; > + plat->reg = (void *)addr; > + plat->flags = dev_get_driver_data(dev); > > return 0; > } > > -#ifndef CONFIG_LPUART_32B_REG > static const struct dm_serial_ops lpuart_serial_ops = { > .putc = lpuart_serial_putc, > .pending = lpuart_serial_pending, > @@ -312,7 +351,9 @@ static const struct dm_serial_ops lpuart_serial_ops = { > }; > > static const struct udevice_id lpuart_serial_ids[] = { > - { .compatible = "fsl,vf610-lpuart" }, > + { .compatible = "fsl,ls1021a-lpuart", .data = > + LPUART_FLAG_REGMAP_32BIT_REG | LPUART_FLAG_REGMAP_ENDIAN_BIG }, > + { .compatible = "fsl,vf610-lpuart"}, > { } > }; > > @@ -326,27 +367,3 @@ U_BOOT_DRIVER(serial_lpuart) = { > .ops = &lpuart_serial_ops, > .flags = DM_FLAG_PRE_RELOC, > }; > -#else /* CONFIG_LPUART_32B_REG */ > -static const struct dm_serial_ops lpuart32_serial_ops = { > - .putc = lpuart32_serial_putc, > - .pending = lpuart32_serial_pending, > - .getc = lpuart32_serial_getc, > - .setbrg = lpuart32_serial_setbrg, > -}; > - > -static const struct udevice_id lpuart32_serial_ids[] = { > - { .compatible = "fsl,ls1021a-lpuart" }, > - { } > -}; > - > -U_BOOT_DRIVER(serial_lpuart32) = { > - .name = "serial_lpuart32", > - .id = UCLASS_SERIAL, > - .of_match = lpuart32_serial_ids, > - .ofdata_to_platdata = lpuart_serial_ofdata_to_platdata, > - .platdata_auto_alloc_size = sizeof(struct lpuart_serial_platdata), > - .probe = lpuart32_serial_probe, > - .ops = &lpuart32_serial_ops, > - .flags = DM_FLAG_PRE_RELOC, > -}; > -#endif /* CONFIG_LPUART_32B_REG */ >
Reviewed-by : Stefano Babic <sba...@denx.de> Best regards, Stefano Babic -- ===================================================================== DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sba...@denx.de ===================================================================== _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot