Loading drivers/platform/msm/ep_pcie/ep_pcie_com.h +2 −1 Original line number Diff line number Diff line Loading @@ -406,7 +406,6 @@ struct ep_pcie_dev_t { bool config_mmio_init; bool enumerated; enum ep_pcie_link_status link_status; bool perst_deast; bool power_on; bool suspending; bool l23_ready; Loading @@ -414,6 +413,8 @@ struct ep_pcie_dev_t { struct ep_pcie_msi_config msi_cfg; bool no_notify; bool client_ready; atomic_t ep_pcie_dev_wake; atomic_t perst_deast; struct ep_pcie_register_event *event_reg; struct work_struct handle_perst_work; Loading drivers/platform/msm/ep_pcie/ep_pcie_core.c +64 −8 Original line number Diff line number Diff line Loading @@ -1805,7 +1805,7 @@ int ep_pcie_core_enable_endpoint(enum ep_pcie_options opt) ret = EP_PCIE_ERROR; goto link_fail; } else { dev->perst_deast = true; atomic_set(&dev->perst_deast, 1); if (opt & EP_PCIE_OPT_AST_WAKE) { /* deassert PCIe WAKE# */ EP_PCIE_DBG(dev, Loading Loading @@ -1971,11 +1971,19 @@ int ep_pcie_core_enable_endpoint(enum ep_pcie_options opt) int ep_pcie_core_disable_endpoint(void) { int rc = 0; u32 val = 0; unsigned long irqsave_flags; struct ep_pcie_dev_t *dev = &ep_pcie_dev; EP_PCIE_DBG(dev, "PCIe V%d\n", dev->rev); mutex_lock(&dev->setup_mtx); if (atomic_read(&dev->perst_deast)) { EP_PCIE_DBG(dev, "PCIe V%d: PERST is de-asserted, exiting disable\n", dev->rev); goto out; } if (!dev->power_on) { EP_PCIE_DBG(dev, Loading @@ -1992,9 +2000,25 @@ int ep_pcie_core_disable_endpoint(void) dev->rev); } val = readl_relaxed(dev->elbi + PCIE20_ELBI_SYS_STTS); EP_PCIE_DBG(dev, "PCIe V%d: LTSSM_STATE during disable:0x%x\n", dev->rev, (val >> 0xC) & 0x3f); ep_pcie_pipe_clk_deinit(dev); ep_pcie_clk_deinit(dev); ep_pcie_vreg_deinit(dev); spin_lock_irqsave(&dev->isr_lock, irqsave_flags); if (atomic_read(&dev->ep_pcie_dev_wake) && !atomic_read(&dev->perst_deast)) { EP_PCIE_DBG(dev, "PCIe V%d: Released wakelock\n", dev->rev); atomic_set(&dev->ep_pcie_dev_wake, 0); pm_relax(&dev->pdev->dev); } else { EP_PCIE_DBG(dev, "PCIe V%d: Bail, Perst-assert:%d wake:%d\n", dev->rev, atomic_read(&dev->perst_deast), atomic_read(&dev->ep_pcie_dev_wake)); } spin_unlock_irqrestore(&dev->isr_lock, irqsave_flags); out: mutex_unlock(&dev->setup_mtx); return rc; Loading Loading @@ -2251,12 +2275,25 @@ static void handle_d3cold_func(struct work_struct *work) { struct ep_pcie_dev_t *dev = container_of(work, struct ep_pcie_dev_t, handle_d3cold_work); unsigned long irqsave_flags; EP_PCIE_DBG(dev, "PCIe V%d: shutdown PCIe link due to PERST assertion before BME is set\n", dev->rev); ep_pcie_core_disable_endpoint(); dev->no_notify = false; spin_lock_irqsave(&dev->isr_lock, irqsave_flags); if (atomic_read(&dev->ep_pcie_dev_wake) && !atomic_read(&dev->perst_deast)) { atomic_set(&dev->ep_pcie_dev_wake, 0); pm_relax(&dev->pdev->dev); EP_PCIE_DBG(dev, "PCIe V%d: Released wakelock\n", dev->rev); } else { EP_PCIE_DBG(dev, "PCIe V%d: Bail, Perst-assert:%d wake:%d\n", dev->rev, atomic_read(&dev->perst_deast), atomic_read(&dev->ep_pcie_dev_wake)); } spin_unlock_irqrestore(&dev->isr_lock, irqsave_flags); } static void handle_bme_func(struct work_struct *work) Loading Loading @@ -2294,14 +2331,24 @@ static irqreturn_t ep_pcie_handle_perst_irq(int irq, void *data) } if (perst) { dev->perst_deast = true; atomic_set(&dev->perst_deast, 1); dev->perst_deast_counter++; /* * Hold a wakelock to avoid missing BME and other * interrupts if apps goes into suspend before BME is set. */ if (!atomic_read(&dev->ep_pcie_dev_wake)) { pm_stay_awake(&dev->pdev->dev); atomic_set(&dev->ep_pcie_dev_wake, 1); EP_PCIE_DBG(dev, "PCIe V%d: Acquired wakelock\n", dev->rev); } EP_PCIE_DBG(dev, "PCIe V%d: No. %ld PERST deassertion\n", dev->rev, dev->perst_deast_counter); ep_pcie_notify_event(dev, EP_PCIE_EVENT_PM_RST_DEAST); } else { dev->perst_deast = false; atomic_set(&dev->perst_deast, 0); dev->perst_ast_counter++; EP_PCIE_DBG(dev, "PCIe V%d: No. %ld PERST assertion\n", Loading Loading @@ -2552,13 +2599,14 @@ int32_t ep_pcie_irq_init(struct ep_pcie_dev_t *dev) * based on the next expected level of the gpio */ if (gpio_get_value(dev->gpio[EP_PCIE_GPIO_PERST].num) == 1) dev->perst_deast = true; atomic_set(&dev->perst_deast, 1); /* register handler for PERST interrupt */ perst_irq = gpio_to_irq(dev->gpio[EP_PCIE_GPIO_PERST].num); ret = devm_request_irq(pdev, perst_irq, ep_pcie_handle_perst_irq, ((dev->perst_deast ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH) ((atomic_read(&dev->perst_deast) ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH) | IRQF_EARLY_RESUME), "ep_pcie_perst", dev); if (ret) { Loading Loading @@ -2953,7 +3001,7 @@ static int ep_pcie_core_wakeup_host(enum ep_pcie_event event) if (event == EP_PCIE_EVENT_PM_D3_HOT) ep_pcie_core_issue_inband_pme(); if (dev->perst_deast && !dev->l23_ready) { if (atomic_read(&dev->perst_deast) && !dev->l23_ready) { EP_PCIE_ERR(dev, "PCIe V%d: request to assert WAKE# when PERST is de-asserted and D3hot is not received\n", dev->rev); Loading @@ -2964,7 +3012,7 @@ static int ep_pcie_core_wakeup_host(enum ep_pcie_event event) EP_PCIE_DBG(dev, "PCIe V%d: No. %ld to assert PCIe WAKE#; perst is %s de-asserted; D3hot is %s received\n", dev->rev, dev->wake_counter, dev->perst_deast ? "" : "not", atomic_read(&dev->perst_deast) ? "" : "not", dev->l23_ready ? "" : "not"); /* * Assert WAKE# GPIO until link is back to L0. Loading Loading @@ -3219,6 +3267,14 @@ static int ep_pcie_probe(struct platform_device *pdev) goto irq_failure; } /* * Wakelock is needed to avoid missing BME and other * interrupts if apps goes into suspend before host * sets them. */ device_init_wakeup(&ep_pcie_dev.pdev->dev, true); atomic_set(&ep_pcie_dev.ep_pcie_dev_wake, 0); if (ep_pcie_dev.perst_enum && !gpio_get_value(ep_pcie_dev.gpio[EP_PCIE_GPIO_PERST].num)) { EP_PCIE_DBG2(&ep_pcie_dev, Loading Loading
drivers/platform/msm/ep_pcie/ep_pcie_com.h +2 −1 Original line number Diff line number Diff line Loading @@ -406,7 +406,6 @@ struct ep_pcie_dev_t { bool config_mmio_init; bool enumerated; enum ep_pcie_link_status link_status; bool perst_deast; bool power_on; bool suspending; bool l23_ready; Loading @@ -414,6 +413,8 @@ struct ep_pcie_dev_t { struct ep_pcie_msi_config msi_cfg; bool no_notify; bool client_ready; atomic_t ep_pcie_dev_wake; atomic_t perst_deast; struct ep_pcie_register_event *event_reg; struct work_struct handle_perst_work; Loading
drivers/platform/msm/ep_pcie/ep_pcie_core.c +64 −8 Original line number Diff line number Diff line Loading @@ -1805,7 +1805,7 @@ int ep_pcie_core_enable_endpoint(enum ep_pcie_options opt) ret = EP_PCIE_ERROR; goto link_fail; } else { dev->perst_deast = true; atomic_set(&dev->perst_deast, 1); if (opt & EP_PCIE_OPT_AST_WAKE) { /* deassert PCIe WAKE# */ EP_PCIE_DBG(dev, Loading Loading @@ -1971,11 +1971,19 @@ int ep_pcie_core_enable_endpoint(enum ep_pcie_options opt) int ep_pcie_core_disable_endpoint(void) { int rc = 0; u32 val = 0; unsigned long irqsave_flags; struct ep_pcie_dev_t *dev = &ep_pcie_dev; EP_PCIE_DBG(dev, "PCIe V%d\n", dev->rev); mutex_lock(&dev->setup_mtx); if (atomic_read(&dev->perst_deast)) { EP_PCIE_DBG(dev, "PCIe V%d: PERST is de-asserted, exiting disable\n", dev->rev); goto out; } if (!dev->power_on) { EP_PCIE_DBG(dev, Loading @@ -1992,9 +2000,25 @@ int ep_pcie_core_disable_endpoint(void) dev->rev); } val = readl_relaxed(dev->elbi + PCIE20_ELBI_SYS_STTS); EP_PCIE_DBG(dev, "PCIe V%d: LTSSM_STATE during disable:0x%x\n", dev->rev, (val >> 0xC) & 0x3f); ep_pcie_pipe_clk_deinit(dev); ep_pcie_clk_deinit(dev); ep_pcie_vreg_deinit(dev); spin_lock_irqsave(&dev->isr_lock, irqsave_flags); if (atomic_read(&dev->ep_pcie_dev_wake) && !atomic_read(&dev->perst_deast)) { EP_PCIE_DBG(dev, "PCIe V%d: Released wakelock\n", dev->rev); atomic_set(&dev->ep_pcie_dev_wake, 0); pm_relax(&dev->pdev->dev); } else { EP_PCIE_DBG(dev, "PCIe V%d: Bail, Perst-assert:%d wake:%d\n", dev->rev, atomic_read(&dev->perst_deast), atomic_read(&dev->ep_pcie_dev_wake)); } spin_unlock_irqrestore(&dev->isr_lock, irqsave_flags); out: mutex_unlock(&dev->setup_mtx); return rc; Loading Loading @@ -2251,12 +2275,25 @@ static void handle_d3cold_func(struct work_struct *work) { struct ep_pcie_dev_t *dev = container_of(work, struct ep_pcie_dev_t, handle_d3cold_work); unsigned long irqsave_flags; EP_PCIE_DBG(dev, "PCIe V%d: shutdown PCIe link due to PERST assertion before BME is set\n", dev->rev); ep_pcie_core_disable_endpoint(); dev->no_notify = false; spin_lock_irqsave(&dev->isr_lock, irqsave_flags); if (atomic_read(&dev->ep_pcie_dev_wake) && !atomic_read(&dev->perst_deast)) { atomic_set(&dev->ep_pcie_dev_wake, 0); pm_relax(&dev->pdev->dev); EP_PCIE_DBG(dev, "PCIe V%d: Released wakelock\n", dev->rev); } else { EP_PCIE_DBG(dev, "PCIe V%d: Bail, Perst-assert:%d wake:%d\n", dev->rev, atomic_read(&dev->perst_deast), atomic_read(&dev->ep_pcie_dev_wake)); } spin_unlock_irqrestore(&dev->isr_lock, irqsave_flags); } static void handle_bme_func(struct work_struct *work) Loading Loading @@ -2294,14 +2331,24 @@ static irqreturn_t ep_pcie_handle_perst_irq(int irq, void *data) } if (perst) { dev->perst_deast = true; atomic_set(&dev->perst_deast, 1); dev->perst_deast_counter++; /* * Hold a wakelock to avoid missing BME and other * interrupts if apps goes into suspend before BME is set. */ if (!atomic_read(&dev->ep_pcie_dev_wake)) { pm_stay_awake(&dev->pdev->dev); atomic_set(&dev->ep_pcie_dev_wake, 1); EP_PCIE_DBG(dev, "PCIe V%d: Acquired wakelock\n", dev->rev); } EP_PCIE_DBG(dev, "PCIe V%d: No. %ld PERST deassertion\n", dev->rev, dev->perst_deast_counter); ep_pcie_notify_event(dev, EP_PCIE_EVENT_PM_RST_DEAST); } else { dev->perst_deast = false; atomic_set(&dev->perst_deast, 0); dev->perst_ast_counter++; EP_PCIE_DBG(dev, "PCIe V%d: No. %ld PERST assertion\n", Loading Loading @@ -2552,13 +2599,14 @@ int32_t ep_pcie_irq_init(struct ep_pcie_dev_t *dev) * based on the next expected level of the gpio */ if (gpio_get_value(dev->gpio[EP_PCIE_GPIO_PERST].num) == 1) dev->perst_deast = true; atomic_set(&dev->perst_deast, 1); /* register handler for PERST interrupt */ perst_irq = gpio_to_irq(dev->gpio[EP_PCIE_GPIO_PERST].num); ret = devm_request_irq(pdev, perst_irq, ep_pcie_handle_perst_irq, ((dev->perst_deast ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH) ((atomic_read(&dev->perst_deast) ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH) | IRQF_EARLY_RESUME), "ep_pcie_perst", dev); if (ret) { Loading Loading @@ -2953,7 +3001,7 @@ static int ep_pcie_core_wakeup_host(enum ep_pcie_event event) if (event == EP_PCIE_EVENT_PM_D3_HOT) ep_pcie_core_issue_inband_pme(); if (dev->perst_deast && !dev->l23_ready) { if (atomic_read(&dev->perst_deast) && !dev->l23_ready) { EP_PCIE_ERR(dev, "PCIe V%d: request to assert WAKE# when PERST is de-asserted and D3hot is not received\n", dev->rev); Loading @@ -2964,7 +3012,7 @@ static int ep_pcie_core_wakeup_host(enum ep_pcie_event event) EP_PCIE_DBG(dev, "PCIe V%d: No. %ld to assert PCIe WAKE#; perst is %s de-asserted; D3hot is %s received\n", dev->rev, dev->wake_counter, dev->perst_deast ? "" : "not", atomic_read(&dev->perst_deast) ? "" : "not", dev->l23_ready ? "" : "not"); /* * Assert WAKE# GPIO until link is back to L0. Loading Loading @@ -3219,6 +3267,14 @@ static int ep_pcie_probe(struct platform_device *pdev) goto irq_failure; } /* * Wakelock is needed to avoid missing BME and other * interrupts if apps goes into suspend before host * sets them. */ device_init_wakeup(&ep_pcie_dev.pdev->dev, true); atomic_set(&ep_pcie_dev.ep_pcie_dev_wake, 0); if (ep_pcie_dev.perst_enum && !gpio_get_value(ep_pcie_dev.gpio[EP_PCIE_GPIO_PERST].num)) { EP_PCIE_DBG2(&ep_pcie_dev, Loading