From 35e3fca7e3ddaa2ae1fe9bd00b22be73e60a6042 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Thu, 25 Aug 2016 12:56:50 +0200 Subject: net: mvneta: Round up top tx buffer boundaries for dcache ops check_cache_range() warns that the top boundaries are not properly aligned when flushing or invalidating the buffers and make these operations fail. This gets rid of the warnings: CACHE: Misaligned operation at range ... Signed-off-by: Stefan Roese Acked-by: Joe Hershberger diff --git a/drivers/net/mvneta.c b/drivers/net/mvneta.c index 6d51b9f..7ed9e29 100644 --- a/drivers/net/mvneta.c +++ b/drivers/net/mvneta.c @@ -1506,7 +1506,8 @@ static int mvneta_send(struct udevice *dev, void *packet, int length) tx_desc->buf_phys_addr = (u32)packet; tx_desc->data_size = length; - flush_dcache_range((u32)packet, (u32)packet + length); + flush_dcache_range((u32)packet, + (u32)packet + ALIGN(length, PKTALIGN)); /* First and Last descriptor */ tx_desc->command = MVNETA_TX_L4_CSUM_NOT | MVNETA_TXD_FLZ_DESC; -- cgit v0.10.2 From 6985d4966232bfc7bd1a13b46fe3ccbdf46e62f0 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Tue, 17 May 2016 16:36:00 +0200 Subject: serial: Add serial_mvebu_a3700 for Armada 3700 SoC The Armada 3700's UART is a simple serial port. It has a 32 bytes Tx FIFO and a 64 bytes Rx FIFO integrated. This patch adds support for this UART including the DEBUG UART functions for very early debug output. Signed-off-by: Stefan Roese Cc: Nadav Haklai Cc: Kostya Porotchkin Cc: Wilson Ding Cc: Victor Gu Cc: Hua Jing Cc: Terry Zhou Cc: Hanna Hawa Cc: Haim Boot 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..192e79a --- /dev/null +++ b/drivers/serial/serial_mvebu_a3700.c @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2016 Stefan Roese + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +struct mvebu_platdata { + void __iomem *base; +}; + +/* + * Register offset + */ +#define UART_RX_REG 0x00 +#define UART_TX_REG 0x04 +#define UART_CTRL_REG 0x08 +#define UART_STATUS_REG 0x0c +#define UART_BAUD_REG 0x10 +#define UART_POSSR_REG 0x14 + +#define UART_STATUS_RX_RDY 0x10 +#define UART_STATUS_TXFIFO_FULL 0x800 + +#define UART_CTRL_RXFIFO_RESET 0x4000 +#define UART_CTRL_TXFIFO_RESET 0x8000 + +#define CONFIG_UART_BASE_CLOCK 25804800 + +static int mvebu_serial_putc(struct udevice *dev, const char ch) +{ + struct mvebu_platdata *plat = dev_get_platdata(dev); + void __iomem *base = plat->base; + + while (readl(base + UART_STATUS_REG) & UART_STATUS_TXFIFO_FULL) + ; + + writel(ch, base + UART_TX_REG); + + return 0; +} + +static int mvebu_serial_getc(struct udevice *dev) +{ + struct mvebu_platdata *plat = dev_get_platdata(dev); + void __iomem *base = plat->base; + + while (!(readl(base + UART_STATUS_REG) & UART_STATUS_RX_RDY)) + ; + + return readl(base + UART_RX_REG) & 0xff; +} + +static int mvebu_serial_pending(struct udevice *dev, bool input) +{ + struct mvebu_platdata *plat = dev_get_platdata(dev); + void __iomem *base = plat->base; + + if (readl(base + UART_STATUS_REG) & UART_STATUS_RX_RDY) + return 1; + + return 0; +} + +static int mvebu_serial_setbrg(struct udevice *dev, int baudrate) +{ + struct mvebu_platdata *plat = dev_get_platdata(dev); + void __iomem *base = plat->base; + + /* + * Calculate divider + * baudrate = clock / 16 / divider + */ + writel(CONFIG_UART_BASE_CLOCK / baudrate / 16, base + UART_BAUD_REG); + + /* + * Set Programmable Oversampling Stack to 0, + * UART defaults to 16x scheme + */ + writel(0, base + UART_POSSR_REG); + + return 0; +} + +static int mvebu_serial_probe(struct udevice *dev) +{ + struct mvebu_platdata *plat = dev_get_platdata(dev); + void __iomem *base = plat->base; + + /* reset FIFOs */ + writel(UART_CTRL_RXFIFO_RESET | UART_CTRL_TXFIFO_RESET, + base + UART_CTRL_REG); + + /* No Parity, 1 Stop */ + writel(0, base + UART_CTRL_REG); + + return 0; +} + +static int mvebu_serial_ofdata_to_platdata(struct udevice *dev) +{ + struct mvebu_platdata *plat = dev_get_platdata(dev); + + plat->base = dev_get_addr_ptr(dev); + + return 0; +} + +static const struct dm_serial_ops mvebu_serial_ops = { + .putc = mvebu_serial_putc, + .pending = mvebu_serial_pending, + .getc = mvebu_serial_getc, + .setbrg = mvebu_serial_setbrg, +}; + +static const struct udevice_id mvebu_serial_ids[] = { + { .compatible = "marvell,armada-3700-uart" }, + { } +}; + +U_BOOT_DRIVER(serial_mvebu) = { + .name = "serial_mvebu", + .id = UCLASS_SERIAL, + .of_match = mvebu_serial_ids, + .ofdata_to_platdata = mvebu_serial_ofdata_to_platdata, + .platdata_auto_alloc_size = sizeof(struct mvebu_platdata), + .probe = mvebu_serial_probe, + .ops = &mvebu_serial_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +#ifdef CONFIG_DEBUG_MVEBU_A3700_UART + +#include + +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 -- cgit v0.10.2 From 3fda4ef39557c070558d51c4ea4562c370c3f96d Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Thu, 19 May 2016 15:56:44 +0200 Subject: spi: Add driver for Marvell Armada 3700 SoC 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 Cc: Nadav Haklai Cc: Kostya Porotchkin Cc: Wilson Ding Cc: Victor Gu Cc: Hua Jing Cc: Terry Zhou Cc: Hanna Hawa Cc: Haim Boot Reviewed-by: Jagan Teki 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..7c58c36 --- /dev/null +++ b/drivers/spi/mvebu_a3700_spi.c @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2015 Marvell International Ltd. + * + * Copyright (C) 2016 Stefan Roese + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#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(®->ctrl, MVEBU_SPI_A3700_SPI_EN_0 << cs); +} + +static void spi_cs_deactivate(struct spi_reg *reg, int cs) +{ + clrbits_le32(®->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__, ®->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, ®->dout); + + if (din) { + ret = wait_for_bit(__func__, ®->ctrl, + MVEBU_SPI_A3700_XFER_RDY, + true, 100, false); + if (ret) + return ret; + + /* Read what is transferred in */ + *din_8 = (u8)readl(®->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__, ®->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(®->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, ®->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(®->cfg, MVEBU_SPI_A3700_CLK_POL); + else + clrbits_le32(®->cfg, MVEBU_SPI_A3700_CLK_POL); + if (mode & SPI_CPHA) + setbits_le32(®->cfg, MVEBU_SPI_A3700_CLK_PHA); + else + clrbits_le32(®->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(®->cfg); + writel(data | MVEBU_SPI_A3700_FIFO_FLUSH, ®->cfg); + ret = wait_for_bit(__func__, ®->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, ®->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, +}; -- cgit v0.10.2 From 3cbc11da866936c04ef95ea077e891d907cd4ad9 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Thu, 19 May 2016 18:09:17 +0200 Subject: net: mvneta: Make driver 64bit safe 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 Cc: Nadav Haklai Cc: Kostya Porotchkin Cc: Wilson Ding Cc: Victor Gu Cc: Hua Jing Cc: Terry Zhou Cc: Hanna Hawa Cc: Haim Boot Acked-by: Joe Hershberger diff --git a/drivers/net/mvneta.c b/drivers/net/mvneta.c index 7ed9e29..a1bf227 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)); -- cgit v0.10.2 From 544eefe084661d5ee486aca0cd0ec03801bfced9 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Thu, 19 May 2016 17:46:36 +0200 Subject: net: mvneta: Add support for Armada 3700 SoC 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 Cc: Nadav Haklai Cc: Kostya Porotchkin Cc: Wilson Ding Cc: Victor Gu Cc: Hua Jing Cc: Terry Zhou Cc: Hanna Hawa Cc: Haim Boot Acked-by: Joe Hershberger diff --git a/drivers/net/mvneta.c b/drivers/net/mvneta.c index a1bf227..51bb569 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" }, { } }; -- cgit v0.10.2 From 81c1f6f0c3b05ae07c521c2dce579f0cb0816926 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Thu, 14 Jul 2016 11:39:20 +0200 Subject: usb: xhci: Add Marvell MVEBU xHCI support 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 Cc: Nadav Haklai Cc: Kostya Porotchkin Cc: Wilson Ding Cc: Victor Gu Cc: Hua Jing Cc: Terry Zhou Cc: Hanna Hawa Cc: Haim Boot Acked-by: Marek Vasut diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 61e13d7..b9c5fbe 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -21,6 +21,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. + config USB_XHCI_ROCKCHIP bool "Support for Rockchip on-chip xHCI USB controller" depends on ARCH_ROCKCHIP diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index de25328..58c0cf5 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -61,6 +61,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 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 +#include +#include +#include +#include + +#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, +}; -- cgit v0.10.2 From c6cfcc91ea59d800672274a056eefa93a10711e9 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Mon, 18 Jul 2016 17:24:56 +0200 Subject: usb: ehci: ehci-marvell.c: Add Armada 3700 support (ARMv8) 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 Cc: Nadav Haklai Cc: Kostya Porotchkin Cc: Wilson Ding Cc: Victor Gu Cc: Hua Jing Cc: Terry Zhou Cc: Hanna Hawa Cc: Haim Boot Acked-by: Marek Vasut diff --git a/drivers/usb/host/ehci-marvell.c b/drivers/usb/host/ehci-marvell.c index 253fcb3..4642470 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,21 +114,33 @@ 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 const struct udevice_id ehci_usb_ids[] = { { .compatible = "marvell,orion-ehci", }, + { .compatible = "marvell,armada3700-ehci", }, { } }; -- cgit v0.10.2 From 3335786a982578abf9a25e4d6ce67d3416ebe15e Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Mon, 23 May 2016 11:12:05 +0200 Subject: drivers/phy: Add Marvell SerDes / PHY drivers used on Armada 3k 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 Cc: Nadav Haklai Cc: Kostya Porotchkin Cc: Wilson Ding Cc: Victor Gu Cc: Hua Jing Cc: Terry Zhou Cc: Hanna Hawa Cc: Haim Boot diff --git a/drivers/Kconfig b/drivers/Kconfig index 4c555a0..e8c9e0a 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -48,6 +48,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 ca98273..761d0b3 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -70,6 +70,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 +#include + +#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 +#include +#include +#include +#include + +#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 at 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..67eb139 --- /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 + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +#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 +#include + +#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_ */ + -- cgit v0.10.2 From 850db82fcbfca9499c600334fd5fa431d87516cf Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Tue, 17 May 2016 14:03:25 +0200 Subject: arm64: mvebu: Armada 3700: Add Armada 37xx dts files This patch integrates the Armada 3700 dts files from the latest submission on the linux-arm-kernel mailing list. Signed-off-by: Stefan Roese Cc: Nadav Haklai Cc: Kostya Porotchkin Cc: Wilson Ding Cc: Victor Gu Cc: Hua Jing Cc: Terry Zhou Cc: Hanna Hawa Cc: Haim Boot diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index e89b6e80..e2de5e4 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 + * + * 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 + * + * 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 + * + * 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@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 + * + * 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 + +/ { + 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@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 = , + , + , + ; + }; + + 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@12000 { + compatible = "marvell,armada-3700-uart"; + reg = <0x12000 0x400>; + interrupts = ; + status = "disabled"; + }; + + usb3: usb@58000 { + compatible = "marvell,armada3700-xhci", + "generic-xhci"; + reg = <0x58000 0x4000>; + interrupts = ; + status = "disabled"; + }; + + xor@60900 { + compatible = "marvell,armada-3700-xor"; + reg = <0x60900 0x100 + 0x60b00 0x100>; + + xor10 { + interrupts = ; + }; + xor11 { + interrupts = ; + }; + }; + + sata: sata@e0000 { + compatible = "marvell,armada-3700-ahci"; + reg = <0xe0000 0x2000>; + interrupts = ; + status = "disabled"; + }; + + gic: interrupt-controller@1d00000 { + compatible = "arm,gic-v3"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0x1d00000 0x10000>, /* GICD */ + <0x1d40000 0x40000>; /* GICR */ + }; + }; + }; +}; -- cgit v0.10.2 From cdccf9c17b4f1d03ce50e89d7cfff6350bb865b1 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Thu, 19 May 2016 10:41:01 +0200 Subject: arm64: mvebu: Armada 3700: Add SPI device tree nodes This patch adds the SPI device tree nodes that are still missing to the Armada 3700 dts files. Signed-off-by: Stefan Roese Cc: Nadav Haklai Cc: Kostya Porotchkin Cc: Wilson Ding Cc: Victor Gu Cc: Hua Jing Cc: Terry Zhou Cc: Hanna Hawa Cc: Haim Boot Reviewed-by: Jagan Teki 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@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@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"; + }; }; }; }; -- cgit v0.10.2 From 3f84e2e8906797772d920a770e556c24762ce464 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Thu, 19 May 2016 17:45:20 +0200 Subject: arm64: mvebu: Armada 3700: Add ethernet device tree nodes This patch adds the ethernet device tree nodes that are still missing to the Armada 3700 dts files. Signed-off-by: Stefan Roese Cc: Nadav Haklai Cc: Kostya Porotchkin Cc: Wilson Ding Cc: Victor Gu Cc: Hua Jing Cc: Terry Zhou Cc: Hanna Hawa Cc: Haim Boot diff --git a/arch/arm/dts/armada-3720-db.dts b/arch/arm/dts/armada-3720-db.dts index 7bfa840..2cc99bf 100644 --- a/arch/arm/dts/armada-3720-db.dts +++ b/arch/arm/dts/armada-3720-db.dts @@ -57,6 +57,7 @@ }; aliases { + ethernet0 = ð0; spi0 = &spi0; }; @@ -66,6 +67,11 @@ }; }; +ð0 { + 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@30000 { + compatible = "marvell,armada-3700-neta"; + reg = <0x30000 0x20>; + status = "disabled"; + }; + + eth1: neta@40000 { + compatible = "marvell,armada-3700-neta"; + reg = <0x40000 0x20>; + status = "disabled"; + }; + spi0: spi@10600 { compatible = "marvell,armada-3700-spi"; reg = <0x10600 0x50>; -- cgit v0.10.2 From 9e9e63c027e52549fcb51188394c6d3a534401c6 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Thu, 21 Jul 2016 11:34:32 +0200 Subject: arm64: mvebu: Armada 3700: Add I2C device tree nodes This patch adds the I2C device tree nodes that are still missing to the Armada 3700 dts files. Signed-off-by: Stefan Roese Cc: Nadav Haklai Cc: Kostya Porotchkin Cc: Wilson Ding Cc: Victor Gu Cc: Hua Jing Cc: Terry Zhou Cc: Hanna Hawa Cc: Haim Boot diff --git a/arch/arm/dts/armada-3720-db.dts b/arch/arm/dts/armada-3720-db.dts index 2cc99bf..f177c76 100644 --- a/arch/arm/dts/armada-3720-db.dts +++ b/arch/arm/dts/armada-3720-db.dts @@ -58,6 +58,7 @@ aliases { ethernet0 = ð0; + 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@11000 { + compatible = "marvell,armada-3700-i2c"; + reg = <0x11000 0x100>; + status = "disabled"; + }; + spi0: spi@10600 { compatible = "marvell,armada-3700-spi"; reg = <0x10600 0x50>; -- cgit v0.10.2 From 56d53956979f233ca767e12f02b8c74e790f6017 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Fri, 26 Aug 2016 13:10:45 +0200 Subject: arm64: mvebu: Armada 3700: Add COMPHY device tree nodes This patch adds the COMPHY device tree nodes that are still missing to the Armada 3700 dts files. Signed-off-by: Stefan Roese Cc: Nadav Haklai Cc: Kostya Porotchkin Cc: Wilson Ding Cc: Victor Gu Cc: Hua Jing Cc: Terry Zhou Cc: Hanna Hawa Cc: Haim Boot diff --git a/arch/arm/dts/armada-3720-db.dts b/arch/arm/dts/armada-3720-db.dts index f177c76..60d841c 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-speed = ; + }; + + phy1 { + phy-type = ; + phy-speed = ; + }; +}; + ð0 { 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 +#include / { model = "Marvell Armada 37xx SoC"; @@ -169,6 +170,14 @@ spi-max-frequency = <40000>; status = "disabled"; }; + + comphy: comphy@18300 { + compatible = "marvell,mvebu-comphy", "marvell,comphy-armada-3700"; + reg = <0x18300 0x28>, + <0x1f300 0x3d000>; + mux-bitcount = <1>; + max-lanes = <2>; + }; }; }; }; -- cgit v0.10.2 From f733228ade3517c975b6dde0de656fc2a7c44dc4 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Fri, 26 Aug 2016 13:50:41 +0200 Subject: arm64: mvebu: Armada 3700: Add USB device tree nodes This patch adds the USB device tree nodes that are still missing to the Armada 3700 dts files. Signed-off-by: Stefan Roese Cc: Nadav Haklai Cc: Kostya Porotchkin Cc: Wilson Ding Cc: Victor Gu Cc: Hua Jing Cc: Terry Zhou Cc: Hanna Hawa Cc: Haim Boot diff --git a/arch/arm/dts/armada-3720-db.dts b/arch/arm/dts/armada-3720-db.dts index 60d841c..83967ee 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@5e000 { + compatible = "marvell,armada3700-ehci"; + reg = <0x5e000 0x450>; + status = "disabled"; + }; + xor@60900 { compatible = "marvell,armada-3700-xor"; reg = <0x60900 0x100 -- cgit v0.10.2 From f61aefc150a30347db2d8aa2427b57d1c78e4357 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Tue, 17 May 2016 15:00:30 +0200 Subject: arm64: mvebu: Add support for the Marvell Armada 3700 SoC 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 Cc: Nadav Haklai Cc: Kostya Porotchkin Cc: Wilson Ding Cc: Victor Gu Cc: Hua Jing Cc: Terry Zhou Cc: Hanna Hawa Cc: Haim Boot diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 38ad590..9ae442e 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 0fd71a7..f169fc5 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 88F6820 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 +# Copyright (C) 2014-2016 Stefan Roese # # 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 +# +# 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 + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +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 -- cgit v0.10.2 From 01e62c7f11eb4c1fe814f109ecb34e1a176eb33b Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Tue, 17 May 2016 15:04:16 +0200 Subject: arm64: mvebu: Add Armada 3700 db-88f3720 development board support 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 Cc: Nadav Haklai Cc: Kostya Porotchkin Cc: Wilson Ding Cc: Victor Gu Cc: Hua Jing Cc: Terry Zhou Cc: Hanna Hawa Cc: Haim Boot diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index f169fc5..58f2296 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -56,6 +56,10 @@ config TARGET_CLEARFOG bool "Support ClearFog" select 88F6820 +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 @@ -88,6 +92,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-88f6820-amc" if TARGET_DB_88F6820_AMC @@ -98,6 +103,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-88f6820-amc" if TARGET_DB_88F6820_AMC @@ -108,6 +114,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 "Marvell" if TARGET_DB_88F6820_AMC 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 +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 +# +# 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 + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +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..e785f24 --- /dev/null +++ b/include/configs/mvebu_db-88f3720.h @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2016 Stefan Roese + * + * 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 } + +/* + * 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 */ -- cgit v0.10.2 From c0132f60059d4a6809341d54f2fe744db8790421 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Tue, 30 Aug 2016 16:48:20 +0200 Subject: drivers/phy: Add Marvell SerDes / PHY drivers used on Armada 7K/8K 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 Cc: Nadav Haklai Cc: Neta Zur Hershkovits Cc: Kostya Porotchkin Cc: Omri Itach Cc: Igal Liberman Cc: Haim Boot Cc: Hanna Hawa diff --git a/drivers/phy/marvell/Makefile b/drivers/phy/marvell/Makefile index 91df554..f181505 100644 --- a/drivers/phy/marvell/Makefile +++ b/drivers/phy/marvell/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_MVEBU_COMPHY_SUPPORT) += comphy_core.o obj-$(CONFIG_MVEBU_COMPHY_SUPPORT) += comphy_mux.o obj-$(CONFIG_ARMADA_3700) += comphy_a3700.o +obj-$(CONFIG_ARMADA_8K) += comphy_cp110.o diff --git a/drivers/phy/marvell/comphy.h b/drivers/phy/marvell/comphy.h index 5c50e9c..df5b7d5 100644 --- a/drivers/phy/marvell/comphy.h +++ b/drivers/phy/marvell/comphy.h @@ -60,6 +60,9 @@ #define COMMON_PHY_SD_CTRL1_RXAUI0_MASK \ (0x1 << COMMON_PHY_SD_CTRL1_RXAUI0_OFFSET) +/* ToDo: Get this address via DT */ +#define MVEBU_CP0_REGS_BASE 0xF2000000UL + #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 \ @@ -117,10 +120,21 @@ static inline int comphy_a3700_init(struct chip_serdes_phy_config *ptr_chip_cfg, return -1; } #endif -int comphy_ap806_init(struct chip_serdes_phy_config *ptr_chip_cfg, - struct comphy_map *serdes_map); + +#ifdef CONFIG_ARMADA_8K int comphy_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg, struct comphy_map *serdes_map); +#else +static inline int comphy_cp110_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 void comphy_dedicated_phys_init(void); diff --git a/drivers/phy/marvell/comphy_core.c b/drivers/phy/marvell/comphy_core.c index 67eb139..344df3b 100644 --- a/drivers/phy/marvell/comphy_core.c +++ b/drivers/phy/marvell/comphy_core.c @@ -139,6 +139,9 @@ static int comphy_probe(struct udevice *dev) if (of_device_is_compatible(dev, "marvell,comphy-armada-3700")) chip_cfg->ptr_comphy_chip_init = comphy_a3700_init; + if (of_device_is_compatible(dev, "marvell,comphy-cp110")) + chip_cfg->ptr_comphy_chip_init = comphy_cp110_init; + /* * Bail out if no chip_init function is defined, e.g. no * compatible node is found diff --git a/drivers/phy/marvell/comphy_cp110.c b/drivers/phy/marvell/comphy_cp110.c new file mode 100644 index 0000000..25c067d --- /dev/null +++ b/drivers/phy/marvell/comphy_cp110.c @@ -0,0 +1,1726 @@ +/* + * Copyright (C) 2015-2016 Marvell International Ltd. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +#include "comphy.h" +#include "comphy_hpipe.h" +#include "sata.h" +#include "utmi_phy.h" + +DECLARE_GLOBAL_DATA_PTR; + +#define SD_ADDR(base, lane) (base + 0x1000 * lane) +#define HPIPE_ADDR(base, lane) (SD_ADDR(base, lane) + 0x800) +#define COMPHY_ADDR(base, lane) (base + 0x28 * lane) + +struct utmi_phy_data { + void __iomem *utmi_base_addr; + void __iomem *usb_cfg_addr; + void __iomem *utmi_cfg_addr; + u32 utmi_phy_port; +}; + +/* + * For CP-110 we have 2 Selector registers "PHY Selectors", + * and "PIPE Selectors". + * PIPE selector include USB and PCIe options. + * PHY selector include the Ethernet and SATA options, every Ethernet + * option has different options, for example: serdes lane2 had option + * Eth_port_0 that include (SGMII0, XAUI0, RXAUI0, KR) + */ +struct comphy_mux_data cp110_comphy_phy_mux_data[] = { + {4, {{PHY_TYPE_UNCONNECTED, 0x0}, {PHY_TYPE_SGMII2, 0x1}, /* Lane 0 */ + {PHY_TYPE_XAUI2, 0x1}, {PHY_TYPE_SATA1, 0x4} } }, + {4, {{PHY_TYPE_UNCONNECTED, 0x0}, {PHY_TYPE_SGMII3, 0x1}, /* Lane 1 */ + {PHY_TYPE_XAUI3, 0x1}, {PHY_TYPE_SATA0, 0x4} } }, + {6, {{PHY_TYPE_UNCONNECTED, 0x0}, {PHY_TYPE_SGMII0, 0x1}, /* Lane 2 */ + {PHY_TYPE_XAUI0, 0x1}, {PHY_TYPE_RXAUI0, 0x1}, + {PHY_TYPE_KR, 0x1}, {PHY_TYPE_SATA0, 0x4} } }, + {8, {{PHY_TYPE_UNCONNECTED, 0x0}, {PHY_TYPE_SGMII0, 0x1}, /* Lane 3 */ + {PHY_TYPE_XAUI0, 0x1}, {PHY_TYPE_RXAUI0, 0x1}, + {PHY_TYPE_KR, 0x1}, {PHY_TYPE_XAUI1, 0x1}, + {PHY_TYPE_RXAUI1, 0x1}, {PHY_TYPE_SATA1, 0x4} } }, + {7, {{PHY_TYPE_UNCONNECTED, 0x0}, {PHY_TYPE_SGMII0, 0x2}, /* Lane 4 */ + {PHY_TYPE_XAUI0, 0x1}, {PHY_TYPE_RXAUI0, 0x1}, {PHY_TYPE_KR, 0x1}, + {PHY_TYPE_SGMII2, 0x1}, {PHY_TYPE_XAUI2, 0x1} } }, + {6, {{PHY_TYPE_UNCONNECTED, 0x0}, {PHY_TYPE_XAUI1, 0x1}, /* Lane 5 */ + {PHY_TYPE_RXAUI1, 0x1}, {PHY_TYPE_SGMII3, 0x1}, + {PHY_TYPE_XAUI3, 0x1}, {PHY_TYPE_SATA1, 0x4} } }, +}; + +struct comphy_mux_data cp110_comphy_pipe_mux_data[] = { + {2, {{PHY_TYPE_UNCONNECTED, 0x0}, {PHY_TYPE_PEX0, 0x4} } }, /* Lane 0 */ + {4, {{PHY_TYPE_UNCONNECTED, 0x0}, /* Lane 1 */ + {PHY_TYPE_USB3_HOST0, 0x1}, {PHY_TYPE_USB3_DEVICE, 0x2}, + {PHY_TYPE_PEX0, 0x4} } }, + {3, {{PHY_TYPE_UNCONNECTED, 0x0}, /* Lane 2 */ + {PHY_TYPE_USB3_HOST0, 0x1}, {PHY_TYPE_PEX0, 0x4} } }, + {3, {{PHY_TYPE_UNCONNECTED, 0x0}, /* Lane 3 */ + {PHY_TYPE_USB3_HOST1, 0x1}, {PHY_TYPE_PEX0, 0x4} } }, + {4, {{PHY_TYPE_UNCONNECTED, 0x0}, /* Lane 4 */ + {PHY_TYPE_USB3_HOST1, 0x1}, + {PHY_TYPE_USB3_DEVICE, 0x2}, {PHY_TYPE_PEX1, 0x4} } }, + {2, {{PHY_TYPE_UNCONNECTED, 0x0}, {PHY_TYPE_PEX2, 0x4} } }, /* Lane 5 */ +}; + +static u32 polling_with_timeout(void __iomem *addr, u32 val, + u32 mask, unsigned long usec_timout) +{ + u32 data; + + do { + udelay(1); + data = readl(addr) & mask; + } while (data != val && --usec_timout > 0); + + if (usec_timout == 0) + return data; + + return 0; +} + +static int comphy_pcie_power_up(u32 lane, u32 pcie_width, + bool clk_src, void __iomem *hpipe_base, + void __iomem *comphy_base) +{ + u32 mask, data, ret = 1; + void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane); + void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane); + void __iomem *addr; + u32 pcie_clk = 0; /* set input by default */ + + debug_enter(); + + /* + * ToDo: + * Add SAR (Sample-At-Reset) configuration for the PCIe clock + * direction. SAR code is currently not ported from Marvell + * U-Boot to mainline version. + * + * SerDes Lane 4/5 got the PCIe ref-clock #1, + * and SerDes Lane 0 got PCIe ref-clock #0 + */ + debug("PCIe clock = %x\n", pcie_clk); + debug("PCIe width = %d\n", pcie_width); + + /* enable PCIe by4 and by2 */ + if (lane == 0) { + if (pcie_width == 4) { + reg_set(comphy_base + COMMON_PHY_SD_CTRL1, + 0x1 << COMMON_PHY_SD_CTRL1_PCIE_X4_EN_OFFSET, + COMMON_PHY_SD_CTRL1_PCIE_X4_EN_MASK); + } else if (pcie_width == 2) { + reg_set(comphy_base + COMMON_PHY_SD_CTRL1, + 0x1 << COMMON_PHY_SD_CTRL1_PCIE_X2_EN_OFFSET, + COMMON_PHY_SD_CTRL1_PCIE_X2_EN_MASK); + } + } + + /* + * If PCIe clock is output and clock source from SerDes lane 5, + * we need to configure the clock-source MUX. + * By default, the clock source is from lane 4 + */ + if (pcie_clk && clk_src && (lane == 5)) { + reg_set((void __iomem *)DFX_DEV_GEN_CTRL12, + 0x3 << DFX_DEV_GEN_PCIE_CLK_SRC_OFFSET, + DFX_DEV_GEN_PCIE_CLK_SRC_MASK); + } + + debug("stage: RFU configurations - hard reset comphy\n"); + /* RFU configurations - hard reset comphy */ + mask = COMMON_PHY_CFG1_PWR_UP_MASK; + data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; + mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; + data |= 0x1 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; + mask |= COMMON_PHY_CFG1_PWR_ON_RESET_MASK; + data |= 0x0 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET; + mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK; + data |= 0x0 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET; + mask |= COMMON_PHY_PHY_MODE_MASK; + data |= 0x0 << COMMON_PHY_PHY_MODE_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); + + /* release from hard reset */ + mask = COMMON_PHY_CFG1_PWR_ON_RESET_MASK; + data = 0x1 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET; + mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK; + data |= 0x1 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); + + /* Wait 1ms - until band gap and ref clock ready */ + mdelay(1); + /* Start comphy Configuration */ + debug("stage: Comphy configuration\n"); + /* Set PIPE soft reset */ + mask = HPIPE_RST_CLK_CTRL_PIPE_RST_MASK; + data = 0x1 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET; + /* Set PHY datapath width mode for V0 */ + mask |= HPIPE_RST_CLK_CTRL_FIXED_PCLK_MASK; + data |= 0x1 << HPIPE_RST_CLK_CTRL_FIXED_PCLK_OFFSET; + /* Set Data bus width USB mode for V0 */ + mask |= HPIPE_RST_CLK_CTRL_PIPE_WIDTH_MASK; + data |= 0x0 << HPIPE_RST_CLK_CTRL_PIPE_WIDTH_OFFSET; + /* Set CORE_CLK output frequency for 250Mhz */ + mask |= HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_MASK; + data |= 0x0 << HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG, data, mask); + /* Set PLL ready delay for 0x2 */ + data = 0x2 << HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET; + mask = HPIPE_CLK_SRC_LO_PLL_RDY_DL_MASK; + if (pcie_width != 1) { + data |= 0x1 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_OFFSET; + mask |= HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_MASK; + data |= 0x1 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_OFFSET; + mask |= HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_MASK; + } + reg_set(hpipe_addr + HPIPE_CLK_SRC_LO_REG, data, mask); + + /* Set PIPE mode interface to PCIe3 - 0x1 & set lane order */ + data = 0x1 << HPIPE_CLK_SRC_HI_MODE_PIPE_OFFSET; + mask = HPIPE_CLK_SRC_HI_MODE_PIPE_MASK; + if (pcie_width != 1) { + mask |= HPIPE_CLK_SRC_HI_LANE_STRT_MASK; + mask |= HPIPE_CLK_SRC_HI_LANE_MASTER_MASK; + mask |= HPIPE_CLK_SRC_HI_LANE_BREAK_MASK; + if (lane == 0) { + data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_STRT_OFFSET; + data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_MASTER_OFFSET; + } else if (lane == (pcie_width - 1)) { + data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_BREAK_OFFSET; + } + } + reg_set(hpipe_addr + HPIPE_CLK_SRC_HI_REG, data, mask); + /* Config update polarity equalization */ + reg_set(hpipe_addr + HPIPE_LANE_EQ_CFG1_REG, + 0x1 << HPIPE_CFG_UPDATE_POLARITY_OFFSET, + HPIPE_CFG_UPDATE_POLARITY_MASK); + /* Set PIPE version 4 to mode enable */ + reg_set(hpipe_addr + HPIPE_DFE_CTRL_28_REG, + 0x1 << HPIPE_DFE_CTRL_28_PIPE4_OFFSET, + HPIPE_DFE_CTRL_28_PIPE4_MASK); + /* TODO: check if pcie clock is output/input - for bringup use input*/ + /* Enable PIN clock 100M_125M */ + mask = 0; + data = 0; + /* Only if clock is output, configure the clock-source mux */ + if (pcie_clk) { + mask |= HPIPE_MISC_CLK100M_125M_MASK; + data |= 0x1 << HPIPE_MISC_CLK100M_125M_OFFSET; + } + /* + * Set PIN_TXDCLK_2X Clock Frequency Selection for outputs 500MHz + * clock + */ + mask |= HPIPE_MISC_TXDCLK_2X_MASK; + data |= 0x0 << HPIPE_MISC_TXDCLK_2X_OFFSET; + /* Enable 500MHz Clock */ + mask |= HPIPE_MISC_CLK500_EN_MASK; + data |= 0x1 << HPIPE_MISC_CLK500_EN_OFFSET; + if (pcie_clk) { /* output */ + /* Set reference clock comes from group 1 */ + mask |= HPIPE_MISC_REFCLK_SEL_MASK; + data |= 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET; + } else { + /* Set reference clock comes from group 2 */ + mask |= HPIPE_MISC_REFCLK_SEL_MASK; + data |= 0x1 << HPIPE_MISC_REFCLK_SEL_OFFSET; + } + reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask); + if (pcie_clk) { /* output */ + /* Set reference frequcency select - 0x2 for 25MHz*/ + mask = HPIPE_PWR_PLL_REF_FREQ_MASK; + data = 0x2 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; + } else { + /* Set reference frequcency select - 0x0 for 100MHz*/ + mask = HPIPE_PWR_PLL_REF_FREQ_MASK; + data = 0x0 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; + } + /* Set PHY mode to PCIe */ + mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; + data |= 0x3 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); + + /* ref clock alignment */ + if (pcie_width != 1) { + mask = HPIPE_LANE_ALIGN_OFF_MASK; + data = 0x0 << HPIPE_LANE_ALIGN_OFF_OFFSET; + reg_set(hpipe_addr + HPIPE_LANE_ALIGN_REG, data, mask); + } + + /* + * Set the amount of time spent in the LoZ state - set for 0x7 only if + * the PCIe clock is output + */ + if (pcie_clk) { + reg_set(hpipe_addr + HPIPE_GLOBAL_PM_CTRL, + 0x7 << HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET, + HPIPE_GLOBAL_PM_RXDLOZ_WAIT_MASK); + } + + /* Set Maximal PHY Generation Setting(8Gbps) */ + mask = HPIPE_INTERFACE_GEN_MAX_MASK; + data = 0x2 << HPIPE_INTERFACE_GEN_MAX_OFFSET; + /* Set Link Train Mode (Tx training control pins are used) */ + mask |= HPIPE_INTERFACE_LINK_TRAIN_MASK; + data |= 0x1 << HPIPE_INTERFACE_LINK_TRAIN_OFFSET; + reg_set(hpipe_addr + HPIPE_INTERFACE_REG, data, mask); + + /* Set Idle_sync enable */ + mask = HPIPE_PCIE_IDLE_SYNC_MASK; + data = 0x1 << HPIPE_PCIE_IDLE_SYNC_OFFSET; + /* Select bits for PCIE Gen3(32bit) */ + mask |= HPIPE_PCIE_SEL_BITS_MASK; + data |= 0x2 << HPIPE_PCIE_SEL_BITS_OFFSET; + reg_set(hpipe_addr + HPIPE_PCIE_REG0, data, mask); + + /* Enable Tx_adapt_g1 */ + mask = HPIPE_TX_TRAIN_CTRL_G1_MASK; + data = 0x1 << HPIPE_TX_TRAIN_CTRL_G1_OFFSET; + /* Enable Tx_adapt_gn1 */ + mask |= HPIPE_TX_TRAIN_CTRL_GN1_MASK; + data |= 0x1 << HPIPE_TX_TRAIN_CTRL_GN1_OFFSET; + /* Disable Tx_adapt_g0 */ + mask |= HPIPE_TX_TRAIN_CTRL_G0_MASK; + data |= 0x0 << HPIPE_TX_TRAIN_CTRL_G0_OFFSET; + reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_REG, data, mask); + + /* Set reg_tx_train_chk_init */ + mask = HPIPE_TX_TRAIN_CHK_INIT_MASK; + data = 0x0 << HPIPE_TX_TRAIN_CHK_INIT_OFFSET; + /* Enable TX_COE_FM_PIN_PCIE3_EN */ + mask |= HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_MASK; + data |= 0x1 << HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_OFFSET; + reg_set(hpipe_addr + HPIPE_TX_TRAIN_REG, data, mask); + + debug("stage: TRx training parameters\n"); + /* Set Preset sweep configurations */ + mask = HPIPE_TX_TX_STATUS_CHECK_MODE_MASK; + data = 0x1 << HPIPE_TX_STATUS_CHECK_MODE_OFFSET; + + mask |= HPIPE_TX_NUM_OF_PRESET_MASK; + data |= 0x7 << HPIPE_TX_NUM_OF_PRESET_OFFSET; + + mask |= HPIPE_TX_SWEEP_PRESET_EN_MASK; + data |= 0x1 << HPIPE_TX_SWEEP_PRESET_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_11_REG, data, mask); + + /* Tx train start configuration */ + mask = HPIPE_TX_TRAIN_START_SQ_EN_MASK; + data = 0x1 << HPIPE_TX_TRAIN_START_SQ_EN_OFFSET; + + mask |= HPIPE_TX_TRAIN_START_FRM_DET_EN_MASK; + data |= 0x0 << HPIPE_TX_TRAIN_START_FRM_DET_EN_OFFSET; + + mask |= HPIPE_TX_TRAIN_START_FRM_LOCK_EN_MASK; + data |= 0x0 << HPIPE_TX_TRAIN_START_FRM_LOCK_EN_OFFSET; + + mask |= HPIPE_TX_TRAIN_WAIT_TIME_EN_MASK; + data |= 0x1 << HPIPE_TX_TRAIN_WAIT_TIME_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_5_REG, data, mask); + + /* Enable Tx train P2P */ + mask = HPIPE_TX_TRAIN_P2P_HOLD_MASK; + data = 0x1 << HPIPE_TX_TRAIN_P2P_HOLD_OFFSET; + reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_0_REG, data, mask); + + /* Configure Tx train timeout */ + mask = HPIPE_TRX_TRAIN_TIMER_MASK; + data = 0x17 << HPIPE_TRX_TRAIN_TIMER_OFFSET; + reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_4_REG, data, mask); + + /* Disable G0/G1/GN1 adaptation */ + mask = HPIPE_TX_TRAIN_CTRL_G1_MASK | HPIPE_TX_TRAIN_CTRL_GN1_MASK + | HPIPE_TX_TRAIN_CTRL_G0_OFFSET; + data = 0; + reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_REG, data, mask); + + /* Disable DTL frequency loop */ + mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK; + data = 0x0 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask); + + /* Configure G3 DFE */ + mask = HPIPE_G3_DFE_RES_MASK; + data = 0x3 << HPIPE_G3_DFE_RES_OFFSET; + reg_set(hpipe_addr + HPIPE_G3_SETTING_4_REG, data, mask); + + /* Force DFE resolution (use GEN table value) */ + mask = HPIPE_DFE_RES_FORCE_MASK; + data = 0x1 << HPIPE_DFE_RES_FORCE_OFFSET; + reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask); + + /* Configure initial and final coefficient value for receiver */ + mask = HPIPE_G3_RX_SELMUPI_MASK; + data = 0x1 << HPIPE_G3_RX_SELMUPI_OFFSET; + + mask |= HPIPE_G3_RX_SELMUPF_MASK; + data |= 0x1 << HPIPE_G3_RX_SELMUPF_OFFSET; + + mask |= HPIPE_G3_SETTING_BIT_MASK; + data |= 0x0 << HPIPE_G3_SETTING_BIT_OFFSET; + reg_set(hpipe_addr + HPIPE_G3_SETTINGS_1_REG, data, mask); + + /* Trigger sampler enable pulse */ + mask = HPIPE_SMAPLER_MASK; + data = 0x1 << HPIPE_SMAPLER_OFFSET; + reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask); + udelay(5); + reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, 0, mask); + + /* FFE resistor tuning for different bandwidth */ + mask = HPIPE_G3_FFE_DEG_RES_LEVEL_MASK; + data = 0x1 << HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET; + + mask |= HPIPE_G3_FFE_LOAD_RES_LEVEL_MASK; + data |= 0x1 << HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET; + reg_set(hpipe_addr + HPIPE_G3_SETTING_3_REG, data, mask); + + /* Set phy in root complex mode */ + mask = HPIPE_CFG_PHY_RC_EP_MASK; + data = 0x1 << HPIPE_CFG_PHY_RC_EP_OFFSET; + reg_set(hpipe_addr + HPIPE_LANE_EQU_CONFIG_0_REG, data, mask); + + debug("stage: Comphy power up\n"); + + /* + * For PCIe by4 or by2 - release from reset only after finish to + * configure all lanes + */ + if ((pcie_width == 1) || (lane == (pcie_width - 1))) { + u32 i, start_lane, end_lane; + + if (pcie_width != 1) { + /* allows writing to all lanes in one write */ + reg_set(comphy_base + COMMON_PHY_SD_CTRL1, + 0x0 << + COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_OFFSET, + COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_MASK); + start_lane = 0; + end_lane = pcie_width; + + /* + * Release from PIPE soft reset + * for PCIe by4 or by2 - release from soft reset + * all lanes - can't use read modify write + */ + reg_set(HPIPE_ADDR(hpipe_base, 0) + + HPIPE_RST_CLK_CTRL_REG, 0x24, 0xffffffff); + } else { + start_lane = lane; + end_lane = lane + 1; + + /* + * Release from PIPE soft reset + * for PCIe by4 or by2 - release from soft reset + * all lanes + */ + reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG, + 0x0 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET, + HPIPE_RST_CLK_CTRL_PIPE_RST_MASK); + } + + + if (pcie_width != 1) { + /* disable writing to all lanes with one write */ + reg_set(comphy_base + COMMON_PHY_SD_CTRL1, + 0x3210 << + COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_OFFSET, + COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_MASK); + } + + debug("stage: Check PLL\n"); + /* Read lane status */ + for (i = start_lane; i < end_lane; i++) { + addr = HPIPE_ADDR(hpipe_base, i) + + HPIPE_LANE_STATUS1_REG; + data = HPIPE_LANE_STATUS1_PCLK_EN_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, 15000); + if (data != 0) { + debug("Read from reg = %p - value = 0x%x\n", + hpipe_addr + HPIPE_LANE_STATUS1_REG, + data); + error("HPIPE_LANE_STATUS1_PCLK_EN_MASK is 0\n"); + ret = 0; + } + } + } + + debug_exit(); + return ret; +} + +static int comphy_usb3_power_up(u32 lane, void __iomem *hpipe_base, + void __iomem *comphy_base) +{ + u32 mask, data, ret = 1; + void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane); + void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane); + void __iomem *addr; + + debug_enter(); + debug("stage: RFU configurations - hard reset comphy\n"); + /* RFU configurations - hard reset comphy */ + mask = COMMON_PHY_CFG1_PWR_UP_MASK; + data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; + mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; + data |= 0x1 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; + mask |= COMMON_PHY_CFG1_PWR_ON_RESET_MASK; + data |= 0x0 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET; + mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK; + data |= 0x0 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET; + mask |= COMMON_PHY_PHY_MODE_MASK; + data |= 0x1 << COMMON_PHY_PHY_MODE_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); + + /* release from hard reset */ + mask = COMMON_PHY_CFG1_PWR_ON_RESET_MASK; + data = 0x1 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET; + mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK; + data |= 0x1 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); + + /* Wait 1ms - until band gap and ref clock ready */ + mdelay(1); + + /* Start comphy Configuration */ + debug("stage: Comphy configuration\n"); + /* Set PIPE soft reset */ + mask = HPIPE_RST_CLK_CTRL_PIPE_RST_MASK; + data = 0x1 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET; + /* Set PHY datapath width mode for V0 */ + mask |= HPIPE_RST_CLK_CTRL_FIXED_PCLK_MASK; + data |= 0x0 << HPIPE_RST_CLK_CTRL_FIXED_PCLK_OFFSET; + /* Set Data bus width USB mode for V0 */ + mask |= HPIPE_RST_CLK_CTRL_PIPE_WIDTH_MASK; + data |= 0x0 << HPIPE_RST_CLK_CTRL_PIPE_WIDTH_OFFSET; + /* Set CORE_CLK output frequency for 250Mhz */ + mask |= HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_MASK; + data |= 0x0 << HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG, data, mask); + /* Set PLL ready delay for 0x2 */ + reg_set(hpipe_addr + HPIPE_CLK_SRC_LO_REG, + 0x2 << HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET, + HPIPE_CLK_SRC_LO_PLL_RDY_DL_MASK); + /* Set reference clock to come from group 1 - 25Mhz */ + reg_set(hpipe_addr + HPIPE_MISC_REG, + 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET, + HPIPE_MISC_REFCLK_SEL_MASK); + /* Set reference frequcency select - 0x2 */ + mask = HPIPE_PWR_PLL_REF_FREQ_MASK; + data = 0x2 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; + /* Set PHY mode to USB - 0x5 */ + mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; + data |= 0x5 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); + /* Set the amount of time spent in the LoZ state - set for 0x7 */ + reg_set(hpipe_addr + HPIPE_GLOBAL_PM_CTRL, + 0x7 << HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET, + HPIPE_GLOBAL_PM_RXDLOZ_WAIT_MASK); + /* Set max PHY generation setting - 5Gbps */ + reg_set(hpipe_addr + HPIPE_INTERFACE_REG, + 0x1 << HPIPE_INTERFACE_GEN_MAX_OFFSET, + HPIPE_INTERFACE_GEN_MAX_MASK); + /* Set select data width 20Bit (SEL_BITS[2:0]) */ + reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, + 0x1 << HPIPE_LOOPBACK_SEL_OFFSET, + HPIPE_LOOPBACK_SEL_MASK); + /* select de-emphasize 3.5db */ + reg_set(hpipe_addr + HPIPE_LANE_CONFIG0_REG, + 0x1 << HPIPE_LANE_CONFIG0_TXDEEMPH0_OFFSET, + HPIPE_LANE_CONFIG0_TXDEEMPH0_MASK); + /* override tx margining from the MAC */ + reg_set(hpipe_addr + HPIPE_TST_MODE_CTRL_REG, + 0x1 << HPIPE_TST_MODE_CTRL_MODE_MARGIN_OFFSET, + HPIPE_TST_MODE_CTRL_MODE_MARGIN_MASK); + + /* Start analog paramters from ETP(HW) */ + debug("stage: Analog paramters from ETP(HW)\n"); + /* Set Pin DFE_PAT_DIS -> Bit[1]: PIN_DFE_PAT_DIS = 0x0 */ + mask = HPIPE_LANE_CFG4_DFE_CTRL_MASK; + data = 0x1 << HPIPE_LANE_CFG4_DFE_CTRL_OFFSET; + /* Set Override PHY DFE control pins for 0x1 */ + mask |= HPIPE_LANE_CFG4_DFE_OVER_MASK; + data |= 0x1 << HPIPE_LANE_CFG4_DFE_OVER_OFFSET; + /* Set Spread Spectrum Clock Enable fot 0x1 */ + mask |= HPIPE_LANE_CFG4_SSC_CTRL_MASK; + data |= 0x1 << HPIPE_LANE_CFG4_SSC_CTRL_OFFSET; + reg_set(hpipe_addr + HPIPE_LANE_CFG4_REG, data, mask); + /* End of analog parameters */ + + debug("stage: Comphy power up\n"); + /* Release from PIPE soft reset */ + reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG, + 0x0 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET, + HPIPE_RST_CLK_CTRL_PIPE_RST_MASK); + + /* wait 15ms - for comphy calibration done */ + debug("stage: Check PLL\n"); + /* Read lane status */ + addr = hpipe_addr + HPIPE_LANE_STATUS1_REG; + data = HPIPE_LANE_STATUS1_PCLK_EN_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, 15000); + if (data != 0) { + debug("Read from reg = %p - value = 0x%x\n", + hpipe_addr + HPIPE_LANE_STATUS1_REG, data); + error("HPIPE_LANE_STATUS1_PCLK_EN_MASK is 0\n"); + ret = 0; + } + + debug_exit(); + return ret; +} + +static int comphy_sata_power_up(u32 lane, void __iomem *hpipe_base, + void __iomem *comphy_base, int comphy_index) +{ + u32 mask, data, i, ret = 1; + void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane); + void __iomem *sd_ip_addr = SD_ADDR(hpipe_base, lane); + void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane); + void __iomem *addr; + void __iomem *sata_base = NULL; + int sata_node = -1; /* Set to -1 in order to read the first sata node */ + + debug_enter(); + + /* + * Assumption - each CP has only one SATA controller + * Calling fdt_node_offset_by_compatible first time (with sata_node = -1 + * will return the first node always. + * In order to parse each CPs SATA node, fdt_node_offset_by_compatible + * must be called again (according to the CP id) + */ + for (i = 0; i < (comphy_index + 1); i++) + sata_node = fdt_node_offset_by_compatible( + gd->fdt_blob, sata_node, "marvell,armada-8k-ahci"); + + if (sata_node == 0) { + error("SATA node not found in FDT\n"); + return 0; + } + + sata_base = (void __iomem *)fdtdec_get_addr_size_auto_noparent( + gd->fdt_blob, sata_node, "reg", 0, NULL, true); + if (sata_base == NULL) { + error("SATA address not found in FDT\n"); + return 0; + } + + debug("SATA address found in FDT %p\n", sata_base); + + debug("stage: MAC configuration - power down comphy\n"); + /* + * MAC configuration powe down comphy use indirect address for + * vendor spesific SATA control register + */ + reg_set(sata_base + SATA3_VENDOR_ADDRESS, + SATA_CONTROL_REG << SATA3_VENDOR_ADDR_OFSSET, + SATA3_VENDOR_ADDR_MASK); + /* SATA 0 power down */ + mask = SATA3_CTRL_SATA0_PD_MASK; + data = 0x1 << SATA3_CTRL_SATA0_PD_OFFSET; + /* SATA 1 power down */ + mask |= SATA3_CTRL_SATA1_PD_MASK; + data |= 0x1 << SATA3_CTRL_SATA1_PD_OFFSET; + /* SATA SSU disable */ + mask |= SATA3_CTRL_SATA1_ENABLE_MASK; + data |= 0x0 << SATA3_CTRL_SATA1_ENABLE_OFFSET; + /* SATA port 1 disable */ + mask |= SATA3_CTRL_SATA_SSU_MASK; + data |= 0x0 << SATA3_CTRL_SATA_SSU_OFFSET; + reg_set(sata_base + SATA3_VENDOR_DATA, data, mask); + + debug("stage: RFU configurations - hard reset comphy\n"); + /* RFU configurations - hard reset comphy */ + mask = COMMON_PHY_CFG1_PWR_UP_MASK; + data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; + mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; + data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; + mask |= COMMON_PHY_CFG1_PWR_ON_RESET_MASK; + data |= 0x0 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET; + mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK; + data |= 0x0 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); + + /* Set select data width 40Bit - SATA mode only */ + reg_set(comphy_addr + COMMON_PHY_CFG6_REG, + 0x1 << COMMON_PHY_CFG6_IF_40_SEL_OFFSET, + COMMON_PHY_CFG6_IF_40_SEL_MASK); + + /* release from hard reset in SD external */ + mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + /* Wait 1ms - until band gap and ref clock ready */ + mdelay(1); + + debug("stage: Comphy configuration\n"); + /* Start comphy Configuration */ + /* Set reference clock to comes from group 1 - choose 25Mhz */ + reg_set(hpipe_addr + HPIPE_MISC_REG, + 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET, + HPIPE_MISC_REFCLK_SEL_MASK); + /* Reference frequency select set 1 (for SATA = 25Mhz) */ + mask = HPIPE_PWR_PLL_REF_FREQ_MASK; + data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; + /* PHY mode select (set SATA = 0x0 */ + mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; + data |= 0x0 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); + /* Set max PHY generation setting - 6Gbps */ + reg_set(hpipe_addr + HPIPE_INTERFACE_REG, + 0x2 << HPIPE_INTERFACE_GEN_MAX_OFFSET, + HPIPE_INTERFACE_GEN_MAX_MASK); + /* Set select data width 40Bit (SEL_BITS[2:0]) */ + reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, + 0x2 << HPIPE_LOOPBACK_SEL_OFFSET, HPIPE_LOOPBACK_SEL_MASK); + + debug("stage: Analog paramters from ETP(HW)\n"); + /* + * TODO: Set analog paramters from ETP(HW) - for now use the + * default datas + */ + + /* DFE reset sequence */ + reg_set(hpipe_addr + HPIPE_PWR_CTR_REG, + 0x1 << HPIPE_PWR_CTR_RST_DFE_OFFSET, + HPIPE_PWR_CTR_RST_DFE_MASK); + reg_set(hpipe_addr + HPIPE_PWR_CTR_REG, + 0x0 << HPIPE_PWR_CTR_RST_DFE_OFFSET, + HPIPE_PWR_CTR_RST_DFE_MASK); + /* SW reset for interupt logic */ + reg_set(hpipe_addr + HPIPE_PWR_CTR_REG, + 0x1 << HPIPE_PWR_CTR_SFT_RST_OFFSET, + HPIPE_PWR_CTR_SFT_RST_MASK); + reg_set(hpipe_addr + HPIPE_PWR_CTR_REG, + 0x0 << HPIPE_PWR_CTR_SFT_RST_OFFSET, + HPIPE_PWR_CTR_SFT_RST_MASK); + + debug("stage: Comphy power up\n"); + /* + * MAC configuration power up comphy - power up PLL/TX/RX + * use indirect address for vendor spesific SATA control register + */ + reg_set(sata_base + SATA3_VENDOR_ADDRESS, + SATA_CONTROL_REG << SATA3_VENDOR_ADDR_OFSSET, + SATA3_VENDOR_ADDR_MASK); + /* SATA 0 power up */ + mask = SATA3_CTRL_SATA0_PD_MASK; + data = 0x0 << SATA3_CTRL_SATA0_PD_OFFSET; + /* SATA 1 power up */ + mask |= SATA3_CTRL_SATA1_PD_MASK; + data |= 0x0 << SATA3_CTRL_SATA1_PD_OFFSET; + /* SATA SSU enable */ + mask |= SATA3_CTRL_SATA1_ENABLE_MASK; + data |= 0x1 << SATA3_CTRL_SATA1_ENABLE_OFFSET; + /* SATA port 1 enable */ + mask |= SATA3_CTRL_SATA_SSU_MASK; + data |= 0x1 << SATA3_CTRL_SATA_SSU_OFFSET; + reg_set(sata_base + SATA3_VENDOR_DATA, data, mask); + + /* MBUS request size and interface select register */ + reg_set(sata_base + SATA3_VENDOR_ADDRESS, + SATA_MBUS_SIZE_SELECT_REG << SATA3_VENDOR_ADDR_OFSSET, + SATA3_VENDOR_ADDR_MASK); + /* Mbus regret enable */ + reg_set(sata_base + SATA3_VENDOR_DATA, + 0x1 << SATA_MBUS_REGRET_EN_OFFSET, SATA_MBUS_REGRET_EN_MASK); + + debug("stage: Check PLL\n"); + + addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; + data = SD_EXTERNAL_STATUS0_PLL_TX_MASK & + SD_EXTERNAL_STATUS0_PLL_RX_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, 15000); + if (data != 0) { + debug("Read from reg = %p - value = 0x%x\n", + hpipe_addr + HPIPE_LANE_STATUS1_REG, data); + error("SD_EXTERNAL_STATUS0_PLL_TX is %d, SD_EXTERNAL_STATUS0_PLL_RX is %d\n", + (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK), + (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK)); + ret = 0; + } + + debug_exit(); + return ret; +} + +static int comphy_sgmii_power_up(u32 lane, u32 sgmii_speed, + void __iomem *hpipe_base, + void __iomem *comphy_base) +{ + u32 mask, data, ret = 1; + void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane); + void __iomem *sd_ip_addr = SD_ADDR(hpipe_base, lane); + void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane); + void __iomem *addr; + + debug_enter(); + debug("stage: RFU configurations - hard reset comphy\n"); + /* RFU configurations - hard reset comphy */ + mask = COMMON_PHY_CFG1_PWR_UP_MASK; + data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; + mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; + data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); + + /* Select Baud Rate of Comphy And PD_PLL/Tx/Rx */ + mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK; + mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK; + if (sgmii_speed == PHY_SPEED_1_25G) { + data |= 0x6 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET; + data |= 0x6 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET; + } else { + /* 3.125G */ + data |= 0x8 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET; + data |= 0x8 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET; + } + mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; + data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; + data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK; + data |= 1 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); + + /* release from hard reset */ + mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + /* release from hard reset */ + mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + + /* Wait 1ms - until band gap and ref clock ready */ + mdelay(1); + + /* Start comphy Configuration */ + debug("stage: Comphy configuration\n"); + /* set reference clock */ + mask = HPIPE_MISC_REFCLK_SEL_MASK; + data = 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask); + /* Power and PLL Control */ + mask = HPIPE_PWR_PLL_REF_FREQ_MASK; + data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; + mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; + data |= 0x4 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); + /* Loopback register */ + mask = HPIPE_LOOPBACK_SEL_MASK; + data = 0x1 << HPIPE_LOOPBACK_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, data, mask); + /* rx control 1 */ + mask = HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK; + data = 0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET; + mask |= HPIPE_RX_CONTROL_1_CLK8T_EN_MASK; + data |= 0x0 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_RX_CONTROL_1_REG, data, mask); + /* DTL Control */ + mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK; + data = 0x0 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask); + + /* Set analog paramters from ETP(HW) - for now use the default datas */ + debug("stage: Analog paramters from ETP(HW)\n"); + + reg_set(hpipe_addr + HPIPE_G1_SET_0_REG, + 0x1 << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET, + HPIPE_G1_SET_0_G1_TX_EMPH1_MASK); + + debug("stage: RFU configurations- Power Up PLL,Tx,Rx\n"); + /* SERDES External Configuration */ + mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); + + /* check PLL rx & tx ready */ + addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; + data = SD_EXTERNAL_STATUS0_PLL_RX_MASK | + SD_EXTERNAL_STATUS0_PLL_TX_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, 15000); + if (data != 0) { + debug("Read from reg = %p - value = 0x%x\n", + sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data); + error("SD_EXTERNAL_STATUS0_PLL_RX is %d, SD_EXTERNAL_STATUS0_PLL_TX is %d\n", + (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK), + (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK)); + ret = 0; + } + + /* RX init */ + mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + /* check that RX init done */ + addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; + data = SD_EXTERNAL_STATUS0_RX_INIT_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, 100); + if (data != 0) { + debug("Read from reg = %p - value = 0x%x\n", sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data); + error("SD_EXTERNAL_STATUS0_RX_INIT is 0\n"); + ret = 0; + } + + debug("stage: RF Reset\n"); + /* RF Reset */ + mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + debug_exit(); + return ret; +} + +static int comphy_kr_power_up(u32 lane, void __iomem *hpipe_base, + void __iomem *comphy_base) +{ + u32 mask, data, ret = 1; + void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane); + void __iomem *sd_ip_addr = SD_ADDR(hpipe_base, lane); + void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane); + void __iomem *addr; + + debug_enter(); + debug("stage: RFU configurations - hard reset comphy\n"); + /* RFU configurations - hard reset comphy */ + mask = COMMON_PHY_CFG1_PWR_UP_MASK; + data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; + mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; + data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); + + /* Select Baud Rate of Comphy And PD_PLL/Tx/Rx */ + mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK; + data |= 0xE << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK; + data |= 0xE << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; + data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; + data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK; + data |= 0 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); + + /* release from hard reset */ + mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + + /* Wait 1ms - until band gap and ref clock ready */ + mdelay(1); + + /* Start comphy Configuration */ + debug("stage: Comphy configuration\n"); + /* set reference clock */ + mask = HPIPE_MISC_ICP_FORCE_MASK; + data = 0x1 << HPIPE_MISC_ICP_FORCE_OFFSET; + mask |= HPIPE_MISC_REFCLK_SEL_MASK; + data |= 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask); + /* Power and PLL Control */ + mask = HPIPE_PWR_PLL_REF_FREQ_MASK; + data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; + mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; + data |= 0x4 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); + /* Loopback register */ + mask = HPIPE_LOOPBACK_SEL_MASK; + data = 0x1 << HPIPE_LOOPBACK_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, data, mask); + /* rx control 1 */ + mask = HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK; + data = 0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET; + mask |= HPIPE_RX_CONTROL_1_CLK8T_EN_MASK; + data |= 0x1 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_RX_CONTROL_1_REG, data, mask); + /* DTL Control */ + mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK; + data = 0x1 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask); + + /* Set analog paramters from ETP(HW) */ + debug("stage: Analog paramters from ETP(HW)\n"); + /* SERDES External Configuration 2 */ + mask = SD_EXTERNAL_CONFIG2_PIN_DFE_EN_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG2_PIN_DFE_EN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG2_REG, data, mask); + /* 0x7-DFE Resolution control */ + mask = HPIPE_DFE_RES_FORCE_MASK; + data = 0x1 << HPIPE_DFE_RES_FORCE_OFFSET; + reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask); + /* 0xd-G1_Setting_0 */ + mask = HPIPE_G1_SET_0_G1_TX_AMP_MASK; + data = 0x1c << HPIPE_G1_SET_0_G1_TX_AMP_OFFSET; + mask |= HPIPE_G1_SET_0_G1_TX_EMPH1_MASK; + data |= 0xe << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SET_0_REG, data, mask); + /* Genration 1 setting 2 (G1_Setting_2) */ + mask = HPIPE_G1_SET_2_G1_TX_EMPH0_MASK; + data = 0x0 << HPIPE_G1_SET_2_G1_TX_EMPH0_OFFSET; + mask |= HPIPE_G1_SET_2_G1_TX_EMPH0_EN_MASK; + data |= 0x1 << HPIPE_G1_SET_2_G1_TX_EMPH0_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SET_2_REG, data, mask); + /* Transmitter Slew Rate Control register (tx_reg1) */ + mask = HPIPE_TX_REG1_TX_EMPH_RES_MASK; + data = 0x3 << HPIPE_TX_REG1_TX_EMPH_RES_OFFSET; + mask |= HPIPE_TX_REG1_SLC_EN_MASK; + data |= 0x3f << HPIPE_TX_REG1_SLC_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_TX_REG1_REG, data, mask); + /* Impedance Calibration Control register (cal_reg1) */ + mask = HPIPE_CAL_REG_1_EXT_TXIMP_MASK; + data = 0xe << HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET; + mask |= HPIPE_CAL_REG_1_EXT_TXIMP_EN_MASK; + data |= 0x1 << HPIPE_CAL_REG_1_EXT_TXIMP_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_CAL_REG1_REG, data, mask); + /* Generation 1 Setting 5 (g1_setting_5) */ + mask = HPIPE_G1_SETTING_5_G1_ICP_MASK; + data = 0 << HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTING_5_REG, data, mask); + /* 0xE-G1_Setting_1 */ + mask = HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK; + data = 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET; + mask |= HPIPE_G1_SET_1_G1_RX_SELMUPP_MASK; + data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPP_OFFSET; + mask |= HPIPE_G1_SET_1_G1_RX_DFE_EN_MASK; + data |= 0x1 << HPIPE_G1_SET_1_G1_RX_DFE_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SET_1_REG, data, mask); + /* 0xA-DFE_Reg3 */ + mask = HPIPE_DFE_F3_F5_DFE_EN_MASK; + data = 0x0 << HPIPE_DFE_F3_F5_DFE_EN_OFFSET; + mask |= HPIPE_DFE_F3_F5_DFE_CTRL_MASK; + data |= 0x0 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET; + reg_set(hpipe_addr + HPIPE_DFE_F3_F5_REG, data, mask); + + /* 0x111-G1_Setting_4 */ + mask = HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK; + data = 0x1 << HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTINGS_4_REG, data, mask); + /* Genration 1 setting 3 (G1_Setting_3) */ + mask = HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_MASK; + data = 0x1 << HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask); + + debug("stage: RFU configurations- Power Up PLL,Tx,Rx\n"); + /* SERDES External Configuration */ + mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); + + + /* check PLL rx & tx ready */ + addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; + data = SD_EXTERNAL_STATUS0_PLL_RX_MASK | + SD_EXTERNAL_STATUS0_PLL_TX_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, 15000); + if (data != 0) { + debug("Read from reg = %p - value = 0x%x\n", sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data); + error("SD_EXTERNAL_STATUS0_PLL_RX is %d, SD_EXTERNAL_STATUS0_PLL_TX is %d\n", + (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK), + (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK)); + ret = 0; + } + + /* RX init */ + mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + + /* check that RX init done */ + addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; + data = SD_EXTERNAL_STATUS0_RX_INIT_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, 100); + if (data != 0) { + debug("Read from reg = %p - value = 0x%x\n", + sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data); + error("SD_EXTERNAL_STATUS0_RX_INIT is 0\n"); + ret = 0; + } + + debug("stage: RF Reset\n"); + /* RF Reset */ + mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + debug_exit(); + return ret; +} + +static int comphy_rxauii_power_up(u32 lane, void __iomem *hpipe_base, + void __iomem *comphy_base) +{ + u32 mask, data, ret = 1; + void __iomem *hpipe_addr = HPIPE_ADDR(hpipe_base, lane); + void __iomem *sd_ip_addr = SD_ADDR(hpipe_base, lane); + void __iomem *comphy_addr = COMPHY_ADDR(comphy_base, lane); + void __iomem *addr; + + debug_enter(); + debug("stage: RFU configurations - hard reset comphy\n"); + /* RFU configurations - hard reset comphy */ + mask = COMMON_PHY_CFG1_PWR_UP_MASK; + data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; + mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; + data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); + + if (lane == 2) { + reg_set(comphy_base + COMMON_PHY_SD_CTRL1, + 0x1 << COMMON_PHY_SD_CTRL1_RXAUI0_OFFSET, + COMMON_PHY_SD_CTRL1_RXAUI0_MASK); + } + if (lane == 4) { + reg_set(comphy_base + COMMON_PHY_SD_CTRL1, + 0x1 << COMMON_PHY_SD_CTRL1_RXAUI1_OFFSET, + COMMON_PHY_SD_CTRL1_RXAUI1_MASK); + } + + /* Select Baud Rate of Comphy And PD_PLL/Tx/Rx */ + mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK; + data |= 0xB << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK; + data |= 0xB << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_MEDIA_MODE_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG0_MEDIA_MODE_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); + + /* release from hard reset */ + mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + /* Wait 1ms - until band gap and ref clock ready */ + mdelay(1); + + /* Start comphy Configuration */ + debug("stage: Comphy configuration\n"); + /* set reference clock */ + reg_set(hpipe_addr + HPIPE_MISC_REG, + 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET, + HPIPE_MISC_REFCLK_SEL_MASK); + /* Power and PLL Control */ + mask = HPIPE_PWR_PLL_REF_FREQ_MASK; + data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; + mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; + data |= 0x4 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); + /* Loopback register */ + reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, + 0x1 << HPIPE_LOOPBACK_SEL_OFFSET, HPIPE_LOOPBACK_SEL_MASK); + /* rx control 1 */ + mask = HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK; + data = 0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET; + mask |= HPIPE_RX_CONTROL_1_CLK8T_EN_MASK; + data |= 0x1 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_RX_CONTROL_1_REG, data, mask); + /* DTL Control */ + reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, + 0x0 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET, + HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK); + + /* Set analog paramters from ETP(HW) */ + debug("stage: Analog paramters from ETP(HW)\n"); + /* SERDES External Configuration 2 */ + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG2_REG, + 0x1 << SD_EXTERNAL_CONFIG2_PIN_DFE_EN_OFFSET, + SD_EXTERNAL_CONFIG2_PIN_DFE_EN_MASK); + /* 0x7-DFE Resolution control */ + reg_set(hpipe_addr + HPIPE_DFE_REG0, 0x1 << HPIPE_DFE_RES_FORCE_OFFSET, + HPIPE_DFE_RES_FORCE_MASK); + /* 0xd-G1_Setting_0 */ + reg_set(hpipe_addr + HPIPE_G1_SET_0_REG, + 0xd << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET, + HPIPE_G1_SET_0_G1_TX_EMPH1_MASK); + /* 0xE-G1_Setting_1 */ + mask = HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK; + data = 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET; + mask |= HPIPE_G1_SET_1_G1_RX_SELMUPP_MASK; + data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPP_OFFSET; + mask |= HPIPE_G1_SET_1_G1_RX_DFE_EN_MASK; + data |= 0x1 << HPIPE_G1_SET_1_G1_RX_DFE_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SET_1_REG, data, mask); + /* 0xA-DFE_Reg3 */ + mask = HPIPE_DFE_F3_F5_DFE_EN_MASK; + data = 0x0 << HPIPE_DFE_F3_F5_DFE_EN_OFFSET; + mask |= HPIPE_DFE_F3_F5_DFE_CTRL_MASK; + data |= 0x0 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET; + reg_set(hpipe_addr + HPIPE_DFE_F3_F5_REG, data, mask); + + /* 0x111-G1_Setting_4 */ + mask = HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK; + data = 0x1 << HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTINGS_4_REG, data, mask); + + debug("stage: RFU configurations- Power Up PLL,Tx,Rx\n"); + /* SERDES External Configuration */ + mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); + + + /* check PLL rx & tx ready */ + addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; + data = SD_EXTERNAL_STATUS0_PLL_RX_MASK | + SD_EXTERNAL_STATUS0_PLL_TX_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, 15000); + if (data != 0) { + debug("Read from reg = %p - value = 0x%x\n", + sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data); + error("SD_EXTERNAL_STATUS0_PLL_RX is %d, SD_EXTERNAL_STATUS0_PLL_TX is %d\n", + (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK), + (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK)); + ret = 0; + } + + /* RX init */ + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, + 0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET, + SD_EXTERNAL_CONFIG1_RX_INIT_MASK); + + /* check that RX init done */ + addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; + data = SD_EXTERNAL_STATUS0_RX_INIT_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, 100); + if (data != 0) { + debug("Read from reg = %p - value = 0x%x\n", + sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data); + error("SD_EXTERNAL_STATUS0_RX_INIT is 0\n"); + ret = 0; + } + + debug("stage: RF Reset\n"); + /* RF Reset */ + mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + debug_exit(); + return ret; +} + +static void comphy_utmi_power_down(u32 utmi_index, void __iomem *utmi_base_addr, + void __iomem *usb_cfg_addr, + void __iomem *utmi_cfg_addr, + u32 utmi_phy_port) +{ + u32 mask, data; + + debug_enter(); + debug("stage: UTMI %d - Power down transceiver (power down Phy), Power down PLL, and SuspendDM\n", + utmi_index); + /* Power down UTMI PHY */ + reg_set(utmi_cfg_addr, 0x0 << UTMI_PHY_CFG_PU_OFFSET, + UTMI_PHY_CFG_PU_MASK); + + /* + * If UTMI connected to USB Device, configure mux prior to PHY init + * (Device can be connected to UTMI0 or to UTMI1) + */ + if (utmi_phy_port == UTMI_PHY_TO_USB_DEVICE0) { + debug("stage: UTMI %d - Enable Device mode and configure UTMI mux\n", + utmi_index); + /* USB3 Device UTMI enable */ + mask = UTMI_USB_CFG_DEVICE_EN_MASK; + data = 0x1 << UTMI_USB_CFG_DEVICE_EN_OFFSET; + /* USB3 Device UTMI MUX */ + mask |= UTMI_USB_CFG_DEVICE_MUX_MASK; + data |= utmi_index << UTMI_USB_CFG_DEVICE_MUX_OFFSET; + reg_set(usb_cfg_addr, data, mask); + } + + /* Set Test suspendm mode */ + mask = UTMI_CTRL_STATUS0_SUSPENDM_MASK; + data = 0x1 << UTMI_CTRL_STATUS0_SUSPENDM_OFFSET; + /* Enable Test UTMI select */ + mask |= UTMI_CTRL_STATUS0_TEST_SEL_MASK; + data |= 0x1 << UTMI_CTRL_STATUS0_TEST_SEL_OFFSET; + reg_set(utmi_base_addr + UTMI_CTRL_STATUS0_REG, data, mask); + + /* Wait for UTMI power down */ + mdelay(1); + + debug_exit(); + return; +} + +static void comphy_utmi_phy_config(u32 utmi_index, void __iomem *utmi_base_addr, + void __iomem *usb_cfg_addr, + void __iomem *utmi_cfg_addr, + u32 utmi_phy_port) +{ + u32 mask, data; + + debug_exit(); + debug("stage: Configure UTMI PHY %d registers\n", utmi_index); + /* Reference Clock Divider Select */ + mask = UTMI_PLL_CTRL_REFDIV_MASK; + data = 0x5 << UTMI_PLL_CTRL_REFDIV_OFFSET; + /* Feedback Clock Divider Select - 90 for 25Mhz*/ + mask |= UTMI_PLL_CTRL_FBDIV_MASK; + data |= 0x60 << UTMI_PLL_CTRL_FBDIV_OFFSET; + /* Select LPFR - 0x0 for 25Mhz/5=5Mhz*/ + mask |= UTMI_PLL_CTRL_SEL_LPFR_MASK; + data |= 0x0 << UTMI_PLL_CTRL_SEL_LPFR_OFFSET; + reg_set(utmi_base_addr + UTMI_PLL_CTRL_REG, data, mask); + + /* Impedance Calibration Threshold Setting */ + reg_set(utmi_base_addr + UTMI_CALIB_CTRL_REG, + 0x6 << UTMI_CALIB_CTRL_IMPCAL_VTH_OFFSET, + UTMI_CALIB_CTRL_IMPCAL_VTH_MASK); + + /* Set LS TX driver strength coarse control */ + mask = UTMI_TX_CH_CTRL_DRV_EN_LS_MASK; + data = 0x3 << UTMI_TX_CH_CTRL_DRV_EN_LS_OFFSET; + /* Set LS TX driver fine adjustment */ + mask |= UTMI_TX_CH_CTRL_IMP_SEL_LS_MASK; + data |= 0x3 << UTMI_TX_CH_CTRL_IMP_SEL_LS_OFFSET; + reg_set(utmi_base_addr + UTMI_TX_CH_CTRL_REG, data, mask); + + /* Enable SQ */ + mask = UTMI_RX_CH_CTRL0_SQ_DET_MASK; + data = 0x0 << UTMI_RX_CH_CTRL0_SQ_DET_OFFSET; + /* Enable analog squelch detect */ + mask |= UTMI_RX_CH_CTRL0_SQ_ANA_DTC_MASK; + data |= 0x1 << UTMI_RX_CH_CTRL0_SQ_ANA_DTC_OFFSET; + reg_set(utmi_base_addr + UTMI_RX_CH_CTRL0_REG, data, mask); + + /* Set External squelch calibration number */ + mask = UTMI_RX_CH_CTRL1_SQ_AMP_CAL_MASK; + data = 0x1 << UTMI_RX_CH_CTRL1_SQ_AMP_CAL_OFFSET; + /* Enable the External squelch calibration */ + mask |= UTMI_RX_CH_CTRL1_SQ_AMP_CAL_EN_MASK; + data |= 0x1 << UTMI_RX_CH_CTRL1_SQ_AMP_CAL_EN_OFFSET; + reg_set(utmi_base_addr + UTMI_RX_CH_CTRL1_REG, data, mask); + + /* Set Control VDAT Reference Voltage - 0.325V */ + mask = UTMI_CHGDTC_CTRL_VDAT_MASK; + data = 0x1 << UTMI_CHGDTC_CTRL_VDAT_OFFSET; + /* Set Control VSRC Reference Voltage - 0.6V */ + mask |= UTMI_CHGDTC_CTRL_VSRC_MASK; + data |= 0x1 << UTMI_CHGDTC_CTRL_VSRC_OFFSET; + reg_set(utmi_base_addr + UTMI_CHGDTC_CTRL_REG, data, mask); + + debug_exit(); + return; +} + +static int comphy_utmi_power_up(u32 utmi_index, void __iomem *utmi_base_addr, + void __iomem *usb_cfg_addr, + void __iomem *utmi_cfg_addr, u32 utmi_phy_port) +{ + u32 data, mask, ret = 1; + void __iomem *addr; + + debug_enter(); + debug("stage: UTMI %d - Power up transceiver(Power up Phy), and exit SuspendDM\n", + utmi_index); + /* Power UP UTMI PHY */ + reg_set(utmi_cfg_addr, 0x1 << UTMI_PHY_CFG_PU_OFFSET, + UTMI_PHY_CFG_PU_MASK); + /* Disable Test UTMI select */ + reg_set(utmi_base_addr + UTMI_CTRL_STATUS0_REG, + 0x0 << UTMI_CTRL_STATUS0_TEST_SEL_OFFSET, + UTMI_CTRL_STATUS0_TEST_SEL_MASK); + + debug("stage: Polling for PLL and impedance calibration done, and PLL ready done\n"); + addr = utmi_base_addr + UTMI_CALIB_CTRL_REG; + data = UTMI_CALIB_CTRL_IMPCAL_DONE_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, 100); + if (data != 0) { + error("Impedance calibration is not done\n"); + debug("Read from reg = %p - value = 0x%x\n", addr, data); + ret = 0; + } + + data = UTMI_CALIB_CTRL_PLLCAL_DONE_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, 100); + if (data != 0) { + error("PLL calibration is not done\n"); + debug("Read from reg = %p - value = 0x%x\n", addr, data); + ret = 0; + } + + addr = utmi_base_addr + UTMI_PLL_CTRL_REG; + data = UTMI_PLL_CTRL_PLL_RDY_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, 100); + if (data != 0) { + error("PLL is not ready\n"); + debug("Read from reg = %p - value = 0x%x\n", addr, data); + ret = 0; + } + + if (ret) + debug("Passed\n"); + else + debug("\n"); + + debug_exit(); + return ret; +} + +/* + * comphy_utmi_phy_init initialize the UTMI PHY + * the init split in 3 parts: + * 1. Power down transceiver and PLL + * 2. UTMI PHY configure + * 3. Powe up transceiver and PLL + * Note: - Power down/up should be once for both UTMI PHYs + * - comphy_dedicated_phys_init call this function if at least there is + * one UTMI PHY exists in FDT blob. access to cp110_utmi_data[0] is + * legal + */ +static void comphy_utmi_phy_init(u32 utmi_phy_count, + struct utmi_phy_data *cp110_utmi_data) +{ + u32 i; + + debug_enter(); + /* UTMI Power down */ + for (i = 0; i < utmi_phy_count; i++) { + comphy_utmi_power_down(i, cp110_utmi_data[i].utmi_base_addr, + cp110_utmi_data[i].usb_cfg_addr, + cp110_utmi_data[i].utmi_cfg_addr, + cp110_utmi_data[i].utmi_phy_port); + } + /* PLL Power down */ + debug("stage: UTMI PHY power down PLL\n"); + for (i = 0; i < utmi_phy_count; i++) { + reg_set(cp110_utmi_data[i].usb_cfg_addr, + 0x0 << UTMI_USB_CFG_PLL_OFFSET, UTMI_USB_CFG_PLL_MASK); + } + /* UTMI configure */ + for (i = 0; i < utmi_phy_count; i++) { + comphy_utmi_phy_config(i, cp110_utmi_data[i].utmi_base_addr, + cp110_utmi_data[i].usb_cfg_addr, + cp110_utmi_data[i].utmi_cfg_addr, + cp110_utmi_data[i].utmi_phy_port); + } + /* UTMI Power up */ + for (i = 0; i < utmi_phy_count; i++) { + if (!comphy_utmi_power_up(i, cp110_utmi_data[i].utmi_base_addr, + cp110_utmi_data[i].usb_cfg_addr, + cp110_utmi_data[i].utmi_cfg_addr, + cp110_utmi_data[i].utmi_phy_port)) { + error("Failed to initialize UTMI PHY %d\n", i); + continue; + } + printf("UTMI PHY %d initialized to ", i); + if (cp110_utmi_data[i].utmi_phy_port == UTMI_PHY_TO_USB_DEVICE0) + printf("USB Device\n"); + else + printf("USB Host%d\n", + cp110_utmi_data[i].utmi_phy_port); + } + /* PLL Power up */ + debug("stage: UTMI PHY power up PLL\n"); + for (i = 0; i < utmi_phy_count; i++) { + reg_set(cp110_utmi_data[i].usb_cfg_addr, + 0x1 << UTMI_USB_CFG_PLL_OFFSET, UTMI_USB_CFG_PLL_MASK); + } + + debug_exit(); + return; +} + +/* + * comphy_dedicated_phys_init initialize the dedicated PHYs + * - not muxed SerDes lanes e.g. UTMI PHY + */ +void comphy_dedicated_phys_init(void) +{ + struct utmi_phy_data cp110_utmi_data[MAX_UTMI_PHY_COUNT]; + int node; + int i; + + debug_enter(); + debug("Initialize USB UTMI PHYs\n"); + + /* Find the UTMI phy node in device tree and go over them */ + node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, + "marvell,mvebu-utmi-2.6.0"); + + i = 0; + while (node > 0) { + /* get base address of UTMI phy */ + cp110_utmi_data[i].utmi_base_addr = + (void __iomem *)fdtdec_get_addr_size_auto_noparent( + gd->fdt_blob, node, "reg", 0, NULL, true); + if (cp110_utmi_data[i].utmi_base_addr == NULL) { + error("UTMI PHY base address is invalid\n"); + i++; + continue; + } + + /* get usb config address */ + cp110_utmi_data[i].usb_cfg_addr = + (void __iomem *)fdtdec_get_addr_size_auto_noparent( + gd->fdt_blob, node, "reg", 1, NULL, true); + if (cp110_utmi_data[i].usb_cfg_addr == NULL) { + error("UTMI PHY base address is invalid\n"); + i++; + continue; + } + + /* get UTMI config address */ + cp110_utmi_data[i].utmi_cfg_addr = + (void __iomem *)fdtdec_get_addr_size_auto_noparent( + gd->fdt_blob, node, "reg", 2, NULL, true); + if (cp110_utmi_data[i].utmi_cfg_addr == NULL) { + error("UTMI PHY base address is invalid\n"); + i++; + continue; + } + + /* + * get the port number (to check if the utmi connected to + * host/device) + */ + cp110_utmi_data[i].utmi_phy_port = fdtdec_get_int( + gd->fdt_blob, node, "utmi-port", UTMI_PHY_INVALID); + if (cp110_utmi_data[i].utmi_phy_port == UTMI_PHY_INVALID) { + error("UTMI PHY port type is invalid\n"); + i++; + continue; + } + + node = fdt_node_offset_by_compatible( + gd->fdt_blob, node, "marvell,mvebu-utmi-2.6.0"); + i++; + } + + if (i > 0) + comphy_utmi_phy_init(i, cp110_utmi_data); + + debug_exit(); +} + +static void comphy_mux_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg, + struct comphy_map *serdes_map) +{ + void __iomem *comphy_base_addr; + struct comphy_map comphy_map_pipe_data[MAX_LANE_OPTIONS]; + struct comphy_map comphy_map_phy_data[MAX_LANE_OPTIONS]; + u32 lane, comphy_max_count; + + comphy_max_count = ptr_chip_cfg->comphy_lanes_count; + comphy_base_addr = ptr_chip_cfg->comphy_base_addr; + + /* + * Copy the SerDes map configuration for PIPE map and PHY map + * the comphy_mux_init modify the type of the lane if the type + * is not valid because we have 2 selectores run the + * comphy_mux_init twice and after that update the original + * serdes_map + */ + for (lane = 0; lane < comphy_max_count; lane++) { + comphy_map_pipe_data[lane].type = serdes_map[lane].type; + comphy_map_pipe_data[lane].speed = serdes_map[lane].speed; + comphy_map_phy_data[lane].type = serdes_map[lane].type; + comphy_map_phy_data[lane].speed = serdes_map[lane].speed; + } + ptr_chip_cfg->mux_data = cp110_comphy_phy_mux_data; + comphy_mux_init(ptr_chip_cfg, comphy_map_phy_data, + comphy_base_addr + COMMON_SELECTOR_PHY_OFFSET); + + ptr_chip_cfg->mux_data = cp110_comphy_pipe_mux_data; + comphy_mux_init(ptr_chip_cfg, comphy_map_pipe_data, + comphy_base_addr + COMMON_SELECTOR_PIPE_OFFSET); + /* Fix the type after check the PHY and PIPE configuration */ + for (lane = 0; lane < comphy_max_count; lane++) { + if ((comphy_map_pipe_data[lane].type == PHY_TYPE_UNCONNECTED) && + (comphy_map_phy_data[lane].type == PHY_TYPE_UNCONNECTED)) + serdes_map[lane].type = PHY_TYPE_UNCONNECTED; + } +} + +int comphy_cp110_init(struct chip_serdes_phy_config *ptr_chip_cfg, + struct comphy_map *serdes_map) +{ + struct comphy_map *ptr_comphy_map; + void __iomem *comphy_base_addr, *hpipe_base_addr; + u32 comphy_max_count, lane, ret = 0; + u32 pcie_width = 0; + + debug_enter(); + + comphy_max_count = ptr_chip_cfg->comphy_lanes_count; + comphy_base_addr = ptr_chip_cfg->comphy_base_addr; + hpipe_base_addr = ptr_chip_cfg->hpipe3_base_addr; + + /* Config Comphy mux configuration */ + comphy_mux_cp110_init(ptr_chip_cfg, serdes_map); + + /* Check if the first 4 lanes configured as By-4 */ + for (lane = 0, ptr_comphy_map = serdes_map; lane < 4; + lane++, ptr_comphy_map++) { + if (ptr_comphy_map->type != PHY_TYPE_PEX0) + break; + pcie_width++; + } + + for (lane = 0, ptr_comphy_map = serdes_map; lane < comphy_max_count; + lane++, ptr_comphy_map++) { + debug("Initialize serdes number %d\n", lane); + debug("Serdes type = 0x%x\n", ptr_comphy_map->type); + if (lane == 4) { + /* + * PCIe lanes above the first 4 lanes, can be only + * by1 + */ + pcie_width = 1; + } + switch (ptr_comphy_map->type) { + case PHY_TYPE_UNCONNECTED: + continue; + break; + case PHY_TYPE_PEX0: + case PHY_TYPE_PEX1: + case PHY_TYPE_PEX2: + case PHY_TYPE_PEX3: + ret = comphy_pcie_power_up( + lane, pcie_width, ptr_comphy_map->clk_src, + hpipe_base_addr, comphy_base_addr); + break; + case PHY_TYPE_SATA0: + case PHY_TYPE_SATA1: + case PHY_TYPE_SATA2: + case PHY_TYPE_SATA3: + ret = comphy_sata_power_up( + lane, hpipe_base_addr, comphy_base_addr, + ptr_chip_cfg->comphy_index); + break; + case PHY_TYPE_USB3_HOST0: + case PHY_TYPE_USB3_HOST1: + case PHY_TYPE_USB3_DEVICE: + ret = comphy_usb3_power_up(lane, hpipe_base_addr, + comphy_base_addr); + break; + case PHY_TYPE_SGMII0: + case PHY_TYPE_SGMII1: + case PHY_TYPE_SGMII2: + case PHY_TYPE_SGMII3: + if (ptr_comphy_map->speed == PHY_SPEED_INVALID) { + debug("Warning: SGMII PHY speed in lane %d is invalid, set PHY speed to 1.25G\n", + lane); + ptr_comphy_map->speed = PHY_SPEED_1_25G; + } + ret = comphy_sgmii_power_up( + lane, ptr_comphy_map->speed, hpipe_base_addr, + comphy_base_addr); + break; + case PHY_TYPE_KR: + ret = comphy_kr_power_up(lane, hpipe_base_addr, + comphy_base_addr); + break; + case PHY_TYPE_RXAUI0: + case PHY_TYPE_RXAUI1: + ret = comphy_rxauii_power_up(lane, hpipe_base_addr, + comphy_base_addr); + break; + default: + debug("Unknown SerDes type, skip initialize SerDes %d\n", + lane); + break; + } + if (ret == 0) { + /* + * If interface wans't initialiuzed, set the lane to + * PHY_TYPE_UNCONNECTED state. + */ + ptr_comphy_map->type = PHY_TYPE_UNCONNECTED; + error("PLL is not locked - Failed to initialize lane %d\n", + lane); + } + } + + debug_exit(); + return 0; +} diff --git a/drivers/phy/marvell/comphy_hpipe.h b/drivers/phy/marvell/comphy_hpipe.h index 0c9b500..179e910 100644 --- a/drivers/phy/marvell/comphy_hpipe.h +++ b/drivers/phy/marvell/comphy_hpipe.h @@ -78,6 +78,14 @@ #define HPIPE_KVCO_CALIB_CTRL_MAX_PLL_MASK \ (0x1 << HPIPE_KVCO_CALIB_CTRL_MAX_PLL_OFFSET) +#define HPIPE_CAL_REG1_REG 0xc +#define HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET 10 +#define HPIPE_CAL_REG_1_EXT_TXIMP_MASK \ + (0x1f << HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET) +#define HPIPE_CAL_REG_1_EXT_TXIMP_EN_OFFSET 15 +#define HPIPE_CAL_REG_1_EXT_TXIMP_EN_MASK \ + (0x1 << HPIPE_CAL_REG_1_EXT_TXIMP_EN_OFFSET) + #define HPIPE_SQUELCH_FFE_SETTING_REG 0x018 #define HPIPE_DFE_REG0 0x01C @@ -94,6 +102,9 @@ (0x1 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET) #define HPIPE_G1_SET_0_REG 0x034 +#define HPIPE_G1_SET_0_G1_TX_AMP_OFFSET 1 +#define HPIPE_G1_SET_0_G1_TX_AMP_MASK \ + (0x1f << HPIPE_G1_SET_0_G1_TX_AMP_OFFSET) #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) @@ -145,6 +156,14 @@ #define HPIPE_ISOLATE_MODE_GEN_TX_MASK \ (0xf << HPIPE_ISOLATE_MODE_GEN_TX_OFFSET) +#define HPIPE_G1_SET_2_REG 0xf4 +#define HPIPE_G1_SET_2_G1_TX_EMPH0_OFFSET 0 +#define HPIPE_G1_SET_2_G1_TX_EMPH0_MASK \ + (0xf << HPIPE_G1_SET_2_G1_TX_EMPH0_OFFSET) +#define HPIPE_G1_SET_2_G1_TX_EMPH0_EN_OFFSET 4 +#define HPIPE_G1_SET_2_G1_TX_EMPH0_EN_MASK \ + (0x1 << HPIPE_G1_SET_2_G1_TX_EMPH0_MASK) + #define HPIPE_VTHIMPCAL_CTRL_REG 0x104 #define HPIPE_PCIE_REG0 0x120 @@ -164,6 +183,9 @@ #define HPIPE_MISC_CLK100M_125M_OFFSET 4 #define HPIPE_MISC_CLK100M_125M_MASK \ (0x1 << HPIPE_MISC_CLK100M_125M_OFFSET) +#define HPIPE_MISC_ICP_FORCE_OFFSET 5 +#define HPIPE_MISC_ICP_FORCE_MASK \ + (0x1 << HPIPE_MISC_ICP_FORCE_OFFSET) #define HPIPE_MISC_TXDCLK_2X_OFFSET 6 #define HPIPE_MISC_TXDCLK_2X_MASK \ (0x1 << HPIPE_MISC_TXDCLK_2X_OFFSET) @@ -197,6 +219,14 @@ #define HPIPE_SMAPLER_MASK \ (0x1 << HPIPE_SMAPLER_OFFSET) +#define HPIPE_TX_REG1_REG 0x174 +#define HPIPE_TX_REG1_TX_EMPH_RES_OFFSET 5 +#define HPIPE_TX_REG1_TX_EMPH_RES_MASK \ + (0x3 << HPIPE_TX_REG1_TX_EMPH_RES_OFFSET) +#define HPIPE_TX_REG1_SLC_EN_OFFSET 10 +#define HPIPE_TX_REG1_SLC_EN_MASK \ + (0x3f << HPIPE_TX_REG1_SLC_EN_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 \ @@ -262,6 +292,9 @@ (0x1 << HPIPE_TX_SWEEP_PRESET_EN_OFFSET) #define HPIPE_G1_SETTINGS_3_REG 0x440 +#define HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_OFFSET 9 +#define HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_MASK \ + (0x1 << HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_OFFSET) #define HPIPE_G1_SETTINGS_4_REG 0x444 #define HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET 8 @@ -289,6 +322,11 @@ #define HPIPE_DFE_CTRL_28_PIPE4_MASK \ (0x1 << HPIPE_DFE_CTRL_28_PIPE4_OFFSET) +#define HPIPE_G1_SETTING_5_REG 0x538 +#define HPIPE_G1_SETTING_5_G1_ICP_OFFSET 0 +#define HPIPE_G1_SETTING_5_G1_ICP_MASK \ + (0xf << HPIPE_G1_SETTING_5_G1_ICP_OFFSET) + #define HPIPE_LANE_CONFIG0_REG 0x600 #define HPIPE_LANE_CONFIG0_TXDEEMPH0_OFFSET 0 #define HPIPE_LANE_CONFIG0_TXDEEMPH0_MASK \ diff --git a/drivers/phy/marvell/sata.h b/drivers/phy/marvell/sata.h new file mode 100644 index 0000000..be2ba54 --- /dev/null +++ b/drivers/phy/marvell/sata.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2015-2016 Marvell International Ltd. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _SATA_H_ +#define _SATA_H_ + +/* SATA3 Unit address */ +#define SATA3_VENDOR_ADDRESS 0xA0 +#define SATA3_VENDOR_ADDR_OFSSET 0 +#define SATA3_VENDOR_ADDR_MASK (0xFFFFFFFF << SATA3_VENDOR_ADDR_OFSSET) +#define SATA3_VENDOR_DATA 0xA4 + +#define SATA_CONTROL_REG 0x0 +#define SATA3_CTRL_SATA0_PD_OFFSET 6 +#define SATA3_CTRL_SATA0_PD_MASK (1 << SATA3_CTRL_SATA0_PD_OFFSET) +#define SATA3_CTRL_SATA1_PD_OFFSET 14 +#define SATA3_CTRL_SATA1_PD_MASK (1 << SATA3_CTRL_SATA1_PD_OFFSET) +#define SATA3_CTRL_SATA1_ENABLE_OFFSET 22 +#define SATA3_CTRL_SATA1_ENABLE_MASK (1 << SATA3_CTRL_SATA1_ENABLE_OFFSET) +#define SATA3_CTRL_SATA_SSU_OFFSET 23 +#define SATA3_CTRL_SATA_SSU_MASK (1 << SATA3_CTRL_SATA_SSU_OFFSET) + +#define SATA_MBUS_SIZE_SELECT_REG 0x4 +#define SATA_MBUS_REGRET_EN_OFFSET 7 +#define SATA_MBUS_REGRET_EN_MASK (0x1 << SATA_MBUS_REGRET_EN_OFFSET) + +#endif /* _SATA_H_ */ diff --git a/drivers/phy/marvell/utmi_phy.h b/drivers/phy/marvell/utmi_phy.h new file mode 100644 index 0000000..01e53ba --- /dev/null +++ b/drivers/phy/marvell/utmi_phy.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2015-2016 Marvell International Ltd. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _UTMI_PHY_H_ +#define _UTMI_PHY_H_ + +#define UTMI_USB_CFG_DEVICE_EN_OFFSET 0 +#define UTMI_USB_CFG_DEVICE_EN_MASK \ + (0x1 << UTMI_USB_CFG_DEVICE_EN_OFFSET) +#define UTMI_USB_CFG_DEVICE_MUX_OFFSET 1 +#define UTMI_USB_CFG_DEVICE_MUX_MASK \ + (0x1 << UTMI_USB_CFG_DEVICE_MUX_OFFSET) +#define UTMI_USB_CFG_PLL_OFFSET 25 +#define UTMI_USB_CFG_PLL_MASK \ + (0x1 << UTMI_USB_CFG_PLL_OFFSET) + +#define UTMI_PHY_CFG_PU_OFFSET 5 +#define UTMI_PHY_CFG_PU_MASK \ + (0x1 << UTMI_PHY_CFG_PU_OFFSET) + +#define UTMI_PLL_CTRL_REG 0x0 +#define UTMI_PLL_CTRL_REFDIV_OFFSET 0 +#define UTMI_PLL_CTRL_REFDIV_MASK \ + (0x7f << UTMI_PLL_CTRL_REFDIV_OFFSET) +#define UTMI_PLL_CTRL_FBDIV_OFFSET 16 +#define UTMI_PLL_CTRL_FBDIV_MASK \ + (0x1FF << UTMI_PLL_CTRL_FBDIV_OFFSET) +#define UTMI_PLL_CTRL_SEL_LPFR_OFFSET 28 +#define UTMI_PLL_CTRL_SEL_LPFR_MASK \ + (0x3 << UTMI_PLL_CTRL_SEL_LPFR_OFFSET) +#define UTMI_PLL_CTRL_PLL_RDY_OFFSET 31 +#define UTMI_PLL_CTRL_PLL_RDY_MASK \ + (0x1 << UTMI_PLL_CTRL_PLL_RDY_OFFSET) + +#define UTMI_CALIB_CTRL_REG 0x8 +#define UTMI_CALIB_CTRL_IMPCAL_VTH_OFFSET 8 +#define UTMI_CALIB_CTRL_IMPCAL_VTH_MASK \ + (0x7 << UTMI_CALIB_CTRL_IMPCAL_VTH_OFFSET) +#define UTMI_CALIB_CTRL_IMPCAL_DONE_OFFSET 23 +#define UTMI_CALIB_CTRL_IMPCAL_DONE_MASK \ + (0x1 << UTMI_CALIB_CTRL_IMPCAL_DONE_OFFSET) +#define UTMI_CALIB_CTRL_PLLCAL_DONE_OFFSET 31 +#define UTMI_CALIB_CTRL_PLLCAL_DONE_MASK \ + (0x1 << UTMI_CALIB_CTRL_PLLCAL_DONE_OFFSET) + +#define UTMI_TX_CH_CTRL_REG 0xC +#define UTMI_TX_CH_CTRL_DRV_EN_LS_OFFSET 12 +#define UTMI_TX_CH_CTRL_DRV_EN_LS_MASK \ + (0xf << UTMI_TX_CH_CTRL_DRV_EN_LS_OFFSET) +#define UTMI_TX_CH_CTRL_IMP_SEL_LS_OFFSET 16 +#define UTMI_TX_CH_CTRL_IMP_SEL_LS_MASK \ + (0xf << UTMI_TX_CH_CTRL_IMP_SEL_LS_OFFSET) + +#define UTMI_RX_CH_CTRL0_REG 0x14 +#define UTMI_RX_CH_CTRL0_SQ_DET_OFFSET 15 +#define UTMI_RX_CH_CTRL0_SQ_DET_MASK \ + (0x1 << UTMI_RX_CH_CTRL0_SQ_DET_OFFSET) +#define UTMI_RX_CH_CTRL0_SQ_ANA_DTC_OFFSET 28 +#define UTMI_RX_CH_CTRL0_SQ_ANA_DTC_MASK \ + (0x1 << UTMI_RX_CH_CTRL0_SQ_ANA_DTC_OFFSET) + +#define UTMI_RX_CH_CTRL1_REG 0x18 +#define UTMI_RX_CH_CTRL1_SQ_AMP_CAL_OFFSET 0 +#define UTMI_RX_CH_CTRL1_SQ_AMP_CAL_MASK \ + (0x3 << UTMI_RX_CH_CTRL1_SQ_AMP_CAL_OFFSET) +#define UTMI_RX_CH_CTRL1_SQ_AMP_CAL_EN_OFFSET 3 +#define UTMI_RX_CH_CTRL1_SQ_AMP_CAL_EN_MASK \ + (0x1 << UTMI_RX_CH_CTRL1_SQ_AMP_CAL_EN_OFFSET) + +#define UTMI_CTRL_STATUS0_REG 0x24 +#define UTMI_CTRL_STATUS0_SUSPENDM_OFFSET 22 +#define UTMI_CTRL_STATUS0_SUSPENDM_MASK \ + (0x1 << UTMI_CTRL_STATUS0_SUSPENDM_OFFSET) +#define UTMI_CTRL_STATUS0_TEST_SEL_OFFSET 25 +#define UTMI_CTRL_STATUS0_TEST_SEL_MASK \ + (0x1 << UTMI_CTRL_STATUS0_TEST_SEL_OFFSET) + +#define UTMI_CHGDTC_CTRL_REG 0x38 +#define UTMI_CHGDTC_CTRL_VDAT_OFFSET 8 +#define UTMI_CHGDTC_CTRL_VDAT_MASK \ + (0x3 << UTMI_CHGDTC_CTRL_VDAT_OFFSET) +#define UTMI_CHGDTC_CTRL_VSRC_OFFSET 10 +#define UTMI_CHGDTC_CTRL_VSRC_MASK \ + (0x3 << UTMI_CHGDTC_CTRL_VSRC_OFFSET) + +#endif /* _UTMI_PHY_H_ */ + -- cgit v0.10.2 From d36277ef4f5b297e5d404d1ad19123b02dc539d1 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Wed, 31 Aug 2016 06:48:56 +0200 Subject: usb: xhci-mvebu: Add Armada 8K to compatiblity list To enable this driver on Armada 7K/8K this patch adds the compatibility property to the list. Signed-off-by: Stefan Roese Cc: Nadav Haklai Cc: Neta Zur Hershkovits Cc: Kostya Porotchkin Cc: Omri Itach Cc: Igal Liberman Cc: Haim Boot Cc: Hanna Hawa diff --git a/drivers/usb/host/xhci-mvebu.c b/drivers/usb/host/xhci-mvebu.c index e09e87a..23c241a 100644 --- a/drivers/usb/host/xhci-mvebu.c +++ b/drivers/usb/host/xhci-mvebu.c @@ -79,6 +79,7 @@ static int xhci_usb_ofdata_to_platdata(struct udevice *dev) static const struct udevice_id xhci_usb_ids[] = { { .compatible = "marvell,armada3700-xhci" }, + { .compatible = "marvell,armada-8k-xhci" }, { } }; -- cgit v0.10.2 From 22f5de6b5cf381acf63b49655cb3d7cb5bf684ab Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Wed, 31 Aug 2016 10:02:15 +0200 Subject: ahci: Make ahci_port_base() non-static to enable overwrite To allow a board- / platform-specific ahci_port_base() function, this patch removes "static inline" and adds __weak to this function. This will be used by the upcoming Armada 7K/8K SATA / AHCI support, which unfortunately needs a different port base address calculation. Signed-off-by: Stefan Roese Cc: Nadav Haklai Cc: Neta Zur Hershkovits Cc: Kostya Porotchkin Cc: Omri Itach Cc: Igal Liberman Cc: Haim Boot Cc: Hanna Hawa diff --git a/drivers/block/ahci.c b/drivers/block/ahci.c index 2e1ddf9..5139989 100644 --- a/drivers/block/ahci.c +++ b/drivers/block/ahci.c @@ -45,7 +45,7 @@ u16 *ataid[AHCI_MAX_PORTS]; #define WAIT_MS_FLUSH 5000 #define WAIT_MS_LINKUP 200 -static inline void __iomem *ahci_port_base(void __iomem *base, u32 port) +__weak void __iomem *ahci_port_base(void __iomem *base, u32 port) { return base + 0x100 + (port * 0x80); } -- cgit v0.10.2 From 1335483a69c0a75445e7daa6771bc3d98af4d986 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Wed, 25 May 2016 08:23:31 +0200 Subject: arm64: mvebu: Armada 7K/8K: Add Armada 7K/8K dts files This patch integrates the Armada 7K/8K dts files from the latest submission on the linux-arm-kernel mailing list. Signed-off-by: Stefan Roese Cc: Nadav Haklai Cc: Neta Zur Hershkovits Cc: Kostya Porotchkin Cc: Omri Itach Cc: Igal Liberman Cc: Haim Boot Cc: Hanna Hawa diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index e2de5e4..032c5ae 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -72,6 +72,7 @@ dtb-$(CONFIG_ARCH_MVEBU) += \ armada-388-clearfog.dtb \ armada-388-gp.dtb \ armada-385-amc.dtb \ + armada-7040-db.dtb \ armada-xp-gp.dtb \ armada-xp-maxbcm.dtb \ armada-xp-synology-ds414.dtb \ diff --git a/arch/arm/dts/armada-7040-db.dts b/arch/arm/dts/armada-7040-db.dts new file mode 100644 index 0000000..070b589 --- /dev/null +++ b/arch/arm/dts/armada-7040-db.dts @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2016 Marvell Technology Group Ltd. + * + * This file is dual-licensed: you can use it either under the terms + * of the GPLv2 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 library 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 library 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 "AS IS", 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. + */ + +/* + * Device Tree file for Marvell Armada 7040 Development board platform + */ + +#include "armada-7040.dtsi" + +/ { + model = "Marvell Armada 7040 DB board"; + compatible = "marvell,armada7040-db", "marvell,armada7040", + "marvell,armada-ap806-quad", "marvell,armada-ap806"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@00000000 { + device_type = "memory"; + reg = <0x0 0x0 0x0 0x80000000>; + }; +}; + +&i2c0 { + status = "okay"; + clock-frequency = <100000>; +}; + +&spi0 { + status = "okay"; + + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <10000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "U-Boot"; + reg = <0 0x200000>; + }; + partition@400000 { + label = "Filesystem"; + reg = <0x200000 0xce0000>; + }; + }; + }; +}; + +&uart0 { + status = "okay"; +}; + + +&cpm_pcie2 { + status = "okay"; +}; + +&cpm_i2c0 { + status = "okay"; + clock-frequency = <100000>; +}; + +&cpm_spi1 { + status = "okay"; + + spi-flash@0 { + #address-cells = <0x1>; + #size-cells = <0x1>; + compatible = "jedec,spi-nor"; + reg = <0x0>; + spi-max-frequency = <20000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "U-Boot"; + reg = <0x0 0x200000>; + }; + + partition@400000 { + label = "Filesystem"; + reg = <0x200000 0xe00000>; + }; + }; + }; +}; + +&cpm_sata0 { + status = "okay"; +}; + +&cpm_usb3_0 { + status = "okay"; +}; + +&cpm_usb3_1 { + status = "okay"; +}; diff --git a/arch/arm/dts/armada-7040.dtsi b/arch/arm/dts/armada-7040.dtsi new file mode 100644 index 0000000..78d995d --- /dev/null +++ b/arch/arm/dts/armada-7040.dtsi @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2016 Marvell Technology Group Ltd. + * + * This file is dual-licensed: you can use it either under the terms + * of the GPLv2 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 library 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 library 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 "AS IS", 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. + */ + +/* + * Device Tree file for the Armada 7040 SoC, made of an AP806 Quad and + * one CP110. + */ + +#include "armada-ap806-quad.dtsi" +#include "armada-cp110-master.dtsi" + +/ { + model = "Marvell Armada 7040"; + compatible = "marvell,armada7040", "marvell,armada-ap806-quad", + "marvell,armada-ap806"; +}; diff --git a/arch/arm/dts/armada-ap806-quad.dtsi b/arch/arm/dts/armada-ap806-quad.dtsi new file mode 100644 index 0000000..ba43a43 --- /dev/null +++ b/arch/arm/dts/armada-ap806-quad.dtsi @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2016 Marvell Technology Group Ltd. + * + * This file is dual-licensed: you can use it either under the terms + * of the GPLv2 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 library 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 library 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 "AS IS", 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. + */ + +/* + * Device Tree file for Marvell Armada AP806. + */ + +#include "armada-ap806.dtsi" + +/ { + model = "Marvell Armada AP806 Quad"; + compatible = "marvell,armada-ap806-quad", "marvell,armada-ap806"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@000 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x000>; + enable-method = "psci"; + }; + cpu@001 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x001>; + enable-method = "psci"; + }; + cpu@100 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x100>; + enable-method = "psci"; + }; + cpu@101 { + device_type = "cpu"; + compatible = "arm,cortex-a72", "arm,armv8"; + reg = <0x101>; + enable-method = "psci"; + }; + }; +}; diff --git a/arch/arm/dts/armada-ap806.dtsi b/arch/arm/dts/armada-ap806.dtsi new file mode 100644 index 0000000..20d256b --- /dev/null +++ b/arch/arm/dts/armada-ap806.dtsi @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2016 Marvell Technology Group Ltd. + * + * This file is dual-licensed: you can use it either under the terms + * of the GPLv2 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 library 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 library 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 "AS IS", 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. + */ + +/* + * Device Tree file for Marvell Armada AP806. + */ + +#include + +/dts-v1/; + +/ { + model = "Marvell Armada AP806"; + compatible = "marvell,armada-ap806"; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &uart0; + serial1 = &uart1; + }; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + ap806 { + #address-cells = <2>; + #size-cells = <2>; + compatible = "simple-bus"; + interrupt-parent = <&gic>; + ranges; + + config-space { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges = <0x0 0x0 0xf0000000 0x1000000>; + + gic: interrupt-controller@210000 { + compatible = "arm,gic-400"; + #interrupt-cells = <3>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + interrupt-controller; + interrupts = ; + reg = <0x210000 0x10000>, + <0x220000 0x20000>, + <0x240000 0x20000>, + <0x260000 0x20000>; + + gic_v2m0: v2m@280000 { + compatible = "arm,gic-v2m-frame"; + msi-controller; + reg = <0x280000 0x1000>; + arm,msi-base-spi = <160>; + arm,msi-num-spis = <32>; + }; + gic_v2m1: v2m@290000 { + compatible = "arm,gic-v2m-frame"; + msi-controller; + reg = <0x290000 0x1000>; + arm,msi-base-spi = <192>; + arm,msi-num-spis = <32>; + }; + gic_v2m2: v2m@2a0000 { + compatible = "arm,gic-v2m-frame"; + msi-controller; + reg = <0x2a0000 0x1000>; + arm,msi-base-spi = <224>; + arm,msi-num-spis = <32>; + }; + gic_v2m3: v2m@2b0000 { + compatible = "arm,gic-v2m-frame"; + msi-controller; + reg = <0x2b0000 0x1000>; + arm,msi-base-spi = <256>; + arm,msi-num-spis = <32>; + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; + + odmi: odmi@300000 { + compatible = "marvell,odmi-controller"; + interrupt-controller; + msi-controller; + marvell,odmi-frames = <4>; + reg = <0x300000 0x4000>, + <0x304000 0x4000>, + <0x308000 0x4000>, + <0x30C000 0x4000>; + marvell,spi-base = <128>, <136>, <144>, <152>; + }; + + xor@400000 { + compatible = "marvell,mv-xor-v2"; + reg = <0x400000 0x1000>, + <0x410000 0x1000>; + msi-parent = <&gic_v2m0>; + dma-coherent; + }; + + xor@420000 { + compatible = "marvell,mv-xor-v2"; + reg = <0x420000 0x1000>, + <0x430000 0x1000>; + msi-parent = <&gic_v2m0>; + dma-coherent; + }; + + xor@440000 { + compatible = "marvell,mv-xor-v2"; + reg = <0x440000 0x1000>, + <0x450000 0x1000>; + msi-parent = <&gic_v2m0>; + dma-coherent; + }; + + xor@460000 { + compatible = "marvell,mv-xor-v2"; + reg = <0x460000 0x1000>, + <0x470000 0x1000>; + msi-parent = <&gic_v2m0>; + dma-coherent; + }; + + spi0: spi@510600 { + compatible = "marvell,armada-380-spi"; + reg = <0x510600 0x50>; + #address-cells = <1>; + #size-cells = <0>; + cell-index = <0>; + interrupts = ; + clocks = <&ap_syscon 3>; + status = "disabled"; + }; + + i2c0: i2c@511000 { + compatible = "marvell,mv78230-i2c"; + reg = <0x511000 0x20>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + timeout-ms = <1000>; + clocks = <&ap_syscon 3>; + status = "disabled"; + }; + + uart0: serial@512000 { + compatible = "snps,dw-apb-uart"; + reg = <0x512000 0x100>; + reg-shift = <2>; + interrupts = ; + reg-io-width = <1>; + clocks = <&ap_syscon 3>; + status = "disabled"; + }; + + uart1: serial@512100 { + compatible = "snps,dw-apb-uart"; + reg = <0x512100 0x100>; + reg-shift = <2>; + interrupts = ; + reg-io-width = <1>; + clocks = <&ap_syscon 3>; + status = "disabled"; + + }; + + ap_syscon: system-controller@6f4000 { + compatible = "marvell,ap806-system-controller", + "syscon"; + #clock-cells = <1>; + clock-output-names = "ap-cpu-cluster-0", + "ap-cpu-cluster-1", + "ap-fixed", "ap-mss"; + reg = <0x6f4000 0x1000>; + }; + }; + }; +}; diff --git a/arch/arm/dts/armada-cp110-master.dtsi b/arch/arm/dts/armada-cp110-master.dtsi new file mode 100644 index 0000000..367138b --- /dev/null +++ b/arch/arm/dts/armada-cp110-master.dtsi @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2016 Marvell Technology Group Ltd. + * + * This file is dual-licensed: you can use it either under the terms + * of the GPLv2 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 library 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 library 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 "AS IS", 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. + */ + +/* + * Device Tree file for Marvell Armada CP110 Master. + */ + +/ { + cp110-master { + #address-cells = <2>; + #size-cells = <2>; + compatible = "simple-bus"; + interrupt-parent = <&gic>; + ranges; + + config-space { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + interrupt-parent = <&gic>; + ranges = <0x0 0x0 0xf2000000 0x2000000>; + + cpm_syscon0: system-controller@440000 { + compatible = "marvell,cp110-system-controller0", + "syscon"; + reg = <0x440000 0x1000>; + #clock-cells = <2>; + core-clock-output-names = + "cpm-apll", "cpm-ppv2-core", "cpm-eip", + "cpm-core", "cpm-nand-core"; + gate-clock-output-names = + "cpm-audio", "cpm-communit", "cpm-nand", + "cpm-ppv2", "cpm-sdio", "cpm-mg-domain", + "cpm-mg-core", "cpm-xor1", "cpm-xor0", + "cpm-gop-dp", "none", "cpm-pcie_x10", + "cpm-pcie_x11", "cpm-pcie_x4", "cpm-pcie-xor", + "cpm-sata", "cpm-sata-usb", "cpm-main", + "cpm-sd-mmc", "none", "none", + "cpm-slow-io", "cpm-usb3h0", "cpm-usb3h1", + "cpm-usb3dev", "cpm-eip150", "cpm-eip197"; + }; + + cpm_sata0: sata@540000 { + compatible = "marvell,armada-8k-ahci"; + reg = <0x540000 0x30000>; + interrupts = ; + clocks = <&cpm_syscon0 1 15>; + status = "disabled"; + }; + + cpm_usb3_0: usb3@500000 { + compatible = "marvell,armada-8k-xhci", + "generic-xhci"; + reg = <0x500000 0x4000>; + dma-coherent; + interrupts = ; + clocks = <&cpm_syscon0 1 22>; + status = "disabled"; + }; + + cpm_usb3_1: usb3@510000 { + compatible = "marvell,armada-8k-xhci", + "generic-xhci"; + reg = <0x510000 0x4000>; + dma-coherent; + interrupts = ; + clocks = <&cpm_syscon0 1 23>; + status = "disabled"; + }; + + cpm_spi0: spi@700600 { + compatible = "marvell,armada-380-spi"; + reg = <0x700600 0x50>; + #address-cells = <0x1>; + #size-cells = <0x0>; + cell-index = <1>; + clocks = <&cpm_syscon0 0 3>; + status = "disabled"; + }; + + cpm_spi1: spi@700680 { + compatible = "marvell,armada-380-spi"; + reg = <0x700680 0x50>; + #address-cells = <1>; + #size-cells = <0>; + cell-index = <2>; + clocks = <&cpm_syscon0 1 21>; + status = "disabled"; + }; + + cpm_i2c0: i2c@701000 { + compatible = "marvell,mv78230-i2c"; + reg = <0x701000 0x20>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&cpm_syscon0 1 21>; + status = "disabled"; + }; + + cpm_i2c1: i2c@701100 { + compatible = "marvell,mv78230-i2c"; + reg = <0x701100 0x20>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = ; + clocks = <&cpm_syscon0 1 21>; + status = "disabled"; + }; + }; + + cpm_pcie0: pcie@f2600000 { + compatible = "marvell,armada8k-pcie", "snps,dw-pcie"; + reg = <0 0xf2600000 0 0x10000>, + <0 0xf6f00000 0 0x80000>; + reg-names = "ctrl", "config"; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + device_type = "pci"; + dma-coherent; + + bus-range = <0 0xff>; + ranges = + /* downstream I/O */ + <0x81000000 0 0xf9000000 0 0xf9000000 0 0x10000 + /* non-prefetchable memory */ + 0x82000000 0 0xf6000000 0 0xf6000000 0 0xf00000>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic 0 GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; + num-lanes = <1>; + clocks = <&cpm_syscon0 1 13>; + status = "disabled"; + }; + + cpm_pcie1: pcie@f2620000 { + compatible = "marvell,armada8k-pcie", "snps,dw-pcie"; + reg = <0 0xf2620000 0 0x10000>, + <0 0xf7f00000 0 0x80000>; + reg-names = "ctrl", "config"; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + device_type = "pci"; + dma-coherent; + + bus-range = <0 0xff>; + ranges = + /* downstream I/O */ + <0x81000000 0 0xf9010000 0 0xf9010000 0 0x10000 + /* non-prefetchable memory */ + 0x82000000 0 0xf7000000 0 0xf7000000 0 0xf00000>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic 0 GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; + + num-lanes = <1>; + clocks = <&cpm_syscon0 1 11>; + status = "disabled"; + }; + + cpm_pcie2: pcie@f2640000 { + compatible = "marvell,armada8k-pcie", "snps,dw-pcie"; + reg = <0 0xf2640000 0 0x10000>, + <0 0xf8f00000 0 0x80000>; + reg-names = "ctrl", "config"; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + device_type = "pci"; + dma-coherent; + + bus-range = <0 0xff>; + ranges = + /* downstream I/O */ + <0x81000000 0 0xf9020000 0 0xf9020000 0 0x10000 + /* non-prefetchable memory */ + 0x82000000 0 0xf8000000 0 0xf8000000 0 0xf00000>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &gic 0 GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>; + interrupts = ; + + num-lanes = <1>; + clocks = <&cpm_syscon0 1 12>; + status = "disabled"; + }; + }; +}; -- cgit v0.10.2 From 21b29fc64e9da24485d044538004d2056bda15e4 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Wed, 25 May 2016 08:13:45 +0200 Subject: arm64: mvebu: Add basic support for the Marvell Armada 7K/8K SoC Compared to the Armada 3700, the Armada 7K and 8K are much more on the high-end side: they use a dual Cortex-A72 or a quad Cortex-A72, as opposed to the Cortex-A53 for the Armada 3700. The Armada 7K and 8K also use a fairly unique architecture, internally they are composed of several components: - One AP (Application Processor), which contains the processor itself and a few core hardware blocks. The AP used in the Armada 7K and 8K is called AP806, and is available in two configurations: dual Cortex-A72 and quad Cortex-A72. - One or two CP (Communication Processor), which contain most of the I/O interfaces (SATA, PCIe, Ethernet, etc.). The 7K family chips have one CP, while the 8K family chips integrate two CPs, providing two times the number of I/O interfaces available in the CP. The CP used in the 7K and 8K is called CP110. All in all, this gives the following combinations: - Armada 7020, which is a dual Cortex-A72 with one CP - Armada 7040, which is a quad Cortex-A72 with one CP - Armada 8020, which is a dual Cortex-A72 with two CPs - Armada 8040, which is a quad Cortex-A72 with two CPs This patch adds basic support for this ARMv8 based SoC into U-Boot. Future patches will integrate other device drivers and board support, starting with the Marvell DB-88F7040 development board. Signed-off-by: Stefan Roese Cc: Nadav Haklai Cc: Neta Zur Hershkovits Cc: Kostya Porotchkin Cc: Omri Itach Cc: Igal Liberman Cc: Haim Boot Cc: Hanna Hawa diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 9ae442e..1e4830a 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -164,7 +164,7 @@ config KIRKWOOD select CPU_ARM926EJS config ARCH_MVEBU - bool "Marvell MVEBU family (Armada XP/375/38x)" + bool "Marvell MVEBU family (Armada XP/375/38x/3700/7K/8K)" select OF_CONTROL select OF_SEPARATE select DM diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index 58f2296..6717844 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -31,6 +31,11 @@ config ARMADA_3700 bool select ARM64 +# Armada 7K and 8K are very similar - use only one Kconfig symbol for both +config ARMADA_8K + bool + select ARM64 + # Armada XP/38x SoC types... config MV78230 bool @@ -49,7 +54,7 @@ config 88F6820 select ARMADA_38X choice - prompt "Marvell MVEBU (Armada XP/375/38x/3700) board select" + prompt "Armada XP/375/38x/3700/7K/8K board select" optional config TARGET_CLEARFOG diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile index 07dc16c..65e90c4 100644 --- a/arch/arm/mach-mvebu/Makefile +++ b/arch/arm/mach-mvebu/Makefile @@ -7,6 +7,9 @@ ifdef CONFIG_ARM64 obj-$(CONFIG_ARMADA_3700) += armada3700/ +obj-$(CONFIG_ARMADA_8K) += armada8k/ +obj-y += arm64-common.o +obj-y += sata.o else # CONFIG_ARM64 diff --git a/arch/arm/mach-mvebu/arm64-common.c b/arch/arm/mach-mvebu/arm64-common.c new file mode 100644 index 0000000..7055a81 --- /dev/null +++ b/arch/arm/mach-mvebu/arm64-common.c @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2016 Stefan Roese + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/* + * 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; +} + +/* 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/Makefile b/arch/arm/mach-mvebu/armada3700/Makefile index b1fac57..84c69d9 100644 --- a/arch/arm/mach-mvebu/armada3700/Makefile +++ b/arch/arm/mach-mvebu/armada3700/Makefile @@ -5,4 +5,3 @@ # 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 index 7d8f7b8..6499eec 100644 --- a/arch/arm/mach-mvebu/armada3700/cpu.c +++ b/arch/arm/mach-mvebu/armada3700/cpu.c @@ -53,16 +53,6 @@ static struct mm_region mvebu_mem_map[] = { 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) { /* @@ -89,100 +79,3 @@ u32 get_ref_clk(void) 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 deleted file mode 100644 index e0e8381..0000000 --- a/arch/arm/mach-mvebu/armada3700/sata.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2016 Stefan Roese - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include - -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/armada8k/Makefile b/arch/arm/mach-mvebu/armada8k/Makefile new file mode 100644 index 0000000..84c69d9 --- /dev/null +++ b/arch/arm/mach-mvebu/armada8k/Makefile @@ -0,0 +1,7 @@ +# +# Copyright (C) 2016 Stefan Roese +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y = cpu.o diff --git a/arch/arm/mach-mvebu/armada8k/cpu.c b/arch/arm/mach-mvebu/armada8k/cpu.c new file mode 100644 index 0000000..036430c --- /dev/null +++ b/arch/arm/mach-mvebu/armada8k/cpu.c @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2016 Stefan Roese + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/* Armada 7k/8k */ +#define MVEBU_RFU_BASE (MVEBU_REGISTER(0x6f0000)) +#define RFU_GLOBAL_SW_RST (MVEBU_RFU_BASE + 0x84) +#define RFU_SW_RESET_OFFSET 0 + +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 - AP806 region */ + .phys = 0xf0000000UL, + .virt = 0xf0000000UL, + .size = 0x01000000UL, /* 16MiB internal registers */ + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE + }, + { + /* SRAM, MMIO regions - CP110 region */ + .phys = 0xf2000000UL, + .virt = 0xf2000000UL, + .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; + +void reset_cpu(ulong ignored) +{ + u32 reg; + + reg = readl(RFU_GLOBAL_SW_RST); + reg &= ~(1 << RFU_SW_RESET_OFFSET); + writel(reg, RFU_GLOBAL_SW_RST); +} diff --git a/arch/arm/mach-mvebu/include/mach/soc.h b/arch/arm/mach-mvebu/include/mach/soc.h index 063d6cc..731fe65 100644 --- a/arch/arm/mach-mvebu/include/mach/soc.h +++ b/arch/arm/mach-mvebu/include/mach/soc.h @@ -46,6 +46,8 @@ * required for the Linux kernel. */ #define SOC_REGS_PHY_BASE 0xd0000000 +#elif defined(CONFIG_ARMADA_8K) +#define SOC_REGS_PHY_BASE 0xf0000000 #else #define SOC_REGS_PHY_BASE 0xf1000000 #endif diff --git a/arch/arm/mach-mvebu/sata.c b/arch/arm/mach-mvebu/sata.c new file mode 100644 index 0000000..140a295 --- /dev/null +++ b/arch/arm/mach-mvebu/sata.c @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2016 Stefan Roese + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/* + * Dummy implementation that can be overwritten by a board + * specific function + */ +__weak int board_ahci_enable(void) +{ + return 0; +} + +#ifdef CONFIG_ARMADA_8K +/* CP110 has different AHCI port addresses */ +void __iomem *ahci_port_base(void __iomem *base, u32 port) +{ + return base + 0x10000 + (port * 0x10000); +} +#endif + +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" }, + { .compatible = "marvell,armada-8k-ahci" }, + { } +}; + +U_BOOT_DRIVER(ahci_mvebu_drv) = { + .name = "ahci_mvebu", + .id = UCLASS_AHCI, + .of_match = mvebu_ahci_ids, + .probe = mvebu_ahci_probe, +}; -- cgit v0.10.2 From 6f8c2d49060a30cda2ea73e93ce0f882f732754f Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Wed, 25 May 2016 08:21:21 +0200 Subject: arm64: mvebu: Add Armada 7K db-88f7040 development board support This patch adds basic support for the Marvell Armada 7K DB-88F7040 development board. Supported are the following interfaces: - UART - SPI (incl. SPI NOR) - I2C - USB - SATA / AHCI Support for other interfaces will follow. Signed-off-by: Stefan Roese Cc: Nadav Haklai Cc: Neta Zur Hershkovits Cc: Kostya Porotchkin Cc: Omri Itach Cc: Igal Liberman Cc: Haim Boot Cc: Hanna Hawa diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index 6717844..6e8026b 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -77,6 +77,10 @@ config TARGET_DB_88F6820_AMC bool "Support DB-88F6820-AMC" select 88F6820 +config TARGET_MVEBU_DB_88F7040 + bool "Support DB-88F7040 Armada 7040" + select ARMADA_8K + config TARGET_DB_MV784MP_GP bool "Support db-mv784mp-gp" select MV78460 @@ -101,6 +105,7 @@ config SYS_BOARD default "db-88f6720" if TARGET_DB_88F6720 default "db-88f6820-gp" if TARGET_DB_88F6820_GP default "db-88f6820-amc" if TARGET_DB_88F6820_AMC + default "mvebu_db-88f7040" if TARGET_MVEBU_DB_88F7040 default "db-mv784mp-gp" if TARGET_DB_MV784MP_GP default "ds414" if TARGET_DS414 default "maxbcm" if TARGET_MAXBCM @@ -112,6 +117,7 @@ config SYS_CONFIG_NAME default "db-88f6720" if TARGET_DB_88F6720 default "db-88f6820-gp" if TARGET_DB_88F6820_GP default "db-88f6820-amc" if TARGET_DB_88F6820_AMC + default "mvebu_db-88f7040" if TARGET_MVEBU_DB_88F7040 default "db-mv784mp-gp" if TARGET_DB_MV784MP_GP default "ds414" if TARGET_DS414 default "maxbcm" if TARGET_MAXBCM @@ -123,6 +129,7 @@ config SYS_VENDOR default "Marvell" if TARGET_DB_88F6720 default "Marvell" if TARGET_DB_88F6820_GP default "Marvell" if TARGET_DB_88F6820_AMC + default "Marvell" if TARGET_MVEBU_DB_88F7040 default "solidrun" if TARGET_CLEARFOG default "Synology" if TARGET_DS414 diff --git a/board/Marvell/mvebu_db-88f7040/MAINTAINERS b/board/Marvell/mvebu_db-88f7040/MAINTAINERS new file mode 100644 index 0000000..820461b --- /dev/null +++ b/board/Marvell/mvebu_db-88f7040/MAINTAINERS @@ -0,0 +1,6 @@ +MVEBU_DB_88F7040 BOARD +M: Stefan Roese +S: Maintained +F: board/Marvell/mvebu_db-88f7040/ +F: include/configs/mvebu_db-88f7040.h +F: configs/mvebu_db-88f7040_defconfig diff --git a/board/Marvell/mvebu_db-88f7040/Makefile b/board/Marvell/mvebu_db-88f7040/Makefile new file mode 100644 index 0000000..ed39738 --- /dev/null +++ b/board/Marvell/mvebu_db-88f7040/Makefile @@ -0,0 +1,7 @@ +# +# Copyright (C) 2016 Stefan Roese +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y := board.o diff --git a/board/Marvell/mvebu_db-88f7040/board.c b/board/Marvell/mvebu_db-88f7040/board.c new file mode 100644 index 0000000..48bd55c --- /dev/null +++ b/board/Marvell/mvebu_db-88f7040/board.c @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2016 Stefan Roese + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/* IO expander I2C device */ +#define I2C_IO_EXP_ADDR 0x21 +#define I2C_IO_CFG_REG_0 0x6 +#define I2C_IO_DATA_OUT_REG_0 0x2 +/* VBus enable */ +#define I2C_IO_REG_0_USB_H0_OFF 0 +#define I2C_IO_REG_0_USB_H1_OFF 1 +#define I2C_IO_REG_VBUS ((1 << I2C_IO_REG_0_USB_H0_OFF) | \ + (1 << I2C_IO_REG_0_USB_H1_OFF)) +/* Current limit */ +#define I2C_IO_REG_0_USB_H0_CL 4 +#define I2C_IO_REG_0_USB_H1_CL 5 +#define I2C_IO_REG_CL ((1 << I2C_IO_REG_0_USB_H0_CL) | \ + (1 << I2C_IO_REG_0_USB_H1_CL)) + +static int usb_enabled = 0; + +/* Board specific xHCI dis-/enable code */ + +/* + * Set USB VBUS signals (via I2C IO expander/GPIO) as output and set + * output value as disabled + * + * Set USB Current Limit signals (via I2C IO expander/GPIO) as output + * and set output value as enabled + */ +int board_xhci_config(void) +{ + struct udevice *dev; + int ret; + u8 buf[8]; + + /* Configure IO exander PCA9555: 7bit address 0x21 */ + ret = i2c_get_chip_for_busnum(0, I2C_IO_EXP_ADDR, 1, &dev); + if (ret) { + printf("Cannot find PCA9555: %d\n", ret); + return 0; + } + + /* + * 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] &= ~I2C_IO_REG_VBUS; + buf[0] &= ~I2C_IO_REG_CL; + 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 output value and configure 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] &= ~I2C_IO_REG_VBUS; + buf[0] |= I2C_IO_REG_CL; + 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; +} + +int board_xhci_enable(void) +{ + struct udevice *dev; + int ret; + u8 buf[8]; + + /* + * This function enables all USB ports simultaniously, + * it only needs to get called once + */ + if (usb_enabled) + return 0; + + /* Configure IO exander PCA9555: 7bit address 0x21 */ + ret = i2c_get_chip_for_busnum(0, I2C_IO_EXP_ADDR, 1, &dev); + if (ret) { + printf("Cannot find PCA9555: %d\n", ret); + return 0; + } + + /* Read VBUS output value */ + 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; + } + + /* Enable VBUS power: Set output value of VBUS pin as enabled */ + buf[0] |= I2C_IO_REG_VBUS; + 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 */ + usb_enabled = 1; + + return 0; +} + +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; +} + +int board_late_init(void) +{ + /* Pre-configure the USB ports (overcurrent, VBus) */ + board_xhci_config(); + + return 0; +} diff --git a/configs/mvebu_db-88f7040_defconfig b/configs/mvebu_db-88f7040_defconfig new file mode 100644 index 0000000..4d68bdc --- /dev/null +++ b/configs/mvebu_db-88f7040_defconfig @@ -0,0 +1,47 @@ +CONFIG_ARM=y +CONFIG_ARCH_MVEBU=y +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_TARGET_MVEBU_DB_88F7040=y +CONFIG_DEFAULT_DEVICE_TREE="armada-7040-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_SYS_I2C_MVTWSI=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_UART_BASE=0xf0512000 +CONFIG_DEBUG_UART_CLOCK=200000000 +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_DEBUG_UART_ANNOUNCE=y +CONFIG_SYS_NS16550=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-88f7040.h b/include/configs/mvebu_db-88f7040.h new file mode 100644 index 0000000..cfb0191 --- /dev/null +++ b/include/configs/mvebu_db-88f7040.h @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2016 Stefan Roese + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _CONFIG_MVEBU_DB_88F7040_H +#define _CONFIG_MVEBU_DB_88F7040_H + +/* + * High Level Configuration Options (easy to change) + */ +#define CONFIG_SYS_TCLK 250000000 /* 250MHz */ + +#define CONFIG_DISPLAY_BOARDINFO_LATE +#define CONFIG_ARCH_EARLY_INIT_R +#define CONFIG_BOARD_LATE_INIT + +#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 } + +/* + * 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) + +/* + * SPI Flash configuration + */ +#define CONFIG_KIRKWOOD_SPI +#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 */ + +/* 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_88F7040_H */ -- cgit v0.10.2 From b5fbf5aabec0b78a4f010eddbaf91fc3ab166b56 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Wed, 25 May 2016 08:34:47 +0200 Subject: arm64: mvebu: armada-ap806.dtsi: Add clock-frequency to UART DT node The clock frequency needs to be provided in the DT. Otherwise the driver won't start in U-Boot. Signed-off-by: Stefan Roese Cc: Nadav Haklai Cc: Neta Zur Hershkovits Cc: Kostya Porotchkin Cc: Omri Itach Cc: Igal Liberman Cc: Haim Boot Cc: Hanna Hawa diff --git a/arch/arm/dts/armada-ap806.dtsi b/arch/arm/dts/armada-ap806.dtsi index 20d256b..d315b29 100644 --- a/arch/arm/dts/armada-ap806.dtsi +++ b/arch/arm/dts/armada-ap806.dtsi @@ -202,6 +202,7 @@ reg-io-width = <1>; clocks = <&ap_syscon 3>; status = "disabled"; + clock-frequency = <200000000>; }; uart1: serial@512100 { -- cgit v0.10.2 From 788068912fd9d10f8d5cc3b6e07ff6338e7a1d8c Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Wed, 25 May 2016 09:06:29 +0200 Subject: arm64: mvebu: Armada 7K/8K: Add COMPHY device tree nodes This patch adds the COMPHY device tree nodes that are still missing to the Armada 7K/8K dts files. Signed-off-by: Stefan Roese Cc: Nadav Haklai Cc: Neta Zur Hershkovits Cc: Kostya Porotchkin Cc: Omri Itach Cc: Igal Liberman Cc: Haim Boot Cc: Hanna Hawa diff --git a/arch/arm/dts/armada-7040-db.dts b/arch/arm/dts/armada-7040-db.dts index 070b589..df0c327 100644 --- a/arch/arm/dts/armada-7040-db.dts +++ b/arch/arm/dts/armada-7040-db.dts @@ -146,3 +146,43 @@ &cpm_usb3_1 { status = "okay"; }; + +&comphy_cp110 { + phy0 { + phy-type = ; + phy-speed = ; + }; + + phy1 { + phy-type = ; + phy-speed = ; + }; + + phy2 { + phy-type = ; + phy-speed = ; + }; + + phy3 { + phy-type = ; + phy-speed = ; + }; + + phy4 { + phy-type = ; + phy-speed = ; + }; + + phy5 { + phy-type = ; + phy-speed = ; + }; +}; + +&utmi0 { + status = "okay"; +}; + +&utmi1 { + status = "okay"; +}; diff --git a/arch/arm/dts/armada-cp110-master.dtsi b/arch/arm/dts/armada-cp110-master.dtsi index 367138b..7da98bf 100644 --- a/arch/arm/dts/armada-cp110-master.dtsi +++ b/arch/arm/dts/armada-cp110-master.dtsi @@ -44,6 +44,8 @@ * Device Tree file for Marvell Armada CP110 Master. */ +#include + / { cp110-master { #address-cells = <2>; @@ -146,6 +148,32 @@ clocks = <&cpm_syscon0 1 21>; status = "disabled"; }; + + comphy_cp110: comphy@441000 { + compatible = "marvell,mvebu-comphy", "marvell,comphy-cp110"; + reg = <0x441000 0x8>, + <0x120000 0x8>; + mux-bitcount = <4>; + max-lanes = <6>; + }; + + utmi0: utmi@580000 { + compatible = "marvell,mvebu-utmi-2.6.0"; + reg = <0x580000 0x1000>, /* utmi-unit */ + <0x440420 0x4>, /* usb-cfg */ + <0x440440 0x4>; /* utmi-cfg */ + utmi-port = ; + status = "disabled"; + }; + + utmi1: utmi@581000 { + compatible = "marvell,mvebu-utmi-2.6.0"; + reg = <0x581000 0x1000>, /* utmi-unit */ + <0x440420 0x4>, /* usb-cfg */ + <0x440444 0x4>; /* utmi-cfg */ + utmi-port = ; + status = "disabled"; + }; }; cpm_pcie0: pcie@f2600000 { -- cgit v0.10.2 From b28d29f784f5cc33c92e291d35eda603ea4e58e3 Mon Sep 17 00:00:00 2001 From: Stefan Roese Date: Wed, 31 Aug 2016 14:47:36 +0200 Subject: arm64: mvebu: armada-7040-db.dts: Add I2C and SPI aliases Add I2C and SPI aliases to enable usage in U-Boot. Signed-off-by: Stefan Roese Cc: Nadav Haklai Cc: Neta Zur Hershkovits Cc: Kostya Porotchkin Cc: Omri Itach Cc: Igal Liberman Cc: Haim Boot Cc: Hanna Hawa diff --git a/arch/arm/dts/armada-7040-db.dts b/arch/arm/dts/armada-7040-db.dts index df0c327..7d0059a 100644 --- a/arch/arm/dts/armada-7040-db.dts +++ b/arch/arm/dts/armada-7040-db.dts @@ -55,6 +55,11 @@ stdout-path = "serial0:115200n8"; }; + aliases { + i2c0 = &cpm_i2c0; + spi0 = &cpm_spi1; + }; + memory@00000000 { device_type = "memory"; reg = <0x0 0x0 0x0 0x80000000>; -- cgit v0.10.2