diff options
author | Stefan Roese <sr@denx.de> | 2016-02-12 14:24:07 +0100 |
---|---|---|
committer | Stefan Roese <sr@denx.de> | 2016-03-24 09:48:34 +0100 |
commit | aea02abec59e8ea8e78c7926162c2b0f6073f32c (patch) | |
tree | 7b8a7d01b37991b2b64bb246fc917fc4fbde7c6a | |
parent | 84d6919118042cba56fe50ee57b1b6351e740cf4 (diff) |
arm: mvebu: theadorable: Add StratixV FPGA programming support
This patch adds support for Altera StratixV bitstream programming. 2 FPGAs
are connected to the SPI busses. This patch uses board specific write
code to program the bitstream via SPI direct write mode.
Signed-off-by: Stefan Roese <sr@denx.de>
Cc: Luka Perkov <luka.perkov@sartura.hr>
Signed-off-by: Stefan Roese <sr@denx.de>
-rw-r--r-- | arch/arm/dts/armada-xp-theadorable.dts | 21 | ||||
-rw-r--r-- | board/theadorable/Makefile | 1 | ||||
-rw-r--r-- | board/theadorable/fpga.c | 179 | ||||
-rw-r--r-- | board/theadorable/theadorable.c | 13 | ||||
-rw-r--r-- | board/theadorable/theadorable.h | 12 | ||||
-rw-r--r-- | configs/theadorable_debug_defconfig | 3 | ||||
-rw-r--r-- | configs/theadorable_defconfig | 2 | ||||
-rw-r--r-- | include/configs/theadorable.h | 5 |
8 files changed, 234 insertions, 2 deletions
diff --git a/arch/arm/dts/armada-xp-theadorable.dts b/arch/arm/dts/armada-xp-theadorable.dts index cf1be2a3d4e..7087ccfc2f0 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 = ð0; }; @@ -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/board/theadorable/Makefile b/board/theadorable/Makefile index 9d5b39e6964..ef5a519ada9 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 00000000000..6f068c38ada --- /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(®->ctrl); + config_reg = readl(®->cfg); + writel(0x00000214, ®->cfg); /* 27MHz clock */ + writel(0x00000000, ®->dw_cfg); /* don't de-asset CS */ + writel(KWSPI_CSN_ACT, ®->ctrl); /* activate CS */ + + /* Copy data to the SPI direct mapped window */ + memcpy(dst, buf, len); + + /* Restore original register values */ + writel(control_reg, ®->ctrl); + writel(config_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 0e232656fc9..ee88a98a241 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 00000000000..89fe1179a48 --- /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 62a6ee6663b..054038a03be 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 4d5f3b0a0aa..9a6abf2f7e3 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/include/configs/theadorable.h b/include/configs/theadorable.h index 9f186add71f..a4bcf212108 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 |