Esempio n. 1
0
static int wl1271_boot_soft_reset(struct wl1271 *wl)
{
    unsigned long timeout;
    u32 boot_data;

    /* perform soft reset */
    wl1271_reg_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_reg_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_reg_write32(wl, ENABLE, 0x0);

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

    return 0;
}
Esempio n. 2
0
static int wl1271_boot_write_irq_polarity(struct wl1271 *wl)
{
    u32 polarity, status, i;

    wl1271_reg_write32(wl, OCP_POR_CTR, OCP_REG_POLARITY);
    wl1271_reg_write32(wl, OCP_CMD, OCP_CMD_READ);

    /* Wait until the command is complete (ie. bit 18 is set) */
    for (i = 0; i < OCP_CMD_LOOP; i++) {
        polarity = wl1271_reg_read32(wl, OCP_DATA_READ);
        if (polarity & OCP_READY_MASK)
            break;
    }
    if (i == OCP_CMD_LOOP) {
        wl1271_error("OCP command timeout!");
        return -EIO;
    }

    status = polarity & OCP_STATUS_MASK;
    if (status != OCP_STATUS_OK) {
        wl1271_error("OCP command failed (%d)", status);
        return -EIO;
    }

    /* We use HIGH polarity, so unset the LOW bit */
    polarity &= ~POLARITY_LOW;

    wl1271_reg_write32(wl, OCP_POR_CTR, OCP_REG_POLARITY);
    wl1271_reg_write32(wl, OCP_DATA_WRITE, polarity);
    wl1271_reg_write32(wl, OCP_CMD, OCP_CMD_WRITE);

    return 0;
}
Esempio n. 3
0
void wl1271_event_mbox_config(struct wl1271 *wl)
{
	wl->mbox_ptr[0] = wl1271_reg_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]);
}
Esempio n. 4
0
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_reg_read32(wl, ACX_REG_ECPU_CONTROL);

    /* 10.5.1 run the firmware (II) */
    cpu_ctrl |= flag;
    wl1271_reg_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
}
Esempio n. 5
0
int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len)
{
	struct wl1271_cmd_header *cmd;
	unsigned long timeout;
	u32 intr;
	int ret = 0;

	cmd = buf;
	cmd->id = id;
	cmd->status = 0;

	WARN_ON(len % 4 != 0);

	wl1271_spi_mem_write(wl, wl->cmd_box_addr, buf, len);

	wl1271_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD);

	timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT);

	intr = wl1271_reg_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;
		}

		msleep(1);

		intr = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
	}

	wl1271_reg_write32(wl, ACX_REG_INTERRUPT_ACK,
			   WL1271_ACX_INTR_CMD_COMPLETE);

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

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

    wl1271_reg_write32(wl, PLL_PARAMETERS, clk);

    pause = wl1271_reg_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_reg_write32(wl, WU_COUNTER_PAUSE, pause);

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

    wl1271_set_partition(wl,
                         part_table[PART_DRPW].mem.start,
                         part_table[PART_DRPW].mem.size,
                         part_table[PART_DRPW].reg.start,
                         part_table[PART_DRPW].reg.size);

    /* 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_reg_read32(wl, DRPW_SCRATCH_START);

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

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

    wl1271_set_partition(wl,
                         part_table[PART_WORK].mem.start,
                         part_table[PART_WORK].mem.size,
                         part_table[PART_WORK].reg.start,
                         part_table[PART_WORK].reg.size);

    /* Disable interrupts */
    wl1271_reg_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_reg_write32(wl, ACX_EEPROMLESS_IND_REG, ACX_EEPROMLESS_IND_REG);

    tmp = wl1271_reg_read32(wl, CHIP_ID_B);

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

    /* 6. read the EEPROM parameters */
    tmp = wl1271_reg_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_reg_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;

    /* 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. 7
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_reg_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_reg_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_reg_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_reg_read32(wl, REG_COMMAND_MAILBOX_PTR);

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

    /* set the working partition to its "running" mode offset */
    wl1271_set_partition(wl,
                         part_table[PART_WORK].mem.start,
                         part_table[PART_WORK].mem.size,
                         part_table[PART_WORK].reg.start,
                         part_table[PART_WORK].reg.size);

    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
     */

    /* enable gpio interrupts */
    wl1271_boot_enable_interrupts(wl);

    /* unmask all mbox events  */
    wl->event_mask = 0xffffffff;

    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;
}
Esempio n. 8
0
static void wl1271_irq_work(struct work_struct *work)
{
	u32 intr, ctr = WL1271_IRQ_MAX_LOOPS;
	int ret;
	struct wl1271 *wl =
		container_of(work, struct wl1271, irq_work);

	mutex_lock(&wl->mutex);

	wl1271_debug(DEBUG_IRQ, "IRQ work");

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

	ret = wl1271_ps_elp_wakeup(wl, true);
	if (ret < 0)
		goto out;

	wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);

	intr = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR);
	if (!intr) {
		wl1271_debug(DEBUG_IRQ, "Zero interrupt received.");
		goto out_sleep;
	}

	intr &= WL1271_INTR_MASK;

	do {
		wl1271_fw_status(wl, wl->fw_status);


		if (intr & (WL1271_ACX_INTR_EVENT_A |
			    WL1271_ACX_INTR_EVENT_B)) {
			wl1271_debug(DEBUG_IRQ,
				     "WL1271_ACX_INTR_EVENT (0x%x)", intr);
			if (intr & WL1271_ACX_INTR_EVENT_A)
				wl1271_event_handle(wl, 0);
			else
				wl1271_event_handle(wl, 1);
		}

		if (intr & WL1271_ACX_INTR_INIT_COMPLETE)
			wl1271_debug(DEBUG_IRQ,
				     "WL1271_ACX_INTR_INIT_COMPLETE");

		if (intr & WL1271_ACX_INTR_HW_AVAILABLE)
			wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE");

		if (intr & WL1271_ACX_INTR_DATA) {
			u8 tx_res_cnt = wl->fw_status->tx_results_counter -
				wl->tx_results_count;

			wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA");

			
			if (tx_res_cnt)
				wl1271_tx_complete(wl, tx_res_cnt);

			wl1271_rx(wl, wl->fw_status);
		}

		intr = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR);
		intr &= WL1271_INTR_MASK;
	} while (intr && --ctr);

out_sleep:
	wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK,
			   WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
	wl1271_ps_elp_sleep(wl);

out:
	mutex_unlock(&wl->mutex);
}
Esempio n. 9
0
static int wl1271_chip_wakeup(struct wl1271 *wl)
{
	int ret = 0;

	wl1271_power_on(wl);
	msleep(WL1271_POWER_ON_SLEEP);
	wl1271_spi_reset(wl);
	wl1271_spi_init(wl);

	
	wl1271_set_partition(wl,
			     0x00000000,
			     0x00000000,
			     REGISTERS_BASE,
			     REGISTERS_DOWN_SIZE);

	
	wl1271_fw_wakeup(wl);

	

	
	wl->chip.id = wl1271_reg_read32(wl, CHIP_ID_B);

	

	switch (wl->chip.id) {
	case CHIP_ID_1271_PG10:
		wl1271_warning("chip id 0x%x (1271 PG10) support is obsolete",
			       wl->chip.id);

		ret = wl1271_setup(wl);
		if (ret < 0)
			goto out;
		break;
	case CHIP_ID_1271_PG20:
		wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)",
			     wl->chip.id);

		ret = wl1271_setup(wl);
		if (ret < 0)
			goto out;
		break;
	default:
		wl1271_error("unsupported chip id: 0x%x", wl->chip.id);
		ret = -ENODEV;
		goto out;
	}

	if (wl->fw == NULL) {
		ret = wl1271_fetch_firmware(wl);
		if (ret < 0)
			goto out;
	}

	
	if (wl->nvs == NULL) {
		ret = wl1271_fetch_nvs(wl);
		if (ret < 0)
			goto out;
	}

out:
	return ret;
}
static int wl1271_chip_wakeup(struct wl1271 *wl)
{
	int ret = 0;

	wl1271_power_on(wl);
	msleep(WL1271_POWER_ON_SLEEP);
	wl1271_spi_reset(wl);
	wl1271_spi_init(wl);

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

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

	/* whal_FwCtrl_BootSm() */

	/* 0. read chip id from CHIP_ID */
	wl->chip.id = wl1271_reg_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);

		ret = wl1271_setup(wl);
		if (ret < 0)
			goto out;
		break;
	case CHIP_ID_1271_PG20:
		wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)",
			     wl->chip.id);

		ret = wl1271_setup(wl);
		if (ret < 0)
			goto out;
		break;
	default:
		wl1271_error("unsupported chip id: 0x%x", wl->chip.id);
		ret = -ENODEV;
		goto out;
	}

	if (wl->fw == NULL) {
		ret = wl1271_fetch_firmware(wl);
		if (ret < 0)
			goto out;
	}

	/* No NVS from netlink, try to get it from the filesystem */
	if (wl->nvs == NULL) {
		ret = wl1271_fetch_nvs(wl);
		if (ret < 0)
			goto out;
	}

out:
	return ret;
}