コード例 #1
0
void wl1271_elp_work(struct work_struct *work)
{
	struct delayed_work *dwork;
	struct wl1271 *wl;

	dwork = container_of(work, struct delayed_work, work);
	wl = container_of(dwork, struct wl1271, elp_work);

	wl1271_debug(DEBUG_PSM, "elp work");

	mutex_lock(&wl->mutex);

	if (unlikely(wl->state == WL1271_STATE_OFF))
		goto out;

	if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) ||
	    (!test_bit(WL1271_FLAG_PSM, &wl->flags) &&
	     !test_bit(WL1271_FLAG_IDLE, &wl->flags)))
		goto out;

	wl1271_debug(DEBUG_PSM, "chip to elp");
	wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP);
	set_bit(WL1271_FLAG_IN_ELP, &wl->flags);

out:
	mutex_unlock(&wl->mutex);
}
コード例 #2
0
ファイル: sdio_test.c プロジェクト: 119-org/hi3518-osdrv
static void wl1271_fw_wakeup(struct wl1271 *wl)
{
	u32 elp_reg;

	elp_reg = ELPCTRL_WAKE_UP;
	wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg);
}
コード例 #3
0
/* Set the SPI partitions to access the chip addresses
 *
 * To simplify driver code, a fixed (virtual) memory map is defined for
 * register and memory addresses. Because in the chipset, in different stages
 * of operation, those addresses will move around, an address translation
 * mechanism is required.
 *
 * There are four partitions (three memory and one register partition),
 * which are mapped to two different areas of the hardware memory.
 *
 *                                Virtual address
 *                                     space
 *
 *                                    |    |
 *                                 ...+----+--> mem.start
 *          Physical address    ...   |    |
 *               space       ...      |    | [PART_0]
 *                        ...         |    |
 *  00000000  <--+----+...         ...+----+--> mem.start + mem.size
 *               |    |         ...   |    |
 *               |MEM |      ...      |    |
 *               |    |   ...         |    |
 *  mem.size  <--+----+...            |    | {unused area)
 *               |    |   ...         |    |
 *               |REG |      ...      |    |
 *  mem.size     |    |         ...   |    |
 *      +     <--+----+...         ...+----+--> reg.start
 *  reg.size     |    |   ...         |    |
 *               |MEM2|      ...      |    | [PART_1]
 *               |    |         ...   |    |
 *                                 ...+----+--> reg.start + reg.size
 *                                    |    |
 *
 */
int wl1271_set_partition(struct wl1271 *wl,
			 struct wl1271_partition_set *p)
{
	/* copy partition info */
	memcpy(&wl->part, p, sizeof(*p));

	wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
		     p->mem.start, p->mem.size);
	wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
		     p->reg.start, p->reg.size);
	wl1271_debug(DEBUG_SPI, "mem2_start %08X mem2_size %08X",
		     p->mem2.start, p->mem2.size);
	wl1271_debug(DEBUG_SPI, "mem3_start %08X mem3_size %08X",
		     p->mem3.start, p->mem3.size);

	/* write partition info to the chipset */
	wl1271_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start);
	wl1271_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size);
	wl1271_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start);
	wl1271_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size);
	wl1271_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start);
	wl1271_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size);
	wl1271_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start);

	return 0;
}
コード例 #4
0
int wl1271_ps_elp_wakeup(struct wl1271 *wl)
{
    DECLARE_COMPLETION_ONSTACK(compl);
    unsigned long flags;
    int ret;
    u32 start_time = jiffies;
    bool pending = false;

    if (!test_and_clear_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags))
        return 0;


    cancel_delayed_work(&wl->elp_work);

    if (!test_bit(WL1271_FLAG_IN_ELP, &wl->flags))
        return 0;

    wl1271_debug(DEBUG_PSM, "waking up chip from elp");

    spin_lock_irqsave(&wl->wl_lock, flags);
    if (test_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags))
        pending = true;
    else
        wl->elp_compl = &compl;
    spin_unlock_irqrestore(&wl->wl_lock, flags);

    wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP);

    if (!pending) {
        ret = wait_for_completion_timeout(
                  &compl, msecs_to_jiffies(WL1271_WAKEUP_TIMEOUT));
        if (ret == 0) {
            wl1271_error("ELP wakeup timeout!");
            wl12xx_queue_recovery_work(wl);
            ret = -ETIMEDOUT;
            goto err;
        } else if (ret < 0) {
            wl1271_error("ELP wakeup completion error.");
            goto err;
        }
    }

    clear_bit(WL1271_FLAG_IN_ELP, &wl->flags);

    wl1271_debug(DEBUG_PSM, "wakeup time: %u ms",
                 jiffies_to_msecs(jiffies - start_time));
    goto out;

err:
    spin_lock_irqsave(&wl->wl_lock, flags);
    wl->elp_compl = NULL;
    spin_unlock_irqrestore(&wl->wl_lock, flags);
    return ret;

out:
    return 0;
}
コード例 #5
0
int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake)
{
	DECLARE_COMPLETION_ONSTACK(compl);
	unsigned long flags;
	int ret;
	u32 start_time = jiffies;
	bool pending = false;

	if (!test_bit(WL1271_FLAG_IN_ELP, &wl->flags))
		return 0;

	wl1271_debug(DEBUG_PSM, "waking up chip from elp");

	/*
	 * The spinlock is required here to synchronize both the work and
	 * the completion variable in one entity.
	 */
	spin_lock_irqsave(&wl->wl_lock, flags);
	if (work_pending(&wl->irq_work) || chip_awake)
		pending = true;
	else
		wl->elp_compl = &compl;
	spin_unlock_irqrestore(&wl->wl_lock, flags);

	wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP);

	if (!pending) {
		ret = wait_for_completion_timeout(
			&compl, msecs_to_jiffies(WL1271_WAKEUP_TIMEOUT));
		if (ret == 0) {
			wl1271_error("ELP wakeup timeout!");
			ieee80211_queue_work(wl->hw, &wl->recovery_work);
			ret = -ETIMEDOUT;
			goto err;
		} else if (ret < 0) {
			wl1271_error("ELP wakeup completion error.");
			goto err;
		}
	}

	clear_bit(WL1271_FLAG_IN_ELP, &wl->flags);

	wl1271_debug(DEBUG_PSM, "wakeup time: %u ms",
		     jiffies_to_msecs(jiffies - start_time));
	goto out;

err:
	spin_lock_irqsave(&wl->wl_lock, flags);
	wl->elp_compl = NULL;
	spin_unlock_irqrestore(&wl->wl_lock, flags);
	return ret;

out:
	return 0;
}
コード例 #6
0
void wl1271_elp_work(struct work_struct *work)
{
    struct delayed_work *dwork;
    struct wl1271 *wl;
    struct wl12xx_vif *wlvif;

    dwork = container_of(work, struct delayed_work, work);
    wl = container_of(dwork, struct wl1271, elp_work);

    wl1271_debug(DEBUG_PSM, "elp work");

    mutex_lock(&wl->mutex);

    if (unlikely(wl->state == WL1271_STATE_OFF))
        goto out;


    if (unlikely(!test_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags)))
        goto out;

    if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags))
        goto out;

    wl12xx_for_each_wlvif(wl, wlvif) {
        if (wlvif->bss_type == BSS_TYPE_AP_BSS)
            goto out;

        if (!test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags) &&
                test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags))
            goto out;
    }

    wl1271_debug(DEBUG_PSM, "chip to elp");
    wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP);
    set_bit(WL1271_FLAG_IN_ELP, &wl->flags);

out:
    mutex_unlock(&wl->mutex);
}
コード例 #7
0
void wl1271_write32(struct wl1271 *wl, int addr, u32 val)
{
	wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val);
}
コード例 #8
0
ファイル: ps.c プロジェクト: garwedgess/ICS-ti-wlan
int wl1271_ps_elp_wakeup(struct wl1271 *wl)
{
	DECLARE_COMPLETION_ONSTACK(compl);
	unsigned long flags;
	int ret;
	u32 start_time = jiffies;
	bool pending = false;

	/*
	 * we might try to wake up even if we didn't go to sleep
	 * before (e.g. on boot)
	 */
	if (!test_and_clear_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags))
		return 0;

	/* don't cancel_sync as it might contend for a mutex and deadlock */
	cancel_delayed_work(&wl->elp_work);

	if (!test_bit(WL1271_FLAG_IN_ELP, &wl->flags))
		return 0;

	wl1271_debug(DEBUG_PSM, "waking up chip from elp");

	/*
	 * The spinlock is required here to synchronize both the work and
	 * the completion variable in one entity.
	 */
	spin_lock_irqsave(&wl->wl_lock, flags);
	if (test_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags))
		pending = true;
	else
		wl->elp_compl = &compl;
	spin_unlock_irqrestore(&wl->wl_lock, flags);

	wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP);

	if (!pending) {
		ret = wait_for_completion_timeout(
			&compl, msecs_to_jiffies(WL1271_WAKEUP_TIMEOUT));
		if (ret == 0) {
			wl1271_error("ELP wakeup timeout!");
			wl1271_queue_recovery_work(wl);
			ret = -ETIMEDOUT;
			goto err;
		} else if (ret < 0) {
			wl1271_error("ELP wakeup completion error.");
			goto err;
		}
	}

	clear_bit(WL1271_FLAG_IN_ELP, &wl->flags);

	wl1271_debug(DEBUG_PSM, "wakeup time: %u ms",
		     jiffies_to_msecs(jiffies - start_time));
	goto out;

err:
	spin_lock_irqsave(&wl->wl_lock, flags);
	wl->elp_compl = NULL;
	spin_unlock_irqrestore(&wl->wl_lock, flags);
	return ret;

out:
	return 0;
}