serial: Add serial_mvebu_a3700 for Armada 3700 SoC

The Armada 3700's UART is a simple serial port. It has a 32 bytes
Tx FIFO and a 64 bytes Rx FIFO integrated. This patch adds support
for this UART including the DEBUG UART functions for very early
debug output.

Signed-off-by: Stefan Roese <sr@denx.de>
Cc: Nadav Haklai <nadavh@marvell.com>
Cc: Kostya Porotchkin <kostap@marvell.com>
Cc: Wilson Ding <dingwei@marvell.com>
Cc: Victor Gu <xigu@marvell.com>
Cc: Hua Jing <jinghua@marvell.com>
Cc: Terry Zhou <bjzhou@marvell.com>
Cc: Hanna Hawa <hannah@marvell.com>
Cc: Haim Boot <hayim@marvell.com>
This commit is contained in:
Stefan Roese 2016-05-17 16:36:00 +02:00
parent 35e3fca7e3
commit 6985d49662
3 changed files with 191 additions and 0 deletions

View file

@ -147,6 +147,13 @@ config DEBUG_UART_ARM_DCC
This port is available at least on ARMv6, ARMv7, ARMv8 and XScale This port is available at least on ARMv6, ARMv7, ARMv8 and XScale
architectures. architectures.
config DEBUG_MVEBU_A3700_UART
bool "Marvell Armada 3700"
help
Select this to enable a debug UART using the serial_mvebu driver. 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_ZYNQ config DEBUG_UART_ZYNQ
bool "Xilinx Zynq" bool "Xilinx Zynq"
help help
@ -295,6 +302,13 @@ config FSL_LPUART
Select this to enable a Low Power UART for Freescale VF610 and Select this to enable a Low Power UART for Freescale VF610 and
QorIQ Layerscape devices. QorIQ Layerscape devices.
config MVEBU_A3700_UART
bool "UART support for Armada 3700"
default n
help
Choose this option to add support for UART driver on the Marvell
Armada 3700 SoC. The base address is configured via DT.
config PIC32_SERIAL config PIC32_SERIAL
bool "Support for Microchip PIC32 on-chip UART" bool "Support for Microchip PIC32 on-chip UART"
depends on DM_SERIAL && MACH_PIC32 depends on DM_SERIAL && MACH_PIC32
@ -371,4 +385,5 @@ config MSM_SERIAL
It should support all Qualcomm devices with UARTDM version 1.4, It should support all Qualcomm devices with UARTDM version 1.4,
for example APQ8016 and MSM8916. for example APQ8016 and MSM8916.
Single baudrate is supported in current implementation (115200). Single baudrate is supported in current implementation (115200).
endmenu endmenu

View file

@ -46,6 +46,7 @@ obj-$(CONFIG_PIC32_SERIAL) += serial_pic32.o
obj-$(CONFIG_STM32X7_SERIAL) += serial_stm32x7.o obj-$(CONFIG_STM32X7_SERIAL) += serial_stm32x7.o
obj-$(CONFIG_BCM283X_MU_SERIAL) += serial_bcm283x_mu.o obj-$(CONFIG_BCM283X_MU_SERIAL) += serial_bcm283x_mu.o
obj-$(CONFIG_MSM_SERIAL) += serial_msm.o obj-$(CONFIG_MSM_SERIAL) += serial_msm.o
obj-$(CONFIG_MVEBU_A3700_UART) += serial_mvebu_a3700.o
ifndef CONFIG_SPL_BUILD ifndef CONFIG_SPL_BUILD
obj-$(CONFIG_USB_TTY) += usbtty.o obj-$(CONFIG_USB_TTY) += usbtty.o

View file

@ -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