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 | 
