summaryrefslogtreecommitdiff
path: root/drivers/serial/serial_mvebu_a3700.c
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2016-09-27 11:40:56 -0400
committerTom Rini <trini@konsulko.com>2016-09-27 11:40:56 -0400
commit6d5565608f385b89f528ecf5680410cdc6cf63e9 (patch)
tree9403a25d40b8546e1e8a77fbe70da67c5ed4ade0 /drivers/serial/serial_mvebu_a3700.c
parente120c848bac77cfcc88183541c2e966e625a7840 (diff)
parentb28d29f784f5cc33c92e291d35eda603ea4e58e3 (diff)
downloadu-boot-imx-6d5565608f385b89f528ecf5680410cdc6cf63e9.zip
u-boot-imx-6d5565608f385b89f528ecf5680410cdc6cf63e9.tar.gz
u-boot-imx-6d5565608f385b89f528ecf5680410cdc6cf63e9.tar.bz2
Merge git://www.denx.de/git/u-boot-marvell
Diffstat (limited to 'drivers/serial/serial_mvebu_a3700.c')
-rw-r--r--drivers/serial/serial_mvebu_a3700.c175
1 files changed, 175 insertions, 0 deletions
diff --git a/drivers/serial/serial_mvebu_a3700.c b/drivers/serial/serial_mvebu_a3700.c
new file mode 100644
index 0000000..192e79a
--- /dev/null
+++ b/drivers/serial/serial_mvebu_a3700.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <serial.h>
+#include <asm/io.h>
+
+struct mvebu_platdata {
+ void __iomem *base;
+};
+
+/*
+ * Register offset
+ */
+#define UART_RX_REG 0x00
+#define UART_TX_REG 0x04
+#define UART_CTRL_REG 0x08
+#define UART_STATUS_REG 0x0c
+#define UART_BAUD_REG 0x10
+#define UART_POSSR_REG 0x14
+
+#define UART_STATUS_RX_RDY 0x10
+#define UART_STATUS_TXFIFO_FULL 0x800
+
+#define UART_CTRL_RXFIFO_RESET 0x4000
+#define UART_CTRL_TXFIFO_RESET 0x8000
+
+#define CONFIG_UART_BASE_CLOCK 25804800
+
+static int mvebu_serial_putc(struct udevice *dev, const char ch)
+{
+ struct mvebu_platdata *plat = dev_get_platdata(dev);
+ void __iomem *base = plat->base;
+
+ while (readl(base + UART_STATUS_REG) & UART_STATUS_TXFIFO_FULL)
+ ;
+
+ writel(ch, base + UART_TX_REG);
+
+ return 0;
+}
+
+static int mvebu_serial_getc(struct udevice *dev)
+{
+ struct mvebu_platdata *plat = dev_get_platdata(dev);
+ void __iomem *base = plat->base;
+
+ while (!(readl(base + UART_STATUS_REG) & UART_STATUS_RX_RDY))
+ ;
+
+ return readl(base + UART_RX_REG) & 0xff;
+}
+
+static int mvebu_serial_pending(struct udevice *dev, bool input)
+{
+ struct mvebu_platdata *plat = dev_get_platdata(dev);
+ void __iomem *base = plat->base;
+
+ if (readl(base + UART_STATUS_REG) & UART_STATUS_RX_RDY)
+ return 1;
+
+ return 0;
+}
+
+static int mvebu_serial_setbrg(struct udevice *dev, int baudrate)
+{
+ struct mvebu_platdata *plat = dev_get_platdata(dev);
+ void __iomem *base = plat->base;
+
+ /*
+ * Calculate divider
+ * baudrate = clock / 16 / divider
+ */
+ writel(CONFIG_UART_BASE_CLOCK / baudrate / 16, base + UART_BAUD_REG);
+
+ /*
+ * Set Programmable Oversampling Stack to 0,
+ * UART defaults to 16x scheme
+ */
+ writel(0, base + UART_POSSR_REG);
+
+ return 0;
+}
+
+static int mvebu_serial_probe(struct udevice *dev)
+{
+ struct mvebu_platdata *plat = dev_get_platdata(dev);
+ void __iomem *base = plat->base;
+
+ /* reset FIFOs */
+ writel(UART_CTRL_RXFIFO_RESET | UART_CTRL_TXFIFO_RESET,
+ base + UART_CTRL_REG);
+
+ /* No Parity, 1 Stop */
+ writel(0, base + UART_CTRL_REG);
+
+ return 0;
+}
+
+static int mvebu_serial_ofdata_to_platdata(struct udevice *dev)
+{
+ struct mvebu_platdata *plat = dev_get_platdata(dev);
+
+ plat->base = dev_get_addr_ptr(dev);
+
+ return 0;
+}
+
+static const struct dm_serial_ops mvebu_serial_ops = {
+ .putc = mvebu_serial_putc,
+ .pending = mvebu_serial_pending,
+ .getc = mvebu_serial_getc,
+ .setbrg = mvebu_serial_setbrg,
+};
+
+static const struct udevice_id mvebu_serial_ids[] = {
+ { .compatible = "marvell,armada-3700-uart" },
+ { }
+};
+
+U_BOOT_DRIVER(serial_mvebu) = {
+ .name = "serial_mvebu",
+ .id = UCLASS_SERIAL,
+ .of_match = mvebu_serial_ids,
+ .ofdata_to_platdata = mvebu_serial_ofdata_to_platdata,
+ .platdata_auto_alloc_size = sizeof(struct mvebu_platdata),
+ .probe = mvebu_serial_probe,
+ .ops = &mvebu_serial_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+};
+
+#ifdef CONFIG_DEBUG_MVEBU_A3700_UART
+
+#include <debug_uart.h>
+
+static inline void _debug_uart_init(void)
+{
+ void __iomem *base = (void __iomem *)CONFIG_DEBUG_UART_BASE;
+
+ /* reset FIFOs */
+ writel(UART_CTRL_RXFIFO_RESET | UART_CTRL_TXFIFO_RESET,
+ base + UART_CTRL_REG);
+
+ /* No Parity, 1 Stop */
+ writel(0, base + UART_CTRL_REG);
+
+ /*
+ * Calculate divider
+ * baudrate = clock / 16 / divider
+ */
+ writel(CONFIG_UART_BASE_CLOCK / 115200 / 16, base + UART_BAUD_REG);
+
+ /*
+ * Set Programmable Oversampling Stack to 0,
+ * UART defaults to 16x scheme
+ */
+ writel(0, base + UART_POSSR_REG);
+}
+
+static inline void _debug_uart_putc(int ch)
+{
+ void __iomem *base = (void __iomem *)CONFIG_DEBUG_UART_BASE;
+
+ while (readl(base + UART_STATUS_REG) & UART_STATUS_TXFIFO_FULL)
+ ;
+
+ writel(ch, base + UART_TX_REG);
+}
+
+DEBUG_UART_FUNCS
+#endif