Example #1
0
int wl1251_hw_init_mem_config(struct wl1251 *wl)
{
	int ret;

	ret = wl1251_acx_mem_cfg(wl);
	if (ret < 0)
		return ret;

	wl->target_mem_map = kzalloc(sizeof(struct wl1251_acx_mem_map),
					  GFP_KERNEL);
	if (!wl->target_mem_map) {
		wl1251_error("couldn't allocate target memory map");
		return -ENOMEM;
	}

	/* we now ask for the firmware built memory map */
	ret = wl1251_acx_mem_map(wl, wl->target_mem_map,
				 sizeof(struct wl1251_acx_mem_map));
	if (ret < 0) {
		wl1251_error("couldn't retrieve firmware memory map");
		kfree(wl->target_mem_map);
		wl->target_mem_map = NULL;
		return ret;
	}

	return 0;
}
Example #2
0
static struct wl1251 *ifname_to_wl1251(struct net *net, struct genl_info *info)
{
	struct net_device *netdev;
	struct wireless_dev *wdev;
	struct wiphy *wiphy;
	struct ieee80211_hw *hw;

	netdev = ifname_to_netdev(net, info);
	if (netdev == NULL) {
		wl1251_error("Wrong interface");
		return NULL;
	}

	wdev = netdev->ieee80211_ptr;
	if (wdev == NULL) {
		wl1251_error("ieee80211_ptr is NULL");
		return NULL;
	}

	wiphy = wdev->wiphy;
	if (wiphy == NULL) {
		wl1251_error("wiphy is NULL");
		return NULL;
	}

	hw = wiphy_priv(wiphy);
	if (hw == NULL) {
		wl1251_error("hw is NULL");
		return NULL;
	}

	dev_put(netdev);

	return hw->priv;
}
Example #3
0
/**
 * read acx from firmware
 *
 * @wl: wl struct
 * @id: acx id
 * @buf: buffer for the response, including all headers, must work with dma
 * @len: length of buf
 */
int wl1251_cmd_interrogate(struct wl1251 *wl, u16 id, void *buf, size_t len)
{
	struct acx_header *acx = buf;
	int ret;

	wl1251_debug(DEBUG_CMD, "cmd interrogate");

	acx->id = id;

	/* payload length, does not include any headers */
	acx->len = len - sizeof(*acx);

	ret = wl1251_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx));
	if (ret < 0) {
		wl1251_error("INTERROGATE command failed");
		goto out;
	}

	/* the interrogate command got in, we can read the answer */
	wl1251_mem_read(wl, wl->cmd_box_addr, buf, len);

	acx = buf;
	if (acx->cmd.status != CMD_STATUS_SUCCESS)
		wl1251_error("INTERROGATE command error: %d",
			     acx->cmd.status);

out:
	return ret;
}
int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len,
		    struct ieee80211_channel *channels[],
		    unsigned int n_channels, unsigned int n_probes)
{
	struct wl1251_cmd_scan *cmd;
	int i, ret = 0;

	wl1251_debug(DEBUG_CMD, "cmd scan");

	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
	if (!cmd)
		return -ENOMEM;

	cmd->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD);
	cmd->params.rx_filter_options = cpu_to_le32(CFG_RX_PRSP_EN |
						    CFG_RX_MGMT_EN |
						    CFG_RX_BCN_EN);
	cmd->params.scan_options = 0;
	cmd->params.num_channels = n_channels;
	cmd->params.num_probe_requests = n_probes;
	cmd->params.tx_rate = cpu_to_le16(1 << 1); /* 2 Mbps */
	cmd->params.tid_trigger = 0;

	for (i = 0; i < n_channels; i++) {
		cmd->channels[i].min_duration =
			cpu_to_le32(WL1251_SCAN_MIN_DURATION);
		cmd->channels[i].max_duration =
			cpu_to_le32(WL1251_SCAN_MAX_DURATION);
		memset(&cmd->channels[i].bssid_lsb, 0xff, 4);
		memset(&cmd->channels[i].bssid_msb, 0xff, 2);
		cmd->channels[i].early_termination = 0;
		cmd->channels[i].tx_power_att = 0;
		cmd->channels[i].channel = channels[i]->hw_value;
	}

	cmd->params.ssid_len = ssid_len;
	if (ssid)
		memcpy(cmd->params.ssid, ssid, ssid_len);

	ret = wl1251_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd));
	if (ret < 0) {
		wl1251_error("cmd scan failed: %d", ret);
		goto out;
	}

	wl1251_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd));

	if (cmd->header.status != CMD_STATUS_SUCCESS) {
		wl1251_error("cmd scan status wasn't success: %d",
			     cmd->header.status);
		ret = -EIO;
		goto out;
	}

out:
	kfree(cmd);
	return ret;
}
Example #5
0
static int wl1251_nl_reg_read(struct sk_buff *skb, struct genl_info *info)
{
	struct wl1251 *wl;
	u32 addr, val;
	int ret = 0;
	struct sk_buff *msg;
	void *hdr;

	if (!info->attrs[WL1251_NL_ATTR_REG_ADDR])
		return -EINVAL;

	msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
	if (!msg)
		return -ENOMEM;

	wl = ifname_to_wl1251(&init_net, info);
	if (wl == NULL) {
		wl1251_error("wl1251 not found");
		return -EINVAL;
	}

	addr = nla_get_u32(info->attrs[WL1251_NL_ATTR_REG_ADDR]);

	mutex_lock(&wl->mutex);
	val = wl1251_reg_read32(wl, addr);
	mutex_unlock(&wl->mutex);

	hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq,
			  &wl1251_nl_family, 0, WL1251_NL_CMD_PHY_REG_READ);
	if (IS_ERR(hdr)) {
		ret = PTR_ERR(hdr);
		goto nla_put_failure;
	}

	NLA_PUT_STRING(msg, WL1251_NL_ATTR_IFNAME,
		       nla_data(info->attrs[WL1251_NL_ATTR_IFNAME]));

	NLA_PUT_U32(msg, WL1251_NL_ATTR_REG_VAL, val);

	ret = genlmsg_end(msg, hdr);
	if (ret < 0) {
		wl1251_error("%s() failed", __func__);
		goto nla_put_failure;
	}

	return genlmsg_reply(msg, info);

 nla_put_failure:
	nlmsg_free(msg);

	return ret;
}
static int __init wl1251_sdio_init(void)
{
	int err;

	err = platform_driver_register(&wl1251_platform_driver);
	if (err) {
		wl1251_error("failed to register platform driver: %d", err);
		return err;
	}

	err = sdio_register_driver(&wl1251_sdio_driver);
	if (err)
		wl1251_error("failed to register sdio driver: %d", err);
	return err;
}
int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable)
{
	struct cmd_enabledisable_path *cmd;
	int ret;
	u16 cmd_rx, cmd_tx;

	wl1251_debug(DEBUG_CMD, "cmd data path");

	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
	if (!cmd) {
		ret = -ENOMEM;
		goto out;
	}

	cmd->channel = channel;

	if (enable) {
		cmd_rx = CMD_ENABLE_RX;
		cmd_tx = CMD_ENABLE_TX;
	} else {
		cmd_rx = CMD_DISABLE_RX;
		cmd_tx = CMD_DISABLE_TX;
	}

	ret = wl1251_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd));
	if (ret < 0) {
		wl1251_error("rx %s cmd for channel %d failed",
			     enable ? "start" : "stop", channel);
		goto out;
	}

	wl1251_debug(DEBUG_BOOT, "rx %s cmd channel %d",
		     enable ? "start" : "stop", channel);

	ret = wl1251_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd));
	if (ret < 0) {
		wl1251_error("tx %s cmd for channel %d failed",
			     enable ? "start" : "stop", channel);
		return ret;
	}

	wl1251_debug(DEBUG_BOOT, "tx %s cmd channel %d",
		     enable ? "start" : "stop", channel);

out:
	kfree(cmd);
	return ret;
}
Example #8
0
static int wl1251_nl_set_plt_mode(struct sk_buff *skb, struct genl_info *info)
{
	struct wl1251 *wl;
	u32 val;
	int ret;

	if (!info->attrs[WL1251_NL_ATTR_PLT_MODE])
		return -EINVAL;

	wl = ifname_to_wl1251(&init_net, info);
	if (wl == NULL) {
		wl1251_error("wl1251 not found");
		return -EINVAL;
	}

	val = nla_get_u32(info->attrs[WL1251_NL_ATTR_PLT_MODE]);

	switch (val) {
	case 0:
		ret = wl1251_plt_stop(wl);
		break;
	case 1:
		ret = wl1251_plt_start(wl);
		break;
	default:
		ret = -EINVAL;
		break;
	}

	return ret;
}
Example #9
0
static int wl1251_nl_reg_write(struct sk_buff *skb, struct genl_info *info)
{
	struct wl1251 *wl;
	u32 addr, val;

	if (!info->attrs[WL1251_NL_ATTR_REG_ADDR])
		return -EINVAL;

	if (!info->attrs[WL1251_NL_ATTR_REG_VAL])
		return -EINVAL;

	wl = ifname_to_wl1251(&init_net, info);
	if (wl == NULL) {
		wl1251_error("wl1251 not found");
		return -EINVAL;
	}

	addr = nla_get_u32(info->attrs[WL1251_NL_ATTR_REG_ADDR]);
	val = nla_get_u32(info->attrs[WL1251_NL_ATTR_REG_VAL]);

	mutex_lock(&wl->mutex);
	wl1251_reg_write32(wl, addr, val);
	mutex_unlock(&wl->mutex);

	return 0;
}
int wl1251_cmd_ps_mode(struct wl1251 *wl, u8 ps_mode)
{
	struct wl1251_cmd_ps_params *ps_params = NULL;
	int ret = 0;

	wl1251_debug(DEBUG_CMD, "cmd set ps mode");

	ps_params = kzalloc(sizeof(*ps_params), GFP_KERNEL);
	if (!ps_params) {
		ret = -ENOMEM;
		goto out;
	}

	ps_params->ps_mode = ps_mode;
	ps_params->send_null_data = 1;
	ps_params->retries = 5;
	ps_params->hang_over_period = 128;
	ps_params->null_data_rate = 1; /* 1 Mbps */

	ret = wl1251_cmd_send(wl, CMD_SET_PS_MODE, ps_params,
			      sizeof(*ps_params));
	if (ret < 0) {
		wl1251_error("cmd set_ps_mode failed");
		goto out;
	}

out:
	kfree(ps_params);
	return ret;
}
Example #11
0
/**
 * send test command to firmware
 *
 * @wl: wl struct
 * @buf: buffer containing the command, with all headers, must work with dma
 * @len: length of the buffer
 * @answer: is answer needed
 */
int wl1251_cmd_test(struct wl1251 *wl, void *buf, size_t buf_len, u8 answer)
{
	int ret;

	wl1251_debug(DEBUG_CMD, "cmd test");

	ret = wl1251_cmd_send(wl, CMD_TEST, buf, buf_len);

	if (ret < 0) {
		wl1251_warning("TEST command failed");
		return ret;
	}

	if (answer) {
		struct wl1251_command *cmd_answer;

		/*
		 * The test command got in, we can read the answer.
		 * The answer would be a wl1251_command, where the
		 * parameter array contains the actual answer.
		 */
		wl1251_mem_read(wl, wl->cmd_box_addr, buf, buf_len);

		cmd_answer = buf;

		if (cmd_answer->header.status != CMD_STATUS_SUCCESS)
			wl1251_error("TEST command answer error: %d",
				     cmd_answer->header.status);
	}

	return 0;
}
Example #12
0
int wl1251_acx_default_key(struct wl1251 *wl, u8 key_id)
{
	struct acx_dot11_default_key *default_key;
	int ret;

	wl1251_debug(DEBUG_ACX, "acx dot11_default_key (%d)", key_id);

	default_key = kzalloc(sizeof(*default_key), GFP_KERNEL);
	if (!default_key)
		return -ENOMEM;

	default_key->id = key_id;

	ret = wl1251_cmd_configure(wl, DOT11_DEFAULT_KEY,
				   default_key, sizeof(*default_key));
	if (ret < 0) {
		wl1251_error("Couldn't set default key");
		goto out;
	}

	wl->default_key = key_id;

out:
	kfree(default_key);
	return ret;
}
Example #13
0
int wl1251_boot_soft_reset(struct wl1251 *wl)
{
	unsigned long timeout;
	u32 boot_data;

	/* perform soft reset */
	wl1251_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 = wl1251_reg_read32(wl, ACX_REG_SLV_SOFT_RESET);
		wl1251_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 */
			wl1251_error("soft reset timeout");
			return -1;
		}

		udelay(SOFT_RESET_STALL_TIME);
	}

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

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

	return 0;
}
Example #14
0
int wl1251_boot_soft_reset(struct wl1251 *wl)
{
	unsigned long timeout;
	u32 boot_data;

	/*                    */
	wl1251_reg_write32(wl, ACX_REG_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT);

	/*                             */
	timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME);
	while (1) {
		boot_data = wl1251_reg_read32(wl, ACX_REG_SLV_SOFT_RESET);
		wl1251_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)) {
			/*                                          
                          */
			wl1251_error("soft reset timeout");
			return -1;
		}

		udelay(SOFT_RESET_STALL_TIME);
	}

	/*               */
	wl1251_reg_write32(wl, ENABLE, 0x0);

	/*                                  */
	wl1251_reg_write32(wl, SPARE_A2, 0xffff);

	return 0;
}
Example #15
0
File: event.c Project: 020gzh/linux
static int wl1251_event_ps_report(struct wl1251 *wl,
				  struct event_mailbox *mbox)
{
	int ret = 0;

	wl1251_debug(DEBUG_EVENT, "ps status: %x", mbox->ps_status);

	switch (mbox->ps_status) {
	case EVENT_ENTER_POWER_SAVE_FAIL:
		wl1251_debug(DEBUG_PSM, "PSM entry failed");

		if (wl->station_mode != STATION_POWER_SAVE_MODE) {
			/* remain in active mode */
			wl->psm_entry_retry = 0;
			break;
		}

		if (wl->psm_entry_retry < WL1251_PSM_ENTRY_RETRIES) {
			wl->psm_entry_retry++;
			ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
		} else {
			wl1251_error("Power save entry failed, giving up");
			wl->psm_entry_retry = 0;
		}
		break;
	case EVENT_ENTER_POWER_SAVE_SUCCESS:
	case EVENT_EXIT_POWER_SAVE_FAIL:
	case EVENT_EXIT_POWER_SAVE_SUCCESS:
	default:
		wl->psm_entry_retry = 0;
		break;
	}

	return 0;
}
Example #16
0
int wl1251_acx_frame_rates(struct wl1251 *wl, u8 ctrl_rate, u8 ctrl_mod,
			   u8 mgt_rate, u8 mgt_mod)
{
	struct acx_fw_gen_frame_rates *rates;
	int ret;

	wl1251_debug(DEBUG_ACX, "acx frame rates");

	rates = kzalloc(sizeof(*rates), GFP_KERNEL);
	if (!rates)
		return -ENOMEM;

	rates->tx_ctrl_frame_rate = ctrl_rate;
	rates->tx_ctrl_frame_mod = ctrl_mod;
	rates->tx_mgt_frame_rate = mgt_rate;
	rates->tx_mgt_frame_mod = mgt_mod;

	ret = wl1251_cmd_configure(wl, ACX_FW_GEN_FRAME_RATES,
				   rates, sizeof(*rates));
	if (ret < 0) {
		wl1251_error("Failed to set FW rates and modulation");
		goto out;
	}

out:
	kfree(rates);
	return ret;
}
Example #17
0
int wl1251_acx_feature_cfg(struct wl1251 *wl)
{
	struct acx_feature_config *feature;
	int ret;

	wl1251_debug(DEBUG_ACX, "acx feature cfg");

	feature = kzalloc(sizeof(*feature), GFP_KERNEL);
	if (!feature)
		return -ENOMEM;

	/* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */
	feature->data_flow_options = 0;
	feature->options = 0;

	ret = wl1251_cmd_configure(wl, ACX_FEATURE_CFG,
				   feature, sizeof(*feature));
	if (ret < 0) {
		wl1251_error("Couldn't set HW encryption");
		goto out;
	}

out:
	kfree(feature);
	return ret;
}
Example #18
0
static int wl1251_event_ps_report(struct wl1251 *wl,
				  struct event_mailbox *mbox)
{
	int ret = 0;

	wl1251_debug(DEBUG_EVENT, "ps status: %x", mbox->ps_status);

	switch (mbox->ps_status) {
	case ENTER_POWER_SAVE_FAIL:
		if (!wl->psm) {
			wl->ps_entry_retry = 0;
			break;
		}

		if (wl->ps_entry_retry < WL1251_PS_ENTRY_RETRIES) {
			ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
			wl->ps_entry_retry++;
		} else {
			wl1251_error("Power save entry failed, giving up");
			wl->ps_entry_retry = 0;
		}
		break;
	case ENTER_POWER_SAVE_SUCCESS:
	default:
		wl->ps_entry_retry = 0;
		break;
	}

	return 0;
}
Example #19
0
File: spi.c Project: 03199618/linux
static void wl1251_spi_reset(struct wl1251 *wl)
{
	u8 *cmd;
	struct spi_transfer t;
	struct spi_message m;

	cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
	if (!cmd) {
		wl1251_error("could not allocate cmd for spi reset");
		return;
	}

	memset(&t, 0, sizeof(t));
	spi_message_init(&m);

	memset(cmd, 0xff, WSPI_INIT_CMD_LEN);

	t.tx_buf = cmd;
	t.len = WSPI_INIT_CMD_LEN;
	spi_message_add_tail(&t, &m);

	spi_sync(wl_to_spi(wl), &m);

	wl1251_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN);

	kfree(cmd);
}
Example #20
0
int wl1251_ps_elp_wakeup(struct wl1251 *wl)
{
	unsigned long timeout;
	u32 elp_reg;

	if (!wl->elp)
		return 0;

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

	timeout = jiffies + msecs_to_jiffies(WL1251_WAKEUP_TIMEOUT);

	wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP);

	elp_reg = wl1251_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);

	
	while (!(elp_reg & ELPCTRL_WLAN_READY)) {
		if (time_after(jiffies, timeout)) {
			wl1251_error("elp wakeup timeout");
			return -ETIMEDOUT;
		}
		msleep(1);
		elp_reg = wl1251_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR);
	}

	wl1251_debug(DEBUG_PSM, "wakeup time: %u ms",
		     jiffies_to_msecs(jiffies) -
		     (jiffies_to_msecs(timeout) - WL1251_WAKEUP_TIMEOUT));

	wl->elp = false;

	return 0;
}
Example #21
0
static int wl1251_nl_nvs_push(struct sk_buff *skb, struct genl_info *info)
{
	struct wl1251 *wl;
	int ret = 0;

	if (!info->attrs[WL1251_NL_ATTR_NVS_BUFFER])
		return -EINVAL;

	if (!info->attrs[WL1251_NL_ATTR_NVS_LEN])
		return -EINVAL;

	wl = ifname_to_wl1251(&init_net, info);
	if (wl == NULL) {
		wl1251_error("wl1251 not found");
		return -EINVAL;
	}

	mutex_lock(&wl->mutex);
	wl->nvs_len = nla_get_u32(info->attrs[WL1251_NL_ATTR_NVS_LEN]);
	if (wl->nvs_len % 4) {
		wl1251_error("NVS size is not multiple of 32: %d", wl->nvs_len);
		ret = -EILSEQ;
		goto out;
	}

	/* If we already have an NVS, we should free it */
	kfree(wl->nvs);

	wl->nvs = kzalloc(wl->nvs_len, GFP_KERNEL);
	if (wl->nvs == NULL) {
		wl1251_error("Can't allocate NVS");
		ret = -ENOMEM;
		goto out;
	}

	memcpy(wl->nvs,
	       nla_data(info->attrs[WL1251_NL_ATTR_NVS_BUFFER]),
	       wl->nvs_len);

	wl1251_debug(DEBUG_NETLINK, "got NVS from userspace, %d bytes",
		     wl->nvs_len);

out:
	mutex_unlock(&wl->mutex);

	return ret;
}
static int wl1251_sdio_set_power(struct wl1251 *wl, bool enable)
{
	int ret = 0;
	struct sdio_func *func = wl_to_func(wl);

	wl1251_enter();
	if (enable) {
		if (wl->set_power)
			wl->set_power(true);

		ret = mmc_power_restore_host(func->card->host);
		if (ret) {
			wl1251_error("failed to restore host power");
			goto out;
		}

		wl1251_debug(DEBUG_PSM, "sdio_claim_host");
		sdio_claim_host(func);
		wl1251_debug(DEBUG_PSM, "sdio_enable_func");
		sdio_enable_func(func);
		wl1251_debug(DEBUG_PSM, "sdio_release_host");
		sdio_release_host(func);
		wl1251_debug(DEBUG_PSM, "sdio_done");
	} else {
		wl1251_debug(DEBUG_PSM, "sdio_claim_host");
		sdio_claim_host(func);
		wl1251_debug(DEBUG_PSM, "sdio_disable_func");
		sdio_disable_func(func);
		wl1251_debug(DEBUG_PSM, "sdio_release_host");
		sdio_release_host(func);
		wl1251_debug(DEBUG_PSM, "power_save_host");
		ret = mmc_power_save_host(func->card->host);
		if (ret) {
			wl1251_error("failed to disable host power");
			goto out;
		}
		wl1251_debug(DEBUG_PSM, "power_save done");

		if (wl->set_power)
			wl->set_power(false);
	}

out:
	wl1251_leave();
	return ret;
}
static int wl1251_chip_wakeup(struct wl1251 *wl)
{
	int ret = 0;

	wl1251_power_on(wl);
	msleep(WL1251_POWER_ON_SLEEP);
	wl->if_ops->reset(wl);

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

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

	/* whal_FwCtrl_BootSm() */

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

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

	switch (wl->chip_id) {
	case CHIP_ID_1251_PG12:
		wl1251_debug(DEBUG_BOOT, "chip id 0x%x (1251 PG12)",
			     wl->chip_id);
		break;
	case CHIP_ID_1251_PG11:
		wl1251_debug(DEBUG_BOOT, "chip id 0x%x (1251 PG11)",
			     wl->chip_id);
		break;
	case CHIP_ID_1251_PG10:
	default:
		wl1251_error("unsupported chip id: 0x%x", wl->chip_id);
		ret = -ENODEV;
		goto out;
	}

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

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

out:
	return ret;
}
static int wl1251_platform_probe(struct platform_device *pdev)
{
	if (pdev->id != -1) {
		wl1251_error("can only handle single device");
		return -ENODEV;
	}

	wl12xx_board_data = pdev->dev.platform_data;
	return 0;
}
Example #25
0
static void wl1251_spi_wake(struct wl1251 *wl)
{
	u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd;
	struct spi_transfer t;
	struct spi_message m;

	cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
	if (!cmd) {
		wl1251_error("could not allocate cmd for spi init");
		return;
	}

	memset(crc, 0, sizeof(crc));
	memset(&t, 0, sizeof(t));
	spi_message_init(&m);

	/*
	 * Set WSPI_INIT_COMMAND
	 * the data is being send from the MSB to LSB
	 */
	cmd[2] = 0xff;
	cmd[3] = 0xff;
	cmd[1] = WSPI_INIT_CMD_START | WSPI_INIT_CMD_TX;
	cmd[0] = 0;
	cmd[7] = 0;
	cmd[6] |= HW_ACCESS_WSPI_INIT_CMD_MASK << 3;
	cmd[6] |= HW_ACCESS_WSPI_FIXED_BUSY_LEN & WSPI_INIT_CMD_FIXEDBUSY_LEN;

	if (HW_ACCESS_WSPI_FIXED_BUSY_LEN == 0)
		cmd[5] |=  WSPI_INIT_CMD_DIS_FIXEDBUSY;
	else
		cmd[5] |= WSPI_INIT_CMD_EN_FIXEDBUSY;

	cmd[5] |= WSPI_INIT_CMD_IOD | WSPI_INIT_CMD_IP | WSPI_INIT_CMD_CS
		| WSPI_INIT_CMD_WSPI | WSPI_INIT_CMD_WS;

	crc[0] = cmd[1];
	crc[1] = cmd[0];
	crc[2] = cmd[7];
	crc[3] = cmd[6];
	crc[4] = cmd[5];

	cmd[4] |= crc7(0, crc, WSPI_INIT_CMD_CRC_LEN) << 1;
	cmd[4] |= WSPI_INIT_CMD_END;

	t.tx_buf = cmd;
	t.len = WSPI_INIT_CMD_LEN;
	spi_message_add_tail(&t, &m);

	spi_sync(wl_to_spi(wl), &m);

	wl1251_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN);

	kfree(cmd);
}
Example #26
0
static void wl1251_rx_body(struct wl1251 *wl,
			   struct wl1251_rx_descriptor *desc)
{
	struct sk_buff *skb;
	struct ieee80211_rx_status status;
	u8 *rx_buffer, beacon = 0;
	u16 length, *fc;
	u32 curr_id, last_id_inc, rx_packet_ring_addr;

	length = WL1251_RX_ALIGN(desc->length  - PLCP_HEADER_LENGTH);
	curr_id = (desc->flags & RX_DESC_SEQNUM_MASK) >> RX_DESC_PACKETID_SHIFT;
	last_id_inc = (wl->rx_last_id + 1) % (RX_MAX_PACKET_ID + 1);

	if (last_id_inc != curr_id) {
		wl1251_warning("curr ID:%d, last ID inc:%d",
			       curr_id, last_id_inc);
		wl->rx_last_id = curr_id;
	} else {
		wl->rx_last_id = last_id_inc;
	}

	rx_packet_ring_addr = wl->data_path->rx_packet_ring_addr +
		sizeof(struct wl1251_rx_descriptor) + 20;
	if (wl->rx_current_buffer)
		rx_packet_ring_addr += wl->data_path->rx_packet_ring_chunk_size;

	skb = __dev_alloc_skb(length, GFP_KERNEL);
	if (!skb) {
		wl1251_error("Couldn't allocate RX frame");
		return;
	}

	rx_buffer = skb_put(skb, length);
	wl1251_mem_read(wl, rx_packet_ring_addr, rx_buffer, length);

	/* The actual length doesn't include the target's alignment */
	skb_trim(skb, desc->length - PLCP_HEADER_LENGTH);

	fc = (u16 *)skb->data;

	if ((*fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON)
		beacon = 1;

	wl1251_rx_status(wl, desc, &status, beacon);

	wl1251_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, skb->len,
		     beacon ? "beacon" : "");

	memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
	ieee80211_rx_ni(wl->hw, skb);

	wl1251_update_rate(wl, length);
}
int wl1251_cmd_join(struct wl1251 *wl, u8 bss_type, u8 channel,
		    u16 beacon_interval, u8 dtim_interval)
{
	struct cmd_join *join;
	int ret, i;
	u8 *bssid;

	join = kzalloc(sizeof(*join), GFP_KERNEL);
	if (!join) {
		ret = -ENOMEM;
		goto out;
	}

	wl1251_debug(DEBUG_CMD, "cmd join%s ch %d %d/%d",
		     bss_type == BSS_TYPE_IBSS ? " ibss" : "",
		     channel, beacon_interval, dtim_interval);

	/* Reverse order BSSID */
	bssid = (u8 *) &join->bssid_lsb;
	for (i = 0; i < ETH_ALEN; i++)
		bssid[i] = wl->bssid[ETH_ALEN - i - 1];

	join->rx_config_options = wl->rx_config;
	join->rx_filter_options = wl->rx_filter;

	/*
	 * FIXME: disable temporarily all filters because after commit
	 * 9cef8737 "mac80211: fix managed mode BSSID handling" broke
	 * association. The filter logic needs to be implemented properly
	 * and once that is done, this hack can be removed.
	 */
	join->rx_config_options = 0;
	join->rx_filter_options = WL1251_DEFAULT_RX_FILTER;

	join->basic_rate_set = RATE_MASK_1MBPS | RATE_MASK_2MBPS |
		RATE_MASK_5_5MBPS | RATE_MASK_11MBPS;

	join->beacon_interval = beacon_interval;
	join->dtim_interval = dtim_interval;
	join->bss_type = bss_type;
	join->channel = channel;
	join->ctrl = JOIN_CMD_CTRL_TX_FLUSH;

	ret = wl1251_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join));
	if (ret < 0) {
		wl1251_error("failed to initiate cmd join");
		goto out;
	}

out:
	kfree(join);
	return ret;
}
static void wl1251_sdio_write_elp(struct wl1251 *wl, int addr, u32 val)
{
	int ret = 0;
	struct sdio_func *func = wl_to_func(wl);

	sdio_claim_host(func);
	sdio_writeb(func, val, addr, &ret);
	sdio_release_host(func);

	if (ret)
		wl1251_error("sdio_writeb failed (%d)", ret);
}
Example #29
0
static void wl1251_sdio_write(struct wl1251 *wl, int addr,
			      void *buf, size_t len)
{
	int ret;
	struct sdio_func *func = wl_to_func(wl);

	sdio_claim_host(func);
	ret = sdio_memcpy_toio(func, addr, buf, len);
	if (ret)
		wl1251_error("sdio write failed (%d)", ret);
	sdio_release_host(func);
}
Example #30
0
static int __init wl1251_spi_init(void)
{
	int ret;

	ret = spi_register_driver(&wl1251_spi_driver);
	if (ret < 0) {
		wl1251_error("failed to register spi driver: %d", ret);
		goto out;
	}

out:
	return ret;
}