예제 #1
0
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;
}
예제 #2
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) {
#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;
}
예제 #3
0
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, &regs);
	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;
}
예제 #5
0
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;
}
예제 #6
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;
}
예제 #7
0
int bcmsdh_register(bcmsdh_driver_t *driver)
{
	drvinfo = *driver;

	SDLX_MSG(("Linux Kernel SDIO/MMC Driver\n"));
	return sdio_function_init();
}
예제 #8
0
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;
}
예제 #9
0
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;
}
예제 #11
0
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;
}
예제 #12
0
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;
}
예제 #13
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 **)&regs, irq);
	if (!sdh) {
		SDLX_MSG(("%s: bcmsdh_attach failed\n", __func__));
		goto err;
	}
#else
	sdh = bcmsdh_attach(osh, (void *)r->start, (void **)&regs, 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;
}