Esempio n. 1
0
/*
 * send command to firmware
 *
 * @wl: wl struct
 * @id: command id
 * @buf: buffer containing the command, must work with dma
 * @len: length of the buffer
 */
int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
                    size_t res_len)
{
    struct wl1271_cmd_header *cmd;
    unsigned long timeout;
    u32 intr;
    int ret = 0;
    u16 status;
    u16 poll_count = 0;

    cmd = buf;
    cmd->id = cpu_to_le16(id);
    cmd->status = 0;

    WARN_ON(len % 4 != 0);

    wl1271_write(wl, wl->cmd_box_addr, buf, len, false);

    wl1271_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD);

    timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT);

    intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
    while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) {
        if (time_after(jiffies, timeout)) {
            wl1271_error("command complete timeout");
            ret = -ETIMEDOUT;
            goto out;
        }

        poll_count++;
        if (poll_count < WL1271_CMD_FAST_POLL_COUNT)
            udelay(10);
        else
            msleep(1);

        intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
    }

    /* read back the status code of the command */
    if (res_len == 0)
        res_len = sizeof(struct wl1271_cmd_header);
    wl1271_read(wl, wl->cmd_box_addr, cmd, res_len, false);

    status = le16_to_cpu(cmd->status);
    if (status != CMD_STATUS_SUCCESS) {
        wl1271_error("command execute failure %d", status);
        ieee80211_queue_work(wl->hw, &wl->recovery_work);
        ret = -EIO;
    }

    wl1271_write32(wl, ACX_REG_INTERRUPT_ACK,
                   WL1271_ACX_INTR_CMD_COMPLETE);

out:
    return ret;
}
static int wl1271_boot_soft_reset(struct wl1271 *wl)
{
	unsigned long timeout;
	u32 boot_data;

	/* perform soft reset */
	wl1271_write32(wl, ACX_REG_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT);

	/* SOFT_RESET is self clearing */
	timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME);
	while (1) {
		boot_data = wl1271_read32(wl, ACX_REG_SLV_SOFT_RESET);
		wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data);
		if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0)
			break;

		if (time_after(jiffies, timeout)) {
			/* 1.2 check pWhalBus->uSelfClearTime if the
			 * timeout was reached */
			wl1271_error("soft reset timeout");
			return -1;
		}

		udelay(SOFT_RESET_STALL_TIME);
	}

	/* disable Rx/Tx */
	wl1271_write32(wl, ENABLE, 0x0);

	/* disable auto calibration on start*/
	wl1271_write32(wl, SPARE_A2, 0xffff);

	return 0;
}
Esempio n. 3
0
void wl1271_event_mbox_config(struct wl1271 *wl)
{
	wl->mbox_ptr[0] = wl1271_read32(wl, REG_EVENT_MAILBOX_PTR);
	wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox);

	wl1271_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x",
		     wl->mbox_ptr[0], wl->mbox_ptr[1]);
}
static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)
{
	u32 cpu_ctrl;

	/* 10.5.0 run the firmware (I) */
	cpu_ctrl = wl1271_read32(wl, ACX_REG_ECPU_CONTROL);

	/* 10.5.1 run the firmware (II) */
	cpu_ctrl |= flag;
	wl1271_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
}
Esempio n. 5
0
static int wl1271_chip_wakeup(struct wl1271 *wl)
{
	struct wl1271_partition_set partition;
	int ret;

	msleep(WL1271_PRE_POWER_ON_SLEEP);
	ret = wl1271_power_on(wl);
	if (ret)
		return ret;

	msleep(WL1271_POWER_ON_SLEEP);

	/* We don't need a real memory partition here, because we only want
	 * to use the registers at this point. */
	memset(&partition, 0, sizeof(partition));
	partition.reg.start = REGISTERS_BASE;
	partition.reg.size = REGISTERS_DOWN_SIZE;
	wl1271_set_partition(wl, &partition);

	/* ELP module wake up */
	wl1271_fw_wakeup(wl);

	/* whal_FwCtrl_BootSm() */

	/* 0. read chip id from CHIP_ID */
	wl->chip.id = wl1271_read32(wl, CHIP_ID_B);

	/* 1. check if chip id is valid */

	switch (wl->chip.id) {
	case CHIP_ID_1271_PG10:
		wl1271_warning("chip id 0x%x (1271 PG10) support is obsolete",
				wl->chip.id);
		break;
	case CHIP_ID_1271_PG20:
		wl1271_notice("chip id 0x%x (1271 PG20)",
				wl->chip.id);
		break;
	case CHIP_ID_1283_PG20:
		wl1271_notice("chip id 0x%x (1283 PG20)",
				wl->chip.id);
		break;
	case CHIP_ID_1283_PG10:
	default:
		wl1271_warning("unsupported chip id: 0x%x", wl->chip.id);
		return -ENODEV;
	}

	return ret;
}
Esempio n. 6
0
/*
 * Poll the mailbox event field until any of the bits in the mask is set or a
 * timeout occurs (WL1271_EVENT_TIMEOUT in msecs)
 */
static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl, u32 mask,
						bool *timeout)
{
	u32 events_vector, event;
	unsigned long timeout_time;
	int ret;

	*timeout = false;

	timeout_time = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT);

	do {
		if (time_after(jiffies, timeout_time)) {
			wl1271_debug(DEBUG_CMD, "timeout waiting for event %d",
				     (int)mask);
			*timeout = true;
			return 0;
		}

		msleep(1);

		/* read from both event fields */
		ret = wl1271_read32(wl, wl->mbox_ptr[0], &events_vector);
		if (ret < 0)
			return ret;

		event = events_vector & mask;

		ret = wl1271_read32(wl, wl->mbox_ptr[1], &events_vector);
		if (ret < 0)
			return ret;

		event |= events_vector & mask;
	} while (!event);

	return 0;
}
Esempio n. 7
0
static int wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)
{
    u32 cpu_ctrl;
    int ret;

    /* 10.5.0 run the firmware (I) */
    ret = wl1271_read32(wl, ACX_REG_ECPU_CONTROL, &cpu_ctrl);
    if (ret < 0)
        goto out;

    /* 10.5.1 run the firmware (II) */
    cpu_ctrl |= flag;
    ret = wl1271_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);

out:
    return ret;
}
Esempio n. 8
0
/* uploads NVS and firmware */
int wl1271_load_firmware(struct wl1271 *wl)
{
    int ret = 0;
    u32 tmp, clk;
    int selected_clock = -1;

    ret = wl12xx_init_pll_clock(wl, &selected_clock);
    if (ret < 0)
        goto out;

    ret = wl1271_set_partition(wl, &wl12xx_part_table[PART_DRPW]);
    if (ret < 0)
        goto out;

    /* Read-modify-write DRPW_SCRATCH_START register (see next state)
       to be used by DRPw FW. The RTRIM value will be added by the FW
       before taking DRPw out of reset */

    wl1271_debug(DEBUG_BOOT, "DRPW_SCRATCH_START %08x", DRPW_SCRATCH_START);
    ret = wl1271_read32(wl, DRPW_SCRATCH_START, &clk);
    if (ret < 0)
        goto out;

    wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk);

    if (wl->chip.id == CHIP_ID_1283_PG20) {
        clk |= ((selected_clock & 0x3) << 1) << 4;
    } else {
        clk |= (wl->ref_clock << 1) << 4;
    }

    ret = wl1271_write32(wl, DRPW_SCRATCH_START, clk);
    if (ret < 0)
        goto out;

    ret = wl1271_set_partition(wl, &wl12xx_part_table[PART_WORK]);
    if (ret < 0)
        goto out;

    /* Disable interrupts */
    ret = wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
    if (ret < 0)
        goto out;

    ret = wl1271_boot_soft_reset(wl);
    if (ret < 0)
        goto out;

    /* 2. start processing NVS file */
    ret = wl1271_boot_upload_nvs(wl);
    if (ret < 0)
        goto out;

    /* write firmware's last address (ie. it's length) to
     * ACX_EEPROMLESS_IND_REG */
    wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG");

    ret = wl1271_write32(wl, ACX_EEPROMLESS_IND_REG,
                         ACX_EEPROMLESS_IND_REG);
    if (ret < 0)
        goto out;

    ret = wl1271_read32(wl, CHIP_ID_B, &tmp);
    if (ret < 0)
        goto out;

    wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp);

    /* 6. read the EEPROM parameters */
    ret = wl1271_read32(wl, SCR_PAD2, &tmp);
    if (ret < 0)
        goto out;

    /* WL1271: The reference driver skips steps 7 to 10 (jumps directly
     * to upload_fw) */

    if (wl->chip.id == CHIP_ID_1283_PG20) {
        ret = wl1271_top_reg_write(wl, SDIO_IO_DS, wl->conf.hci_io_ds);
        if (ret < 0)
            goto out;
    }

    ret = wl1271_boot_upload_firmware(wl);
    if (ret < 0)
        goto out;

    /* update loaded fw type */
    wl->fw_type = wl->saved_fw_type;
out:
    return ret;
}
Esempio n. 9
0
int wl127x_boot_clk(struct wl1271 *wl)
{
    u32 pause;
    u32 clk;
    int ret;

    if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3)
        wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION;

    if (wl->ref_clock == CONF_REF_CLK_19_2_E ||
            wl->ref_clock == CONF_REF_CLK_38_4_E ||
            wl->ref_clock == CONF_REF_CLK_38_4_M_XTAL)
        /* ref clk: 19.2/38.4/38.4-XTAL */
        clk = 0x3;
    else if (wl->ref_clock == CONF_REF_CLK_26_E ||
             wl->ref_clock == CONF_REF_CLK_52_E)
        /* ref clk: 26/52 */
        clk = 0x5;
    else
        return -EINVAL;

    if (wl->ref_clock != CONF_REF_CLK_19_2_E) {
        u16 val;
        /* Set clock type (open drain) */
        ret = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE, &val);
        if (ret < 0)
            return ret;

        val &= FREF_CLK_TYPE_BITS;
        ret = wl1271_top_reg_write(wl, OCP_REG_CLK_TYPE, val);
        if (ret < 0)
            return ret;

        /* Set clock pull mode (no pull) */
        ret = wl1271_top_reg_read(wl, OCP_REG_CLK_PULL, &val);
        if (ret < 0)
            return ret;

        val |= NO_PULL;
        ret = wl1271_top_reg_write(wl, OCP_REG_CLK_PULL, val);
        if (ret < 0)
            return ret;
    } else {
        u16 val;
        /* Set clock polarity */
        ret = wl1271_top_reg_read(wl, OCP_REG_CLK_POLARITY, &val);
        if (ret < 0)
            return ret;

        val &= FREF_CLK_POLARITY_BITS;
        val |= CLK_REQ_OUTN_SEL;
        ret = wl1271_top_reg_write(wl, OCP_REG_CLK_POLARITY, val);
        if (ret < 0)
            return ret;
    }

    ret = wl1271_write32(wl, PLL_PARAMETERS, clk);
    if (ret < 0)
        goto out;

    ret = wl1271_read32(wl, PLL_PARAMETERS, &pause);
    if (ret < 0)
        goto out;

    wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause);

    pause &= ~(WU_COUNTER_PAUSE_VAL);
    pause |= WU_COUNTER_PAUSE_VAL;
    ret = wl1271_write32(wl, WU_COUNTER_PAUSE, pause);

out:
    return ret;
}
Esempio n. 10
0
static int wl1271_boot_run_firmware(struct wl1271 *wl)
{
    int loop, ret;
    u32 chip_id, intr;

    ret = wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT);
    if (ret < 0)
        goto out;

    ret = wl1271_read32(wl, CHIP_ID_B, &chip_id);
    if (ret < 0)
        goto out;

    wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id);

    if (chip_id != wl->chip.id) {
        wl1271_error("chip id doesn't match after firmware boot");
        ret = -EIO;
        goto out;
    }

    /* wait for init to complete */
    loop = 0;
    while (loop++ < INIT_LOOP) {
        udelay(INIT_LOOP_DELAY);
        ret = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR, &intr);
        if (ret < 0)
            goto out;

        if (intr == 0xffffffff) {
            wl1271_error("error reading hardware complete "
                         "init indication");
            ret = -EIO;
            goto out;
        }
        /* check that ACX_INTR_INIT_COMPLETE is enabled */
        else if (intr & WL1271_ACX_INTR_INIT_COMPLETE) {
            ret = wl1271_write32(wl, ACX_REG_INTERRUPT_ACK,
                                 WL1271_ACX_INTR_INIT_COMPLETE);
            if (ret < 0)
                goto out;
            break;
        }
    }

    if (loop > INIT_LOOP) {
        wl1271_error("timeout waiting for the hardware to "
                     "complete initialization");
        ret = -EIO;
        goto out;
    }

    /* get hardware config command mail box */
    ret = wl1271_read32(wl, REG_COMMAND_MAILBOX_PTR, &wl->cmd_box_addr);
    if (ret < 0)
        goto out;

    /* get hardware config event mail box */
    ret = wl1271_read32(wl, REG_EVENT_MAILBOX_PTR, &wl->event_box_addr);
    if (ret < 0)
        goto out;

    /* set the working partition to its "running" mode offset */
    ret = wl1271_set_partition(wl, &wl12xx_part_table[PART_WORK]);
    if (ret < 0)
        goto out;

    wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x event_box_addr 0x%x",
                 wl->cmd_box_addr, wl->event_box_addr);

    ret = wl1271_boot_fw_version(wl);
    if (ret < 0)
        goto out;

    /*
     * in case of full asynchronous mode the firmware event must be
     * ready to receive event from the command mailbox
     */

    /* unmask required mbox events  */
    wl->event_mask = BSS_LOSE_EVENT_ID |
                     SCAN_COMPLETE_EVENT_ID |
                     ROLE_STOP_COMPLETE_EVENT_ID |
                     RSSI_SNR_TRIGGER_0_EVENT_ID |
                     PSPOLL_DELIVERY_FAILURE_EVENT_ID |
                     SOFT_GEMINI_SENSE_EVENT_ID |
                     PERIODIC_SCAN_REPORT_EVENT_ID |
                     PERIODIC_SCAN_COMPLETE_EVENT_ID |
                     DUMMY_PACKET_EVENT_ID |
                     PEER_REMOVE_COMPLETE_EVENT_ID |
                     BA_SESSION_RX_CONSTRAINT_EVENT_ID |
                     REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID |
                     INACTIVE_STA_EVENT_ID |
                     MAX_TX_RETRY_EVENT_ID |
                     CHANNEL_SWITCH_COMPLETE_EVENT_ID;

    ret = wl1271_event_unmask(wl);
    if (ret < 0) {
        wl1271_error("EVENT mask setting failed");
        goto out;
    }

    ret = wl1271_event_mbox_config(wl);

    /* firmware startup completed */
out:
    return ret;
}
Esempio n. 11
0
int wl1271_boot(struct wl1271 *wl)
{
	int ret = 0;
	u32 tmp, clk, pause;

	if (REF_CLOCK == 0 || REF_CLOCK == 2 || REF_CLOCK == 4)
		/* ref clk: 19.2/38.4/38.4-XTAL */
		clk = 0x3;
	else if (REF_CLOCK == 1 || REF_CLOCK == 3)
		/* ref clk: 26/52 */
		clk = 0x5;

	if (REF_CLOCK != 0) {
		u16 val;
		/* Set clock type */
		val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE);
		val &= FREF_CLK_TYPE_BITS;
		val |= CLK_REQ_PRCM;
		wl1271_top_reg_write(wl, OCP_REG_CLK_TYPE, val);
	} else {
		u16 val;
		/* Set clock polarity */
		val = wl1271_top_reg_read(wl, OCP_REG_CLK_POLARITY);
		val &= FREF_CLK_POLARITY_BITS;
		val |= CLK_REQ_OUTN_SEL;
		wl1271_top_reg_write(wl, OCP_REG_CLK_POLARITY, val);
	}

	wl1271_write32(wl, PLL_PARAMETERS, clk);

	pause = wl1271_read32(wl, PLL_PARAMETERS);

	wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause);

	pause &= ~(WU_COUNTER_PAUSE_VAL); /* FIXME: This should probably be
					   * WU_COUNTER_PAUSE_VAL instead of
					   * 0x3ff (magic number ).  How does
					   * this work?! */
	pause |= WU_COUNTER_PAUSE_VAL;
	wl1271_write32(wl, WU_COUNTER_PAUSE, pause);

	/* Continue the ELP wake up sequence */
	wl1271_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
	udelay(500);

	wl1271_set_partition(wl, &part_table[PART_DRPW]);

	/* Read-modify-write DRPW_SCRATCH_START register (see next state)
	   to be used by DRPw FW. The RTRIM value will be added by the FW
	   before taking DRPw out of reset */

	wl1271_debug(DEBUG_BOOT, "DRPW_SCRATCH_START %08x", DRPW_SCRATCH_START);
	clk = wl1271_read32(wl, DRPW_SCRATCH_START);

	wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk);

	/* 2 */
	clk |= (REF_CLOCK << 1) << 4;
	wl1271_write32(wl, DRPW_SCRATCH_START, clk);

	wl1271_set_partition(wl, &part_table[PART_WORK]);

	/* Disable interrupts */
	wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);

	ret = wl1271_boot_soft_reset(wl);
	if (ret < 0)
		goto out;

	/* 2. start processing NVS file */
	ret = wl1271_boot_upload_nvs(wl);
	if (ret < 0)
		goto out;

	/* write firmware's last address (ie. it's length) to
	 * ACX_EEPROMLESS_IND_REG */
	wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG");

	wl1271_write32(wl, ACX_EEPROMLESS_IND_REG, ACX_EEPROMLESS_IND_REG);

	tmp = wl1271_read32(wl, CHIP_ID_B);

	wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp);

	/* 6. read the EEPROM parameters */
	tmp = wl1271_read32(wl, SCR_PAD2);

	ret = wl1271_boot_write_irq_polarity(wl);
	if (ret < 0)
		goto out;

	/* FIXME: Need to check whether this is really what we want */
	wl1271_write32(wl, ACX_REG_INTERRUPT_MASK,
		       WL1271_ACX_ALL_EVENTS_VECTOR);

	/* WL1271: The reference driver skips steps 7 to 10 (jumps directly
	 * to upload_fw) */

	ret = wl1271_boot_upload_firmware(wl);
	if (ret < 0)
		goto out;

	/* 10.5 start firmware */
	ret = wl1271_boot_run_firmware(wl);
	if (ret < 0)
		goto out;

	/* Enable firmware interrupts now */
	wl1271_boot_enable_interrupts(wl);

	/* set the wl1271 default filters */
	wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
	wl->rx_filter = WL1271_DEFAULT_RX_FILTER;

	wl1271_event_mbox_config(wl);

out:
	return ret;
}
Esempio n. 12
0
static int wl1271_boot_run_firmware(struct wl1271 *wl)
{
	int loop, ret;
	u32 chip_id, interrupt;

	wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT);

	chip_id = wl1271_read32(wl, CHIP_ID_B);

	wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id);

	if (chip_id != wl->chip.id) {
		wl1271_error("chip id doesn't match after firmware boot");
		return -EIO;
	}

	/* wait for init to complete */
	loop = 0;
	while (loop++ < INIT_LOOP) {
		udelay(INIT_LOOP_DELAY);
		interrupt = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);

		if (interrupt == 0xffffffff) {
			wl1271_error("error reading hardware complete "
				     "init indication");
			return -EIO;
		}
		/* check that ACX_INTR_INIT_COMPLETE is enabled */
		else if (interrupt & WL1271_ACX_INTR_INIT_COMPLETE) {
			wl1271_write32(wl, ACX_REG_INTERRUPT_ACK,
				       WL1271_ACX_INTR_INIT_COMPLETE);
			break;
		}
	}

	if (loop > INIT_LOOP) {
		wl1271_error("timeout waiting for the hardware to "
			     "complete initialization");
		return -EIO;
	}

	/* get hardware config command mail box */
	wl->cmd_box_addr = wl1271_read32(wl, REG_COMMAND_MAILBOX_PTR);

	/* get hardware config event mail box */
	wl->event_box_addr = wl1271_read32(wl, REG_EVENT_MAILBOX_PTR);

	/* set the working partition to its "running" mode offset */
	wl1271_set_partition(wl, &part_table[PART_WORK]);

	wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x event_box_addr 0x%x",
		     wl->cmd_box_addr, wl->event_box_addr);

	wl1271_boot_fw_version(wl);

	/*
	 * in case of full asynchronous mode the firmware event must be
	 * ready to receive event from the command mailbox
	 */

	/* unmask required mbox events  */
	wl->event_mask = BSS_LOSE_EVENT_ID |
		SCAN_COMPLETE_EVENT_ID |
		PS_REPORT_EVENT_ID;

	ret = wl1271_event_unmask(wl);
	if (ret < 0) {
		wl1271_error("EVENT mask setting failed");
		return ret;
	}

	wl1271_event_mbox_config(wl);

	/* firmware startup completed */
	return 0;
}