IMX6 PCI with external clocks

Document created by Yuri Muhin Employee on Jun 15, 2017Last modified by ebiz_ws_prod on Dec 13, 2017
Version 6Show Document
  • View in full screen mode

(

  converted from discussion created by Alfred Latypov

 

  IMX6 PCI with external cloks 

)

 

   Hello, I had a problem, to launch a board with an imx6 solo processor with a pci-express, and with external clock. I'll tell you my decision.

On my motherboard there is a pci-switch PI7C9X2G606 from Pericom with 4 endpoints of Intel type 82574 ethernet controller.

I used the Linux kernel version 4.9.16

In the device-tree file, I used the following options to enable external clocks for CLK1 input gate (100MHz). Sorry, I had to change the root imx6 device tree file. See attached (imx6*.dtsi) files. From ..kernel/arch/arm/boot/dts/..

Add anatop external clock source for clocks section, and change clk source for pcie-phy.

...

anaclk1 {
            compatible = "fixed-clock";
            reg = <0>;
            #clock-cells = <0>;
            clock-frequency = <100000000>;  /* 100MHz */
        };

...

Change pcie section

...

        pcie: pcie@0x01000000 {
            compatible = "fsl,imx6q-pcie", "snps,dw-pcie";
            reg = <0x01ffc000 0x04000>,
                  <0x01f00000 0x80000>;
            reg-names = "dbi", "config";
            #address-cells = <3>;
            #size-cells = <2>;
            device_type = "pci";
            ranges = <0x81000000 0 0          0x01e00000 0 0x00100000 /* downstream I/O */
                  0x82000000 0 0x01000000 0x01000000 0 0x00e00000>; /* non-prefetchable memory */
            /* ranges = <0x81000000 0 0          0x01f80000 0 0x00010000
                  0x82000000 0 0x01000000 0x01000000 0 0x00f00000>; */
            num-lanes = <1>;
            interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
            interrupt-names = "msi";
            #interrupt-cells = <1>;
            interrupt-map-mask = <0 0 0 0x7>;
            interrupt-map = <0 0 0 1 &gpc GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
                            <0 0 0 2 &gpc GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
                            <0 0 0 3 &gpc GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
                            <0 0 0 4 &gpc GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
            clocks = <&clks IMX6QDL_CLK_PCIE_AXI>,
                 <&clks IMX6QDL_CLK_LVDS1_IN>,
                 <&clks IMX6QDL_CLK_SATA_REF_100M>;
            clock-names = "pcie", "pcie_bus", "pcie_phy";
            status = "disabled";
        };

...

and add new source clocks dependencies:

....

&clks {
        assigned-clocks = <&clks IMX6QDL_PLL6_BYPASS_SRC>,
                          <&clks IMX6QDL_PLL6_BYPASS>;                          
        assigned-clock-parents = <&clks IMX6QDL_CLK_LVDS1_IN>,
                                 <&clks IMX6QDL_PLL6_BYPASS_SRC>;
        assigned-clock-rates = <100000000>, <100000000>;
};

....

for your board dtsi.

I could not start the pcie-bus with the function Gen2.

 

Next, I needed to change the bus driver (pci-imx6.c), for fine tuning the bus clock frequency. I add MPLL frequency services functions (Thanks for Charle Powe i.MX6Q: Using an external reference for PCIe ):

...

static void imx_pcie_override_phy_mpll(struct pcie_port *pp, u32 mpll_multiplier, u32 ref_clkdiv2)
{
    u32 ref_usb2_en;
    u32 reg1;
    
    
    pr_info("Overriding PCIe PHY MPLL config: multiplier = %d, clkdiv2 = %d\n",
        mpll_multiplier, ref_clkdiv2);
        
    
    // set MPLL to disabled
    ////pcie_phy_write(pp->dbi_base, PCIE_PHY_MPLL_OVRD_IN_LO, 0x0001);
    
    // set MPLL multiplier    
    pcie_phy_write(pp->dbi_base, PCIE_PHY_MPLL_OVRD_IN_LO,
            (0x0001<<9 | (mpll_multiplier<<2)) & 0x03fc);
    
    /*
     * set the ref_clkdiv2.  when this override is enabled it
     * overrides both ref_clkdiv2 and ref_usb2_en.  make sure
     * the overriden ref_usb2_en reflects the original value.
     */     
    pcie_phy_read(pp->dbi_base, PCIE_PHY_ATEOVRD, &reg1);     
    ref_usb2_en = (reg1 >> 1) & 0x1;   

 

    /* set the current value of ref_usb2_en as the override */     
    /* set the ref_clkdiv2 override  */     
    /* enable the ref_clkdiv2 override */     
    pcie_phy_write(pp->dbi_base, PCIE_PHY_ATEOVRD,
            (ref_usb2_en << 1) | ref_clkdiv2 | (0x1 << 2));   
    
    /* enable MPLL */    
    ///pcie_phy_write(pp->dbi_base, PCIE_PHY_MPLL_OVRD_IN_LO, 0x0003);
        
}

...

call this function in pcie_hos_init

...

static void imx6_pcie_host_init(struct pcie_port *pp)
{
    imx6_pcie_assert_core_reset(pp);       
    imx6_pcie_init_phy(pp);       
    imx6_pcie_deassert_core_reset(pp);   
    imx_pcie_override_phy_mpll(pp, 50, 1); /* tune this */     
    dw_pcie_setup_rc(pp);

    imx6_pcie_establish_link(pp); 

    if (IS_ENABLED(CONFIG_PCI_MSI))
        dw_pcie_msi_init(pp);
}

...

 

 

See documentation for p.p. IMX6DLRM 50.5.1.2.

Tune <pci_hotplug_mem_size> global variable for optimal pci window sizes enumeration.

See for my imx6_add_pcie_port call.

 

If you use a FEC module, it will stop working. You must use an external clock as specified in the documentation (http://cache.freescale.com/files/32bit/doc/user_guide/IMX6DQ6SDLHDG.pdf ). Changes are shown in the attached dtsi file.

For clocks segment

...

rmii_clk: clock@0 {
            compatible = "fixed-clock";
            reg = <0>;
            #clock-cells = <0>;
            clock-frequency = <50000000>;  /* 50MHz */
        };

...

and for fec:

...

fec: ethernet@02188000 {
                compatible = "fsl,imx6q-fec";
                reg = <0x02188000 0x4000>;
                interrupts-extended =
                    <&intc 0 118 IRQ_TYPE_LEVEL_HIGH>,
                    <&intc 0 119 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&clks IMX6QDL_CLK_ENET>,
                     <&clks IMX6QDL_CLK_ENET>,
                     <&rmii_clk>;
                clock-names = "ipg", "ahb", "ptp";
                status = "disabled";
            };

...

If they are not required, disable this editing this file.

 

Thanks for all. Sorry for my bad English.

Alfred <muksunoved@mail.ru>

 

 

 

This document was generated from the following discussion: IMX6 PCI with external cloks

Original Attachment has been moved to: forum.tar.bz2

Attachments

    Outcomes