int bcmsdh_oob_intr_register(bcmsdh_info_t *bcmsdh, bcmsdh_cb_fn_t oob_irq_handler, void* oob_irq_handler_context) { int err = 0; bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt; SDLX_MSG(("%s: Enter\n", __FUNCTION__)); if (bcmsdh_osinfo->oob_irq_registered) { SDLX_MSG(("%s: irq is already registered\n", __FUNCTION__)); return -EBUSY; } SDLX_MSG(("%s OOB irq=%d flags=%X \n", __FUNCTION__, (int)bcmsdh_osinfo->oob_irq_num, (int)bcmsdh_osinfo->oob_irq_flags)); bcmsdh_osinfo->oob_irq_handler = oob_irq_handler; bcmsdh_osinfo->oob_irq_handler_context = oob_irq_handler_context; err = request_irq(bcmsdh_osinfo->oob_irq_num, wlan_oob_irq, bcmsdh_osinfo->oob_irq_flags, "bcmsdh_sdmmc", bcmsdh); if (err) { SDLX_MSG(("%s: request_irq failed with %d\n", __FUNCTION__, err)); return err; } #if defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI) if (device_may_wakeup(bcmsdh_osinfo->dev)) { #endif /* CONFIG_ARCH_RHEA || CONFIG_ARCH_CAPRI */ err = enable_irq_wake(bcmsdh_osinfo->oob_irq_num); if (!err) bcmsdh_osinfo->oob_irq_wake_enabled = TRUE; #if defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI) } #endif /* CONFIG_ARCH_RHEA || CONFIG_ARCH_CAPRI */ bcmsdh_osinfo->oob_irq_enabled = TRUE; bcmsdh_osinfo->oob_irq_registered = TRUE; return err; }
void bcmsdh_oob_intr_unregister(bcmsdh_info_t *bcmsdh) { int err = 0; bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt; SDLX_MSG(("%s: Enter\n", __FUNCTION__)); if (!bcmsdh_osinfo->oob_irq_registered) { SDLX_MSG(("%s: irq is not registered\n", __FUNCTION__)); return; } if (bcmsdh_osinfo->oob_irq_wake_enabled) { #if defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI) if (device_may_wakeup(bcmsdh_osinfo->dev)) { #endif /* CONFIG_ARCH_RHEA || CONFIG_ARCH_CAPRI */ err = disable_irq_wake(bcmsdh_osinfo->oob_irq_num); if (!err) bcmsdh_osinfo->oob_irq_wake_enabled = FALSE; #if defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI) } #endif /* CONFIG_ARCH_RHEA || CONFIG_ARCH_CAPRI */ } if (bcmsdh_osinfo->oob_irq_enabled) { disable_irq(bcmsdh_osinfo->oob_irq_num); bcmsdh_osinfo->oob_irq_enabled = FALSE; } free_irq(bcmsdh_osinfo->oob_irq_num, bcmsdh); bcmsdh_osinfo->oob_irq_registered = FALSE; }
void* bcmsdh_probe(osl_t *osh, void *dev, void *sdioh, void *adapter_info, uint bus_type, uint bus_num, uint slot_num) { uint32 regs; bcmsdh_info_t *bcmsdh; uint32 vendevid; bcmsdh_os_info_t *bcmsdh_osinfo = NULL; bcmsdh = bcmsdh_attach(osh, sdioh, ®s); if (bcmsdh == NULL) { SDLX_MSG(("%s: bcmsdh_attach failed\n", __FUNCTION__)); goto err; } bcmsdh_osinfo = MALLOC(osh, sizeof(bcmsdh_os_info_t)); if (bcmsdh_osinfo == NULL) { SDLX_MSG(("%s: failed to allocate bcmsdh_os_info_t\n", __FUNCTION__)); goto err; } bzero((char *)bcmsdh_osinfo, sizeof(bcmsdh_os_info_t)); bcmsdh->os_cxt = bcmsdh_osinfo; bcmsdh_osinfo->sdioh = sdioh; bcmsdh_osinfo->dev = dev; osl_set_bus_handle(osh, bcmsdh); #if !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) if (dev && device_init_wakeup(dev, true) == 0) bcmsdh_osinfo->dev_wake_enabled = TRUE; #endif /* !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) */ #if defined(OOB_INTR_ONLY) spin_lock_init(&bcmsdh_osinfo->oob_irq_spinlock); /* Get customer specific OOB IRQ parametres: IRQ number as IRQ type */ bcmsdh_osinfo->oob_irq_num = wifi_platform_get_irq_number(adapter_info, &bcmsdh_osinfo->oob_irq_flags); if (bcmsdh_osinfo->oob_irq_num < 0) { SDLX_MSG(("%s: Host OOB irq is not defined\n", __FUNCTION__)); goto err; } #endif /* defined(BCMLXSDMMC) */ /* Read the vendor/device ID from the CIS */ vendevid = bcmsdh_query_device(bcmsdh); /* try to attach to the target device */ bcmsdh_osinfo->context = drvinfo.probe((vendevid >> 16), (vendevid & 0xFFFF), bus_num, slot_num, 0, bus_type, (void *)regs, osh, bcmsdh); if (bcmsdh_osinfo->context == NULL) { SDLX_MSG(("%s: device attach failed\n", __FUNCTION__)); goto err; } return bcmsdh; /* error handling */ err: if (bcmsdh != NULL) bcmsdh_detach(osh, bcmsdh); if (bcmsdh_osinfo != NULL) MFREE(osh, bcmsdh_osinfo, sizeof(bcmsdh_os_info_t)); return NULL; }
int bcmsdh_oob_intr_register(bcmsdh_info_t *bcmsdh, bcmsdh_cb_fn_t oob_irq_handler, void* oob_irq_handler_context) { int err = 0; bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt; SDLX_MSG(("%s: Enter\n", __FUNCTION__)); if (bcmsdh_osinfo->oob_irq_registered) { SDLX_MSG(("%s: irq is already registered\n", __FUNCTION__)); return -EBUSY; } SDLX_MSG(("%s OOB irq=%d flags=%X \n", __FUNCTION__, (int)bcmsdh_osinfo->oob_irq_num, (int)bcmsdh_osinfo->oob_irq_flags)); bcmsdh_osinfo->oob_irq_handler = oob_irq_handler; bcmsdh_osinfo->oob_irq_handler_context = oob_irq_handler_context; #if defined(CONFIG_ARCH_ODIN) err = odin_gpio_sms_request_irq(bcmsdh_osinfo->oob_irq_num, wlan_oob_irq, bcmsdh_osinfo->oob_irq_flags, "bcmsdh_sdmmc", bcmsdh); #else err = request_irq(bcmsdh_osinfo->oob_irq_num, wlan_oob_irq, bcmsdh_osinfo->oob_irq_flags, "bcmsdh_sdmmc", bcmsdh); #endif /* defined(CONFIG_ARCH_ODIN) */ if (err) { SDLX_MSG(("%s: request_irq failed with %d\n", __FUNCTION__, err)); return err; } bcmdhd_irq_number = (int)bcmsdh_osinfo->oob_irq_num; err = enable_irq_wake(bcmsdh_osinfo->oob_irq_num); if (!err) bcmsdh_osinfo->oob_irq_wake_enabled = TRUE; bcmsdh_osinfo->oob_irq_enabled = TRUE; bcmsdh_osinfo->oob_irq_registered = TRUE; return err; }
int bcmsdh_register_oob_intr(void *dhdp) { int error = 0; SDLX_MSG(("%s Enter\n", __func__)); sdhcinfo->oob_flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE; dev_set_drvdata(sdhcinfo->dev, dhdp); if (!sdhcinfo->oob_irq_registered) { SDLX_MSG(("%s IRQ=%d Type=%X\n", __func__, (int)sdhcinfo->oob_irq, (int)sdhcinfo->oob_flags)); /* Refer to customer Host IRQ docs about proper irqflags definition */ error = request_irq(sdhcinfo->oob_irq, wlan_oob_irq, sdhcinfo->oob_flags, "bcmsdh_sdmmc", NULL); if (error) return -ENODEV; set_irq_wake(sdhcinfo->oob_irq, 1); sdhcinfo->oob_irq_registered = true; } return 0; }
int bcmsdh_register(bcmsdh_driver_t *driver) { int error = 0; drvinfo = *driver; SDLX_MSG(("%s: register client driver\n", __FUNCTION__)); error = bcmsdh_register_client_driver(); if (error) SDLX_MSG(("%s: failed %d\n", __FUNCTION__, error)); return error; }
int bcmsdh_register(bcmsdh_driver_t *driver) { drvinfo = *driver; SDLX_MSG(("Linux Kernel SDIO/MMC Driver\n")); return sdio_function_init(); }
void bcmsdh_unregister_oob_intr(void) { SDLX_MSG(("%s: Enter\n", __func__)); set_irq_wake(sdhcinfo->oob_irq, 0); disable_irq(sdhcinfo->oob_irq); /* just in case.. */ free_irq(sdhcinfo->oob_irq, NULL); sdhcinfo->oob_irq_registered = false; }
int bcmsdh_oob_intr_register(bcmsdh_info_t *bcmsdh, bcmsdh_cb_fn_t oob_irq_handler, void* oob_irq_handler_context) { int err = 0; bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt; SDLX_MSG(("%s: Enter\n", __FUNCTION__)); if (bcmsdh_osinfo->oob_irq_registered) { SDLX_MSG(("%s: irq is already registered\n", __FUNCTION__)); return -EBUSY; } #ifdef HW_OOB printf("%s: HW_OOB enabled\n", __FUNCTION__); #else printf("%s: SW_OOB enabled\n", __FUNCTION__); #endif SDLX_MSG(("%s OOB irq=%d flags=%X\n", __FUNCTION__, (int)bcmsdh_osinfo->oob_irq_num, (int)bcmsdh_osinfo->oob_irq_flags)); bcmsdh_osinfo->oob_irq_handler = oob_irq_handler; bcmsdh_osinfo->oob_irq_handler_context = oob_irq_handler_context; bcmsdh_osinfo->oob_irq_enabled = TRUE; bcmsdh_osinfo->oob_irq_registered = TRUE; #if defined(CONFIG_ARCH_ODIN) err = odin_gpio_sms_request_irq(bcmsdh_osinfo->oob_irq_num, wlan_oob_irq, bcmsdh_osinfo->oob_irq_flags, "bcmsdh_sdmmc", bcmsdh); #else err = request_irq(bcmsdh_osinfo->oob_irq_num, wlan_oob_irq, bcmsdh_osinfo->oob_irq_flags, "bcmsdh_sdmmc", bcmsdh); #endif /* defined(CONFIG_ARCH_ODIN) */ if (err) { bcmsdh_osinfo->oob_irq_enabled = FALSE; bcmsdh_osinfo->oob_irq_registered = FALSE; SDLX_MSG(("%s: request_irq failed with %d\n", __FUNCTION__, err)); return err; } #if defined(DISABLE_WOWLAN) SDLX_MSG(("%s: disable_irq_wake\n", __FUNCTION__)); err = disable_irq_wake(bcmsdh_osinfo->oob_irq_num); if (err) SDLX_MSG(("%s: disable_irq_wake failed with %d\n", __FUNCTION__, err)); else bcmsdh_osinfo->oob_irq_wake_enabled = FALSE; #else SDLX_MSG(("%s: enable_irq_wake\n", __FUNCTION__)); err = enable_irq_wake(bcmsdh_osinfo->oob_irq_num); if (err) SDLX_MSG(("%s: enable_irq_wake failed with %d\n", __FUNCTION__, err)); else bcmsdh_osinfo->oob_irq_wake_enabled = TRUE; #endif return 0; }
void bcmsdh_oob_intr_unregister(bcmsdh_info_t *bcmsdh) { int err = 0; bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt; SDLX_MSG(("%s: Enter\n", __FUNCTION__)); if (!bcmsdh_osinfo->oob_irq_registered) { SDLX_MSG(("%s: irq is not registered\n", __FUNCTION__)); return; } if (bcmsdh_osinfo->oob_irq_wake_enabled) { err = disable_irq_wake(bcmsdh_osinfo->oob_irq_num); if (!err) bcmsdh_osinfo->oob_irq_wake_enabled = FALSE; } if (bcmsdh_osinfo->oob_irq_enabled) { disable_irq(bcmsdh_osinfo->oob_irq_num); bcmsdh_osinfo->oob_irq_enabled = FALSE; } free_irq(bcmsdh_osinfo->oob_irq_num, bcmsdh); bcmsdh_osinfo->oob_irq_registered = FALSE; }
static irqreturn_t wlan_oob_irq(int irq, void *dev_id) { dhd_pub_t *dhdp; dhdp = (dhd_pub_t *) dev_get_drvdata(sdhcinfo->dev); bcmsdh_oob_intr_set(0); if (dhdp == NULL) { SDLX_MSG(("Out of band GPIO interrupt fired way too early\n")); return IRQ_HANDLED; } WAKE_LOCK_TIMEOUT(dhdp, WAKE_LOCK_TMOUT, 25); dhdsdio_isr((void *)dhdp->bus); return IRQ_HANDLED; }
static #endif /* BCMLXSDMMC */ int bcmsdh_remove(struct device *dev) { bcmsdh_hc_t *sdhc, *prev; struct osl_info *osh; sdhc = sdhcinfo; drvinfo.detach(sdhc->ch); bcmsdh_detach(sdhc->osh, sdhc->sdh); /* find the SDIO Host Controller state for this pdev and take it out from the list */ for (sdhc = sdhcinfo, prev = NULL; sdhc; sdhc = sdhc->next) { if (sdhc->dev == (void *)dev) { if (prev) prev->next = sdhc->next; else sdhcinfo = NULL; break; } prev = sdhc; } if (!sdhc) { SDLX_MSG(("%s: failed\n", __func__)); return 0; } /* release SDIO Host Controller info */ osh = sdhc->osh; kfree(sdhc); osl_detach(osh); #if !defined(BCMLXSDMMC) dev_set_drvdata(dev, NULL); #endif /* !defined(BCMLXSDMMC) */ return 0; }
static #endif /* BCMLXSDMMC */ int bcmsdh_probe(struct device *dev) { struct osl_info *osh = NULL; bcmsdh_hc_t *sdhc = NULL; unsigned long regs = 0; bcmsdh_info_t *sdh = NULL; #if !defined(BCMLXSDMMC) && defined(BCMPLATFORM_BUS) struct platform_device *pdev; struct resource *r; #endif /* BCMLXSDMMC */ int irq = 0; u32 vendevid; unsigned long irq_flags = 0; #if !defined(BCMLXSDMMC) && defined(BCMPLATFORM_BUS) pdev = to_platform_device(dev); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); if (!r || irq == NO_IRQ) return -ENXIO; #endif /* BCMLXSDMMC */ #if defined(OOB_INTR_ONLY) #ifdef HW_OOB irq_flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE; #else irq_flags = IRQF_TRIGGER_FALLING; #endif /* HW_OOB */ irq = dhd_customer_oob_irq_map(&irq_flags); if (irq < 0) { SDLX_MSG(("%s: Host irq is not defined\n", __func__)); return 1; } #endif /* defined(OOB_INTR_ONLY) */ /* allocate SDIO Host Controller state info */ osh = osl_attach(dev, PCI_BUS); if (!osh) { SDLX_MSG(("%s: osl_attach failed\n", __func__)); goto err; } sdhc = kzalloc(sizeof(bcmsdh_hc_t), GFP_ATOMIC); if (!sdhc) { SDLX_MSG(("%s: out of memory\n", __func__)); goto err; } sdhc->osh = osh; sdhc->dev = (void *)dev; #ifdef BCMLXSDMMC sdh = bcmsdh_attach(osh, (void *)0, (void **)®s, irq); if (!sdh) { SDLX_MSG(("%s: bcmsdh_attach failed\n", __func__)); goto err; } #else sdh = bcmsdh_attach(osh, (void *)r->start, (void **)®s, irq); if (!sdh) { SDLX_MSG(("%s: bcmsdh_attach failed\n", __func__)); goto err; } #endif /* BCMLXSDMMC */ sdhc->sdh = sdh; sdhc->oob_irq = irq; sdhc->oob_flags = irq_flags; sdhc->oob_irq_registered = false; /* to make sure.. */ #if defined(OOB_INTR_ONLY) spin_lock_init(&sdhc->irq_lock); #endif /* chain SDIO Host Controller info together */ sdhc->next = sdhcinfo; sdhcinfo = sdhc; /* Read the vendor/device ID from the CIS */ vendevid = bcmsdh_query_device(sdh); /* try to attach to the target device */ sdhc->ch = drvinfo.attach((vendevid >> 16), (vendevid & 0xFFFF), 0, 0, 0, 0, (void *)regs, NULL, sdh); if (!sdhc->ch) { SDLX_MSG(("%s: device attach failed\n", __func__)); goto err; } return 0; /* error handling */ err: if (sdhc) { if (sdhc->sdh) bcmsdh_detach(sdhc->osh, sdhc->sdh); kfree(sdhc); } if (osh) osl_detach(osh); return -ENODEV; }