2011-04-04 07:05:55

by Shahar Levi

[permalink] [raw]
Subject: [PATCH] wl12xx: FM WLAN coexistence

Add support to FM WLAN coexistence (STA only).
Few WiFi harmonics may interfere FM operation, to
avoid this problem special coexistence techniques are
activated around some FM frequencies.

Signed-off-by: Shahar Levi <[email protected]>
---
drivers/net/wireless/wl12xx/acx.c | 42 ++++++++++++++++++++++++
drivers/net/wireless/wl12xx/acx.h | 61 ++++++++++++++++++++++++++++++++++++
drivers/net/wireless/wl12xx/conf.h | 14 ++++++++
drivers/net/wireless/wl12xx/init.c | 5 +++
drivers/net/wireless/wl12xx/main.c | 17 ++++++++++
5 files changed, 139 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index e005aa4..5f5afbe 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -1604,3 +1604,45 @@ out:
kfree(acx);
return ret;
}
+
+int wl1271_acx_fm_coex(struct wl1271 *wl)
+{
+ struct wl1271_acx_fm_coex *acx;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "acx fm coex setting");
+
+ acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+ if (!acx) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ acx->enable = wl->conf.fm_coex.enable;
+ acx->swallow_period = wl->conf.fm_coex.swallow_period;
+ acx->n_divider_fref_set_1 = wl->conf.fm_coex.n_divider_fref_set_1;
+ acx->n_divider_fref_set_2 = wl->conf.fm_coex.n_divider_fref_set_2;
+ acx->m_divider_fref_set_1 =
+ cpu_to_le16(wl->conf.fm_coex.m_divider_fref_set_1);
+ acx->m_divider_fref_set_2 =
+ cpu_to_le16(wl->conf.fm_coex.m_divider_fref_set_2);
+ acx->coex_pll_stabilization_time =
+ cpu_to_le32(wl->conf.fm_coex.coex_pll_stabilization_time);
+ acx->ldo_stabilization_timwl12xx-fm-coex-v2/e =
+ cpu_to_le16(wl->conf.fm_coex.ldo_stabilization_time);
+ acx->fm_disturbed_band_margin =
+ wl->conf.fm_coex.fm_disturbed_band_margin;
+ acx->swallow_clk_diff = wl->conf.fm_coex.swallow_clk_diff;
+
+ ret = wl1271_cmd_configure(wl, ACX_FM_COEX_CFG, acx, sizeof(*acx));
+ if (ret < 0) {
+ wl1271_warning("acx fm coex setting failed: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(acx);
+ return ret;
+}
+
+
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h
index 0a40cae..45242db 100644
--- a/drivers/net/wireless/wl12xx/acx.h
+++ b/drivers/net/wireless/wl12xx/acx.h
@@ -1172,6 +1172,65 @@ struct wl1271_acx_inconnection_sta {
u8 padding1[2];
} __packed;

+/*
+ * ACX_FM_COEX_CFG
+ * set the FM co-existence parameters.
+ */
+struct wl1271_acx_fm_coex {
+ struct acx_header header;
+ /* enable(1) / disable(0) the FM Coex feature */
+ u8 enable;
+ /*
+ * Swallow period used in COEX PLL swallowing mechanism.
+ * 0xFF = use FW default
+ */
+ u8 swallow_period;
+ /*
+ * The N divider used in COEX PLL swallowing mechanism for Fref of
+ * 38.4/19.2 Mhz. 0xFF = use FW default
+ */
+ u8 n_divider_fref_set_1;
+ /*
+ * The N divider used in COEX PLL swallowing mechanism for Fref of
+ * 26/52 Mhz. 0xFF = use FW default
+ */
+ u8 n_divider_fref_set_2;
+ /*
+ * The M divider used in COEX PLL swallowing mechanism for Fref of
+ * 38.4/19.2 Mhz. 0xFFFF = use FW default
+ */
+ u16 m_divider_fref_set_1;
+ /*
+ * The M divider used in COEX PLL swallowing mechanism for Fref of
+ * 26/52 Mhz. 0xFFFF = use FW default
+ */
+ u16 m_divider_fref_set_2;
+ /*
+ * The time duration in uSec required for COEX PLL to stabilize.
+ * 0xFFFFFFFF = use FW default
+ */
+ u32 coex_pll_stabilization_time;
+ /*
+ * The time duration in uSec required for LDO to stabilize.
+ * 0xFFFFFFFF = use FW default
+ */
+ u16 ldo_stabilization_time;
+ /*
+ * The disturbed frequency band margin around the disturbed frequency
+ * center (single sided).
+ * For example, if 2 is configured, the following channels will be
+ * considered disturbed channel:
+ * 80 +- 0.1 MHz, 91 +- 0.1 MHz, 98 +- 0.1 MHz, 102 +- 0.1 MH
+ * 0xFF = use FW default
+ */
+ u8 fm_disturbed_band_margin;
+ /*
+ * The swallow clock difference of the swallowing mechanism.
+ * 0xFF = use FW default
+ */
+ u8 swallow_clk_diff;
+} __packed;
+
enum {
ACX_WAKE_UP_CONDITIONS = 0x0002,
ACX_MEM_CFG = 0x0003,
@@ -1201,6 +1260,7 @@ enum {
ACX_BCN_DTIM_OPTIONS = 0x0031,
ACX_SG_ENABLE = 0x0032,
ACX_SG_CFG = 0x0033,
+ ACX_FM_COEX_CFG = 0x0034,
ACX_BEACON_FILTER_TABLE = 0x0038,
ACX_ARP_IP_FILTER = 0x0039,
ACX_ROAMING_STATISTICS_TBL = 0x003B,
@@ -1310,5 +1370,6 @@ int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime);
int wl1271_acx_max_tx_retry(struct wl1271 *wl);
int wl1271_acx_config_ps(struct wl1271 *wl);
int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr);
+int wl1271_acx_fm_coex(struct wl1271 *wl);

#endif /* __WL1271_ACX_H__ */
diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h
index 743bd0b..44cbce6 100644
--- a/drivers/net/wireless/wl12xx/conf.h
+++ b/drivers/net/wireless/wl12xx/conf.h
@@ -1193,6 +1193,19 @@ struct conf_memory_settings {
u8 tx_min;
};

+struct conf_fm_coex {
+ u8 enable;
+ u8 swallow_period;
+ u8 n_divider_fref_set_1;
+ u8 n_divider_fref_set_2;
+ u16 m_divider_fref_set_1;
+ u16 m_divider_fref_set_2;
+ u32 coex_pll_stabilization_time;
+ u16 ldo_stabilization_time;
+ u8 fm_disturbed_band_margin;
+ u8 swallow_clk_diff;
+};
+
struct conf_drv_settings {
struct conf_sg_settings sg;
struct conf_rx_settings rx;
@@ -1206,6 +1219,7 @@ struct conf_drv_settings {
struct conf_ht_setting ht;
struct conf_memory_settings mem_wl127x;
struct conf_memory_settings mem_wl128x;
+ struct conf_fm_coex fm_coex;
};

#endif
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
index 2dbc083..7169d82 100644
--- a/drivers/net/wireless/wl12xx/init.c
+++ b/drivers/net/wireless/wl12xx/init.c
@@ -356,6 +356,11 @@ static int wl1271_sta_hw_init(struct wl1271 *wl)
if (ret < 0)
return ret;

+ /* FM WLAN coexistence */
+ ret = wl1271_acx_fm_coex(wl);
+ if (ret < 0)
+ return ret;
+
/* Beacons and broadcast settings */
ret = wl1271_init_beacon_broadcast(wl);
if (ret < 0)
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 85cb4da..f4c0063 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -318,6 +318,18 @@ static struct conf_drv_settings default_conf = {
.min_req_rx_blocks = 22,
.tx_min = 27,
},
+ .fm_coex = {
+ .enable = true,
+ .swallow_period = 5,
+ .n_divider_fref_set_1 = 0xff, /* default */
+ .n_divider_fref_set_2 = 12,
+ .m_divider_fref_set_1 = 148,
+ .m_divider_fref_set_2 = 0xffff, /* default */
+ .coex_pll_stabilization_time = 0xffffffff, /* default */
+ .ldo_stabilization_time = 0xffff, /* default */
+ .fm_disturbed_band_margin = 0xff, /* default */
+ .swallow_clk_diff = 0xff, /* default */
+ },
};

static void __wl1271_op_remove_interface(struct wl1271 *wl);
@@ -505,6 +517,11 @@ static int wl1271_plt_init(struct wl1271 *wl)
if (ret < 0)
goto out_free_memmap;

+ /* FM WLAN coexistence */
+ ret = wl1271_acx_fm_coex(wl);
+ if (ret < 0)
+ goto out_free_memmap;
+
/* Energy detection */
ret = wl1271_init_energy_detection(wl);
if (ret < 0)
--
1.7.0.4



2011-04-11 11:12:25

by Shahar Levi

[permalink] [raw]
Subject: Re: [PATCH] wl12xx: FM WLAN coexistence

On Wed, Apr 6, 2011 at 9:13 PM, Luciano Coelho <[email protected]> wrote:
> On Mon, 2011-04-04 at 10:07 +0300, Shahar Levi wrote:
>> Add support to FM WLAN coexistence (STA only).
>> Few WiFi harmonics may interfere FM operation, to
>> avoid this problem special coexistence techniques are
>> activated around some FM frequencies.
>>
>> Signed-off-by: Shahar Levi <[email protected]>
>> ---
>
> Some comments.
>
>
>> diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
>> index e005aa4..5f5afbe 100644
>> --- a/drivers/net/wireless/wl12xx/acx.c
>> +++ b/drivers/net/wireless/wl12xx/acx.c
>> @@ -1604,3 +1604,45 @@ out:
>> ? ? ? kfree(acx);
>> ? ? ? return ret;
>> ?}
>> +
>> +int wl1271_acx_fm_coex(struct wl1271 *wl)
>> +{
>> + ? ? struct wl1271_acx_fm_coex *acx;
>> + ? ? int ret;
>> +
>> + ? ? wl1271_debug(DEBUG_ACX, "acx fm coex setting");
>> +
>> + ? ? acx = kzalloc(sizeof(*acx), GFP_KERNEL);
>> + ? ? if (!acx) {
>> + ? ? ? ? ? ? ret = -ENOMEM;
>> + ? ? ? ? ? ? goto out;
>> + ? ? }
>> +
>> + ? ? acx->enable = wl->conf.fm_coex.enable;
>> + ? ? acx->swallow_period = wl->conf.fm_coex.swallow_period;
>> + ? ? acx->n_divider_fref_set_1 = wl->conf.fm_coex.n_divider_fref_set_1;
>> + ? ? acx->n_divider_fref_set_2 = wl->conf.fm_coex.n_divider_fref_set_2;
>> + ? ? acx->m_divider_fref_set_1 =
>> + ? ? ? ? ? ? cpu_to_le16(wl->conf.fm_coex.m_divider_fref_set_1);
>> + ? ? acx->m_divider_fref_set_2 =
>> + ? ? ? ? ? ? cpu_to_le16(wl->conf.fm_coex.m_divider_fref_set_2);
>> + ? ? acx->coex_pll_stabilization_time =
>> + ? ? ? ? ? ? cpu_to_le32(wl->conf.fm_coex.coex_pll_stabilization_time);
>
>> + ? ? acx->ldo_stabilization_timwl12xx-fm-coex-v2/e =
>> + ? ? ? ? ? ? cpu_to_le16(wl->conf.fm_coex.ldo_stabilization_time);
>
> What's this? There is some garbage pasted into this statement here!
How that get in? This is a typo of copy&paste of "wl12xx-fm-coex-v2/"
Will be fix.

>
>
>> diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h
>> index 0a40cae..45242db 100644
>> --- a/drivers/net/wireless/wl12xx/acx.h
>> +++ b/drivers/net/wireless/wl12xx/acx.h
>> @@ -1172,6 +1172,65 @@ struct wl1271_acx_inconnection_sta {
>> ? ? ? u8 padding1[2];
>> ?} __packed;
>>
>> +/*
>> + * ACX_FM_COEX_CFG
>> + * set the FM co-existence parameters.
>> + */
>> +struct wl1271_acx_fm_coex {
>> + ? ? struct acx_header header;
>> + ? ? /* enable(1) / disable(0) the FM Coex feature */
>> + ? ? u8 enable;
>> + ? ? /*
>> + ? ? ?* Swallow period used in COEX PLL swallowing mechanism.
>> + ? ? ?* 0xFF = use FW default
>> + ? ? ?*/
>> + ? ? u8 swallow_period;
>> + ? ? /*
>> + ? ? ?* The N divider used in COEX PLL swallowing mechanism for Fref of
>> + ? ? ?* 38.4/19.2 Mhz. 0xFF = use FW default
>> + ? ? ?*/
>> + ? ? u8 n_divider_fref_set_1;
>> + ? ? /*
>> + ? ? ?* The N divider used in COEX PLL swallowing mechanism for Fref of
>> + ? ? ?* 26/52 Mhz. 0xFF = use FW default
>> + ? ? ?*/
>> + ? ? u8 n_divider_fref_set_2;
>> + ? ? /*
>> + ? ? ?* The M divider used in COEX PLL swallowing mechanism for Fref of
>> + ? ? ?* 38.4/19.2 Mhz. 0xFFFF = use FW default
>> + ? ? ?*/
>> + ? ? u16 m_divider_fref_set_1;
>
> This must be __le16.
Will be fix

>
>
>> + ? ? /*
>> + ? ? ?* The M divider used in COEX PLL swallowing mechanism for Fref of
>> + ? ? ?* 26/52 Mhz. 0xFFFF = use FW default
>> + ? ? ?*/
>> + ? ? u16 m_divider_fref_set_2;
>
> Same here.
Will be fix

>
>
>> + ? ? /*
>> + ? ? ?* The time duration in uSec required for COEX PLL to stabilize.
>> + ? ? ?* 0xFFFFFFFF = use FW default
>> + ? ? ?*/
>> + ? ? u32 coex_pll_stabilization_time;
>
> __le32
Will be fix

>
>
>> + ? ? /*
>> + ? ? ?* The time duration in uSec required for LDO to stabilize.
>> + ? ? ?* 0xFFFFFFFF = use FW default
>> + ? ? ?*/
>> + ? ? u16 ldo_stabilization_time;
>
> __le16
Will be fix

>
>
> --
> Cheers,
> Luca.

--
All the best,
Shahar

2011-04-06 18:13:53

by Luciano Coelho

[permalink] [raw]
Subject: Re: [PATCH] wl12xx: FM WLAN coexistence

On Mon, 2011-04-04 at 10:07 +0300, Shahar Levi wrote:
> Add support to FM WLAN coexistence (STA only).
> Few WiFi harmonics may interfere FM operation, to
> avoid this problem special coexistence techniques are
> activated around some FM frequencies.
>
> Signed-off-by: Shahar Levi <[email protected]>
> ---

Some comments.


> diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
> index e005aa4..5f5afbe 100644
> --- a/drivers/net/wireless/wl12xx/acx.c
> +++ b/drivers/net/wireless/wl12xx/acx.c
> @@ -1604,3 +1604,45 @@ out:
> kfree(acx);
> return ret;
> }
> +
> +int wl1271_acx_fm_coex(struct wl1271 *wl)
> +{
> + struct wl1271_acx_fm_coex *acx;
> + int ret;
> +
> + wl1271_debug(DEBUG_ACX, "acx fm coex setting");
> +
> + acx = kzalloc(sizeof(*acx), GFP_KERNEL);
> + if (!acx) {
> + ret = -ENOMEM;
> + goto out;
> + }
> +
> + acx->enable = wl->conf.fm_coex.enable;
> + acx->swallow_period = wl->conf.fm_coex.swallow_period;
> + acx->n_divider_fref_set_1 = wl->conf.fm_coex.n_divider_fref_set_1;
> + acx->n_divider_fref_set_2 = wl->conf.fm_coex.n_divider_fref_set_2;
> + acx->m_divider_fref_set_1 =
> + cpu_to_le16(wl->conf.fm_coex.m_divider_fref_set_1);
> + acx->m_divider_fref_set_2 =
> + cpu_to_le16(wl->conf.fm_coex.m_divider_fref_set_2);
> + acx->coex_pll_stabilization_time =
> + cpu_to_le32(wl->conf.fm_coex.coex_pll_stabilization_time);

> + acx->ldo_stabilization_timwl12xx-fm-coex-v2/e =
> + cpu_to_le16(wl->conf.fm_coex.ldo_stabilization_time);

What's this? There is some garbage pasted into this statement here!


> diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h
> index 0a40cae..45242db 100644
> --- a/drivers/net/wireless/wl12xx/acx.h
> +++ b/drivers/net/wireless/wl12xx/acx.h
> @@ -1172,6 +1172,65 @@ struct wl1271_acx_inconnection_sta {
> u8 padding1[2];
> } __packed;
>
> +/*
> + * ACX_FM_COEX_CFG
> + * set the FM co-existence parameters.
> + */
> +struct wl1271_acx_fm_coex {
> + struct acx_header header;
> + /* enable(1) / disable(0) the FM Coex feature */
> + u8 enable;
> + /*
> + * Swallow period used in COEX PLL swallowing mechanism.
> + * 0xFF = use FW default
> + */
> + u8 swallow_period;
> + /*
> + * The N divider used in COEX PLL swallowing mechanism for Fref of
> + * 38.4/19.2 Mhz. 0xFF = use FW default
> + */
> + u8 n_divider_fref_set_1;
> + /*
> + * The N divider used in COEX PLL swallowing mechanism for Fref of
> + * 26/52 Mhz. 0xFF = use FW default
> + */
> + u8 n_divider_fref_set_2;
> + /*
> + * The M divider used in COEX PLL swallowing mechanism for Fref of
> + * 38.4/19.2 Mhz. 0xFFFF = use FW default
> + */
> + u16 m_divider_fref_set_1;

This must be __le16.


> + /*
> + * The M divider used in COEX PLL swallowing mechanism for Fref of
> + * 26/52 Mhz. 0xFFFF = use FW default
> + */
> + u16 m_divider_fref_set_2;

Same here.


> + /*
> + * The time duration in uSec required for COEX PLL to stabilize.
> + * 0xFFFFFFFF = use FW default
> + */
> + u32 coex_pll_stabilization_time;

__le32


> + /*
> + * The time duration in uSec required for LDO to stabilize.
> + * 0xFFFFFFFF = use FW default
> + */
> + u16 ldo_stabilization_time;

__le16


--
Cheers,
Luca.