2011-03-06 14:28:08

by Shahar Levi

[permalink] [raw]
Subject: [PATCH 00/15] wl12xx: 1281/1283 support

Adding support to 1281/1283 WLAN TI chip (Quattro).
That support required changes in boot sequence, Tx&Rx path, ISR
polarity, SDIO block size padding, dynamic TX mem blocks, Dummy
packet event support, interrupt pacing and more.
Auto detection support between wl127x and wl128x that add the ability to operate
in each of them automatically.

Note:
That patch doesn't add support for wl128x with SPI bus.

Arik Nemtsov (2):
wl12xx: 1281/1283 support - Use different FW file for AP mode
wl127x/wl128x chips
wl12xx: 1281/1283 support - disable TX aggregation for AP mode in
wl128x

Shahar Levi (13):
wl12xx: 1281/1283 support - move IRQ polarity
wl12xx: 1281/1283 support - Add Definitions
wl12xx: 1281/1283 support - Add acx commands
wl12xx: 1281/1283 support - New radio struc & func
wl12xx: 1281/1283 support - Loading FW & NVS
wl12xx: 1281/1283 support - New boot sequence
wl12xx: 1281/1283 support - Set mem conf & dynamic mem
wl12xx: 1281/1283 support - Improve Tx & Rx path
wl12xx: 1281/1283 support - Add dummy packet support
wl12xx: 1281/1283 support - Set WiFi & BT cox
wl12xx: 1281/1283 support - Add chip interrupt pacing
wl12xx: 1281/1283 support - Use 1 spare blocks for 128x STA, and 2
for the rest
wl12xx: 1281/1283 support - enable chip support

drivers/net/wireless/wl12xx/Kconfig | 2 +-
drivers/net/wireless/wl12xx/acx.c | 71 ++++++--
drivers/net/wireless/wl12xx/acx.h | 11 +
drivers/net/wireless/wl12xx/boot.c | 307 ++++++++++++++++++++++++++-----
drivers/net/wireless/wl12xx/boot.h | 59 ++++++
drivers/net/wireless/wl12xx/cmd.c | 97 +++++++++-
drivers/net/wireless/wl12xx/cmd.h | 34 ++++
drivers/net/wireless/wl12xx/conf.h | 17 ++-
drivers/net/wireless/wl12xx/event.c | 6 +
drivers/net/wireless/wl12xx/event.h | 5 +-
drivers/net/wireless/wl12xx/ini.h | 96 ++++++++++-
drivers/net/wireless/wl12xx/init.c | 37 ++++-
drivers/net/wireless/wl12xx/io.c | 5 +
drivers/net/wireless/wl12xx/io.h | 2 +
drivers/net/wireless/wl12xx/main.c | 154 ++++++++++++++--
drivers/net/wireless/wl12xx/reg.h | 15 +--
drivers/net/wireless/wl12xx/rx.c | 34 ++--
drivers/net/wireless/wl12xx/sdio.c | 20 ++-
drivers/net/wireless/wl12xx/sdio_test.c | 17 ++-
drivers/net/wireless/wl12xx/spi.c | 16 ++-
drivers/net/wireless/wl12xx/testmode.c | 22 ++-
drivers/net/wireless/wl12xx/tx.c | 172 ++++++++++++++----
drivers/net/wireless/wl12xx/tx.h | 53 +++++-
drivers/net/wireless/wl12xx/wl12xx.h | 24 ++-
include/linux/wl12xx.h | 1 +
25 files changed, 1092 insertions(+), 185 deletions(-)



2011-03-06 14:28:27

by Shahar Levi

[permalink] [raw]
Subject: [PATCH 14/15] wl12xx: 1281/1283 support - disable TX aggregation for AP mode in wl128x

From: Arik Nemtsov <[email protected]>

This is a workaround for the HW bug we're encountering when operating
with 48Mhz SDIO clocks. This workaround is currently employed by the MCP
driver as well.

This is not healthy for CPU usage, and UDP TX seems hurt by this change.
TCP RX/TX seems unchanged from Trio or the 1-spare-block FW variant.

With this workaround we get a working AP on Blaze.

Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/wl12xx/tx.c | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 9c0ec06..831248e 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -568,6 +568,11 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
}
buf_offset += ret;
wl->tx_packets_count++;
+
+ /* Disable packet aggregation for 1283 AP-mode */
+ if (wl->chip.id == CHIP_ID_1283_PG20 &&
+ wl->bss_type == BSS_TYPE_AP_BSS)
+ break;
}

out_ack:
--
1.7.0.4


2011-03-09 14:37:09

by Luciano Coelho

[permalink] [raw]
Subject: Re: [PATCH 10/15] wl12xx: 1281/1283 support - Set WiFi & BT cox

On Sun, 2011-03-06 at 16:32 +0200, Shahar Levi wrote:
> Set different Cox setting between wl127x and wl128x.
>
> Signed-off-by: Shahar Levi <[email protected]>
> ---
> drivers/net/wireless/wl12xx/acx.c | 5 +++++
> drivers/net/wireless/wl12xx/main.c | 6 +++++-
> 2 files changed, 10 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
> index f0345e6..e970b71 100644
> --- a/drivers/net/wireless/wl12xx/acx.c
> +++ b/drivers/net/wireless/wl12xx/acx.c
> @@ -554,6 +554,11 @@ int wl1271_acx_sg_cfg(struct wl1271 *wl)
> goto out;
> }
>
> + if (wl->chip.id == CHIP_ID_1283_PG20)
> + c->params[CONF_SG_BT_LOAD_RATIO] = 50;
> + else
> + c->params[CONF_SG_BT_LOAD_RATIO] = 200;
> +

You can't change this value in the global array. This needs to be
changed only in the allocated ACX. I'll change it before taking it in.

Also, I think it's cleaner to keep the correct value for wl127x in the
global array (as was before) and only change the value for wl128x here
in this function.

> diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
> index 32d963d..f8e9e3f 100644
> --- a/drivers/net/wireless/wl12xx/main.c
> +++ b/drivers/net/wireless/wl12xx/main.c
> @@ -54,7 +54,11 @@ static struct conf_drv_settings default_conf = {
> [CONF_SG_BT_PER_THRESHOLD] = 7500,
> [CONF_SG_HV3_MAX_OVERRIDE] = 0,
> [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400,
> - [CONF_SG_BT_LOAD_RATIO] = 50,
> + /*
> + * CONF_SG_BT_LOAD_RATIO has wl127x or wl128x dependency
> + * (set in wl1271_acx_sg_cfg()
> + */
> + [CONF_SG_BT_LOAD_RATIO] = 0,
> [CONF_SG_AUTO_PS_MODE] = 1,
> [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170,
> [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50,

Previously, the value used for wl127x was 50, from the default global
settings. Now you're using 200 for wl127x. This looks suspicious. You
now use 50 (which was the value for wl127x) for wl128x and 200 for
wl127x.

At least the change for wl127x should be done in a separate patch.

--
Cheers,
Luca.


2011-03-06 14:28:19

by Shahar Levi

[permalink] [raw]
Subject: [PATCH 08/15] wl12xx: 1281/1283 support - Improve Tx & Rx path

Reduced bus transactions in Tx & Rx path

Signed-off-by: Shahar Levi <[email protected]>
---
drivers/net/wireless/wl12xx/rx.c | 34 +++++++++++++++++++++-------------
drivers/net/wireless/wl12xx/tx.c | 22 ++++++++++++++++++----
2 files changed, 39 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c
index 919b59f..c95ae19 100644
--- a/drivers/net/wireless/wl12xx/rx.c
+++ b/drivers/net/wireless/wl12xx/rx.c
@@ -163,18 +163,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,
@@ -204,7 +211,8 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
* 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)
+ if ((wl->chip.id != CHIP_ID_1283_PG20) &&
+ (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION))
wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
}

diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 542b785..a7cec1c 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -159,8 +159,14 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
desc = (struct wl1271_tx_hw_descr *)skb_push(
skb, total_len - skb->len);

- desc->wl127x_mem.extra_blocks = TX_HW_BLOCK_SPARE;
- desc->wl127x_mem.total_mem_blocks = total_blocks;
+ /* HW descriptor fields change between wl127x and wl128x */
+ if (wl->chip.id == CHIP_ID_1283_PG20) {
+ desc->wl128x_mem.total_mem_blocks = total_blocks;
+ } else {
+ desc->wl127x_mem.extra_blocks = TX_HW_BLOCK_SPARE;
+ desc->wl127x_mem.total_mem_blocks = total_blocks;
+ }
+
desc->id = id;

wl->tx_blocks_available -= total_blocks;
@@ -265,7 +271,14 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,

desc->tx_attr = cpu_to_le16(tx_attr);

- wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d hlid: %d "
+ if (wl->chip.id == CHIP_ID_1283_PG20)
+ wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d hlid: %d "
+ "tx_attr: 0x%x len: %d life: %d mem: %d", pad, desc->hlid,
+ le16_to_cpu(desc->tx_attr), le16_to_cpu(desc->length),
+ le16_to_cpu(desc->life_time),
+ desc->wl128x_mem.total_mem_blocks);
+ else
+ wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d hlid: %d "
"tx_attr: 0x%x len: %d life: %d mem: %d", pad, desc->hlid,
le16_to_cpu(desc->tx_attr), le16_to_cpu(desc->length),
le16_to_cpu(desc->life_time),
@@ -537,7 +550,8 @@ out_ack:
* Interrupt the firmware with the new packets. This is only
* required for older hardware revisions
*/
- if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION)
+ if ((wl->chip.id != CHIP_ID_1283_PG20) &&
+ (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION))
wl1271_write32(wl, WL1271_HOST_WR_ACCESS,
wl->tx_packets_count);

--
1.7.0.4


2011-03-08 13:11:17

by Luciano Coelho

[permalink] [raw]
Subject: Re: [PATCH 06/15] wl12xx: 1281/1283 support - New boot sequence

On Sun, 2011-03-06 at 16:32 +0200, Shahar Levi wrote:
> - clk |= (wl->ref_clock << 1) << 4;
> + if (wl->chip.id == CHIP_ID_1283_PG20) {
> + if (is_ref_clk == false)
> + clk |= ((wl->tcxo_clock & 0x3) << 1) << 4;
> + else
> + clk |= ((wl->ref_clock & 0x3) << 1) << 4;
> + } else
> + clk |= ((wl->ref_clock & 0x3) << 1) << 4;
> +
> wl1271_write32(wl, DRPW_SCRATCH_START, clk);

Can you explain why you changed the wl127x part as well? For wl127x
you're essentially changing:

clk |= (wl->ref_clock << 1) << 4;

to:

clk |= ((wl->ref_clock & 0x3) << 1) << 4;

This means that CONF_REF_CLK_38_4_M_XTAL will be treated in the same way
as CONF_REF_CLK_19_2_E. Is that right? If it is, it must be addressed
in a separate patch and not as part of the Quattro series.


--
Cheers,
Luca.


2011-03-06 14:28:15

by Shahar Levi

[permalink] [raw]
Subject: [PATCH 05/15] wl12xx: 1281/1283 support - Loading FW & NVS

Take care of FW & NVS with the auto-detection between wl127x and
wl128x.

Signed-off-by: Shahar Levi <[email protected]>
---
drivers/net/wireless/wl12xx/boot.c | 86 ++++++++++++++++++++-----------
drivers/net/wireless/wl12xx/cmd.c | 11 ++--
drivers/net/wireless/wl12xx/main.c | 9 ++-
drivers/net/wireless/wl12xx/sdio_test.c | 9 +++-
drivers/net/wireless/wl12xx/testmode.c | 22 ++++++--
drivers/net/wireless/wl12xx/wl12xx.h | 2 +-
6 files changed, 93 insertions(+), 46 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
index 69fe870..7984631 100644
--- a/drivers/net/wireless/wl12xx/boot.c
+++ b/drivers/net/wireless/wl12xx/boot.c
@@ -240,36 +240,62 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
u32 dest_addr, val;
u8 *nvs_ptr, *nvs_aligned;

- 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 (nvs == NULL)
+ return -ENODEV;
+
+ 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(nvs);
+ nvs = NULL;
+ wl->nvs_len = 0;
+ return -EILSEQ;
+ }

- /*
- * 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;
- }
+ /* only the first part of the NVS needs to be uploaded */
+ nvs_len = sizeof(nvs->nvs);
+ nvs_ptr = (u8 *)nvs->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;
- }
+ } else {
+ struct wl1271_nvs_file *nvs = (struct wl1271_nvs_file *)wl->nvs;

- /* only the first part of the NVS needs to be uploaded */
- nvs_len = sizeof(wl->nvs->nvs);
- nvs_ptr = (u8 *)wl->nvs->nvs;
+ if (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 &&
+ 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(nvs);
+ 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];
@@ -320,9 +346,9 @@ 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.
*/
- 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]);
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index 37eb9f3..2468044 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -187,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)
@@ -201,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: ",
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 0a23a9e..4823897 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -813,7 +813,10 @@ static int wl1271_fetch_firmware(struct wl1271 *wl)
break;
case BSS_TYPE_IBSS:
case BSS_TYPE_STA_BSS:
- fw_name = WL1271_FW_NAME;
+ if (wl->chip.id == CHIP_ID_1283_PG20)
+ fw_name = WL128X_FW_NAME;
+ else
+ fw_name = WL1271_FW_NAME;
break;
default:
wl1271_error("no compatible firmware for bss_type %d",
@@ -869,7 +872,7 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
return ret;
}

- wl->nvs = kmemdup(fw->data, sizeof(struct wl1271_nvs_file), GFP_KERNEL);
+ wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL);

if (!wl->nvs) {
wl1271_error("could not allocate memory for the nvs file");
@@ -3297,7 +3300,7 @@ int wl1271_register_hw(struct wl1271 *wl)

ret = wl1271_fetch_nvs(wl);
if (ret == 0) {
- u8 *nvs_ptr = (u8 *)wl->nvs->nvs;
+ u8 *nvs_ptr = (u8 *)wl->nvs;

wl->mac_addr[0] = nvs_ptr[11];
wl->mac_addr[1] = nvs_ptr[10];
diff --git a/drivers/net/wireless/wl12xx/sdio_test.c b/drivers/net/wireless/wl12xx/sdio_test.c
index 01adf1b..e6e2ad6 100644
--- a/drivers/net/wireless/wl12xx/sdio_test.c
+++ b/drivers/net/wireless/wl12xx/sdio_test.c
@@ -189,7 +189,12 @@ static int wl1271_fetch_firmware(struct wl1271 *wl)
const struct firmware *fw;
int ret;

- ret = request_firmware(&fw, WL1271_FW_NAME, wl1271_wl_to_dev(wl));
+ if (wl->chip.id == CHIP_ID_1283_PG20)
+ ret = request_firmware(&fw, WL128X_FW_NAME,
+ wl1271_wl_to_dev(wl));
+ else
+ ret = request_firmware(&fw, WL1271_FW_NAME,
+ wl1271_wl_to_dev(wl));

if (ret < 0) {
wl1271_error("could not get firmware: %d", ret);
@@ -234,7 +239,7 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
return ret;
}

- wl->nvs = kmemdup(fw->data, sizeof(struct wl1271_nvs_file), GFP_KERNEL);
+ wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL);

if (!wl->nvs) {
wl1271_error("could not allocate memory for the nvs file");
diff --git a/drivers/net/wireless/wl12xx/testmode.c b/drivers/net/wireless/wl12xx/testmode.c
index e64403b..7cd5093 100644
--- a/drivers/net/wireless/wl12xx/testmode.c
+++ b/drivers/net/wireless/wl12xx/testmode.c
@@ -27,6 +27,7 @@

#include "wl12xx.h"
#include "acx.h"
+#include "reg.h"

#define WL1271_TM_MAX_DATA_LENGTH 1024

@@ -204,11 +205,22 @@ static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[])

kfree(wl->nvs);

- wl->nvs = kzalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL);
- if (!wl->nvs) {
- wl1271_error("could not allocate memory for the nvs file");
- ret = -ENOMEM;
- goto out;
+ if (wl->chip.id == CHIP_ID_1283_PG20) {
+ wl->nvs = kzalloc(sizeof(struct wl128x_nvs_file), GFP_KERNEL);
+ if (!wl->nvs) {
+ wl1271_error("could not allocate memory for the nvs "
+ "file");
+ ret = -ENOMEM;
+ goto out;
+ }
+ } else {
+ wl->nvs = kzalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL);
+ if (!wl->nvs) {
+ wl1271_error("could not allocate memory for the nvs "
+ "file");
+ ret = -ENOMEM;
+ goto out;
+ }
}

memcpy(wl->nvs, buf, len);
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 3c3bde9..cc7f01c 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -378,7 +378,7 @@ struct wl1271 {
u8 *fw;
size_t fw_len;
u8 fw_bss_type;
- struct wl1271_nvs_file *nvs;
+ void *nvs;
size_t nvs_len;

s8 hw_pg_ver;
--
1.7.0.4


2011-03-06 14:28:14

by Shahar Levi

[permalink] [raw]
Subject: [PATCH 04/15] wl12xx: 1281/1283 support - New radio struc & func

New general radio parameters structures & functions.
Implemented as separate functions due to auto-detection
between wl127x and wl128x.

Signed-off-by: Shahar Levi <[email protected]>
---
drivers/net/wireless/wl12xx/cmd.c | 86 +++++++++++++++++++++++++++++++-
drivers/net/wireless/wl12xx/cmd.h | 34 +++++++++++++
drivers/net/wireless/wl12xx/ini.h | 96 +++++++++++++++++++++++++++++++++++-
drivers/net/wireless/wl12xx/init.c | 18 +++++--
drivers/net/wireless/wl12xx/main.c | 16 +++++-
5 files changed, 240 insertions(+), 10 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index f0aa7ab..37eb9f3 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -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;

@@ -186,6 +226,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;
diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h
index 54c12e7..5cac95d 100644
--- a/drivers/net/wireless/wl12xx/cmd.h
+++ b/drivers/net/wireless/wl12xx/cmd.h
@@ -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;

diff --git a/drivers/net/wireless/wl12xx/ini.h b/drivers/net/wireless/wl12xx/ini.h
index c330a25..30efcd6 100644
--- a/drivers/net/wireless/wl12xx/ini.h
+++ b/drivers/net/wireless/wl12xx/ini.h
@@ -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
@@ -120,4 +194,24 @@ struct wl1271_nvs_file {
} dyn_radio_params_5[WL1271_INI_FEM_MODULE_COUNT];
} __packed;

+struct wl128x_nvs_file {
+ /* NVS section */
+ 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
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
index 2f31d14..3676082 100644
--- a/drivers/net/wireless/wl12xx/init.c
+++ b/drivers/net/wireless/wl12xx/init.c
@@ -322,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);
@@ -512,11 +514,17 @@ 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;

diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index ac0513a..0a23a9e 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -438,15 +438,25 @@ static int wl1271_plt_init(struct wl1271 *wl)
struct conf_tx_tid *conf_tid;
int ret, i;

- 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;

- ret = wl1271_cmd_ext_radio_parms(wl);
+ if (wl->chip.id != CHIP_ID_1283_PG20) {
+ ret = wl1271_cmd_ext_radio_parms(wl);
+ if (ret < 0)
+ return ret;
+ }
if (ret < 0)
return ret;

--
1.7.0.4


2011-03-06 14:28:16

by Shahar Levi

[permalink] [raw]
Subject: [PATCH 06/15] wl12xx: 1281/1283 support - New boot sequence

Boot sequence support FREF clock and TCXO clock.
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.
Auto-detection checks where TCXO is 32.736MHz or 16.368MHz, in that
case the FREF will be used as the WLAN/BT main clock.

Signed-off-by: Shahar Levi <[email protected]>
---
drivers/net/wireless/wl12xx/boot.c | 200 +++++++++++++++++++++++++++++-
drivers/net/wireless/wl12xx/main.c | 2 +-
drivers/net/wireless/wl12xx/sdio.c | 1 +
drivers/net/wireless/wl12xx/sdio_test.c | 1 +
drivers/net/wireless/wl12xx/spi.c | 1 +
drivers/net/wireless/wl12xx/wl12xx.h | 1 +
include/linux/wl12xx.h | 1 +
7 files changed, 199 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
index 7984631..2f40909 100644
--- a/drivers/net/wireless/wl12xx/boot.c
+++ b/drivers/net/wireless/wl12xx/boot.c
@@ -519,18 +519,164 @@ 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)
+/*
+ * 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_switch_fref(struct wl1271 *wl, bool *is_ref_clk)
{
- int ret = 0;
- u32 tmp, clk, pause;
+ u16 sys_clk_cfg_val;
+
+ /* if working on XTAL-only mode go directly to TCXO TO FREF SWITCH */
+ if ((wl->ref_clock == CONF_REF_CLK_38_4_M_XTAL) ||
+ (wl->ref_clock == CONF_REF_CLK_26_M_XTAL)) {
+ wl1271_debug(DEBUG_BOOT, "XTAL-only mode go directly to"
+ " TCXO TO FREF SWITCH");
+
+ return true;
+ } else {
+ /* Read clock source FREF or TCXO */
+ sys_clk_cfg_val = wl1271_top_reg_read(wl, SYS_CLK_CFG_REG);
+
+ if (sys_clk_cfg_val & PRCM_CM_EN_MUX_WLAN_FREF) {
+ /* if bit 3 is set - working with FREF clock */
+ wl1271_debug(DEBUG_BOOT, "working with FREF clock, skip"
+ " to FREF");
+
+ *is_ref_clk = true;
+ } else {
+ /* if bit 3 is clear - working with TCXO clock */
+ wl1271_debug(DEBUG_BOOT, "working with TCXO clock");
+
+ /* TCXO to FREF switch, check TXCO clock config */
+ if ((wl->tcxo_clock != CLOCK_TCXO_16_368_M) &&
+ (wl->tcxo_clock != CLOCK_TCXO_32_736_M)) {
+ /*
+ * not 16.368Mhz and not 32.736Mhz - skip to
+ * configure ELP stage
+ */
+ wl1271_debug(DEBUG_BOOT, "NEW PLL ALGO:"
+ " TcxoRefClk=%d - not 16.368Mhz and not"
+ " 32.736Mhz - skip to configure ELP"
+ " stage", wl->tcxo_clock);
+
+ *is_ref_clk = false;
+ } else {
+ wl1271_debug(DEBUG_BOOT, "NEW PLL ALGO:"
+ "TcxoRefClk=%d - 16.368Mhz or 32.736Mhz"
+ " - TCXO to FREF switch",
+ wl->tcxo_clock);
+
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static int wl128x_boot_clk(struct wl1271 *wl, bool *is_ref_clk)
+{
+
+ if (wl128x_switch_fref(wl, is_ref_clk)) {
+ /* TCXO to FREF switch - for PG2.0 */
+ wl1271_top_reg_write(wl, WL_SPARE_REG,
+ WL_SPARE_MASK_8526);
+
+ wl1271_top_reg_write(wl, SYS_CLK_CFG_REG,
+ WL_CLK_REQ_TYPE_PG2 | MCS_PLL_CLK_SEL_FREF);
+
+ wl1271_debug(DEBUG_BOOT, "Wait settling time, "
+ "Read FREF_CLK_DETECT_REG");
+
+ *is_ref_clk = true;
+ /* wait 15ms */
+ mdelay(15);
+ }
+
+ wl1271_debug(DEBUG_BOOT, "Setting bit 2 in spare register to avoid "
+ "illegal access");
+ wl1271_top_reg_write(wl, WL_SPARE_REG, WL_SPARE_VAL);
+
+ /* working with TCXO clock */
+ if ((*is_ref_clk == false) &&
+ ((wl->tcxo_clock == CLOCK_TCXO_16_8_M) ||
+ (wl->tcxo_clock == CLOCK_TCXO_33_6_M))) {
+
+ /* Manually Configure MCS PLL settings PG2.0 Only */
+ wl1271_debug(DEBUG_BOOT, "16_8_M or 33_6_M TCXO detected so "
+ "configure the MCS PLL settings manually!!!!");
+
+ 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);
+ } else {
+ int pll_config;
+ u16 mcs_pll_config_val;
+
+ /*
+ * Configure MCS PLL settings to FREF Freq
+ * Set the values that determine the time elapse since the PLL's
+ * get their enable signal until the lock indication is set
+ */
+ wl1271_top_reg_write(wl, PLL_LOCK_COUNTERS_REG,
+ PLL_LOCK_COUNTERS_COEX | PLL_LOCK_COUNTERS_MCS);
+
+ mcs_pll_config_val = wl1271_top_reg_read(wl,
+ MCS_PLL_CONFIG_REG);
+
+ /*
+ * Set the MCS PLL input frequency value according to the
+ * reference clock value detected/read
+ */
+ if (*is_ref_clk == false) {
+ if ((wl->tcxo_clock == CLOCK_TCXO_19_2_M) ||
+ (wl->tcxo_clock == CLOCK_TCXO_38_4_M))
+ pll_config = 1;
+ else if ((wl->tcxo_clock == CLOCK_TCXO_26_M)
+ ||
+ (wl->tcxo_clock == CLOCK_TCXO_52_M))
+ pll_config = 2;
+ } else {
+ if ((wl->ref_clock == CONF_REF_CLK_19_2_E) ||
+ (wl->ref_clock == CONF_REF_CLK_38_4_E))
+ pll_config = 1;
+ else if ((wl->ref_clock == CONF_REF_CLK_26_E) ||
+ (wl->ref_clock == CONF_REF_CLK_52_E))
+ pll_config = 2;
+ }
+
+ /* Setting Bits[6:4] */
+ mcs_pll_config_val |= (pll_config << (MCS_SEL_IN_FREQ_SHIFT)) &
+ (MCS_SEL_IN_FREQ_MASK);
+
+ wl1271_top_reg_write(wl, MCS_PLL_CONFIG_REG,
+ mcs_pll_config_val);
+ }
+
+ return 0;
+}
+
+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
@@ -566,6 +712,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;
+ bool is_ref_clk = false;
+
+ if (wl->chip.id == CHIP_ID_1283_PG20) {
+ ret = wl128x_boot_clk(wl, &is_ref_clk);
+ 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);
@@ -581,7 +747,14 @@ 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) {
+ if (is_ref_clk == false)
+ clk |= ((wl->tcxo_clock & 0x3) << 1) << 4;
+ else
+ clk |= ((wl->ref_clock & 0x3) << 1) << 4;
+ } else
+ clk |= ((wl->ref_clock & 0x3) << 1) << 4;
+
wl1271_write32(wl, DRPW_SCRATCH_START, clk);

wl1271_set_partition(wl, &part_table[PART_WORK]);
@@ -614,6 +787,19 @@ int wl1271_load_firmware(struct wl1271 *wl)
/* WL1271: The reference driver skips steps 7 to 10 (jumps directly
* to upload_fw) */

+ if (wl->chip.id == CHIP_ID_1283_PG20) {
+ /*
+ * Configure SDIO/wSPI DS according to the following table:
+ * 00 8mA.
+ * 01 4mA (default).
+ * 10 6mA.
+ * 11 2mA.
+ * Write bits [1:0] of Register 0xd14
+ * data is in pWlanParams->PlatformConfiguration bits [2:1]
+ */
+ wl1271_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA);
+ }
+
ret = wl1271_boot_upload_firmware(wl);
if (ret < 0)
goto out;
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 4823897..4bcac46 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -307,7 +307,7 @@ static struct conf_drv_settings default_conf = {
.min_req_tx_blocks = 100,
.min_req_rx_blocks = 22,
.tx_min = 27,
- }
+ },
};

static void __wl1271_op_remove_interface(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c
index ed0f37e..521a187 100644
--- a/drivers/net/wireless/wl12xx/sdio.c
+++ b/drivers/net/wireless/wl12xx/sdio.c
@@ -252,6 +252,7 @@ static int __devinit wl1271_probe(struct sdio_func *func,

wl->irq = wlan_data->irq;
wl->ref_clock = wlan_data->board_ref_clock;
+ wl->tcxo_clock = wlan_data->board_tcxo_clock;

ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq,
IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
diff --git a/drivers/net/wireless/wl12xx/sdio_test.c b/drivers/net/wireless/wl12xx/sdio_test.c
index e6e2ad6..c02c870 100644
--- a/drivers/net/wireless/wl12xx/sdio_test.c
+++ b/drivers/net/wireless/wl12xx/sdio_test.c
@@ -421,6 +421,7 @@ static int __devinit wl1271_probe(struct sdio_func *func,

wl->irq = wlan_data->irq;
wl->ref_clock = wlan_data->board_ref_clock;
+ wl->tcxo_clock = wlan_data->board_tcxo_clock;

sdio_set_drvdata(func, wl_test);

diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c
index d6e566e..abbb8dc 100644
--- a/drivers/net/wireless/wl12xx/spi.c
+++ b/drivers/net/wireless/wl12xx/spi.c
@@ -409,6 +409,7 @@ static int __devinit wl1271_probe(struct spi_device *spi)
}

wl->ref_clock = pdata->board_ref_clock;
+ wl->tcxo_clock = pdata->board_tcxo_clock;

wl->irq = spi->irq;
if (wl->irq < 0) {
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index cc7f01c..ed4be73 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -537,6 +537,7 @@ struct wl1271 {
/* wl128x features only */
__le32 host_cfg_bitmap;
u32 block_size;
+ int tcxo_clock;

/*
* AP-mode - links indexed by HLID. The global and broadcast links
diff --git a/include/linux/wl12xx.h b/include/linux/wl12xx.h
index bebb8ef..cc2a6e1 100644
--- a/include/linux/wl12xx.h
+++ b/include/linux/wl12xx.h
@@ -38,6 +38,7 @@ struct wl12xx_platform_data {
int irq;
bool use_eeprom;
int board_ref_clock;
+ int board_tcxo_clock;
};

#ifdef CONFIG_WL12XX_PLATFORM_DATA
--
1.7.0.4


2011-03-08 16:56:38

by Shahar Levi

[permalink] [raw]
Subject: Re: [PATCH v2] wl12xx: fixes for 1281/1283 support - Add acx commands

On 3/8/11, Luciano Coelho <[email protected]> wrote:
> This patch fixes up some issues with patch 03/15 in the wl128x support
> series:
>
> * Fix endianess issues;
> * Simplify sdio-specific block_size handling;
> * Minor changes in comments
>
> This has been compile-tested only. I will test this changes after I
> go through the whole series and, if everything is still ok, I'll merge
> this patch into 03/15.
>
> Cc: Shahar Levi <[email protected]>
> Signed-off-by: Luciano Coelho <[email protected]>
> ---
Looks good. Thanks for your fixes.

Reviewed-by: Shahar Levi <[email protected]>



--
All the best,
Shahar

2011-03-07 12:53:25

by Luciano Coelho

[permalink] [raw]
Subject: [PATCH] wl12xx: fixes for 1281/1283 support - Add acx commands

This patch fixes up some issues with patch 03/15 in the wl128x support
series:

* Fix endianess issues;
* Simplify sdio-specific block_size handling;
* Minor changes in comments

This has been compile-tested only. I will test this changes after I
go through the whole series and, if everything is still ok, I'll merge
this patch into 03/15.

Cc: Shahar Levi <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/acx.c | 4 +-
drivers/net/wireless/wl12xx/acx.h | 8 +++---
drivers/net/wireless/wl12xx/init.c | 42 ++++++++++++++++++++-------------
drivers/net/wireless/wl12xx/init.h | 1 +
drivers/net/wireless/wl12xx/io.c | 9 +++++-
drivers/net/wireless/wl12xx/io.h | 2 +-
drivers/net/wireless/wl12xx/main.c | 18 ++++----------
drivers/net/wireless/wl12xx/spi.c | 10 +-------
drivers/net/wireless/wl12xx/tx.c | 41 +++++++++++++-------------------
drivers/net/wireless/wl12xx/tx.h | 24 +++++++++---------
drivers/net/wireless/wl12xx/wl12xx.h | 4 +--
11 files changed, 76 insertions(+), 87 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index aa0fc12..50676b3 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -1019,7 +1019,7 @@ out:
return ret;
}

-int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl)
+int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap)
{
struct wl1271_acx_host_config_bitmap *bitmap_conf;
int ret;
@@ -1030,7 +1030,7 @@ int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl)
goto out;
}

- bitmap_conf->host_cfg_bitmap = wl->host_cfg_bitmap;
+ 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));
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h
index 2d0bbfe..0a40cae 100644
--- a/drivers/net/wireless/wl12xx/acx.h
+++ b/drivers/net/wireless/wl12xx/acx.h
@@ -939,9 +939,9 @@ struct wl1271_acx_keep_alive_config {
u8 padding;
} __packed;

-#define HOST_IF_CFG_BITMAP_RX_FIFO_ENABLE BIT(0)
-#define HOST_IF_CFG_BITMAP_TX_EXTRA_BLKS_SWAP BIT(1)
-#define HOST_IF_CFG_BITMAP_TX_PAD_TO_SDIO_BLK BIT(3)
+#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;
@@ -1285,7 +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);
+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);
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
index 2f31d14..34c4108 100644
--- a/drivers/net/wireless/wl12xx/init.c
+++ b/drivers/net/wireless/wl12xx/init.c
@@ -505,6 +505,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 (wl1271_set_block_size(wl))
+ /* 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;
@@ -520,23 +541,10 @@ int wl1271_hw_init(struct wl1271 *wl)
if (ret < 0)
return ret;

- if (wl->chip.id == CHIP_ID_1283_PG20) {
- wl1271_set_block_size(wl);
-
- wl->host_cfg_bitmap = HOST_IF_CFG_BITMAP_RX_FIFO_ENABLE;
-
- if (wl->block_size)
- wl->host_cfg_bitmap |=
- HOST_IF_CFG_BITMAP_TX_PAD_TO_SDIO_BLK;
-
- /*
- * Host interface configuration must be before
- * wl1271_acx_init_mem_config !
- */
- ret = wl1271_acx_host_if_cfg_bitmap(wl);
- if (ret < 0)
- return ret;
- }
+ /* Chip-specific init */
+ ret = wl1271_chip_specific_init(wl);
+ if (ret < 0)
+ return ret;

/* Mode specific init */
if (is_ap)
diff --git a/drivers/net/wireless/wl12xx/init.h b/drivers/net/wireless/wl12xx/init.h
index 3a8bd3f..4975270 100644
--- a/drivers/net/wireless/wl12xx/init.h
+++ b/drivers/net/wireless/wl12xx/init.h
@@ -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
diff --git a/drivers/net/wireless/wl12xx/io.c b/drivers/net/wireless/wl12xx/io.c
index ca7229f..aa40c98 100644
--- a/drivers/net/wireless/wl12xx/io.c
+++ b/drivers/net/wireless/wl12xx/io.c
@@ -43,9 +43,14 @@
#define OCP_STATUS_REQ_FAILED 0x20000
#define OCP_STATUS_RESP_ERROR 0x30000

-void wl1271_set_block_size(struct wl1271 *wl)
+bool wl1271_set_block_size(struct wl1271 *wl)
{
- wl->if_ops->set_block_size(wl);
+ if (wl->if_ops->set_block_size) {
+ wl->if_ops->set_block_size(wl);
+ return true;
+ }
+
+ return false;
}

void wl1271_disable_interrupts(struct wl1271 *wl)
diff --git a/drivers/net/wireless/wl12xx/io.h b/drivers/net/wireless/wl12xx/io.h
index 9ae2f4a..84454f6 100644
--- a/drivers/net/wireless/wl12xx/io.h
+++ b/drivers/net/wireless/wl12xx/io.h
@@ -169,6 +169,6 @@ 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);
-void wl1271_set_block_size(struct wl1271 *wl);
+bool wl1271_set_block_size(struct wl1271 *wl);

#endif
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index ac0513a..c03876d 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -450,19 +450,10 @@ static int wl1271_plt_init(struct wl1271 *wl)
if (ret < 0)
return ret;

- if (wl->chip.id == CHIP_ID_1283_PG20) {
- wl1271_set_block_size(wl);
-
- wl->host_cfg_bitmap = HOST_IF_CFG_BITMAP_RX_FIFO_ENABLE;
-
- if (wl->block_size)
- wl->host_cfg_bitmap |=
- HOST_IF_CFG_BITMAP_TX_PAD_TO_SDIO_BLK;
-
- ret = wl1271_acx_host_if_cfg_bitmap(wl);
- if (ret < 0)
- return ret;
- }
+ /* Chip-specific initializations */
+ ret = wl1271_chip_specific_init(wl);
+ if (ret < 0)
+ return ret;

ret = wl1271_sta_init_templates_config(wl);
if (ret < 0)
@@ -3472,6 +3463,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
wl->ap_ps_map = 0;
wl->ap_fw_ps_map = 0;
wl->quirks = 0;
+ wl->block_size = 0;

memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map));
for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c
index d6e566e..2a57583 100644
--- a/drivers/net/wireless/wl12xx/spi.c
+++ b/drivers/net/wireless/wl12xx/spi.c
@@ -68,14 +68,6 @@

#define WSPI_MAX_NUM_OF_CHUNKS (WL1271_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE)

-/* When working with SPI block size not relevent*/
-#define TX_PAD_SDIO_BLK_SIZE 0
-
-void wl1271_spi_set_block_size(struct wl1271 *wl)
-{
- wl->block_size = TX_PAD_SDIO_BLK_SIZE;
-}
-
static inline struct spi_device *wl_to_spi(struct wl1271 *wl)
{
return wl->if_priv;
@@ -364,7 +356,7 @@ static struct wl1271_if_operations spi_ops = {
.dev = wl1271_spi_wl_to_dev,
.enable_irq = wl1271_spi_enable_interrupts,
.disable_irq = wl1271_spi_disable_interrupts,
- .set_block_size = wl1271_spi_set_block_size,
+ .set_block_size = NULL,
};

static int __devinit wl1271_probe(struct spi_device *spi)
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 542b785..30dc45a 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -145,14 +145,11 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,

/* approximate the number of blocks required for this packet
in the firmware */
- if (wl->host_cfg_bitmap & HOST_IF_CFG_BITMAP_TX_PAD_TO_SDIO_BLK) {
- u32 sdio_block_mask = wl->block_size - 1;
- int pad = (total_len + sdio_block_mask) & (~sdio_block_mask);
-
- total_blocks = pad + TX_HW_BLOCK_SIZE - 1;
- } else {
+ if (wl->block_size)
+ total_blocks = ALIGN(total_len, wl->block_size) +
+ TX_HW_BLOCK_SIZE - 1;
+ else
total_blocks = total_len + TX_HW_BLOCK_SIZE - 1;
- }

total_blocks = total_blocks / TX_HW_BLOCK_SIZE + TX_HW_BLOCK_SPARE;
if (total_blocks <= wl->tx_blocks_available) {
@@ -245,13 +242,10 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
tx_attr |= rate_idx << TX_HW_ATTR_OFST_RATE_POLICY;
desc->reserved = 0;

- if (wl->host_cfg_bitmap & HOST_IF_CFG_BITMAP_TX_PAD_TO_SDIO_BLK) {
- u32 sdio_block_mask = wl->block_size - 1;
- int pad = (skb->len + sdio_block_mask) &
- (~sdio_block_mask);
+ if (wl->block_size) {
+ pad = ALIGN(skb->len, wl->block_size);

desc->wl128x_mem.extra_bytes = pad - skb->len;
-
desc->length = cpu_to_le16(pad >> 2);
} else {
/* align the length (and store in terms of words) */
@@ -323,19 +317,18 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,

wl1271_tx_fill_hdr(wl, skb, extra, info, hlid);

- if (wl->host_cfg_bitmap & HOST_IF_CFG_BITMAP_TX_PAD_TO_SDIO_BLK) {
- unsigned sdio_block_mask = wl->block_size - 1;
-
- total_len = (skb->len + sdio_block_mask) & (~sdio_block_mask);
- } else {
- /*
- * The length of each packet is stored in terms of words. Thus,
- * we must pad the skb data to make sure its length is aligned.
- * The number of padding bytes is computed and set in
- * wl1271_tx_fill_hdr
- */
+ /*
+ * The length of each packet is stored in terms of
+ * words. Thus, we must pad the skb data to make sure its
+ * length is aligned. The number of padding bytes is computed
+ * and set in wl1271_tx_fill_hdr.
+ * In special cases, we want to align to a specific block size
+ * (eg. for wl128x with SDIO we align to 256).
+ */
+ if (wl->block_size)
+ total_len = ALIGN(skb->len, wl->block_size);
+ else
total_len = ALIGN(skb->len, WL1271_TX_ALIGN_TO);
- }

memcpy(wl->aggr_buf + buf_offset, skb->data, skb->len);
memset(wl->aggr_buf + buf_offset + skb->len, 0, total_len - skb->len);
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h
index 3072f95..e313177 100644
--- a/drivers/net/wireless/wl12xx/tx.h
+++ b/drivers/net/wireless/wl12xx/tx.h
@@ -57,29 +57,29 @@

struct wl127x_tx_mem {
/*
- * on wl127x: Number of extra memory blocks to allocate
- * for this packet in addition to the number of blocks
- * derived from the packet length
+ * Number of extra memory blocks to allocate for this packet
+ * in addition to the number of blocks derived from the packet
+ * length.
*/
u8 extra_blocks;
/*
- * on wl127x: Total number of memory blocks allocated by
- * the host for this packet. Must be equal or greater
- * than the actual blocks number allocated by HW!!
+ * Total number of memory blocks allocated by the host for
+ * this packet. Must be equal or greater than the actual
+ * blocks number allocated by HW.
*/
u8 total_mem_blocks;
} __packed;

struct wl128x_tx_mem {
/*
- * on wl128x: Total number of memory blocks allocated by
- * the host for this packet.
+ * Total number of memory blocks allocated by the host for
+ * this packet.
*/
u8 total_mem_blocks;
/*
- * on wl128x: Number of extra bytes, at the end of the
- * frame. the host uses this padding to complete each
- * frame to integer number of SDIO blocks.
+ * Number of extra bytes, at the end of the frame. the host
+ * uses this padding to complete each frame to integer number
+ * of SDIO blocks.
*/
u8 extra_bytes;
} __packed;
@@ -95,7 +95,7 @@ struct wl1271_tx_hw_descr {
__le32 start_time;
/*
* Max delay in TUs until transmission. The last device time the
- * packet can be transmitted is: startTime+(1024*LifeTime)
+ * packet can be transmitted is: start_time + (1024 * life_time)
*/
__le16 life_time;
/* Bitwise fields - see TX_ATTR... definitions above. */
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 94b4062..959b338 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -534,9 +534,7 @@ struct wl1271 {
bool ba_support;
u8 ba_rx_bitmap;

- /* wl128x features only */
- __le32 host_cfg_bitmap;
- u32 block_size;
+ u32 block_size;

/*
* AP-mode - links indexed by HLID. The global and broadcast links
--
1.7.1


2011-03-06 14:28:24

by Shahar Levi

[permalink] [raw]
Subject: [PATCH 12/15] wl12xx: 1281/1283 support - Use 1 spare blocks for 128x STA, and 2 for the rest

From: Arik Nemtsov <[email protected]>

All FW except for 127x AP use 1 spare blocks for TX. Reflect this in
the code.
In case of GEM need 2 spare blocks in STA.

Signed-off-by: Arik Nemtsov <[email protected]>
Signed-off-by: Shahar Levi <[email protected]>
---
drivers/net/wireless/wl12xx/tx.c | 20 +++++++++++++++++++-
drivers/net/wireless/wl12xx/tx.h | 3 ++-
2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 441c7de..9c0ec06 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -130,6 +130,7 @@ u8 wl1271_tx_get_hlid(struct sk_buff *skb)
static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
u32 buf_offset, u8 hlid)
{
+ struct ieee80211_tx_info *info;
struct wl1271_tx_hw_descr *desc;
u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra;
u32 total_blocks;
@@ -154,7 +155,24 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
total_blocks = total_len + TX_HW_BLOCK_SIZE - 1;
}

- total_blocks = total_blocks / TX_HW_BLOCK_SIZE + TX_HW_BLOCK_SPARE;
+ total_blocks = total_blocks / TX_HW_BLOCK_SIZE;
+
+ /* 127x AP works with 2 spare block. Everything else must use 1 */
+ if ((wl->chip.id != CHIP_ID_1283_PG20) &&
+ (wl->bss_type == BSS_TYPE_AP_BSS)) {
+ total_blocks += TX_HW_BLOCK_WL127X_AP_SPARE;
+ } else {
+ total_blocks += TX_HW_BLOCK_SPARE;
+
+ info = IEEE80211_SKB_CB(skb);
+
+ /* In case of GEM need 2 spare blocks in STA */
+ if (info->control.hw_key &&
+ info->control.hw_key->cipher == WL1271_CIPHER_SUITE_GEM &&
+ wl->bss_type != BSS_TYPE_AP_BSS)
+ total_blocks += 1;
+ }
+
if (total_blocks <= wl->tx_blocks_available) {
desc = (struct wl1271_tx_hw_descr *)skb_push(
skb, total_len - skb->len);
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h
index 0dbd8f5..b2f9e67 100644
--- a/drivers/net/wireless/wl12xx/tx.h
+++ b/drivers/net/wireless/wl12xx/tx.h
@@ -25,7 +25,8 @@
#ifndef __TX_H__
#define __TX_H__

-#define TX_HW_BLOCK_SPARE 2
+#define TX_HW_BLOCK_WL127X_AP_SPARE 2
+#define TX_HW_BLOCK_SPARE 1
#define TX_HW_BLOCK_SIZE 252

#define TX_HW_MGMT_PKT_LIFETIME_TU 2000
--
1.7.0.4


2011-03-06 15:38:22

by Arik Nemtsov

[permalink] [raw]
Subject: Re: [PATCH 14/15] wl12xx: 1281/1283 support - disable TX aggregation for AP mode in wl128x

[ relooping the list ]

On Sun, Mar 6, 2011 at 17:36, Arik Nemtsov <[email protected]> wrote:
>
>
> On Sun, Mar 6, 2011 at 16:32, Shahar Levi <[email protected]> wrote:
>>
>> From: Arik Nemtsov <[email protected]>
>>
>> This is a workaround for the HW bug we're encountering when operating
>> with 48Mhz SDIO clocks. This workaround is currently employed by the MCP
>> driver as well.
>>
>> This is not healthy for CPU usage, and UDP TX seems hurt by this change.
>> TCP RX/TX seems unchanged from Trio or the 1-spare-block FW variant.
>>
>> With this workaround we get a working AP on Blaze.
>>
>> Signed-off-by: Arik Nemtsov <[email protected]>
>> ---
>> ?drivers/net/wireless/wl12xx/tx.c | ? ?5 +++++
>> ?1 files changed, 5 insertions(+), 0 deletions(-)
>>
>> diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
>> index 9c0ec06..831248e 100644
>> --- a/drivers/net/wireless/wl12xx/tx.c
>> +++ b/drivers/net/wireless/wl12xx/tx.c
>> @@ -568,6 +568,11 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
>> ? ? ? ? ? ? ? ?}
>> ? ? ? ? ? ? ? ?buf_offset += ret;
>> ? ? ? ? ? ? ? ?wl->tx_packets_count++;
>> +
>> + ? ? ? ? ? ? ? /* Disable packet aggregation for 1283 AP-mode */
>> + ? ? ? ? ? ? ? if (wl->chip.id == CHIP_ID_1283_PG20 &&
>> + ? ? ? ? ? ? ? ? ? wl->bss_type == BSS_TYPE_AP_BSS)
>> + ? ? ? ? ? ? ? ? ? ? ? break;
>> ? ? ? ?}
>>
>> ?out_ack:
>> --
>> 1.7.0.4
>>
>
> This bug has already been resolved. Luca - please disregard this workaround.
> Regards,
> Arik

2011-03-06 14:28:17

by Shahar Levi

[permalink] [raw]
Subject: [PATCH 07/15] wl12xx: 1281/1283 support - Set mem conf & dynamic mem

Support dynamic TX mem blocks in the driver to wl128x FW that
supports moving TX mem blocks to RX in case the RX path is loaded.
The TX blocks available to use updated dynamically.

Thanks for Arik Nemtsov <[email protected]> for helping simplify
wl1271_fw_status() code.

Signed-off-by: Shahar Levi <[email protected]>
---
drivers/net/wireless/wl12xx/acx.c | 32 ++++++++++++++--------
drivers/net/wireless/wl12xx/conf.h | 3 +-
drivers/net/wireless/wl12xx/main.c | 48 +++++++++++++++++++++++++++++-----
drivers/net/wireless/wl12xx/wl12xx.h | 5 +++
4 files changed, 68 insertions(+), 20 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index aa0fc12..f0345e6 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -965,10 +965,10 @@ 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;
+ 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 +986,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 +997,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));
@@ -1072,6 +1078,8 @@ int wl1271_acx_init_mem_config(struct wl1271 *wl)
wl1271_debug(DEBUG_TX, "available tx blocks: %d",
wl->tx_blocks_available);

+ wl->tx_new_total = wl->tx_blocks_available;
+
return 0;
}

diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h
index a00f22c..743bd0b 100644
--- a/drivers/net/wireless/wl12xx/conf.h
+++ b/drivers/net/wireless/wl12xx/conf.h
@@ -1204,7 +1204,8 @@ 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;
};

#endif
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 4bcac46..94f99ae 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -298,7 +298,7 @@ static struct conf_drv_settings default_conf = {
.tx_ba_win_size = 64,
.inactivity_timeout = 10000,
},
- .mem = {
+ .mem_wl127x = {
.num_stations = 1,
.ssid_profiles = 1,
.rx_block_num = 70,
@@ -308,6 +308,16 @@ static struct conf_drv_settings default_conf = {
.min_req_rx_blocks = 22,
.tx_min = 27,
},
+ .mem_wl128x = {
+ .num_stations = 1,
+ .ssid_profiles = 1,
+ .rx_block_num = 40,
+ .tx_min_block_num = 40,
+ .dynamic_memory = 1,
+ .min_req_tx_blocks = 45,
+ .min_req_rx_blocks = 22,
+ .tx_min = 27,
+ },
};

static void __wl1271_op_remove_interface(struct wl1271 *wl);
@@ -617,16 +627,27 @@ static void wl1271_fw_status(struct wl1271 *wl,
{
struct wl1271_fw_common_status *status = &full_status->common;
struct timespec ts;
+ u32 old_tx_blk_count = wl->tx_blocks_available;
u32 total = 0;
int i;

- if (wl->bss_type == BSS_TYPE_AP_BSS)
+ if (wl->bss_type == BSS_TYPE_AP_BSS) {
wl1271_raw_read(wl, FW_STATUS_ADDR, status,
sizeof(struct wl1271_fw_ap_status), false);
- else
+ } else {
wl1271_raw_read(wl, FW_STATUS_ADDR, status,
sizeof(struct wl1271_fw_sta_status), false);

+ /* Update tx total blocks change */
+ wl->tx_total_diff +=
+ ((struct wl1271_fw_sta_status *)status)->tx_total -
+ wl->tx_new_total;
+
+ /* Update total tx blocks */
+ wl->tx_new_total =
+ ((struct wl1271_fw_sta_status *)status)->tx_total;
+ }
+
wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
"drv_rx_counter = %d, tx_results_counter = %d)",
status->intr,
@@ -636,17 +657,30 @@ static void wl1271_fw_status(struct wl1271 *wl,

/* update number of available TX blocks */
for (i = 0; i < NUM_TX_QUEUES; i++) {
- u32 cnt = le32_to_cpu(status->tx_released_blks[i]) -
+ total += le32_to_cpu(status->tx_released_blks[i]) -
wl->tx_blocks_freed[i];

wl->tx_blocks_freed[i] =
le32_to_cpu(status->tx_released_blks[i]);
- wl->tx_blocks_available += cnt;
- total += cnt;
+
+ }
+
+ /*
+ * By adding the freed blocks to tx_total_diff we are
+ * actually moving them to RX poll
+ */
+ wl->tx_total_diff += total;
+
+ /*
+ * In case we have positive difference we can add the blocks to TX poll
+ */
+ if (wl->tx_total_diff >= 0) {
+ wl->tx_blocks_available += wl->tx_total_diff;
+ wl->tx_total_diff = 0;
}

/* if more blocks are available now, tx work can be scheduled */
- if (total)
+ if (wl->tx_blocks_available > old_tx_blk_count)
clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags);

/* for AP update num of allocated TX blocks per link and ps status */
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index ed4be73..1114b7c 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -267,6 +267,8 @@ struct wl1271_fw_sta_status {
u8 tx_total;
u8 reserved1;
__le16 reserved2;
+ /* Total structure size is 68 bytes */
+ u32 spare;
} __packed;

struct wl1271_fw_full_status {
@@ -397,6 +399,9 @@ struct wl1271 {
u32 tx_blocks_freed[NUM_TX_QUEUES];
u32 tx_blocks_available;
u32 tx_results_count;
+ /* Indicates How much Memory blocks should be moved to RX poll */
+ int tx_total_diff;
+ u32 tx_new_total;

/* Transmitted TX packets counter for chipset interface */
u32 tx_packets_count;
--
1.7.0.4


2011-03-08 13:37:36

by Luciano Coelho

[permalink] [raw]
Subject: [PATCH] wl12xx: fixes for 1281/1283 support - New boot sequence

This patch fixes up some issues with patch 06/15 in the wl128x support
series:

* Remove unnecessary else block in wl128x_switch_fref;
* Remove unnecessary change in main.c;
* Remove some unnecessary debug prints and comments;
* Fix potential use of uninitialized value (pll_config)
* Add more all the defines for HCI_IO_DS_* instead of having them in a comment

This has been compile-tested only. I will test this changes after I
go through the whole series and, if everything is still ok, I'll merge
this patch into 06/15.

Cc: Shahar Levi <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/boot.c | 106 +++++++++++++++---------------------
drivers/net/wireless/wl12xx/boot.h | 5 ++
2 files changed, 48 insertions(+), 63 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
index e0d60ab..ffdcb7e 100644
--- a/drivers/net/wireless/wl12xx/boot.c
+++ b/drivers/net/wireless/wl12xx/boot.c
@@ -533,46 +533,42 @@ static int wl128x_switch_fref(struct wl1271 *wl, bool *is_ref_clk)

/* if working on XTAL-only mode go directly to TCXO TO FREF SWITCH */
if ((wl->ref_clock == CONF_REF_CLK_38_4_M_XTAL) ||
- (wl->ref_clock == CONF_REF_CLK_26_M_XTAL)) {
- wl1271_debug(DEBUG_BOOT, "XTAL-only mode go directly to"
- " TCXO TO FREF SWITCH");
-
+ (wl->ref_clock == CONF_REF_CLK_26_M_XTAL))
return true;
- } else {
- /* Read clock source FREF or TCXO */
- sys_clk_cfg_val = wl1271_top_reg_read(wl, SYS_CLK_CFG_REG);

- if (sys_clk_cfg_val & PRCM_CM_EN_MUX_WLAN_FREF) {
- /* if bit 3 is set - working with FREF clock */
- wl1271_debug(DEBUG_BOOT, "working with FREF clock, skip"
- " to FREF");
+ /* Read clock source FREF or TCXO */
+ sys_clk_cfg_val = wl1271_top_reg_read(wl, SYS_CLK_CFG_REG);
+
+ if (sys_clk_cfg_val & PRCM_CM_EN_MUX_WLAN_FREF) {
+ /* if bit 3 is set - working with FREF clock */
+ wl1271_debug(DEBUG_BOOT, "working with FREF clock, skip"
+ " to FREF");

*is_ref_clk = true;
- } else {
- /* if bit 3 is clear - working with TCXO clock */
- wl1271_debug(DEBUG_BOOT, "working with TCXO clock");
+ } else {
+ /* if bit 3 is clear - working with TCXO clock */
+ wl1271_debug(DEBUG_BOOT, "working with TCXO clock");

- /* TCXO to FREF switch, check TXCO clock config */
- if ((wl->tcxo_clock != CLOCK_TCXO_16_368_M) &&
- (wl->tcxo_clock != CLOCK_TCXO_32_736_M)) {
- /*
+ /* TCXO to FREF switch, check TXCO clock config */
+ if ((wl->tcxo_clock != CLOCK_TCXO_16_368_M) &&
+ (wl->tcxo_clock != CLOCK_TCXO_32_736_M)) {
+ /*
* not 16.368Mhz and not 32.736Mhz - skip to
- * configure ELP stage
- */
- wl1271_debug(DEBUG_BOOT, "NEW PLL ALGO:"
- " TcxoRefClk=%d - not 16.368Mhz and not"
- " 32.736Mhz - skip to configure ELP"
- " stage", wl->tcxo_clock);
-
- *is_ref_clk = false;
- } else {
- wl1271_debug(DEBUG_BOOT, "NEW PLL ALGO:"
- "TcxoRefClk=%d - 16.368Mhz or 32.736Mhz"
- " - TCXO to FREF switch",
- wl->tcxo_clock);
-
- return true;
- }
+ * configure ELP stage
+ */
+ wl1271_debug(DEBUG_BOOT, "NEW PLL ALGO:"
+ " TcxoRefClk=%d - not 16.368Mhz and not"
+ " 32.736Mhz - skip to configure ELP"
+ " stage", wl->tcxo_clock);
+
+ *is_ref_clk = false;
+ } else {
+ wl1271_debug(DEBUG_BOOT, "NEW PLL ALGO:"
+ "TcxoRefClk=%d - 16.368Mhz or 32.736Mhz"
+ " - TCXO to FREF switch",
+ wl->tcxo_clock);
+
+ return true;
}
}

@@ -581,8 +577,9 @@ static int wl128x_switch_fref(struct wl1271 *wl, bool *is_ref_clk)

static int wl128x_boot_clk(struct wl1271 *wl, bool *is_ref_clk)
{
-
if (wl128x_switch_fref(wl, is_ref_clk)) {
+ wl1271_debug(DEBUG_BOOT, "XTAL-only mode go directly to"
+ " TCXO TO FREF SWITCH");
/* TCXO to FREF switch - for PG2.0 */
wl1271_top_reg_write(wl, WL_SPARE_REG,
WL_SPARE_MASK_8526);
@@ -590,31 +587,22 @@ static int wl128x_boot_clk(struct wl1271 *wl, bool *is_ref_clk)
wl1271_top_reg_write(wl, SYS_CLK_CFG_REG,
WL_CLK_REQ_TYPE_PG2 | MCS_PLL_CLK_SEL_FREF);

- wl1271_debug(DEBUG_BOOT, "Wait settling time, "
- "Read FREF_CLK_DETECT_REG");
-
*is_ref_clk = true;
- /* wait 15ms */
mdelay(15);
}

- wl1271_debug(DEBUG_BOOT, "Setting bit 2 in spare register to avoid "
- "illegal access");
+ /* Set bit 2 in spare register to avoid illegal access */
wl1271_top_reg_write(wl, WL_SPARE_REG, WL_SPARE_VAL);

/* working with TCXO clock */
if ((*is_ref_clk == false) &&
((wl->tcxo_clock == CLOCK_TCXO_16_8_M) ||
(wl->tcxo_clock == CLOCK_TCXO_33_6_M))) {
+ wl1271_debug(DEBUG_BOOT, "16_8_M or 33_6_M TCXO detected");

/* Manually Configure MCS PLL settings PG2.0 Only */
- wl1271_debug(DEBUG_BOOT, "16_8_M or 33_6_M TCXO detected so "
- "configure the MCS PLL settings manually!!!!");
-
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);
} else {
@@ -631,7 +619,6 @@ static int wl128x_boot_clk(struct wl1271 *wl, bool *is_ref_clk)

mcs_pll_config_val = wl1271_top_reg_read(wl,
MCS_PLL_CONFIG_REG);
-
/*
* Set the MCS PLL input frequency value according to the
* reference clock value detected/read
@@ -644,6 +631,8 @@ static int wl128x_boot_clk(struct wl1271 *wl, bool *is_ref_clk)
||
(wl->tcxo_clock == CLOCK_TCXO_52_M))
pll_config = 2;
+ else
+ return -EINVAL;
} else {
if ((wl->ref_clock == CONF_REF_CLK_19_2_E) ||
(wl->ref_clock == CONF_REF_CLK_38_4_E))
@@ -651,12 +640,12 @@ static int wl128x_boot_clk(struct wl1271 *wl, bool *is_ref_clk)
else if ((wl->ref_clock == CONF_REF_CLK_26_E) ||
(wl->ref_clock == CONF_REF_CLK_52_E))
pll_config = 2;
+ else
+ return -EINVAL;
}

- /* Setting Bits[6:4] */
mcs_pll_config_val |= (pll_config << (MCS_SEL_IN_FREQ_SHIFT)) &
(MCS_SEL_IN_FREQ_MASK);
-
wl1271_top_reg_write(wl, MCS_PLL_CONFIG_REG,
mcs_pll_config_val);
}
@@ -683,7 +672,7 @@ static int wl127x_boot_clk(struct wl1271 *wl)
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);
@@ -753,8 +742,9 @@ int wl1271_load_firmware(struct wl1271 *wl)
clk |= ((wl->tcxo_clock & 0x3) << 1) << 4;
else
clk |= ((wl->ref_clock & 0x3) << 1) << 4;
- } else
- clk |= ((wl->ref_clock & 0x3) << 1) << 4;
+ } else {
+ clk |= (wl->ref_clock << 1) << 4;
+ }

wl1271_write32(wl, DRPW_SCRATCH_START, clk);

@@ -788,18 +778,8 @@ int wl1271_load_firmware(struct wl1271 *wl)
/* WL1271: The reference driver skips steps 7 to 10 (jumps directly
* to upload_fw) */

- if (wl->chip.id == CHIP_ID_1283_PG20) {
- /*
- * Configure SDIO/wSPI DS according to the following table:
- * 00 8mA.
- * 01 4mA (default).
- * 10 6mA.
- * 11 2mA.
- * Write bits [1:0] of Register 0xd14
- * data is in pWlanParams->PlatformConfiguration bits [2:1]
- */
+ if (wl->chip.id == CHIP_ID_1283_PG20)
wl1271_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA);
- }

ret = wl1271_boot_upload_firmware(wl);
if (ret < 0)
diff --git a/drivers/net/wireless/wl12xx/boot.h b/drivers/net/wireless/wl12xx/boot.h
index daaf0e7..429c926 100644
--- a/drivers/net/wireless/wl12xx/boot.h
+++ b/drivers/net/wireless/wl12xx/boot.h
@@ -125,7 +125,12 @@ struct wl1271_static_data {
#define MCS_PLL_N_REG_VAL 0x07

#define SDIO_IO_DS 0xd14
+
+/* SDIO/wSPI DS configuration values */
+#define HCI_IO_DS_8MA 0
+#define HCI_IO_DS_4MA 1 /* default */
#define HCI_IO_DS_6MA 2
+#define HCI_IO_DS_2MA 4

#define HW_CONFIG_19_2_M 1
#define HW_CONFIG_26_M 2
--
1.7.1


2011-03-06 14:28:21

by Shahar Levi

[permalink] [raw]
Subject: [PATCH 10/15] wl12xx: 1281/1283 support - Set WiFi & BT cox

Set different Cox setting between wl127x and wl128x.

Signed-off-by: Shahar Levi <[email protected]>
---
drivers/net/wireless/wl12xx/acx.c | 5 +++++
drivers/net/wireless/wl12xx/main.c | 6 +++++-
2 files changed, 10 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index f0345e6..e970b71 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -554,6 +554,11 @@ int wl1271_acx_sg_cfg(struct wl1271 *wl)
goto out;
}

+ if (wl->chip.id == CHIP_ID_1283_PG20)
+ c->params[CONF_SG_BT_LOAD_RATIO] = 50;
+ else
+ c->params[CONF_SG_BT_LOAD_RATIO] = 200;
+
/* BT-WLAN coext parameters */
for (i = 0; i < CONF_SG_PARAMS_MAX; i++)
param->params[i] = cpu_to_le32(c->params[i]);
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 32d963d..f8e9e3f 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -54,7 +54,11 @@ static struct conf_drv_settings default_conf = {
[CONF_SG_BT_PER_THRESHOLD] = 7500,
[CONF_SG_HV3_MAX_OVERRIDE] = 0,
[CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400,
- [CONF_SG_BT_LOAD_RATIO] = 50,
+ /*
+ * CONF_SG_BT_LOAD_RATIO has wl127x or wl128x dependency
+ * (set in wl1271_acx_sg_cfg()
+ */
+ [CONF_SG_BT_LOAD_RATIO] = 0,
[CONF_SG_AUTO_PS_MODE] = 1,
[CONF_SG_AUTO_SCAN_PROBE_REQ] = 170,
[CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50,
--
1.7.0.4


2011-03-09 08:16:21

by Luciano Coelho

[permalink] [raw]
Subject: Re: [PATCH] wl12xx: fixes for 1281/1283 support - New boot sequence

On Tue, 2011-03-08 at 20:15 +0200, Levi, Shahar wrote:
> On Tue, Mar 8, 2011 at 3:37 PM, Luciano Coelho <[email protected]> wrote:
> > diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
> > index e0d60ab..ffdcb7e 100644
> > --- a/drivers/net/wireless/wl12xx/boot.c
> > +++ b/drivers/net/wireless/wl12xx/boot.c
> > @@ -533,46 +533,42 @@ static int wl128x_switch_fref(struct wl1271 *wl, bool *is_ref_clk)
> >
> > /* if working on XTAL-only mode go directly to TCXO TO FREF SWITCH */
> > if ((wl->ref_clock == CONF_REF_CLK_38_4_M_XTAL) ||
> > - (wl->ref_clock == CONF_REF_CLK_26_M_XTAL)) {
> > - wl1271_debug(DEBUG_BOOT, "XTAL-only mode go directly to"
> > - " TCXO TO FREF SWITCH");
> I believe that debug should be say in that function that check the ref value.

Sorry, I disagree. This debug message is actually saying what is
happening when the ref_clock value is *_XTAL and what happens cannot be
seen in this part of the code, only in the part that calls this
function.

In fact, I almost removed this debug message completely, because there
are way too many debug messages that are good during implementation, but
shouldn't go out when the implementation is working.

I'll keep it (for now) after the function is called.


> > @@ -788,18 +778,8 @@ int wl1271_load_firmware(struct wl1271 *wl)
> > /* WL1271: The reference driver skips steps 7 to 10 (jumps directly
> > * to upload_fw) */
> >
> > - if (wl->chip.id == CHIP_ID_1283_PG20) {
> > - /*
> > - * Configure SDIO/wSPI DS according to the following table:
> > - * 00 8mA.
> > - * 01 4mA (default).
> > - * 10 6mA.
> > - * 11 2mA.
> > - * Write bits [1:0] of Register 0xd14
> > - * data is in pWlanParams->PlatformConfiguration bits [2:1]
> Those two lines above is redundant. however I believe the comment
> should be stay.

This comment is useless in this part of the code. If it should be
somewhere, it should be where the macros are defined. But even there, I
think it doesn't add any value, because it's so obvious.


> > diff --git a/drivers/net/wireless/wl12xx/boot.h b/drivers/net/wireless/wl12xx/boot.h
> > index daaf0e7..429c926 100644
> > --- a/drivers/net/wireless/wl12xx/boot.h
> > +++ b/drivers/net/wireless/wl12xx/boot.h
> > @@ -125,7 +125,12 @@ struct wl1271_static_data {
> > #define MCS_PLL_N_REG_VAL 0x07
> >
> > #define SDIO_IO_DS 0xd14
> > +
> > +/* SDIO/wSPI DS configuration values */
> > +#define HCI_IO_DS_8MA 0
> > +#define HCI_IO_DS_4MA 1 /* default */
> > #define HCI_IO_DS_6MA 2
> > +#define HCI_IO_DS_2MA 4
> This value should be 3.

Ooops! Good that you noticed, thanks! I'll fix it.


--
Cheers,
Luca.


2011-03-06 14:28:20

by Shahar Levi

[permalink] [raw]
Subject: [PATCH 09/15] wl12xx: 1281/1283 support - Add dummy packet support

Support sending dummy packet to wl128x FW as results of
dummy packet event. That is part of dynamic TX mem blocks mechanism.

Only send dummy packet when not in AP mode (Thanks to
Ido Yariv" <[email protected]> and Arik Nemtsov" <[email protected]> for this one)

Signed-off-by: Shahar Levi <[email protected]>
---
drivers/net/wireless/wl12xx/boot.c | 7 +--
drivers/net/wireless/wl12xx/event.c | 6 +++
drivers/net/wireless/wl12xx/event.h | 5 ++-
drivers/net/wireless/wl12xx/io.h | 1 +
drivers/net/wireless/wl12xx/main.c | 40 ++++++++++++++++++++
drivers/net/wireless/wl12xx/tx.c | 70 +++++++++++++++++++++++++---------
drivers/net/wireless/wl12xx/tx.h | 4 ++
7 files changed, 109 insertions(+), 24 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
index 2f40909..d92c90a 100644
--- a/drivers/net/wireless/wl12xx/boot.c
+++ b/drivers/net/wireless/wl12xx/boot.c
@@ -476,10 +476,9 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
DISCONNECT_EVENT_COMPLETE_ID |
RSSI_SNR_TRIGGER_0_EVENT_ID |
PSPOLL_DELIVERY_FAILURE_EVENT_ID |
- SOFT_GEMINI_SENSE_EVENT_ID;
-
- if (wl->bss_type == BSS_TYPE_AP_BSS)
- wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID;
+ SOFT_GEMINI_SENSE_EVENT_ID |
+ /* The same value as STA_REMOVE_COMPLETE_EVENT_ID */
+ DUMMY_PACKET_EVENT_ID;

ret = wl1271_event_unmask(wl);
if (ret < 0) {
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c
index 1b170c5..413d901 100644
--- a/drivers/net/wireless/wl12xx/event.c
+++ b/drivers/net/wireless/wl12xx/event.c
@@ -228,6 +228,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);

diff --git a/drivers/net/wireless/wl12xx/event.h b/drivers/net/wireless/wl12xx/event.h
index 0e80886..b6cf06e 100644
--- a/drivers/net/wireless/wl12xx/event.h
+++ b/drivers/net/wireless/wl12xx/event.h
@@ -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),
diff --git a/drivers/net/wireless/wl12xx/io.h b/drivers/net/wireless/wl12xx/io.h
index 9ae2f4a..4ea1a77 100644
--- a/drivers/net/wireless/wl12xx/io.h
+++ b/drivers/net/wireless/wl12xx/io.h
@@ -170,5 +170,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void);
int wl1271_free_hw(struct wl1271 *wl);
irqreturn_t wl1271_irq(int irq, void *data);
void wl1271_set_block_size(struct wl1271 *wl);
+int wl1271_tx_dummy_packet(struct wl1271 *wl);

#endif
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 94f99ae..32d963d 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1185,6 +1185,46 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
spin_unlock_irqrestore(&wl->wl_lock, flags);
}

+int wl1271_tx_dummy_packet(struct wl1271 *wl)
+{
+ struct sk_buff *skb = NULL;
+ struct ieee80211_hdr_3addr *hdr;
+ int ret = 0;
+
+ /* 1400 = Regular mpdu size without aggregation */
+ skb = dev_alloc_skb(
+ sizeof(struct wl1271_tx_hw_descr) + sizeof(*hdr) + 1400);
+ if (!skb) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ skb_reserve(skb, sizeof(struct wl1271_tx_hw_descr));
+
+ hdr = (struct ieee80211_hdr_3addr *) skb_put(skb, sizeof(*hdr));
+ memset(hdr, 0, sizeof(*hdr));
+ hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
+ IEEE80211_FCTL_TODS);
+
+ memcpy(hdr->addr1, wl->bssid, ETH_ALEN);
+ memcpy(hdr->addr2, wl->mac_addr, ETH_ALEN);
+ memcpy(hdr->addr3, wl->bssid, ETH_ALEN);
+
+ skb_put(skb, 1400);
+
+ skb->pkt_type = TX_PKT_TYPE_DUMMY_REQ;
+ /* CONF_TX_AC_VO */
+ skb->queue_mapping = 0;
+
+ wl1271_op_tx(wl->hw, skb);
+
+out:
+ if (ret)
+ wl1271_warning("failed to allocate buffer for dummy packet");
+
+ return ret;
+}
+
static struct notifier_block wl1271_dev_notifier = {
.notifier_call = wl1271_dev_notify,
};
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index a7cec1c..441c7de 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -216,8 +216,21 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
else
desc->life_time = cpu_to_le16(TX_HW_AP_MODE_PKT_LIFETIME_TU);

- /* configure the tx attributes */
- tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER;
+ if (skb->pkt_type == TX_PKT_TYPE_DUMMY_REQ) {
+ /*
+ * FW expects the dummy packet to have an invalid session id -
+ * any session id that is different than the one set in the join
+ */
+ tx_attr = ((~wl->session_counter) <<
+ TX_HW_ATTR_OFST_SESSION_COUNTER) &
+ TX_HW_ATTR_SESSION_COUNTER;
+
+ tx_attr |= TX_HW_ATTR_TX_DUMMY_REQ;
+ } else {
+ /* configure the tx attributes */
+ tx_attr =
+ wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER;
+ }

/* queue (we use same identifiers for tid's and ac's */
ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
@@ -590,6 +603,12 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
skb = wl->tx_frames[id];
info = IEEE80211_SKB_CB(skb);

+ if (skb->pkt_type == TX_PKT_TYPE_DUMMY_REQ) {
+ dev_kfree_skb(skb);
+ wl1271_free_tx_id(wl, id);
+ return;
+ }
+
/* update the TX status info */
if (result->status == TX_SUCCESS) {
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
@@ -719,10 +738,15 @@ void wl1271_tx_reset(struct wl1271 *wl)
while ((skb = skb_dequeue(&wl->tx_queue[i]))) {
wl1271_debug(DEBUG_TX, "freeing skb 0x%p",
skb);
- info = IEEE80211_SKB_CB(skb);
- info->status.rates[0].idx = -1;
- info->status.rates[0].count = 0;
- ieee80211_tx_status(wl->hw, skb);
+
+ if (skb->pkt_type == TX_PKT_TYPE_DUMMY_REQ) {
+ dev_kfree_skb(skb);
+ } else {
+ info = IEEE80211_SKB_CB(skb);
+ info->status.rates[0].idx = -1;
+ info->status.rates[0].count = 0;
+ ieee80211_tx_status(wl->hw, skb);
+ }
}
}
}
@@ -743,21 +767,29 @@ void wl1271_tx_reset(struct wl1271 *wl)
wl1271_free_tx_id(wl, i);
wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb);

- /* Remove private headers before passing the skb to mac80211 */
- info = IEEE80211_SKB_CB(skb);
- skb_pull(skb, sizeof(struct wl1271_tx_hw_descr));
- if (info->control.hw_key &&
- info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) {
- int hdrlen = ieee80211_get_hdrlen_from_skb(skb);
- memmove(skb->data + WL1271_TKIP_IV_SPACE, skb->data,
- hdrlen);
- skb_pull(skb, WL1271_TKIP_IV_SPACE);
- }
+ if (skb->pkt_type == TX_PKT_TYPE_DUMMY_REQ) {
+ dev_kfree_skb(skb);
+ } else {
+ /*
+ * Remove private headers before passing the skb to
+ * mac80211
+ */
+ info = IEEE80211_SKB_CB(skb);
+ skb_pull(skb, sizeof(struct wl1271_tx_hw_descr));
+ if (info->control.hw_key &&
+ info->control.hw_key->cipher ==
+ WLAN_CIPHER_SUITE_TKIP) {
+ int hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+ memmove(skb->data + WL1271_TKIP_IV_SPACE,
+ skb->data, hdrlen);
+ skb_pull(skb, WL1271_TKIP_IV_SPACE);
+ }

- info->status.rates[0].idx = -1;
- info->status.rates[0].count = 0;
+ info->status.rates[0].idx = -1;
+ info->status.rates[0].count = 0;

- ieee80211_tx_status(wl->hw, skb);
+ ieee80211_tx_status(wl->hw, skb);
+ }
}
}

diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h
index 3072f95..0dbd8f5 100644
--- a/drivers/net/wireless/wl12xx/tx.h
+++ b/drivers/net/wireless/wl12xx/tx.h
@@ -41,6 +41,7 @@
BIT(8) | BIT(9))
#define TX_HW_ATTR_LAST_WORD_PAD (BIT(10) | BIT(11))
#define TX_HW_ATTR_TX_CMPLT_REQ BIT(12)
+#define TX_HW_ATTR_TX_DUMMY_REQ BIT(13)

#define TX_HW_ATTR_OFST_SAVE_RETRIES 0
#define TX_HW_ATTR_OFST_HEADER_PAD 1
@@ -48,6 +49,9 @@
#define TX_HW_ATTR_OFST_RATE_POLICY 5
#define TX_HW_ATTR_OFST_LAST_WORD_PAD 10
#define TX_HW_ATTR_OFST_TX_CMPLT_REQ 12
+#define TX_HW_ATTR_OFST_TX_DUMMY_REQ 13
+
+#define TX_PKT_TYPE_DUMMY_REQ 5

#define TX_HW_RESULT_QUEUE_LEN 16
#define TX_HW_RESULT_QUEUE_LEN_MASK 0xf
--
1.7.0.4


2011-03-09 17:39:38

by Shahar Levi

[permalink] [raw]
Subject: Re: [PATCH 10/15] wl12xx: 1281/1283 support - Set WiFi & BT cox

On 3/9/11, Luciano Coelho <[email protected]> wrote:
> On Sun, 2011-03-06 at 16:32 +0200, Shahar Levi wrote:
>> Set different Cox setting between wl127x and wl128x.
>>
>> Signed-off-by: Shahar Levi <[email protected]>
>> ---
>> drivers/net/wireless/wl12xx/acx.c | 5 +++++
>> drivers/net/wireless/wl12xx/main.c | 6 +++++-
>> 2 files changed, 10 insertions(+), 1 deletions(-)
>>
>> diff --git a/drivers/net/wireless/wl12xx/acx.c
>> b/drivers/net/wireless/wl12xx/acx.c
>> index f0345e6..e970b71 100644
>> --- a/drivers/net/wireless/wl12xx/acx.c
>> +++ b/drivers/net/wireless/wl12xx/acx.c
>> @@ -554,6 +554,11 @@ int wl1271_acx_sg_cfg(struct wl1271 *wl)
>> goto out;
>> }
>>
>> + if (wl->chip.id == CHIP_ID_1283_PG20)
>> + c->params[CONF_SG_BT_LOAD_RATIO] = 50;
>> + else
>> + c->params[CONF_SG_BT_LOAD_RATIO] = 200;
>> +
>
> You can't change this value in the global array. This needs to be
> changed only in the allocated ACX. I'll change it before taking it in.
>
> Also, I think it's cleaner to keep the correct value for wl127x in the
> global array (as was before) and only change the value for wl128x here
> in this function.
>
>> diff --git a/drivers/net/wireless/wl12xx/main.c
>> b/drivers/net/wireless/wl12xx/main.c
>> index 32d963d..f8e9e3f 100644
>> --- a/drivers/net/wireless/wl12xx/main.c
>> +++ b/drivers/net/wireless/wl12xx/main.c
>> @@ -54,7 +54,11 @@ static struct conf_drv_settings default_conf = {
>> [CONF_SG_BT_PER_THRESHOLD] = 7500,
>> [CONF_SG_HV3_MAX_OVERRIDE] = 0,
>> [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400,
>> - [CONF_SG_BT_LOAD_RATIO] = 50,
>> + /*
>> + * CONF_SG_BT_LOAD_RATIO has wl127x or wl128x dependency
>> + * (set in wl1271_acx_sg_cfg()
>> + */
>> + [CONF_SG_BT_LOAD_RATIO] = 0,
>> [CONF_SG_AUTO_PS_MODE] = 1,
>> [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170,
>> [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50,
>
> Previously, the value used for wl127x was 50, from the default global
> settings. Now you're using 200 for wl127x. This looks suspicious. You
> now use 50 (which was the value for wl127x) for wl128x and 200 for
> wl127x.
>
> At least the change for wl127x should be done in a separate patch.
It was incorrect value for wl127x. That patch fixes that and set
wl128x value. I can do the fix for wl127x in separate patch.

>
> --
> Cheers,
> Luca.
>
>
--
All the best,
Shahar

2011-03-06 14:28:12

by Shahar Levi

[permalink] [raw]
Subject: [PATCH 03/15] wl12xx: 1281/1283 support - Add acx commands

New acx command that sets: Rx fifo enable reduced bus transactions
in RX path. Tx bus transactions padding to SDIO block size that
improve preference in Tx and essential for working with SDIO HS (48Mhz).
The max SDIO block size is 256 when working with Tx bus transactions
padding to SDIO block.

Add new ops to SDIO & SPI that handles the win size change in case of
transactions padding (relevant only for SDIO).

Signed-off-by: Shahar Levi <[email protected]>
---
drivers/net/wireless/wl12xx/acx.c | 26 +++++++++++++++
drivers/net/wireless/wl12xx/acx.h | 11 ++++++
drivers/net/wireless/wl12xx/init.c | 19 +++++++++++
drivers/net/wireless/wl12xx/io.c | 5 +++
drivers/net/wireless/wl12xx/io.h | 1 +
drivers/net/wireless/wl12xx/main.c | 14 ++++++++
drivers/net/wireless/wl12xx/sdio.c | 15 ++++++++-
drivers/net/wireless/wl12xx/spi.c | 11 ++++++-
drivers/net/wireless/wl12xx/tx.c | 59 ++++++++++++++++++++++++---------
drivers/net/wireless/wl12xx/tx.h | 46 +++++++++++++++++++++-----
drivers/net/wireless/wl12xx/wl12xx.h | 5 +++
11 files changed, 185 insertions(+), 27 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index a3db755..aa0fc12 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -1019,6 +1019,32 @@ out:
return ret;
}

+int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl)
+{
+ 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 = wl->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;
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h
index dd19b01..2d0bbfe 100644
--- a/drivers/net/wireless/wl12xx/acx.h
+++ b/drivers/net/wireless/wl12xx/acx.h
@@ -939,6 +939,16 @@ struct wl1271_acx_keep_alive_config {
u8 padding;
} __packed;

+#define HOST_IF_CFG_BITMAP_RX_FIFO_ENABLE BIT(0)
+#define HOST_IF_CFG_BITMAP_TX_EXTRA_BLKS_SWAP BIT(1)
+#define HOST_IF_CFG_BITMAP_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);
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);
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
index 6072fe4..2f31d14 100644
--- a/drivers/net/wireless/wl12xx/init.c
+++ b/drivers/net/wireless/wl12xx/init.c
@@ -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)
{
@@ -519,6 +520,24 @@ int wl1271_hw_init(struct wl1271 *wl)
if (ret < 0)
return ret;

+ if (wl->chip.id == CHIP_ID_1283_PG20) {
+ wl1271_set_block_size(wl);
+
+ wl->host_cfg_bitmap = HOST_IF_CFG_BITMAP_RX_FIFO_ENABLE;
+
+ if (wl->block_size)
+ wl->host_cfg_bitmap |=
+ HOST_IF_CFG_BITMAP_TX_PAD_TO_SDIO_BLK;
+
+ /*
+ * Host interface configuration must be before
+ * wl1271_acx_init_mem_config !
+ */
+ ret = wl1271_acx_host_if_cfg_bitmap(wl);
+ if (ret < 0)
+ return ret;
+ }
+
/* Mode specific init */
if (is_ap)
ret = wl1271_ap_hw_init(wl);
diff --git a/drivers/net/wireless/wl12xx/io.c b/drivers/net/wireless/wl12xx/io.c
index d557f73..ca7229f 100644
--- a/drivers/net/wireless/wl12xx/io.c
+++ b/drivers/net/wireless/wl12xx/io.c
@@ -43,6 +43,11 @@
#define OCP_STATUS_REQ_FAILED 0x20000
#define OCP_STATUS_RESP_ERROR 0x30000

+void wl1271_set_block_size(struct wl1271 *wl)
+{
+ wl->if_ops->set_block_size(wl);
+}
+
void wl1271_disable_interrupts(struct wl1271 *wl)
{
wl->if_ops->disable_irq(wl);
diff --git a/drivers/net/wireless/wl12xx/io.h b/drivers/net/wireless/wl12xx/io.h
index c1aac82..9ae2f4a 100644
--- a/drivers/net/wireless/wl12xx/io.h
+++ b/drivers/net/wireless/wl12xx/io.h
@@ -169,5 +169,6 @@ 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);
+void wl1271_set_block_size(struct wl1271 *wl);

#endif
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index b0c4935..ac0513a 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -450,6 +450,20 @@ static int wl1271_plt_init(struct wl1271 *wl)
if (ret < 0)
return ret;

+ if (wl->chip.id == CHIP_ID_1283_PG20) {
+ wl1271_set_block_size(wl);
+
+ wl->host_cfg_bitmap = HOST_IF_CFG_BITMAP_RX_FIFO_ENABLE;
+
+ if (wl->block_size)
+ wl->host_cfg_bitmap |=
+ HOST_IF_CFG_BITMAP_TX_PAD_TO_SDIO_BLK;
+
+ ret = wl1271_acx_host_if_cfg_bitmap(wl);
+ if (ret < 0)
+ return ret;
+ }
+
ret = wl1271_sta_init_templates_config(wl);
if (ret < 0)
return ret;
diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c
index 58d0208..ed0f37e 100644
--- a/drivers/net/wireless/wl12xx/sdio.c
+++ b/drivers/net/wireless/wl12xx/sdio.c
@@ -51,6 +51,18 @@ static const struct sdio_device_id wl1271_devices[] = {
};
MODULE_DEVICE_TABLE(sdio, wl1271_devices);

+/* The max SDIO block size is 256 when working with tx padding to SDIO block */
+#define TX_PAD_SDIO_BLK_SIZE 256
+
+static void wl1271_sdio_set_block_size(struct wl1271 *wl)
+{
+ wl->block_size = TX_PAD_SDIO_BLK_SIZE;
+
+ sdio_claim_host(wl->if_priv);
+ sdio_set_block_size(wl->if_priv, TX_PAD_SDIO_BLK_SIZE);
+ sdio_release_host(wl->if_priv);
+}
+
static inline struct sdio_func *wl_to_func(struct wl1271 *wl)
{
return wl->if_priv;
@@ -203,7 +215,8 @@ static struct wl1271_if_operations sdio_ops = {
.power = wl1271_sdio_set_power,
.dev = wl1271_sdio_wl_to_dev,
.enable_irq = wl1271_sdio_enable_interrupts,
- .disable_irq = wl1271_sdio_disable_interrupts
+ .disable_irq = wl1271_sdio_disable_interrupts,
+ .set_block_size = wl1271_sdio_set_block_size,
};

static int __devinit wl1271_probe(struct sdio_func *func,
diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c
index 2993715..d6e566e 100644
--- a/drivers/net/wireless/wl12xx/spi.c
+++ b/drivers/net/wireless/wl12xx/spi.c
@@ -68,6 +68,14 @@

#define WSPI_MAX_NUM_OF_CHUNKS (WL1271_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE)

+/* When working with SPI block size not relevent*/
+#define TX_PAD_SDIO_BLK_SIZE 0
+
+void wl1271_spi_set_block_size(struct wl1271 *wl)
+{
+ wl->block_size = TX_PAD_SDIO_BLK_SIZE;
+}
+
static inline struct spi_device *wl_to_spi(struct wl1271 *wl)
{
return wl->if_priv;
@@ -355,7 +363,8 @@ static struct wl1271_if_operations spi_ops = {
.power = wl1271_spi_set_power,
.dev = wl1271_spi_wl_to_dev,
.enable_irq = wl1271_spi_enable_interrupts,
- .disable_irq = wl1271_spi_disable_interrupts
+ .disable_irq = wl1271_spi_disable_interrupts,
+ .set_block_size = wl1271_spi_set_block_size,
};

static int __devinit wl1271_probe(struct spi_device *spi)
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 5e9ef7d..542b785 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -145,14 +145,22 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,

/* approximate the number of blocks required for this packet
in the firmware */
- total_blocks = total_len + TX_HW_BLOCK_SIZE - 1;
+ if (wl->host_cfg_bitmap & HOST_IF_CFG_BITMAP_TX_PAD_TO_SDIO_BLK) {
+ u32 sdio_block_mask = wl->block_size - 1;
+ int pad = (total_len + sdio_block_mask) & (~sdio_block_mask);
+
+ total_blocks = pad + TX_HW_BLOCK_SIZE - 1;
+ } else {
+ total_blocks = total_len + TX_HW_BLOCK_SIZE - 1;
+ }
+
total_blocks = total_blocks / TX_HW_BLOCK_SIZE + TX_HW_BLOCK_SPARE;
if (total_blocks <= wl->tx_blocks_available) {
desc = (struct wl1271_tx_hw_descr *)skb_push(
skb, total_len - skb->len);

- desc->extra_mem_blocks = TX_HW_BLOCK_SPARE;
- desc->total_mem_blocks = total_blocks;
+ desc->wl127x_mem.extra_blocks = TX_HW_BLOCK_SPARE;
+ desc->wl127x_mem.total_mem_blocks = total_blocks;
desc->id = id;

wl->tx_blocks_available -= total_blocks;
@@ -237,20 +245,31 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
tx_attr |= rate_idx << TX_HW_ATTR_OFST_RATE_POLICY;
desc->reserved = 0;

- /* align the length (and store in terms of words) */
- pad = ALIGN(skb->len, WL1271_TX_ALIGN_TO);
- desc->length = cpu_to_le16(pad >> 2);
+ if (wl->host_cfg_bitmap & HOST_IF_CFG_BITMAP_TX_PAD_TO_SDIO_BLK) {
+ u32 sdio_block_mask = wl->block_size - 1;
+ int pad = (skb->len + sdio_block_mask) &
+ (~sdio_block_mask);

- /* calculate number of padding bytes */
- pad = pad - skb->len;
- tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD;
+ desc->wl128x_mem.extra_bytes = pad - skb->len;
+
+ desc->length = cpu_to_le16(pad >> 2);
+ } else {
+ /* align the length (and store in terms of words) */
+ pad = ALIGN(skb->len, WL1271_TX_ALIGN_TO);
+ desc->length = cpu_to_le16(pad >> 2);
+
+ /* calculate number of padding bytes */
+ pad = pad - skb->len;
+ tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD;
+ }

desc->tx_attr = cpu_to_le16(tx_attr);

wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d hlid: %d "
"tx_attr: 0x%x len: %d life: %d mem: %d", pad, desc->hlid,
le16_to_cpu(desc->tx_attr), le16_to_cpu(desc->length),
- le16_to_cpu(desc->life_time), desc->total_mem_blocks);
+ le16_to_cpu(desc->life_time),
+ desc->wl127x_mem.total_mem_blocks);
}

/* caller must hold wl->mutex */
@@ -304,12 +323,20 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,

wl1271_tx_fill_hdr(wl, skb, extra, info, hlid);

- /*
- * The length of each packet is stored in terms of words. Thus, we must
- * pad the skb data to make sure its length is aligned.
- * The number of padding bytes is computed and set in wl1271_tx_fill_hdr
- */
- total_len = ALIGN(skb->len, WL1271_TX_ALIGN_TO);
+ if (wl->host_cfg_bitmap & HOST_IF_CFG_BITMAP_TX_PAD_TO_SDIO_BLK) {
+ unsigned sdio_block_mask = wl->block_size - 1;
+
+ total_len = (skb->len + sdio_block_mask) & (~sdio_block_mask);
+ } else {
+ /*
+ * The length of each packet is stored in terms of words. Thus,
+ * we must pad the skb data to make sure its length is aligned.
+ * The number of padding bytes is computed and set in
+ * wl1271_tx_fill_hdr
+ */
+ total_len = ALIGN(skb->len, WL1271_TX_ALIGN_TO);
+ }
+
memcpy(wl->aggr_buf + buf_offset, skb->data, skb->len);
memset(wl->aggr_buf + buf_offset + skb->len, 0, total_len - skb->len);

diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h
index 02f07fa..3072f95 100644
--- a/drivers/net/wireless/wl12xx/tx.h
+++ b/drivers/net/wireless/wl12xx/tx.h
@@ -55,20 +55,48 @@
#define WL1271_TX_ALIGN_TO 4
#define WL1271_TKIP_IV_SPACE 4

+struct wl127x_tx_mem {
+ /*
+ * on wl127x: Number of extra memory blocks to allocate
+ * for this packet in addition to the number of blocks
+ * derived from the packet length
+ */
+ u8 extra_blocks;
+ /*
+ * on wl127x: Total number of memory blocks allocated by
+ * the host for this packet. Must be equal or greater
+ * than the actual blocks number allocated by HW!!
+ */
+ u8 total_mem_blocks;
+} __packed;
+
+struct wl128x_tx_mem {
+ /*
+ * on wl128x: Total number of memory blocks allocated by
+ * the host for this packet.
+ */
+ u8 total_mem_blocks;
+ /*
+ * on wl128x: Number of extra bytes, at the end of the
+ * frame. the host uses this padding to complete each
+ * frame to integer number of SDIO blocks.
+ */
+ u8 extra_bytes;
+} __packed;
+
struct wl1271_tx_hw_descr {
/* Length of packet in words, including descriptor+header+data */
__le16 length;
- /* Number of extra memory blocks to allocate for this packet in
- addition to the number of blocks derived from the packet length */
- u8 extra_mem_blocks;
- /* Total number of memory blocks allocated by the host for this packet.
- Must be equal or greater than the actual blocks number allocated by
- HW!! */
- u8 total_mem_blocks;
+ union {
+ struct wl127x_tx_mem wl127x_mem;
+ struct wl128x_tx_mem wl128x_mem;
+ } __packed;
/* Device time (in us) when the packet arrived to the driver */
__le32 start_time;
- /* Max delay in TUs until transmission. The last device time the
- packet can be transmitted is: startTime+(1024*LifeTime) */
+ /*
+ * Max delay in TUs until transmission. The last device time the
+ * packet can be transmitted is: startTime+(1024*LifeTime)
+ */
__le16 life_time;
/* Bitwise fields - see TX_ATTR... definitions above. */
__le16 tx_attr;
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 7adb856..3c3bde9 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -303,6 +303,7 @@ struct wl1271_if_operations {
struct device* (*dev)(struct wl1271 *wl);
void (*enable_irq)(struct wl1271 *wl);
void (*disable_irq)(struct wl1271 *wl);
+ void (*set_block_size) (struct wl1271 *wl);
};

#define MAX_NUM_KEYS 14
@@ -533,6 +534,10 @@ struct wl1271 {
bool ba_support;
u8 ba_rx_bitmap;

+ /* wl128x features only */
+ __le32 host_cfg_bitmap;
+ u32 block_size;
+
/*
* AP-mode - links indexed by HLID. The global and broadcast links
* are always active.
--
1.7.0.4


2011-03-08 18:08:27

by Shahar Levi

[permalink] [raw]
Subject: Re: [PATCH 06/15] wl12xx: 1281/1283 support - New boot sequence

On Tue, Mar 8, 2011 at 3:11 PM, Luciano Coelho <[email protected]> wrote:
> On Sun, 2011-03-06 at 16:32 +0200, Shahar Levi wrote:
>> - ? ? ? clk |= (wl->ref_clock << 1) << 4;
>> + ? ? ? if (wl->chip.id == CHIP_ID_1283_PG20) {
>> + ? ? ? ? ? ? ? if (is_ref_clk == false)
>> + ? ? ? ? ? ? ? ? ? ? ? clk |= ((wl->tcxo_clock & 0x3) << 1) << 4;
>> + ? ? ? ? ? ? ? else
>> + ? ? ? ? ? ? ? ? ? ? ? clk |= ((wl->ref_clock & 0x3) << 1) << 4;
>> + ? ? ? } else
>> + ? ? ? ? ? ? ? clk |= ((wl->ref_clock & 0x3) << 1) << 4;
>> +
>> ? ? ? ? wl1271_write32(wl, DRPW_SCRATCH_START, clk);
>
> Can you explain why you changed the wl127x part as well? For wl127x
> you're essentially changing:
>
> clk |= (wl->ref_clock << 1) << 4;
>
> to:
>
> clk |= ((wl->ref_clock & 0x3) << 1) << 4;
>
> This means that CONF_REF_CLK_38_4_M_XTAL will be treated in the same way
> as CONF_REF_CLK_19_2_E. ?Is that right? If it is, it must be addressed
> in a separate patch and not as part of the Quattro series.
This implantation is due to the fact only those two bits is valid for
clk setting (from MCP).
CONF_REF_CLK_38_4_M_XTAL should be set as 19M.
I will address is as separate patch.

> --
> Cheers,
> Luca.
--
All the best,
Shahar

2011-03-07 12:55:09

by Luciano Coelho

[permalink] [raw]
Subject: Re: [PATCH] wl12xx: fixes for 1281/1283 support - Add acx commands

Ooops! Used the wrong email address for Shahar.


On Mon, 2011-03-07 at 14:53 +0200, Luciano Coelho wrote:
> This patch fixes up some issues with patch 03/15 in the wl128x support
> series:
>
> * Fix endianess issues;
> * Simplify sdio-specific block_size handling;
> * Minor changes in comments
>
> This has been compile-tested only. I will test this changes after I
> go through the whole series and, if everything is still ok, I'll merge
> this patch into 03/15.
>
> Cc: Shahar Levi <[email protected]>
> Signed-off-by: Luciano Coelho <[email protected]>
> ---
> drivers/net/wireless/wl12xx/acx.c | 4 +-
> drivers/net/wireless/wl12xx/acx.h | 8 +++---
> drivers/net/wireless/wl12xx/init.c | 42 ++++++++++++++++++++-------------
> drivers/net/wireless/wl12xx/init.h | 1 +
> drivers/net/wireless/wl12xx/io.c | 9 +++++-
> drivers/net/wireless/wl12xx/io.h | 2 +-
> drivers/net/wireless/wl12xx/main.c | 18 ++++----------
> drivers/net/wireless/wl12xx/spi.c | 10 +-------
> drivers/net/wireless/wl12xx/tx.c | 41 +++++++++++++-------------------
> drivers/net/wireless/wl12xx/tx.h | 24 +++++++++---------
> drivers/net/wireless/wl12xx/wl12xx.h | 4 +--
> 11 files changed, 76 insertions(+), 87 deletions(-)
>
> diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
> index aa0fc12..50676b3 100644
> --- a/drivers/net/wireless/wl12xx/acx.c
> +++ b/drivers/net/wireless/wl12xx/acx.c
> @@ -1019,7 +1019,7 @@ out:
> return ret;
> }
>
> -int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl)
> +int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap)
> {
> struct wl1271_acx_host_config_bitmap *bitmap_conf;
> int ret;
> @@ -1030,7 +1030,7 @@ int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl)
> goto out;
> }
>
> - bitmap_conf->host_cfg_bitmap = wl->host_cfg_bitmap;
> + 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));
> diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h
> index 2d0bbfe..0a40cae 100644
> --- a/drivers/net/wireless/wl12xx/acx.h
> +++ b/drivers/net/wireless/wl12xx/acx.h
> @@ -939,9 +939,9 @@ struct wl1271_acx_keep_alive_config {
> u8 padding;
> } __packed;
>
> -#define HOST_IF_CFG_BITMAP_RX_FIFO_ENABLE BIT(0)
> -#define HOST_IF_CFG_BITMAP_TX_EXTRA_BLKS_SWAP BIT(1)
> -#define HOST_IF_CFG_BITMAP_TX_PAD_TO_SDIO_BLK BIT(3)
> +#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;
> @@ -1285,7 +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);
> +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);
> diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
> index 2f31d14..34c4108 100644
> --- a/drivers/net/wireless/wl12xx/init.c
> +++ b/drivers/net/wireless/wl12xx/init.c
> @@ -505,6 +505,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 (wl1271_set_block_size(wl))
> + /* 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;
> @@ -520,23 +541,10 @@ int wl1271_hw_init(struct wl1271 *wl)
> if (ret < 0)
> return ret;
>
> - if (wl->chip.id == CHIP_ID_1283_PG20) {
> - wl1271_set_block_size(wl);
> -
> - wl->host_cfg_bitmap = HOST_IF_CFG_BITMAP_RX_FIFO_ENABLE;
> -
> - if (wl->block_size)
> - wl->host_cfg_bitmap |=
> - HOST_IF_CFG_BITMAP_TX_PAD_TO_SDIO_BLK;
> -
> - /*
> - * Host interface configuration must be before
> - * wl1271_acx_init_mem_config !
> - */
> - ret = wl1271_acx_host_if_cfg_bitmap(wl);
> - if (ret < 0)
> - return ret;
> - }
> + /* Chip-specific init */
> + ret = wl1271_chip_specific_init(wl);
> + if (ret < 0)
> + return ret;
>
> /* Mode specific init */
> if (is_ap)
> diff --git a/drivers/net/wireless/wl12xx/init.h b/drivers/net/wireless/wl12xx/init.h
> index 3a8bd3f..4975270 100644
> --- a/drivers/net/wireless/wl12xx/init.h
> +++ b/drivers/net/wireless/wl12xx/init.h
> @@ -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
> diff --git a/drivers/net/wireless/wl12xx/io.c b/drivers/net/wireless/wl12xx/io.c
> index ca7229f..aa40c98 100644
> --- a/drivers/net/wireless/wl12xx/io.c
> +++ b/drivers/net/wireless/wl12xx/io.c
> @@ -43,9 +43,14 @@
> #define OCP_STATUS_REQ_FAILED 0x20000
> #define OCP_STATUS_RESP_ERROR 0x30000
>
> -void wl1271_set_block_size(struct wl1271 *wl)
> +bool wl1271_set_block_size(struct wl1271 *wl)
> {
> - wl->if_ops->set_block_size(wl);
> + if (wl->if_ops->set_block_size) {
> + wl->if_ops->set_block_size(wl);
> + return true;
> + }
> +
> + return false;
> }
>
> void wl1271_disable_interrupts(struct wl1271 *wl)
> diff --git a/drivers/net/wireless/wl12xx/io.h b/drivers/net/wireless/wl12xx/io.h
> index 9ae2f4a..84454f6 100644
> --- a/drivers/net/wireless/wl12xx/io.h
> +++ b/drivers/net/wireless/wl12xx/io.h
> @@ -169,6 +169,6 @@ 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);
> -void wl1271_set_block_size(struct wl1271 *wl);
> +bool wl1271_set_block_size(struct wl1271 *wl);
>
> #endif
> diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
> index ac0513a..c03876d 100644
> --- a/drivers/net/wireless/wl12xx/main.c
> +++ b/drivers/net/wireless/wl12xx/main.c
> @@ -450,19 +450,10 @@ static int wl1271_plt_init(struct wl1271 *wl)
> if (ret < 0)
> return ret;
>
> - if (wl->chip.id == CHIP_ID_1283_PG20) {
> - wl1271_set_block_size(wl);
> -
> - wl->host_cfg_bitmap = HOST_IF_CFG_BITMAP_RX_FIFO_ENABLE;
> -
> - if (wl->block_size)
> - wl->host_cfg_bitmap |=
> - HOST_IF_CFG_BITMAP_TX_PAD_TO_SDIO_BLK;
> -
> - ret = wl1271_acx_host_if_cfg_bitmap(wl);
> - if (ret < 0)
> - return ret;
> - }
> + /* Chip-specific initializations */
> + ret = wl1271_chip_specific_init(wl);
> + if (ret < 0)
> + return ret;
>
> ret = wl1271_sta_init_templates_config(wl);
> if (ret < 0)
> @@ -3472,6 +3463,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
> wl->ap_ps_map = 0;
> wl->ap_fw_ps_map = 0;
> wl->quirks = 0;
> + wl->block_size = 0;
>
> memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map));
> for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
> diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c
> index d6e566e..2a57583 100644
> --- a/drivers/net/wireless/wl12xx/spi.c
> +++ b/drivers/net/wireless/wl12xx/spi.c
> @@ -68,14 +68,6 @@
>
> #define WSPI_MAX_NUM_OF_CHUNKS (WL1271_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE)
>
> -/* When working with SPI block size not relevent*/
> -#define TX_PAD_SDIO_BLK_SIZE 0
> -
> -void wl1271_spi_set_block_size(struct wl1271 *wl)
> -{
> - wl->block_size = TX_PAD_SDIO_BLK_SIZE;
> -}
> -
> static inline struct spi_device *wl_to_spi(struct wl1271 *wl)
> {
> return wl->if_priv;
> @@ -364,7 +356,7 @@ static struct wl1271_if_operations spi_ops = {
> .dev = wl1271_spi_wl_to_dev,
> .enable_irq = wl1271_spi_enable_interrupts,
> .disable_irq = wl1271_spi_disable_interrupts,
> - .set_block_size = wl1271_spi_set_block_size,
> + .set_block_size = NULL,
> };
>
> static int __devinit wl1271_probe(struct spi_device *spi)
> diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
> index 542b785..30dc45a 100644
> --- a/drivers/net/wireless/wl12xx/tx.c
> +++ b/drivers/net/wireless/wl12xx/tx.c
> @@ -145,14 +145,11 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
>
> /* approximate the number of blocks required for this packet
> in the firmware */
> - if (wl->host_cfg_bitmap & HOST_IF_CFG_BITMAP_TX_PAD_TO_SDIO_BLK) {
> - u32 sdio_block_mask = wl->block_size - 1;
> - int pad = (total_len + sdio_block_mask) & (~sdio_block_mask);
> -
> - total_blocks = pad + TX_HW_BLOCK_SIZE - 1;
> - } else {
> + if (wl->block_size)
> + total_blocks = ALIGN(total_len, wl->block_size) +
> + TX_HW_BLOCK_SIZE - 1;
> + else
> total_blocks = total_len + TX_HW_BLOCK_SIZE - 1;
> - }
>
> total_blocks = total_blocks / TX_HW_BLOCK_SIZE + TX_HW_BLOCK_SPARE;
> if (total_blocks <= wl->tx_blocks_available) {
> @@ -245,13 +242,10 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
> tx_attr |= rate_idx << TX_HW_ATTR_OFST_RATE_POLICY;
> desc->reserved = 0;
>
> - if (wl->host_cfg_bitmap & HOST_IF_CFG_BITMAP_TX_PAD_TO_SDIO_BLK) {
> - u32 sdio_block_mask = wl->block_size - 1;
> - int pad = (skb->len + sdio_block_mask) &
> - (~sdio_block_mask);
> + if (wl->block_size) {
> + pad = ALIGN(skb->len, wl->block_size);
>
> desc->wl128x_mem.extra_bytes = pad - skb->len;
> -
> desc->length = cpu_to_le16(pad >> 2);
> } else {
> /* align the length (and store in terms of words) */
> @@ -323,19 +317,18 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
>
> wl1271_tx_fill_hdr(wl, skb, extra, info, hlid);
>
> - if (wl->host_cfg_bitmap & HOST_IF_CFG_BITMAP_TX_PAD_TO_SDIO_BLK) {
> - unsigned sdio_block_mask = wl->block_size - 1;
> -
> - total_len = (skb->len + sdio_block_mask) & (~sdio_block_mask);
> - } else {
> - /*
> - * The length of each packet is stored in terms of words. Thus,
> - * we must pad the skb data to make sure its length is aligned.
> - * The number of padding bytes is computed and set in
> - * wl1271_tx_fill_hdr
> - */
> + /*
> + * The length of each packet is stored in terms of
> + * words. Thus, we must pad the skb data to make sure its
> + * length is aligned. The number of padding bytes is computed
> + * and set in wl1271_tx_fill_hdr.
> + * In special cases, we want to align to a specific block size
> + * (eg. for wl128x with SDIO we align to 256).
> + */
> + if (wl->block_size)
> + total_len = ALIGN(skb->len, wl->block_size);
> + else
> total_len = ALIGN(skb->len, WL1271_TX_ALIGN_TO);
> - }
>
> memcpy(wl->aggr_buf + buf_offset, skb->data, skb->len);
> memset(wl->aggr_buf + buf_offset + skb->len, 0, total_len - skb->len);
> diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h
> index 3072f95..e313177 100644
> --- a/drivers/net/wireless/wl12xx/tx.h
> +++ b/drivers/net/wireless/wl12xx/tx.h
> @@ -57,29 +57,29 @@
>
> struct wl127x_tx_mem {
> /*
> - * on wl127x: Number of extra memory blocks to allocate
> - * for this packet in addition to the number of blocks
> - * derived from the packet length
> + * Number of extra memory blocks to allocate for this packet
> + * in addition to the number of blocks derived from the packet
> + * length.
> */
> u8 extra_blocks;
> /*
> - * on wl127x: Total number of memory blocks allocated by
> - * the host for this packet. Must be equal or greater
> - * than the actual blocks number allocated by HW!!
> + * Total number of memory blocks allocated by the host for
> + * this packet. Must be equal or greater than the actual
> + * blocks number allocated by HW.
> */
> u8 total_mem_blocks;
> } __packed;
>
> struct wl128x_tx_mem {
> /*
> - * on wl128x: Total number of memory blocks allocated by
> - * the host for this packet.
> + * Total number of memory blocks allocated by the host for
> + * this packet.
> */
> u8 total_mem_blocks;
> /*
> - * on wl128x: Number of extra bytes, at the end of the
> - * frame. the host uses this padding to complete each
> - * frame to integer number of SDIO blocks.
> + * Number of extra bytes, at the end of the frame. the host
> + * uses this padding to complete each frame to integer number
> + * of SDIO blocks.
> */
> u8 extra_bytes;
> } __packed;
> @@ -95,7 +95,7 @@ struct wl1271_tx_hw_descr {
> __le32 start_time;
> /*
> * Max delay in TUs until transmission. The last device time the
> - * packet can be transmitted is: startTime+(1024*LifeTime)
> + * packet can be transmitted is: start_time + (1024 * life_time)
> */
> __le16 life_time;
> /* Bitwise fields - see TX_ATTR... definitions above. */
> diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
> index 94b4062..959b338 100644
> --- a/drivers/net/wireless/wl12xx/wl12xx.h
> +++ b/drivers/net/wireless/wl12xx/wl12xx.h
> @@ -534,9 +534,7 @@ struct wl1271 {
> bool ba_support;
> u8 ba_rx_bitmap;
>
> - /* wl128x features only */
> - __le32 host_cfg_bitmap;
> - u32 block_size;
> + u32 block_size;
>
> /*
> * AP-mode - links indexed by HLID. The global and broadcast links

--
Cheers,
Luca.


2011-03-10 21:13:48

by Luciano Coelho

[permalink] [raw]
Subject: Re: [PATCH 05/15] wl12xx: 1281/1283 support - Loading FW & NVS

> diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
> index 69fe870..7984631 100644
> --- a/drivers/net/wireless/wl12xx/boot.c
> +++ b/drivers/net/wireless/wl12xx/boot.c
> @@ -240,36 +240,62 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
> u32 dest_addr, val;
> u8 *nvs_ptr, *nvs_aligned;
>
> - 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 (nvs == NULL)
> + return -ENODEV;
> +
> + 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(nvs);
> + nvs = NULL;

This is wrong. You're just setting the local nvs variable to NULL.
It's wl->nvs that should be set to NULL instead.


> + wl->nvs_len = 0;
> + return -EILSEQ;
> + }
>
> - /*
> - * 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;
> - }
> + /* only the first part of the NVS needs to be uploaded */
> + nvs_len = sizeof(nvs->nvs);
> + nvs_ptr = (u8 *)nvs->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;

Same thing here. I have fixed these.

This was causing very bad behaviour when the NVS was with the wrong
size, because we were not setting wl->nvs to NULL, but were setting
wl->nvs_len to 0.


--
Cheers,
Luca.


2011-03-06 14:28:29

by Shahar Levi

[permalink] [raw]
Subject: [PATCH 15/15] wl12xx: 1281/1283 support - enable chip support

Add support to wl128x chip via chip id

Signed-off-by: Shahar Levi <[email protected]>
---
drivers/net/wireless/wl12xx/Kconfig | 2 +-
drivers/net/wireless/wl12xx/main.c | 9 +++++++++
drivers/net/wireless/wl12xx/sdio_test.c | 5 +++++
3 files changed, 15 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig
index 692ebff..35ce7b0 100644
--- a/drivers/net/wireless/wl12xx/Kconfig
+++ b/drivers/net/wireless/wl12xx/Kconfig
@@ -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
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 8ac3936..af4739d 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1023,6 +1023,15 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
if (ret < 0)
goto out;
break;
+ case CHIP_ID_1283_PG20:
+ wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1283 PG20)",
+ wl->chip.id);
+
+ ret = wl1271_setup(wl);
+ if (ret < 0)
+ goto out;
+ break;
+ case CHIP_ID_1283_PG10:
default:
wl1271_warning("unsupported chip id: 0x%x", wl->chip.id);
ret = -ENODEV;
diff --git a/drivers/net/wireless/wl12xx/sdio_test.c b/drivers/net/wireless/wl12xx/sdio_test.c
index c02c870..968249a 100644
--- a/drivers/net/wireless/wl12xx/sdio_test.c
+++ b/drivers/net/wireless/wl12xx/sdio_test.c
@@ -293,6 +293,11 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
wl1271_notice("chip id 0x%x (1271 PG20)",
wl->chip.id);
break;
+ case CHIP_ID_1283_PG20:
+ wl1271_notice("chip id 0x%x (1283 PG20)",
+ wl->chip.id);
+ break;
+ case CHIP_ID_1283_PG10:
default:
wl1271_warning("unsupported chip id: 0x%x", wl->chip.id);
return -ENODEV;
--
1.7.0.4


2011-03-08 18:15:34

by Shahar Levi

[permalink] [raw]
Subject: Re: [PATCH] wl12xx: fixes for 1281/1283 support - New boot sequence

On Tue, Mar 8, 2011 at 3:37 PM, Luciano Coelho <[email protected]> wrote:
> This patch fixes up some issues with patch 06/15 in the wl128x support
> series:
>
> * Remove unnecessary else block in wl128x_switch_fref;
> * Remove unnecessary change in main.c;
> * Remove some unnecessary debug prints and comments;
> * Fix potential use of uninitialized value (pll_config)
> * Add more all the defines for HCI_IO_DS_* instead of having them in a comment
>
> This has been compile-tested only. ?I will test this changes after I
> go through the whole series and, if everything is still ok, I'll merge
> this patch into 06/15.
>
> Cc: Shahar Levi <[email protected]>
> Signed-off-by: Luciano Coelho <[email protected]>
> ---
> ?drivers/net/wireless/wl12xx/boot.c | ?106 +++++++++++++++---------------------
> ?drivers/net/wireless/wl12xx/boot.h | ? ?5 ++
> ?2 files changed, 48 insertions(+), 63 deletions(-)
>
> diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
> index e0d60ab..ffdcb7e 100644
> --- a/drivers/net/wireless/wl12xx/boot.c
> +++ b/drivers/net/wireless/wl12xx/boot.c
> @@ -533,46 +533,42 @@ static int wl128x_switch_fref(struct wl1271 *wl, bool *is_ref_clk)
>
> ? ? ? ?/* if working on XTAL-only mode go directly to TCXO TO FREF SWITCH */
> ? ? ? ?if ((wl->ref_clock == CONF_REF_CLK_38_4_M_XTAL) ||
> - ? ? ? ? ? (wl->ref_clock == CONF_REF_CLK_26_M_XTAL)) {
> - ? ? ? ? ? ? ? wl1271_debug(DEBUG_BOOT, "XTAL-only mode go directly to"
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?" TCXO TO FREF SWITCH");
I believe that debug should be say in that function that check the ref value.

...
> @@ -753,8 +742,9 @@ int wl1271_load_firmware(struct wl1271 *wl)
> ? ? ? ? ? ? ? ? ? ? ? ?clk |= ((wl->tcxo_clock & 0x3) << 1) << 4;
> ? ? ? ? ? ? ? ?else
> ? ? ? ? ? ? ? ? ? ? ? ?clk |= ((wl->ref_clock & 0x3) << 1) << 4;
> - ? ? ? } else
> - ? ? ? ? ? ? ? clk |= ((wl->ref_clock & 0x3) << 1) << 4;
> + ? ? ? } else {
> + ? ? ? ? ? ? ? clk |= (wl->ref_clock << 1) << 4;
> + ? ? ? }
This implantation is due to the fact only those two bits is valid for
clk setting (from MCP).
CONF_REF_CLK_38_4_M_XTAL should be set as 19M.
I will address is as separate patch.

>
> ? ? ? ?wl1271_write32(wl, DRPW_SCRATCH_START, clk);
>
> @@ -788,18 +778,8 @@ int wl1271_load_firmware(struct wl1271 *wl)
> ? ? ? ?/* WL1271: The reference driver skips steps 7 to 10 (jumps directly
> ? ? ? ? * to upload_fw) */
>
> - ? ? ? if (wl->chip.id == CHIP_ID_1283_PG20) {
> - ? ? ? ? ? ? ? /*
> - ? ? ? ? ? ? ? ?* Configure SDIO/wSPI DS according to the following table:
> - ? ? ? ? ? ? ? ?* 00 ? 8mA.
> - ? ? ? ? ? ? ? ?* 01 ? 4mA (default).
> - ? ? ? ? ? ? ? ?* 10 ? 6mA.
> - ? ? ? ? ? ? ? ?* 11 ? 2mA.
> - ? ? ? ? ? ? ? ?* Write bits [1:0] of Register 0xd14
> - ? ? ? ? ? ? ? ?* data is in pWlanParams->PlatformConfiguration bits [2:1]
Those two lines above is redundant. however I believe the comment
should be stay.

> - ? ? ? ? ? ? ? ?*/
> + ? ? ? if (wl->chip.id == CHIP_ID_1283_PG20)
> ? ? ? ? ? ? ? ?wl1271_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA);
> - ? ? ? }
>
> ? ? ? ?ret = wl1271_boot_upload_firmware(wl);
> ? ? ? ?if (ret < 0)
> diff --git a/drivers/net/wireless/wl12xx/boot.h b/drivers/net/wireless/wl12xx/boot.h
> index daaf0e7..429c926 100644
> --- a/drivers/net/wireless/wl12xx/boot.h
> +++ b/drivers/net/wireless/wl12xx/boot.h
> @@ -125,7 +125,12 @@ struct wl1271_static_data {
> ?#define MCS_PLL_N_REG_VAL ? ? ? ? ? ?0x07
>
> ?#define SDIO_IO_DS ? ? ? ? ? ? ? ? ? 0xd14
> +
> +/* SDIO/wSPI DS configuration values */
> +#define HCI_IO_DS_8MA ? ? ? ? ? ? ? ?0
> +#define HCI_IO_DS_4MA ? ? ? ? ? ? ? ?1 /* default */
> ?#define HCI_IO_DS_6MA ? ? ? ? ? ? ? ?2
> +#define HCI_IO_DS_2MA ? ? ? ? ? ? ? ?4
This value should be 3.

>
> ?#define HW_CONFIG_19_2_M ? ? ? ? ? ? 1
> ?#define HW_CONFIG_26_M ? ? ? ? ? ? ? 2
> --
> 1.7.1
Thanks for you fixes, comments above.

--
All the best,
Shahar

2011-03-08 07:57:28

by Luciano Coelho

[permalink] [raw]
Subject: [PATCH v2] wl12xx: fixes for 1281/1283 support - Add acx commands

This patch fixes up some issues with patch 03/15 in the wl128x support
series:

* Fix endianess issues;
* Simplify sdio-specific block_size handling;
* Minor changes in comments

This has been compile-tested only. I will test this changes after I
go through the whole series and, if everything is still ok, I'll merge
this patch into 03/15.

Cc: Shahar Levi <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/acx.c | 4 +-
drivers/net/wireless/wl12xx/acx.h | 8 +++---
drivers/net/wireless/wl12xx/init.c | 42 ++++++++++++++++++++-------------
drivers/net/wireless/wl12xx/init.h | 1 +
drivers/net/wireless/wl12xx/io.c | 9 +++++-
drivers/net/wireless/wl12xx/io.h | 2 +-
drivers/net/wireless/wl12xx/main.c | 19 +++++----------
drivers/net/wireless/wl12xx/sdio.c | 3 ++
drivers/net/wireless/wl12xx/spi.c | 10 +-------
drivers/net/wireless/wl12xx/tx.c | 41 +++++++++++++-------------------
drivers/net/wireless/wl12xx/tx.h | 24 +++++++++---------
drivers/net/wireless/wl12xx/wl12xx.h | 4 +--
12 files changed, 80 insertions(+), 87 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index aa0fc12..50676b3 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -1019,7 +1019,7 @@ out:
return ret;
}

-int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl)
+int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap)
{
struct wl1271_acx_host_config_bitmap *bitmap_conf;
int ret;
@@ -1030,7 +1030,7 @@ int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl)
goto out;
}

- bitmap_conf->host_cfg_bitmap = wl->host_cfg_bitmap;
+ 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));
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h
index 2d0bbfe..0a40cae 100644
--- a/drivers/net/wireless/wl12xx/acx.h
+++ b/drivers/net/wireless/wl12xx/acx.h
@@ -939,9 +939,9 @@ struct wl1271_acx_keep_alive_config {
u8 padding;
} __packed;

-#define HOST_IF_CFG_BITMAP_RX_FIFO_ENABLE BIT(0)
-#define HOST_IF_CFG_BITMAP_TX_EXTRA_BLKS_SWAP BIT(1)
-#define HOST_IF_CFG_BITMAP_TX_PAD_TO_SDIO_BLK BIT(3)
+#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;
@@ -1285,7 +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);
+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);
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
index 2f31d14..34c4108 100644
--- a/drivers/net/wireless/wl12xx/init.c
+++ b/drivers/net/wireless/wl12xx/init.c
@@ -505,6 +505,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 (wl1271_set_block_size(wl))
+ /* 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;
@@ -520,23 +541,10 @@ int wl1271_hw_init(struct wl1271 *wl)
if (ret < 0)
return ret;

- if (wl->chip.id == CHIP_ID_1283_PG20) {
- wl1271_set_block_size(wl);
-
- wl->host_cfg_bitmap = HOST_IF_CFG_BITMAP_RX_FIFO_ENABLE;
-
- if (wl->block_size)
- wl->host_cfg_bitmap |=
- HOST_IF_CFG_BITMAP_TX_PAD_TO_SDIO_BLK;
-
- /*
- * Host interface configuration must be before
- * wl1271_acx_init_mem_config !
- */
- ret = wl1271_acx_host_if_cfg_bitmap(wl);
- if (ret < 0)
- return ret;
- }
+ /* Chip-specific init */
+ ret = wl1271_chip_specific_init(wl);
+ if (ret < 0)
+ return ret;

/* Mode specific init */
if (is_ap)
diff --git a/drivers/net/wireless/wl12xx/init.h b/drivers/net/wireless/wl12xx/init.h
index 3a8bd3f..4975270 100644
--- a/drivers/net/wireless/wl12xx/init.h
+++ b/drivers/net/wireless/wl12xx/init.h
@@ -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
diff --git a/drivers/net/wireless/wl12xx/io.c b/drivers/net/wireless/wl12xx/io.c
index ca7229f..aa40c98 100644
--- a/drivers/net/wireless/wl12xx/io.c
+++ b/drivers/net/wireless/wl12xx/io.c
@@ -43,9 +43,14 @@
#define OCP_STATUS_REQ_FAILED 0x20000
#define OCP_STATUS_RESP_ERROR 0x30000

-void wl1271_set_block_size(struct wl1271 *wl)
+bool wl1271_set_block_size(struct wl1271 *wl)
{
- wl->if_ops->set_block_size(wl);
+ if (wl->if_ops->set_block_size) {
+ wl->if_ops->set_block_size(wl);
+ return true;
+ }
+
+ return false;
}

void wl1271_disable_interrupts(struct wl1271 *wl)
diff --git a/drivers/net/wireless/wl12xx/io.h b/drivers/net/wireless/wl12xx/io.h
index 9ae2f4a..84454f6 100644
--- a/drivers/net/wireless/wl12xx/io.h
+++ b/drivers/net/wireless/wl12xx/io.h
@@ -169,6 +169,6 @@ 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);
-void wl1271_set_block_size(struct wl1271 *wl);
+bool wl1271_set_block_size(struct wl1271 *wl);

#endif
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index ac0513a..f24906f 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -450,19 +450,10 @@ static int wl1271_plt_init(struct wl1271 *wl)
if (ret < 0)
return ret;

- if (wl->chip.id == CHIP_ID_1283_PG20) {
- wl1271_set_block_size(wl);
-
- wl->host_cfg_bitmap = HOST_IF_CFG_BITMAP_RX_FIFO_ENABLE;
-
- if (wl->block_size)
- wl->host_cfg_bitmap |=
- HOST_IF_CFG_BITMAP_TX_PAD_TO_SDIO_BLK;
-
- ret = wl1271_acx_host_if_cfg_bitmap(wl);
- if (ret < 0)
- return ret;
- }
+ /* Chip-specific initializations */
+ ret = wl1271_chip_specific_init(wl);
+ if (ret < 0)
+ return ret;

ret = wl1271_sta_init_templates_config(wl);
if (ret < 0)
@@ -1349,6 +1340,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl)
memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map));
wl->ap_fw_ps_map = 0;
wl->ap_ps_map = 0;
+ wl->block_size = 0;

for (i = 0; i < NUM_TX_QUEUES; i++)
wl->tx_blocks_freed[i] = 0;
@@ -3472,6 +3464,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
wl->ap_ps_map = 0;
wl->ap_fw_ps_map = 0;
wl->quirks = 0;
+ wl->block_size = 0;

memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map));
for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c
index ed0f37e..55dc6e3 100644
--- a/drivers/net/wireless/wl12xx/sdio.c
+++ b/drivers/net/wireless/wl12xx/sdio.c
@@ -178,6 +178,9 @@ static int wl1271_sdio_power_on(struct wl1271 *wl)
sdio_claim_host(func);
sdio_enable_func(func);

+ /* Set the default block size in case it was modified */
+ sdio_set_block_size(func, 0);
+
out:
return ret;
}
diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c
index d6e566e..2a57583 100644
--- a/drivers/net/wireless/wl12xx/spi.c
+++ b/drivers/net/wireless/wl12xx/spi.c
@@ -68,14 +68,6 @@

#define WSPI_MAX_NUM_OF_CHUNKS (WL1271_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE)

-/* When working with SPI block size not relevent*/
-#define TX_PAD_SDIO_BLK_SIZE 0
-
-void wl1271_spi_set_block_size(struct wl1271 *wl)
-{
- wl->block_size = TX_PAD_SDIO_BLK_SIZE;
-}
-
static inline struct spi_device *wl_to_spi(struct wl1271 *wl)
{
return wl->if_priv;
@@ -364,7 +356,7 @@ static struct wl1271_if_operations spi_ops = {
.dev = wl1271_spi_wl_to_dev,
.enable_irq = wl1271_spi_enable_interrupts,
.disable_irq = wl1271_spi_disable_interrupts,
- .set_block_size = wl1271_spi_set_block_size,
+ .set_block_size = NULL,
};

static int __devinit wl1271_probe(struct spi_device *spi)
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 542b785..30dc45a 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -145,14 +145,11 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,

/* approximate the number of blocks required for this packet
in the firmware */
- if (wl->host_cfg_bitmap & HOST_IF_CFG_BITMAP_TX_PAD_TO_SDIO_BLK) {
- u32 sdio_block_mask = wl->block_size - 1;
- int pad = (total_len + sdio_block_mask) & (~sdio_block_mask);
-
- total_blocks = pad + TX_HW_BLOCK_SIZE - 1;
- } else {
+ if (wl->block_size)
+ total_blocks = ALIGN(total_len, wl->block_size) +
+ TX_HW_BLOCK_SIZE - 1;
+ else
total_blocks = total_len + TX_HW_BLOCK_SIZE - 1;
- }

total_blocks = total_blocks / TX_HW_BLOCK_SIZE + TX_HW_BLOCK_SPARE;
if (total_blocks <= wl->tx_blocks_available) {
@@ -245,13 +242,10 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
tx_attr |= rate_idx << TX_HW_ATTR_OFST_RATE_POLICY;
desc->reserved = 0;

- if (wl->host_cfg_bitmap & HOST_IF_CFG_BITMAP_TX_PAD_TO_SDIO_BLK) {
- u32 sdio_block_mask = wl->block_size - 1;
- int pad = (skb->len + sdio_block_mask) &
- (~sdio_block_mask);
+ if (wl->block_size) {
+ pad = ALIGN(skb->len, wl->block_size);

desc->wl128x_mem.extra_bytes = pad - skb->len;
-
desc->length = cpu_to_le16(pad >> 2);
} else {
/* align the length (and store in terms of words) */
@@ -323,19 +317,18 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,

wl1271_tx_fill_hdr(wl, skb, extra, info, hlid);

- if (wl->host_cfg_bitmap & HOST_IF_CFG_BITMAP_TX_PAD_TO_SDIO_BLK) {
- unsigned sdio_block_mask = wl->block_size - 1;
-
- total_len = (skb->len + sdio_block_mask) & (~sdio_block_mask);
- } else {
- /*
- * The length of each packet is stored in terms of words. Thus,
- * we must pad the skb data to make sure its length is aligned.
- * The number of padding bytes is computed and set in
- * wl1271_tx_fill_hdr
- */
+ /*
+ * The length of each packet is stored in terms of
+ * words. Thus, we must pad the skb data to make sure its
+ * length is aligned. The number of padding bytes is computed
+ * and set in wl1271_tx_fill_hdr.
+ * In special cases, we want to align to a specific block size
+ * (eg. for wl128x with SDIO we align to 256).
+ */
+ if (wl->block_size)
+ total_len = ALIGN(skb->len, wl->block_size);
+ else
total_len = ALIGN(skb->len, WL1271_TX_ALIGN_TO);
- }

memcpy(wl->aggr_buf + buf_offset, skb->data, skb->len);
memset(wl->aggr_buf + buf_offset + skb->len, 0, total_len - skb->len);
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h
index 3072f95..e313177 100644
--- a/drivers/net/wireless/wl12xx/tx.h
+++ b/drivers/net/wireless/wl12xx/tx.h
@@ -57,29 +57,29 @@

struct wl127x_tx_mem {
/*
- * on wl127x: Number of extra memory blocks to allocate
- * for this packet in addition to the number of blocks
- * derived from the packet length
+ * Number of extra memory blocks to allocate for this packet
+ * in addition to the number of blocks derived from the packet
+ * length.
*/
u8 extra_blocks;
/*
- * on wl127x: Total number of memory blocks allocated by
- * the host for this packet. Must be equal or greater
- * than the actual blocks number allocated by HW!!
+ * Total number of memory blocks allocated by the host for
+ * this packet. Must be equal or greater than the actual
+ * blocks number allocated by HW.
*/
u8 total_mem_blocks;
} __packed;

struct wl128x_tx_mem {
/*
- * on wl128x: Total number of memory blocks allocated by
- * the host for this packet.
+ * Total number of memory blocks allocated by the host for
+ * this packet.
*/
u8 total_mem_blocks;
/*
- * on wl128x: Number of extra bytes, at the end of the
- * frame. the host uses this padding to complete each
- * frame to integer number of SDIO blocks.
+ * Number of extra bytes, at the end of the frame. the host
+ * uses this padding to complete each frame to integer number
+ * of SDIO blocks.
*/
u8 extra_bytes;
} __packed;
@@ -95,7 +95,7 @@ struct wl1271_tx_hw_descr {
__le32 start_time;
/*
* Max delay in TUs until transmission. The last device time the
- * packet can be transmitted is: startTime+(1024*LifeTime)
+ * packet can be transmitted is: start_time + (1024 * life_time)
*/
__le16 life_time;
/* Bitwise fields - see TX_ATTR... definitions above. */
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 94b4062..959b338 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -534,9 +534,7 @@ struct wl1271 {
bool ba_support;
u8 ba_rx_bitmap;

- /* wl128x features only */
- __le32 host_cfg_bitmap;
- u32 block_size;
+ u32 block_size;

/*
* AP-mode - links indexed by HLID. The global and broadcast links
--
1.7.1


2011-03-06 14:28:10

by Shahar Levi

[permalink] [raw]
Subject: [PATCH 01/15] wl12xx: 1281/1283 support - move IRQ polarity

In order to prevent overran of IRQ polarity via FW the polarity setting move after
FW download and before IRQ enable.

Signed-off-by: Shahar Levi <[email protected]>
Reviewed-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/boot.c | 14 +++++++-------
1 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
index 6934dff..69fe870 100644
--- a/drivers/net/wireless/wl12xx/boot.c
+++ b/drivers/net/wireless/wl12xx/boot.c
@@ -585,13 +585,6 @@ 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) */

@@ -618,6 +611,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);

--
1.7.0.4


2011-03-09 18:15:52

by Luciano Coelho

[permalink] [raw]
Subject: Re: [PATCH 10/15] wl12xx: 1281/1283 support - Set WiFi & BT cox

On Wed, 2011-03-09 at 19:39 +0200, Levi, Shahar wrote:
> On 3/9/11, Luciano Coelho <[email protected]> wrote:
> > On Sun, 2011-03-06 at 16:32 +0200, Shahar Levi wrote:
> >> Set different Cox setting between wl127x and wl128x.
> >>
> >> Signed-off-by: Shahar Levi <[email protected]>
> >> ---
> >> drivers/net/wireless/wl12xx/acx.c | 5 +++++
> >> drivers/net/wireless/wl12xx/main.c | 6 +++++-
> >> 2 files changed, 10 insertions(+), 1 deletions(-)
> >>
> >> diff --git a/drivers/net/wireless/wl12xx/acx.c
> >> b/drivers/net/wireless/wl12xx/acx.c
> >> index f0345e6..e970b71 100644
> >> --- a/drivers/net/wireless/wl12xx/acx.c
> >> +++ b/drivers/net/wireless/wl12xx/acx.c
> >> @@ -554,6 +554,11 @@ int wl1271_acx_sg_cfg(struct wl1271 *wl)
> >> goto out;
> >> }
> >>
> >> + if (wl->chip.id == CHIP_ID_1283_PG20)
> >> + c->params[CONF_SG_BT_LOAD_RATIO] = 50;
> >> + else
> >> + c->params[CONF_SG_BT_LOAD_RATIO] = 200;
> >> +
> >
> > You can't change this value in the global array. This needs to be
> > changed only in the allocated ACX. I'll change it before taking it in.
> >
> > Also, I think it's cleaner to keep the correct value for wl127x in the
> > global array (as was before) and only change the value for wl128x here
> > in this function.
> >
> >> diff --git a/drivers/net/wireless/wl12xx/main.c
> >> b/drivers/net/wireless/wl12xx/main.c
> >> index 32d963d..f8e9e3f 100644
> >> --- a/drivers/net/wireless/wl12xx/main.c
> >> +++ b/drivers/net/wireless/wl12xx/main.c
> >> @@ -54,7 +54,11 @@ static struct conf_drv_settings default_conf = {
> >> [CONF_SG_BT_PER_THRESHOLD] = 7500,
> >> [CONF_SG_HV3_MAX_OVERRIDE] = 0,
> >> [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400,
> >> - [CONF_SG_BT_LOAD_RATIO] = 50,
> >> + /*
> >> + * CONF_SG_BT_LOAD_RATIO has wl127x or wl128x dependency
> >> + * (set in wl1271_acx_sg_cfg()
> >> + */
> >> + [CONF_SG_BT_LOAD_RATIO] = 0,
> >> [CONF_SG_AUTO_PS_MODE] = 1,
> >> [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170,
> >> [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50,
> >
> > Previously, the value used for wl127x was 50, from the default global
> > settings. Now you're using 200 for wl127x. This looks suspicious. You
> > now use 50 (which was the value for wl127x) for wl128x and 200 for
> > wl127x.
> >
> > At least the change for wl127x should be done in a separate patch.
> It was incorrect value for wl127x. That patch fixes that and set
> wl128x value. I can do the fix for wl127x in separate patch.

Okay, so this means that for wl128x we don't need the current patch at
all. The value is already 50, which is good for wl128x. A new patch
for wl127x should be sent separately.

--
Cheers,
Luca.


2011-03-06 14:28:23

by Shahar Levi

[permalink] [raw]
Subject: [PATCH 11/15] wl12xx: 1281/1283 support - Add chip interrupt pacing

Set data path interrupt pacing for wl128x

Signed-off-by: Shahar Levi <[email protected]>
---
drivers/net/wireless/wl12xx/acx.c | 8 +++++++-
drivers/net/wireless/wl12xx/conf.h | 10 +++++++++-
drivers/net/wireless/wl12xx/main.c | 3 ++-
3 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index e970b71..4341f6e 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -943,8 +943,14 @@ int wl1271_acx_tx_config_options(struct wl1271 *wl)
goto out;
}

+ if (wl->chip.id == CHIP_ID_1283_PG20)
+ acx->tx_compl_threshold =
+ cpu_to_le16(wl->conf.tx.wl128x_tx_compl_threshold);
+ else
+ acx->tx_compl_threshold =
+ cpu_to_le16(wl->conf.tx.wl127x_tx_compl_threshold);
+
acx->tx_compl_timeout = cpu_to_le16(wl->conf.tx.tx_compl_timeout);
- acx->tx_compl_threshold = cpu_to_le16(wl->conf.tx.tx_compl_threshold);
ret = wl1271_cmd_configure(wl, ACX_TX_CONFIG_OPT, acx, sizeof(*acx));
if (ret < 0) {
wl1271_warning("Setting of tx options failed: %d", ret);
diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h
index 743bd0b..ef8b220 100644
--- a/drivers/net/wireless/wl12xx/conf.h
+++ b/drivers/net/wireless/wl12xx/conf.h
@@ -714,7 +714,15 @@ struct conf_tx_settings {
*
* Range: u16
*/
- u16 tx_compl_threshold;
+ u16 wl127x_tx_compl_threshold;
+
+ /*
+ * Completed TX packet count which requires to issue the TX-Complete
+ * interrupt.
+ *
+ * Range: u16
+ */
+ u16 wl128x_tx_compl_threshold;

/*
* The rate used for control messages and scanning on the 2.4GHz band
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index f8e9e3f..6fda932 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -233,7 +233,8 @@ static struct conf_drv_settings default_conf = {
},
.frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD,
.tx_compl_timeout = 700,
- .tx_compl_threshold = 4,
+ .wl127x_tx_compl_threshold = 4,
+ .wl128x_tx_compl_threshold = 3,
.basic_rate = CONF_HW_BIT_RATE_1MBPS,
.basic_rate_5 = CONF_HW_BIT_RATE_6MBPS,
.tmpl_short_retry_limit = 10,
--
1.7.0.4


2011-03-09 08:12:11

by Luciano Coelho

[permalink] [raw]
Subject: Re: [PATCH 06/15] wl12xx: 1281/1283 support - New boot sequence

On Tue, 2011-03-08 at 20:08 +0200, Levi, Shahar wrote:
> On Tue, Mar 8, 2011 at 3:11 PM, Luciano Coelho <[email protected]> wrote:
> > On Sun, 2011-03-06 at 16:32 +0200, Shahar Levi wrote:
> >> - clk |= (wl->ref_clock << 1) << 4;
> >> + if (wl->chip.id == CHIP_ID_1283_PG20) {
> >> + if (is_ref_clk == false)
> >> + clk |= ((wl->tcxo_clock & 0x3) << 1) << 4;
> >> + else
> >> + clk |= ((wl->ref_clock & 0x3) << 1) << 4;
> >> + } else
> >> + clk |= ((wl->ref_clock & 0x3) << 1) << 4;
> >> +
> >> wl1271_write32(wl, DRPW_SCRATCH_START, clk);
> >
> > Can you explain why you changed the wl127x part as well? For wl127x
> > you're essentially changing:
> >
> > clk |= (wl->ref_clock << 1) << 4;
> >
> > to:
> >
> > clk |= ((wl->ref_clock & 0x3) << 1) << 4;
> >
> > This means that CONF_REF_CLK_38_4_M_XTAL will be treated in the same way
> > as CONF_REF_CLK_19_2_E. Is that right? If it is, it must be addressed
> > in a separate patch and not as part of the Quattro series.
> This implantation is due to the fact only those two bits is valid for
> clk setting (from MCP).
> CONF_REF_CLK_38_4_M_XTAL should be set as 19M.
> I will address is as separate patch.

Thanks! I think there should be a comment with an explanation that
CLK_38_4_M_XTAL should be set as CLK_19_2_E and why.


--
Cheers,
Luca.


2011-03-06 14:28:11

by Shahar Levi

[permalink] [raw]
Subject: [PATCH 02/15] wl12xx: 1281/1283 support - Add Definitions

Definitions to support wl128x:
- New FW file name
- Chip ID
- New PLL Configuration Algorithm macros that will be used at wl128x
boot stage
- Rename NVS macro name: wl127x and wl128x are using the same NVS
file name. However, the ini parameters between of them are
different. The driver will validate the correct NVS size in
wl1271_boot_upload_nvs().

Signed-off-by: Shahar Levi <[email protected]>
---
drivers/net/wireless/wl12xx/boot.h | 59 +++++++++++++++++++++++++++++++
drivers/net/wireless/wl12xx/conf.h | 4 ++-
drivers/net/wireless/wl12xx/main.c | 2 +-
drivers/net/wireless/wl12xx/reg.h | 15 +-------
drivers/net/wireless/wl12xx/sdio.c | 1 +
drivers/net/wireless/wl12xx/sdio_test.c | 2 +-
drivers/net/wireless/wl12xx/spi.c | 1 +
drivers/net/wireless/wl12xx/wl12xx.h | 8 ++++-
8 files changed, 75 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/boot.h b/drivers/net/wireless/wl12xx/boot.h
index 17229b8..daaf0e7 100644
--- a/drivers/net/wireless/wl12xx/boot.h
+++ b/drivers/net/wireless/wl12xx/boot.h
@@ -74,4 +74,63 @@ struct wl1271_static_data {
#define FREF_CLK_POLARITY_BITS 0xfffff8ff
#define CLK_REQ_OUTN_SEL 0x700

+/* PLL configuration algorithm for wl128x */
+#define CLOCK_TCXO_19_2_M 0
+#define CLOCK_TCXO_26_M 1
+#define CLOCK_TCXO_38_4_M 2
+#define CLOCK_TCXO_52_M 3
+#define CLOCK_TCXO_16_368_M 4
+#define CLOCK_TCXO_32_736_M 5
+#define CLOCK_TCXO_16_8_M 6
+#define CLOCK_TCXO_33_6_M 7
+
+
+#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_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
+#define HCI_IO_DS_6MA 2
+
+#define HW_CONFIG_19_2_M 1
+#define HW_CONFIG_26_M 2
+#define HW_CONFIG_38_4_M 3
+#define HW_CONFIG_52_M 4
+/* end PLL configuration algorithm for wl128x */
+
#endif
diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h
index 856a8a2..a00f22c 100644
--- a/drivers/net/wireless/wl12xx/conf.h
+++ b/drivers/net/wireless/wl12xx/conf.h
@@ -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 {
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 8b3c8d1..b0c4935 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -838,7 +838,7 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
const struct firmware *fw;
int ret;

- ret = request_firmware(&fw, WL1271_NVS_NAME, wl1271_wl_to_dev(wl));
+ ret = request_firmware(&fw, WL12XX_NVS_NAME, wl1271_wl_to_dev(wl));

if (ret < 0) {
wl1271_error("could not get nvs file: %d", ret);
diff --git a/drivers/net/wireless/wl12xx/reg.h b/drivers/net/wireless/wl12xx/reg.h
index 9909607..440a4ee 100644
--- a/drivers/net/wireless/wl12xx/reg.h
+++ b/drivers/net/wireless/wl12xx/reg.h
@@ -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
diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c
index 5b9dbea..58d0208 100644
--- a/drivers/net/wireless/wl12xx/sdio.c
+++ b/drivers/net/wireless/wl12xx/sdio.c
@@ -343,4 +343,5 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Luciano Coelho <[email protected]>");
MODULE_AUTHOR("Juuso Oikarinen <[email protected]>");
MODULE_FIRMWARE(WL1271_FW_NAME);
+MODULE_FIRMWARE(WL128X_FW_NAME);
MODULE_FIRMWARE(WL1271_AP_FW_NAME);
diff --git a/drivers/net/wireless/wl12xx/sdio_test.c b/drivers/net/wireless/wl12xx/sdio_test.c
index 9fcbd3d..01adf1b 100644
--- a/drivers/net/wireless/wl12xx/sdio_test.c
+++ b/drivers/net/wireless/wl12xx/sdio_test.c
@@ -227,7 +227,7 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
const struct firmware *fw;
int ret;

- ret = request_firmware(&fw, WL1271_NVS_NAME, wl1271_wl_to_dev(wl));
+ ret = request_firmware(&fw, WL12XX_NVS_NAME, wl1271_wl_to_dev(wl));

if (ret < 0) {
wl1271_error("could not get nvs file: %d", ret);
diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c
index 18cf017..2993715 100644
--- a/drivers/net/wireless/wl12xx/spi.c
+++ b/drivers/net/wireless/wl12xx/spi.c
@@ -490,5 +490,6 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Luciano Coelho <[email protected]>");
MODULE_AUTHOR("Juuso Oikarinen <[email protected]>");
MODULE_FIRMWARE(WL1271_FW_NAME);
+MODULE_FIRMWARE(WL128X_FW_NAME);
MODULE_FIRMWARE(WL1271_AP_FW_NAME);
MODULE_ALIAS("spi:wl1271");
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 86be83e..7adb856 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -131,9 +131,15 @@ extern u32 wl12xx_debug_level;


#define WL1271_FW_NAME "ti-connectivity/wl1271-fw-2.bin"
+#define WL128X_FW_NAME "ti-connectivity/wl128x-fw.bin"
#define WL1271_AP_FW_NAME "ti-connectivity/wl1271-fw-ap.bin"

-#define WL1271_NVS_NAME "ti-connectivity/wl1271-nvs.bin"
+/*
+ * wl127x and wl128x are using the same NVS file name. However, the ini
+ * parameters between of them are different.
+ * The driver validate the correct NVS size in wl1271_boot_upload_nvs().
+ */
+#define WL12XX_NVS_NAME "ti-connectivity/wl1271-nvs.bin"

#define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff))
#define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff))
--
1.7.0.4


2011-03-06 14:28:26

by Shahar Levi

[permalink] [raw]
Subject: [PATCH 13/15] wl12xx: 1281/1283 support - Use different FW file for AP mode wl127x/wl128x chips

From: Arik Nemtsov <[email protected]>

Choose a different FW for AP-mode wl127x and wl128x chips, base on chip
ID at boot time.

Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/wl12xx/main.c | 5 ++++-
drivers/net/wireless/wl12xx/sdio.c | 3 ++-
drivers/net/wireless/wl12xx/spi.c | 3 ++-
drivers/net/wireless/wl12xx/wl12xx.h | 3 ++-
4 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 6fda932..8ac3936 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -848,7 +848,10 @@ static int wl1271_fetch_firmware(struct wl1271 *wl)

switch (wl->bss_type) {
case BSS_TYPE_AP_BSS:
- fw_name = WL1271_AP_FW_NAME;
+ if (wl->chip.id == CHIP_ID_1283_PG20)
+ fw_name = WL128X_AP_FW_NAME;
+ else
+ fw_name = WL127X_AP_FW_NAME;
break;
case BSS_TYPE_IBSS:
case BSS_TYPE_STA_BSS:
diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c
index 521a187..5f4dd73 100644
--- a/drivers/net/wireless/wl12xx/sdio.c
+++ b/drivers/net/wireless/wl12xx/sdio.c
@@ -358,4 +358,5 @@ MODULE_AUTHOR("Luciano Coelho <[email protected]>");
MODULE_AUTHOR("Juuso Oikarinen <[email protected]>");
MODULE_FIRMWARE(WL1271_FW_NAME);
MODULE_FIRMWARE(WL128X_FW_NAME);
-MODULE_FIRMWARE(WL1271_AP_FW_NAME);
+MODULE_FIRMWARE(WL127X_AP_FW_NAME);
+MODULE_FIRMWARE(WL128X_AP_FW_NAME);
diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c
index abbb8dc..e4e9ea5 100644
--- a/drivers/net/wireless/wl12xx/spi.c
+++ b/drivers/net/wireless/wl12xx/spi.c
@@ -501,5 +501,6 @@ MODULE_AUTHOR("Luciano Coelho <[email protected]>");
MODULE_AUTHOR("Juuso Oikarinen <[email protected]>");
MODULE_FIRMWARE(WL1271_FW_NAME);
MODULE_FIRMWARE(WL128X_FW_NAME);
-MODULE_FIRMWARE(WL1271_AP_FW_NAME);
+MODULE_FIRMWARE(WL127X_AP_FW_NAME);
+MODULE_FIRMWARE(WL128X_AP_FW_NAME);
MODULE_ALIAS("spi:wl1271");
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 1114b7c..6fa760e 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -132,7 +132,8 @@ extern u32 wl12xx_debug_level;

#define WL1271_FW_NAME "ti-connectivity/wl1271-fw-2.bin"
#define WL128X_FW_NAME "ti-connectivity/wl128x-fw.bin"
-#define WL1271_AP_FW_NAME "ti-connectivity/wl1271-fw-ap.bin"
+#define WL127X_AP_FW_NAME "ti-connectivity/wl1271-fw-ap.bin"
+#define WL128X_AP_FW_NAME "ti-connectivity/wl128x-fw-ap.bin"

/*
* wl127x and wl128x are using the same NVS file name. However, the ini
--
1.7.0.4


2011-03-09 08:41:59

by Luciano Coelho

[permalink] [raw]
Subject: Re: [PATCH 08/15] wl12xx: 1281/1283 support - Improve Tx & Rx path

On Sun, 2011-03-06 at 16:32 +0200, Shahar Levi wrote:
> Reduced bus transactions in Tx & Rx path
>
> Signed-off-by: Shahar Levi <[email protected]>
> ---




> diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c
> index 919b59f..c95ae19 100644
> --- a/drivers/net/wireless/wl12xx/rx.c
> +++ b/drivers/net/wireless/wl12xx/rx.c

[...]

> @@ -204,7 +211,8 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
> * 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)
> + if ((wl->chip.id != CHIP_ID_1283_PG20) &&
> + (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION))
> wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
> }

The WL12XX_QUIRK_END_OF_TRANSACTION is only enabled for wl127x, so no
need to check that it's not wl128x here.

> @@ -537,7 +550,8 @@ out_ack:
> * Interrupt the firmware with the new packets. This is only
> * required for older hardware revisions
> */
> - if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION)
> + if ((wl->chip.id != CHIP_ID_1283_PG20) &&
> + (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION))
> wl1271_write32(wl, WL1271_HOST_WR_ACCESS,
> wl->tx_packets_count);
>

Same thing here.

I'll remove these unnecessary checks.


--
Cheers,
Luca.