From: Alyssa Rosenzweig <alyssa@xxxxxxxxxxxxx> Apple's PCIe controller requires clocks to be configured in order to bring up the hardware. Add the register pokes required to do so. Adapted from Corellium's driver via Mark Kettenis's U-Boot patches. Co-developed-by: Stan Skowronek <stan@xxxxxxxxxxxxx> Signed-off-by: Stan Skowronek <stan@xxxxxxxxxxxxx> Signed-off-by: Alyssa Rosenzweig <alyssa@xxxxxxxxxxxxx> Signed-off-by: Marc Zyngier <maz@xxxxxxxxxx> Link: https://lore.kernel.org/r/20210816031621.240268-4-alyssa@xxxxxxxxxxxxx --- drivers/pci/controller/pcie-apple.c | 44 +++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/drivers/pci/controller/pcie-apple.c b/drivers/pci/controller/pcie-apple.c index f3c414950a10..dabbfc2e1fb0 100644 --- a/drivers/pci/controller/pcie-apple.c +++ b/drivers/pci/controller/pcie-apple.c @@ -132,6 +132,46 @@ static inline void rmwl(u32 clr, u32 set, void __iomem *addr) writel_relaxed((readl_relaxed(addr) & ~clr) | set, addr); } +static int apple_pcie_setup_refclk(struct apple_pcie *pcie, + struct apple_pcie_port *port) +{ + u32 stat; + int res; + + res = readl_relaxed_poll_timeout(pcie->base + CORE_RC_PHYIF_STAT, stat, + stat & CORE_RC_PHYIF_STAT_REFCLK, + 100, 50000); + if (res < 0) + return res; + + rmwl(0, CORE_LANE_CTL_CFGACC, pcie->base + CORE_LANE_CTL(port->idx)); + rmwl(0, CORE_LANE_CFG_REFCLK0REQ, pcie->base + CORE_LANE_CFG(port->idx)); + + res = readl_relaxed_poll_timeout(pcie->base + CORE_LANE_CFG(port->idx), + stat, stat & CORE_LANE_CFG_REFCLK0ACK, + 100, 50000); + if (res < 0) + return res; + + rmwl(0, CORE_LANE_CFG_REFCLK1, pcie->base + CORE_LANE_CFG(port->idx)); + res = readl_relaxed_poll_timeout(pcie->base + CORE_LANE_CFG(port->idx), + stat, stat & CORE_LANE_CFG_REFCLK1, + 100, 50000); + + if (res < 0) + return res; + + rmwl(CORE_LANE_CTL_CFGACC, 0, pcie->base + CORE_LANE_CTL(port->idx)); + + /* Flush writes before enabling the clocks */ + dma_wmb(); + + rmwl(0, CORE_LANE_CFG_REFCLKEN, pcie->base + CORE_LANE_CFG(port->idx)); + rmwl(0, PORT_REFCLK_EN, port->base + PORT_REFCLK); + + return 0; +} + static int apple_pcie_setup_port(struct apple_pcie *pcie, struct device_node *np) { @@ -165,6 +205,10 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie, rmwl(0, PORT_APPCLK_EN, port + PORT_APPCLK); + ret = apple_pcie_setup_refclk(pcie, port); + if (ret < 0) + return ret; + rmwl(0, PORT_PERST_OFF, port->base + PORT_PERST); gpiod_set_value(reset, 1); -- 2.30.2