static void wl1271_boot_enable_interrupts(struct wl1271 *wl)
{
	enable_irq(wl->irq);
	wl1271_write32(wl, ACX_REG_INTERRUPT_MASK,
		       WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
	wl1271_write32(wl, HI_CFG, HI_CFG_DEF_VAL);
}
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;
}
/*
 * 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;
}
Example #4
0
static int wl1271_boot_enable_interrupts(struct wl1271 *wl)
{
	int ret;

	wl1271_enable_interrupts(wl);
	ret = wl1271_write32(wl, ACX_REG_INTERRUPT_MASK,
			     WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
	if (ret < 0)
		goto out;

	ret = wl1271_write32(wl, HI_CFG, HI_CFG_DEF_VAL);

out:
	return ret;
}
Example #5
0
int wl1271_boot(struct wl1271 *wl)
{
	int ret;

	/* polarity must be set before the firmware is loaded */
	ret = wl1271_boot_write_irq_polarity(wl);
	if (ret < 0)
		goto out;

	/* upload NVS and firmware */
	ret = wl1271_load_firmware(wl);
	if (ret)
		return ret;

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

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

	/* Enable firmware interrupts now */
	ret = wl1271_boot_enable_interrupts(wl);
	if (ret < 0)
		goto out;

	ret = wl1271_event_mbox_config(wl);

out:
	return ret;
}
void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status)
{
	struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map;
	u32 buf_size;
	u32 fw_rx_counter  = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
	u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
	u32 mem_block;

	while (drv_rx_counter != fw_rx_counter) {
		mem_block = wl1271_rx_get_mem_block(status, drv_rx_counter);
		buf_size = wl1271_rx_get_buf_size(status, drv_rx_counter);

		if (buf_size == 0) {
			wl1271_warning("received empty data");
			break;
		}

		wl->rx_mem_pool_addr.addr = (mem_block << 8) +
			le32_to_cpu(wl_mem_map->packet_memory_pool_start);
		wl->rx_mem_pool_addr.addr_extra =
			wl->rx_mem_pool_addr.addr + 4;

		/* Choose the block we want to read */
		wl1271_write(wl, WL1271_SLV_REG_DATA, &wl->rx_mem_pool_addr,
			     sizeof(wl->rx_mem_pool_addr), false);

		wl1271_rx_handle_data(wl, buf_size);

		wl->rx_counter++;
		drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
	}

	wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
}
Example #7
0
static void wl1271_fw_wakeup(struct wl1271 *wl)
{
	u32 elp_reg;

	elp_reg = ELPCTRL_WAKE_UP;
	wl1271_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg);
}
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);
}
Example #9
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;
}
Example #10
0
int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
{
	struct event_mailbox mbox;
	int ret;

	wl1271_debug(DEBUG_EVENT, "EVENT on mbox %d", mbox_num);

	if (mbox_num > 1)
		return -EINVAL;

	/* first we read the mbox descriptor */
	wl1271_read(wl, wl->mbox_ptr[mbox_num], &mbox,
		    sizeof(struct event_mailbox), false);

	/* process the descriptor */
	ret = wl1271_event_process(wl, &mbox);
	if (ret < 0)
		return ret;

	/* then we let the firmware know it can go on...*/
	wl1271_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK);

	return 0;
}
Example #11
0
void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
{
	struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map;
	unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0};
	u32 buf_size;
	u32 fw_rx_counter  = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
	u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
	u32 rx_counter;
	u32 mem_block;
	u32 pkt_length;
	u32 pkt_offset;
	u8 hlid;
	bool unaligned = false;

	while (drv_rx_counter != fw_rx_counter) {
		buf_size = 0;
		rx_counter = drv_rx_counter;
		while (rx_counter != fw_rx_counter) {
			pkt_length = wl12xx_rx_get_buf_size(status, rx_counter);
			if (buf_size + pkt_length > WL1271_AGGR_BUFFER_SIZE)
				break;
			buf_size += pkt_length;
			rx_counter++;
			rx_counter &= NUM_RX_PKT_DESC_MOD_MASK;
		}

		if (buf_size == 0) {
			wl1271_warning("received empty data");
			break;
		}

		if (wl->chip.id != CHIP_ID_1283_PG20) {
			/*
                                      
                                                         
                                                         
    */
			mem_block = wl12xx_rx_get_mem_block(status,
							    drv_rx_counter);

			wl->rx_mem_pool_addr.addr = (mem_block << 8) +
			   le32_to_cpu(wl_mem_map->packet_memory_pool_start);

			wl->rx_mem_pool_addr.addr_extra =
				wl->rx_mem_pool_addr.addr + 4;

			wl1271_write(wl, WL1271_SLV_REG_DATA,
				     &wl->rx_mem_pool_addr,
				     sizeof(wl->rx_mem_pool_addr), false);
		}

		/*                                    */
		wl1271_read(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf,
				buf_size, true);

		/*                                  */
		pkt_offset = 0;
		while (pkt_offset < buf_size) {
			pkt_length = wl12xx_rx_get_buf_size(status,
					drv_rx_counter);

			unaligned = wl12xx_rx_get_unaligned(status,
					drv_rx_counter);

			/*
                                                         
                                                           
                 
    */
			if (wl1271_rx_handle_data(wl,
						  wl->aggr_buf + pkt_offset,
						  pkt_length, unaligned,
						  &hlid) == 1) {
				if (hlid < WL12XX_MAX_LINKS)
					__set_bit(hlid, active_hlids);
				else
					WARN(1,
					     "hlid exceeded WL12XX_MAX_LINKS "
					     "(%d)\n", hlid);
			}

			wl->rx_counter++;
			drv_rx_counter++;
			drv_rx_counter &= NUM_RX_PKT_DESC_MOD_MASK;
			pkt_offset += pkt_length;
		}
	}

	/*
                                                                      
                                
  */
	if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION)
		wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);

	wl12xx_rearm_rx_streaming(wl, active_hlids);
}
Example #12
0
int wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
{
	struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map;
	unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0};
	u32 buf_size;
	u32 fw_rx_counter  = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
	u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
	u32 rx_counter;
	u32 mem_block;
	u32 pkt_length;
	u32 pkt_offset;
	u8 hlid;
	bool unaligned = false;
	int ret = 0;

	while (drv_rx_counter != fw_rx_counter) {
		buf_size = 0;
		rx_counter = drv_rx_counter;
		while (rx_counter != fw_rx_counter) {
			pkt_length = wl12xx_rx_get_buf_size(status, rx_counter);
			if (buf_size + pkt_length > WL1271_AGGR_BUFFER_SIZE)
				break;
			buf_size += pkt_length;
			rx_counter++;
			rx_counter &= NUM_RX_PKT_DESC_MOD_MASK;
		}

		if (buf_size == 0) {
			wl1271_warning("received empty data");
			break;
		}

		if (wl->chip.id != CHIP_ID_1283_PG20) {
			/*
			 * Choose the block we want to read
			 * For aggregated packets, only the first memory block
			 * should be retrieved. The FW takes care of the rest.
			 */
			mem_block = wl12xx_rx_get_mem_block(status,
							    drv_rx_counter);

			wl->rx_mem_pool_addr->addr = (mem_block << 8) +
			   le32_to_cpu(wl_mem_map->packet_memory_pool_start);

			wl->rx_mem_pool_addr->addr_extra =
				wl->rx_mem_pool_addr->addr + 4;

			ret = wl1271_write(wl, WL1271_SLV_REG_DATA,
					   wl->rx_mem_pool_addr,
					   sizeof(*wl->rx_mem_pool_addr),
					   false);
			if (ret < 0)
				goto out;
		}

		/* Read all available packets at once */
		ret = wl1271_read(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf,
				  buf_size, true);
		if (ret < 0)
			goto out;

		/* Split data into separate packets */
		pkt_offset = 0;
		while (pkt_offset < buf_size) {
			pkt_length = wl12xx_rx_get_buf_size(status,
					drv_rx_counter);

			unaligned = wl12xx_rx_get_unaligned(status,
					drv_rx_counter);

			/*
			 * the handle data call can only fail in memory-outage
			 * conditions, in that case the received frame will just
			 * be dropped.
			 */
			if (wl1271_rx_handle_data(wl,
						  wl->aggr_buf + pkt_offset,
						  pkt_length, unaligned,
						  &hlid) == 1) {
				if (hlid < WL12XX_MAX_LINKS)
					__set_bit(hlid, active_hlids);
				else
					WARN(1,
					     "hlid exceeded WL12XX_MAX_LINKS "
					     "(%d)\n", hlid);
			}

			wl->rx_counter++;
			drv_rx_counter++;
			drv_rx_counter &= NUM_RX_PKT_DESC_MOD_MASK;
			pkt_offset += pkt_length;
		}
	}

	/*
	 * Write the driver's packet counter to the FW. This is only required
	 * for older hardware revisions
	 */
	if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION) {
		ret = wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS,
				     wl->rx_counter);
		if (ret < 0)
			goto out;
	}

	wl12xx_rearm_rx_streaming(wl, active_hlids);

out:
	return ret;
}
Example #13
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;
}
Example #14
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;
}
Example #15
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;
}
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;
}
Example #17
0
static int wl1271_boot_upload_nvs(struct wl1271 *wl)
{
    size_t nvs_len, burst_len;
    int i;
    u32 dest_addr, val;
    u8 *nvs_ptr, *nvs_aligned;
    int ret;

    if (wl->nvs == NULL)
        return -ENODEV;

    if (wl->chip.id == CHIP_ID_1283_PG20) {
        struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs;

        if (wl->nvs_len == sizeof(struct wl128x_nvs_file)) {
            if (nvs->general_params.dual_mode_select)
                wl->enable_11a = true;
        } else {
            wl1271_error("nvs size is not as expected: %zu != %zu",
                         wl->nvs_len,
                         sizeof(struct wl128x_nvs_file));
            kfree(wl->nvs);
            wl->nvs = NULL;
            wl->nvs_len = 0;
            return -EILSEQ;
        }

        /* only the first part of the NVS needs to be uploaded */
        nvs_len = sizeof(nvs->nvs);
        nvs_ptr = (u8 *)nvs->nvs;

    } else {
        struct wl1271_nvs_file *nvs =
            (struct wl1271_nvs_file *)wl->nvs;
        /*
         * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz
         * band configurations) can be removed when those NVS files stop
         * floating around.
         */
        if (wl->nvs_len == sizeof(struct wl1271_nvs_file) ||
                wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) {
            if (nvs->general_params.dual_mode_select)
                wl->enable_11a = true;
        }

        if (wl->nvs_len != sizeof(struct wl1271_nvs_file) &&
                (wl->nvs_len != WL1271_INI_LEGACY_NVS_FILE_SIZE ||
                 wl->enable_11a)) {
            wl1271_error("nvs size is not as expected: %zu != %zu",
                         wl->nvs_len, sizeof(struct wl1271_nvs_file));
            kfree(wl->nvs);
            wl->nvs = NULL;
            wl->nvs_len = 0;
            return -EILSEQ;
        }

        /* only the first part of the NVS needs to be uploaded */
        nvs_len = sizeof(nvs->nvs);
        nvs_ptr = (u8 *) nvs->nvs;
    }

    /* update current MAC address to NVS */
    nvs_ptr[11] = wl->addresses[0].addr[0];
    nvs_ptr[10] = wl->addresses[0].addr[1];
    nvs_ptr[6] = wl->addresses[0].addr[2];
    nvs_ptr[5] = wl->addresses[0].addr[3];
    nvs_ptr[4] = wl->addresses[0].addr[4];
    nvs_ptr[3] = wl->addresses[0].addr[5];

    /*
     * Layout before the actual NVS tables:
     * 1 byte : burst length.
     * 2 bytes: destination address.
     * n bytes: data to burst copy.
     *
     * This is ended by a 0 length, then the NVS tables.
     */

    /* FIXME: Do we need to check here whether the LSB is 1? */
    while (nvs_ptr[0]) {
        burst_len = nvs_ptr[0];
        dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8));

        /*
         * Due to our new wl1271_translate_reg_addr function,
         * we need to add the REGISTER_BASE to the destination
         */
        dest_addr += REGISTERS_BASE;

        /* We move our pointer to the data */
        nvs_ptr += 3;

        for (i = 0; i < burst_len; i++) {
            if (nvs_ptr + 3 >= (u8 *) wl->nvs + nvs_len)
                goto out_badnvs;

            val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
                   | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));

            wl1271_debug(DEBUG_BOOT,
                         "nvs burst write 0x%x: 0x%x",
                         dest_addr, val);
            ret = wl1271_write32(wl, dest_addr, val);
            if (ret < 0)
                return ret;

            nvs_ptr += 4;
            dest_addr += 4;
        }

        if (nvs_ptr >= (u8 *) wl->nvs + nvs_len)
            goto out_badnvs;
    }

    /*
     * We've reached the first zero length, the first NVS table
     * is located at an aligned offset which is at least 7 bytes further.
     * NOTE: The wl->nvs->nvs element must be first, in order to
     * simplify the casting, we assume it is at the beginning of
     * the wl->nvs structure.
     */
    nvs_ptr = (u8 *)wl->nvs +
              ALIGN(nvs_ptr - (u8 *)wl->nvs + 7, 4);

    if (nvs_ptr >= (u8 *) wl->nvs + nvs_len)
        goto out_badnvs;

    nvs_len -= nvs_ptr - (u8 *)wl->nvs;

    /* Now we must set the partition correctly */
    ret = wl1271_set_partition(wl, &wl12xx_part_table[PART_WORK]);
    if (ret < 0)
        return ret;

    /* Copy the NVS tables to a new block to ensure alignment */
    nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL);
    if (!nvs_aligned)
        return -ENOMEM;

    /* And finally we upload the NVS tables */
    ret = wl1271_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, false);
    if (ret < 0)
        return ret;

    kfree(nvs_aligned);
    return 0;

out_badnvs:
    wl1271_error("nvs data is malformed");
    return -EILSEQ;
}
Example #18
0
void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status)
{
	struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map;
	u32 buf_size;
	u32 fw_rx_counter  = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
	u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
	u32 rx_counter;
	u32 mem_block;
	u32 pkt_length;
	u32 pkt_offset;
	bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
	bool had_data = false;
	bool unaligned = false;

	while (drv_rx_counter != fw_rx_counter) {
		buf_size = 0;
		rx_counter = drv_rx_counter;
		while (rx_counter != fw_rx_counter) {
			pkt_length = wl1271_rx_get_buf_size(status, rx_counter);
			if (buf_size + pkt_length > WL1271_AGGR_BUFFER_SIZE)
				break;
			buf_size += pkt_length;
			rx_counter++;
			rx_counter &= NUM_RX_PKT_DESC_MOD_MASK;
		}

		if (buf_size == 0) {
			wl1271_warning("received empty data");
			break;
		}

		if (wl->chip.id != CHIP_ID_1283_PG20) {
			/*
			 * Choose the block we want to read
			 * For aggregated packets, only the first memory block
			 * should be retrieved. The FW takes care of the rest.
			 */
			mem_block = wl1271_rx_get_mem_block(status,
							    drv_rx_counter);

			wl->rx_mem_pool_addr.addr = (mem_block << 8) +
			   le32_to_cpu(wl_mem_map->packet_memory_pool_start);

			wl->rx_mem_pool_addr.addr_extra =
				wl->rx_mem_pool_addr.addr + 4;

			wl1271_write(wl, WL1271_SLV_REG_DATA,
				     &wl->rx_mem_pool_addr,
				     sizeof(wl->rx_mem_pool_addr), false);
		}

		/* Read all available packets at once */
		wl1271_read(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf,
				buf_size, true);

		/* Split data into separate packets */
		pkt_offset = 0;
		while (pkt_offset < buf_size) {
			pkt_length = wl1271_rx_get_buf_size(status,
					drv_rx_counter);

			unaligned = wl1271_rx_get_unaligned(status,
					drv_rx_counter);

			/*
			 * the handle data call can only fail in memory-outage
			 * conditions, in that case the received frame will just
			 * be dropped.
			 */
			if (wl1271_rx_handle_data(wl,
						  wl->aggr_buf + pkt_offset,
						  pkt_length, unaligned) == 1)
				had_data = true;

			wl->rx_counter++;
			drv_rx_counter++;
			drv_rx_counter &= NUM_RX_PKT_DESC_MOD_MASK;
			pkt_offset += pkt_length;
		}
	}

	/*
	 * Write the driver's packet counter to the FW. This is only required
	 * for older hardware revisions
	 */
	if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION)
		wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);

	if (!is_ap && wl->conf.rx_streaming.interval && had_data &&
	    (wl->conf.rx_streaming.always ||
	     test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) {
		u32 timeout = wl->conf.rx_streaming.duration;

		/* restart rx streaming */
		if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags))
			ieee80211_queue_work(wl->hw,
					     &wl->rx_streaming_enable_work);

		mod_timer(&wl->rx_streaming_timer,
			  jiffies + msecs_to_jiffies(timeout));
	}
}
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;
}
Example #20
0
void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
{
	struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map;
	u32 buf_size;
	u32 fw_rx_counter  = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
	u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
	u32 rx_counter;
	u32 mem_block;
	u32 pkt_length;
	u32 pkt_offset;

	while (drv_rx_counter != fw_rx_counter) {
		buf_size = 0;
		rx_counter = drv_rx_counter;
		while (rx_counter != fw_rx_counter) {
			pkt_length = wl1271_rx_get_buf_size(status, rx_counter);
			if (buf_size + pkt_length > WL1271_AGGR_BUFFER_SIZE)
				break;
			buf_size += pkt_length;
			rx_counter++;
			rx_counter &= NUM_RX_PKT_DESC_MOD_MASK;
		}

		if (buf_size == 0) {
			wl1271_warning("received empty data");
			break;
		}

		/*
		 * Choose the block we want to read
		 * For aggregated packets, only the first memory block should
		 * be retrieved. The FW takes care of the rest.
		 */
		mem_block = wl1271_rx_get_mem_block(status, drv_rx_counter);
		wl->rx_mem_pool_addr.addr = (mem_block << 8) +
			le32_to_cpu(wl_mem_map->packet_memory_pool_start);
		wl->rx_mem_pool_addr.addr_extra =
			wl->rx_mem_pool_addr.addr + 4;
		wl1271_write(wl, WL1271_SLV_REG_DATA, &wl->rx_mem_pool_addr,
				sizeof(wl->rx_mem_pool_addr), false);

		/* Read all available packets at once */
		wl1271_read(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf,
				buf_size, true);

		/* Split data into separate packets */
		pkt_offset = 0;
		while (pkt_offset < buf_size) {
			pkt_length = wl1271_rx_get_buf_size(status,
					drv_rx_counter);
			/*
			 * the handle data call can only fail in memory-outage
			 * conditions, in that case the received frame will just
			 * be dropped.
			 */
			wl1271_rx_handle_data(wl,
					      wl->aggr_buf + pkt_offset,
					      pkt_length);
			wl->rx_counter++;
			drv_rx_counter++;
			drv_rx_counter &= NUM_RX_PKT_DESC_MOD_MASK;
			pkt_offset += pkt_length;
		}
	}
	wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
}
static int wl1271_boot_upload_nvs(struct wl1271 *wl)
{
	size_t nvs_len, burst_len;
	int i;
	u32 dest_addr, val;
	u8 *nvs_ptr, *nvs_aligned;

	if (wl->nvs == NULL)
		return -ENODEV;

	/* only the first part of the NVS needs to be uploaded */
	nvs_len = sizeof(wl->nvs->nvs);
	nvs_ptr = (u8 *)wl->nvs->nvs;

	/*
	 * Layout before the actual NVS tables:
	 * 1 byte : burst length.
	 * 2 bytes: destination address.
	 * n bytes: data to burst copy.
	 *
	 * This is ended by a 0 length, then the NVS tables.
	 */

	/* FIXME: Do we need to check here whether the LSB is 1? */
	while (nvs_ptr[0]) {
		burst_len = nvs_ptr[0];
		dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8));

		/* FIXME: Due to our new wl1271_translate_reg_addr function,
		   we need to add the REGISTER_BASE to the destination */
		dest_addr += REGISTERS_BASE;

		/* We move our pointer to the data */
		nvs_ptr += 3;

		for (i = 0; i < burst_len; i++) {
			val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
			       | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));

			wl1271_debug(DEBUG_BOOT,
				     "nvs burst write 0x%x: 0x%x",
				     dest_addr, val);
			wl1271_write32(wl, dest_addr, val);

			nvs_ptr += 4;
			dest_addr += 4;
		}
	}

	/*
	 * We've reached the first zero length, the first NVS table
	 * is 7 bytes further.
	 */
	nvs_ptr += 7;
	nvs_len -= nvs_ptr - (u8 *)wl->nvs->nvs;
	nvs_len = ALIGN(nvs_len, 4);

	/* FIXME: The driver sets the partition here, but this is not needed,
	   since it sets to the same one as currently in use */
	/* Now we must set the partition correctly */
	wl1271_set_partition(wl, &part_table[PART_WORK]);

	/* Copy the NVS tables to a new block to ensure alignment */
	/* FIXME: We jump 3 more bytes before uploading the NVS.  It seems
	that our NVS files have three extra zeros here.  I'm not sure whether
	the problem is in our NVS generation or we should really jumpt these
	3 bytes here */
	nvs_ptr += 3;

	nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); if
	(!nvs_aligned) return -ENOMEM;

	/* And finally we upload the NVS tables */
	/* FIXME: In wl1271, we upload everything at once.
	   No endianness handling needed here?! The ref driver doesn't do
	   anything about it at this point */
	wl1271_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, false);

	kfree(nvs_aligned);
	return 0;
}