( 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, ®1); 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 <
[email protected]> This document was generated from the following discussion: IMX6 PCI with external cloks