Device Family: Intel® Stratix® 10 SX

Type: Answers, How-To

Area: Embedded


Last Modified: October 17, 2018
Version Found: v18.1
Bug ID: FB: 559364;

How do I update the Linux Device Tree for Intel® Stratix® 10 SX devices to match the clock settings in Quartus® Prime Pro Platform Designer?

Description

SoC FPGA Linux Kernel Versions 4.17 June 2018 and later, and 4.18 and later:   

  • Only the top level reference clock frequencies for the Intel® Stratix® 10 SX are specified in the Linux Device Tree. 
  • The clock tree setup as set on the Stratix 10 HPS Component in the Intel® Quartus® Prime Pro Platform Designer design is loaded from the FPGA bitstream by the Clock Manager Driver.  

For SoC FPGA Linux Kernel version 4.17 (pre June 2018) and earlier: 

The Linux Device Tree contains information on the full clocking structure of the Intel® Stratix® 10 SX,  and must reflect the clock setup in the Stratix 10 HPS Component, in the Intel® Quartus® Prime Pro Platform Designer design.

If the clocking structure is not updated to reflect your board and design, peripherals may operate incorrectly in Linux. 

The Linux kernel contains a generic top level device tree  and an example device tree for the  Intel Stratix 10 SX Development kit:

arch/arm64/boot/dts/altera/

socfpga_stratix10.dtsi     #Generic top level device tree

Socfpga_stratix10_socdk.dts     # Example device tree for the Intel Stratix 10 SX Development kit, Golden Hardware Reference Design (GHRD) and Golden Software Reference Design (GSRD)

 

Note: 

  • The Golden Hardware Reference Design (GHRD) is shipped with Intel FPGA SoC EDS in the examples/hardware/ folder
  • The Golden Software Reference Design (GSRD) can be downloaded from Rocketboards.org  https://rocketboards.org/foswiki/Documentation/GSRD

Workaround/Fix

SoC FPGA Linux Kernel Versions 4.17 June 2018 and later, and 4.18 and later:   

Only the top level reference clock frequencies for the Intel® Stratix® 10 SX are specified in the Linux Device Tree.

clkmgr@ffd10000 {

clocks {   

osc1 {        clock-frequency = <25000000>;        };

};

};

 

For SoC FPGA Linux Kernel version 4.17 (pre June 2018) and earlier: 

The socfpga_stratix10.dtsi shows the possible settings for each clock tree component.   

peri_emacb_clk: peri_emacb_clk@ec {

                        #clock-cells = <0>;

                        compatible = "altr,socfpga-s10-perip-clk";

                        clocks = <&main_pll>, <&periph_pll>, <&osc1>, <&cb_intosc_hs_div2_clk>,  <&f2s_free_clk>;

                        reg = <0xc0>;

                    };

 

Below is part of the tree showing the clock supplying the UART and I2C.  Notice that by default, the source clocks for the IP are set, but their connection up the tree is not set.  The  the IP set there clocks to be l4_sp_clock,  which is driven by noc_clk,  but noc_clk and noc_free_clk does not have a defined driver:

:

main_noc_base_clk: main_noc_base_clk {

                        …

                        clocks = <&main_pll>;

                        …

                    };

noc_free_clk: noc_free_clk@4c {

    …

    clocks = <&main_noc_base_clk>, <&peri_noc_base_clk>,

         <&osc1>, <&cb_intosc_hs_div2_clk>,

         <&f2s_free_clk>;

    …

};

noc_clk: noc_clk@30 {

    …

    clocks = <&noc_free_clk>, <&boot_clk>;

    …

};

l4_sp_clk: l4_sp_clk {

    …

    clocks = <&noc_clk>;

    …

};

i2c1: i2c@ffc02900 {

    …

    clocks = <&l4_sp_clk>;

    …

};

uart0: serial0@ffc02000 {

    …

    clocks = <&l4_sp_clk>;

    …

};

 

The required settings can be applied via the .dts file for your board using the syntax shown below: 

 

soc {

clkmgr@ffd10000 {

clocks {

    osc1 {

        clock-frequency = <25000000>;

        };

    periph_pll@e4 {

        peri_emaca_clk@e8{

            clocks = <&periph_pll>;

            };

                    peri_emacb_clk@ec {

            clocks = <&periph_pll>;

            };

        };

    noc_free_clk@4c {

        clocks = <&main_noc_base_clk>;

        };

    noc_clk@30 {

        clocks = <&noc_free_clk>;

        };

    emaca_free_clk {

        clocks = <&peri_emaca_clk>;

        };

    emacb_free_clk {

        clocks = <&peri_emacb_clk>;

        };

    emac0_clk {

        clocks = <&emaca_free_clk>;

        };

    emac1_clk {

        clocks = <&emaca_free_clk>;

        };

    emac2_clk{

        clocks = <&emaca_free_clk>;

        };

    };

};

};

};

 

The above fixes the problem for the UART / I2C and also defines some Ethernet clocks.   The clock tree is now complete from UART / I2C up to the main PLL..   This means that the logic that sets up the UART and I2C  based on the source clock frequency can make the right calculation.  

For more information on Device Tree see the Linux Kernel documentation.