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 /board/theadorable | |
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>
Diffstat (limited to 'board/theadorable')
-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 |
4 files changed, 205 insertions, 0 deletions
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(®->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 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); |