lkml.org 
[lkml]   [2020]   [Nov]   [25]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v1 3/6] PCI: brcmstb: Do not turn off regulators if EP can wake up
    Date
    If any downstream device may wake up during S2/S3 suspend, we do not want
    to turn off its power when suspending.

    Signed-off-by: Jim Quinlan <james.quinlan@broadcom.com>
    ---
    drivers/pci/controller/pcie-brcmstb.c | 56 ++++++++++++++++++++++++---
    1 file changed, 50 insertions(+), 6 deletions(-)

    diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
    index 34d6bad07b66..9b888846f0bc 100644
    --- a/drivers/pci/controller/pcie-brcmstb.c
    +++ b/drivers/pci/controller/pcie-brcmstb.c
    @@ -193,6 +193,7 @@ static inline void brcm_pcie_bridge_sw_init_set_7278(struct brcm_pcie *pcie, u32
    static inline void brcm_pcie_bridge_sw_init_set_generic(struct brcm_pcie *pcie, u32 val);
    static inline void brcm_pcie_perst_set_7278(struct brcm_pcie *pcie, u32 val);
    static inline void brcm_pcie_perst_set_generic(struct brcm_pcie *pcie, u32 val);
    +static bool brcm_pcie_link_up(struct brcm_pcie *pcie);

    enum {
    RGR1_SW_INIT_1,
    @@ -302,6 +303,7 @@ struct brcm_pcie {
    void (*bridge_sw_init_set)(struct brcm_pcie *pcie, u32 val);
    struct regulator *regulators[PCIE_REGULATORS_MAX];
    int num_regulators;
    + bool ep_wakeup_capable;
    };

    static int brcm_parse_regulators(struct brcm_pcie *pcie)
    @@ -324,18 +326,60 @@ static int brcm_parse_regulators(struct brcm_pcie *pcie)
    return 0;
    }

    -static void brcm_set_regulators(struct brcm_pcie *pcie, bool on)
    +static int pci_dev_may_wakeup(struct pci_dev *dev, void *data)
    {
    + bool *ret = data;
    +
    + if (device_may_wakeup(&dev->dev)) {
    + *ret = true;
    + dev_dbg(&dev->dev, "disable cancelled for wake-up device\n");
    + }
    + return (int) *ret;
    +}
    +
    +enum {
    + TURN_OFF, /* Turn egulators off, unless an EP is wakeup-capable */
    + TURN_OFF_ALWAYS, /* Turn Regulators off, no exceptions */
    + TURN_ON, /* Turn regulators on, unless pcie->ep_wakeup_capable */
    +};
    +
    +static void brcm_set_regulators(struct brcm_pcie *pcie, int how)
    +{
    + struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
    struct device *dev = pcie->dev;
    int ret, i;

    if (pcie->num_regulators == 0)
    return;

    + if (how == TURN_ON) {
    + if (pcie->ep_wakeup_capable) {
    + /*
    + * We are resuming from a suspend. In the
    + * previous suspend we did not disable the power
    + * supplies, so there is no need to enable them
    + * (and falsely increase their usage count).
    + */
    + pcie->ep_wakeup_capable = false;
    + return;
    + }
    + } else if (how == TURN_OFF) {
    + /*
    + * If at least one device on this bus is enabled as a
    + * wake-up source, do not turn off regulators.
    + */
    + pcie->ep_wakeup_capable = false;
    + if (bridge->bus && brcm_pcie_link_up(pcie)) {
    + pci_walk_bus(bridge->bus, pci_dev_may_wakeup, &pcie->ep_wakeup_capable);
    + if (pcie->ep_wakeup_capable)
    + return;
    + }
    + }
    +
    for (i = 0; i < PCIE_REGULATORS_MAX; i++) {
    if (!pcie->regulators[i])
    continue;
    - if (on) {
    + if (how == TURN_ON) {
    ret = regulator_enable(pcie->regulators[i]);
    dev_dbg(dev, "enable regulator %s (%s)\n",
    ep_regulator_names[i], ret ? "fail" : "pass");
    @@ -1197,7 +1241,7 @@ static int brcm_pcie_suspend(struct device *dev)
    brcm_pcie_turn_off(pcie);
    ret = brcm_phy_stop(pcie);
    clk_disable_unprepare(pcie->clk);
    - brcm_set_regulators(pcie, false);
    + brcm_set_regulators(pcie, TURN_OFF);

    return ret;
    }
    @@ -1210,7 +1254,7 @@ static int brcm_pcie_resume(struct device *dev)
    int ret;

    base = pcie->base;
    - brcm_set_regulators(pcie, true);
    + brcm_set_regulators(pcie, TURN_ON);
    clk_prepare_enable(pcie->clk);

    ret = brcm_phy_start(pcie);
    @@ -1249,7 +1293,7 @@ static void __brcm_pcie_remove(struct brcm_pcie *pcie)
    brcm_phy_stop(pcie);
    reset_control_assert(pcie->rescal);
    clk_disable_unprepare(pcie->clk);
    - brcm_set_regulators(pcie, false);
    + brcm_set_regulators(pcie, TURN_OFF_ALWAYS);
    }

    static int brcm_pcie_remove(struct platform_device *pdev)
    @@ -1338,7 +1382,7 @@ static int brcm_pcie_probe(struct platform_device *pdev)
    return ret;
    }

    - brcm_set_regulators(pcie, true);
    + brcm_set_regulators(pcie, TURN_ON);
    ret = brcm_pcie_setup(pcie);
    if (ret)
    goto fail;
    --
    2.17.1
    [unhandled content-type:application/pkcs7-signature]
    \
     
     \ /
      Last update: 2020-11-25 20:26    [W:3.162 / U:0.140 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site