Load fpga rbf from device tree overlay example?

I have used u-boot from Altera Quartus with boot script to load FPGA for the first time.
It was linux kernel 4.1-ltsi.
Then I have reloaded FPGA from my application with HPS regs. The sequence is described in hand-book for CycloneV.
You can mmap() regs to take control of them.

Thanks, which handbook are you referring too?

cyclone5_handbook.pdf
Look for issue A-26 Full Configuration (p. 3800): “The HPS uses the FPGA manager to configure the FPGA portion of the device. The following sequence suggests one way for software to perform a full configuration…” Then you have to find registers with mentioned bits in the configuration flow to controll the process (find correct register offsets).
Or look here for short view Booting and Configuration Introduction

1 Like

You have also to check correct MSEL Pin Settings (block 7-3, page 239 in handbook) “For configuration with HPS in SoC FPGA devices, refer to the FPGA Manager for the related MSEL pin settings.”

1 Like

Thanks, more reading to do :slight_smile:
Mainly I am looking for an example overlay DTS to get going.

I see, but I use this method. It can be useful when you have to change behaviour for your FPGA in different modes. May be some one have another solution, but I don’t have.

I think it’s not available in 4.9.20 but you can easily cherry pick the commit that enable it.

But i’m also stuck at the point “how to load a dt overlay :S”

I am not using a stock 4.9.20 but a kernel from https://github.com/RobertCNelson/socfpga-kernel-dev.

OK. I think the only way to load an overlay is to use the configfs.

Which is available in your kernel.

I put the .dtbo and .rbf in /lib/firmare/
The DTS overlay i used :

/dts-v1/;
/plugin/;

/ {
fragment@0 {
target-path = “/soc/base_fpga_region”;

  #address-cells = <1>;
  #size-cells = <1>;
  __overlay__ {
  	#address-cells = <1>;
  	#size-cells = <1>;
  	firmware-name = "firmware.rbf";
  };

};
};

Thanks I’ll give it a try. I’ll probably need to load from u-boot to be able to do a full FGPA (re)config.

No don’t load from uboot if you do that the fpga will not be flashed.

  • firmware-name : should contain the name of an FPGA image file located on the
    firmware search path. If this property shows up in a live device tree
    it indicates that the FPGA has already been programmed with this image.
    If this property is in an overlay targeting a FPGA region, it is a
    request to program the FPGA with that image.

Documentation/devicetree/bindings/fpga/fpga-region.txt

Okay, I got the FPGA to load with the DT overlay method. Now I need to be able to enable the brigde afterwarts…

echo 1 > "/sys/class/fpga_bridge/br0/state

Does not work. There should be a way to enable through the dtbo …

Works for me.

In socfpga.dtsi :

  base_fpga_region: base_fpga_region {
  	compatible = "fpga-region";
  	fpga-mgr = <&fpgamgr0>;
  	fpga-bridges = <&fpga_bridge0>, <&fpga_bridge1>,
  	<&fpga_bridge2>;
  	ranges = <0 0xff200000 0x100000>;
  	#address-cells = <0x1>;
  	#size-cells = <0x1>;
  };

And in my board

&fpga_bridge0 { /* HPS2FPGA */
bridge-enable = <1>;
};

&fpga_bridge1 { /* LWHPS2FPGA */
bridge-enable = <1>;
};

&fpga_bridge2 { /* FPGA2HPS */
bridge-enable = <1>;
};

Hello,
Can you send me the whole dts file? I just want to load the FPGA as before using /def/fpga0 on a DE10 Standard but I can’t get it to work…

At the moment, I’m using the following code:

/dts-v1/ /plugin/;
/ {
fragment@0 {
target-path = “/soc/base-fpga-region”;
#address-cells = <2>;
#size-cells = <1>;
overlay {
#address-cells = <2>;
#size-cells = <1>;
firmware-name = “test.rbf”;
hps_0_bridges: bridge@0xc0000000 {
compatible = “altr,bridge-17.0”, “simple-bus”;
reg = <0xc0000000 0x20000000>;
#address-cells = <2>;
#size-cells = <1>;
ranges = <0x00000000 0x00000000 0xc0000000 0x00100000>,
<0x00000000 0x00100000 0xc0100000 0x00000008>,
<0x00000000 0x00100020 0xc0100020 0x00000020>,
<0x00000000 0x00100060 0xc0100060 0x00000020>,
<0x00000000 0x00100040 0xc0100040 0x00000008>;

            av_master_bridge: unknown@0x000000000 {
                compatible = "unknown,unknown-1.0";
                reg = <0x00000000 0x00000000 0x00100000>;
            }; //end unknown@0x000000000 (av_master_bridge)
            fifo_from_pc: fifo@0x000100000 {
                compatible = "ALTR,fifo-17.0", "ALTR,fifo-1.0";
                reg = <0x00000000 0x00100000 0x00000008>,
                    <0x00000000 0x00100020 0x00000020>;
                reg-names = "in", "in_csr";
            }; //end fifo@0x000100000 (fifo_from_pc)
            fifo_to_pc: fifo@0x000100060 {
                compatible = "ALTR,fifo-17.0", "ALTR,fifo-1.0";
                reg = <0x00000000 0x00100040 0x00000008>,
                    <0x00000000 0x00100060 0x00000020>;
                reg-names = "out", "in_csr";
            }; //end fifo@0x000100060 (fifo_to_pc)
        }; //end bridge@0xc0000000 (hps_0_bridges)
    };
};

};

Then I compile it using:

$ dtc -O dtb -o no_hw_tree.dtbo -b 0 -@ no_hw_tree.dts
Warning (reg_format): “reg” property in /fragment@0/overlay/bridge@0xc0000000 has invalid length
(8 bytes) (#address-cells == 2, #size-cells == 1)

and load it using:

mount -t configfs configfs /config
rmdir /config/device-tree/overlays/test
mkdir /config/device-tree/overlays/test
echo no_hw_tree.dtbo > /config/device-tree/overlays/test/path

The FPGA seams to be loaded:

[   99.601984] fpga_manager fpga0: writing test.rbf to Altera SOCFPGA FPGA Manager

But when I start accessing the hardware using /dev/mem I get a Bus Error and:

[ 165.968920] Unhandled fault: external abort on non-linefetch (0x018) at 0x76eb6060
[ 165.968943] Unhandled fault: external abort on non-linefetch (0x018) at 0x76eb6020
[ 165.968946] pgd = ede60000
[ 165.968954] [76eb6020] *pgd=2ee2f831, *pte=c0100703, *ppte=c0100e33
[ 165.992917] pgd = ede60000
[ 165.995612] [76eb6060] *pgd=2ee2f831, *pte=c0100703, *ppte=c0100e33

When I load the exactly the same image using uBoot, everything works. However, reloading the image while the system is runnig would be much faster.

Finally, I found a working solution:

  1. load_rbf.dts

/dts-v1/ /plugin/;
/ {
fragment@0 {
target-path = “/soc/base-fpga-region”;
#address-cells = <1>;
#size-cells = <1>;
overlay {
firmware-name = “de10_soc.rbf”;
#address-cells = <1>;
#size-cells = <1>;
};
};
};

dtc -O dtb -o load_rbf.dtbo -b 0 -@ load_rbf.dts

Copy load_rbf.dtbo and de10_soc.rbf to /lib/firmware

mount -t configfs configfs /config
rmdir /config/device-tree/overlays/test
mkdir /config/device-tree/overlays/test
echo load_rbf.dtbo > /config/device-tree/overlays/test/path

  1. The magic command is:

devmem 0xff800000 32 0x00000019

I really don’t know what this does. However, by looking at how the bridge is enabled in u-boot:

#bridge_enable_handoff=mw $fpgaintf ${fpgaintf_handoff}; go $fpga2sdram_apply; mw $fpga2sdram ${fpga2sdram_handoff}; mw $axibridge ${axibridge_handoff}; mw $l3remap ${l3remap_handoff}

#mw $fpgaintf ${fpgaintf_handoff};
#fpgaintf=ffd08028
#fpgaintf_handoff=0x00000000
->devmem 0xffd08028 32 0x00000000

#go $fpga2sdram_apply;
->??

#mw $fpga2sdram ${fpga2sdram_handoff};
#fpga2sdram=ffc25080
#fpga2sdram_handoff=0x00000000
->devmem 0xffc25080 32 0x00000000

#mw $axibridge ${axibridge_handoff};
#axibridge=ffd0501c
#axibridge_handoff=0x00000000
->devmem 0xffd0501c 32 0x00000000

#mw $l3remap ${l3remap_handoff}
#l3remap=ff800000
#l3remap_handoff=0x00000019
->devmem 0xff800000 32 0x00000019

I found that this register needs to be written to 0x19 and then there is no bus error any more.

Reading the cv_5v4 manual, p7-32 this appears to be the remap register.
0x19 decodes as

  • lwhps2fpga = 1 => the Lightweight HPS2FPGA AXI Bridge is visible to L3 masters
  • hps2fpga = 1 => the HPS2FPGA AXI Bridge is visible to L3 masters
  • reserved = 0
  • nonmpuzero = 0 => Maps the SDRAM (not the on-chip RAM) to address 0x0 for the non-MPU L3 masters
  • mpuzero = 1 => Maps the On-chip RAM (not the boot ROM) to address 0x0 for the MPU L3 master.

I do not claim to understand this any more than “it’s to do with enabling the bridges”, but hopefully will be a starting point.

Regards,

Jonathan.

Thanks! It seams that reloading the rbf using device tree resets this register without setting the bits again. May be the commands mentioned from Clement_Peron activate these bits also, but I was not able to figure out where I have to insert these in my device tree.

However, using devmem 0xff800000 32 0x00000019 works also, so that’s fine for me!

Regards,
Hannes

Hi @Fabian_red,
I am currently trying to provide another rbf file to the DE10-Nano board to re-program the FPGA from HPS side.
Current kernel version is as below:
< The Angstrom Distribution de10-nano ttyS0

Angstrom v2016.12 - Kernel 4.1.33-ltsi-altera/>
My question is are there any kernel level API’s available for the above kernel that we can directly use to re-program the FPGA? If yes i would like to use them to program the HPS registers.
Reference (though for different version of kernel):
https://www.kernel.org/doc/html/v4.18/driver-api/fpga/fpga-mgr.html

This git repository might help you:

This indeed is implementing the steps given in FPGA Configuration, A-26 Cyclone5 handbook.

I tried to run the generated code on the DE10-nano. But unfortunately, after the step 4. ctrl.nconfigpull bit is set to 1, to pull down the nCONFIG pin of FPGA to enter reset phase. The linux reset is happening and reboot is trigerred after a few seconds. I am sure steps 1-3 are completed and also steps12-13 are met. Here are the register values:


MSEL Pin Config… 0xa
FPGA State… User Phase
cfgwdth Register… 0x1
cdratio Register… 0x3
axicfgen Register… 0x0
Nconfig pull reg… 0x0
CONF DONE… 0x0
nSTATUS… 0x0
ctrl.nce… 0x0
Ctrl.en… 0x1
dclk.dclkcnt… 0x5000
dclkstat.dcntdone… 0x0


Do point to what else is missing here!