On Tue, Jul 31, 2018 at 12:21:49PM +0200, Lucas Stach wrote: > The power up defaults of the MPLL are designed for the standard 125MHz > refclock derived from the ENET PLL. As this clock has a jitter that > violates the PCIe Gen2 timing requirements, some board designs use > an external reference clock generator. Those clock generators may > output a clock at a different rate than what the MPLL expects > (usually a 100MHz clock, to re-use the PCIe bus clock). > > In that case the MPLL must be reconfigured via overrides to use > different refclock dividers and loop multipliers. The i.MX6 > reference manual lists both 100MHz and 200MHz as supported refclock > rates and the associated mult and div values. > > Only the 100MHz setup has been tested on a real board, but since the > 200MHz setup only differs in the used pre-divider it seems safe to > add it now. > > Signed-off-by: Lucas Stach <l.stach@xxxxxxxxxxxxxx> > --- > drivers/pci/controller/dwc/pci-imx6.c | 55 +++++++++++++++++++++++++++ > 1 file changed, 55 insertions(+) Applied to pci/dwc for v4.20, thanks. Lorenzo > diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c > index 80f604602783..c481c61a41b8 100644 > --- a/drivers/pci/controller/dwc/pci-imx6.c > +++ b/drivers/pci/controller/dwc/pci-imx6.c > @@ -97,6 +97,16 @@ struct imx6_pcie { > #define PORT_LOGIC_SPEED_CHANGE (0x1 << 17) > > /* PHY registers (not memory-mapped) */ > +#define PCIE_PHY_ATEOVRD 0x10 > +#define PCIE_PHY_ATEOVRD_EN (0x1 << 2) > +#define PCIE_PHY_ATEOVRD_REF_CLKDIV_SHIFT 0 > +#define PCIE_PHY_ATEOVRD_REF_CLKDIV_MASK 0x1 > + > +#define PCIE_PHY_MPLL_OVRD_IN_LO 0x11 > +#define PCIE_PHY_MPLL_MULTIPLIER_SHIFT 2 > +#define PCIE_PHY_MPLL_MULTIPLIER_MASK 0x7f > +#define PCIE_PHY_MPLL_MULTIPLIER_OVRD (0x1 << 9) > + > #define PCIE_PHY_RX_ASIC_OUT 0x100D > #define PCIE_PHY_RX_ASIC_OUT_VALID (1 << 0) > > @@ -508,6 +518,50 @@ static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie) > IMX6Q_GPR12_DEVICE_TYPE, PCI_EXP_TYPE_ROOT_PORT << 12); > } > > +static int imx6_setup_phy_mpll(struct imx6_pcie *imx6_pcie) > +{ > + unsigned long phy_rate = clk_get_rate(imx6_pcie->pcie_phy); > + int mult, div; > + u32 val; > + > + switch (phy_rate) { > + case 125000000: > + /* > + * The default settings of the MPLL are for a 125MHz input > + * clock, so no need to reconfigure anything in that case. > + */ > + return 0; > + case 100000000: > + mult = 25; > + div = 0; > + break; > + case 200000000: > + mult = 25; > + div = 1; > + break; > + default: > + dev_err(imx6_pcie->pci->dev, > + "Unsupported PHY reference clock rate %lu\n", phy_rate); > + return -EINVAL; > + } > + > + pcie_phy_read(imx6_pcie, PCIE_PHY_MPLL_OVRD_IN_LO, &val); > + val &= ~(PCIE_PHY_MPLL_MULTIPLIER_MASK << > + PCIE_PHY_MPLL_MULTIPLIER_SHIFT); > + val |= mult << PCIE_PHY_MPLL_MULTIPLIER_SHIFT; > + val |= PCIE_PHY_MPLL_MULTIPLIER_OVRD; > + pcie_phy_write(imx6_pcie, PCIE_PHY_MPLL_OVRD_IN_LO, val); > + > + pcie_phy_read(imx6_pcie, PCIE_PHY_ATEOVRD, &val); > + val &= ~(PCIE_PHY_ATEOVRD_REF_CLKDIV_MASK << > + PCIE_PHY_ATEOVRD_REF_CLKDIV_SHIFT); > + val |= div << PCIE_PHY_ATEOVRD_REF_CLKDIV_SHIFT; > + val |= PCIE_PHY_ATEOVRD_EN; > + pcie_phy_write(imx6_pcie, PCIE_PHY_ATEOVRD, val); > + > + return 0; > +} > + > static int imx6_pcie_wait_for_link(struct imx6_pcie *imx6_pcie) > { > struct dw_pcie *pci = imx6_pcie->pci; > @@ -632,6 +686,7 @@ static int imx6_pcie_host_init(struct pcie_port *pp) > imx6_pcie_assert_core_reset(imx6_pcie); > imx6_pcie_init_phy(imx6_pcie); > imx6_pcie_deassert_core_reset(imx6_pcie); > + imx6_setup_phy_mpll(imx6_pcie); > dw_pcie_setup_rc(pp); > imx6_pcie_establish_link(imx6_pcie); > > -- > 2.18.0 >