PCI: apple: Set up reference clocks when probing

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@corellium.com>
Link: https://lore.kernel.org/r/20210929163847.2807812-6-maz@kernel.org
Signed-off-by: Stan Skowronek <stan@corellium.com>
Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
This commit is contained in:
Alyssa Rosenzweig 2021-09-29 17:38:38 +01:00 committed by Bjorn Helgaas
parent 1e33888fbe
commit 1512f908f3

View File

@ -132,6 +132,48 @@ static void rmw_set(u32 set, void __iomem *addr)
writel_relaxed(readl_relaxed(addr) | set, addr);
}
static void rmw_clear(u32 clr, void __iomem *addr)
{
writel_relaxed(readl_relaxed(addr) & ~clr, 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;
rmw_set(CORE_LANE_CTL_CFGACC, pcie->base + CORE_LANE_CTL(port->idx));
rmw_set(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;
rmw_set(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;
rmw_clear(CORE_LANE_CTL_CFGACC, pcie->base + CORE_LANE_CTL(port->idx));
rmw_set(CORE_LANE_CFG_REFCLKEN, pcie->base + CORE_LANE_CFG(port->idx));
rmw_set(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 +207,10 @@ static int apple_pcie_setup_port(struct apple_pcie *pcie,
rmw_set(PORT_APPCLK_EN, port->base + PORT_APPCLK);
ret = apple_pcie_setup_refclk(pcie, port);
if (ret < 0)
return ret;
rmw_set(PORT_PERST_OFF, port->base + PORT_PERST);
gpiod_set_value(reset, 1);