Am 13.04.2017 um 17:52 schrieb Álvaro Fernández Rojas: > It is based on linux/drivers/tty/serial/bcm63xx_uart.c > > Signed-off-by: Álvaro Fernández Rojas <nolt...@gmail.com> > --- > drivers/serial/Kconfig | 14 ++ > drivers/serial/Makefile | 1 + > drivers/serial/serial_bcm6345.c | 341 > ++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 356 insertions(+) > create mode 100644 drivers/serial/serial_bcm6345.c > > diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig > index c0ec2ec..ca776d8 100644 > --- a/drivers/serial/Kconfig > +++ b/drivers/serial/Kconfig > @@ -134,6 +134,14 @@ config DEBUG_UART_ATMEL > will need to provide parameters to make this work. The driver will > be available until the real driver-model serial is running. > > +config DEBUG_UART_BCM6345 > + bool "BCM6345 UART" > + depends on BCM6345_SERIAL > + help > + Select this to enable a debug UART on BCM6345 SoCs. You > + will need to provide parameters to make this work. The driver will > + be available until the real driver model serial is running. > + > config DEBUG_UART_NS16550 > bool "ns16550" > help > @@ -339,6 +347,12 @@ config ATMEL_USART > configured in the device tree, and input clock frequency can > be got from the clk node. > > +config BCM6345_SERIAL > + bool "Support for BCM6345 UART" > + depends on DM_SERIAL > + help > + Select this to enable UART on BCM6345 SoCs. > + > config FSL_LPUART > bool "Freescale LPUART support" > help > diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile > index 4382cf9..dca31b2 100644 > --- a/drivers/serial/Makefile > +++ b/drivers/serial/Makefile > @@ -20,6 +20,7 @@ obj-$(CONFIG_ALTERA_JTAG_UART) += altera_jtag_uart.o > obj-$(CONFIG_AR933X_UART) += serial_ar933x.o > obj-$(CONFIG_ARM_DCC) += arm_dcc.o > obj-$(CONFIG_ATMEL_USART) += atmel_usart.o > +obj-$(CONFIG_BCM6345_SERIAL) += serial_bcm6345.o > obj-$(CONFIG_EFI_APP) += serial_efi.o > obj-$(CONFIG_LPC32XX_HSUART) += lpc32xx_hsuart.o > obj-$(CONFIG_MCFUART) += mcfuart.o > diff --git a/drivers/serial/serial_bcm6345.c b/drivers/serial/serial_bcm6345.c > new file mode 100644 > index 0000000..8754e76 > --- /dev/null > +++ b/drivers/serial/serial_bcm6345.c > @@ -0,0 +1,341 @@ > +/* > + * Copyright (C) 2017 Álvaro Fernández Rojas <nolt...@gmail.com> > + * > + * Derived from linux/drivers/tty/serial/bcm63xx_uart.c: > + * Copyright (C) 2008 Maxime Bizon <mbi...@freebox.fr> > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#include <serial.h> > +#include <errno.h> > +#include <clk.h> > +#include <debug_uart.h> > +#include <asm/io.h> > +#include <asm/types.h> > +#include <dm/device.h> > + > +/* UART Control Register */ > +#define UART_CTL_REG 0x0 > +#define UART_CTL_RXTMOUTCNT_SHIFT 0 > +#define UART_CTL_RXTMOUTCNT_MASK (0x1f << UART_CTL_RXTMOUTCNT_SHIFT) > +#define UART_CTL_RSTTXDN_SHIFT 5 > +#define UART_CTL_RSTTXDN_MASK (1 << UART_CTL_RSTTXDN_SHIFT) > +#define UART_CTL_RSTRXFIFO_SHIFT 6 > +#define UART_CTL_RSTRXFIFO_MASK (1 << UART_CTL_RSTRXFIFO_SHIFT) > +#define UART_CTL_RSTTXFIFO_SHIFT 7 > +#define UART_CTL_RSTTXFIFO_MASK (1 << UART_CTL_RSTTXFIFO_SHIFT) > +#define UART_CTL_STOPBITS_SHIFT 8 > +#define UART_CTL_STOPBITS_MASK (0xf << UART_CTL_STOPBITS_SHIFT) > +#define UART_CTL_STOPBITS_1 (0x7 << UART_CTL_STOPBITS_SHIFT) > +#define UART_CTL_STOPBITS_2 (0xf << UART_CTL_STOPBITS_SHIFT) > +#define UART_CTL_BITSPERSYM_SHIFT 12 > +#define UART_CTL_BITSPERSYM_MASK (0x3 << UART_CTL_BITSPERSYM_SHIFT) > +#define UART_CTL_XMITBRK_SHIFT 14 > +#define UART_CTL_XMITBRK_MASK (1 << UART_CTL_XMITBRK_SHIFT) > +#define UART_CTL_RSVD_SHIFT 15 > +#define UART_CTL_RSVD_MASK (1 << UART_CTL_RSVD_SHIFT) > +#define UART_CTL_RXPAREVEN_SHIFT 16 > +#define UART_CTL_RXPAREVEN_MASK (1 << UART_CTL_RXPAREVEN_SHIFT) > +#define UART_CTL_RXPAREN_SHIFT 17 > +#define UART_CTL_RXPAREN_MASK (1 << UART_CTL_RXPAREN_SHIFT) > +#define UART_CTL_TXPAREVEN_SHIFT 18 > +#define UART_CTL_TXPAREVEN_MASK (1 << UART_CTL_TXPAREVEN_SHIFT) > +#define UART_CTL_TXPAREN_SHIFT 18 > +#define UART_CTL_TXPAREN_MASK (1 << UART_CTL_TXPAREN_SHIFT) > +#define UART_CTL_LOOPBACK_SHIFT 20 > +#define UART_CTL_LOOPBACK_MASK (1 << UART_CTL_LOOPBACK_SHIFT) > +#define UART_CTL_RXEN_SHIFT 21 > +#define UART_CTL_RXEN_MASK (1 << UART_CTL_RXEN_SHIFT) > +#define UART_CTL_TXEN_SHIFT 22 > +#define UART_CTL_TXEN_MASK (1 << UART_CTL_TXEN_SHIFT) > +#define UART_CTL_BRGEN_SHIFT 23 > +#define UART_CTL_BRGEN_MASK (1 << UART_CTL_BRGEN_SHIFT) > + > +/* UART Baudword register */ > +#define UART_BAUD_REG 0x4 > + > +/* UART Misc Control register */ > +#define UART_MCTL_REG 0x8 > +#define UART_MCTL_DTR_SHIFT 0 > +#define UART_MCTL_DTR_MASK (1 << UART_MCTL_DTR_SHIFT) > +#define UART_MCTL_RTS_SHIFT 1 > +#define UART_MCTL_RTS_MASK (1 << UART_MCTL_RTS_SHIFT) > +#define UART_MCTL_RXFIFOTHRESH_SHIFT 8 > +#define UART_MCTL_RXFIFOTHRESH_MASK (0xf << UART_MCTL_RXFIFOTHRESH_SHIFT) > +#define UART_MCTL_TXFIFOTHRESH_SHIFT 12 > +#define UART_MCTL_TXFIFOTHRESH_MASK (0xf << UART_MCTL_TXFIFOTHRESH_SHIFT) > +#define UART_MCTL_RXFIFOFILL_SHIFT 16 > +#define UART_MCTL_RXFIFOFILL_MASK (0x1f << UART_MCTL_RXFIFOFILL_SHIFT) > +#define UART_MCTL_TXFIFOFILL_SHIFT 24 > +#define UART_MCTL_TXFIFOFILL_MASK (0x1f << UART_MCTL_TXFIFOFILL_SHIFT) > + > +/* UART External Input Configuration register */ > +#define UART_EXTINP_REG 0xc > +#define UART_EXTINP_RI_SHIFT 0 > +#define UART_EXTINP_RI_MASK (1 << UART_EXTINP_RI_SHIFT) > +#define UART_EXTINP_CTS_SHIFT 1 > +#define UART_EXTINP_CTS_MASK (1 << UART_EXTINP_CTS_SHIFT) > +#define UART_EXTINP_DCD_SHIFT 2 > +#define UART_EXTINP_DCD_MASK (1 << UART_EXTINP_DCD_SHIFT) > +#define UART_EXTINP_DSR_SHIFT 3 > +#define UART_EXTINP_DSR_MASK (1 << UART_EXTINP_DSR_SHIFT) > +#define UART_EXTINP_IRSTAT(x) (1 << (x + 4)) > +#define UART_EXTINP_IRMASK(x) (1 << (x + 8)) > +#define UART_EXTINP_IR_RI 0 > +#define UART_EXTINP_IR_CTS 1 > +#define UART_EXTINP_IR_DCD 2 > +#define UART_EXTINP_IR_DSR 3 > +#define UART_EXTINP_RI_NOSENSE_SHIFT 16 > +#define UART_EXTINP_RI_NOSENSE_MASK (1 << UART_EXTINP_RI_NOSENSE_SHIFT) > +#define UART_EXTINP_CTS_NOSENSE_SHIFT 17 > +#define UART_EXTINP_CTS_NOSENSE_MASK (1 << UART_EXTINP_CTS_NOSENSE_SHIFT) > +#define UART_EXTINP_DCD_NOSENSE_SHIFT 18 > +#define UART_EXTINP_DCD_NOSENSE_MASK (1 << UART_EXTINP_DCD_NOSENSE_SHIFT) > +#define UART_EXTINP_DSR_NOSENSE_SHIFT 19 > +#define UART_EXTINP_DSR_NOSENSE_MASK (1 << UART_EXTINP_DSR_NOSENSE_SHIFT) > + > +/* UART Interrupt register */ > +#define UART_IR_REG 0x10 > +#define UART_IR_MASK(x) (1 << (x + 16)) > +#define UART_IR_STAT(x) (1 << (x)) > +#define UART_IR_EXTIP 0 > +#define UART_IR_TXUNDER 1 > +#define UART_IR_TXOVER 2 > +#define UART_IR_TXTRESH 3 > +#define UART_IR_TXRDLATCH 4 > +#define UART_IR_TXEMPTY 5 > +#define UART_IR_RXUNDER 6 > +#define UART_IR_RXOVER 7 > +#define UART_IR_RXTIMEOUT 8 > +#define UART_IR_RXFULL 9 > +#define UART_IR_RXTHRESH 10 > +#define UART_IR_RXNOTEMPTY 11 > +#define UART_IR_RXFRAMEERR 12 > +#define UART_IR_RXPARERR 13 > +#define UART_IR_RXBRK 14 > +#define UART_IR_TXDONE 15 > + > +/* UART Fifo register */ > +#define UART_FIFO_REG 0x14 > +#define UART_FIFO_VALID_SHIFT 0 > +#define UART_FIFO_VALID_MASK 0xff > +#define UART_FIFO_FRAMEERR_SHIFT 8 > +#define UART_FIFO_FRAMEERR_MASK (1 << UART_FIFO_FRAMEERR_SHIFT) > +#define UART_FIFO_PARERR_SHIFT 9 > +#define UART_FIFO_PARERR_MASK (1 << UART_FIFO_PARERR_SHIFT) > +#define UART_FIFO_BRKDET_SHIFT 10 > +#define UART_FIFO_BRKDET_MASK (1 << UART_FIFO_BRKDET_SHIFT) > +#define UART_FIFO_ANYERR_MASK (UART_FIFO_FRAMEERR_MASK | > \ > + UART_FIFO_PARERR_MASK | \ > + UART_FIFO_BRKDET_MASK) > +
you should remove all defines you don't need in your driver code > +struct bcm6345_serial_priv { > + void __iomem *base; > + ulong uartclk; > +}; > + > +/* > + * enable rx & tx operation on uart > + */ > +static void bcm6345_serial_enable(void __iomem *base) > +{ > + u32 val; > + > + val = __raw_readl(base + UART_CTL_REG); > + val |= (UART_CTL_BRGEN_MASK | UART_CTL_TXEN_MASK | UART_CTL_RXEN_MASK); > + __raw_writel(val, base + UART_CTL_REG); in general you should try to use readl/writel as well as setbits_32/clrbits_32/clrsetbit_32. But because you have CONFIG_SWAP_IO_SPACE enabled in all your defconfigs, you have to switch to readl_be32/writel_be32 and setbits_be32/clrbits_be32/clrsetbits_be32 > +} > + > +/* > + * disable rx & tx operation on uart > + */ > +static void bcm6345_serial_disable(void __iomem *base) > +{ > + u32 val; > + > + val = __raw_readl(base + UART_CTL_REG); > + val &= ~(UART_CTL_BRGEN_MASK | UART_CTL_TXEN_MASK | > + UART_CTL_RXEN_MASK); > + __raw_writel(val, base + UART_CTL_REG); > +} > + > +/* > + * clear all unread data in rx fifo and unsent data in tx fifo > + */ > +static void bcm6345_serial_flush(void __iomem *base) > +{ > + u32 val; > + > + /* empty rx and tx fifo */ > + val = __raw_readl(base + UART_CTL_REG); > + val |= UART_CTL_RSTRXFIFO_MASK | UART_CTL_RSTTXFIFO_MASK; > + __raw_writel(val, base + UART_CTL_REG); > + > + /* read any pending char to make sure all irq status are > + * cleared */ incorrect multi-line comment > + __raw_readl(base + UART_FIFO_REG); > +} > + > +static int bcm6345_serial_init(void __iomem *base, ulong clk, u32 baudrate) > +{ > + u32 val; > + > + /* mask all irq and flush port */ > + bcm6345_serial_disable(base); > + bcm6345_serial_flush(base); > + > + /* set bits per sym and stop bits */ > + val = __raw_readl(base + UART_CTL_REG); > + val &= ~UART_CTL_BITSPERSYM_MASK; > + val |= (3 << UART_CTL_BITSPERSYM_SHIFT); > + val |= UART_CTL_STOPBITS_1; > + __raw_writel(val, base + UART_CTL_REG); > + > + /* set baud rate */ > + val = (clk / baudrate) / 16; > + if (val & 0x1) > + val = val; > + else > + val = val / 2 - 1; > + __raw_writel(val, base + UART_BAUD_REG); > + > + /* clear interrupts */ > + __raw_writel(0, base + UART_IR_REG); > + > + /* enable uart */ > + bcm6345_serial_enable(base); > + > + return 0; > +} > + > +static int bcm6345_serial_pending(struct udevice *dev, bool input) > +{ > + struct bcm6345_serial_priv *priv = dev_get_priv(dev); > + u32 val = __raw_readl(priv->base + UART_IR_REG); > + > + if (input) > + return (val & UART_IR_STAT(UART_IR_RXNOTEMPTY)) ? 1 : 0; > + else > + return (val & UART_IR_STAT(UART_IR_TXEMPTY)) ? 0 : 1; > +} > + > +static int bcm6345_serial_setbrg(struct udevice *dev, int baudrate) > +{ > + struct bcm6345_serial_priv *priv = dev_get_priv(dev); > + > + return bcm6345_serial_init(priv->base, priv->uartclk, baudrate); > +} > + > +static int bcm6345_serial_putc(struct udevice *dev, const char ch) > +{ > + struct bcm6345_serial_priv *priv = dev_get_priv(dev); > + u32 val; > + > + val = __raw_readl(priv->base + UART_IR_REG); > + if (!(val & UART_IR_STAT(UART_IR_TXEMPTY))) > + return -EAGAIN; > + > + __raw_writel(ch, priv->base + UART_FIFO_REG); > + > + return 0; > +} > + > +static int bcm6345_serial_getc(struct udevice *dev) > +{ > + struct bcm6345_serial_priv *priv = dev_get_priv(dev); > + u32 val; > + > + val = __raw_readl(priv->base + UART_IR_REG); > + if (val & UART_IR_STAT(UART_IR_RXOVER)) { > + /* fifo reset is required to clear interrupt */ > + val = __raw_readl(priv->base + UART_CTL_REG); > + val |= UART_CTL_RSTRXFIFO_MASK; > + __raw_writel(val, priv->base + UART_CTL_REG); > + } > + if (!(val & UART_IR_STAT(UART_IR_RXNOTEMPTY))) > + return -EAGAIN; > + > + val = __raw_readl(priv->base + UART_FIFO_REG); > + if (val & UART_FIFO_ANYERR_MASK) > + return -EAGAIN; > + > + return (val & UART_FIFO_VALID_MASK); > +} > + > +static int bcm6345_serial_probe(struct udevice *dev) > +{ > + struct bcm6345_serial_priv *priv = dev_get_priv(dev); > + struct clk clk; > + fdt_addr_t addr; > + fdt_size_t size; > + int ret; > + > + /* get address */ > + addr = dev_get_addr_size_index(dev, 0, &size); > + if (addr == FDT_ADDR_T_NONE) > + return -EINVAL; > + > + priv->base = ioremap(addr, size); > + > + /* get clock rate */ > + ret = clk_get_by_index(dev, 0, &clk); > + if (ret < 0) > + return ret; > + priv->uartclk = clk_get_rate(&clk) / 2; > + clk_free(&clk); > + > + /* initialize serial */ > + return bcm6345_serial_init(priv->base, priv->uartclk, CONFIG_BAUDRATE); > +} > + > +static const struct dm_serial_ops bcm6345_serial_ops = { > + .putc = bcm6345_serial_putc, > + .pending = bcm6345_serial_pending, > + .getc = bcm6345_serial_getc, > + .setbrg = bcm6345_serial_setbrg, > +}; > + > +static const struct udevice_id bcm6345_serial_of_match[] = { > + { .compatible = "brcm,bcm6345-uart" }, > + { /* sentinel */ } > +}; > + > +U_BOOT_DRIVER(bcm6345_serial) = { > + .name = "bcm6345-uart", > + .id = UCLASS_SERIAL, > + .of_match = bcm6345_serial_of_match, > + .probe = bcm6345_serial_probe, > + .priv_auto_alloc_size = sizeof(struct bcm6345_serial_priv), > + .ops = &bcm6345_serial_ops, > + .flags = DM_FLAG_PRE_RELOC, > +}; > + > +#ifdef CONFIG_DEBUG_UART_BCM6345 > +static inline void _debug_uart_init(void) > +{ > + void __iomem *base = (void __iomem *)CONFIG_DEBUG_UART_BASE; > + > + bcm6345_serial_init(base, CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE); > +} > + > +static inline void wait_xfered(void __iomem *base) > +{ > + do { > + u32 val = __raw_readl(base + UART_IR_REG); > + if (val & UART_IR_STAT(UART_IR_TXEMPTY)) > + break; > + } while (1); > +} > + > +static inline void _debug_uart_putc(int ch) > +{ > + void __iomem *base = (void __iomem *)CONFIG_DEBUG_UART_BASE; > + > + wait_xfered(base); > + __raw_writel(ch, base + UART_FIFO_REG); > + wait_xfered(base); > +} > + > +DEBUG_UART_FUNCS > +#endif > -- - Daniel
signature.asc
Description: OpenPGP digital signature
_______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot