From cb9bc6333d4409a41c640e2ff6958ab7ef567872 Mon Sep 17 00:00:00 2001 From: Houston Hoffman Date: Mon, 8 Aug 2016 21:46:55 -0700 Subject: [PATCH] qcacmn: Configure the wakeup sources for the snoc bus Need to register the device as a wakeup source and configure the corect interrupt as a wakeup source for the snoc bus. Change-Id: I2afcd69a8308183e141d7560a225a3b48d0e9f55 CRs-Fixed: 1051968 --- hif/src/dispatcher/multibus_snoc.c | 4 +- hif/src/dispatcher/snoc_api.h | 4 +- hif/src/snoc/if_snoc.c | 99 ++++++++++++++++++++++++++++++ qdf/inc/qdf_util.h | 13 ++++ qdf/linux/src/i_qdf_util.h | 5 ++ 5 files changed, 121 insertions(+), 4 deletions(-) diff --git a/hif/src/dispatcher/multibus_snoc.c b/hif/src/dispatcher/multibus_snoc.c index d2de51262d3a..ae292709fecd 100644 --- a/hif/src/dispatcher/multibus_snoc.c +++ b/hif/src/dispatcher/multibus_snoc.c @@ -45,8 +45,8 @@ QDF_STATUS hif_initialize_snoc_ops(struct hif_bus_ops *bus_ops) bus_ops->hif_bus_close = &hif_snoc_close; bus_ops->hif_bus_prevent_linkdown = &hif_dummy_bus_prevent_linkdown; bus_ops->hif_reset_soc = &hif_dummy_reset_soc; - bus_ops->hif_bus_suspend = &hif_dummy_bus_suspend; - bus_ops->hif_bus_resume = &hif_dummy_bus_resume; + bus_ops->hif_bus_suspend = &hif_snoc_bus_suspend; + bus_ops->hif_bus_resume = &hif_snoc_bus_resume; bus_ops->hif_target_sleep_state_adjust = &hif_dummy_target_sleep_state_adjust; diff --git a/hif/src/dispatcher/snoc_api.h b/hif/src/dispatcher/snoc_api.h index ec7902fa02da..245fc143a818 100644 --- a/hif/src/dispatcher/snoc_api.h +++ b/hif/src/dispatcher/snoc_api.h @@ -28,8 +28,8 @@ QDF_STATUS hif_snoc_open(struct hif_softc *hif_ctx, enum qdf_bus_type bus_type); void hif_snoc_close(struct hif_softc *hif_ctx); - - +int hif_snoc_bus_suspend(struct hif_softc *hif_ctx); +int hif_snoc_bus_resume(struct hif_softc *hif_ctx); void hif_snoc_disable_isr(struct hif_softc *hif_ctx); void hif_snoc_nointrs(struct hif_softc *scn); QDF_STATUS hif_snoc_enable_bus(struct hif_softc *ol_sc, diff --git a/hif/src/snoc/if_snoc.c b/hif/src/snoc/if_snoc.c index 85a69bdc22a9..be5d06ce281c 100644 --- a/hif/src/snoc/if_snoc.c +++ b/hif/src/snoc/if_snoc.c @@ -38,7 +38,9 @@ #include "ce_main.h" #include "ce_tasklet.h" #include "snoc_api.h" +#include #include "pld_common.h" +#include "qdf_util.h" /** * hif_disable_isr(): disable isr @@ -232,6 +234,16 @@ QDF_STATUS hif_snoc_enable_bus(struct hif_softc *ol_sc, return ret; } + ret = qdf_device_init_wakeup(ol_sc->qdf_dev, true); + if (ret == -EEXIST) + HIF_WARN("%s: device_init_wakeup already done", + __func__); + else if (ret) { + HIF_ERROR("%s: device_init_wakeup: err= %d", + __func__, ret); + return ret; + } + if (!ol_sc) { HIF_ERROR("%s: hif_ctx is NULL", __func__); return QDF_STATUS_E_NOMEM; @@ -266,6 +278,10 @@ QDF_STATUS hif_snoc_enable_bus(struct hif_softc *ol_sc, */ void hif_snoc_disable_bus(struct hif_softc *scn) { + int ret = qdf_device_init_wakeup(scn->qdf_dev, false); + + if (ret) + HIF_ERROR("%s: device_init_wakeup: err %d", __func__, ret); } /** @@ -310,3 +326,86 @@ void hif_snoc_irq_disable(struct hif_softc *scn, int ce_id) { ce_disable_irq_in_individual_register(scn, ce_id); } + +/* + * hif_snoc_setup_wakeup_sources() - enable/disable irq wake on correct irqs + * @hif_softc: hif context + * + * Firmware will send a wakeup request to the HTC_CTRL_RSVD_SVC when waking up + * the host driver. Ensure that the copy complete interrupt from this copy + * engine can wake up the apps processor. + * + * Return: 0 for success + */ +QDF_STATUS hif_snoc_setup_wakeup_sources(struct hif_softc *scn, bool enable) +{ + struct hif_opaque_softc *hif_hdl = GET_HIF_OPAQUE_HDL(scn); + uint8_t ul_pipe, dl_pipe; + int ul_is_polled, dl_is_polled; + int irq_to_wake_on; + + QDF_STATUS status; + int ret; + + status = hif_map_service_to_pipe(hif_hdl, HTC_CTRL_RSVD_SVC, + &ul_pipe, &dl_pipe, + &ul_is_polled, &dl_is_polled); + if (status) { + HIF_ERROR("%s: pipe_mapping failure", __func__); + return status; + } + + irq_to_wake_on = icnss_get_irq(dl_pipe); + if (irq_to_wake_on < 0) { + HIF_ERROR("%s: failed to map ce to irq", __func__); + return QDF_STATUS_E_RESOURCES; + } + + if (enable) + ret = enable_irq_wake(irq_to_wake_on); + else + ret = disable_irq_wake(irq_to_wake_on); + + if (ret) { + HIF_ERROR("%s: Fail to setup wake IRQ!", __func__); + return QDF_STATUS_E_RESOURCES; + } + + HIF_ERROR("%s: expecting wake from ce %d, irq %d", + __func__, dl_pipe, irq_to_wake_on); + return QDF_STATUS_SUCCESS; +} + + + +/** + * hif_snoc_bus_suspend() - prepare to suspend the bus + * @scn: hif context + * + * Setup wakeup interrupt configuration. + * + * Return: 0 on success. + */ +int hif_snoc_bus_suspend(struct hif_softc *scn) +{ + if (hif_snoc_setup_wakeup_sources(scn, true) != QDF_STATUS_SUCCESS) + return -EFAULT; + + return 0; +} + +/** + * hif_snoc_bus_resume() - snoc bus resume function + * @scn: hif context + * + * Clear wakeup interrupt configuration. + * + * Return: 0 on success + */ +int hif_snoc_bus_resume(struct hif_softc *scn) +{ + if (hif_snoc_setup_wakeup_sources(scn, false) != QDF_STATUS_SUCCESS) + QDF_BUG(0); + + return 0; +} diff --git a/qdf/inc/qdf_util.h b/qdf/inc/qdf_util.h index 588e55544fe9..44d0450264a4 100644 --- a/qdf/inc/qdf_util.h +++ b/qdf/inc/qdf_util.h @@ -421,4 +421,17 @@ int qdf_get_cpu(void) return __qdf_get_cpu(); } +/** + * qdf_device_init_wakeup() - allow a device to wake up the aps system + * @qdf_dev: the qdf device context + * @enable: enable/disable the device as a wakup source + * + * Return: 0 or errno + */ +static inline int qdf_device_init_wakeup(qdf_device_t qdf_dev, bool enable) +{ + return __qdf_device_init_wakeup(qdf_dev, enable); +} + + #endif /*_QDF_UTIL_H*/ diff --git a/qdf/linux/src/i_qdf_util.h b/qdf/linux/src/i_qdf_util.h index f11f7c6740d7..1cfb71614232 100644 --- a/qdf/linux/src/i_qdf_util.h +++ b/qdf/linux/src/i_qdf_util.h @@ -271,4 +271,9 @@ int __qdf_get_cpu(void) } #endif +static inline int __qdf_device_init_wakeup(__qdf_device_t qdf_dev, bool enable) +{ + return device_init_wakeup(qdf_dev->dev, enable); +} + #endif /*_I_QDF_UTIL_H*/