[RFC] FPGA configuration as MTD using Device Tree

Ulf Samuelsson u-boot at emagii.com
Mon Sep 14 16:22:21 CEST 2020



Den 2020-09-14 kl. 13:49, skrev Michal Simek:
> Hi,
> 
> On 07. 09. 20 19:03, Ulf Samuelsson wrote:
>> Hi,
>> The FPGA support in u-boot looks a bit old-fashioned to me.
>> I would like to have device-tree support and would
>> like comments on my approach.
> 
> Definitely there is a space for improvement.
> In connection to DT - we should likely create fpga DM class for it.
> 
I do not think that it is neccessary.
At least I did not need it to implement passive serial programming.

I have it working right now, and can use the MTD command
and just add the FPGA as a device under the the SPI bus.

If a DM class is added, then either the MTD command
needs to be updated, or a new command developed.


>>
>>
>> ====================================================================
>> BACKGROUND
>> Need to support loading 2 x Cyclone-10 LP FPGAs using Passive Serial.
>> Raw binary files (RBF) are stored in boot flash, and
>> u-boot will load both FPGAs before booting the OS.
>> The OS should be able to update the FPGAs as well.
>> The FPGAs must be independently configurable.
>>
>> Hardwarewise, I have an SPI bus with 4 chip selects.
>> SPI MOSI, SCK, CS2 and CS3 are connected to the synchronous serial bus
>> of the FPGA (DATA0, DCLK, the FPGA1.nCS0 and the FPGA2.nCS0)
>>
>> Intel normally connect FPGA nCS0 to ground but I connect this to the SPI
>> CS. The advantage is that I can have several FPGAs which are programmed
>> independent to each other.
>>
>> The FPGAs require three other signals (nCONFIG, nSTATUS and CONF_DONE).
>> Each FPGA have their own set of those signals.
>> ====================================================================
>>
>> I have not found device-tree support for FPGAs in u-boot.
>> Since the FPGAs are connected to the SPI, I thought adding them as MTD
>> devices would result in a nice interface.
>>
>> ====================================================================
>> Example Device tree connected to a bit-bang SPI driver supporting
>> multiple chip select.
>>
>> The MTD configuration supplies
>> * Name of the FPGA (fpga property)
>> * The size of the configuration data
>> * Sideband signals for starting and checking configuration.
>>
>> &soft_mcspi {
>>      compatible = "mcspi-gpio";
>>      pinctrl-names = "default";
>>      pinctrl-0 = <&soft_mcspi1_pins>;
>>      status = "okay";
>>      gpio-sck  = <&gpio0 7 GPIO_ACTIVE_LOW>;
>>      gpio-miso = <&gpio1 8 GPIO_ACTIVE_HIGH>;
>>      gpio-mosi = <&gpio1 9 GPIO_ACTIVE_HIGH>;
>>      cs-gpios =
>>         <&gpio0 12 GPIO_ACTIVE_LOW>,
>>         <&gpio0 13 GPIO_ACTIVE_LOW>,
>>         <&gpio0 17 GPIO_ACTIVE_LOW>,
>>         <&gpio0 16 GPIO_ACTIVE_LOW>;
>>      num-chipselects = <4>;
>>      #address-cells = <1>;
>>      #size-cells = <0>;
>>      ...
>>      sspy-fpga-cfg at 3 {    /* Intel Cyclone 10, 10CL025 */
>>          #address-cells = <1>;
>>          #size-cells = <1>;
>>          compatible = "intel,cyclone10";
>>          reg = <3>; /* Chip select 0 */
>>          spi-max-frequency = <1000000>;
>>          fpga = "spyf";
>>          config-size    = <718569>;
>>          gpio-nconfig    = <&gpio3 21 GPIO_ACTIVE_HIGH>;
>>          gpio-nstatus    = <&gpio3 17 GPIO_ACTIVE_HIGH>;
>>          gpio-conf_done    = <&gpio0 18 GPIO_ACTIVE_HIGH>;
>>          gpio-crc_error    = <&gpio2 18 GPIO_ACTIVE_HIGH>;
>>      };
>> };
>> ====================================================================
>>
>> With a Cyclone 10 MTD driver, is would appear in the "mtd list" command
>> and configuring the fpga would be done using
>>
>> $ mtd write.raw spyf <ram-addr>
>>
>> The driver would have to implement dummy read and erase commands.
>>
>> An alternative would be to add flags which would be tested by the mtd
>> command which would block the read and erase if the mtd device is an
>> FPGA or simply test for that in the mtd command.
>>
>> What would be best?
>> ====================================================================
>>
>> The MTD driver would start configuration by toggling gpio-nconfig low
>> and then wait for gpio-nstatus to go high.
>>
>> If OK, it would call the spi_xfer routine for the parent spi slave
>> (soft-mcspi)
>>
>> When the spi write returns, the FPGA MTD driver would await the
>> CONF_DONE signal before returning.
>>
>> ====================================================================
>>
>> What do you guys think of such an approach?
> 
> You are writing that fpga should be loaded before OS. You likely have
> any reason for it but I think that make sense to take a look at it from
> different angle.
> You have 4 fpgas and when you load all of them in u-boot you are slowing
> down boot.

The FPGA goes into a system where the FPGAs needs to be running as soon
as possible. It cannot wait for linux to boot.

We only have two FPGAs each on a separate chip select (2 & 3).
One of the FPGAs contains peripherals accessible over SPI,
so chip select 0 goes to a user SPI slave interface inside this FPGA.
SPI chipselect 1 goes to a dedicated SPI peripheral.

=================
I am currently using a bitbanging driver and get programming times of 3 
& 9 seconds. They are not particularily large so they should load in 
less than a second with a H/W driver.
The H/W driver we are using (omap-spi) does not support GPIO chip 
selects, and only two are supported so it needs to be extended.

I hope to do the load during the bootdelay.
=================



> Anyway I think that make sense to take a look at Linux first.
> https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/tree/drivers/fpga
> 
> I see 4 spi based drivers where I expect none is using MTD layer for
> programming. You will find out dt binding for these devices and the same
> binding should be used also in u-boot.

I looked at the linux drivers and the altera-ps-spi.c is the correct 
starting point. It only supports cyclone 5 and Arria 10 and I am using 
Cyclone 10. The linux drivers needs to have Cyclone 10 support added.

The main difference is delay timing, not functionality..

I also found a device tree using this: imx6q-evi.dts
It is the only one using the driver.

+++++++
&ecspi1 {
	cs-gpios = <&gpio4 10 GPIO_ACTIVE_LOW>;
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_ecspi1 &pinctrl_ecspi1cs>;
	status = "okay";

	fpga: fpga at 0 {
		compatible = "altr,fpga-passive-serial";
		spi-max-frequency = <20000000>;
		reg = <0>;
		pinctrl-0 = <&pinctrl_fpgaspi>;
		nconfig-gpios = <&gpio4 9 GPIO_ACTIVE_LOW>;
		nstat-gpios = <&gpio4 11 GPIO_ACTIVE_LOW>;
	};
};

This does not use the confd pin, but the driver supports it.
-------

compared to my current:
&soft_mcspi {
       compatible = "mcspi-gpio";
       pinctrl-names = "default";
       pinctrl-0 = <&soft_mcspi1_pins>;
       status = "okay";
       gpio-sck  = <&gpio0 7 GPIO_ACTIVE_LOW>;
       gpio-miso = <&gpio1 8 GPIO_ACTIVE_HIGH>;
       gpio-mosi = <&gpio1 9 GPIO_ACTIVE_HIGH>;
       cs-gpios =
          <&gpio0 12 GPIO_ACTIVE_LOW>,
          <&gpio0 13 GPIO_ACTIVE_LOW>,
          <&gpio0 17 GPIO_ACTIVE_LOW>,
          <&gpio0 16 GPIO_ACTIVE_LOW>;
       num-chipselects = <4>;
       #address-cells = <1>;
       #size-cells = <0>;
       ...
       sspy-fpga-cfg at 3 {    /* Intel Cyclone 10, 10CL025 */
           #address-cells = <1>;
           #size-cells = <1>;
           compatible = "intel,cyclone10";
           reg = <3>; /* Chip select 0 */
           spi-max-frequency = <1000000>;
           fpga = "spyf";
           config-size    = <718569>;
           gpio-nconfig    = <&gpio3 21 GPIO_ACTIVE_HIGH>;
           gpio-nstatus    = <&gpio3 17 GPIO_ACTIVE_HIGH>;
           gpio-conf_done    = <&gpio0 18 GPIO_ACTIVE_HIGH>;
           gpio-crc_error    = <&gpio2 18 GPIO_ACTIVE_HIGH>;
       };
};

So I can rename the compatible name and the gpios to get it to work.

The current linux driver does not support
* config size. Without this, the config size needs to be specified on
   the command string, which I do not like.
* the crc_error pin
* an optional fpga name which is desirable.
   The driver will generate a generated name using "dev_driver_string".
   Is something similar available in u-boot?

I guess a linux driver will simply ignore them unless updated.

=================
The SPI drivers are not using MTD.
They are using FPGA manager, which I feels is a bit unneccessary.

You need dedicated applications to program the FPGA this way.
Using an mtd approach, I expect you can do

cat fpga-config.rbf > /dev/mtd4 &

=====
The FPGA uses LSB SPI transfer for configuration, and the linux driver 
bitreverses everything in the buffer instead of setting the SPI LSB 
transfer bit, which is a bit odd.

/Ulf
> 
> Thanks,
> Michal
> 


More information about the U-Boot mailing list