123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681 |
- /*
- * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for
- * any purpose with or without fee is hereby granted, provided that the
- * above copyright notice and this permission notice appear in all
- * copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
- * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
- * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
- /**
- * DOC: if_ahb.c
- *
- * c file for ahb specific implementations.
- */
- #include "hif.h"
- #include "hif_main.h"
- #include "hif_debug.h"
- #include "hif_io32.h"
- #include "ce_main.h"
- #include "ce_tasklet.h"
- #include "if_ahb.h"
- #include "if_pci.h"
- #include "ahb_api.h"
- #include "pci_api.h"
- #include "hif_napi.h"
- #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
- #define IRQF_DISABLED 0x00000020
- #endif
- #define HIF_IC_CE0_IRQ_OFFSET 4
- #define HIF_IC_MAX_IRQ 54
- static uint8_t ic_irqnum[HIF_IC_MAX_IRQ];
- /* integrated chip irq names */
- const char *ic_irqname[HIF_IC_MAX_IRQ] = {
- "misc-pulse1",
- "misc-latch",
- "sw-exception",
- "watchdog",
- "ce0",
- "ce1",
- "ce2",
- "ce3",
- "ce4",
- "ce5",
- "ce6",
- "ce7",
- "ce8",
- "ce9",
- "ce10",
- "ce11",
- "ce12",
- "ce13",
- "host2wbm-desc-feed",
- "host2reo-re-injection",
- "host2reo-command",
- "host2rxdma-monitor-ring3",
- "host2rxdma-monitor-ring2",
- "host2rxdma-monitor-ring1",
- "reo2ost-exception",
- "wbm2host-rx-release",
- "reo2host-status",
- "reo2host-destination-ring4",
- "reo2host-destination-ring3",
- "reo2host-destination-ring2",
- "reo2host-destination-ring1",
- "rxdma2host-monitor-destination-mac3",
- "rxdma2host-monitor-destination-mac2",
- "rxdma2host-monitor-destination-mac1",
- "ppdu-end-interrupts-mac3",
- "ppdu-end-interrupts-mac2",
- "ppdu-end-interrupts-mac1",
- "rxdma2host-monitor-status-ring-mac3",
- "rxdma2host-monitor-status-ring-mac2",
- "rxdma2host-monitor-status-ring-mac1",
- "host2rxdma-host-buf-ring-mac3",
- "host2rxdma-host-buf-ring-mac2",
- "host2rxdma-host-buf-ring-mac1",
- "rxdma2host-destination-ring-mac3",
- "rxdma2host-destination-ring-mac2",
- "rxdma2host-destination-ring-mac1",
- "host2tcl-input-ring4",
- "host2tcl-input-ring3",
- "host2tcl-input-ring2",
- "host2tcl-input-ring1",
- "wbm2host-tx-completions-ring3",
- "wbm2host-tx-completions-ring2",
- "wbm2host-tx-completions-ring1",
- "tcl2host-status-ring",
- };
- /**
- * hif_disable_isr() - disable isr
- *
- * This function disables isr and kills tasklets
- *
- * @hif_ctx: struct hif_softc
- *
- * Return: void
- */
- void hif_ahb_disable_isr(struct hif_softc *scn)
- {
- struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn);
- hif_nointrs(scn);
- ce_tasklet_kill(scn);
- hif_grp_tasklet_kill(scn);
- tasklet_kill(&sc->intr_tq);
- qdf_atomic_set(&scn->active_tasklet_cnt, 0);
- qdf_atomic_set(&scn->active_grp_tasklet_cnt, 0);
- }
- /**
- * hif_dump_registers() - dump bus debug registers
- * @scn: struct hif_opaque_softc
- *
- * This function dumps hif bus debug registers
- *
- * Return: 0 for success or error code
- */
- int hif_ahb_dump_registers(struct hif_softc *hif_ctx)
- {
- int status;
- struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
- status = hif_dump_ce_registers(scn);
- if (status)
- HIF_ERROR("%s: Dump CE Registers Failed status %d", __func__,
- status);
- return 0;
- }
- /**
- * hif_ahb_close() - hif_bus_close
- * @scn: pointer to the hif context.
- *
- * This is a callback function for hif_bus_close.
- *
- *
- * Return: n/a
- */
- void hif_ahb_close(struct hif_softc *scn)
- {
- hif_ce_close(scn);
- }
- /**
- * hif_bus_open() - hif_ahb open
- * @hif_ctx: hif context
- * @bus_type: bus type
- *
- * This is a callback function for hif_bus_open.
- *
- * Return: n/a
- */
- QDF_STATUS hif_ahb_open(struct hif_softc *hif_ctx, enum qdf_bus_type bus_type)
- {
- struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(hif_ctx);
- qdf_spinlock_create(&sc->irq_lock);
- return hif_ce_open(hif_ctx);
- }
- /**
- * hif_bus_configure() - Configure the bus
- * @scn: pointer to the hif context.
- *
- * This function configure the ahb bus
- *
- * return: 0 for success. nonzero for failure.
- */
- int hif_ahb_bus_configure(struct hif_softc *scn)
- {
- return hif_pci_bus_configure(scn);
- }
- /**
- * hif_configure_msi_ahb - Configure MSI interrupts
- * @sc : pointer to the hif context
- *
- * return: 0 for success. nonzero for failure.
- */
- int hif_configure_msi_ahb(struct hif_pci_softc *sc)
- {
- return 0;
- }
- /**
- * hif_ahb_configure_legacy_irq() - Configure Legacy IRQ
- * @sc: pointer to the hif context.
- *
- * This function registers the irq handler and enables legacy interrupts
- *
- * return: 0 for success. nonzero for failure.
- */
- int hif_ahb_configure_legacy_irq(struct hif_pci_softc *sc)
- {
- int ret = 0;
- struct hif_softc *scn = HIF_GET_SOFTC(sc);
- struct platform_device *pdev = (struct platform_device *)sc->pdev;
- int irq = 0;
- /* do not support MSI or MSI IRQ failed */
- tasklet_init(&sc->intr_tq, wlan_tasklet, (unsigned long)sc);
- irq = platform_get_irq_byname(pdev, "legacy");
- if (irq < 0) {
- dev_err(&pdev->dev, "Unable to get irq\n");
- ret = -1;
- goto end;
- }
- ret = request_irq(irq, hif_pci_interrupt_handler,
- IRQF_DISABLED, "wlan_ahb", sc);
- if (ret) {
- dev_err(&pdev->dev, "ath_request_irq failed\n");
- ret = -1;
- goto end;
- }
- sc->irq = irq;
- /* Use Legacy PCI Interrupts */
- hif_write32_mb(sc->mem+(SOC_CORE_BASE_ADDRESS |
- PCIE_INTR_ENABLE_ADDRESS),
- PCIE_INTR_FIRMWARE_MASK | PCIE_INTR_CE_MASK_ALL);
- /* read once to flush */
- hif_read32_mb(sc->mem+(SOC_CORE_BASE_ADDRESS |
- PCIE_INTR_ENABLE_ADDRESS)
- );
- end:
- return ret;
- }
- int hif_ahb_configure_irq(struct hif_pci_softc *sc)
- {
- int ret = 0;
- struct hif_softc *scn = HIF_GET_SOFTC(sc);
- struct platform_device *pdev = (struct platform_device *)sc->pdev;
- struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
- struct hif_ext_group_entry *hif_ext_group;
- int irq = 0;
- int i, j;
- /* configure per CE interrupts */
- for (i = 0; i < scn->ce_count; i++) {
- irq = platform_get_irq_byname(pdev, ic_irqname[HIF_IC_CE0_IRQ_OFFSET + i]);
- ic_irqnum[HIF_IC_CE0_IRQ_OFFSET + i] = irq;
- ret = request_irq(irq ,
- hif_ahb_interrupt_handler,
- IRQF_TRIGGER_RISING, ic_irqname[HIF_IC_CE0_IRQ_OFFSET + i],
- &hif_state->tasklets[i]);
- if (ret) {
- dev_err(&pdev->dev, "ath_request_irq failed\n");
- ret = -1;
- goto end;
- }
- hif_ahb_irq_enable(scn, i);
- }
- /* configure external interrupts */
- for (i = 0; i < hif_state->hif_num_extgroup; i++) {
- hif_ext_group = &hif_state->hif_ext_group[i];
- if (hif_ext_group->configured) {
- tasklet_init(&hif_ext_group->intr_tq,
- hif_ext_grp_tasklet,
- (unsigned long)hif_ext_group);
- hif_ext_group->inited = true;
- for (j = 0; j < hif_ext_group->numirq; j++) {
- irq = platform_get_irq_byname(pdev,
- ic_irqname[hif_ext_group->irq[j]]);
- ic_irqnum[hif_ext_group->irq[j]] = irq;
- ret = request_irq(irq,
- hif_ext_group_ahb_interrupt_handler,
- IRQF_TRIGGER_RISING, "wlan_ahb",
- hif_ext_group);
- if (ret) {
- dev_err(&pdev->dev,
- "ath_request_irq failed\n");
- ret = -1;
- goto end;
- }
- }
- }
- }
- end:
- return ret;
- }
- irqreturn_t hif_ahb_interrupt_handler(int irq, void *context)
- {
- struct ce_tasklet_entry *tasklet_entry = context;
- return ce_dispatch_interrupt(tasklet_entry->ce_id, tasklet_entry);
- }
- irqreturn_t hif_ext_group_ahb_interrupt_handler(int irq, void *context)
- {
- struct hif_ext_group_entry *hif_ext_group = context;
- struct HIF_CE_state *hif_state = hif_ext_group->hif_state;
- struct hif_softc *scn = HIF_GET_SOFTC(hif_state);
- struct hif_opaque_softc *hif_hdl = GET_HIF_OPAQUE_HDL(scn);
- uint32_t grp_id = hif_ext_group->grp_id;
- hif_grp_irq_disable(scn, grp_id);
- qdf_atomic_inc(&scn->active_grp_tasklet_cnt);
- if (hif_ext_napi_enabled(hif_hdl, grp_id)) {
- hif_napi_schedule_grp(hif_hdl, grp_id);
- } else {
- tasklet_schedule(&hif_ext_group->intr_tq);
- }
- return IRQ_HANDLED;
- }
- /**
- * hif_target_sync() : ensure the target is ready
- * @scn: hif control structure
- *
- * Informs fw that we plan to use legacy interupts so that
- * it can begin booting. Ensures that the fw finishes booting
- * before continuing. Should be called before trying to write
- * to the targets other registers for the first time.
- *
- * Return: none
- */
- int hif_target_sync_ahb(struct hif_softc *scn)
- {
- hif_write32_mb(scn->mem + FW_INDICATOR_ADDRESS, FW_IND_HOST_READY);
- if (HAS_FW_INDICATOR) {
- int wait_limit = 500;
- int fw_ind = 0;
- while (1) {
- fw_ind = hif_read32_mb(scn->mem +
- FW_INDICATOR_ADDRESS);
- if (fw_ind & FW_IND_INITIALIZED)
- break;
- if (wait_limit-- < 0)
- break;
- hif_write32_mb(scn->mem+(SOC_CORE_BASE_ADDRESS |
- PCIE_INTR_ENABLE_ADDRESS),
- PCIE_INTR_FIRMWARE_MASK);
- qdf_mdelay(10);
- }
- if (wait_limit < 0) {
- HIF_TRACE("%s: FW signal timed out", __func__);
- return -EIO;
- } else {
- HIF_TRACE("%s: Got FW signal, retries = %x", __func__,
- 500-wait_limit);
- }
- }
- return 0;
- }
- /**
- * hif_disable_bus() - Disable the bus
- * @scn : pointer to the hif context
- *
- * This function disables the bus and helds the target in reset state
- *
- * Return: none
- */
- void hif_ahb_disable_bus(struct hif_softc *scn)
- {
- struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn);
- void __iomem *mem;
- struct platform_device *pdev = (struct platform_device *)sc->pdev;
- struct resource *memres = NULL;
- int mem_pa_size = 0;
- /*Disable WIFI clock input*/
- if (sc->mem) {
- memres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!memres) {
- HIF_INFO("%s: Failed to get IORESOURCE_MEM\n",
- __func__);
- return;
- }
- mem_pa_size = memres->end - memres->start + 1;
- hif_ahb_clk_enable_disable(&pdev->dev, 0);
- hif_ahb_device_reset(scn);
- mem = (void __iomem *)sc->mem;
- if (mem) {
- devm_iounmap(&pdev->dev, mem);
- devm_release_mem_region(&pdev->dev, scn->mem_pa,
- mem_pa_size);
- sc->mem = NULL;
- }
- }
- scn->mem = NULL;
- }
- /**
- * hif_enable_bus() - Enable the bus
- * @dev: dev
- * @bdev: bus dev
- * @bid: bus id
- * @type: bus type
- *
- * This function enables the radio bus by enabling necessary
- * clocks and waits for the target to get ready to proceed futher
- *
- * Return: QDF_STATUS
- */
- QDF_STATUS hif_ahb_enable_bus(struct hif_softc *ol_sc,
- struct device *dev, void *bdev,
- const hif_bus_id *bid,
- enum hif_enable_type type)
- {
- int ret = 0;
- int hif_type;
- int target_type;
- const struct platform_device_id *id = (struct platform_device_id *)bid;
- struct platform_device *pdev = bdev;
- struct hif_target_info *tgt_info = NULL;
- struct resource *memres = NULL;
- void __iomem *mem = NULL;
- uint32_t revision_id = 0;
- struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(ol_sc);
- sc->pdev = (struct pci_dev *)pdev;
- sc->dev = &pdev->dev;
- sc->devid = id->driver_data;
- ret = hif_get_device_type(id->driver_data, revision_id,
- &hif_type, &target_type);
- if (ret < 0) {
- HIF_ERROR("%s: invalid device ret %d id %d revision_id %d",
- __func__, ret, (int)id->driver_data, revision_id);
- return QDF_STATUS_E_FAILURE;
- }
- memres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!memres) {
- HIF_INFO("%s: Failed to get IORESOURCE_MEM\n", __func__);
- return -EIO;
- }
- ret = dma_set_mask(dev, DMA_BIT_MASK(32));
- if (ret) {
- HIF_INFO("ath: 32-bit DMA not available\n");
- goto err_cleanup1;
- }
- #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
- ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
- #else
- ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
- #endif
- if (ret) {
- HIF_ERROR("%s: failed to set dma mask error = %d",
- __func__, ret);
- return ret;
- }
- /* Arrange for access to Target SoC registers. */
- #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
- mem = devm_ioremap_resource(&pdev->dev, memres);
- #else
- mem = devm_request_and_ioremap(&pdev->dev, memres);
- #endif
- if (IS_ERR(mem)) {
- HIF_INFO("ath: ioremap error\n");
- ret = PTR_ERR(mem);
- goto err_cleanup1;
- }
- sc->mem = mem;
- ol_sc->mem = mem;
- ol_sc->mem_pa = memres->start;
- tgt_info = hif_get_target_info_handle((struct hif_opaque_softc *)ol_sc);
- tgt_info->target_type = target_type;
- hif_register_tbl_attach(ol_sc, hif_type);
- hif_target_register_tbl_attach(ol_sc, target_type);
- /* QCA_WIFI_QCA8074_VP:Should not be executed on 8074 VP platform */
- if (tgt_info->target_type != TARGET_TYPE_QCA8074) {
- if (hif_ahb_enable_radio(sc, pdev, id) != 0) {
- HIF_INFO("error in enabling soc\n");
- return -EIO;
- }
- if (hif_target_sync_ahb(ol_sc) < 0) {
- ret = -EIO;
- goto err_target_sync;
- }
- }
- HIF_TRACE("%s: X - hif_type = 0x%x, target_type = 0x%x",
- __func__, hif_type, target_type);
- return QDF_STATUS_SUCCESS;
- err_target_sync:
- /* QCA_WIFI_QCA8074_VP:Should not be executed on 8074 VP platform */
- if (tgt_info->target_type != TARGET_TYPE_QCA8074) {
- HIF_INFO("Error: Disabling target\n");
- hif_ahb_disable_bus(ol_sc);
- }
- err_cleanup1:
- return ret;
- }
- /**
- * hif_reset_soc() - reset soc
- *
- * @hif_ctx: HIF context
- *
- * This function resets soc and helds the
- * target in reset state
- *
- * Return: void
- */
- /* Function to reset SoC */
- void hif_ahb_reset_soc(struct hif_softc *hif_ctx)
- {
- hif_ahb_device_reset(hif_ctx);
- }
- /**
- * hif_nointrs() - disable IRQ
- *
- * @scn: struct hif_softc
- *
- * This function stops interrupt(s)
- *
- * Return: none
- */
- void hif_ahb_nointrs(struct hif_softc *scn)
- {
- int i;
- struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn);
- struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
- ce_unregister_irq(hif_state, CE_ALL_BITMAP);
- if (scn->request_irq_done == false)
- return;
- if (sc->num_msi_intrs > 0) {
- /* MSI interrupt(s) */
- for (i = 0; i < sc->num_msi_intrs; i++) {
- free_irq(sc->irq + i, sc);
- }
- sc->num_msi_intrs = 0;
- } else {
- if (!scn->per_ce_irq) {
- free_irq(sc->irq, sc);
- } else {
- for (i = 0; i < scn->ce_count; i++) {
- free_irq(ic_irqnum[HIF_IC_CE0_IRQ_OFFSET + i],
- sc);
- }
- }
- }
- scn->request_irq_done = false;
- }
- /**
- * ce_irq_enable() - enable copy engine IRQ
- * @scn: struct hif_softc
- * @ce_id: ce_id
- *
- * This function enables the interrupt for the radio.
- *
- * Return: N/A
- */
- void hif_ahb_irq_enable(struct hif_softc *scn, int ce_id)
- {
- uint32_t regval;
- uint32_t reg_offset = 0;
- struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
- struct CE_pipe_config *target_ce_conf = &hif_state->target_ce_config[ce_id];
- if (scn->per_ce_irq) {
- if (target_ce_conf->pipedir & PIPEDIR_OUT) {
- reg_offset = HOST_IE_ADDRESS;
- qdf_spin_lock_irqsave(&hif_state->irq_reg_lock);
- regval = hif_read32_mb(scn->mem + reg_offset);
- regval |= (1 << ce_id);
- hif_write32_mb(scn->mem + reg_offset, regval);
- qdf_spin_unlock_irqrestore(&hif_state->irq_reg_lock);
- }
- if (target_ce_conf->pipedir & PIPEDIR_IN) {
- reg_offset = HOST_IE_ADDRESS_2;
- qdf_spin_lock_irqsave(&hif_state->irq_reg_lock);
- regval = hif_read32_mb(scn->mem + reg_offset);
- regval |= (1 << ce_id);
- hif_write32_mb(scn->mem + reg_offset, regval);
- qdf_spin_unlock_irqrestore(&hif_state->irq_reg_lock);
- }
- } else {
- hif_pci_irq_enable(scn, ce_id);
- }
- }
- /**
- * ce_irq_disable() - disable copy engine IRQ
- * @scn: struct hif_softc
- * @ce_id: ce_id
- *
- * Return: N/A
- */
- void hif_ahb_irq_disable(struct hif_softc *scn, int ce_id)
- {
- uint32_t regval;
- uint32_t reg_offset = 0;
- struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
- struct CE_pipe_config *target_ce_conf = &hif_state->target_ce_config[ce_id];
- if (scn->per_ce_irq) {
- if (target_ce_conf->pipedir & PIPEDIR_OUT) {
- reg_offset = HOST_IE_ADDRESS;
- qdf_spin_lock_irqsave(&hif_state->irq_reg_lock);
- regval = hif_read32_mb(scn->mem + reg_offset);
- regval &= ~(1 << ce_id);
- hif_write32_mb(scn->mem + reg_offset, regval);
- qdf_spin_unlock_irqrestore(&hif_state->irq_reg_lock);
- }
- if (target_ce_conf->pipedir & PIPEDIR_IN) {
- reg_offset = HOST_IE_ADDRESS_2;
- qdf_spin_lock_irqsave(&hif_state->irq_reg_lock);
- regval = hif_read32_mb(scn->mem + reg_offset);
- regval &= ~(1 << ce_id);
- hif_write32_mb(scn->mem + reg_offset, regval);
- qdf_spin_unlock_irqrestore(&hif_state->irq_reg_lock);
- }
- }
- }
- void hif_ahb_grp_irq_disable(struct hif_softc *scn, uint32_t grp_id)
- {
- struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
- struct hif_ext_group_entry *hif_ext_group;
- uint32_t i;
- hif_ext_group = &hif_state->hif_ext_group[grp_id];
- for (i = 0; i < hif_ext_group->numirq; i++) {
- disable_irq_nosync(ic_irqnum[hif_ext_group->irq[i]]);
- }
- }
- void hif_ahb_grp_irq_enable(struct hif_softc *scn, uint32_t grp_id)
- {
- struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
- struct hif_ext_group_entry *hif_ext_group;
- uint32_t i;
- hif_ext_group = &hif_state->hif_ext_group[grp_id];
- for (i = 0; i < hif_ext_group->numirq; i++) {
- enable_irq(ic_irqnum[hif_ext_group->irq[i]]);
- }
- }
|