Load fpga rbf from device tree overlay example?


I have managed to get a 4.9.20 kernel and 2017 u-boot going on my de0-nano-soc board. I’d like to be able to load the FGPA from linux. Recent versions of the kernel seem to work with device tree overlays to accomplish that.

I searched the net but could not find a nice working example. Is there an example for dt overlay which can load a simple rbf (only blinking leds, no interaction with Linux).?



Try this load overlay example for the base: look here.
Or you can load FPGA manually with hps regs without drivers.


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?


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

How to program FPGA from HPS (de10-nano)

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.”


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 :


/ {
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.



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>,
  	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>;


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};
->devmem 0xffd08028 32 0x00000000

#go $fpga2sdram_apply;

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

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

#mw $l3remap ${l3remap_handoff}
->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.




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!