RFC: FPGAs as Memory Technology Devices in U-Boot

Ulf Samuelsson u-boot at emagii.com
Tue Feb 7 10:10:46 CET 2023


As shown at a presentation in the recent OpenEmbedded Workshop,
it is possible to configure an FPGA in Passive Serial mode
using a standard SPI controller, each FPGA getting its own chipselect.

https://pretalx.com/openembedded-workshop-2023/talk/D3AQ3R/

This allows you to add the FPGA to the devicetree and to use standard 
MTD commands, instead of the FPGA commands.


I.E: The SPI portion is

&spi1 {
     u-boot,dm-spl;
     status = "okay";
     pinctrl-names = "default";
     pinctrl-0 = <&spi1_pins>;
     num-cs = <4>; /* Needed for GPIO cs */
     cs-gpios =
         <&gpio0 12 GPIO_ACTIVE_LOW>, /* D18,0:12 uart1_ctsn.spi1_cs0 */
         <&gpio0 13 GPIO_ACTIVE_LOW>, /* D17,0:13 uart1_rtsn.spi1_cs1 */
         <&gpio0 17 GPIO_ACTIVE_LOW>, /* K15,0:17 mii_txd2.spi1_cs2 */
         <&gpio0 16 GPIO_ACTIVE_LOW>; /* J18,0:16 mii_txd3.spi1_cs3 */
         spi-max-frequency = <10000000>; ;
         gpio_spi0: gpio_spi at 0 {...}
         gpio_spi1: gpio_spi at 1 {...}
         spi-fpga-cfg at 2 {...} /* FPGA #1 */
         spy-fpga-cfg at 3 {...} /* FPGA #2 */
};

The FPGA part is.

spi-fpga-cfg at 2 { /* Intel Cyclone 10, 10CL010 */
     #address-cells = <1>;
     #size-cells = <1>;
     compatible = "intel,cyclone10";
     reg = <2>; /* Chip select 2 */
     spi-max-frequency = <10000000>;
     fpga = "spif"; /* Installed as /dev/spif */
     config-size = <368011>;
     nconfig-gpios = <&gpio3 15 GPIO_ACTIVE_HIGH>; /* ,3:15 */
     nstat-gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>; /* ,3:19 */
     confd-gpios = <&gpio3 18 GPIO_ACTIVE_HIGH>; /* ,3:18 */
     crc-error-gpios= <&gpio2 1 GPIO_ACTIVE_HIGH>; /* ,2:01 */
     partition at 0 {
         label = "spi-fpga";
         reg = <0x0000000 0x8000>;
     };
};

To configure the FPGA, you load the config info into RAM and write it to 
the FPGA.

U-BOOT> mtd read spi1 ${loadaddr} 0 ${filesize} # read from SPI
U-BOOT> mtd write fpga0 ${loadaddr} 0 ${filesize} # configure FPGA

A driver will pulse the nCONFIG pin of the FPGA, do an SPI transfer
and then check the FPGA status outputs.

Since the MTD command set can be used (and is needed anyway)
the FPGA command set can be removed from the U-Boot both simplifying
the user interface and reducing code size of the u-boot image.

It relies on the (hopefully) existing SPI driver for the chip in u-boot
so it should be easy to use in most systems (as long as the H/W is 
designed for it)


A linux driver, using the same principle would allow the FPGA to be
configured using a simple statement.

$ cat <bitfile> > /dev/fpga

The approach has been tested on a development board using an AM335x and 
2 x Cyclone 10.

The changes needed are
* adding the FPGA class in mtd-abi.h
* The "mtd" command hardwires the transfer to be RAW and no OOB.
* A driver wrapping the control signals around an SPI transfer
   1.Claim SPI bus
   2.Pulse nCONFIG low for 40 us,
   3.Wait for nSTATUS high
   4.Transfer bitstream using U-Boot SPI transfer
   5.Release SPI bus
   6.Wait until CONFIG_DONE (or error on nSTATUS)

Best Regards
Ulf Samuelsson


More information about the U-Boot mailing list