summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/dts/armada-xp-theadorable.dts21
-rw-r--r--arch/arm/include/asm/arch-mvebu/spi.h3
-rw-r--r--arch/arm/mach-mvebu/include/mach/cpu.h3
-rw-r--r--board/Marvell/db-88f6820-gp/binary.016
-rw-r--r--board/theadorable/Makefile1
-rw-r--r--board/theadorable/fpga.c179
-rw-r--r--board/theadorable/theadorable.c13
-rw-r--r--board/theadorable/theadorable.h12
-rw-r--r--configs/theadorable_debug_defconfig3
-rw-r--r--configs/theadorable_defconfig2
-rw-r--r--drivers/ddr/marvell/a38x/ddr3_init.c2
-rw-r--r--drivers/fpga/Makefile1
-rw-r--r--drivers/fpga/altera.c3
-rw-r--r--drivers/fpga/stratixv.c103
-rw-r--r--drivers/gpio/Kconfig7
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/mvebu_gpio.c119
-rw-r--r--include/altera.h20
-rw-r--r--include/configs/sheevaplug.h6
-rw-r--r--include/configs/theadorable.h5
-rw-r--r--tools/kwboot.c13
21 files changed, 507 insertions, 26 deletions
diff --git a/arch/arm/dts/armada-xp-theadorable.dts b/arch/arm/dts/armada-xp-theadorable.dts
index cf1be2a3d4..7087ccfc2f 100644
--- a/arch/arm/dts/armada-xp-theadorable.dts
+++ b/arch/arm/dts/armada-xp-theadorable.dts
@@ -69,6 +69,7 @@
aliases {
spi0 = &spi0;
+ spi1 = &spi1;
ethernet0 = &eth0;
};
@@ -137,6 +138,26 @@
reg = <0>; /* Chip select 0 */
spi-max-frequency = <27777777>;
};
+
+ fpga@1 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "spi-generic-device";
+ reg = <1>; /* Chip select 1 */
+ spi-max-frequency = <27777777>;
+ };
+ };
+
+ spi1: spi@10680 {
+ status = "okay";
+
+ fpga@2 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "spi-generic-device";
+ reg = <2>; /* Chip select 2 */
+ spi-max-frequency = <27777777>;
+ };
};
};
};
diff --git a/arch/arm/include/asm/arch-mvebu/spi.h b/arch/arm/include/asm/arch-mvebu/spi.h
index e512dcec16..526fea68e6 100644
--- a/arch/arm/include/asm/arch-mvebu/spi.h
+++ b/arch/arm/include/asm/arch-mvebu/spi.h
@@ -19,6 +19,9 @@ struct kwspi_registers {
u32 din; /* 0x1060c */
u32 irq_cause; /* 0x10610 */
u32 irq_mask; /* 0x10614 */
+ u32 timing1; /* 0x10618 */
+ u32 timing2; /* 0x1061c */
+ u32 dw_cfg; /* 0x10620 - Direct Write Configuration */
};
/* They are used to define CONFIG_SYS_KW_SPI_MPP
diff --git a/arch/arm/mach-mvebu/include/mach/cpu.h b/arch/arm/mach-mvebu/include/mach/cpu.h
index 017d55f412..dd58b4adc4 100644
--- a/arch/arm/mach-mvebu/include/mach/cpu.h
+++ b/arch/arm/mach-mvebu/include/mach/cpu.h
@@ -47,6 +47,9 @@ enum cpu_attrib {
CPU_ATTR_DRAM_CS3 = 0x07,
CPU_ATTR_NANDFLASH = 0x2f,
CPU_ATTR_SPIFLASH = 0x1e,
+ CPU_ATTR_SPI0_CS0 = 0x1e,
+ CPU_ATTR_SPI0_CS1 = 0x5e,
+ CPU_ATTR_SPI1_CS2 = 0x9a,
CPU_ATTR_BOOTROM = 0x1d,
CPU_ATTR_PCIE_IO = 0xe0,
CPU_ATTR_PCIE_MEM = 0xe8,
diff --git a/board/Marvell/db-88f6820-gp/binary.0 b/board/Marvell/db-88f6820-gp/binary.0
deleted file mode 100644
index 57a4cbf330..0000000000
--- a/board/Marvell/db-88f6820-gp/binary.0
+++ /dev/null
@@ -1,16 +0,0 @@
---------
-WARNING:
---------
-This file should contain the bin_hdr generated by the original Marvell
-U-Boot implementation. As this is currently not included in this
-U-Boot version, we have added this placeholder, so that the U-Boot
-image can be generated without errors.
-
-If you have a known to be working bin_hdr for your board, then you
-just need to replace this text file here with the binary header
-and recompile U-Boot.
-
-In a few weeks, mainline U-Boot will get support to generate the
-bin_hdr with the DDR training code itself. By implementing this code
-as SPL U-Boot. Then this file will not be needed any more and will
-get removed.
diff --git a/board/theadorable/Makefile b/board/theadorable/Makefile
index 9d5b39e696..ef5a519ada 100644
--- a/board/theadorable/Makefile
+++ b/board/theadorable/Makefile
@@ -5,3 +5,4 @@
#
obj-y := theadorable.o
+obj-y += fpga.o
diff --git a/board/theadorable/fpga.c b/board/theadorable/fpga.c
new file mode 100644
index 0000000000..6f068c38ad
--- /dev/null
+++ b/board/theadorable/fpga.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <altera.h>
+#include <errno.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/soc.h>
+#include <asm/arch-mvebu/spi.h>
+#include "theadorable.h"
+
+/*
+ * FPGA programming support
+ */
+static int fpga_pre_fn(int cookie)
+{
+ int gpio_config = COOKIE2CONFIG(cookie);
+ int gpio_done = COOKIE2DONE(cookie);
+ int ret;
+
+ debug("%s (%d): cookie=%08x gpio_config=%d gpio_done=%d\n",
+ __func__, __LINE__, cookie, gpio_config, gpio_done);
+
+ /* Configure config pin */
+ /* Set to output */
+ ret = gpio_request(gpio_config, "CONFIG");
+ if (ret < 0)
+ return ret;
+ gpio_direction_output(gpio_config, 1);
+
+ /* Configure done pin */
+ /* Set to input */
+ ret = gpio_request(gpio_done, "DONE");
+ if (ret < 0)
+ return ret;
+
+ gpio_direction_input(gpio_done);
+
+ return 0;
+}
+
+static int fpga_config_fn(int assert, int flush, int cookie)
+{
+ int gpio_config = COOKIE2CONFIG(cookie);
+
+ debug("%s (%d): cookie=%08x gpio_config=%d\n",
+ __func__, __LINE__, cookie, gpio_config);
+
+ if (assert)
+ gpio_set_value(gpio_config, 1);
+ else
+ gpio_set_value(gpio_config, 0);
+
+ return 0;
+}
+
+static int fpga_write_fn(const void *buf, size_t len, int flush, int cookie)
+{
+ int spi_bus = COOKIE2SPI_BUS(cookie);
+ int spi_dev = COOKIE2SPI_DEV(cookie);
+ struct kwspi_registers *reg;
+ u32 control_reg;
+ u32 config_reg;
+ void *dst;
+
+ /*
+ * Write data to FPGA attached to SPI bus via SPI direct write.
+ * This results in the fastest and easiest way to program the
+ * bitstream into the FPGA.
+ */
+ debug("%s (%d): cookie=%08x spi_bus=%d spi_dev=%d\n",
+ __func__, __LINE__, cookie, spi_bus, spi_dev);
+
+ if (spi_bus == 0) {
+ reg = (struct kwspi_registers *)MVEBU_REGISTER(0x10600);
+ dst = (void *)SPI_BUS0_DEV1_BASE;
+ } else {
+ reg = (struct kwspi_registers *)MVEBU_REGISTER(0x10680);
+ dst = (void *)SPI_BUS1_DEV2_BASE;
+ }
+
+ /* Configure SPI controller for direct access mode */
+ control_reg = readl(&reg->ctrl);
+ config_reg = readl(&reg->cfg);
+ writel(0x00000214, &reg->cfg); /* 27MHz clock */
+ writel(0x00000000, &reg->dw_cfg); /* don't de-asset CS */
+ writel(KWSPI_CSN_ACT, &reg->ctrl); /* activate CS */
+
+ /* Copy data to the SPI direct mapped window */
+ memcpy(dst, buf, len);
+
+ /* Restore original register values */
+ writel(control_reg, &reg->ctrl);
+ writel(config_reg, &reg->cfg);
+
+ return 0;
+}
+
+/* Returns the state of CONF_DONE Pin */
+static int fpga_done_fn(int cookie)
+{
+ int gpio_done = COOKIE2DONE(cookie);
+ unsigned long ts;
+
+ debug("%s (%d): cookie=%08x gpio_done=%d\n",
+ __func__, __LINE__, cookie, gpio_done);
+
+ ts = get_timer(0);
+ do {
+ if (gpio_get_value(gpio_done))
+ return 0;
+ } while (get_timer(ts) < 1000);
+
+ /* timeout so return error */
+ return -ENODEV;
+}
+
+static altera_board_specific_func stratixv_fns = {
+ .pre = fpga_pre_fn,
+ .config = fpga_config_fn,
+ .write = fpga_write_fn,
+ .done = fpga_done_fn,
+};
+
+static Altera_desc altera_fpga[] = {
+ {
+ /* Family */
+ Altera_StratixV,
+ /* Interface type */
+ passive_serial,
+ /* No limitation as additional data will be ignored */
+ -1,
+ /* Device function table */
+ (void *)&stratixv_fns,
+ /* Base interface address specified in driver */
+ NULL,
+ /* Cookie implementation */
+ /*
+ * In this 32bit word the following information is coded:
+ * Bit 31 ... Bit 0
+ * SPI-Bus | SPI-Dev | Config-Pin | Done-Pin
+ */
+ FPGA_COOKIE(0, 1, 26, 7)
+ },
+ {
+ /* Family */
+ Altera_StratixV,
+ /* Interface type */
+ passive_serial,
+ /* No limitation as additional data will be ignored */
+ -1,
+ /* Device function table */
+ (void *)&stratixv_fns,
+ /* Base interface address specified in driver */
+ NULL,
+ /* Cookie implementation */
+ /*
+ * In this 32bit word the following information is coded:
+ * Bit 31 ... Bit 0
+ * SPI-Bus | SPI-Dev | Config-Pin | Done-Pin
+ */
+ FPGA_COOKIE(1, 2, 29, 9)
+ },
+};
+
+/* Add device descriptor to FPGA device table */
+void board_fpga_add(void)
+{
+ int i;
+
+ fpga_init();
+ for (i = 0; i < ARRAY_SIZE(altera_fpga); i++)
+ fpga_add(fpga_altera, &altera_fpga[i]);
+}
diff --git a/board/theadorable/theadorable.c b/board/theadorable/theadorable.c
index 0e232656fc..ee88a98a24 100644
--- a/board/theadorable/theadorable.c
+++ b/board/theadorable/theadorable.c
@@ -8,9 +8,11 @@
#include <asm/io.h>
#include <asm/arch/cpu.h>
#include <asm/arch/soc.h>
+#include <linux/mbus.h>
#ifdef CONFIG_NET
#include <netdev.h>
#endif
+#include "theadorable.h"
#include "../drivers/ddr/marvell/axp/ddr3_hw_training.h"
#include "../arch/arm/mach-mvebu/serdes/axp/high_speed_env_spec.h"
@@ -136,6 +138,15 @@ int board_init(void)
/* adress of boot parameters */
gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
+ /*
+ * Map SPI devices via MBUS so that they can be accessed via
+ * the SPI direct access mode
+ */
+ mbus_dt_setup_win(&mbus_state, SPI_BUS0_DEV1_BASE, SPI_BUS0_DEV1_SIZE,
+ CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_SPI0_CS1);
+ mbus_dt_setup_win(&mbus_state, SPI_BUS1_DEV2_BASE, SPI_BUS0_DEV1_SIZE,
+ CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_SPI1_CS2);
+
return 0;
}
@@ -143,6 +154,8 @@ int checkboard(void)
{
puts("Board: theadorable\n");
+ board_fpga_add();
+
return 0;
}
diff --git a/board/theadorable/theadorable.h b/board/theadorable/theadorable.h
new file mode 100644
index 0000000000..89fe1179a4
--- /dev/null
+++ b/board/theadorable/theadorable.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/* Base addresses for the SPI direct access mode */
+#define SPI_BUS0_DEV1_BASE 0xe0000000
+#define SPI_BUS0_DEV1_SIZE (1 << 20)
+#define SPI_BUS1_DEV2_BASE (SPI_BUS0_DEV1_BASE + SPI_BUS0_DEV1_SIZE)
+
+void board_fpga_add(void);
diff --git a/configs/theadorable_debug_defconfig b/configs/theadorable_debug_defconfig
index 62a6ee6663..054038a03b 100644
--- a/configs/theadorable_debug_defconfig
+++ b/configs/theadorable_debug_defconfig
@@ -2,6 +2,7 @@ CONFIG_ARM=y
CONFIG_ARCH_MVEBU=y
CONFIG_SYS_MALLOC_F_LEN=0x2000
CONFIG_TARGET_THEADORABLE=y
+CONFIG_DM_GPIO=y
CONFIG_DEFAULT_DEVICE_TREE="armada-xp-theadorable"
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL=y
@@ -10,7 +11,7 @@ CONFIG_FIT=y
# CONFIG_CMD_FLASH is not set
CONFIG_CMD_SF=y
CONFIG_CMD_USB=y
-# CONFIG_CMD_FPGA is not set
+CONFIG_CMD_GPIO=y
# CONFIG_CMD_SETEXPR is not set
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_SPL_OF_TRANSLATE=y
diff --git a/configs/theadorable_defconfig b/configs/theadorable_defconfig
index 4d5f3b0a0a..9a6abf2f7e 100644
--- a/configs/theadorable_defconfig
+++ b/configs/theadorable_defconfig
@@ -2,6 +2,7 @@ CONFIG_ARM=y
CONFIG_ARCH_MVEBU=y
CONFIG_SYS_MALLOC_F_LEN=0x2000
CONFIG_TARGET_THEADORABLE=y
+CONFIG_DM_GPIO=y
CONFIG_DEFAULT_DEVICE_TREE="armada-xp-theadorable"
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL=y
@@ -9,7 +10,6 @@ CONFIG_FIT=y
# CONFIG_CMD_IMLS is not set
# CONFIG_CMD_FLASH is not set
CONFIG_CMD_SF=y
-# CONFIG_CMD_FPGA is not set
# CONFIG_CMD_SETEXPR is not set
# CONFIG_CMD_NET is not set
# CONFIG_CMD_NFS is not set
diff --git a/drivers/ddr/marvell/a38x/ddr3_init.c b/drivers/ddr/marvell/a38x/ddr3_init.c
index 556f877039..ee05f57f43 100644
--- a/drivers/ddr/marvell/a38x/ddr3_init.c
+++ b/drivers/ddr/marvell/a38x/ddr3_init.c
@@ -305,8 +305,6 @@ int ddr3_init(void)
SAR1_CPU_CORE_OFFSET;
switch (soc_num) {
case 0x3:
- reg_bit_set(CPU_CONFIGURATION_REG(3), CPU_MRVL_ID_OFFSET);
- reg_bit_set(CPU_CONFIGURATION_REG(2), CPU_MRVL_ID_OFFSET);
case 0x1:
reg_bit_set(CPU_CONFIGURATION_REG(1), CPU_MRVL_ID_OFFSET);
case 0x0:
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index 6aa24d4359..fec3fecbdf 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -17,5 +17,6 @@ obj-y += altera.o
obj-$(CONFIG_FPGA_ACEX1K) += ACEX1K.o
obj-$(CONFIG_FPGA_CYCLON2) += cyclon2.o
obj-$(CONFIG_FPGA_STRATIX_II) += stratixII.o
+obj-$(CONFIG_FPGA_STRATIX_V) += stratixv.o
obj-$(CONFIG_FPGA_SOCFPGA) += socfpga.o
endif
diff --git a/drivers/fpga/altera.c b/drivers/fpga/altera.c
index a5bfe5dce1..135a3572a8 100644
--- a/drivers/fpga/altera.c
+++ b/drivers/fpga/altera.c
@@ -37,6 +37,9 @@ static const struct altera_fpga {
{ Altera_StratixII, "StratixII", StratixII_load,
StratixII_dump, StratixII_info },
#endif
+#if defined(CONFIG_FPGA_STRATIX_V)
+ { Altera_StratixV, "StratixV", stratixv_load, NULL, NULL },
+#endif
#if defined(CONFIG_FPGA_SOCFPGA)
{ Altera_SoCFPGA, "SoC FPGA", socfpga_load, NULL, NULL },
#endif
diff --git a/drivers/fpga/stratixv.c b/drivers/fpga/stratixv.c
new file mode 100644
index 0000000000..cc035eb2a1
--- /dev/null
+++ b/drivers/fpga/stratixv.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <altera.h>
+#include <spi.h>
+#include <asm/io.h>
+#include <asm/errno.h>
+
+/* Write the RBF data to FPGA via SPI */
+static int program_write(int spi_bus, int spi_dev, const void *rbf_data,
+ unsigned long rbf_size)
+{
+ struct spi_slave *slave;
+ int ret;
+
+ debug("%s (%d): data=%p size=%ld\n",
+ __func__, __LINE__, rbf_data, rbf_size);
+
+ /* FIXME: How to get the max. SPI clock and SPI mode? */
+ slave = spi_setup_slave(spi_bus, spi_dev, 27777777, SPI_MODE_3);
+ if (!slave)
+ return -1;
+
+ if (spi_claim_bus(slave))
+ return -1;
+
+ ret = spi_xfer(slave, rbf_size * 8, rbf_data, (void *)rbf_data,
+ SPI_XFER_BEGIN | SPI_XFER_END);
+
+ spi_release_bus(slave);
+
+ return ret;
+}
+
+/*
+ * This is the interface used by FPGA driver.
+ * Return 0 for sucess, non-zero for error.
+ */
+int stratixv_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size)
+{
+ altera_board_specific_func *pfns = desc->iface_fns;
+ int cookie = desc->cookie;
+ int spi_bus;
+ int spi_dev;
+ int ret = 0;
+
+ if ((u32)rbf_data & 0x3) {
+ puts("FPGA: Unaligned data, realign to 32bit boundary.\n");
+ return -EINVAL;
+ }
+
+ /* Run the pre configuration function if there is one */
+ if (pfns->pre)
+ (pfns->pre)(cookie);
+
+ /* Establish the initial state */
+ if (pfns->config) {
+ /* De-assert nCONFIG */
+ (pfns->config)(false, true, cookie);
+
+ /* nConfig minimum low pulse width is 2us */
+ udelay(200);
+
+ /* Assert nCONFIG */
+ (pfns->config)(true, true, cookie);
+
+ /* nCONFIG high to first rising clock on DCLK min 1506 us */
+ udelay(1600);
+ }
+
+ /* Write the RBF data to FPGA */
+ if (pfns->write) {
+ /*
+ * Use board specific data function to write bitstream
+ * into the FPGA
+ */
+ ret = (pfns->write)(rbf_data, rbf_size, true, cookie);
+ } else {
+ /*
+ * Use common SPI functions to write bitstream into the
+ * FPGA
+ */
+ spi_bus = COOKIE2SPI_BUS(cookie);
+ spi_dev = COOKIE2SPI_DEV(cookie);
+ ret = program_write(spi_bus, spi_dev, rbf_data, rbf_size);
+ }
+ if (ret)
+ return ret;
+
+ /* Check done pin */
+ if (pfns->done) {
+ ret = (pfns->done)(cookie);
+
+ if (ret)
+ printf("Error: DONE not set (ret=%d)!\n", ret);
+ }
+
+ return ret;
+}
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index a5da5e7e88..23113090b3 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -105,4 +105,11 @@ config PIC32_GPIO
help
Say yes here to support Microchip PIC32 GPIOs.
+config MVEBU_GPIO
+ bool "Marvell MVEBU GPIO driver"
+ depends on DM_GPIO && ARCH_MVEBU
+ default y
+ help
+ Say yes here to support Marvell MVEBU (Armada XP/38x) GPIOs.
+
endmenu
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index e7b7ec45b7..ea6e2ede0d 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -49,3 +49,4 @@ obj-$(CONFIG_ZYNQ_GPIO) += zynq_gpio.o
obj-$(CONFIG_VYBRID_GPIO) += vybrid_gpio.o
obj-$(CONFIG_HIKEY_GPIO) += hi6220_gpio.o
obj-$(CONFIG_PIC32_GPIO) += pic32_gpio.o
+obj-$(CONFIG_MVEBU_GPIO) += mvebu_gpio.o
diff --git a/drivers/gpio/mvebu_gpio.c b/drivers/gpio/mvebu_gpio.c
new file mode 100644
index 0000000000..9564ce2b13
--- /dev/null
+++ b/drivers/gpio/mvebu_gpio.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <errno.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define MVEBU_GPIOS_PER_BANK 32
+
+struct mvebu_gpio_regs {
+ u32 data_out;
+ u32 io_conf;
+ u32 blink_en;
+ u32 in_pol;
+ u32 data_in;
+};
+
+struct mvebu_gpio_priv {
+ struct mvebu_gpio_regs *regs;
+ char name[2];
+};
+
+static int mvebu_gpio_direction_input(struct udevice *dev, unsigned int gpio)
+{
+ struct mvebu_gpio_priv *priv = dev_get_priv(dev);
+ struct mvebu_gpio_regs *regs = priv->regs;
+
+ setbits_le32(&regs->io_conf, BIT(gpio));
+
+ return 0;
+}
+
+static int mvebu_gpio_direction_output(struct udevice *dev, unsigned gpio,
+ int value)
+{
+ struct mvebu_gpio_priv *priv = dev_get_priv(dev);
+ struct mvebu_gpio_regs *regs = priv->regs;
+
+ clrbits_le32(&regs->io_conf, BIT(gpio));
+
+ return 0;
+}
+
+static int mvebu_gpio_get_function(struct udevice *dev, unsigned gpio)
+{
+ struct mvebu_gpio_priv *priv = dev_get_priv(dev);
+ struct mvebu_gpio_regs *regs = priv->regs;
+ u32 val;
+
+ val = readl(&regs->io_conf) & BIT(gpio);
+ if (val)
+ return GPIOF_INPUT;
+ else
+ return GPIOF_OUTPUT;
+}
+
+static int mvebu_gpio_set_value(struct udevice *dev, unsigned gpio,
+ int value)
+{
+ struct mvebu_gpio_priv *priv = dev_get_priv(dev);
+ struct mvebu_gpio_regs *regs = priv->regs;
+
+ if (value)
+ setbits_le32(&regs->data_out, BIT(gpio));
+ else
+ clrbits_le32(&regs->data_out, BIT(gpio));
+
+ return 0;
+}
+
+static int mvebu_gpio_get_value(struct udevice *dev, unsigned gpio)
+{
+ struct mvebu_gpio_priv *priv = dev_get_priv(dev);
+ struct mvebu_gpio_regs *regs = priv->regs;
+
+ return !!(readl(&regs->data_in) & BIT(gpio));
+}
+
+static int mvebu_gpio_probe(struct udevice *dev)
+{
+ struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+ struct mvebu_gpio_priv *priv = dev_get_priv(dev);
+
+ priv->regs = (struct mvebu_gpio_regs *)dev_get_addr(dev);
+ uc_priv->gpio_count = MVEBU_GPIOS_PER_BANK;
+ priv->name[0] = 'A' + dev->req_seq;
+ uc_priv->bank_name = priv->name;
+
+ return 0;
+}
+
+static const struct dm_gpio_ops mvebu_gpio_ops = {
+ .direction_input = mvebu_gpio_direction_input,
+ .direction_output = mvebu_gpio_direction_output,
+ .get_function = mvebu_gpio_get_function,
+ .get_value = mvebu_gpio_get_value,
+ .set_value = mvebu_gpio_set_value,
+};
+
+static const struct udevice_id mvebu_gpio_ids[] = {
+ { .compatible = "marvell,orion-gpio" },
+ { }
+};
+
+U_BOOT_DRIVER(gpio_mvebu) = {
+ .name = "gpio_mvebu",
+ .id = UCLASS_GPIO,
+ .of_match = mvebu_gpio_ids,
+ .ops = &mvebu_gpio_ops,
+ .probe = mvebu_gpio_probe,
+ .priv_auto_alloc_size = sizeof(struct mvebu_gpio_priv),
+};
diff --git a/include/altera.h b/include/altera.h
index c2991ad800..48d3eb73c9 100644
--- a/include/altera.h
+++ b/include/altera.h
@@ -10,6 +10,19 @@
#ifndef _ALTERA_H_
#define _ALTERA_H_
+/*
+ * For the StratixV FPGA programming via SPI, the following
+ * information is coded in the 32bit cookie:
+ * Bit 31 ... Bit 0
+ * SPI-Bus | SPI-Dev | Config-Pin | Done-Pin
+ */
+#define FPGA_COOKIE(bus, dev, config, done) \
+ (((bus) << 24) | ((dev) << 16) | ((config) << 8) | (done))
+#define COOKIE2SPI_BUS(c) (((c) >> 24) & 0xff)
+#define COOKIE2SPI_DEV(c) (((c) >> 16) & 0xff)
+#define COOKIE2CONFIG(c) (((c) >> 8) & 0xff)
+#define COOKIE2DONE(c) ((c) & 0xff)
+
enum altera_iface {
/* insert all new types after this */
min_altera_iface_type,
@@ -40,6 +53,8 @@ enum altera_family {
Altera_CYC2,
/* StratixII Family */
Altera_StratixII,
+ /* StratixV Family */
+ Altera_StratixV,
/* SoCFPGA Family */
Altera_SoCFPGA,
@@ -89,6 +104,7 @@ typedef struct {
Altera_done_fn done;
Altera_clk_fn clk;
Altera_data_fn data;
+ Altera_write_fn write;
Altera_abort_fn abort;
Altera_post_fn post;
} altera_board_specific_func;
@@ -97,4 +113,8 @@ typedef struct {
int socfpga_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size);
#endif
+#ifdef CONFIG_FPGA_STRATIX_V
+int stratixv_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size);
+#endif
+
#endif /* _ALTERA_H_ */
diff --git a/include/configs/sheevaplug.h b/include/configs/sheevaplug.h
index c529636a66..f9fb9bc9af 100644
--- a/include/configs/sheevaplug.h
+++ b/include/configs/sheevaplug.h
@@ -64,12 +64,12 @@
#define CONFIG_MTDPARTS \
"orion_nand:512K(uboot)," \
- "512K(env),1M(script),6M(kernel)," \
- "12M(ramdisk),4M(spare),-(rootfs)\0"
+ "512K(env),4M(kernel)," \
+ "-(rootfs)\0"
#define CONFIG_EXTRA_ENV_SETTINGS "x_bootargs=console" \
"=ttyS0,115200 mtdparts="CONFIG_MTDPARTS \
- "x_bootcmd_kernel=nand read 0x6400000 0x100000 0x300000\0" \
+ "x_bootcmd_kernel=nand read 0x6400000 0x100000 0x400000\0" \
"x_bootcmd_usb=usb start\0" \
"x_bootargs_root=root=/dev/mtdblock3 rw rootfstype=jffs2\0"
diff --git a/include/configs/theadorable.h b/include/configs/theadorable.h
index 9f186add71..a4bcf21210 100644
--- a/include/configs/theadorable.h
+++ b/include/configs/theadorable.h
@@ -114,6 +114,11 @@
#define CONFIG_VGA_AS_SINGLE_DEVICE
#define CONFIG_CMD_BMP
+/* FPGA programming support */
+#define CONFIG_FPGA
+#define CONFIG_FPGA_ALTERA
+#define CONFIG_FPGA_STRATIX_V
+
/*
* mv-common.h should be defined after CMD configs since it used them
* to enable certain macros
diff --git a/tools/kwboot.c b/tools/kwboot.c
index 905ade3b01..e00958a4ce 100644
--- a/tools/kwboot.c
+++ b/tools/kwboot.c
@@ -76,6 +76,7 @@ static int kwboot_verbose;
static int msg_req_delay = KWBOOT_MSG_REQ_DELAY;
static int msg_rsp_timeo = KWBOOT_MSG_RSP_TIMEO;
+static int blk_rsp_timeo = KWBOOT_BLK_RSP_TIMEO;
static void
kwboot_printv(const char *fmt, ...)
@@ -380,7 +381,7 @@ kwboot_xm_sendblock(int fd, struct kwboot_block *block)
break;
do {
- rc = kwboot_tty_recv(fd, &c, 1, KWBOOT_BLK_RSP_TIMEO);
+ rc = kwboot_tty_recv(fd, &c, 1, blk_rsp_timeo);
if (rc)
break;
@@ -684,7 +685,7 @@ static void
kwboot_usage(FILE *stream, char *progname)
{
fprintf(stream,
- "Usage: %s [-d | -a | -q <req-delay> | -s <resp-timeo> | -b <image> | -D <image> ] [ -t ] [-B <baud> ] <TTY>\n",
+ "Usage: %s [OPTIONS] [-b <image> | -D <image> ] [-B <baud> ] <TTY>\n",
progname);
fprintf(stream, "\n");
fprintf(stream,
@@ -696,6 +697,8 @@ kwboot_usage(FILE *stream, char *progname)
fprintf(stream, " -a: use timings for Armada XP\n");
fprintf(stream, " -q <req-delay>: use specific request-delay\n");
fprintf(stream, " -s <resp-timeo>: use specific response-timeout\n");
+ fprintf(stream,
+ " -o <block-timeo>: use specific xmodem block timeout\n");
fprintf(stream, "\n");
fprintf(stream, " -t: mini terminal\n");
fprintf(stream, "\n");
@@ -728,7 +731,7 @@ main(int argc, char **argv)
kwboot_verbose = isatty(STDOUT_FILENO);
do {
- int c = getopt(argc, argv, "hb:ptaB:dD:q:s:");
+ int c = getopt(argc, argv, "hb:ptaB:dD:q:s:o:");
if (c < 0)
break;
@@ -768,6 +771,10 @@ main(int argc, char **argv)
msg_rsp_timeo = atoi(optarg);
break;
+ case 'o':
+ blk_rsp_timeo = atoi(optarg);
+ break;
+
case 'B':
speed = kwboot_tty_speed(atoi(optarg));
if (speed == -1)