Commit ff9c4c535a8b722c54d45e77aa083fa08552341d

Authored by Stefan Roese
1 parent 704d9a645e

fpga: altera: Add StratixV support

This patch adds support for programming of the StratixV FPGAs. Programming
is done in this case (board theadorable) via SPI. The board may provide
board specific code for bitstream programming.

This StratixV support will be used by the theadorable board.

Signed-off-by: Stefan Roese <sr@denx.de>
Cc: Tom Rini <trini@konsulko.com>
Signed-off-by: Stefan Roese <sr@denx.de>

Showing 4 changed files with 127 additions and 0 deletions Side-by-side Diff

drivers/fpga/Makefile
... ... @@ -17,6 +17,7 @@
17 17 obj-$(CONFIG_FPGA_ACEX1K) += ACEX1K.o
18 18 obj-$(CONFIG_FPGA_CYCLON2) += cyclon2.o
19 19 obj-$(CONFIG_FPGA_STRATIX_II) += stratixII.o
  20 +obj-$(CONFIG_FPGA_STRATIX_V) += stratixv.o
20 21 obj-$(CONFIG_FPGA_SOCFPGA) += socfpga.o
21 22 endif
drivers/fpga/altera.c
... ... @@ -37,6 +37,9 @@
37 37 { Altera_StratixII, "StratixII", StratixII_load,
38 38 StratixII_dump, StratixII_info },
39 39 #endif
  40 +#if defined(CONFIG_FPGA_STRATIX_V)
  41 + { Altera_StratixV, "StratixV", stratixv_load, NULL, NULL },
  42 +#endif
40 43 #if defined(CONFIG_FPGA_SOCFPGA)
41 44 { Altera_SoCFPGA, "SoC FPGA", socfpga_load, NULL, NULL },
42 45 #endif
drivers/fpga/stratixv.c
  1 +/*
  2 + * Copyright (C) 2016 Stefan Roese <sr@denx.de>
  3 + *
  4 + * SPDX-License-Identifier: GPL-2.0+
  5 + */
  6 +
  7 +#include <common.h>
  8 +#include <altera.h>
  9 +#include <spi.h>
  10 +#include <asm/io.h>
  11 +#include <asm/errno.h>
  12 +
  13 +/* Write the RBF data to FPGA via SPI */
  14 +static int program_write(int spi_bus, int spi_dev, const void *rbf_data,
  15 + unsigned long rbf_size)
  16 +{
  17 + struct spi_slave *slave;
  18 + int ret;
  19 +
  20 + debug("%s (%d): data=%p size=%ld\n",
  21 + __func__, __LINE__, rbf_data, rbf_size);
  22 +
  23 + /* FIXME: How to get the max. SPI clock and SPI mode? */
  24 + slave = spi_setup_slave(spi_bus, spi_dev, 27777777, SPI_MODE_3);
  25 + if (!slave)
  26 + return -1;
  27 +
  28 + if (spi_claim_bus(slave))
  29 + return -1;
  30 +
  31 + ret = spi_xfer(slave, rbf_size * 8, rbf_data, (void *)rbf_data,
  32 + SPI_XFER_BEGIN | SPI_XFER_END);
  33 +
  34 + spi_release_bus(slave);
  35 +
  36 + return ret;
  37 +}
  38 +
  39 +/*
  40 + * This is the interface used by FPGA driver.
  41 + * Return 0 for sucess, non-zero for error.
  42 + */
  43 +int stratixv_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size)
  44 +{
  45 + altera_board_specific_func *pfns = desc->iface_fns;
  46 + int cookie = desc->cookie;
  47 + int spi_bus;
  48 + int spi_dev;
  49 + int ret = 0;
  50 +
  51 + if ((u32)rbf_data & 0x3) {
  52 + puts("FPGA: Unaligned data, realign to 32bit boundary.\n");
  53 + return -EINVAL;
  54 + }
  55 +
  56 + /* Run the pre configuration function if there is one */
  57 + if (pfns->pre)
  58 + (pfns->pre)(cookie);
  59 +
  60 + /* Establish the initial state */
  61 + if (pfns->config) {
  62 + /* De-assert nCONFIG */
  63 + (pfns->config)(false, true, cookie);
  64 +
  65 + /* nConfig minimum low pulse width is 2us */
  66 + udelay(200);
  67 +
  68 + /* Assert nCONFIG */
  69 + (pfns->config)(true, true, cookie);
  70 +
  71 + /* nCONFIG high to first rising clock on DCLK min 1506 us */
  72 + udelay(1600);
  73 + }
  74 +
  75 + /* Write the RBF data to FPGA */
  76 + if (pfns->write) {
  77 + /*
  78 + * Use board specific data function to write bitstream
  79 + * into the FPGA
  80 + */
  81 + ret = (pfns->write)(rbf_data, rbf_size, true, cookie);
  82 + } else {
  83 + /*
  84 + * Use common SPI functions to write bitstream into the
  85 + * FPGA
  86 + */
  87 + spi_bus = COOKIE2SPI_BUS(cookie);
  88 + spi_dev = COOKIE2SPI_DEV(cookie);
  89 + ret = program_write(spi_bus, spi_dev, rbf_data, rbf_size);
  90 + }
  91 + if (ret)
  92 + return ret;
  93 +
  94 + /* Check done pin */
  95 + if (pfns->done) {
  96 + ret = (pfns->done)(cookie);
  97 +
  98 + if (ret)
  99 + printf("Error: DONE not set (ret=%d)!\n", ret);
  100 + }
  101 +
  102 + return ret;
  103 +}
... ... @@ -10,6 +10,19 @@
10 10 #ifndef _ALTERA_H_
11 11 #define _ALTERA_H_
12 12  
  13 +/*
  14 + * For the StratixV FPGA programming via SPI, the following
  15 + * information is coded in the 32bit cookie:
  16 + * Bit 31 ... Bit 0
  17 + * SPI-Bus | SPI-Dev | Config-Pin | Done-Pin
  18 + */
  19 +#define FPGA_COOKIE(bus, dev, config, done) \
  20 + (((bus) << 24) | ((dev) << 16) | ((config) << 8) | (done))
  21 +#define COOKIE2SPI_BUS(c) (((c) >> 24) & 0xff)
  22 +#define COOKIE2SPI_DEV(c) (((c) >> 16) & 0xff)
  23 +#define COOKIE2CONFIG(c) (((c) >> 8) & 0xff)
  24 +#define COOKIE2DONE(c) ((c) & 0xff)
  25 +
13 26 enum altera_iface {
14 27 /* insert all new types after this */
15 28 min_altera_iface_type,
... ... @@ -40,6 +53,8 @@
40 53 Altera_CYC2,
41 54 /* StratixII Family */
42 55 Altera_StratixII,
  56 + /* StratixV Family */
  57 + Altera_StratixV,
43 58 /* SoCFPGA Family */
44 59 Altera_SoCFPGA,
45 60  
46 61  
... ... @@ -89,12 +104,17 @@
89 104 Altera_done_fn done;
90 105 Altera_clk_fn clk;
91 106 Altera_data_fn data;
  107 + Altera_write_fn write;
92 108 Altera_abort_fn abort;
93 109 Altera_post_fn post;
94 110 } altera_board_specific_func;
95 111  
96 112 #ifdef CONFIG_FPGA_SOCFPGA
97 113 int socfpga_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size);
  114 +#endif
  115 +
  116 +#ifdef CONFIG_FPGA_STRATIX_V
  117 +int stratixv_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size);
98 118 #endif
99 119  
100 120 #endif /* _ALTERA_H_ */