]> www.infradead.org Git - users/willy/xarray.git/commitdiff
Merge branch 'pci/controller/layerscape'
authorBjorn Helgaas <bhelgaas@google.com>
Mon, 15 Jan 2024 18:10:38 +0000 (12:10 -0600)
committerBjorn Helgaas <bhelgaas@google.com>
Mon, 15 Jan 2024 18:10:38 +0000 (12:10 -0600)
- Add suspend/resume support for Layerscape LS1043a, including
  software-managed PME_Turn_Off and transitions between L0, L2/L3_Ready
  Link states (Frank Li)

* pci/controller/layerscape:
  PCI: layerscape: Add suspend/resume for ls1043a
  PCI: layerscape(ep): Rename pf_* as pf_lut_*
  PCI: layerscape: Add suspend/resume for ls1021a
  PCI: layerscape: Add function pointer for exit_from_l2()

1  2 
drivers/pci/controller/dwc/pci-layerscape-ep.c
drivers/pci/controller/dwc/pci-layerscape.c

index 0c3d7ef729cb6775216e92bedb2c46dd797c4837,7cdada200de7ea357fd6d0f2996c3105b7bd69a3..ee6f5256813374bdf656bef4f9b96e1b8760d1b5
@@@ -168,13 -190,116 +190,116 @@@ static int ls_pcie_host_init(struct dw_
        return 0;
  }
  
+ static void scfg_pcie_send_turnoff_msg(struct regmap *scfg, u32 reg, u32 mask)
+ {
+       /* Send PME_Turn_Off message */
+       regmap_write_bits(scfg, reg, mask, mask);
+       /*
+        * There is no specific register to check for PME_To_Ack from endpoint.
+        * So on the safe side, wait for PCIE_PME_TO_L2_TIMEOUT_US.
+        */
+       mdelay(PCIE_PME_TO_L2_TIMEOUT_US/1000);
+       /*
+        * Layerscape hardware reference manual recommends clearing the PMXMTTURNOFF bit
+        * to complete the PME_Turn_Off handshake.
+        */
+       regmap_write_bits(scfg, reg, mask, 0);
+ }
+ static void ls1021a_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
+ {
+       struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+       struct ls_pcie *pcie = to_ls_pcie(pci);
+       scfg_pcie_send_turnoff_msg(pcie->scfg, SCFG_PEXPMWRCR(pcie->index), PMXMTTURNOFF);
+ }
+ static int scfg_pcie_exit_from_l2(struct regmap *scfg, u32 reg, u32 mask)
+ {
+       /* Reset the PEX wrapper to bring the link out of L2 */
+       regmap_write_bits(scfg, reg, mask, mask);
+       regmap_write_bits(scfg, reg, mask, 0);
+       return 0;
+ }
+ static int ls1021a_pcie_exit_from_l2(struct dw_pcie_rp *pp)
+ {
+       struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+       struct ls_pcie *pcie = to_ls_pcie(pci);
+       return scfg_pcie_exit_from_l2(pcie->scfg, SCFG_PEXSFTRSTCR, PEXSR(pcie->index));
+ }
+ static void ls1043a_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
+ {
+       struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+       struct ls_pcie *pcie = to_ls_pcie(pci);
+       scfg_pcie_send_turnoff_msg(pcie->scfg, SCFG_PEXPMECR, PEXPME(pcie->index));
+ }
+ static int ls1043a_pcie_exit_from_l2(struct dw_pcie_rp *pp)
+ {
+       struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+       struct ls_pcie *pcie = to_ls_pcie(pci);
+       u32 val;
+       /*
+        * Reset the PEX wrapper to bring the link out of L2.
+        * LDBG_WE: allows the user to have write access to the PEXDBG[SR] for both setting and
+        *          clearing the soft reset on the PEX module.
+        * LDBG_SR: When SR is set to 1, the PEX module enters soft reset.
+        */
+       val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_LDBG);
+       val |= LDBG_WE;
+       ls_pcie_pf_lut_writel(pcie, LS_PCIE_LDBG, val);
+       val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_LDBG);
+       val |= LDBG_SR;
+       ls_pcie_pf_lut_writel(pcie, LS_PCIE_LDBG, val);
+       val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_LDBG);
+       val &= ~LDBG_SR;
+       ls_pcie_pf_lut_writel(pcie, LS_PCIE_LDBG, val);
+       val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_LDBG);
+       val &= ~LDBG_WE;
+       ls_pcie_pf_lut_writel(pcie, LS_PCIE_LDBG, val);
+       return 0;
+ }
  static const struct dw_pcie_host_ops ls_pcie_host_ops = {
 -      .host_init = ls_pcie_host_init,
 +      .init = ls_pcie_host_init,
        .pme_turn_off = ls_pcie_send_turnoff_msg,
  };
  
 -      .host_init = ls_pcie_host_init,
+ static const struct dw_pcie_host_ops ls1021a_pcie_host_ops = {
++      .init = ls_pcie_host_init,
+       .pme_turn_off = ls1021a_pcie_send_turnoff_msg,
+ };
  static const struct ls_pcie_drvdata ls1021a_drvdata = {
-       .pm_support = false,
+       .pm_support = true,
+       .scfg_support = true,
+       .ops = &ls1021a_pcie_host_ops,
+       .exit_from_l2 = ls1021a_pcie_exit_from_l2,
+ };
+ static const struct dw_pcie_host_ops ls1043a_pcie_host_ops = {
 -      .host_init = ls_pcie_host_init,
++      .init = ls_pcie_host_init,
+       .pme_turn_off = ls1043a_pcie_send_turnoff_msg,
+ };
+ static const struct ls_pcie_drvdata ls1043a_drvdata = {
+       .pf_lut_off = 0x10000,
+       .pm_support = true,
+       .scfg_support = true,
+       .ops = &ls1043a_pcie_host_ops,
+       .exit_from_l2 = ls1043a_pcie_exit_from_l2,
  };
  
  static const struct ls_pcie_drvdata layerscape_drvdata = {