예제 #1
0
static void wl1271_sdio_enable_irq_wake(struct wl1271 *wl)
{
	int ret;
	mmc_pm_flag_t mmcflags;
	struct ieee80211_hw *hw = wl->hw;
	struct sdio_func *func = wl_to_func(wl);

	ret = enable_irq_wake(wl->irq);
	if (!ret) {
		wl->irq_wake_enabled = true;
		device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 1);

		/* if sdio can keep power while host is suspended, enable wow */
		mmcflags = sdio_get_host_pm_caps(func);
		wl1271_debug(DEBUG_SDIO, "sdio PM caps = 0x%x", mmcflags);

		if (mmcflags & MMC_PM_KEEP_POWER) {
			hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY;
			hw->wiphy->wowlan.n_patterns =
					WL1271_MAX_RX_DATA_FILTERS;
			hw->wiphy->wowlan.pattern_min_len = 1;
			hw->wiphy->wowlan.pattern_max_len =
					WL1271_RX_DATA_FILTER_MAX_PATTERN_SIZE;
		}
	}
}
예제 #2
0
static void wl1271_sdio_disable_irq_wake(struct wl1271 *wl)
{
	if (wl->irq_wake_enabled) {
		device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 0);
		disable_irq_wake(wl->irq);
	}
}
예제 #3
0
static irqreturn_t wl1271_hardirq(int irq, void *cookie)
{
	struct wl1271 *wl = cookie;
	unsigned long flags;

	wl1271_debug(DEBUG_IRQ, "IRQ");

	/* complete the ELP completion */
	spin_lock_irqsave(&wl->wl_lock, flags);
	set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
	if (wl->elp_compl) {
		complete(wl->elp_compl);
		wl->elp_compl = NULL;
	}

	if (test_bit(WL1271_FLAG_SUSPENDED, &wl->flags)) {
		/* don't enqueue a work right now. mark it as pending */
		set_bit(WL1271_FLAG_PENDING_WORK, &wl->flags);
		wl1271_debug(DEBUG_IRQ, "should not enqueue work");
		disable_irq_nosync(wl->irq);
		pm_wakeup_event(wl1271_sdio_wl_to_dev(wl), 0);
		spin_unlock_irqrestore(&wl->wl_lock, flags);
		return IRQ_HANDLED;
	}
	spin_unlock_irqrestore(&wl->wl_lock, flags);

	return IRQ_WAKE_THREAD;
}
예제 #4
0
static void __devexit wl1271_remove(struct sdio_func *func)
{
	struct wl1271 *wl = sdio_get_drvdata(func);

	/* Undo decrement done above in wl1271_probe */
	pm_runtime_get_noresume(&func->dev);

	wl1271_unregister_hw(wl);
	device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 0);
	disable_irq_wake(wl->irq);
	free_irq(wl->irq, wl);
	wl1271_free_hw(wl);
}
예제 #5
0
static int __devinit wl1271_probe(struct sdio_func *func,
                                  const struct sdio_device_id *id)
{
    struct ieee80211_hw *hw;
    const struct wl12xx_platform_data *wlan_data;
    struct wl1271 *wl;
    unsigned long irqflags;
    mmc_pm_flag_t mmcflags;
    int ret;

    /* We are only able to handle the wlan function */
    if (func->num != 0x02)
        return -ENODEV;

    hw = wl1271_alloc_hw();
    if (IS_ERR(hw))
        return PTR_ERR(hw);

    wl = hw->priv;

    wl->if_priv = func;
    wl->if_ops = &sdio_ops;

    /* Grab access to FN0 for ELP reg. */
    func->card->quirks |= MMC_QUIRK_LENIENT_FN0;

    /* Use block mode for transferring over one block size of data */
    func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;

    wlan_data = wl12xx_get_platform_data();
    if (IS_ERR(wlan_data)) {
        ret = PTR_ERR(wlan_data);
        wl1271_error("missing wlan platform data: %d", ret);
        goto out_free;
    }

    wl->irq = wlan_data->irq;
    wl->ref_clock = wlan_data->board_ref_clock;
    wl->tcxo_clock = wlan_data->board_tcxo_clock;
    wl->platform_quirks = wlan_data->platform_quirks;

    if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ)
        irqflags = IRQF_TRIGGER_RISING;
    else
        irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT;

    ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq,
                               irqflags,
                               DRIVER_NAME, wl);
    if (ret < 0) {
        wl1271_error("request_irq() failed: %d", ret);
        goto out_free;
    }

    ret = enable_irq_wake(wl->irq);
    if (!ret) {
        wl->irq_wake_enabled = true;
        device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 1);

        /* if sdio can keep power while host is suspended, enable wow */
        mmcflags = sdio_get_host_pm_caps(func);
        wl1271_debug(DEBUG_SDIO, "sdio PM caps = 0x%x", mmcflags);

        if (mmcflags & MMC_PM_KEEP_POWER)
            hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY;
    }
    disable_irq(wl->irq);

    ret = wl1271_init_ieee80211(wl);
    if (ret)
        goto out_irq;

    ret = wl1271_register_hw(wl);
    if (ret)
        goto out_irq;

    sdio_set_drvdata(func, wl);

    /* Tell PM core that we don't need the card to be powered now */
    pm_runtime_put_noidle(&func->dev);

    return 0;

out_irq:
    free_irq(wl->irq, wl);

out_free:
    wl1271_free_hw(wl);

    return ret;
}