Merge branch 'for-linville' of git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx

This commit is contained in:
John W. Linville
2011-04-25 14:36:35 -04:00
29 changed files with 1326 additions and 291 deletions
+1 -1
View File
@@ -3,7 +3,7 @@ menuconfig WL12XX_MENU
depends on MAC80211 && EXPERIMENTAL
---help---
This will enable TI wl12xx driver support for the following chips:
wl1271 and wl1273.
wl1271, wl1273, wl1281 and wl1283.
The drivers make use of the mac80211 stack.
config WL12XX
+47 -12
View File
@@ -965,10 +965,13 @@ int wl1271_acx_ap_mem_cfg(struct wl1271 *wl)
}
/* memory config */
mem_conf->num_stations = wl->conf.mem.num_stations;
mem_conf->rx_mem_block_num = wl->conf.mem.rx_block_num;
mem_conf->tx_min_mem_block_num = wl->conf.mem.tx_min_block_num;
mem_conf->num_ssid_profiles = wl->conf.mem.ssid_profiles;
/* FIXME: for now we always use mem_wl127x for AP, because it
* doesn't support dynamic memory and we don't have the
* optimal values for wl128x without dynamic memory yet */
mem_conf->num_stations = wl->conf.mem_wl127x.num_stations;
mem_conf->rx_mem_block_num = wl->conf.mem_wl127x.rx_block_num;
mem_conf->tx_min_mem_block_num = wl->conf.mem_wl127x.tx_min_block_num;
mem_conf->num_ssid_profiles = wl->conf.mem_wl127x.ssid_profiles;
mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS);
ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
@@ -986,6 +989,7 @@ out:
int wl1271_acx_sta_mem_cfg(struct wl1271 *wl)
{
struct wl1271_acx_sta_config_memory *mem_conf;
struct conf_memory_settings *mem;
int ret;
wl1271_debug(DEBUG_ACX, "wl1271 mem cfg");
@@ -996,16 +1000,21 @@ int wl1271_acx_sta_mem_cfg(struct wl1271 *wl)
goto out;
}
if (wl->chip.id == CHIP_ID_1283_PG20)
mem = &wl->conf.mem_wl128x;
else
mem = &wl->conf.mem_wl127x;
/* memory config */
mem_conf->num_stations = wl->conf.mem.num_stations;
mem_conf->rx_mem_block_num = wl->conf.mem.rx_block_num;
mem_conf->tx_min_mem_block_num = wl->conf.mem.tx_min_block_num;
mem_conf->num_ssid_profiles = wl->conf.mem.ssid_profiles;
mem_conf->num_stations = mem->num_stations;
mem_conf->rx_mem_block_num = mem->rx_block_num;
mem_conf->tx_min_mem_block_num = mem->tx_min_block_num;
mem_conf->num_ssid_profiles = mem->ssid_profiles;
mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS);
mem_conf->dyn_mem_enable = wl->conf.mem.dynamic_memory;
mem_conf->tx_free_req = wl->conf.mem.min_req_tx_blocks;
mem_conf->rx_free_req = wl->conf.mem.min_req_rx_blocks;
mem_conf->tx_min = wl->conf.mem.tx_min;
mem_conf->dyn_mem_enable = mem->dynamic_memory;
mem_conf->tx_free_req = mem->min_req_tx_blocks;
mem_conf->rx_free_req = mem->min_req_rx_blocks;
mem_conf->tx_min = mem->tx_min;
ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
sizeof(*mem_conf));
@@ -1019,6 +1028,32 @@ out:
return ret;
}
int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap)
{
struct wl1271_acx_host_config_bitmap *bitmap_conf;
int ret;
bitmap_conf = kzalloc(sizeof(*bitmap_conf), GFP_KERNEL);
if (!bitmap_conf) {
ret = -ENOMEM;
goto out;
}
bitmap_conf->host_cfg_bitmap = cpu_to_le32(host_cfg_bitmap);
ret = wl1271_cmd_configure(wl, ACX_HOST_IF_CFG_BITMAP,
bitmap_conf, sizeof(*bitmap_conf));
if (ret < 0) {
wl1271_warning("wl1271 bitmap config opt failed: %d", ret);
goto out;
}
out:
kfree(bitmap_conf);
return ret;
}
int wl1271_acx_init_mem_config(struct wl1271 *wl)
{
int ret;
+11
View File
@@ -939,6 +939,16 @@ struct wl1271_acx_keep_alive_config {
u8 padding;
} __packed;
#define HOST_IF_CFG_RX_FIFO_ENABLE BIT(0)
#define HOST_IF_CFG_TX_EXTRA_BLKS_SWAP BIT(1)
#define HOST_IF_CFG_TX_PAD_TO_SDIO_BLK BIT(3)
struct wl1271_acx_host_config_bitmap {
struct acx_header header;
__le32 host_cfg_bitmap;
} __packed;
enum {
WL1271_ACX_TRIG_TYPE_LEVEL = 0,
WL1271_ACX_TRIG_TYPE_EDGE,
@@ -1275,6 +1285,7 @@ int wl1271_acx_tx_config_options(struct wl1271 *wl);
int wl1271_acx_ap_mem_cfg(struct wl1271 *wl);
int wl1271_acx_sta_mem_cfg(struct wl1271 *wl);
int wl1271_acx_init_mem_config(struct wl1271 *wl);
int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap);
int wl1271_acx_init_rx_interrupt(struct wl1271 *wl);
int wl1271_acx_smart_reflex(struct wl1271 *wl);
int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable);
+236 -43
View File
@@ -22,6 +22,7 @@
*/
#include <linux/slab.h>
#include <linux/wl12xx.h>
#include "acx.h"
#include "reg.h"
@@ -243,33 +244,57 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
if (wl->nvs == NULL)
return -ENODEV;
/*
* 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) {
/* for now 11a is unsupported in AP mode */
if (wl->bss_type != BSS_TYPE_AP_BSS &&
wl->nvs->general_params.dual_mode_select)
wl->enable_11a = true;
}
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 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;
}
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(wl->nvs->nvs);
nvs_ptr = (u8 *)wl->nvs->nvs;
/* 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) {
/* for now 11a is unsupported in AP mode */
if (wl->bss_type != BSS_TYPE_AP_BSS &&
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->mac_addr[0];
@@ -319,10 +344,13 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
/*
* 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->nvs +
ALIGN(nvs_ptr - (u8 *)wl->nvs->nvs + 7, 4);
nvs_len -= nvs_ptr - (u8 *)wl->nvs->nvs;
nvs_ptr = (u8 *)wl->nvs +
ALIGN(nvs_ptr - (u8 *)wl->nvs + 7, 4);
nvs_len -= nvs_ptr - (u8 *)wl->nvs;
/* Now we must set the partition correctly */
wl1271_set_partition(wl, &part_table[PART_WORK]);
@@ -454,6 +482,8 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
if (wl->bss_type == BSS_TYPE_AP_BSS)
wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID;
else
wl->event_mask |= DUMMY_PACKET_EVENT_ID;
ret = wl1271_event_unmask(wl);
if (ret < 0) {
@@ -493,24 +523,159 @@ static void wl1271_boot_hw_version(struct wl1271 *wl)
wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION;
}
/* uploads NVS and firmware */
int wl1271_load_firmware(struct wl1271 *wl)
static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl)
{
int ret = 0;
u32 tmp, clk, pause;
u16 spare_reg;
/* Mask bits [2] & [8:4] in the sys_clk_cfg register */
spare_reg = wl1271_top_reg_read(wl, WL_SPARE_REG);
if (spare_reg == 0xFFFF)
return -EFAULT;
spare_reg |= (BIT(3) | BIT(5) | BIT(6));
wl1271_top_reg_write(wl, WL_SPARE_REG, spare_reg);
/* Enable FREF_CLK_REQ & mux MCS and coex PLLs to FREF */
wl1271_top_reg_write(wl, SYS_CLK_CFG_REG,
WL_CLK_REQ_TYPE_PG2 | MCS_PLL_CLK_SEL_FREF);
/* Delay execution for 15msec, to let the HW settle */
mdelay(15);
return 0;
}
static bool wl128x_is_tcxo_valid(struct wl1271 *wl)
{
u16 tcxo_detection;
tcxo_detection = wl1271_top_reg_read(wl, TCXO_CLK_DETECT_REG);
if (tcxo_detection & TCXO_DET_FAILED)
return false;
return true;
}
static bool wl128x_is_fref_valid(struct wl1271 *wl)
{
u16 fref_detection;
fref_detection = wl1271_top_reg_read(wl, FREF_CLK_DETECT_REG);
if (fref_detection & FREF_CLK_DETECT_FAIL)
return false;
return true;
}
static int wl128x_manually_configure_mcs_pll(struct wl1271 *wl)
{
wl1271_top_reg_write(wl, MCS_PLL_M_REG, MCS_PLL_M_REG_VAL);
wl1271_top_reg_write(wl, MCS_PLL_N_REG, MCS_PLL_N_REG_VAL);
wl1271_top_reg_write(wl, MCS_PLL_CONFIG_REG, MCS_PLL_CONFIG_REG_VAL);
return 0;
}
static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk)
{
u16 spare_reg;
u16 pll_config;
u8 input_freq;
/* Mask bits [3:1] in the sys_clk_cfg register */
spare_reg = wl1271_top_reg_read(wl, WL_SPARE_REG);
if (spare_reg == 0xFFFF)
return -EFAULT;
spare_reg |= BIT(2);
wl1271_top_reg_write(wl, WL_SPARE_REG, spare_reg);
/* Handle special cases of the TCXO clock */
if (wl->tcxo_clock == WL12XX_TCXOCLOCK_16_8 ||
wl->tcxo_clock == WL12XX_TCXOCLOCK_33_6)
return wl128x_manually_configure_mcs_pll(wl);
/* Set the input frequency according to the selected clock source */
input_freq = (clk & 1) + 1;
pll_config = wl1271_top_reg_read(wl, MCS_PLL_CONFIG_REG);
if (pll_config == 0xFFFF)
return -EFAULT;
pll_config |= (input_freq << MCS_SEL_IN_FREQ_SHIFT);
pll_config |= MCS_PLL_ENABLE_HP;
wl1271_top_reg_write(wl, MCS_PLL_CONFIG_REG, pll_config);
return 0;
}
/*
* WL128x has two clocks input - TCXO and FREF.
* TCXO is the main clock of the device, while FREF is used to sync
* between the GPS and the cellular modem.
* In cases where TCXO is 32.736MHz or 16.368MHz, the FREF will be used
* as the WLAN/BT main clock.
*/
static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock)
{
u16 sys_clk_cfg;
/* For XTAL-only modes, FREF will be used after switching from TCXO */
if (wl->ref_clock == WL12XX_REFCLOCK_26_XTAL ||
wl->ref_clock == WL12XX_REFCLOCK_38_XTAL) {
if (!wl128x_switch_tcxo_to_fref(wl))
return -EINVAL;
goto fref_clk;
}
/* Query the HW, to determine which clock source we should use */
sys_clk_cfg = wl1271_top_reg_read(wl, SYS_CLK_CFG_REG);
if (sys_clk_cfg == 0xFFFF)
return -EINVAL;
if (sys_clk_cfg & PRCM_CM_EN_MUX_WLAN_FREF)
goto fref_clk;
/* If TCXO is either 32.736MHz or 16.368MHz, switch to FREF */
if (wl->tcxo_clock == WL12XX_TCXOCLOCK_16_368 ||
wl->tcxo_clock == WL12XX_TCXOCLOCK_32_736) {
if (!wl128x_switch_tcxo_to_fref(wl))
return -EINVAL;
goto fref_clk;
}
/* TCXO clock is selected */
if (!wl128x_is_tcxo_valid(wl))
return -EINVAL;
*selected_clock = wl->tcxo_clock;
goto config_mcs_pll;
fref_clk:
/* FREF clock is selected */
if (!wl128x_is_fref_valid(wl))
return -EINVAL;
*selected_clock = wl->ref_clock;
config_mcs_pll:
return wl128x_configure_mcs_pll(wl, *selected_clock);
}
static int wl127x_boot_clk(struct wl1271 *wl)
{
u32 pause;
u32 clk;
wl1271_boot_hw_version(wl);
if (wl->ref_clock == 0 || wl->ref_clock == 2 || wl->ref_clock == 4)
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 == 1 || wl->ref_clock == 3)
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 != 0) {
if (wl->ref_clock != CONF_REF_CLK_19_2_E) {
u16 val;
/* Set clock type (open drain) */
val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE);
@@ -540,6 +705,26 @@ int wl1271_load_firmware(struct wl1271 *wl)
pause |= WU_COUNTER_PAUSE_VAL;
wl1271_write32(wl, WU_COUNTER_PAUSE, pause);
return 0;
}
/* uploads NVS and firmware */
int wl1271_load_firmware(struct wl1271 *wl)
{
int ret = 0;
u32 tmp, clk;
int selected_clock = -1;
if (wl->chip.id == CHIP_ID_1283_PG20) {
ret = wl128x_boot_clk(wl, &selected_clock);
if (ret < 0)
goto out;
} else {
ret = wl127x_boot_clk(wl);
if (ret < 0)
goto out;
}
/* Continue the ELP wake up sequence */
wl1271_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
udelay(500);
@@ -555,7 +740,12 @@ int wl1271_load_firmware(struct wl1271 *wl)
wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk);
clk |= (wl->ref_clock << 1) << 4;
if (wl->chip.id == CHIP_ID_1283_PG20) {
clk |= ((selected_clock & 0x3) << 1) << 4;
} else {
clk |= (wl->ref_clock << 1) << 4;
}
wl1271_write32(wl, DRPW_SCRATCH_START, clk);
wl1271_set_partition(wl, &part_table[PART_WORK]);
@@ -585,16 +775,12 @@ int wl1271_load_firmware(struct wl1271 *wl)
/* 6. read the EEPROM parameters */
tmp = wl1271_read32(wl, SCR_PAD2);
ret = wl1271_boot_write_irq_polarity(wl);
if (ret < 0)
goto out;
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) */
if (wl->chip.id == CHIP_ID_1283_PG20)
wl1271_top_reg_write(wl, SDIO_IO_DS, wl->conf.hci_io_ds);
ret = wl1271_boot_upload_firmware(wl);
if (ret < 0)
goto out;
@@ -618,6 +804,13 @@ int wl1271_boot(struct wl1271 *wl)
if (ret < 0)
goto out;
ret = wl1271_boot_write_irq_polarity(wl);
if (ret < 0)
goto out;
wl1271_write32(wl, ACX_REG_INTERRUPT_MASK,
WL1271_ACX_ALL_EVENTS_VECTOR);
/* Enable firmware interrupts now */
wl1271_boot_enable_interrupts(wl);
+52
View File
@@ -74,4 +74,56 @@ struct wl1271_static_data {
#define FREF_CLK_POLARITY_BITS 0xfffff8ff
#define CLK_REQ_OUTN_SEL 0x700
/* PLL configuration algorithm for wl128x */
#define SYS_CLK_CFG_REG 0x2200
/* Bit[0] - 0-TCXO, 1-FREF */
#define MCS_PLL_CLK_SEL_FREF BIT(0)
/* Bit[3:2] - 01-TCXO, 10-FREF */
#define WL_CLK_REQ_TYPE_FREF BIT(3)
#define WL_CLK_REQ_TYPE_PG2 (BIT(3) | BIT(2))
/* Bit[4] - 0-TCXO, 1-FREF */
#define PRCM_CM_EN_MUX_WLAN_FREF BIT(4)
#define TCXO_ILOAD_INT_REG 0x2264
#define TCXO_CLK_DETECT_REG 0x2266
#define TCXO_DET_FAILED BIT(4)
#define FREF_ILOAD_INT_REG 0x2084
#define FREF_CLK_DETECT_REG 0x2086
#define FREF_CLK_DETECT_FAIL BIT(4)
/* Use this reg for masking during driver access */
#define WL_SPARE_REG 0x2320
#define WL_SPARE_VAL BIT(2)
/* Bit[6:5:3] - mask wl write SYS_CLK_CFG[8:5:2:4] */
#define WL_SPARE_MASK_8526 (BIT(6) | BIT(5) | BIT(3))
#define PLL_LOCK_COUNTERS_REG 0xD8C
#define PLL_LOCK_COUNTERS_COEX 0x0F
#define PLL_LOCK_COUNTERS_MCS 0xF0
#define MCS_PLL_OVERRIDE_REG 0xD90
#define MCS_PLL_CONFIG_REG 0xD92
#define MCS_SEL_IN_FREQ_MASK 0x0070
#define MCS_SEL_IN_FREQ_SHIFT 4
#define MCS_PLL_CONFIG_REG_VAL 0x73
#define MCS_PLL_ENABLE_HP (BIT(0) | BIT(1))
#define MCS_PLL_M_REG 0xD94
#define MCS_PLL_N_REG 0xD96
#define MCS_PLL_M_REG_VAL 0xC8
#define MCS_PLL_N_REG_VAL 0x07
#define SDIO_IO_DS 0xd14
/* SDIO/wSPI DS configuration values */
enum {
HCI_IO_DS_8MA = 0,
HCI_IO_DS_4MA = 1, /* default */
HCI_IO_DS_6MA = 2,
HCI_IO_DS_2MA = 3,
};
/* end PLL configuration algorithm for wl128x */
#endif
+91 -6
View File
@@ -110,7 +110,47 @@ out:
int wl1271_cmd_general_parms(struct wl1271 *wl)
{
struct wl1271_general_parms_cmd *gen_parms;
struct wl1271_ini_general_params *gp = &wl->nvs->general_params;
struct wl1271_ini_general_params *gp =
&((struct wl1271_nvs_file *)wl->nvs)->general_params;
bool answer = false;
int ret;
if (!wl->nvs)
return -ENODEV;
gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL);
if (!gen_parms)
return -ENOMEM;
gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM;
memcpy(&gen_parms->general_params, gp, sizeof(*gp));
if (gp->tx_bip_fem_auto_detect)
answer = true;
ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer);
if (ret < 0) {
wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed");
goto out;
}
gp->tx_bip_fem_manufacturer =
gen_parms->general_params.tx_bip_fem_manufacturer;
wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n",
answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer);
out:
kfree(gen_parms);
return ret;
}
int wl128x_cmd_general_parms(struct wl1271 *wl)
{
struct wl128x_general_parms_cmd *gen_parms;
struct wl128x_ini_general_params *gp =
&((struct wl128x_nvs_file *)wl->nvs)->general_params;
bool answer = false;
int ret;
@@ -147,8 +187,9 @@ out:
int wl1271_cmd_radio_parms(struct wl1271 *wl)
{
struct wl1271_nvs_file *nvs = (struct wl1271_nvs_file *)wl->nvs;
struct wl1271_radio_parms_cmd *radio_parms;
struct wl1271_ini_general_params *gp = &wl->nvs->general_params;
struct wl1271_ini_general_params *gp = &nvs->general_params;
int ret;
if (!wl->nvs)
@@ -161,18 +202,18 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl)
radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM;
/* 2.4GHz parameters */
memcpy(&radio_parms->static_params_2, &wl->nvs->stat_radio_params_2,
memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2,
sizeof(struct wl1271_ini_band_params_2));
memcpy(&radio_parms->dyn_params_2,
&wl->nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params,
&nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params,
sizeof(struct wl1271_ini_fem_params_2));
/* 5GHz parameters */
memcpy(&radio_parms->static_params_5,
&wl->nvs->stat_radio_params_5,
&nvs->stat_radio_params_5,
sizeof(struct wl1271_ini_band_params_5));
memcpy(&radio_parms->dyn_params_5,
&wl->nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params,
&nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params,
sizeof(struct wl1271_ini_fem_params_5));
wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ",
@@ -186,6 +227,50 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl)
return ret;
}
int wl128x_cmd_radio_parms(struct wl1271 *wl)
{
struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs;
struct wl128x_radio_parms_cmd *radio_parms;
struct wl128x_ini_general_params *gp = &nvs->general_params;
int ret;
if (!wl->nvs)
return -ENODEV;
radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL);
if (!radio_parms)
return -ENOMEM;
radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM;
/* 2.4GHz parameters */
memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2,
sizeof(struct wl128x_ini_band_params_2));
memcpy(&radio_parms->dyn_params_2,
&nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params,
sizeof(struct wl128x_ini_fem_params_2));
/* 5GHz parameters */
memcpy(&radio_parms->static_params_5,
&nvs->stat_radio_params_5,
sizeof(struct wl128x_ini_band_params_5));
memcpy(&radio_parms->dyn_params_5,
&nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params,
sizeof(struct wl128x_ini_fem_params_5));
radio_parms->fem_vendor_and_options = nvs->fem_vendor_and_options;
wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ",
radio_parms, sizeof(*radio_parms));
ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0);
if (ret < 0)
wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed");
kfree(radio_parms);
return ret;
}
int wl1271_cmd_ext_radio_parms(struct wl1271 *wl)
{
struct wl1271_ext_radio_parms_cmd *ext_radio_parms;
+34
View File
@@ -32,7 +32,9 @@ struct acx_header;
int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
size_t res_len);
int wl1271_cmd_general_parms(struct wl1271 *wl);
int wl128x_cmd_general_parms(struct wl1271 *wl);
int wl1271_cmd_radio_parms(struct wl1271 *wl);
int wl128x_cmd_radio_parms(struct wl1271 *wl);
int wl1271_cmd_ext_radio_parms(struct wl1271 *wl);
int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type);
int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer);
@@ -415,6 +417,21 @@ struct wl1271_general_parms_cmd {
u8 padding[3];
} __packed;
struct wl128x_general_parms_cmd {
struct wl1271_cmd_header header;
struct wl1271_cmd_test_header test;
struct wl128x_ini_general_params general_params;
u8 sr_debug_table[WL1271_INI_MAX_SMART_REFLEX_PARAM];
u8 sr_sen_n_p;
u8 sr_sen_n_p_gain;
u8 sr_sen_nrn;
u8 sr_sen_prn;
u8 padding[3];
} __packed;
struct wl1271_radio_parms_cmd {
struct wl1271_cmd_header header;
@@ -431,6 +448,23 @@ struct wl1271_radio_parms_cmd {
u8 padding3[2];
} __packed;
struct wl128x_radio_parms_cmd {
struct wl1271_cmd_header header;
struct wl1271_cmd_test_header test;
/* Static radio parameters */
struct wl128x_ini_band_params_2 static_params_2;
struct wl128x_ini_band_params_5 static_params_5;
u8 fem_vendor_and_options;
/* Dynamic radio parameters */
struct wl128x_ini_fem_params_2 dyn_params_2;
u8 padding2;
struct wl128x_ini_fem_params_5 dyn_params_5;
} __packed;
struct wl1271_ext_radio_parms_cmd {
struct wl1271_cmd_header header;
+6 -11
View File
@@ -1004,7 +1004,9 @@ enum {
CONF_REF_CLK_19_2_E,
CONF_REF_CLK_26_E,
CONF_REF_CLK_38_4_E,
CONF_REF_CLK_52_E
CONF_REF_CLK_52_E,
CONF_REF_CLK_38_4_M_XTAL,
CONF_REF_CLK_26_M_XTAL,
};
enum single_dual_band_enum {
@@ -1018,15 +1020,6 @@ enum single_dual_band_enum {
#define CONF_NUMBER_OF_CHANNELS_2_4 14
#define CONF_NUMBER_OF_CHANNELS_5 35
struct conf_radio_parms {
/*
* FEM parameter set to use
*
* Range: 0 or 1
*/
u8 fem;
};
struct conf_itrim_settings {
/* enable dco itrim */
u8 enable;
@@ -1202,7 +1195,9 @@ struct conf_drv_settings {
struct conf_scan_settings scan;
struct conf_rf_settings rf;
struct conf_ht_setting ht;
struct conf_memory_settings mem;
struct conf_memory_settings mem_wl127x;
struct conf_memory_settings mem_wl128x;
u8 hci_io_ds;
};
#endif
+1 -1
View File
@@ -267,7 +267,7 @@ static ssize_t gpio_power_write(struct file *file,
}
buf[len] = '\0';
ret = strict_strtoul(buf, 0, &value);
ret = kstrtoul(buf, 0, &value);
if (ret < 0) {
wl1271_warning("illegal value in gpio_power");
return -EINVAL;
+12 -5
View File
@@ -33,6 +33,7 @@ void wl1271_pspoll_work(struct work_struct *work)
{
struct delayed_work *dwork;
struct wl1271 *wl;
int ret;
dwork = container_of(work, struct delayed_work, work);
wl = container_of(dwork, struct wl1271, pspoll_work);
@@ -55,8 +56,13 @@ void wl1271_pspoll_work(struct work_struct *work)
* delivery failure occurred, and no-one changed state since, so
* we should go back to powersave.
*/
ret = wl1271_ps_elp_wakeup(wl);
if (ret < 0)
goto out;
wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, wl->basic_rate, true);
wl1271_ps_elp_sleep(wl);
out:
mutex_unlock(&wl->mutex);
};
@@ -129,11 +135,6 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
/* enable beacon early termination */
ret = wl1271_acx_bet_enable(wl, true);
if (ret < 0)
break;
/* go to extremely low power mode */
wl1271_ps_elp_sleep(wl);
break;
default:
break;
@@ -228,6 +229,12 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
wl1271_event_rssi_trigger(wl, mbox);
}
if ((vector & DUMMY_PACKET_EVENT_ID) && !is_ap) {
wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID");
if (wl->vif)
wl1271_tx_dummy_packet(wl);
}
if (wl->vif && beacon_loss)
ieee80211_connection_loss(wl->vif);
+4 -1
View File
@@ -59,7 +59,10 @@ enum {
BSS_LOSE_EVENT_ID = BIT(18),
REGAINED_BSS_EVENT_ID = BIT(19),
ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID = BIT(20),
STA_REMOVE_COMPLETE_EVENT_ID = BIT(21), /* AP */
/* STA: dummy paket for dynamic mem blocks */
DUMMY_PACKET_EVENT_ID = BIT(21),
/* AP: STA remove complete */
STA_REMOVE_COMPLETE_EVENT_ID = BIT(21),
SOFT_GEMINI_SENSE_EVENT_ID = BIT(22),
SOFT_GEMINI_PREDICTION_EVENT_ID = BIT(23),
SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24),
+96 -2
View File
@@ -41,6 +41,28 @@ struct wl1271_ini_general_params {
u8 srf3[WL1271_INI_MAX_SMART_REFLEX_PARAM];
} __packed;
#define WL128X_INI_MAX_SETTINGS_PARAM 4
struct wl128x_ini_general_params {
u8 ref_clock;
u8 settling_time;
u8 clk_valid_on_wakeup;
u8 tcxo_ref_clock;
u8 tcxo_settling_time;
u8 tcxo_valid_on_wakeup;
u8 tcxo_ldo_voltage;
u8 xtal_itrim_val;
u8 platform_conf;
u8 dual_mode_select;
u8 tx_bip_fem_auto_detect;
u8 tx_bip_fem_manufacturer;
u8 general_settings[WL128X_INI_MAX_SETTINGS_PARAM];
u8 sr_state;
u8 srf1[WL1271_INI_MAX_SMART_REFLEX_PARAM];
u8 srf2[WL1271_INI_MAX_SMART_REFLEX_PARAM];
u8 srf3[WL1271_INI_MAX_SMART_REFLEX_PARAM];
} __packed;
#define WL1271_INI_RSSI_PROCESS_COMPENS_SIZE 15
struct wl1271_ini_band_params_2 {
@@ -49,9 +71,16 @@ struct wl1271_ini_band_params_2 {
u8 rx_rssi_process_compens[WL1271_INI_RSSI_PROCESS_COMPENS_SIZE];
} __packed;
#define WL1271_INI_RATE_GROUP_COUNT 6
#define WL1271_INI_CHANNEL_COUNT_2 14
struct wl128x_ini_band_params_2 {
u8 rx_trace_insertion_loss;
u8 tx_trace_loss[WL1271_INI_CHANNEL_COUNT_2];
u8 rx_rssi_process_compens[WL1271_INI_RSSI_PROCESS_COMPENS_SIZE];
} __packed;
#define WL1271_INI_RATE_GROUP_COUNT 6
struct wl1271_ini_fem_params_2 {
__le16 tx_bip_ref_pd_voltage;
u8 tx_bip_ref_power;
@@ -68,6 +97,28 @@ struct wl1271_ini_fem_params_2 {
u8 normal_to_degraded_high_thr;
} __packed;
#define WL128X_INI_RATE_GROUP_COUNT 7
/* low and high temperatures */
#define WL128X_INI_PD_VS_TEMPERATURE_RANGES 2
struct wl128x_ini_fem_params_2 {
__le16 tx_bip_ref_pd_voltage;
u8 tx_bip_ref_power;
u8 tx_bip_ref_offset;
u8 tx_per_rate_pwr_limits_normal[WL128X_INI_RATE_GROUP_COUNT];
u8 tx_per_rate_pwr_limits_degraded[WL128X_INI_RATE_GROUP_COUNT];
u8 tx_per_rate_pwr_limits_extreme[WL128X_INI_RATE_GROUP_COUNT];
u8 tx_per_chan_pwr_limits_11b[WL1271_INI_CHANNEL_COUNT_2];
u8 tx_per_chan_pwr_limits_ofdm[WL1271_INI_CHANNEL_COUNT_2];
u8 tx_pd_vs_rate_offsets[WL128X_INI_RATE_GROUP_COUNT];
u8 tx_ibias[WL128X_INI_RATE_GROUP_COUNT + 1];
u8 tx_pd_vs_chan_offsets[WL1271_INI_CHANNEL_COUNT_2];
u8 tx_pd_vs_temperature[WL128X_INI_PD_VS_TEMPERATURE_RANGES];
u8 rx_fem_insertion_loss;
u8 degraded_low_to_normal_thr;
u8 normal_to_degraded_high_thr;
} __packed;
#define WL1271_INI_CHANNEL_COUNT_5 35
#define WL1271_INI_SUB_BAND_COUNT_5 7
@@ -77,6 +128,12 @@ struct wl1271_ini_band_params_5 {
u8 rx_rssi_process_compens[WL1271_INI_RSSI_PROCESS_COMPENS_SIZE];
} __packed;
struct wl128x_ini_band_params_5 {
u8 rx_trace_insertion_loss[WL1271_INI_SUB_BAND_COUNT_5];
u8 tx_trace_loss[WL1271_INI_CHANNEL_COUNT_5];
u8 rx_rssi_process_compens[WL1271_INI_RSSI_PROCESS_COMPENS_SIZE];
} __packed;
struct wl1271_ini_fem_params_5 {
__le16 tx_bip_ref_pd_voltage[WL1271_INI_SUB_BAND_COUNT_5];
u8 tx_bip_ref_power[WL1271_INI_SUB_BAND_COUNT_5];
@@ -92,6 +149,23 @@ struct wl1271_ini_fem_params_5 {
u8 normal_to_degraded_high_thr;
} __packed;
struct wl128x_ini_fem_params_5 {
__le16 tx_bip_ref_pd_voltage[WL1271_INI_SUB_BAND_COUNT_5];
u8 tx_bip_ref_power[WL1271_INI_SUB_BAND_COUNT_5];
u8 tx_bip_ref_offset[WL1271_INI_SUB_BAND_COUNT_5];
u8 tx_per_rate_pwr_limits_normal[WL128X_INI_RATE_GROUP_COUNT];
u8 tx_per_rate_pwr_limits_degraded[WL128X_INI_RATE_GROUP_COUNT];
u8 tx_per_rate_pwr_limits_extreme[WL128X_INI_RATE_GROUP_COUNT];
u8 tx_per_chan_pwr_limits_ofdm[WL1271_INI_CHANNEL_COUNT_5];
u8 tx_pd_vs_rate_offsets[WL128X_INI_RATE_GROUP_COUNT];
u8 tx_ibias[WL128X_INI_RATE_GROUP_COUNT];
u8 tx_pd_vs_chan_offsets[WL1271_INI_CHANNEL_COUNT_5];
u8 tx_pd_vs_temperature[WL1271_INI_SUB_BAND_COUNT_5 *
WL128X_INI_PD_VS_TEMPERATURE_RANGES];
u8 rx_fem_insertion_loss[WL1271_INI_SUB_BAND_COUNT_5];
u8 degraded_low_to_normal_thr;
u8 normal_to_degraded_high_thr;
} __packed;
/* NVS data structure */
#define WL1271_INI_NVS_SECTION_SIZE 468
@@ -100,7 +174,7 @@ struct wl1271_ini_fem_params_5 {
#define WL1271_INI_LEGACY_NVS_FILE_SIZE 800
struct wl1271_nvs_file {
/* NVS section */
/* NVS section - must be first! */
u8 nvs[WL1271_INI_NVS_SECTION_SIZE];
/* INI section */
@@ -120,4 +194,24 @@ struct wl1271_nvs_file {
} dyn_radio_params_5[WL1271_INI_FEM_MODULE_COUNT];
} __packed;
struct wl128x_nvs_file {
/* NVS section - must be first! */
u8 nvs[WL1271_INI_NVS_SECTION_SIZE];
/* INI section */
struct wl128x_ini_general_params general_params;
u8 fem_vendor_and_options;
struct wl128x_ini_band_params_2 stat_radio_params_2;
u8 padding2;
struct {
struct wl128x_ini_fem_params_2 params;
u8 padding;
} dyn_radio_params_2[WL1271_INI_FEM_MODULE_COUNT];
struct wl128x_ini_band_params_5 stat_radio_params_5;
u8 padding3;
struct {
struct wl128x_ini_fem_params_5 params;
u8 padding;
} dyn_radio_params_5[WL1271_INI_FEM_MODULE_COUNT];
} __packed;
#endif
+40 -5
View File
@@ -31,6 +31,7 @@
#include "cmd.h"
#include "reg.h"
#include "tx.h"
#include "io.h"
int wl1271_sta_init_templates_config(struct wl1271 *wl)
{
@@ -321,9 +322,11 @@ static int wl1271_sta_hw_init(struct wl1271 *wl)
{
int ret;
ret = wl1271_cmd_ext_radio_parms(wl);
if (ret < 0)
return ret;
if (wl->chip.id != CHIP_ID_1283_PG20) {
ret = wl1271_cmd_ext_radio_parms(wl);
if (ret < 0)
return ret;
}
/* PS config */
ret = wl1271_acx_config_ps(wl);
@@ -504,6 +507,27 @@ static int wl1271_set_ba_policies(struct wl1271 *wl)
return ret;
}
int wl1271_chip_specific_init(struct wl1271 *wl)
{
int ret = 0;
if (wl->chip.id == CHIP_ID_1283_PG20) {
u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE;
if (wl->quirks & WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT)
/* Enable SDIO padding */
host_cfg_bitmap |= HOST_IF_CFG_TX_PAD_TO_SDIO_BLK;
/* Must be before wl1271_acx_init_mem_config() */
ret = wl1271_acx_host_if_cfg_bitmap(wl, host_cfg_bitmap);
if (ret < 0)
goto out;
}
out:
return ret;
}
int wl1271_hw_init(struct wl1271 *wl)
{
struct conf_tx_ac_category *conf_ac;
@@ -511,11 +535,22 @@ int wl1271_hw_init(struct wl1271 *wl)
int ret, i;
bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
ret = wl1271_cmd_general_parms(wl);
if (wl->chip.id == CHIP_ID_1283_PG20)
ret = wl128x_cmd_general_parms(wl);
else
ret = wl1271_cmd_general_parms(wl);
if (ret < 0)
return ret;
ret = wl1271_cmd_radio_parms(wl);
if (wl->chip.id == CHIP_ID_1283_PG20)
ret = wl128x_cmd_radio_parms(wl);
else
ret = wl1271_cmd_radio_parms(wl);
if (ret < 0)
return ret;
/* Chip-specific init */
ret = wl1271_chip_specific_init(wl);
if (ret < 0)
return ret;
+1
View File
@@ -31,6 +31,7 @@ int wl1271_sta_init_templates_config(struct wl1271 *wl);
int wl1271_init_phy_config(struct wl1271 *wl);
int wl1271_init_pta(struct wl1271 *wl);
int wl1271_init_energy_detection(struct wl1271 *wl);
int wl1271_chip_specific_init(struct wl1271 *wl);
int wl1271_hw_init(struct wl1271 *wl);
#endif
+11
View File
@@ -29,6 +29,7 @@
#include "wl12xx.h"
#include "wl12xx_80211.h"
#include "io.h"
#include "tx.h"
#define OCP_CMD_LOOP 32
@@ -43,6 +44,16 @@
#define OCP_STATUS_REQ_FAILED 0x20000
#define OCP_STATUS_RESP_ERROR 0x30000
bool wl1271_set_block_size(struct wl1271 *wl)
{
if (wl->if_ops->set_block_size) {
wl->if_ops->set_block_size(wl, WL12XX_BUS_BLOCK_SIZE);
return true;
}
return false;
}
void wl1271_disable_interrupts(struct wl1271 *wl)
{
wl->if_ops->disable_irq(wl);
+3
View File
@@ -169,5 +169,8 @@ int wl1271_init_ieee80211(struct wl1271 *wl);
struct ieee80211_hw *wl1271_alloc_hw(void);
int wl1271_free_hw(struct wl1271 *wl);
irqreturn_t wl1271_irq(int irq, void *data);
bool wl1271_set_block_size(struct wl1271 *wl);
int wl1271_tx_dummy_packet(struct wl1271 *wl);
void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters);
#endif
File diff suppressed because it is too large Load Diff
-3
View File
@@ -149,9 +149,6 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
case STATION_ACTIVE_MODE:
default:
wl1271_debug(DEBUG_PSM, "leaving psm");
ret = wl1271_ps_elp_wakeup(wl);
if (ret < 0)
return ret;
/* disable beacon early termination */
ret = wl1271_acx_bet_enable(wl, false);
+2 -13
View File
@@ -207,6 +207,8 @@
#define CHIP_ID_1271_PG10 (0x4030101)
#define CHIP_ID_1271_PG20 (0x4030111)
#define CHIP_ID_1283_PG10 (0x05030101)
#define CHIP_ID_1283_PG20 (0x05030111)
#define ENABLE (REGISTERS_BASE + 0x5450)
@@ -452,24 +454,11 @@
#define HI_CFG_UART_TX_OUT_GPIO_14 0x00000200
#define HI_CFG_UART_TX_OUT_GPIO_7 0x00000400
/*
* NOTE: USE_ACTIVE_HIGH compilation flag should be defined in makefile
* for platforms using active high interrupt level
*/
#ifdef USE_ACTIVE_HIGH
#define HI_CFG_DEF_VAL \
(HI_CFG_UART_ENABLE | \
HI_CFG_RST232_ENABLE | \
HI_CFG_CLOCK_REQ_SELECT | \
HI_CFG_HOST_INT_ENABLE)
#else
#define HI_CFG_DEF_VAL \
(HI_CFG_UART_ENABLE | \
HI_CFG_RST232_ENABLE | \
HI_CFG_CLOCK_REQ_SELECT | \
HI_CFG_HOST_INT_ENABLE)
#endif
#define REF_FREQ_19_2 0
#define REF_FREQ_26_0 1
+24 -20
View File
@@ -48,18 +48,14 @@ static void wl1271_rx_status(struct wl1271 *wl,
struct ieee80211_rx_status *status,
u8 beacon)
{
enum ieee80211_band desc_band;
memset(status, 0, sizeof(struct ieee80211_rx_status));
status->band = wl->band;
if ((desc->flags & WL1271_RX_DESC_BAND_MASK) == WL1271_RX_DESC_BAND_BG)
desc_band = IEEE80211_BAND_2GHZ;
status->band = IEEE80211_BAND_2GHZ;
else
desc_band = IEEE80211_BAND_5GHZ;
status->band = IEEE80211_BAND_5GHZ;
status->rate_idx = wl1271_rate_to_idx(desc->rate, desc_band);
status->rate_idx = wl1271_rate_to_idx(desc->rate, status->band);
#ifdef CONFIG_WL12XX_HT
/* 11n support */
@@ -76,7 +72,8 @@ static void wl1271_rx_status(struct wl1271 *wl,
*/
wl->noise = desc->rssi - (desc->snr >> 1);
status->freq = ieee80211_channel_to_frequency(desc->channel, desc_band);
status->freq = ieee80211_channel_to_frequency(desc->channel,
status->band);
if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) {
status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED;
@@ -163,18 +160,25 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
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);
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,

Some files were not shown because too many files have changed in this diff Show More