Esempio n. 1
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 = wlcore_read_reg(wl, REG_ECPU_CONTROL, &cpu_ctrl);
	if (ret < 0)
		goto out;

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

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

	/* Make sure we have the boot partition */
	ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
	if (ret < 0)
		return ret;

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

	ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &chip_id);
	if (ret < 0)
		return ret;

	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);
		ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &intr);
		if (ret < 0)
			return ret;

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

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

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

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

	/* get hardware config event mail box */
	ret = wlcore_read_reg(wl, REG_EVENT_MAILBOX_PTR, &wl->mbox_ptr[0]);
	if (ret < 0)
		return ret;

	wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox);

	wl1271_debug(DEBUG_MAILBOX, "MBOX ptrs: 0x%x 0x%x",
		     wl->mbox_ptr[0], wl->mbox_ptr[1]);

	ret = wlcore_boot_static_data(wl);
	if (ret < 0) {
		wl1271_error("error getting static data");
		return ret;
	}

	/*
	 * 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_LOSS_EVENT_ID |
		SCAN_COMPLETE_EVENT_ID |
		RSSI_SNR_TRIGGER_0_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_FAILURE_EVENT_ID |
		CHANNEL_SWITCH_COMPLETE_EVENT_ID;

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

	/* set the working partition to its "running" mode offset */
	ret = wlcore_set_partition(wl, &wl->ptable[PART_WORK]);

	/* firmware startup completed */
	return ret;
}
Esempio n. 3
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
 * return the cmd status code on success.
 */
static int __wlcore_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;
	u16 status;
	u16 poll_count = 0;

	if (unlikely(wl->state == WLCORE_STATE_RESTARTING &&
		     id != CMD_STOP_FWLOGGER))
		return -EIO;

	if (WARN_ON_ONCE(len < sizeof(*cmd)))
		return -EIO;

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

	WARN_ON(len % 4 != 0);
	WARN_ON(test_bit(WL1271_FLAG_IN_ELP, &wl->flags));

	ret = wlcore_write(wl, wl->cmd_box_addr, buf, len, false);
	if (ret < 0)
		return ret;

	/*
	 * TODO: we just need this because one bit is in a different
	 * place.  Is there any better way?
	 */
	ret = wl->ops->trigger_cmd(wl, wl->cmd_box_addr, buf, len);
	if (ret < 0)
		return ret;

	timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT);

	ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &intr);
	if (ret < 0)
		return ret;

	while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) {
		if (time_after(jiffies, timeout)) {
			wl1271_error("command complete timeout");
			return -ETIMEDOUT;
		}

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

		ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &intr);
		if (ret < 0)
			return ret;
	}

	/* read back the status code of the command */
	if (res_len == 0)
		res_len = sizeof(struct wl1271_cmd_header);

	ret = wlcore_read(wl, wl->cmd_box_addr, cmd, res_len, false);
	if (ret < 0)
		return ret;

	status = le16_to_cpu(cmd->status);

	ret = wlcore_write_reg(wl, REG_INTERRUPT_ACK,
			       WL1271_ACX_INTR_CMD_COMPLETE);
	if (ret < 0)
		return ret;

	return status;
}