|
@@ -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);
|
|
|
|