From: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 4/8] serial: add serial driver for BCM6345
Date: Fri, 14 Apr 2017 20:19:31 +0200 [thread overview]
Message-ID: <3d280a84-a2cb-d026-2b31-e575e7750af8@gmail.com> (raw)
In-Reply-To: <1492098775-3518-5-git-send-email-noltari@gmail.com>
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 <noltari@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 <noltari@gmail.com>
> + *
> + * Derived from linux/drivers/tty/serial/bcm63xx_uart.c:
> + * Copyright (C) 2008 Maxime Bizon <mbizon@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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20170414/a3ad4e0d/attachment.sig>
next prev parent reply other threads:[~2017-04-14 18:19 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <1492098775-3518-1-git-send-email-noltari@gmail.com>
[not found] ` <1492098775-3518-2-git-send-email-noltari@gmail.com>
2017-04-14 17:43 ` [U-Boot] [PATCH 1/8] cmd: cpu: fix NULL cpu feature prints Daniel Schwierzeck
2017-04-15 17:16 ` Álvaro Fernández Rojas
[not found] ` <1492098775-3518-5-git-send-email-noltari@gmail.com>
2017-04-14 18:19 ` Daniel Schwierzeck [this message]
2017-04-15 17:17 ` [U-Boot] [PATCH 4/8] serial: add serial driver for BCM6345 Álvaro Fernández Rojas
[not found] ` <1492098775-3518-8-git-send-email-noltari@gmail.com>
2017-04-14 18:26 ` [U-Boot] [PATCH 7/8] mips: bmips: fix ioremap for BCM6358 Daniel Schwierzeck
2017-04-15 17:18 ` Álvaro Fernández Rojas
2017-04-15 18:08 ` Álvaro Fernández Rojas
2017-04-15 18:48 ` Daniel Schwierzeck
2017-04-15 19:15 ` Álvaro Fernández Rojas
[not found] ` <1492098775-3518-9-git-send-email-noltari@gmail.com>
2017-04-14 19:05 ` [U-Boot] [PATCH 8/8] mips: bmips: add support for raw .elf images Daniel Schwierzeck
2017-04-15 17:19 ` Álvaro Fernández Rojas
2017-04-15 18:10 ` Álvaro Fernández Rojas
2017-04-15 18:54 ` Daniel Schwierzeck
2017-04-15 19:14 ` Álvaro Fernández Rojas
2017-04-15 19:30 ` Álvaro Fernández Rojas
[not found] ` <1492098775-3518-6-git-send-email-noltari@gmail.com>
2017-04-14 19:23 ` [U-Boot] [PATCH 5/8] mips: add support for Broadcom MIPS Daniel Schwierzeck
2017-04-15 17:24 ` Álvaro Fernández Rojas
2017-04-13 15:44 [U-Boot] [PATCH 0/8] Add support for Broadcom MIPS SoCs Álvaro Fernández Rojas
2017-04-13 15:44 ` [U-Boot] [PATCH 4/8] serial: add serial driver for BCM6345 Álvaro Fernández Rojas
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3d280a84-a2cb-d026-2b31-e575e7750af8@gmail.com \
--to=daniel.schwierzeck@gmail.com \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.