All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 01/15] serial: Add serial_mvebu_a3700 for Armada 3700 SoC
@ 2016-09-16 13:09 Stefan Roese
  2016-09-16 13:09 ` [U-Boot] [PATCH 02/15] spi: Add driver for Marvell " Stefan Roese
                   ` (13 more replies)
  0 siblings, 14 replies; 36+ messages in thread
From: Stefan Roese @ 2016-09-16 13:09 UTC (permalink / raw)
  To: u-boot

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>
---
 drivers/serial/Kconfig              |  15 ++++
 drivers/serial/Makefile             |   1 +
 drivers/serial/serial_mvebu_a3700.c | 173 ++++++++++++++++++++++++++++++++++++
 3 files changed, 189 insertions(+)
 create mode 100644 drivers/serial/serial_mvebu_a3700.c

diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index ab5df70..541cf2e 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -147,6 +147,13 @@ config DEBUG_UART_ARM_DCC
 	  This port is available at least on ARMv6, ARMv7, ARMv8 and XScale
 	  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
 	bool "Xilinx Zynq"
 	help
@@ -295,6 +302,13 @@ config FSL_LPUART
 	  Select this to enable a Low Power UART for Freescale VF610 and
 	  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
 	bool "Support for Microchip PIC32 on-chip UART"
 	depends on DM_SERIAL && MACH_PIC32
@@ -371,4 +385,5 @@ config MSM_SERIAL
 	  It should support all Qualcomm devices with UARTDM version 1.4,
 	  for example APQ8016 and MSM8916.
 	  Single baudrate is supported in current implementation (115200).
+
 endmenu
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 6986d65..21b1292 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_PIC32_SERIAL) += serial_pic32.o
 obj-$(CONFIG_STM32X7_SERIAL) += serial_stm32x7.o
 obj-$(CONFIG_BCM283X_MU_SERIAL) += serial_bcm283x_mu.o
 obj-$(CONFIG_MSM_SERIAL) += serial_msm.o
+obj-$(CONFIG_MVEBU_A3700_UART) += serial_mvebu_a3700.o
 
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_USB_TTY) += usbtty.o
diff --git a/drivers/serial/serial_mvebu_a3700.c b/drivers/serial/serial_mvebu_a3700.c
new file mode 100644
index 0000000..e7b2db1
--- /dev/null
+++ b/drivers/serial/serial_mvebu_a3700.c
@@ -0,0 +1,173 @@
+/*
+ * 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
+
+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
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 02/15] spi: Add driver for Marvell Armada 3700 SoC
  2016-09-16 13:09 [U-Boot] [PATCH 01/15] serial: Add serial_mvebu_a3700 for Armada 3700 SoC Stefan Roese
@ 2016-09-16 13:09 ` Stefan Roese
  2016-09-21  7:56   ` Jagan Teki
                     ` (2 more replies)
  2016-09-16 13:09 ` [U-Boot] [PATCH 03/15] net: mvneta: Make driver 64bit safe Stefan Roese
                   ` (12 subsequent siblings)
  13 siblings, 3 replies; 36+ messages in thread
From: Stefan Roese @ 2016-09-16 13:09 UTC (permalink / raw)
  To: u-boot

The SPI IP core in the Marvell Armada 3700 is similar to the one in the
other Armada SoCs. But the differences are big enough that it makes
sense to introduce a new driver instead of cluttering the old
kirkwood driver with #ifdef's.

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>
Cc: Jagan Teki <jteki@openedev.com>
---
 drivers/spi/Kconfig           |   7 ++
 drivers/spi/Makefile          |   1 +
 drivers/spi/mvebu_a3700_spi.c | 281 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 289 insertions(+)
 create mode 100644 drivers/spi/mvebu_a3700_spi.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index aca385d..bc5e716 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -75,6 +75,13 @@ config ICH_SPI
 	  access the SPI NOR flash on platforms embedding this Intel
 	  ICH IP core.
 
+config MVEBU_A3700_SPI
+	bool "Marvell Armada 3700 SPI driver"
+	help
+	  Enable the Marvell Armada 3700 SPI driver. This driver can be
+	  used to access the SPI NOR flash on platforms embedding this
+	  Marvell IP core.
+
 config PIC32_SPI
 	bool "Microchip PIC32 SPI driver"
 	depends on MACH_PIC32
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index b1d9e20..247c5f6 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
 obj-$(CONFIG_LPC32XX_SSP) += lpc32xx_ssp.o
 obj-$(CONFIG_MPC52XX_SPI) += mpc52xx_spi.o
 obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
+obj-$(CONFIG_MVEBU_A3700_SPI) += mvebu_a3700_spi.o
 obj-$(CONFIG_MXC_SPI) += mxc_spi.o
 obj-$(CONFIG_MXS_SPI) += mxs_spi.o
 obj-$(CONFIG_OMAP3_SPI) += omap3_spi.o
diff --git a/drivers/spi/mvebu_a3700_spi.c b/drivers/spi/mvebu_a3700_spi.c
new file mode 100644
index 0000000..26f9a8f
--- /dev/null
+++ b/drivers/spi/mvebu_a3700_spi.c
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2015 Marvell International Ltd.
+ *
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <malloc.h>
+#include <spi.h>
+#include <wait_bit.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define SPI_TIMEOUT				10000
+
+#define MVEBU_SPI_A3700_XFER_RDY		BIT(1)
+#define MVEBU_SPI_A3700_FIFO_FLUSH		BIT(9)
+#define MVEBU_SPI_A3700_BYTE_LEN		BIT(5)
+#define MVEBU_SPI_A3700_CLK_PHA			BIT(6)
+#define MVEBU_SPI_A3700_CLK_POL			BIT(7)
+#define MVEBU_SPI_A3700_FIFO_EN			BIT(17)
+#define MVEBU_SPI_A3700_SPI_EN_0		BIT(16)
+#define MVEBU_SPI_A3700_CLK_PRESCALE_BIT	0
+#define MVEBU_SPI_A3700_CLK_PRESCALE_MASK	\
+	(0x1f << MVEBU_SPI_A3700_CLK_PRESCALE_BIT)
+
+/* SPI registers */
+struct spi_reg {
+	u32 ctrl;	/* 0x10600 */
+	u32 cfg;	/* 0x10604 */
+	u32 dout;	/* 0x10608 */
+	u32 din;	/* 0x1060c */
+};
+
+struct mvebu_spi_platdata {
+	struct spi_reg *spireg;
+};
+
+static void spi_cs_activate(struct spi_reg *reg, int cs)
+{
+	setbits_le32(&reg->ctrl, MVEBU_SPI_A3700_SPI_EN_0 << cs);
+}
+
+static void spi_cs_deactivate(struct spi_reg *reg, int cs)
+{
+	clrbits_le32(&reg->ctrl, MVEBU_SPI_A3700_SPI_EN_0 << cs);
+}
+
+/**
+ * spi_legacy_shift_byte() - triggers the real SPI transfer
+ * @bytelen:	Indicate how many bytes to transfer.
+ * @dout:	Buffer address of what to send.
+ * @din:	Buffer address of where to receive.
+ *
+ * This function triggers the real SPI transfer in legacy mode. It
+ * will shift out char buffer from @dout, and shift in char buffer to
+ * @din, if necessary.
+ *
+ * This function assumes that only one byte is shifted@one time.
+ * However, it is not its responisbility to set the transfer type to
+ * one-byte. Also, it does not guarantee that it will work if transfer
+ * type becomes two-byte. See spi_set_legacy() for details.
+ *
+ * In legacy mode, simply write to the SPI_DOUT register will trigger
+ * the transfer.
+ *
+ * If @dout == NULL, which means no actual data needs to be sent out,
+ * then the function will shift out 0x00 in order to shift in data.
+ * The XFER_RDY flag is checked every time before accessing SPI_DOUT
+ * and SPI_DIN register.
+ *
+ * The number of transfers to be triggerred is decided by @bytelen.
+ *
+ * Return:	0 - cool
+ *		-ETIMEDOUT - XFER_RDY flag timeout
+ */
+static int spi_legacy_shift_byte(struct spi_reg *reg, unsigned int bytelen,
+				 const void *dout, void *din)
+{
+	const u8 *dout_8;
+	u8 *din_8;
+	int ret;
+
+	/* Use 0x00 as dummy dout */
+	const u8 dummy_dout = 0x0;
+	u32 pending_dout = 0x0;
+
+	/* dout_8: pointer of current dout */
+	dout_8 = dout;
+	/* din_8: pointer of current din */
+	din_8 = din;
+
+	while (bytelen) {
+		ret = wait_for_bit(__func__, &reg->ctrl,
+				   MVEBU_SPI_A3700_XFER_RDY, true, 100, false);
+		if (ret)
+			return ret;
+
+		if (dout)
+			pending_dout = (u32)*dout_8;
+		else
+			pending_dout = (u32)dummy_dout;
+
+		/* Trigger the xfer */
+		writel(pending_dout, &reg->dout);
+
+		if (din) {
+			ret = wait_for_bit(__func__, &reg->ctrl,
+					   MVEBU_SPI_A3700_XFER_RDY,
+					   true, 100, false);
+			if (ret)
+				return ret;
+
+			/* Read what is transferred in */
+			*din_8 = (u8)readl(&reg->din);
+		}
+
+		/* Don't increment the current pointer if NULL */
+		if (dout)
+			dout_8++;
+		if (din)
+			din_8++;
+
+		bytelen--;
+	}
+
+	return 0;
+}
+
+static int mvebu_spi_xfer(struct udevice *dev, unsigned int bitlen,
+			  const void *dout, void *din, unsigned long flags)
+{
+	struct udevice *bus = dev->parent;
+	struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
+	struct spi_reg *reg = plat->spireg;
+	unsigned int bytelen;
+	int ret;
+
+	bytelen = bitlen / 8;
+
+	if (dout && din)
+		debug("This is a duplex transfer.\n");
+
+	/* Activate CS */
+	if (flags & SPI_XFER_BEGIN) {
+		debug("SPI: activate cs.\n");
+		spi_cs_activate(reg, spi_chip_select(dev));
+	}
+
+	/* Send and/or receive */
+	if (dout || din) {
+		ret = spi_legacy_shift_byte(reg, bytelen, dout, din);
+		if (ret)
+			return ret;
+	}
+
+	/* Deactivate CS */
+	if (flags & SPI_XFER_END) {
+		ret = wait_for_bit(__func__, &reg->ctrl,
+				   MVEBU_SPI_A3700_XFER_RDY, true, 100, false);
+		if (ret)
+			return ret;
+
+		debug("SPI: deactivate cs.\n");
+		spi_cs_deactivate(reg, spi_chip_select(dev));
+	}
+
+	return 0;
+}
+
+static int mvebu_spi_set_speed(struct udevice *bus, uint hz)
+{
+	struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
+	struct spi_reg *reg = plat->spireg;
+	u32 data;
+
+	data = readl(&reg->cfg);
+
+	/* Set Prescaler */
+	data &= ~MVEBU_SPI_A3700_CLK_PRESCALE_MASK;
+
+	/* Calculate Prescaler = (spi_input_freq / spi_max_freq) */
+	/* ToDo: get real values for clock and frequency */
+	data |= 160000 / 40000;
+
+	writel(data, &reg->cfg);
+
+	return 0;
+}
+
+static int mvebu_spi_set_mode(struct udevice *bus, uint mode)
+{
+	struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
+	struct spi_reg *reg = plat->spireg;
+
+	/*
+	 * Set SPI polarity
+	 * 0: Serial interface clock is low when inactive
+	 * 1: Serial interface clock is high when inactive
+	 */
+	if (mode & SPI_CPOL)
+		setbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_POL);
+	else
+		clrbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_POL);
+	if (mode & SPI_CPHA)
+		setbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_PHA);
+	else
+		clrbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_PHA);
+
+	return 0;
+}
+
+static int mvebu_spi_probe(struct udevice *bus)
+{
+	struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
+	struct spi_reg *reg = plat->spireg;
+	u32 data;
+	int ret;
+
+	/*
+	 * Settings SPI controller to be working in legacy mode, which
+	 * means use only DO pin (I/O 1) for Data Out, and DI pin (I/O 0)
+	 * for Data In.
+	 */
+
+	/* Flush read/write FIFO */
+	data = readl(&reg->cfg);
+	writel(data | MVEBU_SPI_A3700_FIFO_FLUSH, &reg->cfg);
+	ret = wait_for_bit(__func__, &reg->cfg, MVEBU_SPI_A3700_FIFO_FLUSH,
+			   false, 1000, false);
+	if (ret)
+		return ret;
+
+	/* Disable FIFO mode */
+	data &= ~MVEBU_SPI_A3700_FIFO_EN;
+
+	/* Always shift 1 byte at a time */
+	data &= ~MVEBU_SPI_A3700_BYTE_LEN;
+
+	writel(data, &reg->cfg);
+
+	return 0;
+}
+
+static int mvebu_spi_ofdata_to_platdata(struct udevice *bus)
+{
+	struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
+
+	plat->spireg = (struct spi_reg *)dev_get_addr(bus);
+
+	return 0;
+}
+
+static const struct dm_spi_ops mvebu_spi_ops = {
+	.xfer		= mvebu_spi_xfer,
+	.set_speed	= mvebu_spi_set_speed,
+	.set_mode	= mvebu_spi_set_mode,
+	/*
+	 * cs_info is not needed, since we require all chip selects to be
+	 * in the device tree explicitly
+	 */
+};
+
+static const struct udevice_id mvebu_spi_ids[] = {
+	{ .compatible = "marvell,armada-3700-spi" },
+	{ }
+};
+
+U_BOOT_DRIVER(mvebu_spi) = {
+	.name = "mvebu_spi",
+	.id = UCLASS_SPI,
+	.of_match = mvebu_spi_ids,
+	.ops = &mvebu_spi_ops,
+	.ofdata_to_platdata = mvebu_spi_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct mvebu_spi_platdata),
+	.probe = mvebu_spi_probe,
+};
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 03/15] net: mvneta: Make driver 64bit safe
  2016-09-16 13:09 [U-Boot] [PATCH 01/15] serial: Add serial_mvebu_a3700 for Armada 3700 SoC Stefan Roese
  2016-09-16 13:09 ` [U-Boot] [PATCH 02/15] spi: Add driver for Marvell " Stefan Roese
@ 2016-09-16 13:09 ` Stefan Roese
  2016-09-16 17:30   ` Joe Hershberger
  2016-09-16 13:09 ` [U-Boot] [PATCH 04/15] net: mvneta: Add support for Armada 3700 SoC Stefan Roese
                   ` (11 subsequent siblings)
  13 siblings, 1 reply; 36+ messages in thread
From: Stefan Roese @ 2016-09-16 13:09 UTC (permalink / raw)
  To: u-boot

The mvneta driver is also used on the ARMv8 64bit Armada 3700 SoC. This
patch fixes the compilation warnings seen on this 64bit platform.

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>
Cc: Joe Hershberger <joe.hershberger@ni.com>
---
 drivers/net/mvneta.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/net/mvneta.c b/drivers/net/mvneta.c
index c23fe9a..433e186 100644
--- a/drivers/net/mvneta.c
+++ b/drivers/net/mvneta.c
@@ -1022,7 +1022,7 @@ static int mvneta_txq_init(struct mvneta_port *pp,
 	txq->size = pp->tx_ring_size;
 
 	/* Allocate memory for TX descriptors */
-	txq->descs_phys = (u32)txq->descs;
+	txq->descs_phys = (dma_addr_t)txq->descs;
 	if (txq->descs == NULL)
 		return -ENOMEM;
 
@@ -1504,10 +1504,10 @@ static int mvneta_send(struct udevice *dev, void *packet, int length)
 	/* Get a descriptor for the first part of the packet */
 	tx_desc = mvneta_txq_next_desc_get(txq);
 
-	tx_desc->buf_phys_addr = (u32)packet;
+	tx_desc->buf_phys_addr = (u32)(uintptr_t)packet;
 	tx_desc->data_size = length;
-	flush_dcache_range((u32)packet,
-			   (u32)packet + ALIGN(length, PKTALIGN));
+	flush_dcache_range((ulong)packet,
+			   (ulong)packet + ALIGN(length, PKTALIGN));
 
 	/* First and Last descriptor */
 	tx_desc->command = MVNETA_TX_L4_CSUM_NOT | MVNETA_TXD_FLZ_DESC;
@@ -1563,7 +1563,7 @@ static int mvneta_recv(struct udevice *dev, int flags, uchar **packetp)
 		rx_bytes = rx_desc->data_size - 6;
 
 		/* give packet to stack - skip on first 2 bytes */
-		data = (u8 *)rx_desc->buf_cookie + 2;
+		data = (u8 *)(uintptr_t)rx_desc->buf_cookie + 2;
 		/*
 		 * No cache invalidation needed here, since the rx_buffer's are
 		 * located in a uncached memory region
@@ -1594,13 +1594,13 @@ static int mvneta_probe(struct udevice *dev)
 	if (!buffer_loc.tx_descs) {
 		/* Align buffer area for descs and rx_buffers to 1MiB */
 		bd_space = memalign(1 << MMU_SECTION_SHIFT, BD_SPACE);
-		mmu_set_region_dcache_behaviour((u32)bd_space, BD_SPACE,
+		mmu_set_region_dcache_behaviour((phys_addr_t)bd_space, BD_SPACE,
 						DCACHE_OFF);
 		buffer_loc.tx_descs = (struct mvneta_tx_desc *)bd_space;
 		buffer_loc.rx_descs = (struct mvneta_rx_desc *)
-			((u32)bd_space +
+			((phys_addr_t)bd_space +
 			 MVNETA_MAX_TXD * sizeof(struct mvneta_tx_desc));
-		buffer_loc.rx_buffers = (u32)
+		buffer_loc.rx_buffers = (phys_addr_t)
 			(bd_space +
 			 MVNETA_MAX_TXD * sizeof(struct mvneta_tx_desc) +
 			 MVNETA_MAX_RXD * sizeof(struct mvneta_rx_desc));
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 04/15] net: mvneta: Add support for Armada 3700 SoC
  2016-09-16 13:09 [U-Boot] [PATCH 01/15] serial: Add serial_mvebu_a3700 for Armada 3700 SoC Stefan Roese
  2016-09-16 13:09 ` [U-Boot] [PATCH 02/15] spi: Add driver for Marvell " Stefan Roese
  2016-09-16 13:09 ` [U-Boot] [PATCH 03/15] net: mvneta: Make driver 64bit safe Stefan Roese
@ 2016-09-16 13:09 ` Stefan Roese
  2016-09-16 17:59   ` Joe Hershberger
  2016-09-23 11:26   ` [U-Boot] [PATCH 04/15 v2] " Stefan Roese
  2016-09-16 13:09 ` [U-Boot] [PATCH 05/15] usb: xhci: Add Marvell MVEBU xHCI support Stefan Roese
                   ` (10 subsequent siblings)
  13 siblings, 2 replies; 36+ messages in thread
From: Stefan Roese @ 2016-09-16 13:09 UTC (permalink / raw)
  To: u-boot

This patch adds support for the Armada 3700 SoC to the Marvell mvneta
network driver.

Not like A380, in Armada3700, there are two layers of decode windows for GBE:
First layer is:  GbE Address window that resides inside the GBE unit,
Second layer is: Fabric address window which is located in the NIC400
                 (South Fabric).
To simplify the address decode configuration for Armada3700, we bypass the
first layer of GBE decode window by setting the first window to 4GB.

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>
Cc: Joe Hershberger <joe.hershberger@ni.com>
---
 drivers/net/mvneta.c | 39 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 38 insertions(+), 1 deletion(-)

diff --git a/drivers/net/mvneta.c b/drivers/net/mvneta.c
index 433e186..2b98a92 100644
--- a/drivers/net/mvneta.c
+++ b/drivers/net/mvneta.c
@@ -91,7 +91,10 @@ DECLARE_GLOBAL_DATA_PTR;
 #define MVNETA_WIN_BASE(w)                      (0x2200 + ((w) << 3))
 #define MVNETA_WIN_SIZE(w)                      (0x2204 + ((w) << 3))
 #define MVNETA_WIN_REMAP(w)                     (0x2280 + ((w) << 2))
+#define MVNETA_WIN_SIZE_MASK			(0xffff0000)
 #define MVNETA_BASE_ADDR_ENABLE                 0x2290
+#define MVNETA_PORT_ACCESS_PROTECT              0x2294
+#define      MVNETA_PORT_ACCESS_PROTECT_WIN0_RW	0x3
 #define MVNETA_PORT_CONFIG                      0x2400
 #define      MVNETA_UNI_PROMISC_MODE            BIT(0)
 #define      MVNETA_DEF_RXQ(q)                  ((q) << 1)
@@ -1241,6 +1244,36 @@ static int mvneta_init2(struct mvneta_port *pp)
 }
 
 /* platform glue : initialize decoding windows */
+
+/*
+ * Not like A380, in Armada3700, there are two layers of decode windows for GBE:
+ * First layer is:  GbE Address window that resides inside the GBE unit,
+ * Second layer is: Fabric address window which is located in the NIC400
+ *                  (South Fabric).
+ * To simplify the address decode configuration for Armada3700, we bypass the
+ * first layer of GBE decode window by setting the first window to 4GB.
+ */
+static void mvneta_bypass_mbus_windows(struct mvneta_port *pp)
+{
+	u32 tmp_value;
+
+	/*
+	 * Set window size to 4GB, to bypass GBE address decode, leave the
+	 * work to MBUS decode window
+	 */
+	mvreg_write(pp, MVNETA_WIN_SIZE(0), MVNETA_WIN_SIZE_MASK);
+
+	/* Enable GBE address decode window 0 by set bit 0 to 0 */
+	tmp_value = mvreg_read(pp, MVNETA_BASE_ADDR_ENABLE);
+	tmp_value = tmp_value & ~(1);
+	mvreg_write(pp, MVNETA_BASE_ADDR_ENABLE, tmp_value);
+
+	/* Set GBE address decode window 0 to full Access (read or write) */
+	tmp_value = mvreg_read(pp, MVNETA_PORT_ACCESS_PROTECT);
+	tmp_value = tmp_value | MVNETA_PORT_ACCESS_PROTECT_WIN0_RW;
+	mvreg_write(pp, MVNETA_PORT_ACCESS_PROTECT, tmp_value);
+}
+
 static void mvneta_conf_mbus_windows(struct mvneta_port *pp)
 {
 	const struct mbus_dram_target_info *dram;
@@ -1609,7 +1642,10 @@ static int mvneta_probe(struct udevice *dev)
 	pp->base = (void __iomem *)pdata->iobase;
 
 	/* Configure MBUS address windows */
-	mvneta_conf_mbus_windows(pp);
+	if (of_device_is_compatible(dev, "marvell,armada-3700-neta"))
+		mvneta_bypass_mbus_windows(pp);
+	else
+		mvneta_conf_mbus_windows(pp);
 
 	/* PHY interface is already decoded in mvneta_ofdata_to_platdata() */
 	pp->phy_interface = pdata->phy_interface;
@@ -1672,6 +1708,7 @@ static int mvneta_ofdata_to_platdata(struct udevice *dev)
 static const struct udevice_id mvneta_ids[] = {
 	{ .compatible = "marvell,armada-370-neta" },
 	{ .compatible = "marvell,armada-xp-neta" },
+	{ .compatible = "marvell,armada-3700-neta" },
 	{ }
 };
 
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 05/15] usb: xhci: Add Marvell MVEBU xHCI support
  2016-09-16 13:09 [U-Boot] [PATCH 01/15] serial: Add serial_mvebu_a3700 for Armada 3700 SoC Stefan Roese
                   ` (2 preceding siblings ...)
  2016-09-16 13:09 ` [U-Boot] [PATCH 04/15] net: mvneta: Add support for Armada 3700 SoC Stefan Roese
@ 2016-09-16 13:09 ` Stefan Roese
  2016-09-18 10:46   ` Marek Vasut
  2016-09-16 13:09 ` [U-Boot] [PATCH 06/15] usb: ehci: ehci-marvell.c: Add Armada 3700 support (ARMv8) Stefan Roese
                   ` (9 subsequent siblings)
  13 siblings, 1 reply; 36+ messages in thread
From: Stefan Roese @ 2016-09-16 13:09 UTC (permalink / raw)
  To: u-boot

This patch adds DM based support for the xHCI USB 3.0 controller
integrated in the Armada 3700 SoC. It may be extended to be used
by other MVEBU SoCs as well.

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>
Cc: Marek Vasut <marex@denx.de>
---
 drivers/usb/host/Kconfig      |  9 ++++
 drivers/usb/host/Makefile     |  1 +
 drivers/usb/host/xhci-mvebu.c | 96 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 106 insertions(+)
 create mode 100644 drivers/usb/host/xhci-mvebu.c

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index e0699d4..f996c75 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -28,6 +28,15 @@ config USB_XHCI_DWC3
 	  Say Y or if your system has a Dual Role SuperSpeed
 	  USB controller based on the DesignWare USB3 IP Core.
 
+config USB_XHCI_MVEBU
+	bool "MVEBU USB 3.0 support"
+	default y
+	depends on ARCH_MVEBU
+	help
+	  Choose this option to add support for USB 3.0 driver on mvebu
+	  SoCs, which includes Armada8K, Armada3700 and other Armada
+	  family SoCs.
+
 endif # USB_XHCI_HCD
 
 config USB_EHCI_HCD
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 620d114..519325d 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -60,6 +60,7 @@ obj-$(CONFIG_USB_XHCI_ZYNQMP) += xhci-zynqmp.o
 obj-$(CONFIG_USB_XHCI_KEYSTONE) += xhci-keystone.o
 obj-$(CONFIG_USB_XHCI_EXYNOS) += xhci-exynos5.o
 obj-$(CONFIG_USB_XHCI_FSL) += xhci-fsl.o
+obj-$(CONFIG_USB_XHCI_MVEBU) += xhci-mvebu.o
 obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o
 obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o
 obj-$(CONFIG_USB_XHCI_UNIPHIER) += xhci-uniphier.o
diff --git a/drivers/usb/host/xhci-mvebu.c b/drivers/usb/host/xhci-mvebu.c
new file mode 100644
index 0000000..e09e87a
--- /dev/null
+++ b/drivers/usb/host/xhci-mvebu.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2015 Marvell International Ltd.
+ *
+ * MVEBU USB HOST xHCI Controller
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <usb.h>
+#include <asm/gpio.h>
+
+#include "xhci.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct mvebu_xhci_platdata {
+	fdt_addr_t hcd_base;
+};
+
+/**
+ * Contains pointers to register base addresses
+ * for the usb controller.
+ */
+struct mvebu_xhci {
+	struct xhci_ctrl ctrl;	/* Needs to come first in this struct! */
+	struct usb_platdata usb_plat;
+	struct xhci_hccr *hcd;
+};
+
+/*
+ * Dummy implementation that can be overwritten by a board
+ * specific function
+ */
+__weak int board_xhci_enable(void)
+{
+	return 0;
+}
+
+static int xhci_usb_probe(struct udevice *dev)
+{
+	struct mvebu_xhci_platdata *plat = dev_get_platdata(dev);
+	struct mvebu_xhci *ctx = dev_get_priv(dev);
+	struct xhci_hcor *hcor;
+	int len;
+
+	ctx->hcd = (struct xhci_hccr *)plat->hcd_base;
+	len = HC_LENGTH(xhci_readl(&ctx->hcd->cr_capbase));
+	hcor = (struct xhci_hcor *)((uintptr_t)ctx->hcd + len);
+
+	/* Enable USB xHCI (VBUS, reset etc) in board specific code */
+	board_xhci_enable();
+
+	return xhci_register(dev, ctx->hcd, hcor);
+}
+
+static int xhci_usb_remove(struct udevice *dev)
+{
+	return xhci_deregister(dev);
+}
+
+static int xhci_usb_ofdata_to_platdata(struct udevice *dev)
+{
+	struct mvebu_xhci_platdata *plat = dev_get_platdata(dev);
+
+	/*
+	 * Get the base address for XHCI controller from the device node
+	 */
+	plat->hcd_base = dev_get_addr(dev);
+	if (plat->hcd_base == FDT_ADDR_T_NONE) {
+		debug("Can't get the XHCI register base address\n");
+		return -ENXIO;
+	}
+
+	return 0;
+}
+
+static const struct udevice_id xhci_usb_ids[] = {
+	{ .compatible = "marvell,armada3700-xhci" },
+	{ }
+};
+
+U_BOOT_DRIVER(usb_xhci) = {
+	.name	= "xhci_mvebu",
+	.id	= UCLASS_USB,
+	.of_match = xhci_usb_ids,
+	.ofdata_to_platdata = xhci_usb_ofdata_to_platdata,
+	.probe = xhci_usb_probe,
+	.remove = xhci_usb_remove,
+	.ops	= &xhci_usb_ops,
+	.platdata_auto_alloc_size = sizeof(struct mvebu_xhci_platdata),
+	.priv_auto_alloc_size = sizeof(struct mvebu_xhci),
+	.flags	= DM_FLAG_ALLOC_PRIV_DMA,
+};
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 06/15] usb: ehci: ehci-marvell.c: Add Armada 3700 support (ARMv8)
  2016-09-16 13:09 [U-Boot] [PATCH 01/15] serial: Add serial_mvebu_a3700 for Armada 3700 SoC Stefan Roese
                   ` (3 preceding siblings ...)
  2016-09-16 13:09 ` [U-Boot] [PATCH 05/15] usb: xhci: Add Marvell MVEBU xHCI support Stefan Roese
@ 2016-09-16 13:09 ` Stefan Roese
  2016-09-18 10:47   ` Marek Vasut
  2016-09-16 13:09 ` [U-Boot] [PATCH 07/15] drivers/phy: Add Marvell SerDes / PHY drivers used on Armada 3k Stefan Roese
                   ` (8 subsequent siblings)
  13 siblings, 1 reply; 36+ messages in thread
From: Stefan Roese @ 2016-09-16 13:09 UTC (permalink / raw)
  To: u-boot

This patch adds DM based support for the Armada 3700 EHCI controller.
The address windows don't need to get configured in this case. The
difference here is detected via DT compatible property at runtime.

With this support and the DM xHCI driver, both XHCI and eHCI can be
used simultaniously on the MVEBU boards now.

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>
Cc: Marek Vasut <marex@denx.de>
---
 drivers/usb/host/ehci-marvell.c | 59 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 52 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/host/ehci-marvell.c b/drivers/usb/host/ehci-marvell.c
index 5b0f46a..72b9b30 100644
--- a/drivers/usb/host/ehci-marvell.c
+++ b/drivers/usb/host/ehci-marvell.c
@@ -26,6 +26,16 @@ DECLARE_GLOBAL_DATA_PTR;
 #define USB_WINDOW_BASE(i)	(0x324 + ((i) << 4))
 #define USB_TARGET_DRAM		0x0
 
+#define USB2_SBUSCFG_OFF	0x90
+
+#define USB_SBUSCFG_BAWR_OFF	0x6
+#define USB_SBUSCFG_BARD_OFF	0x3
+#define USB_SBUSCFG_AHBBRST_OFF	0x0
+
+#define USB_SBUSCFG_BAWR_ALIGN_64B	0x4
+#define USB_SBUSCFG_BARD_ALIGN_64B	0x4
+#define USB_SBUSCFG_AHBBRST_INCR16	0x7
+
 /*
  * USB 2.0 Bridge Address Decoding registers setup
  */
@@ -41,7 +51,7 @@ struct ehci_mvebu_priv {
  * to the common mvebu archticture including the mbus setup, this
  * will be the only function needed to configure the access windows
  */
-static void usb_brg_adrdec_setup(u32 base)
+static void usb_brg_adrdec_setup(void *base)
 {
 	const struct mbus_dram_target_info *dram;
 	int i;
@@ -66,6 +76,29 @@ static void usb_brg_adrdec_setup(u32 base)
 	}
 }
 
+static void marvell_ehci_powerup_fixup(struct ehci_ctrl *ctrl,
+				       uint32_t *status_reg, uint32_t *reg)
+{
+	struct ehci_mvebu_priv *priv = ctrl->priv;
+
+	/*
+	 * Set default value for reg SBUSCFG, which is Control for the AMBA
+	 * system bus interface:
+	 * BAWR = BARD = 4 : Align rd/wr bursts packets larger than 64 bytes
+	 * AHBBRST = 7     : Align AHB burst for packets larger than 64 bytes
+	 */
+	writel((USB_SBUSCFG_BAWR_ALIGN_64B << USB_SBUSCFG_BAWR_OFF) |
+	       (USB_SBUSCFG_BARD_ALIGN_64B << USB_SBUSCFG_BARD_OFF) |
+	       (USB_SBUSCFG_AHBBRST_INCR16 << USB_SBUSCFG_AHBBRST_OFF),
+	       priv->hcd_base + USB2_SBUSCFG_OFF);
+
+	mdelay(50);
+}
+
+static struct ehci_ops marvell_ehci_ops = {
+	.powerup_fixup	= NULL,
+};
+
 static int ehci_mvebu_probe(struct udevice *dev)
 {
 	struct ehci_mvebu_priv *priv = dev_get_priv(dev);
@@ -81,17 +114,28 @@ static int ehci_mvebu_probe(struct udevice *dev)
 		return -ENXIO;
 	}
 
-	usb_brg_adrdec_setup(priv->hcd_base);
+	/*
+	 * For SoCs without hlock like Armada3700 we need to program the sbuscfg
+	 * reg to guarantee AHB master's burst will not overrun or underrun
+	 * the FIFO. Otherwise all USB2 write option will fail.
+	 * Also, the address decoder doesn't need to get setup with this
+	 * SoC, so don't call usb_brg_adrdec_setup().
+	 */
+	if (of_device_is_compatible(dev, "marvell,armada3700-ehci"))
+		marvell_ehci_ops.powerup_fixup = marvell_ehci_powerup_fixup;
+	else
+		usb_brg_adrdec_setup((void *)priv->hcd_base);
 
 	hccr = (struct ehci_hccr *)(priv->hcd_base + 0x100);
 	hcor = (struct ehci_hcor *)
-		((u32)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+		((uintptr_t)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
 
-	debug("ehci-marvell: init hccr %x and hcor %x hc_length %d\n",
-	      (u32)hccr, (u32)hcor,
-	      (u32)HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+	debug("ehci-marvell: init hccr %lx and hcor %lx hc_length %ld\n",
+	      (uintptr_t)hccr, (uintptr_t)hcor,
+	      (uintptr_t)HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
 
-	return ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST);
+	return ehci_register(dev, hccr, hcor, &marvell_ehci_ops, 0,
+			     USB_INIT_HOST);
 }
 
 static int ehci_mvebu_remove(struct udevice *dev)
@@ -107,6 +151,7 @@ static int ehci_mvebu_remove(struct udevice *dev)
 
 static const struct udevice_id ehci_usb_ids[] = {
 	{ .compatible = "marvell,orion-ehci", },
+	{ .compatible = "marvell,armada3700-ehci", },
 	{ }
 };
 
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 07/15] drivers/phy: Add Marvell SerDes / PHY drivers used on Armada 3k
  2016-09-16 13:09 [U-Boot] [PATCH 01/15] serial: Add serial_mvebu_a3700 for Armada 3700 SoC Stefan Roese
                   ` (4 preceding siblings ...)
  2016-09-16 13:09 ` [U-Boot] [PATCH 06/15] usb: ehci: ehci-marvell.c: Add Armada 3700 support (ARMv8) Stefan Roese
@ 2016-09-16 13:09 ` Stefan Roese
  2016-09-16 13:09 ` [U-Boot] [PATCH 08/15] arm64: mvebu: Armada 3700: Add Armada 37xx dts files Stefan Roese
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 36+ messages in thread
From: Stefan Roese @ 2016-09-16 13:09 UTC (permalink / raw)
  To: u-boot

This version is based on the Marvell U-Boot version with this patch
applied as latest patch:

Git ID 7f408573: "fix: comphy: cp110: add comphy initialization for usb
device mode" from 2016-07-05.

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>
---
 drivers/Kconfig                          |   2 +
 drivers/Makefile                         |   1 +
 drivers/phy/marvell/Kconfig              |   9 +
 drivers/phy/marvell/Makefile             |   7 +
 drivers/phy/marvell/comphy.h             | 139 +++++
 drivers/phy/marvell/comphy_a3700.c       | 962 +++++++++++++++++++++++++++++++
 drivers/phy/marvell/comphy_a3700.h       | 275 +++++++++
 drivers/phy/marvell/comphy_core.c        | 197 +++++++
 drivers/phy/marvell/comphy_hpipe.h       | 382 ++++++++++++
 drivers/phy/marvell/comphy_mux.c         | 118 ++++
 include/dt-bindings/comphy/comphy_data.h |  61 ++
 11 files changed, 2153 insertions(+)
 create mode 100644 drivers/phy/marvell/Kconfig
 create mode 100644 drivers/phy/marvell/Makefile
 create mode 100644 drivers/phy/marvell/comphy.h
 create mode 100644 drivers/phy/marvell/comphy_a3700.c
 create mode 100644 drivers/phy/marvell/comphy_a3700.h
 create mode 100644 drivers/phy/marvell/comphy_core.c
 create mode 100644 drivers/phy/marvell/comphy_hpipe.h
 create mode 100644 drivers/phy/marvell/comphy_mux.c
 create mode 100644 include/dt-bindings/comphy/comphy_data.h

diff --git a/drivers/Kconfig b/drivers/Kconfig
index 4f84469..5729999 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -46,6 +46,8 @@ source "drivers/pci/Kconfig"
 
 source "drivers/pcmcia/Kconfig"
 
+source "drivers/phy/marvell/Kconfig"
+
 source "drivers/pinctrl/Kconfig"
 
 source "drivers/power/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 7861d34..365cc8d 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -56,6 +56,7 @@ obj-y += misc/
 obj-y += pcmcia/
 obj-y += dfu/
 obj-$(CONFIG_X86) += pch/
+obj-y += phy/marvell/
 obj-y += rtc/
 obj-y += sound/
 obj-y += spmi/
diff --git a/drivers/phy/marvell/Kconfig b/drivers/phy/marvell/Kconfig
new file mode 100644
index 0000000..4240028
--- /dev/null
+++ b/drivers/phy/marvell/Kconfig
@@ -0,0 +1,9 @@
+config MVEBU_COMPHY_SUPPORT
+	bool "ComPhy SerDes driver"
+	default n
+	help
+	  Choose this option to add support
+	  for Comphy driver.
+	  This driver passes over the lanes
+	  and initialize the lane depends on the
+	  type and speed.
diff --git a/drivers/phy/marvell/Makefile b/drivers/phy/marvell/Makefile
new file mode 100644
index 0000000..91df554
--- /dev/null
+++ b/drivers/phy/marvell/Makefile
@@ -0,0 +1,7 @@
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-$(CONFIG_MVEBU_COMPHY_SUPPORT) += comphy_core.o
+obj-$(CONFIG_MVEBU_COMPHY_SUPPORT) += comphy_mux.o
+obj-$(CONFIG_ARMADA_3700) += comphy_a3700.o
diff --git a/drivers/phy/marvell/comphy.h b/drivers/phy/marvell/comphy.h
new file mode 100644
index 0000000..5c50e9c
--- /dev/null
+++ b/drivers/phy/marvell/comphy.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2015-2016 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _COMPHY_H_
+#define _COMPHY_H_
+
+#include <dt-bindings/comphy/comphy_data.h>
+#include <fdtdec.h>
+
+#if defined(DEBUG)
+#define debug_enter()	printf("----> Enter %s\n", __func__);
+#define debug_exit()	printf("<---- Exit  %s\n", __func__);
+#else
+#define debug_enter()
+#define debug_exit()
+#endif
+
+/* COMPHY registers */
+#define COMMON_PHY_CFG1_REG			0x0
+#define COMMON_PHY_CFG1_PWR_UP_OFFSET		1
+#define COMMON_PHY_CFG1_PWR_UP_MASK		\
+	(0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET)
+#define COMMON_PHY_CFG1_PIPE_SELECT_OFFSET	2
+#define COMMON_PHY_CFG1_PIPE_SELECT_MASK	\
+	(0x1 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET)
+#define COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET	13
+#define COMMON_PHY_CFG1_PWR_ON_RESET_MASK	\
+	(0x1 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET)
+#define COMMON_PHY_CFG1_CORE_RSTN_OFFSET	14
+#define COMMON_PHY_CFG1_CORE_RSTN_MASK		\
+	(0x1 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET)
+#define COMMON_PHY_PHY_MODE_OFFSET		15
+#define COMMON_PHY_PHY_MODE_MASK		\
+	(0x1 << COMMON_PHY_PHY_MODE_OFFSET)
+
+#define COMMON_PHY_CFG6_REG			0x14
+#define COMMON_PHY_CFG6_IF_40_SEL_OFFSET	18
+#define COMMON_PHY_CFG6_IF_40_SEL_MASK		\
+	(0x1 << COMMON_PHY_CFG6_IF_40_SEL_OFFSET)
+
+#define COMMON_SELECTOR_PHY_OFFSET		0x140
+#define COMMON_SELECTOR_PIPE_OFFSET		0x144
+
+#define COMMON_PHY_SD_CTRL1			0x148
+#define COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_OFFSET	0
+#define COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_MASK	0xFFFF
+#define COMMON_PHY_SD_CTRL1_PCIE_X4_EN_OFFSET	24
+#define COMMON_PHY_SD_CTRL1_PCIE_X4_EN_MASK	\
+	(0x1 << COMMON_PHY_SD_CTRL1_PCIE_X4_EN_OFFSET)
+#define COMMON_PHY_SD_CTRL1_PCIE_X2_EN_OFFSET	25
+#define COMMON_PHY_SD_CTRL1_PCIE_X2_EN_MASK	\
+	(0x1 << COMMON_PHY_SD_CTRL1_PCIE_X2_EN_OFFSET)
+#define COMMON_PHY_SD_CTRL1_RXAUI1_OFFSET	26
+#define COMMON_PHY_SD_CTRL1_RXAUI1_MASK		\
+	(0x1 << COMMON_PHY_SD_CTRL1_RXAUI1_OFFSET)
+#define COMMON_PHY_SD_CTRL1_RXAUI0_OFFSET	27
+#define COMMON_PHY_SD_CTRL1_RXAUI0_MASK		\
+	(0x1 << COMMON_PHY_SD_CTRL1_RXAUI0_OFFSET)
+
+#define DFX_DEV_GEN_CTRL12			(MVEBU_CP0_REGS_BASE + 0x400280)
+#define DFX_DEV_GEN_PCIE_CLK_SRC_OFFSET		7
+#define DFX_DEV_GEN_PCIE_CLK_SRC_MASK		\
+	(0x3 << DFX_DEV_GEN_PCIE_CLK_SRC_OFFSET)
+
+#define MAX_LANE_OPTIONS			10
+#define MAX_UTMI_PHY_COUNT			2
+
+struct comphy_mux_options {
+	u32 type;
+	u32 mux_value;
+};
+
+struct comphy_mux_data {
+	u32 max_lane_values;
+	struct comphy_mux_options mux_values[MAX_LANE_OPTIONS];
+};
+
+struct comphy_map {
+	u32 type;
+	u32 speed;
+	u32 invert;
+	bool clk_src;
+};
+
+struct chip_serdes_phy_config {
+	struct comphy_mux_data *mux_data;
+	int (*ptr_comphy_chip_init)(struct chip_serdes_phy_config *,
+				    struct comphy_map *);
+	void __iomem *comphy_base_addr;
+	void __iomem *hpipe3_base_addr;
+	u32 comphy_lanes_count;
+	u32 comphy_mux_bitcount;
+	u32 comphy_index;
+};
+
+/* Register helper functions */
+void reg_set(void __iomem *addr, u32 data, u32 mask);
+void reg_set_silent(void __iomem *addr, u32 data, u32 mask);
+void reg_set16(void __iomem *addr, u16 data, u16 mask);
+void reg_set_silent16(void __iomem *addr, u16 data, u16 mask);
+
+/* SoC specific init functions */
+#ifdef CONFIG_ARMADA_3700
+int comphy_a3700_init(struct chip_serdes_phy_config *ptr_chip_cfg,
+		      struct comphy_map *serdes_map);
+#else
+static inline int comphy_a3700_init(struct chip_serdes_phy_config *ptr_chip_cfg,
+				    struct comphy_map *serdes_map)
+{
+	/*
+	 * This function should never be called in this configuration, so
+	 * lets return an error here.
+	 */
+	return -1;
+}
+#endif
+int comphy_ap806_init(struct chip_serdes_phy_config *ptr_chip_cfg,
+		      struct comphy_map *serdes_map);
+int comphy_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg,
+		      struct comphy_map *serdes_map);
+
+void comphy_dedicated_phys_init(void);
+
+/* MUX function */
+void comphy_mux_init(struct chip_serdes_phy_config *ptr_chip_cfg,
+		     struct comphy_map *comphy_map_data,
+		     void __iomem *selector_base);
+
+void comphy_pcie_config_set(u32 comphy_max_count,
+			    struct comphy_map *serdes_map);
+void comphy_pcie_config_detect(u32 comphy_max_count,
+			       struct comphy_map *serdes_map);
+void comphy_pcie_unit_general_config(u32 pex_index);
+
+#endif /* _COMPHY_H_ */
+
diff --git a/drivers/phy/marvell/comphy_a3700.c b/drivers/phy/marvell/comphy_a3700.c
new file mode 100644
index 0000000..faa62f9
--- /dev/null
+++ b/drivers/phy/marvell/comphy_a3700.c
@@ -0,0 +1,962 @@
+/*
+ * Copyright (C) 2015-2016 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+#include "comphy_a3700.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct sgmii_phy_init_data_fix {
+	u16 addr;
+	u16 value;
+};
+
+/* Changes to 40M1G25 mode data required for running 40M3G125 init mode */
+static struct sgmii_phy_init_data_fix sgmii_phy_init_fix[] = {
+	{0x005, 0x07CC}, {0x015, 0x0000}, {0x01B, 0x0000}, {0x01D, 0x0000},
+	{0x01E, 0x0000}, {0x01F, 0x0000}, {0x020, 0x0000}, {0x021, 0x0030},
+	{0x026, 0x0888}, {0x04D, 0x0152}, {0x04F, 0xA020}, {0x050, 0x07CC},
+	{0x053, 0xE9CA}, {0x055, 0xBD97}, {0x071, 0x3015}, {0x076, 0x03AA},
+	{0x07C, 0x0FDF}, {0x0C2, 0x3030}, {0x0C3, 0x8000}, {0x0E2, 0x5550},
+	{0x0E3, 0x12A4}, {0x0E4, 0x7D00}, {0x0E6, 0x0C83}, {0x101, 0xFCC0},
+	{0x104, 0x0C10}
+};
+
+/* 40M1G25 mode init data */
+static u16 sgmii_phy_init[512] = {
+	/* 0       1       2       3       4       5       6       7 */
+	/*-----------------------------------------------------------*/
+	/* 8       9       A       B       C       D       E       F */
+	0x3110, 0xFD83, 0x6430, 0x412F, 0x82C0, 0x06FA, 0x4500, 0x6D26,	/* 00 */
+	0xAFC0, 0x8000, 0xC000, 0x0000, 0x2000, 0x49CC, 0x0BC9, 0x2A52,	/* 08 */
+	0x0BD2, 0x0CDE, 0x13D2, 0x0CE8, 0x1149, 0x10E0, 0x0000, 0x0000,	/* 10 */
+	0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x4134, 0x0D2D, 0xFFFF,	/* 18 */
+	0xFFE0, 0x4030, 0x1016, 0x0030, 0x0000, 0x0800, 0x0866, 0x0000,	/* 20 */
+	0x0000, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,	/* 28 */
+	0xFFFF, 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/* 30 */
+	0x0000, 0x0000, 0x000F, 0x6A62, 0x1988, 0x3100, 0x3100, 0x3100,	/* 38 */
+	0x3100, 0xA708, 0x2430, 0x0830, 0x1030, 0x4610, 0xFF00, 0xFF00,	/* 40 */
+	0x0060, 0x1000, 0x0400, 0x0040, 0x00F0, 0x0155, 0x1100, 0xA02A,	/* 48 */
+	0x06FA, 0x0080, 0xB008, 0xE3ED, 0x5002, 0xB592, 0x7A80, 0x0001,	/* 50 */
+	0x020A, 0x8820, 0x6014, 0x8054, 0xACAA, 0xFC88, 0x2A02, 0x45CF,	/* 58 */
+	0x000F, 0x1817, 0x2860, 0x064F, 0x0000, 0x0204, 0x1800, 0x6000,	/* 60 */
+	0x810F, 0x4F23, 0x4000, 0x4498, 0x0850, 0x0000, 0x000E, 0x1002,	/* 68 */
+	0x9D3A, 0x3009, 0xD066, 0x0491, 0x0001, 0x6AB0, 0x0399, 0x3780,	/* 70 */
+	0x0040, 0x5AC0, 0x4A80, 0x0000, 0x01DF, 0x0000, 0x0007, 0x0000,	/* 78 */
+	0x2D54, 0x00A1, 0x4000, 0x0100, 0xA20A, 0x0000, 0x0000, 0x0000,	/* 80 */
+	0x0000, 0x0000, 0x0000, 0x7400, 0x0E81, 0x1000, 0x1242, 0x0210,	/* 88 */
+	0x80DF, 0x0F1F, 0x2F3F, 0x4F5F, 0x6F7F, 0x0F1F, 0x2F3F, 0x4F5F,	/* 90 */
+	0x6F7F, 0x4BAD, 0x0000, 0x0000, 0x0800, 0x0000, 0x2400, 0xB651,	/* 98 */
+	0xC9E0, 0x4247, 0x0A24, 0x0000, 0xAF19, 0x1004, 0x0000, 0x0000,	/* A0 */
+	0x0000, 0x0013, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/* A8 */
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/* B0 */
+	0x0000, 0x0000, 0x0000, 0x0060, 0x0000, 0x0000, 0x0000, 0x0000,	/* B8 */
+	0x0000, 0x0000, 0x3010, 0xFA00, 0x0000, 0x0000, 0x0000, 0x0003,	/* C0 */
+	0x1618, 0x8200, 0x8000, 0x0400, 0x050F, 0x0000, 0x0000, 0x0000,	/* C8 */
+	0x4C93, 0x0000, 0x1000, 0x1120, 0x0010, 0x1242, 0x1242, 0x1E00,	/* D0 */
+	0x0000, 0x0000, 0x0000, 0x00F8, 0x0000, 0x0041, 0x0800, 0x0000,	/* D8 */
+	0x82A0, 0x572E, 0x2490, 0x14A9, 0x4E00, 0x0000, 0x0803, 0x0541,	/* E0 */
+	0x0C15, 0x0000, 0x0000, 0x0400, 0x2626, 0x0000, 0x0000, 0x4200,	/* E8 */
+	0x0000, 0xAA55, 0x1020, 0x0000, 0x0000, 0x5010, 0x0000, 0x0000,	/* F0 */
+	0x0000, 0x0000, 0x5000, 0x0000, 0x0000, 0x0000, 0x02F2, 0x0000,	/* F8 */
+	0x101F, 0xFDC0, 0x4000, 0x8010, 0x0110, 0x0006, 0x0000, 0x0000,	/*100 */
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*108 */
+	0x04CF, 0x0000, 0x04CF, 0x0000, 0x04CF, 0x0000, 0x04C6, 0x0000,	/*110 */
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*118 */
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*120 */
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*128 */
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*130 */
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*138 */
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*140 */
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*148 */
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*150 */
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*158 */
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*160 */
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*168 */
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*170 */
+	0x0000, 0x0000, 0x0000, 0x00F0, 0x08A2, 0x3112, 0x0A14, 0x0000,	/*178 */
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*180 */
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*188 */
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*190 */
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*198 */
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*1A0 */
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*1A8 */
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*1B0 */
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*1B8 */
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*1C0 */
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*1C8 */
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*1D0 */
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*1D8 */
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*1E0 */
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*1E8 */
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,	/*1F0 */
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000	/*1F8 */
+};
+
+/*
+ * comphy_poll_reg
+ *
+ * return: 1 on success, 0 on timeout
+ */
+static u32 comphy_poll_reg(void *addr, u32 val, u32 mask, u32 timeout,
+			   u8 op_type)
+{
+	u32 rval = 0xDEAD;
+
+	for (; timeout > 0; timeout--) {
+		if (op_type == POLL_16B_REG)
+			rval = readw(addr);	/* 16 bit */
+		else
+			rval = readl(addr) ;	/* 32 bit */
+
+		if ((rval & mask) == val)
+			return 1;
+
+		udelay(10000);
+	}
+
+	debug("Time out waiting (%p = %#010x)\n", addr, rval);
+	return 0;
+}
+
+/*
+ * comphy_pcie_power_up
+ *
+ * return: 1 if PLL locked (OK), 0 otherwise (FAIL)
+ */
+static int comphy_pcie_power_up(u32 speed, u32 invert)
+{
+	int	ret;
+
+	debug_enter();
+
+	/*
+	 * 1. Enable max PLL.
+	 */
+	reg_set16((void __iomem *)LANE_CFG1_ADDR(PCIE),
+		  bf_use_max_pll_rate, 0);
+
+	/*
+	 * 2. Select 20 bit SERDES interface.
+	 */
+	reg_set16((void __iomem *)GLOB_CLK_SRC_LO_ADDR(PCIE),
+		  bf_cfg_sel_20b, 0);
+
+	/*
+	 * 3. Force to use reg setting for PCIe mode
+	 */
+	reg_set16((void __iomem *)MISC_REG1_ADDR(PCIE),
+		  bf_sel_bits_pcie_force, 0);
+
+	/*
+	 * 4. Change RX wait
+	 */
+	reg_set16((void __iomem *)PWR_MGM_TIM1_ADDR(PCIE), 0x10C, 0xFFFF);
+
+	/*
+	 * 5. Enable idle sync
+	 */
+	reg_set16((void __iomem *)UNIT_CTRL_ADDR(PCIE),
+		  0x60 | rb_idle_sync_en, 0xFFFF);
+
+	/*
+	 * 6. Enable the output of 100M/125M/500M clock
+	 */
+	reg_set16((void __iomem *)MISC_REG0_ADDR(PCIE),
+		  0xA00D | rb_clk500m_en | rb_clk100m_125m_en, 0xFFFF);
+
+	/*
+	 * 7. Enable TX
+	 */
+	reg_set((void __iomem *)PHY_REF_CLK_ADDR, 0x1342, 0xFFFFFFFF);
+
+	/*
+	 * 8. Check crystal jumper setting and program the Power and PLL
+	 *    Control accordingly
+	 */
+	if (get_ref_clk() == 40) {
+		reg_set16((void __iomem *)PWR_PLL_CTRL_ADDR(PCIE),
+			  0xFC63, 0xFFFF); /* 40 MHz */
+	} else {
+		reg_set16((void __iomem *)PWR_PLL_CTRL_ADDR(PCIE),
+			  0xFC62, 0xFFFF); /* 25 MHz */
+	}
+
+	/*
+	 * 9. Override Speed_PLL value and use MAC PLL
+	 */
+	reg_set16((void __iomem *)KVCO_CAL_CTRL_ADDR(PCIE),
+		  0x0040 | rb_use_max_pll_rate, 0xFFFF);
+
+	/*
+	 * 10. Check the Polarity invert bit
+	 */
+	if (invert & PHY_POLARITY_TXD_INVERT) {
+		reg_set16((void __iomem *)SYNC_PATTERN_ADDR(PCIE),
+			  phy_txd_inv, 0);
+	}
+
+	if (invert & PHY_POLARITY_RXD_INVERT) {
+		reg_set16((void __iomem *)SYNC_PATTERN_ADDR(PCIE),
+			  phy_rxd_inv, 0);
+	}
+
+	/*
+	 * 11. Release SW reset
+	 */
+	reg_set16((void __iomem *)GLOB_PHY_CTRL0_ADDR(PCIE),
+		  rb_mode_core_clk_freq_sel | rb_mode_pipe_width_32,
+		  bf_soft_rst | bf_mode_refdiv);
+
+	/* Wait for > 55 us to allow PCLK be enabled */
+	udelay(PLL_SET_DELAY_US);
+
+	/* Assert PCLK enabled */
+	ret = comphy_poll_reg((void *)LANE_STAT1_ADDR(PCIE),	/* address */
+			      rb_txdclk_pclk_en,		/* value */
+			      rb_txdclk_pclk_en,		/* mask */
+			      PLL_LOCK_TIMEOUT,			/* timeout */
+			      POLL_16B_REG);			/* 16bit */
+	if (ret == 0)
+		printf("Failed to lock PCIe PLL\n");
+
+	debug_exit();
+
+	/* Return the status of the PLL */
+	return ret;
+}
+
+/*
+ * comphy_sata_power_up
+ *
+ * return: 1 if PLL locked (OK), 0 otherwise (FAIL)
+ */
+static int comphy_sata_power_up(void)
+{
+	int	ret;
+
+	debug_enter();
+
+	/*
+	 * 0. Swap SATA TX lines
+	 */
+	reg_set((void __iomem *)rh_vsreg_addr,
+		vphy_sync_pattern_reg, 0xFFFFFFFF);
+	reg_set((void __iomem *)rh_vsreg_data, bs_txd_inv, bs_txd_inv);
+
+	/*
+	 * 1. Select 40-bit data width width
+	 */
+	reg_set((void __iomem *)rh_vsreg_addr, vphy_loopback_reg0, 0xFFFFFFFF);
+	reg_set((void __iomem *)rh_vsreg_data, 0x800, bs_phyintf_40bit);
+
+	/*
+	 * 2. Select reference clock and PHY mode (SATA)
+	 */
+	reg_set((void __iomem *)rh_vsreg_addr, vphy_power_reg0, 0xFFFFFFFF);
+	if (get_ref_clk() == 40) {
+		reg_set((void __iomem *)rh_vsreg_data,
+			0x3, 0x00FF); /* 40 MHz */
+	} else {
+		reg_set((void __iomem *)rh_vsreg_data,
+			0x1, 0x00FF); /* 25 MHz */
+	}
+
+	/*
+	 * 3. Use maximum PLL rate (no power save)
+	 */
+	reg_set((void __iomem *)rh_vsreg_addr, vphy_calctl_reg, 0xFFFFFFFF);
+	reg_set((void __iomem *)rh_vsreg_data,
+		bs_max_pll_rate, bs_max_pll_rate);
+
+	/*
+	 * 4. Reset reserved bit (??)
+	 */
+	reg_set((void __iomem *)rh_vsreg_addr, vphy_reserve_reg, 0xFFFFFFFF);
+	reg_set((void __iomem *)rh_vsreg_data, 0, bs_phyctrl_frm_pin);
+
+	/*
+	 * 5. Set vendor-specific configuration (??)
+	 */
+	reg_set((void __iomem *)rh_vs0_a, vsata_ctrl_reg, 0xFFFFFFFF);
+	reg_set((void __iomem *)rh_vs0_d, bs_phy_pu_pll, bs_phy_pu_pll);
+
+	/* Wait for > 55 us to allow PLL be enabled */
+	udelay(PLL_SET_DELAY_US);
+
+	/* Assert SATA PLL enabled */
+	reg_set((void __iomem *)rh_vsreg_addr, vphy_loopback_reg0, 0xFFFFFFFF);
+	ret = comphy_poll_reg((void *)rh_vsreg_data,	/* address */
+			      bs_pll_ready_tx,		/* value */
+			      bs_pll_ready_tx,		/* mask */
+			      PLL_LOCK_TIMEOUT,		/* timeout */
+			      POLL_32B_REG);		/* 32bit */
+	if (ret == 0)
+		printf("Failed to lock SATA PLL\n");
+
+	debug_exit();
+
+	return ret;
+}
+
+/*
+ * comphy_usb3_power_up
+ *
+ * return: 1 if PLL locked (OK), 0 otherwise (FAIL)
+ */
+static int comphy_usb3_power_up(u32 type, u32 speed, u32 invert)
+{
+	int	ret;
+
+	debug_enter();
+
+	/*
+	 * 1. Power up OTG module
+	 */
+	reg_set((void __iomem *)USB2_PHY_OTG_CTRL_ADDR, rb_pu_otg, 0);
+
+	/*
+	 * 2. Set counter for 100us pulse in USB3 Host and Device
+	 * restore default burst size limit (Reference Clock 31:24)
+	 */
+	reg_set((void __iomem *)USB3_CTRPUL_VAL_REG,
+		0x8 << 24, rb_usb3_ctr_100ns);
+
+
+	/* 0xd005c300 = 0x1001 */
+	/* set PRD_TXDEEMPH (3.5db de-emph) */
+	reg_set16((void __iomem *)LANE_CFG0_ADDR(USB3), 0x1, 0xFF);
+
+	/*
+	 * unset BIT0: set Tx Electrical Idle Mode: Transmitter is in
+	 * low impedance mode during electrical idle
+	 */
+	/* unset BIT4: set G2 Tx Datapath with no Delayed Latency */
+	/* unset BIT6: set Tx Detect Rx Mode at LoZ mode */
+	reg_set16((void __iomem *)LANE_CFG1_ADDR(USB3), 0x0, 0xFFFF);
+
+
+	/* 0xd005c310 = 0x93: set Spread Spectrum Clock Enabled  */
+	reg_set16((void __iomem *)LANE_CFG4_ADDR(USB3),
+		  bf_spread_spectrum_clock_en, 0x80);
+
+	/*
+	 * set Override Margining Controls From the MAC: Use margining signals
+	 * from lane configuration
+	 */
+	reg_set16((void __iomem *)TEST_MODE_CTRL_ADDR(USB3),
+		  rb_mode_margin_override, 0xFFFF);
+
+	/* set Lane-to-Lane Bundle Clock Sampling Period = per PCLK cycles */
+	/* set Mode Clock Source = PCLK is generated from REFCLK */
+	reg_set16((void __iomem *)GLOB_CLK_SRC_LO_ADDR(USB3), 0x0, 0xFF);
+
+	/* set G2 Spread Spectrum Clock Amplitude@4K */
+	reg_set16((void __iomem *)GEN2_SETTING_2_ADDR(USB3), g2_tx_ssc_amp,
+		  0xF000);
+
+	/*
+	 * unset G3 Spread Spectrum Clock Amplitude & set G3 TX and RX Register
+	 * Master Current Select
+	 */
+	reg_set16((void __iomem *)GEN2_SETTING_3_ADDR(USB3), 0x0, 0xFFFF);
+
+	/*
+	 * 3. Check crystal jumper setting and program the Power and PLL
+	 * Control accordingly
+	 */
+	if (get_ref_clk() == 40) {
+		reg_set16((void __iomem *)PWR_PLL_CTRL_ADDR(USB3), 0xFCA3,
+			  0xFFFF); /* 40 MHz */
+	} else {
+		reg_set16((void __iomem *)PWR_PLL_CTRL_ADDR(USB3), 0xFCA2,
+			  0xFFFF); /* 25 MHz */
+	}
+
+	/*
+	 * 4. Change RX wait
+	 */
+	reg_set16((void __iomem *)PWR_MGM_TIM1_ADDR(USB3), 0x10C, 0xFFFF);
+
+	/*
+	 * 5. Enable idle sync
+	 */
+	reg_set16((void __iomem *)UNIT_CTRL_ADDR(USB3), 0x60 | rb_idle_sync_en,
+		  0xFFFF);
+
+	/*
+	 * 6. Enable the output of 500M clock
+	 */
+	reg_set16((void __iomem *)MISC_REG0_ADDR(USB3), 0xA00D | rb_clk500m_en,
+		  0xFFFF);
+
+	/*
+	 * 7. Set 20-bit data width
+	 */
+	reg_set16((void __iomem *)DIG_LB_EN_ADDR(USB3), 0x0400, 0xFFFF);
+
+	/*
+	 * 8. Override Speed_PLL value and use MAC PLL
+	 */
+	reg_set16((void __iomem *)KVCO_CAL_CTRL_ADDR(USB3),
+		  0x0040 | rb_use_max_pll_rate, 0xFFFF);
+
+	/*
+	 * 9. Check the Polarity invert bit
+	 */
+	if (invert & PHY_POLARITY_TXD_INVERT) {
+		reg_set16((void __iomem *)SYNC_PATTERN_ADDR(USB3),
+			  phy_txd_inv, 0);
+	}
+
+	if (invert & PHY_POLARITY_RXD_INVERT) {
+		reg_set16((void __iomem *)SYNC_PATTERN_ADDR(USB3),
+			  phy_rxd_inv, 0);
+	}
+
+	/*
+	 * 10. Release SW reset
+	 */
+	reg_set16((void __iomem *)GLOB_PHY_CTRL0_ADDR(USB3),
+		  rb_mode_core_clk_freq_sel | rb_mode_pipe_width_32 | 0x20,
+		  0xFFFF);
+
+	/* Wait for > 55 us to allow PCLK be enabled */
+	udelay(PLL_SET_DELAY_US);
+
+	/* Assert PCLK enabled */
+	ret = comphy_poll_reg((void *)LANE_STAT1_ADDR(USB3),	/* address */
+			      rb_txdclk_pclk_en,		/* value */
+			      rb_txdclk_pclk_en,		/* mask */
+			      PLL_LOCK_TIMEOUT,			/* timeout */
+			      POLL_16B_REG);			/* 16bit */
+	if (ret == 0)
+		printf("Failed to lock USB3 PLL\n");
+
+	/*
+	 * Set Soft ID for Host mode (Device mode works with Hard ID
+	 * detection)
+	 */
+	if (type == PHY_TYPE_USB3_HOST0) {
+		/*
+		 * set   BIT0: set ID_MODE of Host/Device = "Soft ID" (BIT1)
+		 * clear BIT1: set SOFT_ID = Host
+		 * set   BIT4: set INT_MODE = ID. Interrupt Mode: enable
+		 *             interrupt by ID instead of using both interrupts
+		 *             of HOST and Device ORed simultaneously
+		 *             INT_MODE=ID in order to avoid unexpected
+		 *             behaviour or both interrupts together
+		 */
+		reg_set((void __iomem *)USB32_CTRL_BASE,
+			usb32_ctrl_id_mode | usb32_ctrl_int_mode,
+			usb32_ctrl_id_mode | usb32_ctrl_soft_id |
+			usb32_ctrl_int_mode);
+	}
+
+	debug_exit();
+
+	return ret;
+}
+
+/*
+ * comphy_usb2_power_up
+ *
+ * return: 1 if PLL locked (OK), 0 otherwise (FAIL)
+ */
+static int comphy_usb2_power_up(u8 usb32)
+{
+	int	ret;
+
+	debug_enter();
+
+	if (usb32 != 0 && usb32 != 1) {
+		printf("invalid usb32 value: (%d), should be either 0 or 1\n",
+		       usb32);
+		debug_exit();
+		return 0;
+	}
+
+	/*
+	 * 0. Setup PLL. 40MHz clock uses defaults.
+	 *    See "PLL Settings for Typical REFCLK" table
+	 */
+	if (get_ref_clk() == 25) {
+		reg_set((void __iomem *)USB2_PHY_BASE(usb32),
+			5 | (96 << 16), 0x3F | (0xFF << 16) | (0x3 << 28));
+	}
+
+	/*
+	 * 1. PHY pull up and disable USB2 suspend
+	 */
+	reg_set((void __iomem *)USB2_PHY_CTRL_ADDR(usb32),
+		RB_USB2PHY_SUSPM(usb32) | RB_USB2PHY_PU(usb32), 0);
+
+	if (usb32 != 0) {
+		/*
+		 * 2. Power up OTG module
+		 */
+		reg_set((void __iomem *)USB2_PHY_OTG_CTRL_ADDR, rb_pu_otg, 0);
+
+		/*
+		 * 3. Configure PHY charger detection
+		 */
+		reg_set((void __iomem *)USB2_PHY_CHRGR_DET_ADDR, 0,
+			rb_cdp_en | rb_dcp_en | rb_pd_en | rb_cdp_dm_auto |
+			rb_enswitch_dp | rb_enswitch_dm | rb_pu_chrg_dtc);
+	}
+
+	/* Assert PLL calibration done */
+	ret = comphy_poll_reg((void *)USB2_PHY_CAL_CTRL_ADDR(usb32),
+			      rb_usb2phy_pllcal_done,	/* value */
+			      rb_usb2phy_pllcal_done,	/* mask */
+			      PLL_LOCK_TIMEOUT,		/* timeout */
+			      POLL_32B_REG);		/* 32bit */
+	if (ret == 0)
+		printf("Failed to end USB2 PLL calibration\n");
+
+	/* Assert impedance calibration done */
+	ret = comphy_poll_reg((void *)USB2_PHY_CAL_CTRL_ADDR(usb32),
+			      rb_usb2phy_impcal_done,	/* value */
+			      rb_usb2phy_impcal_done,	/* mask */
+			      PLL_LOCK_TIMEOUT,		/* timeout */
+			      POLL_32B_REG);		/* 32bit */
+	if (ret == 0)
+		printf("Failed to end USB2 impedance calibration\n");
+
+	/* Assert squetch calibration done */
+	ret = comphy_poll_reg((void *)USB2_PHY_RX_CHAN_CTRL1_ADDR(usb32),
+			      rb_usb2phy_sqcal_done,	/* value */
+			      rb_usb2phy_sqcal_done,	/* mask */
+			      PLL_LOCK_TIMEOUT,		/* timeout */
+			      POLL_32B_REG);		/* 32bit */
+	if (ret == 0)
+		printf("Failed to end USB2 unknown calibration\n");
+
+	/* Assert PLL is ready */
+	ret = comphy_poll_reg((void *)USB2_PHY_PLL_CTRL0_ADDR(usb32),
+			      rb_usb2phy_pll_ready,		/* value */
+			      rb_usb2phy_pll_ready,		/* mask */
+			      PLL_LOCK_TIMEOUT,		/* timeout */
+			      POLL_32B_REG);		/* 32bit */
+
+	if (ret == 0)
+		printf("Failed to lock USB2 PLL\n");
+
+	debug_exit();
+
+	return ret;
+}
+
+/*
+ * comphy_emmc_power_up
+ *
+ * return: 1 if PLL locked (OK), 0 otherwise (FAIL)
+ */
+static int comphy_emmc_power_up(void)
+{
+	debug_enter();
+
+	/*
+	 * 1. Bus power ON, Bus voltage 1.8V
+	 */
+	reg_set((void __iomem *)SDIO_HOST_CTRL1_ADDR, 0xB00, 0xF00);
+
+	/*
+	 * 2. Set FIFO parameters
+	 */
+	reg_set((void __iomem *)SDIO_SDHC_FIFO_ADDR, 0x315, 0xFFFFFFFF);
+
+	/*
+	 * 3. Set Capabilities 1_2
+	 */
+	reg_set((void __iomem *)SDIO_CAP_12_ADDR, 0x25FAC8B2, 0xFFFFFFFF);
+
+	/*
+	 * 4. Set Endian
+	 */
+	reg_set((void __iomem *)SDIO_ENDIAN_ADDR, 0x00c00000, 0);
+
+	/*
+	 * 4. Init PHY
+	 */
+	reg_set((void __iomem *)SDIO_PHY_TIMING_ADDR, 0x80000000, 0x80000000);
+	reg_set((void __iomem *)SDIO_PHY_PAD_CTRL0_ADDR, 0x50000000,
+		0xF0000000);
+
+	/*
+	 * 5. DLL reset
+	 */
+	reg_set((void __iomem *)SDIO_DLL_RST_ADDR, 0xFFFEFFFF, 0);
+	reg_set((void __iomem *)SDIO_DLL_RST_ADDR, 0x00010000, 0);
+
+	debug_exit();
+
+	return 1;
+}
+
+/*
+ * comphy_sgmii_power_up
+ *
+ * return:
+ */
+static void comphy_sgmii_phy_init(u32 lane, u32 speed)
+{
+	const int fix_arr_sz = ARRAY_SIZE(sgmii_phy_init_fix);
+	int addr, fix_idx;
+	u16 val;
+
+	fix_idx = 0;
+	for (addr = 0; addr < 512; addr++) {
+		/*
+		 * All PHY register values are defined in full for 3.125Gbps
+		 * SERDES speed. The values required for 1.25 Gbps are almost
+		 * the same and only few registers should be "fixed" in
+		 * comparison to 3.125 Gbps values. These register values are
+		 * stored in "sgmii_phy_init_fix" array.
+		 */
+		if ((speed != PHY_SPEED_1_25G) &&
+		    (sgmii_phy_init_fix[fix_idx].addr == addr)) {
+			/* Use new value */
+			val = sgmii_phy_init_fix[fix_idx].value;
+			if (fix_idx < fix_arr_sz)
+				fix_idx++;
+		} else {
+			val = sgmii_phy_init[addr];
+		}
+
+		phy_write16(lane, addr, val, 0xFFFF);
+	}
+}
+
+/*
+ * comphy_sgmii_power_up
+ *
+ * return: 1 if PLL locked (OK), 0 otherwise (FAIL)
+ */
+static int comphy_sgmii_power_up(u32 lane, u32 speed, u32 invert)
+{
+	int	ret;
+
+	debug_enter();
+
+	/*
+	 * 1. Configure PHY to SATA/SAS mode by setting pin PIN_PIPE_SEL=0
+	 */
+	reg_set((void __iomem *)COMPHY_SEL_ADDR, 0, rf_compy_select(lane));
+
+	/*
+	 * 2. Reset PHY by setting PHY input port PIN_RESET=1.
+	 * 3. Set PHY input port PIN_TX_IDLE=1, PIN_PU_IVREF=1 to keep
+	 *    PHY TXP/TXN output to idle state during PHY initialization
+	 * 4. Set PHY input port PIN_PU_PLL=0, PIN_PU_RX=0, PIN_PU_TX=0.
+	 */
+	reg_set((void __iomem *)COMPHY_PHY_CFG1_ADDR(lane),
+		rb_pin_reset_comphy | rb_pin_tx_idle | rb_pin_pu_iveref,
+		rb_pin_reset_core | rb_pin_pu_pll |
+		rb_pin_pu_rx | rb_pin_pu_tx);
+
+	/*
+	 * 5. Release reset to the PHY by setting PIN_RESET=0.
+	 */
+	reg_set((void __iomem *)COMPHY_PHY_CFG1_ADDR(lane),
+		0, rb_pin_reset_comphy);
+
+	/*
+	 * 7. Set PIN_PHY_GEN_TX[3:0] and PIN_PHY_GEN_RX[3:0] to decide
+	 *    COMPHY bit rate
+	 */
+	if (speed == PHY_SPEED_3_125G) { /* 3.125 GHz */
+		reg_set((void __iomem *)COMPHY_PHY_CFG1_ADDR(lane),
+			(0x8 << rf_gen_rx_sel_shift) |
+			(0x8 << rf_gen_tx_sel_shift),
+			rf_gen_rx_select | rf_gen_tx_select);
+
+	} else if (speed == PHY_SPEED_1_25G) { /* 1.25 GHz */
+		reg_set((void __iomem *)COMPHY_PHY_CFG1_ADDR(lane),
+			(0x6 << rf_gen_rx_sel_shift) |
+			(0x6 << rf_gen_tx_sel_shift),
+			rf_gen_rx_select | rf_gen_tx_select);
+	} else {
+		printf("Unsupported COMPHY speed!\n");
+		return 0;
+	}
+
+	/*
+	 * 8. Wait 1mS for bandgap and reference clocks to stabilize;
+	 *    then start SW programming.
+	 */
+	mdelay(10);
+
+	/* 9. Program COMPHY register PHY_MODE */
+	phy_write16(lane, PHY_PWR_PLL_CTRL_ADDR,
+		    PHY_MODE_SGMII << rf_phy_mode_shift, rf_phy_mode_mask);
+
+	/*
+	 * 10. Set COMPHY register REFCLK_SEL to select the correct REFCLK
+	 *     source
+	 */
+	phy_write16(lane, PHY_MISC_REG0_ADDR, 0, rb_ref_clk_sel);
+
+	/*
+	 * 11. Set correct reference clock frequency in COMPHY register
+	 *     REF_FREF_SEL.
+	 */
+	if (get_ref_clk() == 40) {
+		phy_write16(lane, PHY_PWR_PLL_CTRL_ADDR,
+			    0x4 << rf_ref_freq_sel_shift, rf_ref_freq_sel_mask);
+	} else {
+		/* 25MHz */
+		phy_write16(lane, PHY_PWR_PLL_CTRL_ADDR,
+			    0x1 << rf_ref_freq_sel_shift, rf_ref_freq_sel_mask);
+	}
+
+	/* 12. Program COMPHY register PHY_GEN_MAX[1:0] */
+	/*
+	 * This step is mentioned in the flow received from verification team.
+	 * However the PHY_GEN_MAX value is only meaningful for other
+	 * interfaces (not SGMII). For instance, it selects SATA speed
+	 * 1.5/3/6 Gbps or PCIe speed  2.5/5 Gbps
+	 */
+
+	/*
+	 * 13. Program COMPHY register SEL_BITS to set correct parallel data
+	 *     bus width
+	 */
+	/* 10bit */
+	phy_write16(lane, PHY_DIG_LB_EN_ADDR, 0, rf_data_width_mask);
+
+	/*
+	 * 14. As long as DFE function needs to be enabled in any mode,
+	 *     COMPHY register DFE_UPDATE_EN[5:0] shall be programmed to 0x3F
+	 *     for real chip during COMPHY power on.
+	 */
+	/*
+	 * The step 14 exists (and empty) in the original initialization flow
+	 * obtained from the verification team. According to the functional
+	 * specification DFE_UPDATE_EN already has the default value 0x3F
+	 */
+
+	/*
+	 * 15. Program COMPHY GEN registers.
+	 *     These registers should be programmed based on the lab testing
+	 *     result to achieve optimal performance. Please contact the CEA
+	 *     group to get the related GEN table during real chip bring-up.
+	 *     We only requred to run though the entire registers programming
+	 *     flow defined by "comphy_sgmii_phy_init" when the REF clock is
+	 *     40 MHz. For REF clock 25 MHz the default values stored in PHY
+	 *     registers are OK.
+	 */
+	debug("Running C-DPI phy init %s mode\n",
+	      speed == PHY_SPEED_3_125G ? "2G5" : "1G");
+	if (get_ref_clk() == 40)
+		comphy_sgmii_phy_init(lane, speed);
+
+	/*
+	 * 16. [Simulation Only] should not be used for real chip.
+	 *     By pass power up calibration by programming EXT_FORCE_CAL_DONE
+	 *     (R02h[9]) to 1 to shorten COMPHY simulation time.
+	 */
+	/*
+	 * 17. [Simulation Only: should not be used for real chip]
+	 *     Program COMPHY register FAST_DFE_TIMER_EN=1 to shorten RX
+	 *     training simulation time.
+	 */
+
+	/*
+	 * 18. Check the PHY Polarity invert bit
+	 */
+	if (invert & PHY_POLARITY_TXD_INVERT)
+		phy_write16(lane, PHY_SYNC_PATTERN_ADDR, phy_txd_inv, 0);
+
+	if (invert & PHY_POLARITY_RXD_INVERT)
+		phy_write16(lane, PHY_SYNC_PATTERN_ADDR, phy_rxd_inv, 0);
+
+	/*
+	 * 19. Set PHY input ports PIN_PU_PLL, PIN_PU_TX and PIN_PU_RX to 1
+	 *     to start PHY power up sequence. All the PHY register
+	 *     programming should be done before PIN_PU_PLL=1. There should be
+	 *     no register programming for normal PHY operation from this point.
+	 */
+	reg_set((void __iomem *)COMPHY_PHY_CFG1_ADDR(lane),
+		rb_pin_pu_pll | rb_pin_pu_rx | rb_pin_pu_tx,
+		rb_pin_pu_pll | rb_pin_pu_rx | rb_pin_pu_tx);
+
+	/*
+	 * 20. Wait for PHY power up sequence to finish by checking output ports
+	 *     PIN_PLL_READY_TX=1 and PIN_PLL_READY_RX=1.
+	 */
+	ret = comphy_poll_reg((void *)COMPHY_PHY_STAT1_ADDR(lane), /* address */
+			      rb_pll_ready_tx | rb_pll_ready_rx, /* value */
+			      rb_pll_ready_tx | rb_pll_ready_rx, /* mask */
+			      PLL_LOCK_TIMEOUT,			/* timeout */
+			      POLL_32B_REG);			/* 32bit */
+	if (ret == 0)
+		printf("Failed to lock PLL for SGMII PHY %d\n", lane);
+
+	/*
+	 * 21. Set COMPHY input port PIN_TX_IDLE=0
+	 */
+	reg_set((void __iomem *)COMPHY_PHY_CFG1_ADDR(lane),
+		0x0, rb_pin_tx_idle);
+
+	/*
+	 * 22. After valid data appear on PIN_RXDATA bus, set PIN_RX_INIT=1.
+	 *     to start RX initialization. PIN_RX_INIT_DONE will be cleared to
+	 *     0 by the PHY. After RX initialization is done, PIN_RX_INIT_DONE
+	 *     will be set to 1 by COMPHY. Set PIN_RX_INIT=0 after
+	 *     PIN_RX_INIT_DONE= 1.
+	 *     Please refer to RX initialization part for details.
+	 */
+	reg_set((void __iomem *)COMPHY_PHY_CFG1_ADDR(lane), rb_phy_rx_init,
+		0x0);
+
+	ret = comphy_poll_reg((void *)COMPHY_PHY_STAT1_ADDR(lane), /* address */
+			      rb_rx_init_done,			/* value */
+			      rb_rx_init_done,			/* mask */
+			      PLL_LOCK_TIMEOUT,		/* timeout */
+			      POLL_32B_REG);			/* 32bit */
+	if (ret == 0)
+		printf("Failed to init RX of SGMII PHY %d\n", lane);
+
+	debug_exit();
+
+	return ret;
+}
+
+void comphy_dedicated_phys_init(void)
+{
+	int node, usb32, ret = 1;
+	const void *blob = gd->fdt_blob;
+
+	debug_enter();
+
+	for (usb32 = 0; usb32 <= 1; usb32++) {
+		/*
+		 * There are 2 UTMI PHYs in this SOC.
+		 * One is independendent and one is paired with USB3 port (OTG)
+		 */
+		if (usb32 == 0) {
+			node = fdt_node_offset_by_compatible(
+				blob, -1, "marvell,armada-3700-ehci");
+		} else {
+			node = fdt_node_offset_by_compatible(
+				blob, -1, "marvell,armada3700-xhci");
+		}
+
+		if (node > 0) {
+			if (fdtdec_get_is_enabled(blob, node)) {
+				ret = comphy_usb2_power_up(usb32);
+				if (ret == 0)
+					printf("Failed to initialize UTMI PHY\n");
+				else
+					debug("UTMI PHY init succeed\n");
+			} else {
+				debug("USB%d node is disabled\n",
+				      usb32 == 0 ? 2 : 3);
+			}
+		} else {
+			debug("No USB%d node in DT\n", usb32 == 0 ? 2 : 3);
+		}
+	}
+
+	node = fdt_node_offset_by_compatible(blob, -1,
+					     "marvell,armada-3700-ahci");
+	if (node > 0) {
+		if (fdtdec_get_is_enabled(blob, node)) {
+			ret = comphy_sata_power_up();
+			if (ret == 0)
+				printf("Failed to initialize SATA PHY\n");
+			else
+				debug("SATA PHY init succeed\n");
+		} else {
+			debug("SATA node is disabled\n");
+		}
+	}  else {
+		debug("No SATA node in DT\n");
+	}
+
+	node = fdt_node_offset_by_compatible(blob, -1,
+					     "marvell,armada-3700-sdio");
+	if (node <= 0) {
+		debug("No SDIO node in DT, looking for MMC one\n");
+		node = fdt_node_offset_by_compatible(blob, -1,
+						     "marvell,xenon-sdhci");
+	}
+
+	if (node > 0) {
+		if (fdtdec_get_is_enabled(blob, node)) {
+			ret = comphy_emmc_power_up();
+			if (ret == 0)
+				printf("Failed to initialize SDIO/eMMC PHY\n");
+			else
+				debug("SDIO/eMMC PHY init succeed\n");
+		} else {
+			debug("SDIO/eMMC node is disabled\n");
+		}
+	}  else {
+		debug("No SDIO/eMMC node in DT\n");
+	}
+
+	debug_exit();
+}
+
+int comphy_a3700_init(struct chip_serdes_phy_config *chip_cfg,
+		      struct comphy_map *serdes_map)
+{
+	struct comphy_map *comphy_map;
+	u32 comphy_max_count = chip_cfg->comphy_lanes_count;
+	u32 lane, ret = 0;
+
+	debug_enter();
+
+	for (lane = 0, comphy_map = serdes_map; lane < comphy_max_count;
+	     lane++, comphy_map++) {
+		debug("Initialize serdes number %d\n", lane);
+		debug("Serdes type = 0x%x invert=%d\n",
+		      comphy_map->type, comphy_map->invert);
+
+		switch (comphy_map->type) {
+		case PHY_TYPE_UNCONNECTED:
+			continue;
+			break;
+
+		case PHY_TYPE_PEX0:
+			ret = comphy_pcie_power_up(comphy_map->speed,
+						   comphy_map->invert);
+			break;
+
+		case PHY_TYPE_USB3_HOST0:
+		case PHY_TYPE_USB3_DEVICE:
+			ret = comphy_usb3_power_up(comphy_map->type,
+						   comphy_map->speed,
+						   comphy_map->invert);
+			break;
+
+		case PHY_TYPE_SGMII0:
+		case PHY_TYPE_SGMII1:
+			ret = comphy_sgmii_power_up(lane, comphy_map->speed,
+						    comphy_map->invert);
+			break;
+
+		default:
+			debug("Unknown SerDes type, skip initialize SerDes %d\n",
+			      lane);
+			ret = 1;
+			break;
+		}
+		if (ret == 0)
+			printf("PLL is not locked - Failed to initialize lane %d\n",
+			       lane);
+	}
+
+	debug_exit();
+	return ret;
+}
diff --git a/drivers/phy/marvell/comphy_a3700.h b/drivers/phy/marvell/comphy_a3700.h
new file mode 100644
index 0000000..eb2ed7b
--- /dev/null
+++ b/drivers/phy/marvell/comphy_a3700.h
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2015-2016 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _COMPHY_A3700_H_
+#define _COMPHY_A3700_H_
+
+#include "comphy.h"
+#include "comphy_hpipe.h"
+
+#define MVEBU_REG(offs)			((uintptr_t)MVEBU_REGISTER(offs))
+
+#define DEFAULT_REFCLK_MHZ		25
+#define PLL_SET_DELAY_US		600
+#define PLL_LOCK_TIMEOUT		1000
+#define POLL_16B_REG			1
+#define POLL_32B_REG			0
+
+/*
+ * COMPHY SB definitions
+ */
+#define COMPHY_SEL_ADDR			MVEBU_REG(0x0183FC)
+#define rf_compy_select(lane)		(0x1 << (((lane) == 1) ? 4 : 0))
+
+#define COMPHY_PHY_CFG1_ADDR(lane)	MVEBU_REG(0x018300 + (lane) * 0x28)
+#define rb_pin_pu_iveref		BIT(1)
+#define rb_pin_reset_core		BIT(11)
+#define rb_pin_reset_comphy		BIT(12)
+#define rb_pin_pu_pll			BIT(16)
+#define rb_pin_pu_rx			BIT(17)
+#define rb_pin_pu_tx			BIT(18)
+#define rb_pin_tx_idle			BIT(19)
+#define rf_gen_rx_sel_shift		22
+#define rf_gen_rx_select		(0xFF << rf_gen_rx_sel_shift)
+#define rf_gen_tx_sel_shift		26
+#define rf_gen_tx_select		(0xFF << rf_gen_tx_sel_shift)
+#define rb_phy_rx_init			BIT(30)
+
+#define COMPHY_PHY_STAT1_ADDR(lane)	MVEBU_REG(0x018318 + (lane) * 0x28)
+#define rb_rx_init_done			BIT(0)
+#define rb_pll_ready_rx			BIT(2)
+#define rb_pll_ready_tx			BIT(3)
+
+/*
+ * PCIe/USB/SGMII definitions
+ */
+#define PCIE_BASE			MVEBU_REG(0x070000)
+#define PCIETOP_BASE			MVEBU_REG(0x080000)
+#define PCIE_RAMBASE			MVEBU_REG(0x08C000)
+#define PCIEPHY_BASE			MVEBU_REG(0x01F000)
+#define PCIEPHY_SHFT			2
+
+#define USB32_BASE			MVEBU_REG(0x050000) /* usb3 device */
+#define USB32H_BASE			MVEBU_REG(0x058000) /* usb3 host */
+#define USB3PHY_BASE			MVEBU_REG(0x05C000)
+#define USB2PHY_BASE			MVEBU_REG(0x05D000)
+#define USB2PHY2_BASE			MVEBU_REG(0x05F000)
+#define USB32_CTRL_BASE			MVEBU_REG(0x05D800)
+#define USB3PHY_SHFT			2
+
+#define SGMIIPHY_BASE(l)	(l == 1 ? USB3PHY_BASE : PCIEPHY_BASE)
+#define SGMIIPHY_ADDR(l, a)	(((a & 0x00007FF) * 2) | SGMIIPHY_BASE(l))
+
+#define phy_read16(l, a)	read16((void __iomem *)SGMIIPHY_ADDR(l, a))
+#define phy_write16(l, a, data, mask)	\
+	reg_set16((void __iomem *)SGMIIPHY_ADDR(l, a), data, mask)
+
+/* units */
+#define PCIE				1
+#define USB3				2
+
+#define PHY_BASE(unit)		((unit == PCIE) ? PCIEPHY_BASE : USB3PHY_BASE)
+#define PHY_SHFT(unit)		((unit == PCIE) ? PCIEPHY_SHFT : USB3PHY_SHFT)
+
+/* bit definition for USB32_CTRL_BASE (USB32 Control Mode) */
+#define usb32_ctrl_id_mode		BIT(0)
+#define usb32_ctrl_soft_id		BIT(1)
+#define usb32_ctrl_int_mode		BIT(4)
+
+
+#define PHY_PWR_PLL_CTRL_ADDR	0x01	/* for phy_read16 and phy_write16 */
+#define PWR_PLL_CTRL_ADDR(unit)		\
+	(PHY_PWR_PLL_CTRL_ADDR * PHY_SHFT(unit) + PHY_BASE(unit))
+#define rf_phy_mode_shift		5
+#define rf_phy_mode_mask		(0x7 << rf_phy_mode_shift)
+#define rf_ref_freq_sel_shift		0
+#define rf_ref_freq_sel_mask		(0x1F << rf_ref_freq_sel_shift)
+#define PHY_MODE_SGMII			0x4
+
+/* for phy_read16 and phy_write16 */
+#define PHY_REG_KVCO_CAL_CTRL_ADDR	0x02
+#define KVCO_CAL_CTRL_ADDR(unit)	\
+	(PHY_REG_KVCO_CAL_CTRL_ADDR * PHY_SHFT(unit) + PHY_BASE(unit))
+#define rb_use_max_pll_rate		BIT(12)
+#define rb_force_calibration_done	BIT(9)
+
+/* for phy_read16 and phy_write16 */
+#define PHY_DIG_LB_EN_ADDR		0x23
+#define DIG_LB_EN_ADDR(unit)		\
+	(PHY_DIG_LB_EN_ADDR * PHY_SHFT(unit) + PHY_BASE(unit))
+#define rf_data_width_shift		10
+#define rf_data_width_mask		(0x3 << rf_data_width_shift)
+
+/* for phy_read16 and phy_write16 */
+#define PHY_SYNC_PATTERN_ADDR		0x24
+#define SYNC_PATTERN_ADDR(unit)		\
+	(PHY_SYNC_PATTERN_ADDR * PHY_SHFT(unit) + PHY_BASE(unit))
+#define phy_txd_inv			BIT(10)
+#define phy_rxd_inv			BIT(11)
+
+/* for phy_read16 and phy_write16 */
+#define PHY_REG_UNIT_CTRL_ADDR		0x48
+#define UNIT_CTRL_ADDR(unit)		\
+	(PHY_REG_UNIT_CTRL_ADDR * PHY_SHFT(unit) + PHY_BASE(unit))
+#define rb_idle_sync_en			BIT(12)
+
+/* for phy_read16 and phy_write16 */
+#define PHY_REG_GEN2_SETTINGS_2		0x3e
+#define GEN2_SETTING_2_ADDR(unit)	\
+	(PHY_REG_GEN2_SETTINGS_2 * PHY_SHFT(unit) + PHY_BASE(unit))
+#define g2_tx_ssc_amp			BIT(14)
+
+/* for phy_read16 and phy_write16 */
+#define PHY_REG_GEN2_SETTINGS_3		0x3f
+#define GEN2_SETTING_3_ADDR(unit)	\
+	(PHY_REG_GEN2_SETTINGS_3 * PHY_SHFT(unit) + PHY_BASE(unit))
+
+/* for phy_read16 and phy_write16 */
+#define PHY_MISC_REG0_ADDR		0x4f
+#define MISC_REG0_ADDR(unit)		\
+	(PHY_MISC_REG0_ADDR * PHY_SHFT(unit) + PHY_BASE(unit))
+#define rb_clk100m_125m_en		BIT(4)
+#define rb_clk500m_en			BIT(7)
+#define rb_ref_clk_sel			BIT(10)
+
+/* for phy_read16 and phy_write16 */
+#define PHY_REG_IFACE_REF_CLK_CTRL_ADDR		0x51
+#define UNIT_IFACE_REF_CLK_CTRL_ADDR(unit)	\
+	(PHY_REG_IFACE_REF_CLK_CTRL_ADDR * PHY_SHFT(unit) + PHY_BASE(unit))
+#define rb_ref1m_gen_div_force		BIT(8)
+#define rf_ref1m_gen_div_value_shift	0
+#define rf_ref1m_gen_div_value_mask	(0xFF << rf_ref1m_gen_div_value_shift)
+
+/* for phy_read16 and phy_write16 */
+#define PHY_REG_ERR_CNT_CONST_CTRL_ADDR	0x6A
+#define UNIT_ERR_CNT_CONST_CTRL_ADDR(unit) \
+	(PHY_REG_ERR_CNT_CONST_CTRL_ADDR * PHY_SHFT(unit) + PHY_BASE(unit))
+#define rb_fast_dfe_enable		BIT(13)
+
+#define MISC_REG1_ADDR(u)		(0x73 * PHY_SHFT(u) + PHY_BASE(u))
+#define bf_sel_bits_pcie_force		BIT(15)
+
+#define LANE_CFG0_ADDR(u)		(0x180 * PHY_SHFT(u) + PHY_BASE(u))
+#define bf_use_max_pll_rate		BIT(9)
+#define LANE_CFG1_ADDR(u)		(0x181 * PHY_SHFT(u) + PHY_BASE(u))
+#define bf_use_max_pll_rate		BIT(9)
+/* 0x5c310 = 0x93 (set BIT7) */
+#define LANE_CFG4_ADDR(u)		(0x188 * PHY_SHFT(u) + PHY_BASE(u))
+#define bf_spread_spectrum_clock_en	BIT(7)
+
+#define LANE_STAT1_ADDR(u)		(0x183 * PHY_SHFT(u) + PHY_BASE(u))
+#define rb_txdclk_pclk_en		BIT(0)
+
+#define GLOB_PHY_CTRL0_ADDR(u)		(0x1c1 * PHY_SHFT(u) + PHY_BASE(u))
+#define bf_soft_rst			BIT(0)
+#define bf_mode_refdiv			0x30
+#define rb_mode_core_clk_freq_sel	BIT(9)
+#define rb_mode_pipe_width_32		BIT(3)
+
+#define TEST_MODE_CTRL_ADDR(u)		(0x1c2 * PHY_SHFT(u) + PHY_BASE(u))
+#define rb_mode_margin_override		BIT(2)
+
+#define GLOB_CLK_SRC_LO_ADDR(u)		(0x1c3 * PHY_SHFT(u) + PHY_BASE(u))
+#define bf_cfg_sel_20b			BIT(15)
+
+#define PWR_MGM_TIM1_ADDR(u)		(0x1d0 * PHY_SHFT(u) + PHY_BASE(u))
+
+#define PHY_REF_CLK_ADDR		(0x4814 + PCIE_BASE)
+
+#define USB3_CTRPUL_VAL_REG		(0x20 + USB32_BASE)
+#define USB3H_CTRPUL_VAL_REG		(0x3454 + USB32H_BASE)
+#define rb_usb3_ctr_100ns		0xff000000
+
+#define USB2_OTG_PHY_CTRL_ADDR		(0x820 + USB2PHY_BASE)
+#define rb_usb2phy_suspm		BIT(14)
+#define rb_usb2phy_pu			BIT(0)
+
+#define USB2_PHY_OTG_CTRL_ADDR		(0x34 + USB2PHY_BASE)
+#define rb_pu_otg			BIT(4)
+
+#define USB2_PHY_CHRGR_DET_ADDR		(0x38 + USB2PHY_BASE)
+#define rb_cdp_en			BIT(2)
+#define rb_dcp_en			BIT(3)
+#define rb_pd_en			BIT(4)
+#define rb_pu_chrg_dtc			BIT(5)
+#define rb_cdp_dm_auto			BIT(7)
+#define rb_enswitch_dp			BIT(12)
+#define rb_enswitch_dm			BIT(13)
+
+#define USB2_CAL_CTRL_ADDR		(0x8 + USB2PHY_BASE)
+#define rb_usb2phy_pllcal_done		BIT(31)
+#define rb_usb2phy_impcal_done		BIT(23)
+
+#define USB2_PLL_CTRL0_ADDR		(0x0 + USB2PHY_BASE)
+#define rb_usb2phy_pll_ready		BIT(31)
+
+#define USB2_RX_CHAN_CTRL1_ADDR		(0x18 + USB2PHY_BASE)
+#define rb_usb2phy_sqcal_done		BIT(31)
+
+#define USB2_PHY2_CTRL_ADDR		(0x804 + USB2PHY2_BASE)
+#define rb_usb2phy2_suspm		BIT(7)
+#define rb_usb2phy2_pu			BIT(0)
+#define USB2_PHY2_CAL_CTRL_ADDR		(0x8 + USB2PHY2_BASE)
+#define USB2_PHY2_PLL_CTRL0_ADDR	(0x0 + USB2PHY2_BASE)
+#define USB2_PHY2_RX_CHAN_CTRL1_ADDR	(0x18 + USB2PHY2_BASE)
+
+#define USB2_PHY_BASE(usb32)	(usb32 == 0 ? USB2PHY2_BASE : USB2PHY_BASE)
+#define USB2_PHY_CTRL_ADDR(usb32) \
+	(usb32 == 0 ? USB2_PHY2_CTRL_ADDR : USB2_OTG_PHY_CTRL_ADDR)
+#define RB_USB2PHY_SUSPM(usb32) \
+	(usb32 == 0 ? rb_usb2phy2_suspm : rb_usb2phy_suspm)
+#define RB_USB2PHY_PU(usb32) \
+	(usb32 == 0 ? rb_usb2phy2_pu : rb_usb2phy_pu)
+#define USB2_PHY_CAL_CTRL_ADDR(usb32) \
+	(usb32 == 0 ? USB2_PHY2_CAL_CTRL_ADDR : USB2_CAL_CTRL_ADDR)
+#define USB2_PHY_RX_CHAN_CTRL1_ADDR(usb32) \
+	(usb32 == 0 ? USB2_PHY2_RX_CHAN_CTRL1_ADDR : USB2_RX_CHAN_CTRL1_ADDR)
+#define USB2_PHY_PLL_CTRL0_ADDR(usb32) \
+	(usb32 == 0 ? USB2_PHY2_PLL_CTRL0_ADDR : USB2_PLL_CTRL0_ADDR)
+
+/*
+ * SATA definitions
+ */
+#define AHCI_BASE			MVEBU_REG(0xE0000)
+
+#define rh_vsreg_addr			(AHCI_BASE + 0x178)
+#define rh_vsreg_data			(AHCI_BASE + 0x17C)
+#define rh_vs0_a			(AHCI_BASE + 0xA0)
+#define rh_vs0_d			(AHCI_BASE + 0xA4)
+
+#define vphy_sync_pattern_reg		0x224
+#define bs_txd_inv			BIT(10)
+#define bs_rxd_inv			BIT(11)
+
+#define vphy_loopback_reg0		0x223
+#define bs_phyintf_40bit		0x0C00
+#define bs_pll_ready_tx			0x10
+
+#define vphy_power_reg0			0x201
+
+#define vphy_calctl_reg			0x202
+#define bs_max_pll_rate			BIT(12)
+
+#define vphy_reserve_reg		0x0e
+#define bs_phyctrl_frm_pin		BIT(13)
+
+#define vsata_ctrl_reg			0x00
+#define bs_phy_pu_pll			BIT(6)
+
+/*
+ * SDIO/eMMC definitions
+ */
+#define SDIO_BASE			MVEBU_REG(0xD8000)
+
+#define SDIO_HOST_CTRL1_ADDR		(SDIO_BASE + 0x28)
+#define SDIO_SDHC_FIFO_ADDR		(SDIO_BASE + 0x12C)
+#define SDIO_CAP_12_ADDR		(SDIO_BASE + 0x40)
+#define SDIO_ENDIAN_ADDR		(SDIO_BASE + 0x1A4)
+#define SDIO_PHY_TIMING_ADDR		(SDIO_BASE + 0x170)
+#define SDIO_PHY_PAD_CTRL0_ADDR		(SDIO_BASE + 0x178)
+#define SDIO_DLL_RST_ADDR		(SDIO_BASE + 0x148)
+
+#endif /* _COMPHY_A3700_H_ */
diff --git a/drivers/phy/marvell/comphy_core.c b/drivers/phy/marvell/comphy_core.c
new file mode 100644
index 0000000..519bc16
--- /dev/null
+++ b/drivers/phy/marvell/comphy_core.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2015-2016 Marvell International Ltd.
+ *
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+
+#include "comphy.h"
+
+#define COMPHY_MAX_CHIP 4
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static char *get_speed_string(u32 speed)
+{
+	char *speed_strings[] = {"1.25 Gbps", "1.5 Gbps", "2.5 Gbps",
+				 "3.0 Gbps", "3.125 Gbps", "5 Gbps", "6 Gbps",
+				 "6.25 Gbps", "10.31 Gbps" };
+
+	if (speed < 0 || speed > PHY_SPEED_MAX)
+		return "invalid";
+
+	return speed_strings[speed];
+}
+
+static char *get_type_string(u32 type)
+{
+	char *type_strings[] = {"UNCONNECTED", "PEX0", "PEX1", "PEX2", "PEX3",
+				"SATA0", "SATA1", "SATA2", "SATA3", "SGMII0",
+				"SGMII1", "SGMII2", "SGMII3", "QSGMII",
+				"USB3_HOST0", "USB3_HOST1", "USB3_DEVICE",
+				"XAUI0", "XAUI1", "XAUI2", "XAUI3",
+				"RXAUI0", "RXAUI1", "KR"};
+
+	if (type < 0 || type > PHY_TYPE_MAX)
+		return "invalid";
+
+	return type_strings[type];
+}
+
+void reg_set(void __iomem *addr, u32 data, u32 mask)
+{
+	debug("Write to address = %#010lx, data = %#010x (mask = %#010x) - ",
+	      (unsigned long)addr, data, mask);
+	debug("old value = %#010x ==> ", readl(addr));
+	reg_set_silent(addr, data, mask);
+	debug("new value %#010x\n", readl(addr));
+}
+
+void reg_set_silent(void __iomem *addr, u32 data, u32 mask)
+{
+	u32 reg_data;
+
+	reg_data = readl(addr);
+	reg_data &= ~mask;
+	reg_data |= data;
+	writel(reg_data, addr);
+}
+
+void reg_set16(void __iomem *addr, u16 data, u16 mask)
+{
+	debug("Write to address = %#010lx, data = %#06x (mask = %#06x) - ",
+	      (unsigned long)addr, data, mask);
+	debug("old value = %#06x ==> ", readw(addr));
+	reg_set_silent16(addr, data, mask);
+	debug("new value %#06x\n", readw(addr));
+}
+
+void reg_set_silent16(void __iomem *addr, u16 data, u16 mask)
+{
+	u16 reg_data;
+
+	reg_data = readw(addr);
+	reg_data &= ~mask;
+	reg_data |= data;
+	writew(reg_data, addr);
+}
+
+void comphy_print(struct chip_serdes_phy_config *chip_cfg,
+		  struct comphy_map *comphy_map_data)
+{
+	u32 lane;
+
+	for (lane = 0; lane < chip_cfg->comphy_lanes_count;
+	     lane++, comphy_map_data++) {
+		if (comphy_map_data->type == PHY_TYPE_UNCONNECTED)
+			continue;
+
+		if (comphy_map_data->speed == PHY_SPEED_INVALID) {
+			printf("Comphy-%d: %-13s\n", lane,
+			       get_type_string(comphy_map_data->type));
+		} else {
+			printf("Comphy-%d: %-13s %-10s\n", lane,
+			       get_type_string(comphy_map_data->type),
+			       get_speed_string(comphy_map_data->speed));
+		}
+	}
+}
+
+static int comphy_probe(struct udevice *dev)
+{
+	const void *blob = gd->fdt_blob;
+	int node = dev->of_offset;
+	struct chip_serdes_phy_config *chip_cfg = dev_get_priv(dev);
+	struct comphy_map comphy_map_data[MAX_LANE_OPTIONS];
+	int subnode;
+	int lane;
+
+	/* Save base addresses for later use */
+	chip_cfg->comphy_base_addr = (void *)dev_get_addr_index(dev, 0);
+	if (IS_ERR(chip_cfg->comphy_base_addr))
+		return PTR_ERR(chip_cfg->comphy_base_addr);
+
+	chip_cfg->hpipe3_base_addr = (void *)dev_get_addr_index(dev, 1);
+	if (IS_ERR(chip_cfg->hpipe3_base_addr))
+		return PTR_ERR(chip_cfg->hpipe3_base_addr);
+
+	chip_cfg->comphy_lanes_count = fdtdec_get_int(blob, node,
+						      "max-lanes", 0);
+	if (chip_cfg->comphy_lanes_count <= 0) {
+		dev_err(&dev->dev, "comphy max lanes is wrong\n");
+		return -EINVAL;
+	}
+
+	chip_cfg->comphy_mux_bitcount = fdtdec_get_int(blob, node,
+						       "mux-bitcount", 0);
+	if (chip_cfg->comphy_mux_bitcount <= 0) {
+		dev_err(&dev->dev, "comphy mux bit count is wrong\n");
+		return -EINVAL;
+	}
+
+	if (of_device_is_compatible(dev, "marvell,comphy-armada-3700"))
+		chip_cfg->ptr_comphy_chip_init = comphy_a3700_init;
+
+	/*
+	 * Bail out if no chip_init function is defined, e.g. no
+	 * compatible node is found
+	 */
+	if (!chip_cfg->ptr_comphy_chip_init) {
+		dev_err(&dev->dev, "comphy: No compatible DT node found\n");
+		return -ENODEV;
+	}
+
+	lane = 0;
+	fdt_for_each_subnode(blob, subnode, node) {
+		/* Skip disabled ports */
+		if (!fdtdec_get_is_enabled(blob, subnode))
+			continue;
+
+		comphy_map_data[lane].speed = fdtdec_get_int(
+			blob, subnode, "phy-speed", PHY_TYPE_INVALID);
+		comphy_map_data[lane].type = fdtdec_get_int(
+			blob, subnode, "phy-type", PHY_SPEED_INVALID);
+		comphy_map_data[lane].invert = fdtdec_get_int(
+			blob, subnode, "phy-invert", PHY_POLARITY_NO_INVERT);
+		comphy_map_data[lane].clk_src = fdtdec_get_bool(blob, subnode,
+								"clk-src");
+		if (comphy_map_data[lane].type == PHY_TYPE_INVALID) {
+			printf("no phy type for lane %d, setting lane as unconnected\n",
+			       lane + 1);
+		}
+
+		lane++;
+	}
+
+	/* Save comphy index for MultiCP devices (A8K) */
+	chip_cfg->comphy_index = dev->seq;
+	/* PHY power UP sequence */
+	chip_cfg->ptr_comphy_chip_init(chip_cfg, comphy_map_data);
+	/* PHY print SerDes status */
+	comphy_print(chip_cfg, comphy_map_data);
+
+	/* Initialize dedicated PHYs (not muxed SerDes lanes) */
+	comphy_dedicated_phys_init();
+
+	return 0;
+}
+
+static const struct udevice_id comphy_ids[] = {
+	{ .compatible = "marvell,mvebu-comphy" },
+	{ }
+};
+
+U_BOOT_DRIVER(mvebu_comphy) = {
+	.name	= "mvebu_comphy",
+	.id	= UCLASS_MISC,
+	.of_match = comphy_ids,
+	.probe	= comphy_probe,
+	.priv_auto_alloc_size = sizeof(struct chip_serdes_phy_config),
+};
diff --git a/drivers/phy/marvell/comphy_hpipe.h b/drivers/phy/marvell/comphy_hpipe.h
new file mode 100644
index 0000000..0c9b500
--- /dev/null
+++ b/drivers/phy/marvell/comphy_hpipe.h
@@ -0,0 +1,382 @@
+/*
+ * Copyright (C) 2015-2016 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _COMPHY_HPIPE_H_
+#define _COMPHY_HPIPE_H_
+
+/* SerDes IP register */
+#define SD_EXTERNAL_CONFIG0_REG			0
+#define SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET	1
+#define SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK	\
+	(1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET)
+#define SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET 3
+#define SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK	\
+	(0xf << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET)
+#define SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET 7
+#define SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK	\
+	(0xf << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET)
+#define SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET	11
+#define SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK	\
+	(1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET)
+#define SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET	12
+#define SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK	\
+	(1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET)
+#define SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET 14
+#define SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK	\
+	(1 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET)
+#define SD_EXTERNAL_CONFIG0_MEDIA_MODE_OFFSET	15
+#define SD_EXTERNAL_CONFIG0_MEDIA_MODE_MASK	\
+	(0x1 << SD_EXTERNAL_CONFIG0_MEDIA_MODE_OFFSET)
+
+#define SD_EXTERNAL_CONFIG1_REG			0x4
+#define SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET	3
+#define SD_EXTERNAL_CONFIG1_RESET_IN_MASK	\
+	(0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET)
+#define SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET	4
+#define SD_EXTERNAL_CONFIG1_RX_INIT_MASK	\
+	(0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET)
+#define SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET	5
+#define SD_EXTERNAL_CONFIG1_RESET_CORE_MASK	\
+	(0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET)
+#define SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET	6
+#define SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK	\
+	(0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET)
+
+#define SD_EXTERNAL_CONFIG2_REG			0x8
+#define SD_EXTERNAL_CONFIG2_PIN_DFE_EN_OFFSET	4
+#define SD_EXTERNAL_CONFIG2_PIN_DFE_EN_MASK	\
+	(0x1 << SD_EXTERNAL_CONFIG2_PIN_DFE_EN_OFFSET)
+
+#define SD_EXTERNAL_STATUS0_REG			0x18
+#define SD_EXTERNAL_STATUS0_PLL_TX_OFFSET	2
+#define SD_EXTERNAL_STATUS0_PLL_TX_MASK		\
+	(0x1 << SD_EXTERNAL_STATUS0_PLL_TX_OFFSET)
+#define SD_EXTERNAL_STATUS0_PLL_RX_OFFSET	3
+#define SD_EXTERNAL_STATUS0_PLL_RX_MASK		\
+	(0x1 << SD_EXTERNAL_STATUS0_PLL_RX_OFFSET)
+#define SD_EXTERNAL_STATUS0_RX_INIT_OFFSET	4
+#define SD_EXTERNAL_STATUS0_RX_INIT_MASK	\
+	(0x1 << SD_EXTERNAL_STATUS0_RX_INIT_OFFSET)
+#define SD_EXTERNAL_STATUS0_RF_RESET_IN_OFFSET	6
+#define SD_EXTERNAL_STATUS0_RF_RESET_IN_MASK	\
+	(0x1 << SD_EXTERNAL_STATUS0_RF_RESET_IN_OFFSET)
+
+/* HPIPE register */
+#define HPIPE_PWR_PLL_REG			0x4
+#define HPIPE_PWR_PLL_REF_FREQ_OFFSET		0
+#define HPIPE_PWR_PLL_REF_FREQ_MASK		\
+	(0x1f << HPIPE_PWR_PLL_REF_FREQ_OFFSET)
+#define HPIPE_PWR_PLL_PHY_MODE_OFFSET		5
+#define HPIPE_PWR_PLL_PHY_MODE_MASK		\
+	(0x7 << HPIPE_PWR_PLL_PHY_MODE_OFFSET)
+
+#define HPIPE_KVCO_CALIB_CTRL_REG		0x8
+#define HPIPE_KVCO_CALIB_CTRL_MAX_PLL_OFFSET	12
+#define HPIPE_KVCO_CALIB_CTRL_MAX_PLL_MASK	\
+	(0x1 << HPIPE_KVCO_CALIB_CTRL_MAX_PLL_OFFSET)
+
+#define HPIPE_SQUELCH_FFE_SETTING_REG           0x018
+
+#define HPIPE_DFE_REG0				0x01C
+#define HPIPE_DFE_RES_FORCE_OFFSET		15
+#define HPIPE_DFE_RES_FORCE_MASK		\
+	(0x1 << HPIPE_DFE_RES_FORCE_OFFSET)
+
+#define HPIPE_DFE_F3_F5_REG			0x028
+#define HPIPE_DFE_F3_F5_DFE_EN_OFFSET		14
+#define HPIPE_DFE_F3_F5_DFE_EN_MASK		\
+	(0x1 << HPIPE_DFE_F3_F5_DFE_EN_OFFSET)
+#define HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET		15
+#define HPIPE_DFE_F3_F5_DFE_CTRL_MASK		\
+	(0x1 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET)
+
+#define HPIPE_G1_SET_0_REG			0x034
+#define HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET	7
+#define HPIPE_G1_SET_0_G1_TX_EMPH1_MASK		\
+	(0xf << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET)
+
+#define HPIPE_G1_SET_1_REG			0x038
+#define HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET	0
+#define HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK	\
+	(0x7 << HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET)
+#define HPIPE_G1_SET_1_G1_RX_SELMUPP_OFFSET	3
+#define HPIPE_G1_SET_1_G1_RX_SELMUPP_MASK	\
+	(0x7 << HPIPE_G1_SET_1_G1_RX_SELMUPP_OFFSET)
+#define HPIPE_G1_SET_1_G1_RX_DFE_EN_OFFSET	10
+#define HPIPE_G1_SET_1_G1_RX_DFE_EN_MASK	\
+	(0x1 << HPIPE_G1_SET_1_G1_RX_DFE_EN_OFFSET)
+
+#define HPIPE_G2_SETTINGS_1_REG			0x040
+
+#define HPIPE_G3_SETTINGS_1_REG			0x048
+#define HPIPE_G3_RX_SELMUPI_OFFSET		0
+#define HPIPE_G3_RX_SELMUPI_MASK		\
+	(0x7 << HPIPE_G3_RX_SELMUPI_OFFSET)
+#define HPIPE_G3_RX_SELMUPF_OFFSET		3
+#define HPIPE_G3_RX_SELMUPF_MASK		\
+	(0x7 << HPIPE_G3_RX_SELMUPF_OFFSET)
+#define HPIPE_G3_SETTING_BIT_OFFSET		13
+#define HPIPE_G3_SETTING_BIT_MASK		\
+	(0x1 << HPIPE_G3_SETTING_BIT_OFFSET)
+
+#define HPIPE_LOOPBACK_REG			0x08c
+#define HPIPE_LOOPBACK_SEL_OFFSET		1
+#define HPIPE_LOOPBACK_SEL_MASK			\
+	(0x7 << HPIPE_LOOPBACK_SEL_OFFSET)
+
+#define HPIPE_SYNC_PATTERN_REG                  0x090
+
+#define HPIPE_INTERFACE_REG			0x94
+#define HPIPE_INTERFACE_GEN_MAX_OFFSET		10
+#define HPIPE_INTERFACE_GEN_MAX_MASK		\
+	(0x3 << HPIPE_INTERFACE_GEN_MAX_OFFSET)
+#define HPIPE_INTERFACE_LINK_TRAIN_OFFSET	14
+#define HPIPE_INTERFACE_LINK_TRAIN_MASK		\
+	(0x1 << HPIPE_INTERFACE_LINK_TRAIN_OFFSET)
+
+#define HPIPE_ISOLATE_MODE_REG			0x98
+#define HPIPE_ISOLATE_MODE_GEN_RX_OFFSET	0
+#define HPIPE_ISOLATE_MODE_GEN_RX_MASK		\
+	(0xf << HPIPE_ISOLATE_MODE_GEN_RX_OFFSET)
+#define HPIPE_ISOLATE_MODE_GEN_TX_OFFSET	4
+#define HPIPE_ISOLATE_MODE_GEN_TX_MASK		\
+	(0xf << HPIPE_ISOLATE_MODE_GEN_TX_OFFSET)
+
+#define HPIPE_VTHIMPCAL_CTRL_REG                0x104
+
+#define HPIPE_PCIE_REG0                         0x120
+#define HPIPE_PCIE_IDLE_SYNC_OFFSET		12
+#define HPIPE_PCIE_IDLE_SYNC_MASK		\
+	(0x1 << HPIPE_PCIE_IDLE_SYNC_OFFSET)
+#define HPIPE_PCIE_SEL_BITS_OFFSET		13
+#define HPIPE_PCIE_SEL_BITS_MASK		\
+	(0x3 << HPIPE_PCIE_SEL_BITS_OFFSET)
+
+#define HPIPE_LANE_ALIGN_REG			0x124
+#define HPIPE_LANE_ALIGN_OFF_OFFSET		12
+#define HPIPE_LANE_ALIGN_OFF_MASK		\
+	(0x1 << HPIPE_LANE_ALIGN_OFF_OFFSET)
+
+#define HPIPE_MISC_REG				0x13C
+#define HPIPE_MISC_CLK100M_125M_OFFSET		4
+#define HPIPE_MISC_CLK100M_125M_MASK		\
+	(0x1 << HPIPE_MISC_CLK100M_125M_OFFSET)
+#define HPIPE_MISC_TXDCLK_2X_OFFSET		6
+#define HPIPE_MISC_TXDCLK_2X_MASK		\
+	(0x1 << HPIPE_MISC_TXDCLK_2X_OFFSET)
+#define HPIPE_MISC_CLK500_EN_OFFSET		7
+#define HPIPE_MISC_CLK500_EN_MASK		\
+	(0x1 << HPIPE_MISC_CLK500_EN_OFFSET)
+#define HPIPE_MISC_REFCLK_SEL_OFFSET		10
+#define HPIPE_MISC_REFCLK_SEL_MASK		\
+	(0x1 << HPIPE_MISC_REFCLK_SEL_OFFSET)
+
+#define HPIPE_RX_CONTROL_1_REG			0x140
+#define HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET	11
+#define HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK	\
+	(0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET)
+#define HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET	12
+#define HPIPE_RX_CONTROL_1_CLK8T_EN_MASK	\
+	(0x1 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET)
+
+#define HPIPE_PWR_CTR_REG			0x148
+#define HPIPE_PWR_CTR_RST_DFE_OFFSET		0
+#define HPIPE_PWR_CTR_RST_DFE_MASK		\
+	(0x1 << HPIPE_PWR_CTR_RST_DFE_OFFSET)
+#define HPIPE_PWR_CTR_SFT_RST_OFFSET		10
+#define HPIPE_PWR_CTR_SFT_RST_MASK		\
+	(0x1 << HPIPE_PWR_CTR_SFT_RST_OFFSET)
+
+#define HPIPE_PLLINTP_REG1			0x150
+
+#define HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG	0x16C
+#define HPIPE_SMAPLER_OFFSET			12
+#define HPIPE_SMAPLER_MASK			\
+	(0x1 << HPIPE_SMAPLER_OFFSET)
+
+#define HPIPE_PWR_CTR_DTL_REG			0x184
+#define HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET	2
+#define HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK		\
+	(0x1 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET)
+
+#define HPIPE_RX_REG3				0x188
+
+#define HPIPE_TX_TRAIN_CTRL_0_REG		0x268
+#define HPIPE_TX_TRAIN_P2P_HOLD_OFFSET		15
+#define HPIPE_TX_TRAIN_P2P_HOLD_MASK		\
+	(0x1 << HPIPE_TX_TRAIN_P2P_HOLD_OFFSET)
+
+#define HPIPE_TX_TRAIN_CTRL_REG			0x26C
+#define HPIPE_TX_TRAIN_CTRL_G1_OFFSET		0
+#define HPIPE_TX_TRAIN_CTRL_G1_MASK		\
+	(0x1 << HPIPE_TX_TRAIN_CTRL_G1_OFFSET)
+#define HPIPE_TX_TRAIN_CTRL_GN1_OFFSET		1
+#define HPIPE_TX_TRAIN_CTRL_GN1_MASK		\
+	(0x1 << HPIPE_TX_TRAIN_CTRL_GN1_OFFSET)
+#define HPIPE_TX_TRAIN_CTRL_G0_OFFSET		2
+#define HPIPE_TX_TRAIN_CTRL_G0_MASK		\
+	(0x1 << HPIPE_TX_TRAIN_CTRL_G0_OFFSET)
+
+#define HPIPE_TX_TRAIN_CTRL_4_REG		0x278
+#define HPIPE_TRX_TRAIN_TIMER_OFFSET		0
+#define HPIPE_TRX_TRAIN_TIMER_MASK		\
+	(0x3FF << HPIPE_TRX_TRAIN_TIMER_OFFSET)
+
+#define HPIPE_PCIE_REG1				0x288
+#define HPIPE_PCIE_REG3				0x290
+
+#define HPIPE_TX_TRAIN_CTRL_5_REG		0x2A4
+#define HPIPE_TX_TRAIN_START_SQ_EN_OFFSET	11
+#define HPIPE_TX_TRAIN_START_SQ_EN_MASK		\
+	(0x1 << HPIPE_TX_TRAIN_START_SQ_EN_OFFSET)
+#define HPIPE_TX_TRAIN_START_FRM_DET_EN_OFFSET	12
+#define HPIPE_TX_TRAIN_START_FRM_DET_EN_MASK	\
+	(0x1 << HPIPE_TX_TRAIN_START_FRM_DET_EN_OFFSET)
+#define HPIPE_TX_TRAIN_START_FRM_LOCK_EN_OFFSET	13
+#define HPIPE_TX_TRAIN_START_FRM_LOCK_EN_MASK	\
+	(0x1 << HPIPE_TX_TRAIN_START_FRM_LOCK_EN_OFFSET)
+#define HPIPE_TX_TRAIN_WAIT_TIME_EN_OFFSET	14
+#define HPIPE_TX_TRAIN_WAIT_TIME_EN_MASK	\
+	(0x1 << HPIPE_TX_TRAIN_WAIT_TIME_EN_OFFSET)
+
+#define HPIPE_TX_TRAIN_REG			0x31C
+#define HPIPE_TX_TRAIN_CHK_INIT_OFFSET		4
+#define HPIPE_TX_TRAIN_CHK_INIT_MASK		\
+	(0x1 << HPIPE_TX_TRAIN_CHK_INIT_OFFSET)
+#define HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_OFFSET	7
+#define HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_MASK	\
+	(0x1 << HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_OFFSET)
+
+#define HPIPE_TX_TRAIN_CTRL_11_REG		0x438
+#define HPIPE_TX_STATUS_CHECK_MODE_OFFSET	6
+#define HPIPE_TX_TX_STATUS_CHECK_MODE_MASK	\
+	(0x1 << HPIPE_TX_STATUS_CHECK_MODE_OFFSET)
+#define HPIPE_TX_NUM_OF_PRESET_OFFSET		10
+#define HPIPE_TX_NUM_OF_PRESET_MASK		\
+	(0x7 << HPIPE_TX_NUM_OF_PRESET_OFFSET)
+#define HPIPE_TX_SWEEP_PRESET_EN_OFFSET		15
+#define HPIPE_TX_SWEEP_PRESET_EN_MASK		\
+	(0x1 << HPIPE_TX_SWEEP_PRESET_EN_OFFSET)
+
+#define HPIPE_G1_SETTINGS_3_REG			0x440
+
+#define HPIPE_G1_SETTINGS_4_REG			0x444
+#define HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET	8
+#define HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK	\
+	(0x3 << HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET)
+
+#define HPIPE_G2_SETTINGS_3_REG			0x448
+#define HPIPE_G2_SETTINGS_4_REG			0x44C
+
+#define HPIPE_G3_SETTING_3_REG			0x450
+#define HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET	12
+#define HPIPE_G3_FFE_DEG_RES_LEVEL_MASK		\
+	(0x3 << HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET)
+#define HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET	14
+#define HPIPE_G3_FFE_LOAD_RES_LEVEL_MASK	\
+	(0x3 << HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET)
+
+#define HPIPE_G3_SETTING_4_REG			0x454
+#define HPIPE_G3_DFE_RES_OFFSET			8
+#define HPIPE_G3_DFE_RES_MASK			\
+	(0x3 << HPIPE_G3_DFE_RES_OFFSET)
+
+#define HPIPE_DFE_CTRL_28_REG			0x49C
+#define HPIPE_DFE_CTRL_28_PIPE4_OFFSET		7
+#define HPIPE_DFE_CTRL_28_PIPE4_MASK		\
+	(0x1 << HPIPE_DFE_CTRL_28_PIPE4_OFFSET)
+
+#define HPIPE_LANE_CONFIG0_REG			0x600
+#define HPIPE_LANE_CONFIG0_TXDEEMPH0_OFFSET	0
+#define HPIPE_LANE_CONFIG0_TXDEEMPH0_MASK	\
+	(0x1 << HPIPE_LANE_CONFIG0_TXDEEMPH0_OFFSET)
+
+#define HPIPE_LANE_CONFIG1_REG			0x604
+#define HPIPE_LANE_CONFIG1_MAX_PLL_OFFSET	9
+#define HPIPE_LANE_CONFIG1_MAX_PLL_MASK		\
+	(0x1 << HPIPE_LANE_CONFIG1_MAX_PLL_OFFSET)
+#define HPIPE_LANE_CONFIG1_GEN2_PLL_OFFSET	10
+#define HPIPE_LANE_CONFIG1_GEN2_PLL_MASK	\
+	(0x1 << HPIPE_LANE_CONFIG1_GEN2_PLL_OFFSET)
+
+#define HPIPE_LANE_STATUS1_REG			0x60C
+#define HPIPE_LANE_STATUS1_PCLK_EN_OFFSET	0
+#define HPIPE_LANE_STATUS1_PCLK_EN_MASK		\
+	(0x1 << HPIPE_LANE_STATUS1_PCLK_EN_OFFSET)
+
+#define HPIPE_LANE_CFG4_REG                     0x620
+#define HPIPE_LANE_CFG4_DFE_CTRL_OFFSET		0
+#define HPIPE_LANE_CFG4_DFE_CTRL_MASK		\
+	(0x7 << HPIPE_LANE_CFG4_DFE_CTRL_OFFSET)
+#define HPIPE_LANE_CFG4_DFE_OVER_OFFSET		6
+#define HPIPE_LANE_CFG4_DFE_OVER_MASK		\
+	(0x1 << HPIPE_LANE_CFG4_DFE_OVER_OFFSET)
+#define HPIPE_LANE_CFG4_SSC_CTRL_OFFSET		7
+#define HPIPE_LANE_CFG4_SSC_CTRL_MASK		\
+	(0x1 << HPIPE_LANE_CFG4_SSC_CTRL_OFFSET)
+
+#define HPIPE_LANE_EQU_CONFIG_0_REG		0x69C
+#define HPIPE_CFG_PHY_RC_EP_OFFSET		12
+#define HPIPE_CFG_PHY_RC_EP_MASK		\
+	(0x1 << HPIPE_CFG_PHY_RC_EP_OFFSET)
+
+#define HPIPE_LANE_EQ_CFG1_REG			0x6a0
+#define HPIPE_CFG_UPDATE_POLARITY_OFFSET	12
+#define HPIPE_CFG_UPDATE_POLARITY_MASK		\
+	(0x1 << HPIPE_CFG_UPDATE_POLARITY_OFFSET)
+
+#define HPIPE_RST_CLK_CTRL_REG			0x704
+#define HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET	0
+#define HPIPE_RST_CLK_CTRL_PIPE_RST_MASK	\
+	(0x1 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET)
+#define HPIPE_RST_CLK_CTRL_FIXED_PCLK_OFFSET	2
+#define HPIPE_RST_CLK_CTRL_FIXED_PCLK_MASK	\
+	(0x1 << HPIPE_RST_CLK_CTRL_FIXED_PCLK_OFFSET)
+#define HPIPE_RST_CLK_CTRL_PIPE_WIDTH_OFFSET	3
+#define HPIPE_RST_CLK_CTRL_PIPE_WIDTH_MASK	\
+	(0x1 << HPIPE_RST_CLK_CTRL_PIPE_WIDTH_OFFSET)
+#define HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_OFFSET	9
+#define HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_MASK	\
+	(0x1 << HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_OFFSET)
+
+#define HPIPE_TST_MODE_CTRL_REG			0x708
+#define HPIPE_TST_MODE_CTRL_MODE_MARGIN_OFFSET	2
+#define HPIPE_TST_MODE_CTRL_MODE_MARGIN_MASK	\
+	(0x1 << HPIPE_TST_MODE_CTRL_MODE_MARGIN_OFFSET)
+
+#define HPIPE_CLK_SRC_LO_REG			0x70c
+#define HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_OFFSET 1
+#define HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_MASK	\
+	(0x1 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_OFFSET)
+#define HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_OFFSET 2
+#define HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_MASK \
+	(0x3 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_OFFSET)
+#define HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET	5
+#define HPIPE_CLK_SRC_LO_PLL_RDY_DL_MASK	\
+	(0x7 << HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET)
+
+#define HPIPE_CLK_SRC_HI_REG			0x710
+#define HPIPE_CLK_SRC_HI_LANE_STRT_OFFSET	0
+#define HPIPE_CLK_SRC_HI_LANE_STRT_MASK		\
+	(0x1 << HPIPE_CLK_SRC_HI_LANE_STRT_OFFSET)
+#define HPIPE_CLK_SRC_HI_LANE_BREAK_OFFSET	1
+#define HPIPE_CLK_SRC_HI_LANE_BREAK_MASK	\
+	(0x1 << HPIPE_CLK_SRC_HI_LANE_BREAK_OFFSET)
+#define HPIPE_CLK_SRC_HI_LANE_MASTER_OFFSET	2
+#define HPIPE_CLK_SRC_HI_LANE_MASTER_MASK	\
+	(0x1 << HPIPE_CLK_SRC_HI_LANE_MASTER_OFFSET)
+#define HPIPE_CLK_SRC_HI_MODE_PIPE_OFFSET	7
+#define HPIPE_CLK_SRC_HI_MODE_PIPE_MASK		\
+	(0x1 << HPIPE_CLK_SRC_HI_MODE_PIPE_OFFSET)
+
+#define HPIPE_GLOBAL_MISC_CTRL                  0x718
+#define HPIPE_GLOBAL_PM_CTRL                    0x740
+#define HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET	0
+#define HPIPE_GLOBAL_PM_RXDLOZ_WAIT_MASK	\
+	(0xFF << HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET)
+
+#endif /* _COMPHY_HPIPE_H_ */
+
diff --git a/drivers/phy/marvell/comphy_mux.c b/drivers/phy/marvell/comphy_mux.c
new file mode 100644
index 0000000..1dc7426
--- /dev/null
+++ b/drivers/phy/marvell/comphy_mux.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2015-2016 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+
+#include "comphy.h"
+#include "comphy_hpipe.h"
+
+/*
+ * comphy_mux_check_config()
+ * description: this function passes over the COMPHY lanes and check if the type
+ *              is valid for specific lane. If the type is not valid,
+ *              the function update the struct and set the type of the lane as
+ *              PHY_TYPE_UNCONNECTED
+ */
+static void comphy_mux_check_config(struct comphy_mux_data *mux_data,
+		struct comphy_map *comphy_map_data, int comphy_max_lanes)
+{
+	struct comphy_mux_options *mux_opt;
+	int lane, opt, valid;
+
+	debug_enter();
+
+	for (lane = 0; lane < comphy_max_lanes;
+	     lane++, comphy_map_data++, mux_data++) {
+		mux_opt = mux_data->mux_values;
+		for (opt = 0, valid = 0; opt < mux_data->max_lane_values;
+		     opt++, mux_opt++) {
+			if (mux_opt->type == comphy_map_data->type) {
+				valid = 1;
+				break;
+			}
+		}
+		if (valid == 0) {
+			debug("lane number %d, had invalid type %d\n",
+			      lane, comphy_map_data->type);
+			debug("set lane %d as type %d\n", lane,
+			      PHY_TYPE_UNCONNECTED);
+			comphy_map_data->type = PHY_TYPE_UNCONNECTED;
+		} else {
+			debug("lane number %d, has type %d\n",
+			      lane, comphy_map_data->type);
+		}
+	}
+
+	debug_exit();
+}
+
+static u32 comphy_mux_get_mux_value(struct comphy_mux_data *mux_data,
+				    u32 type, int lane)
+{
+	struct comphy_mux_options *mux_opt;
+	int opt;
+	u32 value = 0;
+
+	debug_enter();
+
+	mux_opt = mux_data->mux_values;
+	for (opt = 0 ; opt < mux_data->max_lane_values; opt++, mux_opt++) {
+		if (mux_opt->type == type) {
+			value = mux_opt->mux_value;
+			break;
+		}
+	}
+
+	debug_exit();
+
+	return value;
+}
+
+static void comphy_mux_reg_write(struct comphy_mux_data *mux_data,
+				 struct comphy_map *comphy_map_data,
+				 int comphy_max_lanes,
+				 void __iomem *selector_base, u32 bitcount)
+{
+	u32 lane, value, offset, mask;
+
+	debug_enter();
+
+	for (lane = 0; lane < comphy_max_lanes;
+	     lane++, comphy_map_data++, mux_data++) {
+		offset = lane * bitcount;
+		mask = (((1 << bitcount) - 1) << offset);
+		value = (comphy_mux_get_mux_value(mux_data,
+						  comphy_map_data->type,
+						  lane) << offset);
+		reg_set(selector_base, value, mask);
+	}
+
+	debug_exit();
+}
+
+void comphy_mux_init(struct chip_serdes_phy_config *chip_cfg,
+		     struct comphy_map *comphy_map_data,
+		     void __iomem *selector_base)
+{
+	struct comphy_mux_data *mux_data;
+	u32 mux_bitcount;
+	u32 comphy_max_lanes;
+
+	debug_enter();
+
+	comphy_max_lanes = chip_cfg->comphy_lanes_count;
+	mux_data = chip_cfg->mux_data;
+	mux_bitcount = chip_cfg->comphy_mux_bitcount;
+
+	/* check if the configuration is valid */
+	comphy_mux_check_config(mux_data, comphy_map_data, comphy_max_lanes);
+	/* Init COMPHY selectors */
+	comphy_mux_reg_write(mux_data, comphy_map_data, comphy_max_lanes,
+			     selector_base, mux_bitcount);
+
+	debug_exit();
+}
diff --git a/include/dt-bindings/comphy/comphy_data.h b/include/dt-bindings/comphy/comphy_data.h
new file mode 100644
index 0000000..a3a6b40
--- /dev/null
+++ b/include/dt-bindings/comphy/comphy_data.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2015-2016 Marvell International Ltd.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _COMPHY_DATA_H_
+#define _COMPHY_DATA_H_
+
+#define PHY_SPEED_1_25G			0
+#define PHY_SPEED_1_5G			1
+#define PHY_SPEED_2_5G			2
+#define PHY_SPEED_3G			3
+#define PHY_SPEED_3_125G		4
+#define PHY_SPEED_5G			5
+#define PHY_SPEED_6G			6
+#define PHY_SPEED_6_25G			7
+#define PHY_SPEED_10_3125G		8
+#define PHY_SPEED_MAX			9
+#define PHY_SPEED_INVALID		0xff
+
+#define PHY_TYPE_UNCONNECTED		0
+#define PHY_TYPE_PEX0			1
+#define PHY_TYPE_PEX1			2
+#define PHY_TYPE_PEX2			3
+#define PHY_TYPE_PEX3			4
+#define PHY_TYPE_SATA0			5
+#define PHY_TYPE_SATA1			6
+#define PHY_TYPE_SATA2			7
+#define PHY_TYPE_SATA3			8
+#define PHY_TYPE_SGMII0			9
+#define PHY_TYPE_SGMII1			10
+#define PHY_TYPE_SGMII2			11
+#define PHY_TYPE_SGMII3			12
+#define PHY_TYPE_QSGMII			13
+#define PHY_TYPE_USB3_HOST0		14
+#define PHY_TYPE_USB3_HOST1		15
+#define PHY_TYPE_USB3_DEVICE		16
+#define PHY_TYPE_XAUI0			17
+#define PHY_TYPE_XAUI1			18
+#define PHY_TYPE_XAUI2			19
+#define PHY_TYPE_XAUI3			20
+#define PHY_TYPE_RXAUI0			21
+#define PHY_TYPE_RXAUI1			22
+#define PHY_TYPE_KR			23
+#define PHY_TYPE_MAX			24
+#define PHY_TYPE_INVALID		0xff
+
+#define PHY_POLARITY_NO_INVERT		0
+#define PHY_POLARITY_TXD_INVERT		1
+#define PHY_POLARITY_RXD_INVERT		2
+#define PHY_POLARITY_ALL_INVERT		\
+	(PHY_POLARITY_TXD_INVERT | PHY_POLARITY_RXD_INVERT)
+
+#define UTMI_PHY_TO_USB_HOST0		0
+#define UTMI_PHY_TO_USB_HOST1		1
+#define UTMI_PHY_TO_USB_DEVICE0		2
+#define UTMI_PHY_INVALID		0xff
+
+#endif /* _COMPHY_DATA_H_ */
+
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 08/15] arm64: mvebu: Armada 3700: Add Armada 37xx dts files
  2016-09-16 13:09 [U-Boot] [PATCH 01/15] serial: Add serial_mvebu_a3700 for Armada 3700 SoC Stefan Roese
                   ` (5 preceding siblings ...)
  2016-09-16 13:09 ` [U-Boot] [PATCH 07/15] drivers/phy: Add Marvell SerDes / PHY drivers used on Armada 3k Stefan Roese
@ 2016-09-16 13:09 ` Stefan Roese
  2016-09-16 13:09 ` [U-Boot] [PATCH 09/15] arm64: mvebu: Armada 3700: Add SPI device tree nodes Stefan Roese
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 36+ messages in thread
From: Stefan Roese @ 2016-09-16 13:09 UTC (permalink / raw)
  To: u-boot

This patch integrates the Armada 3700 dts files from the latest
submission on the linux-arm-kernel mailing list.

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>
---
 arch/arm/dts/Makefile           |   1 +
 arch/arm/dts/armada-371x.dtsi   |  53 +++++++++++++++
 arch/arm/dts/armada-3720-db.dts |  78 +++++++++++++++++++++
 arch/arm/dts/armada-372x.dtsi   |  62 +++++++++++++++++
 arch/arm/dts/armada-37xx.dtsi   | 145 ++++++++++++++++++++++++++++++++++++++++
 5 files changed, 339 insertions(+)
 create mode 100644 arch/arm/dts/armada-371x.dtsi
 create mode 100644 arch/arm/dts/armada-3720-db.dts
 create mode 100644 arch/arm/dts/armada-372x.dtsi
 create mode 100644 arch/arm/dts/armada-37xx.dtsi

diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index a4ab069..4a51de1 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -67,6 +67,7 @@ dtb-$(CONFIG_TEGRA) += tegra20-harmony.dtb \
 	tegra210-p2571.dtb
 
 dtb-$(CONFIG_ARCH_MVEBU) +=			\
+	armada-3720-db.dtb			\
 	armada-375-db.dtb			\
 	armada-388-clearfog.dtb			\
 	armada-388-gp.dtb			\
diff --git a/arch/arm/dts/armada-371x.dtsi b/arch/arm/dts/armada-371x.dtsi
new file mode 100644
index 0000000..c9e5325
--- /dev/null
+++ b/arch/arm/dts/armada-371x.dtsi
@@ -0,0 +1,53 @@
+/*
+ * Device Tree Include file for Marvell Armada 371x family of SoCs
+ * (also named 88F3710)
+ *
+ * Copyright (C) 2016 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "armada-37xx.dtsi"
+
+/ {
+	model = "Marvell Armada 3710 SoC";
+	compatible = "marvell,armada3710", "marvell,armada3700";
+};
diff --git a/arch/arm/dts/armada-3720-db.dts b/arch/arm/dts/armada-3720-db.dts
new file mode 100644
index 0000000..86110a6
--- /dev/null
+++ b/arch/arm/dts/armada-3720-db.dts
@@ -0,0 +1,78 @@
+/*
+ * Device Tree file for Marvell Armada 3720 development board
+ * (DB-88F3720-DDR3)
+ * Copyright (C) 2016 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "armada-372x.dtsi"
+
+/ {
+	model = "Marvell Armada 3720 Development Board DB-88F3720-DDR3";
+	compatible = "marvell,armada-3720-db", "marvell,armada3720", "marvell,armada3710";
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
+	};
+};
+
+/* CON3 */
+&sata {
+	status = "okay";
+};
+
+/* Exported on the micro USB connector CON32 through an FTDI */
+&uart0 {
+	status = "okay";
+};
+
+/* CON31 */
+&usb3 {
+	status = "okay";
+};
diff --git a/arch/arm/dts/armada-372x.dtsi b/arch/arm/dts/armada-372x.dtsi
new file mode 100644
index 0000000..5120296
--- /dev/null
+++ b/arch/arm/dts/armada-372x.dtsi
@@ -0,0 +1,62 @@
+/*
+ * Device Tree Include file for Marvell Armada 372x family of SoCs
+ * (also named 88F3720)
+ *
+ * Copyright (C) 2016 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "armada-37xx.dtsi"
+
+/ {
+	model = "Marvell Armada 3720 SoC";
+	compatible = "marvell,armada3720", "marvell,armada3710";
+
+	cpus {
+		cpu at 1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53","arm,armv8";
+			reg = <0x1>;
+			enable-method = "psci";
+		};
+	};
+};
diff --git a/arch/arm/dts/armada-37xx.dtsi b/arch/arm/dts/armada-37xx.dtsi
new file mode 100644
index 0000000..9e2efb8
--- /dev/null
+++ b/arch/arm/dts/armada-37xx.dtsi
@@ -0,0 +1,145 @@
+/*
+ * Device Tree Include file for Marvell Armada 37xx family of SoCs.
+ *
+ * Copyright (C) 2016 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+	model = "Marvell Armada 37xx SoC";
+	compatible = "marvell,armada3700";
+	interrupt-parent = <&gic>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cpu at 0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53", "arm,armv8";
+			reg = <0>;
+			enable-method = "psci";
+		};
+	};
+
+	psci {
+		compatible = "arm,psci-0.2";
+		method = "smc";
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13
+			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 14
+			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 11
+			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>,
+			     <GIC_PPI 10
+			(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		internal-regs {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "simple-bus";
+			/* 32M internal register @ 0xd000_0000 */
+			ranges = <0x0 0x0 0xd0000000 0x2000000>;
+
+			uart0: serial at 12000 {
+				compatible = "marvell,armada-3700-uart";
+				reg = <0x12000 0x400>;
+				interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+				status = "disabled";
+			};
+
+			usb3: usb at 58000 {
+				compatible = "marvell,armada3700-xhci",
+				"generic-xhci";
+				reg = <0x58000 0x4000>;
+				interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+				status = "disabled";
+			};
+
+			xor at 60900 {
+				compatible = "marvell,armada-3700-xor";
+				reg = <0x60900 0x100
+				       0x60b00 0x100>;
+
+				xor10 {
+					interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
+				};
+				xor11 {
+					interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+				};
+			};
+
+			sata: sata at e0000 {
+				compatible = "marvell,armada-3700-ahci";
+				reg = <0xe0000 0x2000>;
+				interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+				status = "disabled";
+			};
+
+			gic: interrupt-controller at 1d00000 {
+				compatible = "arm,gic-v3";
+				#interrupt-cells = <3>;
+				interrupt-controller;
+				reg = <0x1d00000 0x10000>, /* GICD */
+				      <0x1d40000 0x40000>; /* GICR */
+			};
+		};
+	};
+};
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 09/15] arm64: mvebu: Armada 3700: Add SPI device tree nodes
  2016-09-16 13:09 [U-Boot] [PATCH 01/15] serial: Add serial_mvebu_a3700 for Armada 3700 SoC Stefan Roese
                   ` (6 preceding siblings ...)
  2016-09-16 13:09 ` [U-Boot] [PATCH 08/15] arm64: mvebu: Armada 3700: Add Armada 37xx dts files Stefan Roese
@ 2016-09-16 13:09 ` Stefan Roese
  2016-09-21  8:02   ` Jagan Teki
  2016-09-23 11:37   ` [U-Boot] [PATCH 09/15 v2] " Stefan Roese
  2016-09-16 13:09 ` [U-Boot] [PATCH 10/15] arm64: mvebu: Armada 3700: Add ethernet " Stefan Roese
                   ` (5 subsequent siblings)
  13 siblings, 2 replies; 36+ messages in thread
From: Stefan Roese @ 2016-09-16 13:09 UTC (permalink / raw)
  To: u-boot

This patch adds the SPI device tree nodes that are still missing to
the Armada 3700 dts files.

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>
---
 arch/arm/dts/armada-3720-db.dts | 17 +++++++++++++++++
 arch/arm/dts/armada-37xx.dtsi   | 11 +++++++++++
 2 files changed, 28 insertions(+)

diff --git a/arch/arm/dts/armada-3720-db.dts b/arch/arm/dts/armada-3720-db.dts
index 86110a6..52c90c2 100644
--- a/arch/arm/dts/armada-3720-db.dts
+++ b/arch/arm/dts/armada-3720-db.dts
@@ -56,6 +56,10 @@
 		stdout-path = "serial0:115200n8";
 	};
 
+	aliases {
+		spi0 = &spi0;
+	};
+
 	memory {
 		device_type = "memory";
 		reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
@@ -67,6 +71,19 @@
 	status = "okay";
 };
 
+&spi0 {
+	status = "okay";
+
+	spi-flash at 0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "st,m25p128", "jedec,spi-nor";
+		reg = <0>; /* Chip select 0 */
+		spi-max-frequency = <50000000>;
+		m25p,fast-read;
+	};
+};
+
 /* Exported on the micro USB connector CON32 through an FTDI */
 &uart0 {
 	status = "okay";
diff --git a/arch/arm/dts/armada-37xx.dtsi b/arch/arm/dts/armada-37xx.dtsi
index 9e2efb8..bb14f54 100644
--- a/arch/arm/dts/armada-37xx.dtsi
+++ b/arch/arm/dts/armada-37xx.dtsi
@@ -140,6 +140,17 @@
 				reg = <0x1d00000 0x10000>, /* GICD */
 				      <0x1d40000 0x40000>; /* GICR */
 			};
+
+			spi0: spi at 10600 {
+				compatible = "marvell,armada-3700-spi";
+				reg = <0x10600 0x50>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				#clock-cells = <0>;
+				clock-frequency = <160000>;
+				spi-max-frequency = <40000>;
+				status = "disabled";
+			};
 		};
 	};
 };
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 10/15] arm64: mvebu: Armada 3700: Add ethernet device tree nodes
  2016-09-16 13:09 [U-Boot] [PATCH 01/15] serial: Add serial_mvebu_a3700 for Armada 3700 SoC Stefan Roese
                   ` (7 preceding siblings ...)
  2016-09-16 13:09 ` [U-Boot] [PATCH 09/15] arm64: mvebu: Armada 3700: Add SPI device tree nodes Stefan Roese
@ 2016-09-16 13:09 ` Stefan Roese
  2016-09-16 13:09 ` [U-Boot] [PATCH 11/15] arm64: mvebu: Armada 3700: Add I2C " Stefan Roese
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 36+ messages in thread
From: Stefan Roese @ 2016-09-16 13:09 UTC (permalink / raw)
  To: u-boot

This patch adds the ethernet device tree nodes that are still missing to
the Armada 3700 dts files.

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>
---
 arch/arm/dts/armada-3720-db.dts |  6 ++++++
 arch/arm/dts/armada-37xx.dtsi   | 12 ++++++++++++
 2 files changed, 18 insertions(+)

diff --git a/arch/arm/dts/armada-3720-db.dts b/arch/arm/dts/armada-3720-db.dts
index 52c90c2..87fde2a 100644
--- a/arch/arm/dts/armada-3720-db.dts
+++ b/arch/arm/dts/armada-3720-db.dts
@@ -57,6 +57,7 @@
 	};
 
 	aliases {
+		ethernet0 = &eth0;
 		spi0 = &spi0;
 	};
 
@@ -66,6 +67,11 @@
 	};
 };
 
+&eth0 {
+	status = "okay";
+	phy-mode = "rgmii";
+};
+
 /* CON3 */
 &sata {
 	status = "okay";
diff --git a/arch/arm/dts/armada-37xx.dtsi b/arch/arm/dts/armada-37xx.dtsi
index bb14f54..0c01d43 100644
--- a/arch/arm/dts/armada-37xx.dtsi
+++ b/arch/arm/dts/armada-37xx.dtsi
@@ -141,6 +141,18 @@
 				      <0x1d40000 0x40000>; /* GICR */
 			};
 
+			eth0: neta at 30000 {
+				compatible = "marvell,armada-3700-neta";
+				reg = <0x30000 0x20>;
+				status = "disabled";
+			};
+
+			eth1: neta at 40000 {
+				compatible = "marvell,armada-3700-neta";
+				reg = <0x40000 0x20>;
+				status = "disabled";
+			};
+
 			spi0: spi at 10600 {
 				compatible = "marvell,armada-3700-spi";
 				reg = <0x10600 0x50>;
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 11/15] arm64: mvebu: Armada 3700: Add I2C device tree nodes
  2016-09-16 13:09 [U-Boot] [PATCH 01/15] serial: Add serial_mvebu_a3700 for Armada 3700 SoC Stefan Roese
                   ` (8 preceding siblings ...)
  2016-09-16 13:09 ` [U-Boot] [PATCH 10/15] arm64: mvebu: Armada 3700: Add ethernet " Stefan Roese
@ 2016-09-16 13:09 ` Stefan Roese
  2016-09-16 13:09 ` [U-Boot] [PATCH 12/15] arm64: mvebu: Armada 3700: Add COMPHY " Stefan Roese
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 36+ messages in thread
From: Stefan Roese @ 2016-09-16 13:09 UTC (permalink / raw)
  To: u-boot

This patch adds the I2C device tree nodes that are still missing to
the Armada 3700 dts files.

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>
---
 arch/arm/dts/armada-3720-db.dts | 5 +++++
 arch/arm/dts/armada-37xx.dtsi   | 6 ++++++
 2 files changed, 11 insertions(+)

diff --git a/arch/arm/dts/armada-3720-db.dts b/arch/arm/dts/armada-3720-db.dts
index 87fde2a..ec73786 100644
--- a/arch/arm/dts/armada-3720-db.dts
+++ b/arch/arm/dts/armada-3720-db.dts
@@ -58,6 +58,7 @@
 
 	aliases {
 		ethernet0 = &eth0;
+		i2c0 = &i2c0;
 		spi0 = &spi0;
 	};
 
@@ -72,6 +73,10 @@
 	phy-mode = "rgmii";
 };
 
+&i2c0 {
+	status = "okay";
+};
+
 /* CON3 */
 &sata {
 	status = "okay";
diff --git a/arch/arm/dts/armada-37xx.dtsi b/arch/arm/dts/armada-37xx.dtsi
index 0c01d43..9f350df 100644
--- a/arch/arm/dts/armada-37xx.dtsi
+++ b/arch/arm/dts/armada-37xx.dtsi
@@ -153,6 +153,12 @@
 				status = "disabled";
 			};
 
+			i2c0: i2c at 11000 {
+				compatible = "marvell,armada-3700-i2c";
+				reg = <0x11000 0x100>;
+				status = "disabled";
+			};
+
 			spi0: spi at 10600 {
 				compatible = "marvell,armada-3700-spi";
 				reg = <0x10600 0x50>;
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 12/15] arm64: mvebu: Armada 3700: Add COMPHY device tree nodes
  2016-09-16 13:09 [U-Boot] [PATCH 01/15] serial: Add serial_mvebu_a3700 for Armada 3700 SoC Stefan Roese
                   ` (9 preceding siblings ...)
  2016-09-16 13:09 ` [U-Boot] [PATCH 11/15] arm64: mvebu: Armada 3700: Add I2C " Stefan Roese
@ 2016-09-16 13:09 ` Stefan Roese
  2016-09-16 13:09 ` [U-Boot] [PATCH 13/15] arm64: mvebu: Armada 3700: Add USB " Stefan Roese
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 36+ messages in thread
From: Stefan Roese @ 2016-09-16 13:09 UTC (permalink / raw)
  To: u-boot

This patch adds the COMPHY device tree nodes that are still missing to
the Armada 3700 dts files.

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>
---
 arch/arm/dts/armada-3720-db.dts | 12 ++++++++++++
 arch/arm/dts/armada-37xx.dtsi   |  9 +++++++++
 2 files changed, 21 insertions(+)

diff --git a/arch/arm/dts/armada-3720-db.dts b/arch/arm/dts/armada-3720-db.dts
index ec73786..192c59f 100644
--- a/arch/arm/dts/armada-3720-db.dts
+++ b/arch/arm/dts/armada-3720-db.dts
@@ -68,6 +68,18 @@
 	};
 };
 
+&comphy {
+	phy0 {
+		phy-type = <PHY_TYPE_PEX0>;
+		phy-speed = <PHY_SPEED_2_5G>;
+	};
+
+	phy1 {
+		phy-type = <PHY_TYPE_USB3_HOST0>;
+		phy-speed = <PHY_SPEED_5G>;
+	};
+};
+
 &eth0 {
 	status = "okay";
 	phy-mode = "rgmii";
diff --git a/arch/arm/dts/armada-37xx.dtsi b/arch/arm/dts/armada-37xx.dtsi
index 9f350df..ceeb6e5 100644
--- a/arch/arm/dts/armada-37xx.dtsi
+++ b/arch/arm/dts/armada-37xx.dtsi
@@ -45,6 +45,7 @@
  */
 
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/comphy/comphy_data.h>
 
 / {
 	model = "Marvell Armada 37xx SoC";
@@ -169,6 +170,14 @@
 				spi-max-frequency = <40000>;
 				status = "disabled";
 			};
+
+			comphy: comphy at 18300 {
+				compatible = "marvell,mvebu-comphy", "marvell,comphy-armada-3700";
+				reg = <0x18300 0x28>,
+				      <0x1f300 0x3d000>;
+				mux-bitcount = <1>;
+				max-lanes = <2>;
+			};
 		};
 	};
 };
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 13/15] arm64: mvebu: Armada 3700: Add USB device tree nodes
  2016-09-16 13:09 [U-Boot] [PATCH 01/15] serial: Add serial_mvebu_a3700 for Armada 3700 SoC Stefan Roese
                   ` (10 preceding siblings ...)
  2016-09-16 13:09 ` [U-Boot] [PATCH 12/15] arm64: mvebu: Armada 3700: Add COMPHY " Stefan Roese
@ 2016-09-16 13:09 ` Stefan Roese
  2016-09-16 13:09 ` [U-Boot] [PATCH 14/15] arm64: mvebu: Add support for the Marvell Armada 3700 SoC Stefan Roese
  2016-09-16 13:09 ` [U-Boot] [PATCH 15/15] arm64: mvebu: Add Armada 3700 db-88f3720 development board support Stefan Roese
  13 siblings, 0 replies; 36+ messages in thread
From: Stefan Roese @ 2016-09-16 13:09 UTC (permalink / raw)
  To: u-boot

This patch adds the USB device tree nodes that are still missing to
the Armada 3700 dts files.

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>
---
 arch/arm/dts/armada-3720-db.dts | 5 +++++
 arch/arm/dts/armada-37xx.dtsi   | 6 ++++++
 2 files changed, 11 insertions(+)

diff --git a/arch/arm/dts/armada-3720-db.dts b/arch/arm/dts/armada-3720-db.dts
index 192c59f..1ebfa1e 100644
--- a/arch/arm/dts/armada-3720-db.dts
+++ b/arch/arm/dts/armada-3720-db.dts
@@ -112,6 +112,11 @@
 	status = "okay";
 };
 
+/* CON29 */
+&usb2 {
+	status = "okay";
+};
+
 /* CON31 */
 &usb3 {
 	status = "okay";
diff --git a/arch/arm/dts/armada-37xx.dtsi b/arch/arm/dts/armada-37xx.dtsi
index ceeb6e5..e27eae0 100644
--- a/arch/arm/dts/armada-37xx.dtsi
+++ b/arch/arm/dts/armada-37xx.dtsi
@@ -114,6 +114,12 @@
 				status = "disabled";
 			};
 
+			usb2: usb at 5e000 {
+				compatible = "marvell,armada3700-ehci";
+				reg = <0x5e000 0x450>;
+				status = "disabled";
+			};
+
 			xor at 60900 {
 				compatible = "marvell,armada-3700-xor";
 				reg = <0x60900 0x100
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 14/15] arm64: mvebu: Add support for the Marvell Armada 3700 SoC
  2016-09-16 13:09 [U-Boot] [PATCH 01/15] serial: Add serial_mvebu_a3700 for Armada 3700 SoC Stefan Roese
                   ` (11 preceding siblings ...)
  2016-09-16 13:09 ` [U-Boot] [PATCH 13/15] arm64: mvebu: Armada 3700: Add USB " Stefan Roese
@ 2016-09-16 13:09 ` Stefan Roese
  2016-09-16 13:09 ` [U-Boot] [PATCH 15/15] arm64: mvebu: Add Armada 3700 db-88f3720 development board support Stefan Roese
  13 siblings, 0 replies; 36+ messages in thread
From: Stefan Roese @ 2016-09-16 13:09 UTC (permalink / raw)
  To: u-boot

The Armada 3700 integrates the following interfaces (not complete list):
- Dual Cortex-A53 ARMv8
- USB 3.0
- SATA 3.0
- PCIe 2.0
- 2 x Gigabit Ethernet 1Gbps / 2.5Gbps
- ...

This patch adds basic support for this ARMv8 based SoC into U-Boot.
Future patches will integrate other device drivers and board support
for the Marvell DB-88F3720 development board.

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>
---
 arch/arm/Kconfig                        |   6 -
 arch/arm/mach-mvebu/Kconfig             |  25 ++++-
 arch/arm/mach-mvebu/Makefile            |  15 ++-
 arch/arm/mach-mvebu/armada3700/Makefile |   8 ++
 arch/arm/mach-mvebu/armada3700/cpu.c    | 188 ++++++++++++++++++++++++++++++++
 arch/arm/mach-mvebu/armada3700/sata.c   |  45 ++++++++
 arch/arm/mach-mvebu/include/mach/cpu.h  |   7 ++
 arch/arm/mach-mvebu/include/mach/soc.h  |   2 +-
 8 files changed, 284 insertions(+), 12 deletions(-)
 create mode 100644 arch/arm/mach-mvebu/armada3700/Makefile
 create mode 100644 arch/arm/mach-mvebu/armada3700/cpu.c
 create mode 100644 arch/arm/mach-mvebu/armada3700/sata.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index e63309a..f9d0d2e 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -165,8 +165,6 @@ config KIRKWOOD
 
 config ARCH_MVEBU
 	bool "Marvell MVEBU family (Armada XP/375/38x)"
-	select CPU_V7
-	select SUPPORT_SPL
 	select OF_CONTROL
 	select OF_SEPARATE
 	select DM
@@ -174,10 +172,6 @@ config ARCH_MVEBU
 	select DM_SERIAL
 	select DM_SPI
 	select DM_SPI_FLASH
-	select SPL_DM
-	select SPL_DM_SEQ_ALIAS
-	select SPL_OF_CONTROL
-	select SPL_SIMPLE_BUS
 
 config TARGET_DEVKIT3250
 	bool "Support devkit3250"
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index 220886a..e01b5c3 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -1,14 +1,37 @@
 if ARCH_MVEBU
 
+config ARMADA_32BIT
+	bool
+	select CPU_V7
+	select SUPPORT_SPL
+	select SPL_DM
+	select SPL_DM_SEQ_ALIAS
+	select SPL_OF_CONTROL
+	select SPL_SIMPLE_BUS
+
+config ARMADA_64BIT
+	bool
+	select ARM64
+
+# ARMv7 SoCs...
 config ARMADA_375
 	bool
+	select ARMADA_32BIT
 
 config ARMADA_38X
 	bool
+	select ARMADA_32BIT
 
 config ARMADA_XP
 	bool
+	select ARMADA_32BIT
+
+# ARMv8 SoCs...
+config ARMADA_3700
+	bool
+	select ARM64
 
+# Armada XP/38x SoC types...
 config MV78230
 	bool
 	select ARMADA_XP
@@ -26,7 +49,7 @@ config DB_88F6820_GP
 	select ARMADA_38X
 
 choice
-	prompt "Marvell MVEBU (Armada XP/375/38x) board select"
+	prompt "Marvell MVEBU (Armada XP/375/38x/3700) board select"
 	optional
 
 config TARGET_CLEARFOG
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index ac009a3..07dc16c 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -1,16 +1,22 @@
 #
-# Copyright (C) 2014-2015 Stefan Roese <sr@denx.de>
+# Copyright (C) 2014-2016 Stefan Roese <sr@denx.de>
 #
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
+ifdef CONFIG_ARM64
+
+obj-$(CONFIG_ARMADA_3700) += armada3700/
+
+else # CONFIG_ARM64
+
 ifdef CONFIG_KIRKWOOD
 
 obj-y	= dram.o
 obj-y	+= gpio.o
 obj-y	+= timer.o
 
-else
+else # CONFIG_KIRKWOOD
 
 obj-y	= cpu.o
 obj-y	+= dram.o
@@ -18,7 +24,7 @@ ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_ARMADA_375) += ../../../drivers/ddr/marvell/axp/xor.o
 obj-$(CONFIG_ARMADA_38X) += ../../../drivers/ddr/marvell/a38x/xor.o
 obj-$(CONFIG_ARMADA_XP) += ../../../drivers/ddr/marvell/axp/xor.o
-endif
+endif # CONFIG_SPL_BUILD
 obj-y	+= gpio.o
 obj-y	+= mbus.o
 obj-y	+= timer.o
@@ -28,4 +34,5 @@ obj-$(CONFIG_SPL_BUILD) += lowlevel_spl.o
 obj-$(CONFIG_ARMADA_38X) += serdes/a38x/
 obj-$(CONFIG_ARMADA_XP) += serdes/axp/
 
-endif
+endif # CONFIG_KIRKWOOD
+endif # CONFIG_ARM64
diff --git a/arch/arm/mach-mvebu/armada3700/Makefile b/arch/arm/mach-mvebu/armada3700/Makefile
new file mode 100644
index 0000000..b1fac57
--- /dev/null
+++ b/arch/arm/mach-mvebu/armada3700/Makefile
@@ -0,0 +1,8 @@
+#
+# Copyright (C) 2016 Stefan Roese <sr@denx.de>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y = cpu.o
+obj-y += sata.o
diff --git a/arch/arm/mach-mvebu/armada3700/cpu.c b/arch/arm/mach-mvebu/armada3700/cpu.c
new file mode 100644
index 0000000..7d8f7b8
--- /dev/null
+++ b/arch/arm/mach-mvebu/armada3700/cpu.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <libfdt.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+#include <asm/armv8/mmu.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Armada 3700 */
+#define MVEBU_GPIO_NB_REG_BASE		(MVEBU_REGISTER(0x13800))
+
+#define MVEBU_TEST_PIN_LATCH_N		(MVEBU_GPIO_NB_REG_BASE + 0x8)
+#define MVEBU_XTAL_MODE_MASK		BIT(9)
+#define MVEBU_XTAL_MODE_OFFS		9
+#define MVEBU_XTAL_CLOCK_25MHZ		0x0
+#define MVEBU_XTAL_CLOCK_40MHZ		0x1
+
+#define MVEBU_NB_WARM_RST_REG		(MVEBU_GPIO_NB_REG_BASE + 0x40)
+#define MVEBU_NB_WARM_RST_MAGIC_NUM	0x1d1e
+
+static struct mm_region mvebu_mem_map[] = {
+	{
+		/* RAM */
+		.phys = 0x0UL,
+		.virt = 0x0UL,
+		.size = 0x80000000UL,
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+			 PTE_BLOCK_INNER_SHARE
+	},
+	{
+		/* SRAM, MMIO regions */
+		.phys = 0xd0000000UL,
+		.virt = 0xd0000000UL,
+		.size = 0x02000000UL,	/* 32MiB internal registers */
+		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+			 PTE_BLOCK_NON_SHARE
+	},
+	{
+		/* List terminator */
+		0,
+	}
+};
+
+struct mm_region *mem_map = mvebu_mem_map;
+
+/*
+ * On ARMv8, MBus is not configured in U-Boot. To enable compilation
+ * of the already implemented drivers, lets add a dummy version of
+ * this function so that linking does not fail.
+ */
+const struct mbus_dram_target_info *mvebu_mbus_dram_info(void)
+{
+	return NULL;
+}
+
+void reset_cpu(ulong ignored)
+{
+	/*
+	 * Write magic number of 0x1d1e to North Bridge Warm Reset register
+	 * to trigger warm reset
+	 */
+	writel(MVEBU_NB_WARM_RST_MAGIC_NUM, MVEBU_NB_WARM_RST_REG);
+}
+
+/*
+ * get_ref_clk
+ *
+ * return: reference clock in MHz (25 or 40)
+ */
+u32 get_ref_clk(void)
+{
+	u32 regval;
+
+	regval = (readl(MVEBU_TEST_PIN_LATCH_N) & MVEBU_XTAL_MODE_MASK) >>
+		MVEBU_XTAL_MODE_OFFS;
+
+	if (regval == MVEBU_XTAL_CLOCK_25MHZ)
+		return 25;
+	else
+		return 40;
+}
+
+/* DRAM init code ... */
+
+static const void *get_memory_reg_prop(const void *fdt, int *lenp)
+{
+	int offset;
+
+	offset = fdt_path_offset(fdt, "/memory");
+	if (offset < 0)
+		return NULL;
+
+	return fdt_getprop(fdt, offset, "reg", lenp);
+}
+
+int dram_init(void)
+{
+	const void *fdt = gd->fdt_blob;
+	const fdt32_t *val;
+	int ac, sc, len;
+
+	ac = fdt_address_cells(fdt, 0);
+	sc = fdt_size_cells(fdt, 0);
+	if (ac < 0 || sc < 1 || sc > 2) {
+		printf("invalid address/size cells\n");
+		return -EINVAL;
+	}
+
+	val = get_memory_reg_prop(fdt, &len);
+	if (len / sizeof(*val) < ac + sc)
+		return -EINVAL;
+
+	val += ac;
+
+	gd->ram_size = fdtdec_get_number(val, sc);
+
+	debug("DRAM size = %08lx\n", (unsigned long)gd->ram_size);
+
+	return 0;
+}
+
+void dram_init_banksize(void)
+{
+	const void *fdt = gd->fdt_blob;
+	const fdt32_t *val;
+	int ac, sc, cells, len, i;
+
+	val = get_memory_reg_prop(fdt, &len);
+	if (len < 0)
+		return;
+
+	ac = fdt_address_cells(fdt, 0);
+	sc = fdt_size_cells(fdt, 0);
+	if (ac < 1 || sc > 2 || sc < 1 || sc > 2) {
+		printf("invalid address/size cells\n");
+		return;
+	}
+
+	cells = ac + sc;
+
+	len /= sizeof(*val);
+
+	for (i = 0; i < CONFIG_NR_DRAM_BANKS && len >= cells;
+	     i++, len -= cells) {
+		gd->bd->bi_dram[i].start = fdtdec_get_number(val, ac);
+		val += ac;
+		gd->bd->bi_dram[i].size = fdtdec_get_number(val, sc);
+		val += sc;
+
+		debug("DRAM bank %d: start = %08lx, size = %08lx\n",
+		      i, (unsigned long)gd->bd->bi_dram[i].start,
+		      (unsigned long)gd->bd->bi_dram[i].size);
+	}
+}
+
+int arch_cpu_init(void)
+{
+	/* Nothing to do (yet) */
+	return 0;
+}
+
+int arch_early_init_r(void)
+{
+	struct udevice *dev;
+	int ret;
+
+	/* Call the comphy code via the MISC uclass driver */
+	ret = uclass_get_device(UCLASS_MISC, 0, &dev);
+	if (ret) {
+		debug("COMPHY init failed: %d\n", ret);
+		return -ENODEV;
+	}
+
+	/* Cause the SATA device to do its early init */
+	uclass_first_device(UCLASS_AHCI, &dev);
+
+	return 0;
+}
diff --git a/arch/arm/mach-mvebu/armada3700/sata.c b/arch/arm/mach-mvebu/armada3700/sata.c
new file mode 100644
index 0000000..e0e8381
--- /dev/null
+++ b/arch/arm/mach-mvebu/armada3700/sata.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <ahci.h>
+#include <dm.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Dummy implementation that can be overwritten by a board
+ * specific function
+ */
+__weak int board_ahci_enable(void)
+{
+	return 0;
+}
+
+static int mvebu_ahci_probe(struct udevice *dev)
+{
+	/*
+	 * Board specific SATA / AHCI enable code, e.g. enable the
+	 * AHCI power or deassert reset
+	 */
+	board_ahci_enable();
+
+	ahci_init(dev_get_addr_ptr(dev));
+
+	return 0;
+}
+
+static const struct udevice_id mvebu_ahci_ids[] = {
+	{ .compatible = "marvell,armada-3700-ahci" },
+	{ }
+};
+
+U_BOOT_DRIVER(ahci_mvebu_drv) = {
+	.name		= "ahci_mvebu",
+	.id		= UCLASS_AHCI,
+	.of_match	= mvebu_ahci_ids,
+	.probe		= mvebu_ahci_probe,
+};
diff --git a/arch/arm/mach-mvebu/include/mach/cpu.h b/arch/arm/mach-mvebu/include/mach/cpu.h
index cbec876..66f7680 100644
--- a/arch/arm/mach-mvebu/include/mach/cpu.h
+++ b/arch/arm/mach-mvebu/include/mach/cpu.h
@@ -166,5 +166,12 @@ struct mvebu_lcd_info {
 
 int mvebu_lcd_register_init(struct mvebu_lcd_info *lcd_info);
 
+/*
+ * get_ref_clk
+ *
+ * return: reference clock in MHz (25 or 40)
+ */
+u32 get_ref_clk(void);
+
 #endif /* __ASSEMBLY__ */
 #endif /* _MVEBU_CPU_H */
diff --git a/arch/arm/mach-mvebu/include/mach/soc.h b/arch/arm/mach-mvebu/include/mach/soc.h
index 6342cdc..063d6cc 100644
--- a/arch/arm/mach-mvebu/include/mach/soc.h
+++ b/arch/arm/mach-mvebu/include/mach/soc.h
@@ -37,7 +37,7 @@
 /* SOC specific definations */
 #define INTREG_BASE		0xd0000000
 #define INTREG_BASE_ADDR_REG	(INTREG_BASE + 0x20080)
-#if defined(CONFIG_SPL_BUILD)
+#if defined(CONFIG_SPL_BUILD) || defined(CONFIG_ARMADA_3700)
 /*
  * The SPL U-Boot version still runs with the default
  * address for the internal registers, configured by
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 15/15] arm64: mvebu: Add Armada 3700 db-88f3720 development board support
  2016-09-16 13:09 [U-Boot] [PATCH 01/15] serial: Add serial_mvebu_a3700 for Armada 3700 SoC Stefan Roese
                   ` (12 preceding siblings ...)
  2016-09-16 13:09 ` [U-Boot] [PATCH 14/15] arm64: mvebu: Add support for the Marvell Armada 3700 SoC Stefan Roese
@ 2016-09-16 13:09 ` Stefan Roese
  13 siblings, 0 replies; 36+ messages in thread
From: Stefan Roese @ 2016-09-16 13:09 UTC (permalink / raw)
  To: u-boot

This patch adds basic support for the Marvell Armada 3700 DB-88F3720
development board. Supported are the following interfaces:
- UART
- SPI (incl. SPI NOR)
- I2C
- Ethernet

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>
---
 arch/arm/mach-mvebu/Kconfig                |   7 ++
 board/Marvell/mvebu_db-88f3720/MAINTAINERS |   6 ++
 board/Marvell/mvebu_db-88f3720/Makefile    |   7 ++
 board/Marvell/mvebu_db-88f3720/board.c     | 134 ++++++++++++++++++++++++++
 configs/mvebu_db-88f3720_defconfig         |  49 ++++++++++
 include/configs/mvebu_db-88f3720.h         | 145 +++++++++++++++++++++++++++++
 6 files changed, 348 insertions(+)
 create mode 100644 board/Marvell/mvebu_db-88f3720/MAINTAINERS
 create mode 100644 board/Marvell/mvebu_db-88f3720/Makefile
 create mode 100644 board/Marvell/mvebu_db-88f3720/board.c
 create mode 100644 configs/mvebu_db-88f3720_defconfig
 create mode 100644 include/configs/mvebu_db-88f3720.h

diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index e01b5c3..bede700 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -56,6 +56,10 @@ config TARGET_CLEARFOG
 	bool "Support ClearFog"
 	select DB_88F6820_GP
 
+config TARGET_MVEBU_DB_88F3720
+	bool "Support DB-88F3720 Armada 3720"
+	select ARMADA_3700
+
 config TARGET_DB_88F6720
 	bool "Support DB-88F6720 Armada 375"
 	select ARMADA_375
@@ -84,6 +88,7 @@ endchoice
 
 config SYS_BOARD
 	default "clearfog" if TARGET_CLEARFOG
+	default "mvebu_db-88f3720" if TARGET_MVEBU_DB_88F3720
 	default "db-88f6720" if TARGET_DB_88F6720
 	default "db-88f6820-gp" if TARGET_DB_88F6820_GP
 	default "db-mv784mp-gp" if TARGET_DB_MV784MP_GP
@@ -93,6 +98,7 @@ config SYS_BOARD
 
 config SYS_CONFIG_NAME
 	default "clearfog" if TARGET_CLEARFOG
+	default "mvebu_db-88f3720" if TARGET_MVEBU_DB_88F3720
 	default "db-88f6720" if TARGET_DB_88F6720
 	default "db-88f6820-gp" if TARGET_DB_88F6820_GP
 	default "db-mv784mp-gp" if TARGET_DB_MV784MP_GP
@@ -102,6 +108,7 @@ config SYS_CONFIG_NAME
 
 config SYS_VENDOR
 	default "Marvell" if TARGET_DB_MV784MP_GP
+	default "Marvell" if TARGET_MVEBU_DB_88F3720
 	default "Marvell" if TARGET_DB_88F6720
 	default "Marvell" if TARGET_DB_88F6820_GP
 	default "solidrun" if TARGET_CLEARFOG
diff --git a/board/Marvell/mvebu_db-88f3720/MAINTAINERS b/board/Marvell/mvebu_db-88f3720/MAINTAINERS
new file mode 100644
index 0000000..4e80917
--- /dev/null
+++ b/board/Marvell/mvebu_db-88f3720/MAINTAINERS
@@ -0,0 +1,6 @@
+MVEBU_DB_88F3720 BOARD
+M:	Stefan Roese <sr@denx.de>
+S:	Maintained
+F:	board/Marvell/mvebu_db-88f3720/
+F:	include/configs/mvebu_db-88f3720.h
+F:	configs/mvebu_db-88f3720_defconfig
diff --git a/board/Marvell/mvebu_db-88f3720/Makefile b/board/Marvell/mvebu_db-88f3720/Makefile
new file mode 100644
index 0000000..ed39738
--- /dev/null
+++ b/board/Marvell/mvebu_db-88f3720/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2016 Stefan Roese <sr@denx.de>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+obj-y	:= board.o
diff --git a/board/Marvell/mvebu_db-88f3720/board.c b/board/Marvell/mvebu_db-88f3720/board.c
new file mode 100644
index 0000000..edf88c7
--- /dev/null
+++ b/board/Marvell/mvebu_db-88f3720/board.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <i2c.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* IO expander I2C device */
+#define I2C_IO_EXP_ADDR		0x22
+#define I2C_IO_CFG_REG_0	0x6
+#define I2C_IO_DATA_OUT_REG_0	0x2
+#define I2C_IO_REG_0_SATA_OFF	2
+#define I2C_IO_REG_0_USB_H_OFF	1
+
+int board_early_init_f(void)
+{
+	/* Nothing to do (yet), perhaps later some pin-muxing etc */
+
+	return 0;
+}
+
+int board_init(void)
+{
+	/* adress of boot parameters */
+	gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
+
+	return 0;
+}
+
+/* Board specific AHCI / SATA enable code */
+int board_ahci_enable(void)
+{
+	struct udevice *dev;
+	int ret;
+	u8 buf[8];
+
+	/* Configure IO exander PCA9555: 7bit address 0x22 */
+	ret = i2c_get_chip_for_busnum(0, I2C_IO_EXP_ADDR, 1, &dev);
+	if (ret) {
+		printf("Cannot find PCA9555: %d\n", ret);
+		return 0;
+	}
+
+	ret = dm_i2c_read(dev, I2C_IO_CFG_REG_0, buf, 1);
+	if (ret) {
+		printf("Failed to read IO expander value via I2C\n");
+		return -EIO;
+	}
+
+	/*
+	 * Enable SATA power via IO expander connected via I2C by setting
+	 * the corresponding bit to output mode to enable power for SATA
+	 */
+	buf[0] &= ~(1 << I2C_IO_REG_0_SATA_OFF);
+	ret = dm_i2c_write(dev, I2C_IO_CFG_REG_0, buf, 1);
+	if (ret) {
+		printf("Failed to set IO expander via I2C\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/* Board specific xHCI enable code */
+int board_xhci_enable(void)
+{
+	struct udevice *dev;
+	int ret;
+	u8 buf[8];
+
+	/* Configure IO exander PCA9555: 7bit address 0x22 */
+	ret = i2c_get_chip_for_busnum(0, I2C_IO_EXP_ADDR, 1, &dev);
+	if (ret) {
+		printf("Cannot find PCA9555: %d\n", ret);
+		return 0;
+	}
+
+	printf("Enable USB VBUS\n");
+
+	/*
+	 * Read configuration (direction) and set VBUS pin as output
+	 * (reset pin = output)
+	 */
+	ret = dm_i2c_read(dev, I2C_IO_CFG_REG_0, buf, 1);
+	if (ret) {
+		printf("Failed to read IO expander value via I2C\n");
+		return -EIO;
+	}
+	buf[0] &= ~(1 << I2C_IO_REG_0_USB_H_OFF);
+	ret = dm_i2c_write(dev, I2C_IO_CFG_REG_0, buf, 1);
+	if (ret) {
+		printf("Failed to set IO expander via I2C\n");
+		return -EIO;
+	}
+
+	/* Read VBUS output value and disable it */
+	ret = dm_i2c_read(dev, I2C_IO_DATA_OUT_REG_0, buf, 1);
+	if (ret) {
+		printf("Failed to read IO expander value via I2C\n");
+		return -EIO;
+	}
+	buf[0] &= ~(1 << I2C_IO_REG_0_USB_H_OFF);
+	ret = dm_i2c_write(dev, I2C_IO_DATA_OUT_REG_0, buf, 1);
+	if (ret) {
+		printf("Failed to set IO expander via I2C\n");
+		return -EIO;
+	}
+
+	/*
+	 * Required delay for configuration to settle - must wait for
+	 * power on port is disabled in case VBUS signal was high,
+	 * required 3 seconds delay to let VBUS signal fully settle down
+	 */
+	mdelay(3000);
+
+	/* Enable VBUS power: Set output value of VBUS pin as enabled */
+	buf[0] |= (1 << I2C_IO_REG_0_USB_H_OFF);
+	ret = dm_i2c_write(dev, I2C_IO_DATA_OUT_REG_0, buf, 1);
+	if (ret) {
+		printf("Failed to set IO expander via I2C\n");
+		return -EIO;
+	}
+
+	mdelay(500); /* required delay to let output value settle */
+
+	return 0;
+}
diff --git a/configs/mvebu_db-88f3720_defconfig b/configs/mvebu_db-88f3720_defconfig
new file mode 100644
index 0000000..813d064
--- /dev/null
+++ b/configs/mvebu_db-88f3720_defconfig
@@ -0,0 +1,49 @@
+CONFIG_ARM=y
+CONFIG_ARCH_MVEBU=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_TARGET_MVEBU_DB_88F3720=y
+CONFIG_DEFAULT_DEVICE_TREE="armada-3720-db"
+CONFIG_AHCI=y
+# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_USB=y
+# CONFIG_CMD_FPGA is not set
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_TFTPPUT=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MII=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_CACHE=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_FAT=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_BLOCK_CACHE=y
+CONFIG_DM_I2C=y
+CONFIG_DM_I2C_COMPAT=y
+CONFIG_MISC=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_PHYLIB=y
+CONFIG_MVEBU_COMPHY_SUPPORT=y
+# CONFIG_SPL_SERIAL_PRESENT is not set
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_MVEBU_A3700_UART=y
+CONFIG_DEBUG_UART_BASE=0xd0012000
+CONFIG_DEBUG_UART_CLOCK=25804800
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_DEBUG_UART_ANNOUNCE=y
+CONFIG_MVEBU_A3700_UART=y
+CONFIG_MVEBU_A3700_SPI=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_STORAGE=y
diff --git a/include/configs/mvebu_db-88f3720.h b/include/configs/mvebu_db-88f3720.h
new file mode 100644
index 0000000..b7bae33
--- /dev/null
+++ b/include/configs/mvebu_db-88f3720.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _CONFIG_MVEBU_DB_88F3720_H
+#define _CONFIG_MVEBU_DB_88F3720_H
+
+/*
+ * High Level Configuration Options (easy to change)
+ */
+#define CONFIG_DISPLAY_BOARDINFO_LATE
+#define CONFIG_ARCH_EARLY_INIT_R
+
+#define	CONFIG_SYS_TEXT_BASE	0x00000000
+
+/* additions for new ARM relocation support */
+#define CONFIG_SYS_SDRAM_BASE	0x00000000
+
+#define CONFIG_NR_DRAM_BANKS	1
+
+/* auto boot */
+#define CONFIG_PREBOOT
+
+#define CONFIG_BAUDRATE			115200
+#define CONFIG_SYS_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, \
+					  115200, 230400, 460800, 921600 }
+#define CONFIG_UART_BASE_CLOCK		25804800
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CONFIG_CMDLINE_TAG		/* enable passing of ATAGs  */
+#define CONFIG_INITRD_TAG		/* enable INITRD tag */
+#define CONFIG_SETUP_MEMORY_TAGS	/* enable memory tag */
+
+#define	CONFIG_SYS_CBSIZE	1024	/* Console I/O Buff Size */
+#define	CONFIG_SYS_PBSIZE	(CONFIG_SYS_CBSIZE \
+		+sizeof(CONFIG_SYS_PROMPT) + 16)	/* Print Buff */
+
+/*
+ * Size of malloc() pool
+ */
+#define CONFIG_SYS_MALLOC_LEN	(4 << 20) /* 4MiB for malloc() */
+
+/*
+ * Other required minimal configurations
+ */
+#define CONFIG_SYS_LONGHELP
+#define CONFIG_AUTO_COMPLETE
+#define CONFIG_CMDLINE_EDITING
+#define CONFIG_CONSOLE_INFO_QUIET	/* some code reduction */
+#define CONFIG_ARCH_CPU_INIT		/* call arch_cpu_init() */
+#define CONFIG_BOARD_EARLY_INIT_F	/* call board_init_f for early inits */
+#define CONFIG_SYS_LOAD_ADDR	0x00800000	/* default load adr- 8M */
+#define CONFIG_SYS_MEMTEST_START 0x00800000	/* 8M */
+#define CONFIG_SYS_MEMTEST_END	0x00ffffff	/*(_16M -1) */
+#define CONFIG_SYS_RESET_ADDRESS 0xffff0000	/* Rst Vector Adr */
+#define CONFIG_SYS_MAXARGS	32	/* max number of command args */
+
+#define CONFIG_SYS_CONSOLE_INFO_QUIET	/* don't print console @ startup */
+#define CONFIG_SYS_ALT_MEMTEST
+
+/* End of 16M scrubbed by training in bootrom */
+#define CONFIG_SYS_INIT_SP_ADDR         (CONFIG_SYS_TEXT_BASE + 0xFF0000)
+
+/*
+ * I2C
+ */
+#define CONFIG_I2C_MV
+#define CONFIG_SYS_I2C_SLAVE		0x0
+
+/*
+ * SPI Flash configuration
+ */
+#define CONFIG_ENV_SPI_BUS		0
+#define CONFIG_ENV_SPI_CS		0
+
+/* SPI NOR flash default params, used by sf commands */
+#define CONFIG_SF_DEFAULT_SPEED		1000000
+#define CONFIG_SF_DEFAULT_MODE		SPI_MODE_0
+#define CONFIG_ENV_SPI_MODE		CONFIG_SF_DEFAULT_MODE
+
+/* Environment in SPI NOR flash */
+#define CONFIG_SYS_NO_FLASH		/* Declare no flash (NOR/SPI) */
+#define CONFIG_ENV_IS_IN_SPI_FLASH
+#define CONFIG_ENV_OFFSET		0x180000 /* as Marvell U-Boot version */
+#define CONFIG_ENV_SIZE			(64 << 10) /* 64KiB */
+#define CONFIG_ENV_SECT_SIZE		(64 << 10) /* 64KiB sectors */
+
+/*
+ * Ethernet Driver configuration
+ */
+#define CONFIG_MVNETA		/* Enable Marvell Gbe Controller Driver */
+#define CONFIG_ENV_OVERWRITE	/* ethaddr can be reprogrammed */
+#define CONFIG_PHY_GIGE		/* GbE speed/duplex detect */
+#define CONFIG_ARP_TIMEOUT	200
+#define CONFIG_NET_RETRY_COUNT	50
+
+/* USB 2.0 */
+#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3
+
+/* USB 3.0 */
+#define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 3
+
+#define CONFIG_USB_MAX_CONTROLLER_COUNT (CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS + \
+					 CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS)
+
+/* USB ethernet */
+#define CONFIG_USB_HOST_ETHER
+#define CONFIG_USB_ETHER_ASIX
+#define CONFIG_USB_ETHER_MCS7830
+#define CONFIG_USB_ETHER_RTL8152
+#define CONFIG_USB_ETHER_SMSC95XX
+
+/*
+ * SATA/SCSI/AHCI configuration
+ */
+#define CONFIG_SCSI
+#define CONFIG_SCSI_AHCI
+#define CONFIG_SCSI_AHCI_PLAT
+#define CONFIG_LIBATA
+#define CONFIG_LBA48
+#define CONFIG_SYS_64BIT_LBA
+
+#define CONFIG_SYS_SCSI_MAX_SCSI_ID	2
+#define CONFIG_SYS_SCSI_MAX_LUN		1
+#define CONFIG_SYS_SCSI_MAX_DEVICE	(CONFIG_SYS_SCSI_MAX_SCSI_ID * \
+					 CONFIG_SYS_SCSI_MAX_LUN)
+
+#define CONFIG_SUPPORT_VFAT
+
+/* DISK Partition support */
+#define CONFIG_EFI_PARTITION
+#define CONFIG_DOS_PARTITION
+#define CONFIG_MAC_PARTITION
+#define CONFIG_ISO_PARTITION		/* Experimental */
+
+#define CONFIG_CMD_PART
+#define CONFIG_PARTITION_UUIDS
+
+#endif /* _CONFIG_MVEBU_DB_88F3720_H */
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 03/15] net: mvneta: Make driver 64bit safe
  2016-09-16 13:09 ` [U-Boot] [PATCH 03/15] net: mvneta: Make driver 64bit safe Stefan Roese
@ 2016-09-16 17:30   ` Joe Hershberger
  2016-09-23 11:05     ` Stefan Roese
  0 siblings, 1 reply; 36+ messages in thread
From: Joe Hershberger @ 2016-09-16 17:30 UTC (permalink / raw)
  To: u-boot

On Fri, Sep 16, 2016 at 8:09 AM, Stefan Roese <sr@denx.de> wrote:
> The mvneta driver is also used on the ARMv8 64bit Armada 3700 SoC. This
> patch fixes the compilation warnings seen on this 64bit platform.
>
> 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>
> Cc: Joe Hershberger <joe.hershberger@ni.com>

Acked-by: Joe Hershberger <joe.hershberger@ni.com>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 04/15] net: mvneta: Add support for Armada 3700 SoC
  2016-09-16 13:09 ` [U-Boot] [PATCH 04/15] net: mvneta: Add support for Armada 3700 SoC Stefan Roese
@ 2016-09-16 17:59   ` Joe Hershberger
  2016-09-23 11:26   ` [U-Boot] [PATCH 04/15 v2] " Stefan Roese
  1 sibling, 0 replies; 36+ messages in thread
From: Joe Hershberger @ 2016-09-16 17:59 UTC (permalink / raw)
  To: u-boot

On Fri, Sep 16, 2016 at 8:09 AM, Stefan Roese <sr@denx.de> wrote:
> This patch adds support for the Armada 3700 SoC to the Marvell mvneta
> network driver.
>
> Not like A380, in Armada3700, there are two layers of decode windows for GBE:
> First layer is:  GbE Address window that resides inside the GBE unit,
> Second layer is: Fabric address window which is located in the NIC400
>                  (South Fabric).
> To simplify the address decode configuration for Armada3700, we bypass the
> first layer of GBE decode window by setting the first window to 4GB.
>
> 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>
> Cc: Joe Hershberger <joe.hershberger@ni.com>
> ---
>  drivers/net/mvneta.c | 39 ++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 38 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/mvneta.c b/drivers/net/mvneta.c
> index 433e186..2b98a92 100644
> --- a/drivers/net/mvneta.c
> +++ b/drivers/net/mvneta.c
> @@ -91,7 +91,10 @@ DECLARE_GLOBAL_DATA_PTR;
>  #define MVNETA_WIN_BASE(w)                      (0x2200 + ((w) << 3))
>  #define MVNETA_WIN_SIZE(w)                      (0x2204 + ((w) << 3))
>  #define MVNETA_WIN_REMAP(w)                     (0x2280 + ((w) << 2))
> +#define MVNETA_WIN_SIZE_MASK                   (0xffff0000)
>  #define MVNETA_BASE_ADDR_ENABLE                 0x2290
> +#define MVNETA_PORT_ACCESS_PROTECT              0x2294
> +#define      MVNETA_PORT_ACCESS_PROTECT_WIN0_RW        0x3
>  #define MVNETA_PORT_CONFIG                      0x2400
>  #define      MVNETA_UNI_PROMISC_MODE            BIT(0)
>  #define      MVNETA_DEF_RXQ(q)                  ((q) << 1)
> @@ -1241,6 +1244,36 @@ static int mvneta_init2(struct mvneta_port *pp)
>  }
>
>  /* platform glue : initialize decoding windows */
> +
> +/*
> + * Not like A380, in Armada3700, there are two layers of decode windows for GBE:
> + * First layer is:  GbE Address window that resides inside the GBE unit,
> + * Second layer is: Fabric address window which is located in the NIC400
> + *                  (South Fabric).
> + * To simplify the address decode configuration for Armada3700, we bypass the
> + * first layer of GBE decode window by setting the first window to 4GB.
> + */
> +static void mvneta_bypass_mbus_windows(struct mvneta_port *pp)
> +{
> +       u32 tmp_value;
> +
> +       /*
> +        * Set window size to 4GB, to bypass GBE address decode, leave the
> +        * work to MBUS decode window
> +        */
> +       mvreg_write(pp, MVNETA_WIN_SIZE(0), MVNETA_WIN_SIZE_MASK);
> +
> +       /* Enable GBE address decode window 0 by set bit 0 to 0 */
> +       tmp_value = mvreg_read(pp, MVNETA_BASE_ADDR_ENABLE);
> +       tmp_value = tmp_value & ~(1);

It would be good to have a defined name for this bitfield above like the others.

Also, you could use:

#define MVNETA_BASE_ADDR_ENABLE_BIT 0
clear_bit(MVNETA_BASE_ADDR_ENABLE_BIT, pp->base + MVNETA_BASE_ADDR_ENABLE);

> +       mvreg_write(pp, MVNETA_BASE_ADDR_ENABLE, tmp_value);
> +
> +       /* Set GBE address decode window 0 to full Access (read or write) */
> +       tmp_value = mvreg_read(pp, MVNETA_PORT_ACCESS_PROTECT);
> +       tmp_value = tmp_value | MVNETA_PORT_ACCESS_PROTECT_WIN0_RW;
> +       mvreg_write(pp, MVNETA_PORT_ACCESS_PROTECT, tmp_value);

Or:

setbits_le32(pp->base + MVNETA_PORT_ACCESS_PROTECT,
MVNETA_PORT_ACCESS_PROTECT_WIN0_RW)

> +}
> +
>  static void mvneta_conf_mbus_windows(struct mvneta_port *pp)
>  {
>         const struct mbus_dram_target_info *dram;
> @@ -1609,7 +1642,10 @@ static int mvneta_probe(struct udevice *dev)
>         pp->base = (void __iomem *)pdata->iobase;
>
>         /* Configure MBUS address windows */
> -       mvneta_conf_mbus_windows(pp);
> +       if (of_device_is_compatible(dev, "marvell,armada-3700-neta"))
> +               mvneta_bypass_mbus_windows(pp);
> +       else
> +               mvneta_conf_mbus_windows(pp);
>
>         /* PHY interface is already decoded in mvneta_ofdata_to_platdata() */
>         pp->phy_interface = pdata->phy_interface;
> @@ -1672,6 +1708,7 @@ static int mvneta_ofdata_to_platdata(struct udevice *dev)
>  static const struct udevice_id mvneta_ids[] = {
>         { .compatible = "marvell,armada-370-neta" },
>         { .compatible = "marvell,armada-xp-neta" },
> +       { .compatible = "marvell,armada-3700-neta" },
>         { }
>  };
>
> --
> 2.9.3
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 05/15] usb: xhci: Add Marvell MVEBU xHCI support
  2016-09-16 13:09 ` [U-Boot] [PATCH 05/15] usb: xhci: Add Marvell MVEBU xHCI support Stefan Roese
@ 2016-09-18 10:46   ` Marek Vasut
  0 siblings, 0 replies; 36+ messages in thread
From: Marek Vasut @ 2016-09-18 10:46 UTC (permalink / raw)
  To: u-boot

On 09/16/2016 03:09 PM, Stefan Roese wrote:
> This patch adds DM based support for the xHCI USB 3.0 controller
> integrated in the Armada 3700 SoC. It may be extended to be used
> by other MVEBU SoCs as well.
> 
> 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>
> Cc: Marek Vasut <marex@denx.de>
> ---

Acked-by: Marek Vasut <marex@denx.de>

-- 
Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 06/15] usb: ehci: ehci-marvell.c: Add Armada 3700 support (ARMv8)
  2016-09-16 13:09 ` [U-Boot] [PATCH 06/15] usb: ehci: ehci-marvell.c: Add Armada 3700 support (ARMv8) Stefan Roese
@ 2016-09-18 10:47   ` Marek Vasut
  2016-09-20 11:03     ` Stefan Roese
  0 siblings, 1 reply; 36+ messages in thread
From: Marek Vasut @ 2016-09-18 10:47 UTC (permalink / raw)
  To: u-boot

On 09/16/2016 03:09 PM, Stefan Roese wrote:
> This patch adds DM based support for the Armada 3700 EHCI controller.
> The address windows don't need to get configured in this case. The
> difference here is detected via DT compatible property at runtime.
> 
> With this support and the DM xHCI driver, both XHCI and eHCI can be
> used simultaniously on the MVEBU boards now.
> 
> 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>
> Cc: Marek Vasut <marex@denx.de>
> ---

Acked-by: Marek Vasut <marex@denx.de>

Feel free to pick this all up via the marvell tree if that helps.

-- 
Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 06/15] usb: ehci: ehci-marvell.c: Add Armada 3700 support (ARMv8)
  2016-09-18 10:47   ` Marek Vasut
@ 2016-09-20 11:03     ` Stefan Roese
  0 siblings, 0 replies; 36+ messages in thread
From: Stefan Roese @ 2016-09-20 11:03 UTC (permalink / raw)
  To: u-boot

Hi Marek,

On 18.09.2016 12:47, Marek Vasut wrote:
> On 09/16/2016 03:09 PM, Stefan Roese wrote:
>> This patch adds DM based support for the Armada 3700 EHCI controller.
>> The address windows don't need to get configured in this case. The
>> difference here is detected via DT compatible property at runtime.
>>
>> With this support and the DM xHCI driver, both XHCI and eHCI can be
>> used simultaniously on the MVEBU boards now.
>>
>> 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>
>> Cc: Marek Vasut <marex@denx.de>
>> ---
>
> Acked-by: Marek Vasut <marex@denx.de>
>
> Feel free to pick this all up via the marvell tree if that helps.

Thanks, yes that makes things a bit easier. Will do once everything
is clear.

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 02/15] spi: Add driver for Marvell Armada 3700 SoC
  2016-09-16 13:09 ` [U-Boot] [PATCH 02/15] spi: Add driver for Marvell " Stefan Roese
@ 2016-09-21  7:56   ` Jagan Teki
  2016-09-23 12:14     ` Stefan Roese
  2016-09-23 12:17   ` [U-Boot] [PATCH 02/15 v2] " Stefan Roese
  2016-09-23 14:28   ` [U-Boot] [PATCH 02/15 v3] " Stefan Roese
  2 siblings, 1 reply; 36+ messages in thread
From: Jagan Teki @ 2016-09-21  7:56 UTC (permalink / raw)
  To: u-boot

On Fri, Sep 16, 2016 at 6:39 PM, Stefan Roese <sr@denx.de> wrote:
> The SPI IP core in the Marvell Armada 3700 is similar to the one in the
> other Armada SoCs. But the differences are big enough that it makes
> sense to introduce a new driver instead of cluttering the old
> kirkwood driver with #ifdef's.
>
> 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>
> Cc: Jagan Teki <jteki@openedev.com>
> ---
>  drivers/spi/Kconfig           |   7 ++
>  drivers/spi/Makefile          |   1 +
>  drivers/spi/mvebu_a3700_spi.c | 281 ++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 289 insertions(+)
>  create mode 100644 drivers/spi/mvebu_a3700_spi.c
>
> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> index aca385d..bc5e716 100644
> --- a/drivers/spi/Kconfig
> +++ b/drivers/spi/Kconfig
> @@ -75,6 +75,13 @@ config ICH_SPI
>           access the SPI NOR flash on platforms embedding this Intel
>           ICH IP core.
>
> +config MVEBU_A3700_SPI
> +       bool "Marvell Armada 3700 SPI driver"
> +       help
> +         Enable the Marvell Armada 3700 SPI driver. This driver can be
> +         used to access the SPI NOR flash on platforms embedding this
> +         Marvell IP core.
> +
>  config PIC32_SPI
>         bool "Microchip PIC32 SPI driver"
>         depends on MACH_PIC32
> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
> index b1d9e20..247c5f6 100644
> --- a/drivers/spi/Makefile
> +++ b/drivers/spi/Makefile
> @@ -37,6 +37,7 @@ obj-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
>  obj-$(CONFIG_LPC32XX_SSP) += lpc32xx_ssp.o
>  obj-$(CONFIG_MPC52XX_SPI) += mpc52xx_spi.o
>  obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
> +obj-$(CONFIG_MVEBU_A3700_SPI) += mvebu_a3700_spi.o
>  obj-$(CONFIG_MXC_SPI) += mxc_spi.o
>  obj-$(CONFIG_MXS_SPI) += mxs_spi.o
>  obj-$(CONFIG_OMAP3_SPI) += omap3_spi.o
> diff --git a/drivers/spi/mvebu_a3700_spi.c b/drivers/spi/mvebu_a3700_spi.c
> new file mode 100644
> index 0000000..26f9a8f
> --- /dev/null
> +++ b/drivers/spi/mvebu_a3700_spi.c
> @@ -0,0 +1,281 @@
> +/*
> + * Copyright (C) 2015 Marvell International Ltd.
> + *
> + * Copyright (C) 2016 Stefan Roese <sr@denx.de>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <malloc.h>
> +#include <spi.h>
> +#include <wait_bit.h>
> +#include <asm/io.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#define SPI_TIMEOUT                            10000
> +
> +#define MVEBU_SPI_A3700_XFER_RDY               BIT(1)
> +#define MVEBU_SPI_A3700_FIFO_FLUSH             BIT(9)
> +#define MVEBU_SPI_A3700_BYTE_LEN               BIT(5)
> +#define MVEBU_SPI_A3700_CLK_PHA                        BIT(6)
> +#define MVEBU_SPI_A3700_CLK_POL                        BIT(7)
> +#define MVEBU_SPI_A3700_FIFO_EN                        BIT(17)
> +#define MVEBU_SPI_A3700_SPI_EN_0               BIT(16)
> +#define MVEBU_SPI_A3700_CLK_PRESCALE_BIT       0
> +#define MVEBU_SPI_A3700_CLK_PRESCALE_MASK      \
> +       (0x1f << MVEBU_SPI_A3700_CLK_PRESCALE_BIT)
> +
> +/* SPI registers */
> +struct spi_reg {
> +       u32 ctrl;       /* 0x10600 */
> +       u32 cfg;        /* 0x10604 */
> +       u32 dout;       /* 0x10608 */
> +       u32 din;        /* 0x1060c */
> +};
> +
> +struct mvebu_spi_platdata {
> +       struct spi_reg *spireg;
> +};
> +
> +static void spi_cs_activate(struct spi_reg *reg, int cs)
> +{
> +       setbits_le32(&reg->ctrl, MVEBU_SPI_A3700_SPI_EN_0 << cs);
> +}
> +
> +static void spi_cs_deactivate(struct spi_reg *reg, int cs)
> +{
> +       clrbits_le32(&reg->ctrl, MVEBU_SPI_A3700_SPI_EN_0 << cs);
> +}
> +
> +/**
> + * spi_legacy_shift_byte() - triggers the real SPI transfer
> + * @bytelen:   Indicate how many bytes to transfer.
> + * @dout:      Buffer address of what to send.
> + * @din:       Buffer address of where to receive.
> + *
> + * This function triggers the real SPI transfer in legacy mode. It
> + * will shift out char buffer from @dout, and shift in char buffer to
> + * @din, if necessary.
> + *
> + * This function assumes that only one byte is shifted at one time.
> + * However, it is not its responisbility to set the transfer type to
> + * one-byte. Also, it does not guarantee that it will work if transfer
> + * type becomes two-byte. See spi_set_legacy() for details.
> + *
> + * In legacy mode, simply write to the SPI_DOUT register will trigger
> + * the transfer.
> + *
> + * If @dout == NULL, which means no actual data needs to be sent out,
> + * then the function will shift out 0x00 in order to shift in data.
> + * The XFER_RDY flag is checked every time before accessing SPI_DOUT
> + * and SPI_DIN register.
> + *
> + * The number of transfers to be triggerred is decided by @bytelen.
> + *
> + * Return:     0 - cool
> + *             -ETIMEDOUT - XFER_RDY flag timeout
> + */
> +static int spi_legacy_shift_byte(struct spi_reg *reg, unsigned int bytelen,
> +                                const void *dout, void *din)
> +{
> +       const u8 *dout_8;
> +       u8 *din_8;
> +       int ret;
> +
> +       /* Use 0x00 as dummy dout */
> +       const u8 dummy_dout = 0x0;
> +       u32 pending_dout = 0x0;
> +
> +       /* dout_8: pointer of current dout */
> +       dout_8 = dout;
> +       /* din_8: pointer of current din */
> +       din_8 = din;
> +
> +       while (bytelen) {
> +               ret = wait_for_bit(__func__, &reg->ctrl,
> +                                  MVEBU_SPI_A3700_XFER_RDY, true, 100, false);

Do we have any documentation in data sheet or something for this 100 ms?

> +               if (ret)
> +                       return ret;
> +
> +               if (dout)
> +                       pending_dout = (u32)*dout_8;
> +               else
> +                       pending_dout = (u32)dummy_dout;
> +
> +               /* Trigger the xfer */
> +               writel(pending_dout, &reg->dout);
> +
> +               if (din) {
> +                       ret = wait_for_bit(__func__, &reg->ctrl,
> +                                          MVEBU_SPI_A3700_XFER_RDY,
> +                                          true, 100, false);
> +                       if (ret)
> +                               return ret;
> +
> +                       /* Read what is transferred in */
> +                       *din_8 = (u8)readl(&reg->din);
> +               }
> +
> +               /* Don't increment the current pointer if NULL */
> +               if (dout)
> +                       dout_8++;
> +               if (din)
> +                       din_8++;
> +
> +               bytelen--;
> +       }
> +
> +       return 0;
> +}
> +
> +static int mvebu_spi_xfer(struct udevice *dev, unsigned int bitlen,
> +                         const void *dout, void *din, unsigned long flags)
> +{
> +       struct udevice *bus = dev->parent;
> +       struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
> +       struct spi_reg *reg = plat->spireg;
> +       unsigned int bytelen;
> +       int ret;
> +
> +       bytelen = bitlen / 8;
> +
> +       if (dout && din)
> +               debug("This is a duplex transfer.\n");
> +
> +       /* Activate CS */
> +       if (flags & SPI_XFER_BEGIN) {
> +               debug("SPI: activate cs.\n");
> +               spi_cs_activate(reg, spi_chip_select(dev));
> +       }
> +
> +       /* Send and/or receive */
> +       if (dout || din) {
> +               ret = spi_legacy_shift_byte(reg, bytelen, dout, din);
> +               if (ret)
> +                       return ret;
> +       }
> +
> +       /* Deactivate CS */
> +       if (flags & SPI_XFER_END) {
> +               ret = wait_for_bit(__func__, &reg->ctrl,
> +                                  MVEBU_SPI_A3700_XFER_RDY, true, 100, false);
> +               if (ret)
> +                       return ret;
> +
> +               debug("SPI: deactivate cs.\n");
> +               spi_cs_deactivate(reg, spi_chip_select(dev));
> +       }
> +
> +       return 0;
> +}
> +
> +static int mvebu_spi_set_speed(struct udevice *bus, uint hz)
> +{
> +       struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
> +       struct spi_reg *reg = plat->spireg;
> +       u32 data;
> +
> +       data = readl(&reg->cfg);
> +
> +       /* Set Prescaler */
> +       data &= ~MVEBU_SPI_A3700_CLK_PRESCALE_MASK;
> +
> +       /* Calculate Prescaler = (spi_input_freq / spi_max_freq) */
> +       /* ToDo: get real values for clock and frequency */
> +       data |= 160000 / 40000;

Better to get these from dt atleast for now and also please set the
freq/baud value by evaluating using input 'hz'

thanks!
-- 
Jagan Teki
Free Software Engineer | www.openedev.com
U-Boot, Linux | Upstream Maintainer
Hyderabad, India.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 09/15] arm64: mvebu: Armada 3700: Add SPI device tree nodes
  2016-09-16 13:09 ` [U-Boot] [PATCH 09/15] arm64: mvebu: Armada 3700: Add SPI device tree nodes Stefan Roese
@ 2016-09-21  8:02   ` Jagan Teki
  2016-09-23 11:37   ` [U-Boot] [PATCH 09/15 v2] " Stefan Roese
  1 sibling, 0 replies; 36+ messages in thread
From: Jagan Teki @ 2016-09-21  8:02 UTC (permalink / raw)
  To: u-boot

On Fri, Sep 16, 2016 at 6:39 PM, Stefan Roese <sr@denx.de> wrote:
> This patch adds the SPI device tree nodes that are still missing to
> the Armada 3700 dts files.
>
> 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>
> ---
>  arch/arm/dts/armada-3720-db.dts | 17 +++++++++++++++++
>  arch/arm/dts/armada-37xx.dtsi   | 11 +++++++++++
>  2 files changed, 28 insertions(+)
>
> diff --git a/arch/arm/dts/armada-3720-db.dts b/arch/arm/dts/armada-3720-db.dts
> index 86110a6..52c90c2 100644
> --- a/arch/arm/dts/armada-3720-db.dts
> +++ b/arch/arm/dts/armada-3720-db.dts
> @@ -56,6 +56,10 @@
>                 stdout-path = "serial0:115200n8";
>         };
>
> +       aliases {
> +               spi0 = &spi0;
> +       };
> +
>         memory {
>                 device_type = "memory";
>                 reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
> @@ -67,6 +71,19 @@
>         status = "okay";
>  };
>
> +&spi0 {
> +       status = "okay";
> +
> +       spi-flash at 0 {
> +               #address-cells = <1>;
> +               #size-cells = <1>;
> +               compatible = "st,m25p128", "jedec,spi-nor";

Use spi-flash instead of jedec,spi-nor

thanks!
-- 
Jagan Teki
Free Software Engineer | www.openedev.com
U-Boot, Linux | Upstream Maintainer
Hyderabad, India.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 03/15] net: mvneta: Make driver 64bit safe
  2016-09-16 17:30   ` Joe Hershberger
@ 2016-09-23 11:05     ` Stefan Roese
  2016-09-23 15:28       ` Joe Hershberger
  0 siblings, 1 reply; 36+ messages in thread
From: Stefan Roese @ 2016-09-23 11:05 UTC (permalink / raw)
  To: u-boot

On 16.09.2016 19:30, Joe Hershberger wrote:
> On Fri, Sep 16, 2016 at 8:09 AM, Stefan Roese <sr@denx.de> wrote:
>> The mvneta driver is also used on the ARMv8 64bit Armada 3700 SoC. This
>> patch fixes the compilation warnings seen on this 64bit platform.
>>
>> 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>
>> Cc: Joe Hershberger <joe.hershberger@ni.com>
>
> Acked-by: Joe Hershberger <joe.hershberger@ni.com>

Thanks Joe. Are you okay with me including this patch, and the
other mvneta one (once v2 is accepted / acked) via my Marvell
repository?

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 04/15 v2] net: mvneta: Add support for Armada 3700 SoC
  2016-09-16 13:09 ` [U-Boot] [PATCH 04/15] net: mvneta: Add support for Armada 3700 SoC Stefan Roese
  2016-09-16 17:59   ` Joe Hershberger
@ 2016-09-23 11:26   ` Stefan Roese
  2016-09-23 15:29     ` Joe Hershberger
  1 sibling, 1 reply; 36+ messages in thread
From: Stefan Roese @ 2016-09-23 11:26 UTC (permalink / raw)
  To: u-boot

This patch adds support for the Armada 3700 SoC to the Marvell mvneta
network driver.

Not like A380, in Armada3700, there are two layers of decode windows for GBE:
First layer is:  GbE Address window that resides inside the GBE unit,
Second layer is: Fabric address window which is located in the NIC400
                 (South Fabric).
To simplify the address decode configuration for Armada3700, we bypass the
first layer of GBE decode window by setting the first window to 4GB.

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>
Cc: Joe Hershberger <joe.hershberger@ni.com>
---
v2:
- Use clr/setbits_le32 as suggested by Joe

 drivers/net/mvneta.c | 36 +++++++++++++++++++++++++++++++++++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/drivers/net/mvneta.c b/drivers/net/mvneta.c
index 433e186..57be9f1 100644
--- a/drivers/net/mvneta.c
+++ b/drivers/net/mvneta.c
@@ -91,7 +91,11 @@ DECLARE_GLOBAL_DATA_PTR;
 #define MVNETA_WIN_BASE(w)                      (0x2200 + ((w) << 3))
 #define MVNETA_WIN_SIZE(w)                      (0x2204 + ((w) << 3))
 #define MVNETA_WIN_REMAP(w)                     (0x2280 + ((w) << 2))
+#define MVNETA_WIN_SIZE_MASK			(0xffff0000)
 #define MVNETA_BASE_ADDR_ENABLE                 0x2290
+#define      MVNETA_BASE_ADDR_ENABLE_BIT	0x1
+#define MVNETA_PORT_ACCESS_PROTECT              0x2294
+#define      MVNETA_PORT_ACCESS_PROTECT_WIN0_RW	0x3
 #define MVNETA_PORT_CONFIG                      0x2400
 #define      MVNETA_UNI_PROMISC_MODE            BIT(0)
 #define      MVNETA_DEF_RXQ(q)                  ((q) << 1)
@@ -1241,6 +1245,32 @@ static int mvneta_init2(struct mvneta_port *pp)
 }
 
 /* platform glue : initialize decoding windows */
+
+/*
+ * Not like A380, in Armada3700, there are two layers of decode windows for GBE:
+ * First layer is:  GbE Address window that resides inside the GBE unit,
+ * Second layer is: Fabric address window which is located in the NIC400
+ *                  (South Fabric).
+ * To simplify the address decode configuration for Armada3700, we bypass the
+ * first layer of GBE decode window by setting the first window to 4GB.
+ */
+static void mvneta_bypass_mbus_windows(struct mvneta_port *pp)
+{
+	/*
+	 * Set window size to 4GB, to bypass GBE address decode, leave the
+	 * work to MBUS decode window
+	 */
+	mvreg_write(pp, MVNETA_WIN_SIZE(0), MVNETA_WIN_SIZE_MASK);
+
+	/* Enable GBE address decode window 0 by set bit 0 to 0 */
+	clrbits_le32(pp->base + MVNETA_BASE_ADDR_ENABLE,
+		     MVNETA_BASE_ADDR_ENABLE_BIT);
+
+	/* Set GBE address decode window 0 to full Access (read or write) */
+	setbits_le32(pp->base + MVNETA_PORT_ACCESS_PROTECT,
+		     MVNETA_PORT_ACCESS_PROTECT_WIN0_RW);
+}
+
 static void mvneta_conf_mbus_windows(struct mvneta_port *pp)
 {
 	const struct mbus_dram_target_info *dram;
@@ -1609,7 +1639,10 @@ static int mvneta_probe(struct udevice *dev)
 	pp->base = (void __iomem *)pdata->iobase;
 
 	/* Configure MBUS address windows */
-	mvneta_conf_mbus_windows(pp);
+	if (of_device_is_compatible(dev, "marvell,armada-3700-neta"))
+		mvneta_bypass_mbus_windows(pp);
+	else
+		mvneta_conf_mbus_windows(pp);
 
 	/* PHY interface is already decoded in mvneta_ofdata_to_platdata() */
 	pp->phy_interface = pdata->phy_interface;
@@ -1672,6 +1705,7 @@ static int mvneta_ofdata_to_platdata(struct udevice *dev)
 static const struct udevice_id mvneta_ids[] = {
 	{ .compatible = "marvell,armada-370-neta" },
 	{ .compatible = "marvell,armada-xp-neta" },
+	{ .compatible = "marvell,armada-3700-neta" },
 	{ }
 };
 
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 09/15 v2] arm64: mvebu: Armada 3700: Add SPI device tree nodes
  2016-09-16 13:09 ` [U-Boot] [PATCH 09/15] arm64: mvebu: Armada 3700: Add SPI device tree nodes Stefan Roese
  2016-09-21  8:02   ` Jagan Teki
@ 2016-09-23 11:37   ` Stefan Roese
  2016-09-23 11:49     ` Jagan Teki
  1 sibling, 1 reply; 36+ messages in thread
From: Stefan Roese @ 2016-09-23 11:37 UTC (permalink / raw)
  To: u-boot

This patch adds the SPI device tree nodes that are still missing to
the Armada 3700 dts files.

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>
---
v2:
- Use "spi-flash" instead of "jedec,spi-nor" as suggested by Jagan

 arch/arm/dts/armada-3720-db.dts | 17 +++++++++++++++++
 arch/arm/dts/armada-37xx.dtsi   | 11 +++++++++++
 2 files changed, 28 insertions(+)

diff --git a/arch/arm/dts/armada-3720-db.dts b/arch/arm/dts/armada-3720-db.dts
index 86110a6..7bfa840 100644
--- a/arch/arm/dts/armada-3720-db.dts
+++ b/arch/arm/dts/armada-3720-db.dts
@@ -56,6 +56,10 @@
 		stdout-path = "serial0:115200n8";
 	};
 
+	aliases {
+		spi0 = &spi0;
+	};
+
 	memory {
 		device_type = "memory";
 		reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
@@ -67,6 +71,19 @@
 	status = "okay";
 };
 
+&spi0 {
+	status = "okay";
+
+	spi-flash at 0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "st,m25p128", "spi-flash";
+		reg = <0>; /* Chip select 0 */
+		spi-max-frequency = <50000000>;
+		m25p,fast-read;
+	};
+};
+
 /* Exported on the micro USB connector CON32 through an FTDI */
 &uart0 {
 	status = "okay";
diff --git a/arch/arm/dts/armada-37xx.dtsi b/arch/arm/dts/armada-37xx.dtsi
index 9e2efb8..bb14f54 100644
--- a/arch/arm/dts/armada-37xx.dtsi
+++ b/arch/arm/dts/armada-37xx.dtsi
@@ -140,6 +140,17 @@
 				reg = <0x1d00000 0x10000>, /* GICD */
 				      <0x1d40000 0x40000>; /* GICR */
 			};
+
+			spi0: spi at 10600 {
+				compatible = "marvell,armada-3700-spi";
+				reg = <0x10600 0x50>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				#clock-cells = <0>;
+				clock-frequency = <160000>;
+				spi-max-frequency = <40000>;
+				status = "disabled";
+			};
 		};
 	};
 };
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 09/15 v2] arm64: mvebu: Armada 3700: Add SPI device tree nodes
  2016-09-23 11:37   ` [U-Boot] [PATCH 09/15 v2] " Stefan Roese
@ 2016-09-23 11:49     ` Jagan Teki
  0 siblings, 0 replies; 36+ messages in thread
From: Jagan Teki @ 2016-09-23 11:49 UTC (permalink / raw)
  To: u-boot

On Fri, Sep 23, 2016 at 5:07 PM, Stefan Roese <sr@denx.de> wrote:
> This patch adds the SPI device tree nodes that are still missing to
> the Armada 3700 dts files.
>
> 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>
> ---
> v2:
> - Use "spi-flash" instead of "jedec,spi-nor" as suggested by Jagan

Reviewed-by: Jagan Teki <jteki@openedev.com>

thanks!
-- 
Jagan Teki
Free Software Engineer | www.openedev.com
U-Boot, Linux | Upstream Maintainer
Hyderabad, India.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 02/15] spi: Add driver for Marvell Armada 3700 SoC
  2016-09-21  7:56   ` Jagan Teki
@ 2016-09-23 12:14     ` Stefan Roese
  0 siblings, 0 replies; 36+ messages in thread
From: Stefan Roese @ 2016-09-23 12:14 UTC (permalink / raw)
  To: u-boot

On 21.09.2016 09:56, Jagan Teki wrote:
> On Fri, Sep 16, 2016 at 6:39 PM, Stefan Roese <sr@denx.de> wrote:
>> The SPI IP core in the Marvell Armada 3700 is similar to the one in the
>> other Armada SoCs. But the differences are big enough that it makes
>> sense to introduce a new driver instead of cluttering the old
>> kirkwood driver with #ifdef's.
>>
>> 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>
>> Cc: Jagan Teki <jteki@openedev.com>
>> ---
>>  drivers/spi/Kconfig           |   7 ++
>>  drivers/spi/Makefile          |   1 +
>>  drivers/spi/mvebu_a3700_spi.c | 281 ++++++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 289 insertions(+)
>>  create mode 100644 drivers/spi/mvebu_a3700_spi.c
>>
>> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
>> index aca385d..bc5e716 100644
>> --- a/drivers/spi/Kconfig
>> +++ b/drivers/spi/Kconfig
>> @@ -75,6 +75,13 @@ config ICH_SPI
>>           access the SPI NOR flash on platforms embedding this Intel
>>           ICH IP core.
>>
>> +config MVEBU_A3700_SPI
>> +       bool "Marvell Armada 3700 SPI driver"
>> +       help
>> +         Enable the Marvell Armada 3700 SPI driver. This driver can be
>> +         used to access the SPI NOR flash on platforms embedding this
>> +         Marvell IP core.
>> +
>>  config PIC32_SPI
>>         bool "Microchip PIC32 SPI driver"
>>         depends on MACH_PIC32
>> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
>> index b1d9e20..247c5f6 100644
>> --- a/drivers/spi/Makefile
>> +++ b/drivers/spi/Makefile
>> @@ -37,6 +37,7 @@ obj-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
>>  obj-$(CONFIG_LPC32XX_SSP) += lpc32xx_ssp.o
>>  obj-$(CONFIG_MPC52XX_SPI) += mpc52xx_spi.o
>>  obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
>> +obj-$(CONFIG_MVEBU_A3700_SPI) += mvebu_a3700_spi.o
>>  obj-$(CONFIG_MXC_SPI) += mxc_spi.o
>>  obj-$(CONFIG_MXS_SPI) += mxs_spi.o
>>  obj-$(CONFIG_OMAP3_SPI) += omap3_spi.o
>> diff --git a/drivers/spi/mvebu_a3700_spi.c b/drivers/spi/mvebu_a3700_spi.c
>> new file mode 100644
>> index 0000000..26f9a8f
>> --- /dev/null
>> +++ b/drivers/spi/mvebu_a3700_spi.c
>> @@ -0,0 +1,281 @@
>> +/*
>> + * Copyright (C) 2015 Marvell International Ltd.
>> + *
>> + * Copyright (C) 2016 Stefan Roese <sr@denx.de>
>> + *
>> + * SPDX-License-Identifier:    GPL-2.0+
>> + */
>> +
>> +#include <common.h>
>> +#include <dm.h>
>> +#include <malloc.h>
>> +#include <spi.h>
>> +#include <wait_bit.h>
>> +#include <asm/io.h>
>> +
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> +#define SPI_TIMEOUT                            10000
>> +
>> +#define MVEBU_SPI_A3700_XFER_RDY               BIT(1)
>> +#define MVEBU_SPI_A3700_FIFO_FLUSH             BIT(9)
>> +#define MVEBU_SPI_A3700_BYTE_LEN               BIT(5)
>> +#define MVEBU_SPI_A3700_CLK_PHA                        BIT(6)
>> +#define MVEBU_SPI_A3700_CLK_POL                        BIT(7)
>> +#define MVEBU_SPI_A3700_FIFO_EN                        BIT(17)
>> +#define MVEBU_SPI_A3700_SPI_EN_0               BIT(16)
>> +#define MVEBU_SPI_A3700_CLK_PRESCALE_BIT       0
>> +#define MVEBU_SPI_A3700_CLK_PRESCALE_MASK      \
>> +       (0x1f << MVEBU_SPI_A3700_CLK_PRESCALE_BIT)
>> +
>> +/* SPI registers */
>> +struct spi_reg {
>> +       u32 ctrl;       /* 0x10600 */
>> +       u32 cfg;        /* 0x10604 */
>> +       u32 dout;       /* 0x10608 */
>> +       u32 din;        /* 0x1060c */
>> +};
>> +
>> +struct mvebu_spi_platdata {
>> +       struct spi_reg *spireg;
>> +};
>> +
>> +static void spi_cs_activate(struct spi_reg *reg, int cs)
>> +{
>> +       setbits_le32(&reg->ctrl, MVEBU_SPI_A3700_SPI_EN_0 << cs);
>> +}
>> +
>> +static void spi_cs_deactivate(struct spi_reg *reg, int cs)
>> +{
>> +       clrbits_le32(&reg->ctrl, MVEBU_SPI_A3700_SPI_EN_0 << cs);
>> +}
>> +
>> +/**
>> + * spi_legacy_shift_byte() - triggers the real SPI transfer
>> + * @bytelen:   Indicate how many bytes to transfer.
>> + * @dout:      Buffer address of what to send.
>> + * @din:       Buffer address of where to receive.
>> + *
>> + * This function triggers the real SPI transfer in legacy mode. It
>> + * will shift out char buffer from @dout, and shift in char buffer to
>> + * @din, if necessary.
>> + *
>> + * This function assumes that only one byte is shifted at one time.
>> + * However, it is not its responisbility to set the transfer type to
>> + * one-byte. Also, it does not guarantee that it will work if transfer
>> + * type becomes two-byte. See spi_set_legacy() for details.
>> + *
>> + * In legacy mode, simply write to the SPI_DOUT register will trigger
>> + * the transfer.
>> + *
>> + * If @dout == NULL, which means no actual data needs to be sent out,
>> + * then the function will shift out 0x00 in order to shift in data.
>> + * The XFER_RDY flag is checked every time before accessing SPI_DOUT
>> + * and SPI_DIN register.
>> + *
>> + * The number of transfers to be triggerred is decided by @bytelen.
>> + *
>> + * Return:     0 - cool
>> + *             -ETIMEDOUT - XFER_RDY flag timeout
>> + */
>> +static int spi_legacy_shift_byte(struct spi_reg *reg, unsigned int bytelen,
>> +                                const void *dout, void *din)
>> +{
>> +       const u8 *dout_8;
>> +       u8 *din_8;
>> +       int ret;
>> +
>> +       /* Use 0x00 as dummy dout */
>> +       const u8 dummy_dout = 0x0;
>> +       u32 pending_dout = 0x0;
>> +
>> +       /* dout_8: pointer of current dout */
>> +       dout_8 = dout;
>> +       /* din_8: pointer of current din */
>> +       din_8 = din;
>> +
>> +       while (bytelen) {
>> +               ret = wait_for_bit(__func__, &reg->ctrl,
>> +                                  MVEBU_SPI_A3700_XFER_RDY, true, 100, false);
> 
> Do we have any documentation in data sheet or something for this 100 ms?

No, not really.
 
>> +               if (ret)
>> +                       return ret;
>> +
>> +               if (dout)
>> +                       pending_dout = (u32)*dout_8;
>> +               else
>> +                       pending_dout = (u32)dummy_dout;
>> +
>> +               /* Trigger the xfer */
>> +               writel(pending_dout, &reg->dout);
>> +
>> +               if (din) {
>> +                       ret = wait_for_bit(__func__, &reg->ctrl,
>> +                                          MVEBU_SPI_A3700_XFER_RDY,
>> +                                          true, 100, false);
>> +                       if (ret)
>> +                               return ret;
>> +
>> +                       /* Read what is transferred in */
>> +                       *din_8 = (u8)readl(&reg->din);
>> +               }
>> +
>> +               /* Don't increment the current pointer if NULL */
>> +               if (dout)
>> +                       dout_8++;
>> +               if (din)
>> +                       din_8++;
>> +
>> +               bytelen--;
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static int mvebu_spi_xfer(struct udevice *dev, unsigned int bitlen,
>> +                         const void *dout, void *din, unsigned long flags)
>> +{
>> +       struct udevice *bus = dev->parent;
>> +       struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
>> +       struct spi_reg *reg = plat->spireg;
>> +       unsigned int bytelen;
>> +       int ret;
>> +
>> +       bytelen = bitlen / 8;
>> +
>> +       if (dout && din)
>> +               debug("This is a duplex transfer.\n");
>> +
>> +       /* Activate CS */
>> +       if (flags & SPI_XFER_BEGIN) {
>> +               debug("SPI: activate cs.\n");
>> +               spi_cs_activate(reg, spi_chip_select(dev));
>> +       }
>> +
>> +       /* Send and/or receive */
>> +       if (dout || din) {
>> +               ret = spi_legacy_shift_byte(reg, bytelen, dout, din);
>> +               if (ret)
>> +                       return ret;
>> +       }
>> +
>> +       /* Deactivate CS */
>> +       if (flags & SPI_XFER_END) {
>> +               ret = wait_for_bit(__func__, &reg->ctrl,
>> +                                  MVEBU_SPI_A3700_XFER_RDY, true, 100, false);
>> +               if (ret)
>> +                       return ret;
>> +
>> +               debug("SPI: deactivate cs.\n");
>> +               spi_cs_deactivate(reg, spi_chip_select(dev));
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static int mvebu_spi_set_speed(struct udevice *bus, uint hz)
>> +{
>> +       struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
>> +       struct spi_reg *reg = plat->spireg;
>> +       u32 data;
>> +
>> +       data = readl(&reg->cfg);
>> +
>> +       /* Set Prescaler */
>> +       data &= ~MVEBU_SPI_A3700_CLK_PRESCALE_MASK;
>> +
>> +       /* Calculate Prescaler = (spi_input_freq / spi_max_freq) */
>> +       /* ToDo: get real values for clock and frequency */
>> +       data |= 160000 / 40000;
> 
> Better to get these from dt atleast for now and also please set the
> freq/baud value by evaluating using input 'hz'

Okay. Updated for v2 - coming soon...

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 02/15 v2] spi: Add driver for Marvell Armada 3700 SoC
  2016-09-16 13:09 ` [U-Boot] [PATCH 02/15] spi: Add driver for Marvell " Stefan Roese
  2016-09-21  7:56   ` Jagan Teki
@ 2016-09-23 12:17   ` Stefan Roese
  2016-09-23 12:53     ` Jagan Teki
  2016-09-23 14:28   ` [U-Boot] [PATCH 02/15 v3] " Stefan Roese
  2 siblings, 1 reply; 36+ messages in thread
From: Stefan Roese @ 2016-09-23 12:17 UTC (permalink / raw)
  To: u-boot

The SPI IP core in the Marvell Armada 3700 is similar to the one in the
other Armada SoCs. But the differences are big enough that it makes
sense to introduce a new driver instead of cluttering the old
kirkwood driver with #ifdef's.

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>
Cc: Jagan Teki <jteki@openedev.com>
---
v2:
- Evaluated hz and used values provided by the DT in mvebu_spi_set_speed()
  as suggested by Jagan

 drivers/spi/Kconfig           |   7 +
 drivers/spi/Makefile          |   1 +
 drivers/spi/mvebu_a3700_spi.c | 289 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 297 insertions(+)
 create mode 100644 drivers/spi/mvebu_a3700_spi.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 5da66a6..8724f87 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -68,6 +68,13 @@ config ICH_SPI
 	  access the SPI NOR flash on platforms embedding this Intel
 	  ICH IP core.
 
+config MVEBU_A3700_SPI
+	bool "Marvell Armada 3700 SPI driver"
+	help
+	  Enable the Marvell Armada 3700 SPI driver. This driver can be
+	  used to access the SPI NOR flash on platforms embedding this
+	  Marvell IP core.
+
 config PIC32_SPI
 	bool "Microchip PIC32 SPI driver"
 	depends on MACH_PIC32
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index b1d9e20..247c5f6 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
 obj-$(CONFIG_LPC32XX_SSP) += lpc32xx_ssp.o
 obj-$(CONFIG_MPC52XX_SPI) += mpc52xx_spi.o
 obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
+obj-$(CONFIG_MVEBU_A3700_SPI) += mvebu_a3700_spi.o
 obj-$(CONFIG_MXC_SPI) += mxc_spi.o
 obj-$(CONFIG_MXS_SPI) += mxs_spi.o
 obj-$(CONFIG_OMAP3_SPI) += omap3_spi.o
diff --git a/drivers/spi/mvebu_a3700_spi.c b/drivers/spi/mvebu_a3700_spi.c
new file mode 100644
index 0000000..b566e03
--- /dev/null
+++ b/drivers/spi/mvebu_a3700_spi.c
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2015 Marvell International Ltd.
+ *
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <malloc.h>
+#include <spi.h>
+#include <wait_bit.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define SPI_TIMEOUT				10000
+
+#define MVEBU_SPI_A3700_XFER_RDY		BIT(1)
+#define MVEBU_SPI_A3700_FIFO_FLUSH		BIT(9)
+#define MVEBU_SPI_A3700_BYTE_LEN		BIT(5)
+#define MVEBU_SPI_A3700_CLK_PHA			BIT(6)
+#define MVEBU_SPI_A3700_CLK_POL			BIT(7)
+#define MVEBU_SPI_A3700_FIFO_EN			BIT(17)
+#define MVEBU_SPI_A3700_SPI_EN_0		BIT(16)
+#define MVEBU_SPI_A3700_CLK_PRESCALE_BIT	0
+#define MVEBU_SPI_A3700_CLK_PRESCALE_MASK	\
+	(0x1f << MVEBU_SPI_A3700_CLK_PRESCALE_BIT)
+
+/* SPI registers */
+struct spi_reg {
+	u32 ctrl;	/* 0x10600 */
+	u32 cfg;	/* 0x10604 */
+	u32 dout;	/* 0x10608 */
+	u32 din;	/* 0x1060c */
+};
+
+struct mvebu_spi_platdata {
+	struct spi_reg *spireg;
+	unsigned int frequency;
+	unsigned int clock;
+};
+
+static void spi_cs_activate(struct spi_reg *reg, int cs)
+{
+	setbits_le32(&reg->ctrl, MVEBU_SPI_A3700_SPI_EN_0 << cs);
+}
+
+static void spi_cs_deactivate(struct spi_reg *reg, int cs)
+{
+	clrbits_le32(&reg->ctrl, MVEBU_SPI_A3700_SPI_EN_0 << cs);
+}
+
+/**
+ * spi_legacy_shift_byte() - triggers the real SPI transfer
+ * @bytelen:	Indicate how many bytes to transfer.
+ * @dout:	Buffer address of what to send.
+ * @din:	Buffer address of where to receive.
+ *
+ * This function triggers the real SPI transfer in legacy mode. It
+ * will shift out char buffer from @dout, and shift in char buffer to
+ * @din, if necessary.
+ *
+ * This function assumes that only one byte is shifted@one time.
+ * However, it is not its responisbility to set the transfer type to
+ * one-byte. Also, it does not guarantee that it will work if transfer
+ * type becomes two-byte. See spi_set_legacy() for details.
+ *
+ * In legacy mode, simply write to the SPI_DOUT register will trigger
+ * the transfer.
+ *
+ * If @dout == NULL, which means no actual data needs to be sent out,
+ * then the function will shift out 0x00 in order to shift in data.
+ * The XFER_RDY flag is checked every time before accessing SPI_DOUT
+ * and SPI_DIN register.
+ *
+ * The number of transfers to be triggerred is decided by @bytelen.
+ *
+ * Return:	0 - cool
+ *		-ETIMEDOUT - XFER_RDY flag timeout
+ */
+static int spi_legacy_shift_byte(struct spi_reg *reg, unsigned int bytelen,
+				 const void *dout, void *din)
+{
+	const u8 *dout_8;
+	u8 *din_8;
+	int ret;
+
+	/* Use 0x00 as dummy dout */
+	const u8 dummy_dout = 0x0;
+	u32 pending_dout = 0x0;
+
+	/* dout_8: pointer of current dout */
+	dout_8 = dout;
+	/* din_8: pointer of current din */
+	din_8 = din;
+
+	while (bytelen) {
+		ret = wait_for_bit(__func__, &reg->ctrl,
+				   MVEBU_SPI_A3700_XFER_RDY, true, 100, false);
+		if (ret)
+			return ret;
+
+		if (dout)
+			pending_dout = (u32)*dout_8;
+		else
+			pending_dout = (u32)dummy_dout;
+
+		/* Trigger the xfer */
+		writel(pending_dout, &reg->dout);
+
+		if (din) {
+			ret = wait_for_bit(__func__, &reg->ctrl,
+					   MVEBU_SPI_A3700_XFER_RDY,
+					   true, 100, false);
+			if (ret)
+				return ret;
+
+			/* Read what is transferred in */
+			*din_8 = (u8)readl(&reg->din);
+		}
+
+		/* Don't increment the current pointer if NULL */
+		if (dout)
+			dout_8++;
+		if (din)
+			din_8++;
+
+		bytelen--;
+	}
+
+	return 0;
+}
+
+static int mvebu_spi_xfer(struct udevice *dev, unsigned int bitlen,
+			  const void *dout, void *din, unsigned long flags)
+{
+	struct udevice *bus = dev->parent;
+	struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
+	struct spi_reg *reg = plat->spireg;
+	unsigned int bytelen;
+	int ret;
+
+	bytelen = bitlen / 8;
+
+	if (dout && din)
+		debug("This is a duplex transfer.\n");
+
+	/* Activate CS */
+	if (flags & SPI_XFER_BEGIN) {
+		debug("SPI: activate cs.\n");
+		spi_cs_activate(reg, spi_chip_select(dev));
+	}
+
+	/* Send and/or receive */
+	if (dout || din) {
+		ret = spi_legacy_shift_byte(reg, bytelen, dout, din);
+		if (ret)
+			return ret;
+	}
+
+	/* Deactivate CS */
+	if (flags & SPI_XFER_END) {
+		ret = wait_for_bit(__func__, &reg->ctrl,
+				   MVEBU_SPI_A3700_XFER_RDY, true, 100, false);
+		if (ret)
+			return ret;
+
+		debug("SPI: deactivate cs.\n");
+		spi_cs_deactivate(reg, spi_chip_select(dev));
+	}
+
+	return 0;
+}
+
+static int mvebu_spi_set_speed(struct udevice *bus, uint hz)
+{
+	struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
+	struct spi_reg *reg = plat->spireg;
+	u32 data;
+
+	data = readl(&reg->cfg);
+
+	/* Set Prescaler */
+	data &= ~MVEBU_SPI_A3700_CLK_PRESCALE_MASK;
+
+	/* Calculate Prescaler = (spi_input_freq / spi_max_freq) */
+	if (hz > plat->frequency)
+		hz = plat->frequency;
+	data |= plat->clock / plat->frequency;
+
+	writel(data, &reg->cfg);
+
+	return 0;
+}
+
+static int mvebu_spi_set_mode(struct udevice *bus, uint mode)
+{
+	struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
+	struct spi_reg *reg = plat->spireg;
+
+	/*
+	 * Set SPI polarity
+	 * 0: Serial interface clock is low when inactive
+	 * 1: Serial interface clock is high when inactive
+	 */
+	if (mode & SPI_CPOL)
+		setbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_POL);
+	else
+		clrbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_POL);
+	if (mode & SPI_CPHA)
+		setbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_PHA);
+	else
+		clrbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_PHA);
+
+	return 0;
+}
+
+static int mvebu_spi_probe(struct udevice *bus)
+{
+	struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
+	struct spi_reg *reg = plat->spireg;
+	u32 data;
+	int ret;
+
+	/*
+	 * Settings SPI controller to be working in legacy mode, which
+	 * means use only DO pin (I/O 1) for Data Out, and DI pin (I/O 0)
+	 * for Data In.
+	 */
+
+	/* Flush read/write FIFO */
+	data = readl(&reg->cfg);
+	writel(data | MVEBU_SPI_A3700_FIFO_FLUSH, &reg->cfg);
+	ret = wait_for_bit(__func__, &reg->cfg, MVEBU_SPI_A3700_FIFO_FLUSH,
+			   false, 1000, false);
+	if (ret)
+		return ret;
+
+	/* Disable FIFO mode */
+	data &= ~MVEBU_SPI_A3700_FIFO_EN;
+
+	/* Always shift 1 byte at a time */
+	data &= ~MVEBU_SPI_A3700_BYTE_LEN;
+
+	writel(data, &reg->cfg);
+
+	return 0;
+}
+
+static int mvebu_spi_ofdata_to_platdata(struct udevice *bus)
+{
+	struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
+
+	plat->spireg = (struct spi_reg *)dev_get_addr(bus);
+
+	plat->clock = fdtdec_get_int(gd->fdt_blob, bus->of_offset,
+				     "clock-frequency", 160000);
+	plat->frequency = fdtdec_get_int(gd->fdt_blob, bus->of_offset,
+					 "spi-max-frequency", 40000);
+
+	return 0;
+}
+
+static const struct dm_spi_ops mvebu_spi_ops = {
+	.xfer		= mvebu_spi_xfer,
+	.set_speed	= mvebu_spi_set_speed,
+	.set_mode	= mvebu_spi_set_mode,
+	/*
+	 * cs_info is not needed, since we require all chip selects to be
+	 * in the device tree explicitly
+	 */
+};
+
+static const struct udevice_id mvebu_spi_ids[] = {
+	{ .compatible = "marvell,armada-3700-spi" },
+	{ }
+};
+
+U_BOOT_DRIVER(mvebu_spi) = {
+	.name = "mvebu_spi",
+	.id = UCLASS_SPI,
+	.of_match = mvebu_spi_ids,
+	.ops = &mvebu_spi_ops,
+	.ofdata_to_platdata = mvebu_spi_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct mvebu_spi_platdata),
+	.probe = mvebu_spi_probe,
+};
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 02/15 v2] spi: Add driver for Marvell Armada 3700 SoC
  2016-09-23 12:17   ` [U-Boot] [PATCH 02/15 v2] " Stefan Roese
@ 2016-09-23 12:53     ` Jagan Teki
  2016-09-23 13:24       ` Stefan Roese
  0 siblings, 1 reply; 36+ messages in thread
From: Jagan Teki @ 2016-09-23 12:53 UTC (permalink / raw)
  To: u-boot

On Fri, Sep 23, 2016 at 5:47 PM, Stefan Roese <sr@denx.de> wrote:
> The SPI IP core in the Marvell Armada 3700 is similar to the one in the
> other Armada SoCs. But the differences are big enough that it makes
> sense to introduce a new driver instead of cluttering the old
> kirkwood driver with #ifdef's.
>
> 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>
> Cc: Jagan Teki <jteki@openedev.com>
> ---
> v2:
> - Evaluated hz and used values provided by the DT in mvebu_spi_set_speed()
>   as suggested by Jagan
>
>  drivers/spi/Kconfig           |   7 +
>  drivers/spi/Makefile          |   1 +
>  drivers/spi/mvebu_a3700_spi.c | 289 ++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 297 insertions(+)
>  create mode 100644 drivers/spi/mvebu_a3700_spi.c
>
> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> index 5da66a6..8724f87 100644
> --- a/drivers/spi/Kconfig
> +++ b/drivers/spi/Kconfig
> @@ -68,6 +68,13 @@ config ICH_SPI
>           access the SPI NOR flash on platforms embedding this Intel
>           ICH IP core.
>
> +config MVEBU_A3700_SPI
> +       bool "Marvell Armada 3700 SPI driver"
> +       help
> +         Enable the Marvell Armada 3700 SPI driver. This driver can be
> +         used to access the SPI NOR flash on platforms embedding this
> +         Marvell IP core.
> +
>  config PIC32_SPI
>         bool "Microchip PIC32 SPI driver"
>         depends on MACH_PIC32
> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
> index b1d9e20..247c5f6 100644
> --- a/drivers/spi/Makefile
> +++ b/drivers/spi/Makefile
> @@ -37,6 +37,7 @@ obj-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
>  obj-$(CONFIG_LPC32XX_SSP) += lpc32xx_ssp.o
>  obj-$(CONFIG_MPC52XX_SPI) += mpc52xx_spi.o
>  obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
> +obj-$(CONFIG_MVEBU_A3700_SPI) += mvebu_a3700_spi.o
>  obj-$(CONFIG_MXC_SPI) += mxc_spi.o
>  obj-$(CONFIG_MXS_SPI) += mxs_spi.o
>  obj-$(CONFIG_OMAP3_SPI) += omap3_spi.o
> diff --git a/drivers/spi/mvebu_a3700_spi.c b/drivers/spi/mvebu_a3700_spi.c
> new file mode 100644
> index 0000000..b566e03
> --- /dev/null
> +++ b/drivers/spi/mvebu_a3700_spi.c
> @@ -0,0 +1,289 @@
> +/*
> + * Copyright (C) 2015 Marvell International Ltd.
> + *
> + * Copyright (C) 2016 Stefan Roese <sr@denx.de>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <malloc.h>
> +#include <spi.h>
> +#include <wait_bit.h>
> +#include <asm/io.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#define SPI_TIMEOUT                            10000
> +
> +#define MVEBU_SPI_A3700_XFER_RDY               BIT(1)
> +#define MVEBU_SPI_A3700_FIFO_FLUSH             BIT(9)
> +#define MVEBU_SPI_A3700_BYTE_LEN               BIT(5)
> +#define MVEBU_SPI_A3700_CLK_PHA                        BIT(6)
> +#define MVEBU_SPI_A3700_CLK_POL                        BIT(7)
> +#define MVEBU_SPI_A3700_FIFO_EN                        BIT(17)
> +#define MVEBU_SPI_A3700_SPI_EN_0               BIT(16)
> +#define MVEBU_SPI_A3700_CLK_PRESCALE_BIT       0
> +#define MVEBU_SPI_A3700_CLK_PRESCALE_MASK      \
> +       (0x1f << MVEBU_SPI_A3700_CLK_PRESCALE_BIT)
> +
> +/* SPI registers */
> +struct spi_reg {
> +       u32 ctrl;       /* 0x10600 */
> +       u32 cfg;        /* 0x10604 */
> +       u32 dout;       /* 0x10608 */
> +       u32 din;        /* 0x1060c */
> +};
> +
> +struct mvebu_spi_platdata {
> +       struct spi_reg *spireg;
> +       unsigned int frequency;
> +       unsigned int clock;
> +};
> +
> +static void spi_cs_activate(struct spi_reg *reg, int cs)
> +{
> +       setbits_le32(&reg->ctrl, MVEBU_SPI_A3700_SPI_EN_0 << cs);
> +}
> +
> +static void spi_cs_deactivate(struct spi_reg *reg, int cs)
> +{
> +       clrbits_le32(&reg->ctrl, MVEBU_SPI_A3700_SPI_EN_0 << cs);
> +}
> +
> +/**
> + * spi_legacy_shift_byte() - triggers the real SPI transfer
> + * @bytelen:   Indicate how many bytes to transfer.
> + * @dout:      Buffer address of what to send.
> + * @din:       Buffer address of where to receive.
> + *
> + * This function triggers the real SPI transfer in legacy mode. It
> + * will shift out char buffer from @dout, and shift in char buffer to
> + * @din, if necessary.
> + *
> + * This function assumes that only one byte is shifted at one time.
> + * However, it is not its responisbility to set the transfer type to
> + * one-byte. Also, it does not guarantee that it will work if transfer
> + * type becomes two-byte. See spi_set_legacy() for details.
> + *
> + * In legacy mode, simply write to the SPI_DOUT register will trigger
> + * the transfer.
> + *
> + * If @dout == NULL, which means no actual data needs to be sent out,
> + * then the function will shift out 0x00 in order to shift in data.
> + * The XFER_RDY flag is checked every time before accessing SPI_DOUT
> + * and SPI_DIN register.
> + *
> + * The number of transfers to be triggerred is decided by @bytelen.
> + *
> + * Return:     0 - cool
> + *             -ETIMEDOUT - XFER_RDY flag timeout
> + */
> +static int spi_legacy_shift_byte(struct spi_reg *reg, unsigned int bytelen,
> +                                const void *dout, void *din)
> +{
> +       const u8 *dout_8;
> +       u8 *din_8;
> +       int ret;
> +
> +       /* Use 0x00 as dummy dout */
> +       const u8 dummy_dout = 0x0;
> +       u32 pending_dout = 0x0;
> +
> +       /* dout_8: pointer of current dout */
> +       dout_8 = dout;
> +       /* din_8: pointer of current din */
> +       din_8 = din;
> +
> +       while (bytelen) {
> +               ret = wait_for_bit(__func__, &reg->ctrl,
> +                                  MVEBU_SPI_A3700_XFER_RDY, true, 100, false);
> +               if (ret)
> +                       return ret;
> +
> +               if (dout)
> +                       pending_dout = (u32)*dout_8;
> +               else
> +                       pending_dout = (u32)dummy_dout;
> +
> +               /* Trigger the xfer */
> +               writel(pending_dout, &reg->dout);
> +
> +               if (din) {
> +                       ret = wait_for_bit(__func__, &reg->ctrl,
> +                                          MVEBU_SPI_A3700_XFER_RDY,
> +                                          true, 100, false);
> +                       if (ret)
> +                               return ret;
> +
> +                       /* Read what is transferred in */
> +                       *din_8 = (u8)readl(&reg->din);
> +               }
> +
> +               /* Don't increment the current pointer if NULL */
> +               if (dout)
> +                       dout_8++;
> +               if (din)
> +                       din_8++;
> +
> +               bytelen--;
> +       }
> +
> +       return 0;
> +}
> +
> +static int mvebu_spi_xfer(struct udevice *dev, unsigned int bitlen,
> +                         const void *dout, void *din, unsigned long flags)
> +{
> +       struct udevice *bus = dev->parent;
> +       struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
> +       struct spi_reg *reg = plat->spireg;
> +       unsigned int bytelen;
> +       int ret;
> +
> +       bytelen = bitlen / 8;
> +
> +       if (dout && din)
> +               debug("This is a duplex transfer.\n");
> +
> +       /* Activate CS */
> +       if (flags & SPI_XFER_BEGIN) {
> +               debug("SPI: activate cs.\n");
> +               spi_cs_activate(reg, spi_chip_select(dev));
> +       }
> +
> +       /* Send and/or receive */
> +       if (dout || din) {
> +               ret = spi_legacy_shift_byte(reg, bytelen, dout, din);
> +               if (ret)
> +                       return ret;
> +       }
> +
> +       /* Deactivate CS */
> +       if (flags & SPI_XFER_END) {
> +               ret = wait_for_bit(__func__, &reg->ctrl,
> +                                  MVEBU_SPI_A3700_XFER_RDY, true, 100, false);
> +               if (ret)
> +                       return ret;
> +
> +               debug("SPI: deactivate cs.\n");
> +               spi_cs_deactivate(reg, spi_chip_select(dev));
> +       }
> +
> +       return 0;
> +}
> +
> +static int mvebu_spi_set_speed(struct udevice *bus, uint hz)
> +{
> +       struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
> +       struct spi_reg *reg = plat->spireg;
> +       u32 data;
> +
> +       data = readl(&reg->cfg);
> +
> +       /* Set Prescaler */
> +       data &= ~MVEBU_SPI_A3700_CLK_PRESCALE_MASK;
> +
> +       /* Calculate Prescaler = (spi_input_freq / spi_max_freq) */
> +       if (hz > plat->frequency)
> +               hz = plat->frequency;
> +       data |= plat->clock / plat->frequency;

Need to use the hz to compute here.

> +
> +       writel(data, &reg->cfg);
> +
> +       return 0;
> +}
> +
> +static int mvebu_spi_set_mode(struct udevice *bus, uint mode)
> +{
> +       struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
> +       struct spi_reg *reg = plat->spireg;
> +
> +       /*
> +        * Set SPI polarity
> +        * 0: Serial interface clock is low when inactive
> +        * 1: Serial interface clock is high when inactive
> +        */
> +       if (mode & SPI_CPOL)
> +               setbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_POL);
> +       else
> +               clrbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_POL);
> +       if (mode & SPI_CPHA)
> +               setbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_PHA);
> +       else
> +               clrbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_PHA);
> +
> +       return 0;
> +}
> +
> +static int mvebu_spi_probe(struct udevice *bus)
> +{
> +       struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
> +       struct spi_reg *reg = plat->spireg;
> +       u32 data;
> +       int ret;
> +
> +       /*
> +        * Settings SPI controller to be working in legacy mode, which
> +        * means use only DO pin (I/O 1) for Data Out, and DI pin (I/O 0)
> +        * for Data In.
> +        */
> +
> +       /* Flush read/write FIFO */
> +       data = readl(&reg->cfg);
> +       writel(data | MVEBU_SPI_A3700_FIFO_FLUSH, &reg->cfg);
> +       ret = wait_for_bit(__func__, &reg->cfg, MVEBU_SPI_A3700_FIFO_FLUSH,
> +                          false, 1000, false);
> +       if (ret)
> +               return ret;
> +
> +       /* Disable FIFO mode */
> +       data &= ~MVEBU_SPI_A3700_FIFO_EN;
> +
> +       /* Always shift 1 byte at a time */
> +       data &= ~MVEBU_SPI_A3700_BYTE_LEN;
> +
> +       writel(data, &reg->cfg);
> +
> +       return 0;
> +}
> +
> +static int mvebu_spi_ofdata_to_platdata(struct udevice *bus)
> +{
> +       struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
> +
> +       plat->spireg = (struct spi_reg *)dev_get_addr(bus);
> +
> +       plat->clock = fdtdec_get_int(gd->fdt_blob, bus->of_offset,
> +                                    "clock-frequency", 160000);

I think this is not related to spi, global clock is it? usually we
can't use clock-frequency we set the clock with the help of
spi-max-frequency.

thanks!
-- 
Jagan Teki
Free Software Engineer | www.openedev.com
U-Boot, Linux | Upstream Maintainer
Hyderabad, India.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 02/15 v2] spi: Add driver for Marvell Armada 3700 SoC
  2016-09-23 12:53     ` Jagan Teki
@ 2016-09-23 13:24       ` Stefan Roese
  2016-09-23 14:03         ` Jagan Teki
  0 siblings, 1 reply; 36+ messages in thread
From: Stefan Roese @ 2016-09-23 13:24 UTC (permalink / raw)
  To: u-boot

On 23.09.2016 14:53, Jagan Teki wrote:
> On Fri, Sep 23, 2016 at 5:47 PM, Stefan Roese <sr@denx.de> wrote:
>> The SPI IP core in the Marvell Armada 3700 is similar to the one in the
>> other Armada SoCs. But the differences are big enough that it makes
>> sense to introduce a new driver instead of cluttering the old
>> kirkwood driver with #ifdef's.
>>
>> 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>
>> Cc: Jagan Teki <jteki@openedev.com>
>> ---
>> v2:
>> - Evaluated hz and used values provided by the DT in mvebu_spi_set_speed()
>>   as suggested by Jagan
>>
>>  drivers/spi/Kconfig           |   7 +
>>  drivers/spi/Makefile          |   1 +
>>  drivers/spi/mvebu_a3700_spi.c | 289 ++++++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 297 insertions(+)
>>  create mode 100644 drivers/spi/mvebu_a3700_spi.c
>>
>> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
>> index 5da66a6..8724f87 100644
>> --- a/drivers/spi/Kconfig
>> +++ b/drivers/spi/Kconfig
>> @@ -68,6 +68,13 @@ config ICH_SPI
>>           access the SPI NOR flash on platforms embedding this Intel
>>           ICH IP core.
>>
>> +config MVEBU_A3700_SPI
>> +       bool "Marvell Armada 3700 SPI driver"
>> +       help
>> +         Enable the Marvell Armada 3700 SPI driver. This driver can be
>> +         used to access the SPI NOR flash on platforms embedding this
>> +         Marvell IP core.
>> +
>>  config PIC32_SPI
>>         bool "Microchip PIC32 SPI driver"
>>         depends on MACH_PIC32
>> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
>> index b1d9e20..247c5f6 100644
>> --- a/drivers/spi/Makefile
>> +++ b/drivers/spi/Makefile
>> @@ -37,6 +37,7 @@ obj-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
>>  obj-$(CONFIG_LPC32XX_SSP) += lpc32xx_ssp.o
>>  obj-$(CONFIG_MPC52XX_SPI) += mpc52xx_spi.o
>>  obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
>> +obj-$(CONFIG_MVEBU_A3700_SPI) += mvebu_a3700_spi.o
>>  obj-$(CONFIG_MXC_SPI) += mxc_spi.o
>>  obj-$(CONFIG_MXS_SPI) += mxs_spi.o
>>  obj-$(CONFIG_OMAP3_SPI) += omap3_spi.o
>> diff --git a/drivers/spi/mvebu_a3700_spi.c b/drivers/spi/mvebu_a3700_spi.c
>> new file mode 100644
>> index 0000000..b566e03
>> --- /dev/null
>> +++ b/drivers/spi/mvebu_a3700_spi.c
>> @@ -0,0 +1,289 @@
>> +/*
>> + * Copyright (C) 2015 Marvell International Ltd.
>> + *
>> + * Copyright (C) 2016 Stefan Roese <sr@denx.de>
>> + *
>> + * SPDX-License-Identifier:    GPL-2.0+
>> + */
>> +
>> +#include <common.h>
>> +#include <dm.h>
>> +#include <malloc.h>
>> +#include <spi.h>
>> +#include <wait_bit.h>
>> +#include <asm/io.h>
>> +
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> +#define SPI_TIMEOUT                            10000
>> +
>> +#define MVEBU_SPI_A3700_XFER_RDY               BIT(1)
>> +#define MVEBU_SPI_A3700_FIFO_FLUSH             BIT(9)
>> +#define MVEBU_SPI_A3700_BYTE_LEN               BIT(5)
>> +#define MVEBU_SPI_A3700_CLK_PHA                        BIT(6)
>> +#define MVEBU_SPI_A3700_CLK_POL                        BIT(7)
>> +#define MVEBU_SPI_A3700_FIFO_EN                        BIT(17)
>> +#define MVEBU_SPI_A3700_SPI_EN_0               BIT(16)
>> +#define MVEBU_SPI_A3700_CLK_PRESCALE_BIT       0
>> +#define MVEBU_SPI_A3700_CLK_PRESCALE_MASK      \
>> +       (0x1f << MVEBU_SPI_A3700_CLK_PRESCALE_BIT)
>> +
>> +/* SPI registers */
>> +struct spi_reg {
>> +       u32 ctrl;       /* 0x10600 */
>> +       u32 cfg;        /* 0x10604 */
>> +       u32 dout;       /* 0x10608 */
>> +       u32 din;        /* 0x1060c */
>> +};
>> +
>> +struct mvebu_spi_platdata {
>> +       struct spi_reg *spireg;
>> +       unsigned int frequency;
>> +       unsigned int clock;
>> +};
>> +
>> +static void spi_cs_activate(struct spi_reg *reg, int cs)
>> +{
>> +       setbits_le32(&reg->ctrl, MVEBU_SPI_A3700_SPI_EN_0 << cs);
>> +}
>> +
>> +static void spi_cs_deactivate(struct spi_reg *reg, int cs)
>> +{
>> +       clrbits_le32(&reg->ctrl, MVEBU_SPI_A3700_SPI_EN_0 << cs);
>> +}
>> +
>> +/**
>> + * spi_legacy_shift_byte() - triggers the real SPI transfer
>> + * @bytelen:   Indicate how many bytes to transfer.
>> + * @dout:      Buffer address of what to send.
>> + * @din:       Buffer address of where to receive.
>> + *
>> + * This function triggers the real SPI transfer in legacy mode. It
>> + * will shift out char buffer from @dout, and shift in char buffer to
>> + * @din, if necessary.
>> + *
>> + * This function assumes that only one byte is shifted at one time.
>> + * However, it is not its responisbility to set the transfer type to
>> + * one-byte. Also, it does not guarantee that it will work if transfer
>> + * type becomes two-byte. See spi_set_legacy() for details.
>> + *
>> + * In legacy mode, simply write to the SPI_DOUT register will trigger
>> + * the transfer.
>> + *
>> + * If @dout == NULL, which means no actual data needs to be sent out,
>> + * then the function will shift out 0x00 in order to shift in data.
>> + * The XFER_RDY flag is checked every time before accessing SPI_DOUT
>> + * and SPI_DIN register.
>> + *
>> + * The number of transfers to be triggerred is decided by @bytelen.
>> + *
>> + * Return:     0 - cool
>> + *             -ETIMEDOUT - XFER_RDY flag timeout
>> + */
>> +static int spi_legacy_shift_byte(struct spi_reg *reg, unsigned int bytelen,
>> +                                const void *dout, void *din)
>> +{
>> +       const u8 *dout_8;
>> +       u8 *din_8;
>> +       int ret;
>> +
>> +       /* Use 0x00 as dummy dout */
>> +       const u8 dummy_dout = 0x0;
>> +       u32 pending_dout = 0x0;
>> +
>> +       /* dout_8: pointer of current dout */
>> +       dout_8 = dout;
>> +       /* din_8: pointer of current din */
>> +       din_8 = din;
>> +
>> +       while (bytelen) {
>> +               ret = wait_for_bit(__func__, &reg->ctrl,
>> +                                  MVEBU_SPI_A3700_XFER_RDY, true, 100, false);
>> +               if (ret)
>> +                       return ret;
>> +
>> +               if (dout)
>> +                       pending_dout = (u32)*dout_8;
>> +               else
>> +                       pending_dout = (u32)dummy_dout;
>> +
>> +               /* Trigger the xfer */
>> +               writel(pending_dout, &reg->dout);
>> +
>> +               if (din) {
>> +                       ret = wait_for_bit(__func__, &reg->ctrl,
>> +                                          MVEBU_SPI_A3700_XFER_RDY,
>> +                                          true, 100, false);
>> +                       if (ret)
>> +                               return ret;
>> +
>> +                       /* Read what is transferred in */
>> +                       *din_8 = (u8)readl(&reg->din);
>> +               }
>> +
>> +               /* Don't increment the current pointer if NULL */
>> +               if (dout)
>> +                       dout_8++;
>> +               if (din)
>> +                       din_8++;
>> +
>> +               bytelen--;
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static int mvebu_spi_xfer(struct udevice *dev, unsigned int bitlen,
>> +                         const void *dout, void *din, unsigned long flags)
>> +{
>> +       struct udevice *bus = dev->parent;
>> +       struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
>> +       struct spi_reg *reg = plat->spireg;
>> +       unsigned int bytelen;
>> +       int ret;
>> +
>> +       bytelen = bitlen / 8;
>> +
>> +       if (dout && din)
>> +               debug("This is a duplex transfer.\n");
>> +
>> +       /* Activate CS */
>> +       if (flags & SPI_XFER_BEGIN) {
>> +               debug("SPI: activate cs.\n");
>> +               spi_cs_activate(reg, spi_chip_select(dev));
>> +       }
>> +
>> +       /* Send and/or receive */
>> +       if (dout || din) {
>> +               ret = spi_legacy_shift_byte(reg, bytelen, dout, din);
>> +               if (ret)
>> +                       return ret;
>> +       }
>> +
>> +       /* Deactivate CS */
>> +       if (flags & SPI_XFER_END) {
>> +               ret = wait_for_bit(__func__, &reg->ctrl,
>> +                                  MVEBU_SPI_A3700_XFER_RDY, true, 100, false);
>> +               if (ret)
>> +                       return ret;
>> +
>> +               debug("SPI: deactivate cs.\n");
>> +               spi_cs_deactivate(reg, spi_chip_select(dev));
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static int mvebu_spi_set_speed(struct udevice *bus, uint hz)
>> +{
>> +       struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
>> +       struct spi_reg *reg = plat->spireg;
>> +       u32 data;
>> +
>> +       data = readl(&reg->cfg);
>> +
>> +       /* Set Prescaler */
>> +       data &= ~MVEBU_SPI_A3700_CLK_PRESCALE_MASK;
>> +
>> +       /* Calculate Prescaler = (spi_input_freq / spi_max_freq) */
>> +       if (hz > plat->frequency)
>> +               hz = plat->frequency;
>> +       data |= plat->clock / plat->frequency;
>
> Need to use the hz to compute here.

Yes, hz should be used instead of plat->frequency here. Will fix
in v3. Thanks for noticing.

>> +
>> +       writel(data, &reg->cfg);
>> +
>> +       return 0;
>> +}
>> +
>> +static int mvebu_spi_set_mode(struct udevice *bus, uint mode)
>> +{
>> +       struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
>> +       struct spi_reg *reg = plat->spireg;
>> +
>> +       /*
>> +        * Set SPI polarity
>> +        * 0: Serial interface clock is low when inactive
>> +        * 1: Serial interface clock is high when inactive
>> +        */
>> +       if (mode & SPI_CPOL)
>> +               setbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_POL);
>> +       else
>> +               clrbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_POL);
>> +       if (mode & SPI_CPHA)
>> +               setbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_PHA);
>> +       else
>> +               clrbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_PHA);
>> +
>> +       return 0;
>> +}
>> +
>> +static int mvebu_spi_probe(struct udevice *bus)
>> +{
>> +       struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
>> +       struct spi_reg *reg = plat->spireg;
>> +       u32 data;
>> +       int ret;
>> +
>> +       /*
>> +        * Settings SPI controller to be working in legacy mode, which
>> +        * means use only DO pin (I/O 1) for Data Out, and DI pin (I/O 0)
>> +        * for Data In.
>> +        */
>> +
>> +       /* Flush read/write FIFO */
>> +       data = readl(&reg->cfg);
>> +       writel(data | MVEBU_SPI_A3700_FIFO_FLUSH, &reg->cfg);
>> +       ret = wait_for_bit(__func__, &reg->cfg, MVEBU_SPI_A3700_FIFO_FLUSH,
>> +                          false, 1000, false);
>> +       if (ret)
>> +               return ret;
>> +
>> +       /* Disable FIFO mode */
>> +       data &= ~MVEBU_SPI_A3700_FIFO_EN;
>> +
>> +       /* Always shift 1 byte at a time */
>> +       data &= ~MVEBU_SPI_A3700_BYTE_LEN;
>> +
>> +       writel(data, &reg->cfg);
>> +
>> +       return 0;
>> +}
>> +
>> +static int mvebu_spi_ofdata_to_platdata(struct udevice *bus)
>> +{
>> +       struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
>> +
>> +       plat->spireg = (struct spi_reg *)dev_get_addr(bus);
>> +
>> +       plat->clock = fdtdec_get_int(gd->fdt_blob, bus->of_offset,
>> +                                    "clock-frequency", 160000);
>
> I think this is not related to spi, global clock is it? usually we
> can't use clock-frequency we set the clock with the help of
> spi-max-frequency.

This is the input clock to the SPI IP core in the SoC. And
in most drivers I've seen so far, this frequency is configured
via some macros / defines. E.g.:

CONFIG_SYS_TCLK
CONFIG_CQSPI_REF_CLK
...

Best would be if this SPI input clock could be read via some
clock driver infrastructure. But this is something that we
don't have for MVEBU in U-Boot yet. So I can either switch back
to some define for this value here or leave it as the DT property
for now.

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 02/15 v2] spi: Add driver for Marvell Armada 3700 SoC
  2016-09-23 13:24       ` Stefan Roese
@ 2016-09-23 14:03         ` Jagan Teki
  0 siblings, 0 replies; 36+ messages in thread
From: Jagan Teki @ 2016-09-23 14:03 UTC (permalink / raw)
  To: u-boot

On Fri, Sep 23, 2016 at 6:54 PM, Stefan Roese <sr@denx.de> wrote:
> On 23.09.2016 14:53, Jagan Teki wrote:
>>
>> On Fri, Sep 23, 2016 at 5:47 PM, Stefan Roese <sr@denx.de> wrote:
>>>
>>> The SPI IP core in the Marvell Armada 3700 is similar to the one in the
>>> other Armada SoCs. But the differences are big enough that it makes
>>> sense to introduce a new driver instead of cluttering the old
>>> kirkwood driver with #ifdef's.
>>>
>>> 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>
>>> Cc: Jagan Teki <jteki@openedev.com>
>>> ---
>>> v2:
>>> - Evaluated hz and used values provided by the DT in
>>> mvebu_spi_set_speed()
>>>   as suggested by Jagan
>>>
>>>  drivers/spi/Kconfig           |   7 +
>>>  drivers/spi/Makefile          |   1 +
>>>  drivers/spi/mvebu_a3700_spi.c | 289
>>> ++++++++++++++++++++++++++++++++++++++++++
>>>  3 files changed, 297 insertions(+)
>>>  create mode 100644 drivers/spi/mvebu_a3700_spi.c
>>>
>>> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
>>> index 5da66a6..8724f87 100644
>>> --- a/drivers/spi/Kconfig
>>> +++ b/drivers/spi/Kconfig
>>> @@ -68,6 +68,13 @@ config ICH_SPI
>>>           access the SPI NOR flash on platforms embedding this Intel
>>>           ICH IP core.
>>>
>>> +config MVEBU_A3700_SPI
>>> +       bool "Marvell Armada 3700 SPI driver"
>>> +       help
>>> +         Enable the Marvell Armada 3700 SPI driver. This driver can be
>>> +         used to access the SPI NOR flash on platforms embedding this
>>> +         Marvell IP core.
>>> +
>>>  config PIC32_SPI
>>>         bool "Microchip PIC32 SPI driver"
>>>         depends on MACH_PIC32
>>> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
>>> index b1d9e20..247c5f6 100644
>>> --- a/drivers/spi/Makefile
>>> +++ b/drivers/spi/Makefile
>>> @@ -37,6 +37,7 @@ obj-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
>>>  obj-$(CONFIG_LPC32XX_SSP) += lpc32xx_ssp.o
>>>  obj-$(CONFIG_MPC52XX_SPI) += mpc52xx_spi.o
>>>  obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
>>> +obj-$(CONFIG_MVEBU_A3700_SPI) += mvebu_a3700_spi.o
>>>  obj-$(CONFIG_MXC_SPI) += mxc_spi.o
>>>  obj-$(CONFIG_MXS_SPI) += mxs_spi.o
>>>  obj-$(CONFIG_OMAP3_SPI) += omap3_spi.o
>>> diff --git a/drivers/spi/mvebu_a3700_spi.c
>>> b/drivers/spi/mvebu_a3700_spi.c
>>> new file mode 100644
>>> index 0000000..b566e03
>>> --- /dev/null
>>> +++ b/drivers/spi/mvebu_a3700_spi.c
>>> @@ -0,0 +1,289 @@
>>> +/*
>>> + * Copyright (C) 2015 Marvell International Ltd.
>>> + *
>>> + * Copyright (C) 2016 Stefan Roese <sr@denx.de>
>>> + *
>>> + * SPDX-License-Identifier:    GPL-2.0+
>>> + */
>>> +
>>> +#include <common.h>
>>> +#include <dm.h>
>>> +#include <malloc.h>
>>> +#include <spi.h>
>>> +#include <wait_bit.h>
>>> +#include <asm/io.h>
>>> +
>>> +DECLARE_GLOBAL_DATA_PTR;
>>> +
>>> +#define SPI_TIMEOUT                            10000
>>> +
>>> +#define MVEBU_SPI_A3700_XFER_RDY               BIT(1)
>>> +#define MVEBU_SPI_A3700_FIFO_FLUSH             BIT(9)
>>> +#define MVEBU_SPI_A3700_BYTE_LEN               BIT(5)
>>> +#define MVEBU_SPI_A3700_CLK_PHA                        BIT(6)
>>> +#define MVEBU_SPI_A3700_CLK_POL                        BIT(7)
>>> +#define MVEBU_SPI_A3700_FIFO_EN                        BIT(17)
>>> +#define MVEBU_SPI_A3700_SPI_EN_0               BIT(16)
>>> +#define MVEBU_SPI_A3700_CLK_PRESCALE_BIT       0
>>> +#define MVEBU_SPI_A3700_CLK_PRESCALE_MASK      \
>>> +       (0x1f << MVEBU_SPI_A3700_CLK_PRESCALE_BIT)
>>> +
>>> +/* SPI registers */
>>> +struct spi_reg {
>>> +       u32 ctrl;       /* 0x10600 */
>>> +       u32 cfg;        /* 0x10604 */
>>> +       u32 dout;       /* 0x10608 */
>>> +       u32 din;        /* 0x1060c */
>>> +};
>>> +
>>> +struct mvebu_spi_platdata {
>>> +       struct spi_reg *spireg;
>>> +       unsigned int frequency;
>>> +       unsigned int clock;
>>> +};
>>> +
>>> +static void spi_cs_activate(struct spi_reg *reg, int cs)
>>> +{
>>> +       setbits_le32(&reg->ctrl, MVEBU_SPI_A3700_SPI_EN_0 << cs);
>>> +}
>>> +
>>> +static void spi_cs_deactivate(struct spi_reg *reg, int cs)
>>> +{
>>> +       clrbits_le32(&reg->ctrl, MVEBU_SPI_A3700_SPI_EN_0 << cs);
>>> +}
>>> +
>>> +/**
>>> + * spi_legacy_shift_byte() - triggers the real SPI transfer
>>> + * @bytelen:   Indicate how many bytes to transfer.
>>> + * @dout:      Buffer address of what to send.
>>> + * @din:       Buffer address of where to receive.
>>> + *
>>> + * This function triggers the real SPI transfer in legacy mode. It
>>> + * will shift out char buffer from @dout, and shift in char buffer to
>>> + * @din, if necessary.
>>> + *
>>> + * This function assumes that only one byte is shifted at one time.
>>> + * However, it is not its responisbility to set the transfer type to
>>> + * one-byte. Also, it does not guarantee that it will work if transfer
>>> + * type becomes two-byte. See spi_set_legacy() for details.
>>> + *
>>> + * In legacy mode, simply write to the SPI_DOUT register will trigger
>>> + * the transfer.
>>> + *
>>> + * If @dout == NULL, which means no actual data needs to be sent out,
>>> + * then the function will shift out 0x00 in order to shift in data.
>>> + * The XFER_RDY flag is checked every time before accessing SPI_DOUT
>>> + * and SPI_DIN register.
>>> + *
>>> + * The number of transfers to be triggerred is decided by @bytelen.
>>> + *
>>> + * Return:     0 - cool
>>> + *             -ETIMEDOUT - XFER_RDY flag timeout
>>> + */
>>> +static int spi_legacy_shift_byte(struct spi_reg *reg, unsigned int
>>> bytelen,
>>> +                                const void *dout, void *din)
>>> +{
>>> +       const u8 *dout_8;
>>> +       u8 *din_8;
>>> +       int ret;
>>> +
>>> +       /* Use 0x00 as dummy dout */
>>> +       const u8 dummy_dout = 0x0;
>>> +       u32 pending_dout = 0x0;
>>> +
>>> +       /* dout_8: pointer of current dout */
>>> +       dout_8 = dout;
>>> +       /* din_8: pointer of current din */
>>> +       din_8 = din;
>>> +
>>> +       while (bytelen) {
>>> +               ret = wait_for_bit(__func__, &reg->ctrl,
>>> +                                  MVEBU_SPI_A3700_XFER_RDY, true, 100,
>>> false);
>>> +               if (ret)
>>> +                       return ret;
>>> +
>>> +               if (dout)
>>> +                       pending_dout = (u32)*dout_8;
>>> +               else
>>> +                       pending_dout = (u32)dummy_dout;
>>> +
>>> +               /* Trigger the xfer */
>>> +               writel(pending_dout, &reg->dout);
>>> +
>>> +               if (din) {
>>> +                       ret = wait_for_bit(__func__, &reg->ctrl,
>>> +                                          MVEBU_SPI_A3700_XFER_RDY,
>>> +                                          true, 100, false);
>>> +                       if (ret)
>>> +                               return ret;
>>> +
>>> +                       /* Read what is transferred in */
>>> +                       *din_8 = (u8)readl(&reg->din);
>>> +               }
>>> +
>>> +               /* Don't increment the current pointer if NULL */
>>> +               if (dout)
>>> +                       dout_8++;
>>> +               if (din)
>>> +                       din_8++;
>>> +
>>> +               bytelen--;
>>> +       }
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static int mvebu_spi_xfer(struct udevice *dev, unsigned int bitlen,
>>> +                         const void *dout, void *din, unsigned long
>>> flags)
>>> +{
>>> +       struct udevice *bus = dev->parent;
>>> +       struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
>>> +       struct spi_reg *reg = plat->spireg;
>>> +       unsigned int bytelen;
>>> +       int ret;
>>> +
>>> +       bytelen = bitlen / 8;
>>> +
>>> +       if (dout && din)
>>> +               debug("This is a duplex transfer.\n");
>>> +
>>> +       /* Activate CS */
>>> +       if (flags & SPI_XFER_BEGIN) {
>>> +               debug("SPI: activate cs.\n");
>>> +               spi_cs_activate(reg, spi_chip_select(dev));
>>> +       }
>>> +
>>> +       /* Send and/or receive */
>>> +       if (dout || din) {
>>> +               ret = spi_legacy_shift_byte(reg, bytelen, dout, din);
>>> +               if (ret)
>>> +                       return ret;
>>> +       }
>>> +
>>> +       /* Deactivate CS */
>>> +       if (flags & SPI_XFER_END) {
>>> +               ret = wait_for_bit(__func__, &reg->ctrl,
>>> +                                  MVEBU_SPI_A3700_XFER_RDY, true, 100,
>>> false);
>>> +               if (ret)
>>> +                       return ret;
>>> +
>>> +               debug("SPI: deactivate cs.\n");
>>> +               spi_cs_deactivate(reg, spi_chip_select(dev));
>>> +       }
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static int mvebu_spi_set_speed(struct udevice *bus, uint hz)
>>> +{
>>> +       struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
>>> +       struct spi_reg *reg = plat->spireg;
>>> +       u32 data;
>>> +
>>> +       data = readl(&reg->cfg);
>>> +
>>> +       /* Set Prescaler */
>>> +       data &= ~MVEBU_SPI_A3700_CLK_PRESCALE_MASK;
>>> +
>>> +       /* Calculate Prescaler = (spi_input_freq / spi_max_freq) */
>>> +       if (hz > plat->frequency)
>>> +               hz = plat->frequency;
>>> +       data |= plat->clock / plat->frequency;
>>
>>
>> Need to use the hz to compute here.
>
>
> Yes, hz should be used instead of plat->frequency here. Will fix
> in v3. Thanks for noticing.
>
>
>>> +
>>> +       writel(data, &reg->cfg);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static int mvebu_spi_set_mode(struct udevice *bus, uint mode)
>>> +{
>>> +       struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
>>> +       struct spi_reg *reg = plat->spireg;
>>> +
>>> +       /*
>>> +        * Set SPI polarity
>>> +        * 0: Serial interface clock is low when inactive
>>> +        * 1: Serial interface clock is high when inactive
>>> +        */
>>> +       if (mode & SPI_CPOL)
>>> +               setbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_POL);
>>> +       else
>>> +               clrbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_POL);
>>> +       if (mode & SPI_CPHA)
>>> +               setbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_PHA);
>>> +       else
>>> +               clrbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_PHA);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static int mvebu_spi_probe(struct udevice *bus)
>>> +{
>>> +       struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
>>> +       struct spi_reg *reg = plat->spireg;
>>> +       u32 data;
>>> +       int ret;
>>> +
>>> +       /*
>>> +        * Settings SPI controller to be working in legacy mode, which
>>> +        * means use only DO pin (I/O 1) for Data Out, and DI pin (I/O 0)
>>> +        * for Data In.
>>> +        */
>>> +
>>> +       /* Flush read/write FIFO */
>>> +       data = readl(&reg->cfg);
>>> +       writel(data | MVEBU_SPI_A3700_FIFO_FLUSH, &reg->cfg);
>>> +       ret = wait_for_bit(__func__, &reg->cfg,
>>> MVEBU_SPI_A3700_FIFO_FLUSH,
>>> +                          false, 1000, false);
>>> +       if (ret)
>>> +               return ret;
>>> +
>>> +       /* Disable FIFO mode */
>>> +       data &= ~MVEBU_SPI_A3700_FIFO_EN;
>>> +
>>> +       /* Always shift 1 byte at a time */
>>> +       data &= ~MVEBU_SPI_A3700_BYTE_LEN;
>>> +
>>> +       writel(data, &reg->cfg);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static int mvebu_spi_ofdata_to_platdata(struct udevice *bus)
>>> +{
>>> +       struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
>>> +
>>> +       plat->spireg = (struct spi_reg *)dev_get_addr(bus);
>>> +
>>> +       plat->clock = fdtdec_get_int(gd->fdt_blob, bus->of_offset,
>>> +                                    "clock-frequency", 160000);
>>
>>
>> I think this is not related to spi, global clock is it? usually we
>> can't use clock-frequency we set the clock with the help of
>> spi-max-frequency.
>
>
> This is the input clock to the SPI IP core in the SoC. And
> in most drivers I've seen so far, this frequency is configured
> via some macros / defines. E.g.:
>
> CONFIG_SYS_TCLK
> CONFIG_CQSPI_REF_CLK
> ...
>
> Best would be if this SPI input clock could be read via some
> clock driver infrastructure. But this is something that we
> don't have for MVEBU in U-Boot yet. So I can either switch back
> to some define for this value here or leave it as the DT property
> for now.

OK, use the dt and add FIXME with some proper comment.

thanks!
-- 
Jagan Teki
Free Software Engineer | www.openedev.com
U-Boot, Linux | Upstream Maintainer
Hyderabad, India.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 02/15 v3] spi: Add driver for Marvell Armada 3700 SoC
  2016-09-16 13:09 ` [U-Boot] [PATCH 02/15] spi: Add driver for Marvell " Stefan Roese
  2016-09-21  7:56   ` Jagan Teki
  2016-09-23 12:17   ` [U-Boot] [PATCH 02/15 v2] " Stefan Roese
@ 2016-09-23 14:28   ` Stefan Roese
  2016-09-23 14:44     ` Jagan Teki
  2 siblings, 1 reply; 36+ messages in thread
From: Stefan Roese @ 2016-09-23 14:28 UTC (permalink / raw)
  To: u-boot

The SPI IP core in the Marvell Armada 3700 is similar to the one in the
other Armada SoCs. But the differences are big enough that it makes
sense to introduce a new driver instead of cluttering the old
kirkwood driver with #ifdef's.

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>
Cc: Jagan Teki <jteki@openedev.com>
---
v3:
- Really use hz now in equation
- Add comment that the DT property for the input clock is deprecated
  and the clock infrastructure should be used, once available for
  mvebu in U-Boot

v2:
- Evaluated hz and used values provided by the DT in mvebu_spi_set_speed()
  as suggested by Jagan
  
 drivers/spi/Kconfig           |   7 +
 drivers/spi/Makefile          |   1 +
 drivers/spi/mvebu_a3700_spi.c | 297 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 305 insertions(+)
 create mode 100644 drivers/spi/mvebu_a3700_spi.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 5da66a6..8724f87 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -68,6 +68,13 @@ config ICH_SPI
 	  access the SPI NOR flash on platforms embedding this Intel
 	  ICH IP core.
 
+config MVEBU_A3700_SPI
+	bool "Marvell Armada 3700 SPI driver"
+	help
+	  Enable the Marvell Armada 3700 SPI driver. This driver can be
+	  used to access the SPI NOR flash on platforms embedding this
+	  Marvell IP core.
+
 config PIC32_SPI
 	bool "Microchip PIC32 SPI driver"
 	depends on MACH_PIC32
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index b1d9e20..247c5f6 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
 obj-$(CONFIG_LPC32XX_SSP) += lpc32xx_ssp.o
 obj-$(CONFIG_MPC52XX_SPI) += mpc52xx_spi.o
 obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
+obj-$(CONFIG_MVEBU_A3700_SPI) += mvebu_a3700_spi.o
 obj-$(CONFIG_MXC_SPI) += mxc_spi.o
 obj-$(CONFIG_MXS_SPI) += mxs_spi.o
 obj-$(CONFIG_OMAP3_SPI) += omap3_spi.o
diff --git a/drivers/spi/mvebu_a3700_spi.c b/drivers/spi/mvebu_a3700_spi.c
new file mode 100644
index 0000000..0a55f3f
--- /dev/null
+++ b/drivers/spi/mvebu_a3700_spi.c
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2015 Marvell International Ltd.
+ *
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <malloc.h>
+#include <spi.h>
+#include <wait_bit.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define SPI_TIMEOUT				10000
+
+#define MVEBU_SPI_A3700_XFER_RDY		BIT(1)
+#define MVEBU_SPI_A3700_FIFO_FLUSH		BIT(9)
+#define MVEBU_SPI_A3700_BYTE_LEN		BIT(5)
+#define MVEBU_SPI_A3700_CLK_PHA			BIT(6)
+#define MVEBU_SPI_A3700_CLK_POL			BIT(7)
+#define MVEBU_SPI_A3700_FIFO_EN			BIT(17)
+#define MVEBU_SPI_A3700_SPI_EN_0		BIT(16)
+#define MVEBU_SPI_A3700_CLK_PRESCALE_BIT	0
+#define MVEBU_SPI_A3700_CLK_PRESCALE_MASK	\
+	(0x1f << MVEBU_SPI_A3700_CLK_PRESCALE_BIT)
+
+/* SPI registers */
+struct spi_reg {
+	u32 ctrl;	/* 0x10600 */
+	u32 cfg;	/* 0x10604 */
+	u32 dout;	/* 0x10608 */
+	u32 din;	/* 0x1060c */
+};
+
+struct mvebu_spi_platdata {
+	struct spi_reg *spireg;
+	unsigned int frequency;
+	unsigned int clock;
+};
+
+static void spi_cs_activate(struct spi_reg *reg, int cs)
+{
+	setbits_le32(&reg->ctrl, MVEBU_SPI_A3700_SPI_EN_0 << cs);
+}
+
+static void spi_cs_deactivate(struct spi_reg *reg, int cs)
+{
+	clrbits_le32(&reg->ctrl, MVEBU_SPI_A3700_SPI_EN_0 << cs);
+}
+
+/**
+ * spi_legacy_shift_byte() - triggers the real SPI transfer
+ * @bytelen:	Indicate how many bytes to transfer.
+ * @dout:	Buffer address of what to send.
+ * @din:	Buffer address of where to receive.
+ *
+ * This function triggers the real SPI transfer in legacy mode. It
+ * will shift out char buffer from @dout, and shift in char buffer to
+ * @din, if necessary.
+ *
+ * This function assumes that only one byte is shifted@one time.
+ * However, it is not its responisbility to set the transfer type to
+ * one-byte. Also, it does not guarantee that it will work if transfer
+ * type becomes two-byte. See spi_set_legacy() for details.
+ *
+ * In legacy mode, simply write to the SPI_DOUT register will trigger
+ * the transfer.
+ *
+ * If @dout == NULL, which means no actual data needs to be sent out,
+ * then the function will shift out 0x00 in order to shift in data.
+ * The XFER_RDY flag is checked every time before accessing SPI_DOUT
+ * and SPI_DIN register.
+ *
+ * The number of transfers to be triggerred is decided by @bytelen.
+ *
+ * Return:	0 - cool
+ *		-ETIMEDOUT - XFER_RDY flag timeout
+ */
+static int spi_legacy_shift_byte(struct spi_reg *reg, unsigned int bytelen,
+				 const void *dout, void *din)
+{
+	const u8 *dout_8;
+	u8 *din_8;
+	int ret;
+
+	/* Use 0x00 as dummy dout */
+	const u8 dummy_dout = 0x0;
+	u32 pending_dout = 0x0;
+
+	/* dout_8: pointer of current dout */
+	dout_8 = dout;
+	/* din_8: pointer of current din */
+	din_8 = din;
+
+	while (bytelen) {
+		ret = wait_for_bit(__func__, &reg->ctrl,
+				   MVEBU_SPI_A3700_XFER_RDY, true, 100, false);
+		if (ret)
+			return ret;
+
+		if (dout)
+			pending_dout = (u32)*dout_8;
+		else
+			pending_dout = (u32)dummy_dout;
+
+		/* Trigger the xfer */
+		writel(pending_dout, &reg->dout);
+
+		if (din) {
+			ret = wait_for_bit(__func__, &reg->ctrl,
+					   MVEBU_SPI_A3700_XFER_RDY,
+					   true, 100, false);
+			if (ret)
+				return ret;
+
+			/* Read what is transferred in */
+			*din_8 = (u8)readl(&reg->din);
+		}
+
+		/* Don't increment the current pointer if NULL */
+		if (dout)
+			dout_8++;
+		if (din)
+			din_8++;
+
+		bytelen--;
+	}
+
+	return 0;
+}
+
+static int mvebu_spi_xfer(struct udevice *dev, unsigned int bitlen,
+			  const void *dout, void *din, unsigned long flags)
+{
+	struct udevice *bus = dev->parent;
+	struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
+	struct spi_reg *reg = plat->spireg;
+	unsigned int bytelen;
+	int ret;
+
+	bytelen = bitlen / 8;
+
+	if (dout && din)
+		debug("This is a duplex transfer.\n");
+
+	/* Activate CS */
+	if (flags & SPI_XFER_BEGIN) {
+		debug("SPI: activate cs.\n");
+		spi_cs_activate(reg, spi_chip_select(dev));
+	}
+
+	/* Send and/or receive */
+	if (dout || din) {
+		ret = spi_legacy_shift_byte(reg, bytelen, dout, din);
+		if (ret)
+			return ret;
+	}
+
+	/* Deactivate CS */
+	if (flags & SPI_XFER_END) {
+		ret = wait_for_bit(__func__, &reg->ctrl,
+				   MVEBU_SPI_A3700_XFER_RDY, true, 100, false);
+		if (ret)
+			return ret;
+
+		debug("SPI: deactivate cs.\n");
+		spi_cs_deactivate(reg, spi_chip_select(dev));
+	}
+
+	return 0;
+}
+
+static int mvebu_spi_set_speed(struct udevice *bus, uint hz)
+{
+	struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
+	struct spi_reg *reg = plat->spireg;
+	u32 data;
+
+	data = readl(&reg->cfg);
+
+	/* Set Prescaler */
+	data &= ~MVEBU_SPI_A3700_CLK_PRESCALE_MASK;
+
+	/* Calculate Prescaler = (spi_input_freq / spi_max_freq) */
+	if (hz > plat->frequency)
+		hz = plat->frequency;
+	data |= plat->clock / hz;
+
+	writel(data, &reg->cfg);
+
+	return 0;
+}
+
+static int mvebu_spi_set_mode(struct udevice *bus, uint mode)
+{
+	struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
+	struct spi_reg *reg = plat->spireg;
+
+	/*
+	 * Set SPI polarity
+	 * 0: Serial interface clock is low when inactive
+	 * 1: Serial interface clock is high when inactive
+	 */
+	if (mode & SPI_CPOL)
+		setbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_POL);
+	else
+		clrbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_POL);
+	if (mode & SPI_CPHA)
+		setbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_PHA);
+	else
+		clrbits_le32(&reg->cfg, MVEBU_SPI_A3700_CLK_PHA);
+
+	return 0;
+}
+
+static int mvebu_spi_probe(struct udevice *bus)
+{
+	struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
+	struct spi_reg *reg = plat->spireg;
+	u32 data;
+	int ret;
+
+	/*
+	 * Settings SPI controller to be working in legacy mode, which
+	 * means use only DO pin (I/O 1) for Data Out, and DI pin (I/O 0)
+	 * for Data In.
+	 */
+
+	/* Flush read/write FIFO */
+	data = readl(&reg->cfg);
+	writel(data | MVEBU_SPI_A3700_FIFO_FLUSH, &reg->cfg);
+	ret = wait_for_bit(__func__, &reg->cfg, MVEBU_SPI_A3700_FIFO_FLUSH,
+			   false, 1000, false);
+	if (ret)
+		return ret;
+
+	/* Disable FIFO mode */
+	data &= ~MVEBU_SPI_A3700_FIFO_EN;
+
+	/* Always shift 1 byte at a time */
+	data &= ~MVEBU_SPI_A3700_BYTE_LEN;
+
+	writel(data, &reg->cfg);
+
+	return 0;
+}
+
+static int mvebu_spi_ofdata_to_platdata(struct udevice *bus)
+{
+	struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
+
+	plat->spireg = (struct spi_reg *)dev_get_addr(bus);
+
+	/*
+	 * FIXME
+	 * Right now, mvebu does not have a clock infrastructure in U-Boot
+	 * which should be used to query the input clock to the SPI
+	 * controller. Once this clock driver is integrated into U-Boot
+	 * it should be used to read the input clock and the DT property
+	 * can be removed.
+	 */
+	plat->clock = fdtdec_get_int(gd->fdt_blob, bus->of_offset,
+				     "clock-frequency", 160000);
+	plat->frequency = fdtdec_get_int(gd->fdt_blob, bus->of_offset,
+					 "spi-max-frequency", 40000);
+
+	return 0;
+}
+
+static const struct dm_spi_ops mvebu_spi_ops = {
+	.xfer		= mvebu_spi_xfer,
+	.set_speed	= mvebu_spi_set_speed,
+	.set_mode	= mvebu_spi_set_mode,
+	/*
+	 * cs_info is not needed, since we require all chip selects to be
+	 * in the device tree explicitly
+	 */
+};
+
+static const struct udevice_id mvebu_spi_ids[] = {
+	{ .compatible = "marvell,armada-3700-spi" },
+	{ }
+};
+
+U_BOOT_DRIVER(mvebu_spi) = {
+	.name = "mvebu_spi",
+	.id = UCLASS_SPI,
+	.of_match = mvebu_spi_ids,
+	.ops = &mvebu_spi_ops,
+	.ofdata_to_platdata = mvebu_spi_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct mvebu_spi_platdata),
+	.probe = mvebu_spi_probe,
+};
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 02/15 v3] spi: Add driver for Marvell Armada 3700 SoC
  2016-09-23 14:28   ` [U-Boot] [PATCH 02/15 v3] " Stefan Roese
@ 2016-09-23 14:44     ` Jagan Teki
  2016-09-24  7:52       ` Stefan Roese
  0 siblings, 1 reply; 36+ messages in thread
From: Jagan Teki @ 2016-09-23 14:44 UTC (permalink / raw)
  To: u-boot

On Fri, Sep 23, 2016 at 7:58 PM, Stefan Roese <sr@denx.de> wrote:
> The SPI IP core in the Marvell Armada 3700 is similar to the one in the
> other Armada SoCs. But the differences are big enough that it makes
> sense to introduce a new driver instead of cluttering the old
> kirkwood driver with #ifdef's.
>
> 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>
> Cc: Jagan Teki <jteki@openedev.com>
> ---
> v3:
> - Really use hz now in equation
> - Add comment that the DT property for the input clock is deprecated
>   and the clock infrastructure should be used, once available for
>   mvebu in U-Boot
>
> v2:
> - Evaluated hz and used values provided by the DT in mvebu_spi_set_speed()
>   as suggested by Jagan
>
>  drivers/spi/Kconfig           |   7 +
>  drivers/spi/Makefile          |   1 +
>  drivers/spi/mvebu_a3700_spi.c | 297 ++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 305 insertions(+)
>  create mode 100644 drivers/spi/mvebu_a3700_spi.c
>
> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> index 5da66a6..8724f87 100644
> --- a/drivers/spi/Kconfig
> +++ b/drivers/spi/Kconfig
> @@ -68,6 +68,13 @@ config ICH_SPI
>           access the SPI NOR flash on platforms embedding this Intel
>           ICH IP core.
>
> +config MVEBU_A3700_SPI
> +       bool "Marvell Armada 3700 SPI driver"
> +       help
> +         Enable the Marvell Armada 3700 SPI driver. This driver can be
> +         used to access the SPI NOR flash on platforms embedding this
> +         Marvell IP core.
> +
>  config PIC32_SPI
>         bool "Microchip PIC32 SPI driver"
>         depends on MACH_PIC32
> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
> index b1d9e20..247c5f6 100644
> --- a/drivers/spi/Makefile
> +++ b/drivers/spi/Makefile
> @@ -37,6 +37,7 @@ obj-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
>  obj-$(CONFIG_LPC32XX_SSP) += lpc32xx_ssp.o
>  obj-$(CONFIG_MPC52XX_SPI) += mpc52xx_spi.o
>  obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
> +obj-$(CONFIG_MVEBU_A3700_SPI) += mvebu_a3700_spi.o
>  obj-$(CONFIG_MXC_SPI) += mxc_spi.o
>  obj-$(CONFIG_MXS_SPI) += mxs_spi.o
>  obj-$(CONFIG_OMAP3_SPI) += omap3_spi.o
> diff --git a/drivers/spi/mvebu_a3700_spi.c b/drivers/spi/mvebu_a3700_spi.c
> new file mode 100644
> index 0000000..0a55f3f
> --- /dev/null
> +++ b/drivers/spi/mvebu_a3700_spi.c
> @@ -0,0 +1,297 @@
> +/*
> + * Copyright (C) 2015 Marvell International Ltd.
> + *
> + * Copyright (C) 2016 Stefan Roese <sr@denx.de>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <malloc.h>
> +#include <spi.h>
> +#include <wait_bit.h>
> +#include <asm/io.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#define SPI_TIMEOUT                            10000

Can you remove this - sorry, never looked previously.

Reviewed-by: Jagan Teki <jteki@openedev.com>

thanks!
-- 
Jagan Teki
Free Software Engineer | www.openedev.com
U-Boot, Linux | Upstream Maintainer
Hyderabad, India.

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 03/15] net: mvneta: Make driver 64bit safe
  2016-09-23 11:05     ` Stefan Roese
@ 2016-09-23 15:28       ` Joe Hershberger
  0 siblings, 0 replies; 36+ messages in thread
From: Joe Hershberger @ 2016-09-23 15:28 UTC (permalink / raw)
  To: u-boot

Hi Stefan,

On Fri, Sep 23, 2016 at 6:05 AM, Stefan Roese <sr@denx.de> wrote:
> On 16.09.2016 19:30, Joe Hershberger wrote:
>>
>> On Fri, Sep 16, 2016 at 8:09 AM, Stefan Roese <sr@denx.de> wrote:
>>>
>>> The mvneta driver is also used on the ARMv8 64bit Armada 3700 SoC. This
>>> patch fixes the compilation warnings seen on this 64bit platform.
>>>
>>> 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>
>>> Cc: Joe Hershberger <joe.hershberger@ni.com>
>>
>>
>> Acked-by: Joe Hershberger <joe.hershberger@ni.com>
>
>
> Thanks Joe. Are you okay with me including this patch, and the
> other mvneta one (once v2 is accepted / acked) via my Marvell
> repository?

Yes, for sure.

Cheers,
-Joe

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 04/15 v2] net: mvneta: Add support for Armada 3700 SoC
  2016-09-23 11:26   ` [U-Boot] [PATCH 04/15 v2] " Stefan Roese
@ 2016-09-23 15:29     ` Joe Hershberger
  0 siblings, 0 replies; 36+ messages in thread
From: Joe Hershberger @ 2016-09-23 15:29 UTC (permalink / raw)
  To: u-boot

On Fri, Sep 23, 2016 at 6:26 AM, Stefan Roese <sr@denx.de> wrote:
> This patch adds support for the Armada 3700 SoC to the Marvell mvneta
> network driver.
>
> Not like A380, in Armada3700, there are two layers of decode windows for GBE:
> First layer is:  GbE Address window that resides inside the GBE unit,
> Second layer is: Fabric address window which is located in the NIC400
>                  (South Fabric).
> To simplify the address decode configuration for Armada3700, we bypass the
> first layer of GBE decode window by setting the first window to 4GB.
>
> 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>
> Cc: Joe Hershberger <joe.hershberger@ni.com>

Acked-by: Joe Hershberger <joe.hershberger@ni.com>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [U-Boot] [PATCH 02/15 v3] spi: Add driver for Marvell Armada 3700 SoC
  2016-09-23 14:44     ` Jagan Teki
@ 2016-09-24  7:52       ` Stefan Roese
  0 siblings, 0 replies; 36+ messages in thread
From: Stefan Roese @ 2016-09-24  7:52 UTC (permalink / raw)
  To: u-boot

On 23.09.2016 16:44, Jagan Teki wrote:
> On Fri, Sep 23, 2016 at 7:58 PM, Stefan Roese <sr@denx.de> wrote:
>> The SPI IP core in the Marvell Armada 3700 is similar to the one in the
>> other Armada SoCs. But the differences are big enough that it makes
>> sense to introduce a new driver instead of cluttering the old
>> kirkwood driver with #ifdef's.
>>
>> 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>
>> Cc: Jagan Teki <jteki@openedev.com>
>> ---
>> v3:
>> - Really use hz now in equation
>> - Add comment that the DT property for the input clock is deprecated
>>   and the clock infrastructure should be used, once available for
>>   mvebu in U-Boot
>>
>> v2:
>> - Evaluated hz and used values provided by the DT in mvebu_spi_set_speed()
>>   as suggested by Jagan
>>
>>  drivers/spi/Kconfig           |   7 +
>>  drivers/spi/Makefile          |   1 +
>>  drivers/spi/mvebu_a3700_spi.c | 297 ++++++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 305 insertions(+)
>>  create mode 100644 drivers/spi/mvebu_a3700_spi.c
>>
>> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
>> index 5da66a6..8724f87 100644
>> --- a/drivers/spi/Kconfig
>> +++ b/drivers/spi/Kconfig
>> @@ -68,6 +68,13 @@ config ICH_SPI
>>           access the SPI NOR flash on platforms embedding this Intel
>>           ICH IP core.
>>
>> +config MVEBU_A3700_SPI
>> +       bool "Marvell Armada 3700 SPI driver"
>> +       help
>> +         Enable the Marvell Armada 3700 SPI driver. This driver can be
>> +         used to access the SPI NOR flash on platforms embedding this
>> +         Marvell IP core.
>> +
>>  config PIC32_SPI
>>         bool "Microchip PIC32 SPI driver"
>>         depends on MACH_PIC32
>> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
>> index b1d9e20..247c5f6 100644
>> --- a/drivers/spi/Makefile
>> +++ b/drivers/spi/Makefile
>> @@ -37,6 +37,7 @@ obj-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
>>  obj-$(CONFIG_LPC32XX_SSP) += lpc32xx_ssp.o
>>  obj-$(CONFIG_MPC52XX_SPI) += mpc52xx_spi.o
>>  obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
>> +obj-$(CONFIG_MVEBU_A3700_SPI) += mvebu_a3700_spi.o
>>  obj-$(CONFIG_MXC_SPI) += mxc_spi.o
>>  obj-$(CONFIG_MXS_SPI) += mxs_spi.o
>>  obj-$(CONFIG_OMAP3_SPI) += omap3_spi.o
>> diff --git a/drivers/spi/mvebu_a3700_spi.c b/drivers/spi/mvebu_a3700_spi.c
>> new file mode 100644
>> index 0000000..0a55f3f
>> --- /dev/null
>> +++ b/drivers/spi/mvebu_a3700_spi.c
>> @@ -0,0 +1,297 @@
>> +/*
>> + * Copyright (C) 2015 Marvell International Ltd.
>> + *
>> + * Copyright (C) 2016 Stefan Roese <sr@denx.de>
>> + *
>> + * SPDX-License-Identifier:    GPL-2.0+
>> + */
>> +
>> +#include <common.h>
>> +#include <dm.h>
>> +#include <malloc.h>
>> +#include <spi.h>
>> +#include <wait_bit.h>
>> +#include <asm/io.h>
>> +
>> +DECLARE_GLOBAL_DATA_PTR;
>> +
>> +#define SPI_TIMEOUT                            10000
>
> Can you remove this - sorry, never looked previously.

Done.

> Reviewed-by: Jagan Teki <jteki@openedev.com>

Added.

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 36+ messages in thread

end of thread, other threads:[~2016-09-24  7:52 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-16 13:09 [U-Boot] [PATCH 01/15] serial: Add serial_mvebu_a3700 for Armada 3700 SoC Stefan Roese
2016-09-16 13:09 ` [U-Boot] [PATCH 02/15] spi: Add driver for Marvell " Stefan Roese
2016-09-21  7:56   ` Jagan Teki
2016-09-23 12:14     ` Stefan Roese
2016-09-23 12:17   ` [U-Boot] [PATCH 02/15 v2] " Stefan Roese
2016-09-23 12:53     ` Jagan Teki
2016-09-23 13:24       ` Stefan Roese
2016-09-23 14:03         ` Jagan Teki
2016-09-23 14:28   ` [U-Boot] [PATCH 02/15 v3] " Stefan Roese
2016-09-23 14:44     ` Jagan Teki
2016-09-24  7:52       ` Stefan Roese
2016-09-16 13:09 ` [U-Boot] [PATCH 03/15] net: mvneta: Make driver 64bit safe Stefan Roese
2016-09-16 17:30   ` Joe Hershberger
2016-09-23 11:05     ` Stefan Roese
2016-09-23 15:28       ` Joe Hershberger
2016-09-16 13:09 ` [U-Boot] [PATCH 04/15] net: mvneta: Add support for Armada 3700 SoC Stefan Roese
2016-09-16 17:59   ` Joe Hershberger
2016-09-23 11:26   ` [U-Boot] [PATCH 04/15 v2] " Stefan Roese
2016-09-23 15:29     ` Joe Hershberger
2016-09-16 13:09 ` [U-Boot] [PATCH 05/15] usb: xhci: Add Marvell MVEBU xHCI support Stefan Roese
2016-09-18 10:46   ` Marek Vasut
2016-09-16 13:09 ` [U-Boot] [PATCH 06/15] usb: ehci: ehci-marvell.c: Add Armada 3700 support (ARMv8) Stefan Roese
2016-09-18 10:47   ` Marek Vasut
2016-09-20 11:03     ` Stefan Roese
2016-09-16 13:09 ` [U-Boot] [PATCH 07/15] drivers/phy: Add Marvell SerDes / PHY drivers used on Armada 3k Stefan Roese
2016-09-16 13:09 ` [U-Boot] [PATCH 08/15] arm64: mvebu: Armada 3700: Add Armada 37xx dts files Stefan Roese
2016-09-16 13:09 ` [U-Boot] [PATCH 09/15] arm64: mvebu: Armada 3700: Add SPI device tree nodes Stefan Roese
2016-09-21  8:02   ` Jagan Teki
2016-09-23 11:37   ` [U-Boot] [PATCH 09/15 v2] " Stefan Roese
2016-09-23 11:49     ` Jagan Teki
2016-09-16 13:09 ` [U-Boot] [PATCH 10/15] arm64: mvebu: Armada 3700: Add ethernet " Stefan Roese
2016-09-16 13:09 ` [U-Boot] [PATCH 11/15] arm64: mvebu: Armada 3700: Add I2C " Stefan Roese
2016-09-16 13:09 ` [U-Boot] [PATCH 12/15] arm64: mvebu: Armada 3700: Add COMPHY " Stefan Roese
2016-09-16 13:09 ` [U-Boot] [PATCH 13/15] arm64: mvebu: Armada 3700: Add USB " Stefan Roese
2016-09-16 13:09 ` [U-Boot] [PATCH 14/15] arm64: mvebu: Add support for the Marvell Armada 3700 SoC Stefan Roese
2016-09-16 13:09 ` [U-Boot] [PATCH 15/15] arm64: mvebu: Add Armada 3700 db-88f3720 development board support Stefan Roese

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.