]> Pileus Git - ~andy/linux/commitdiff
Merge branch 'for-linville' of git://git.kernel.org/pub/scm/linux/kernel/git/luca...
authorJohn W. Linville <linville@tuxdriver.com>
Fri, 13 Apr 2012 18:28:56 +0000 (14:28 -0400)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 13 Apr 2012 18:28:56 +0000 (14:28 -0400)
85 files changed:
MAINTAINERS
drivers/net/wireless/Kconfig
drivers/net/wireless/Makefile
drivers/net/wireless/ti/Kconfig [new file with mode: 0644]
drivers/net/wireless/ti/Makefile [new file with mode: 0644]
drivers/net/wireless/ti/wl1251/Kconfig [moved from drivers/net/wireless/wl1251/Kconfig with 100% similarity]
drivers/net/wireless/ti/wl1251/Makefile [moved from drivers/net/wireless/wl1251/Makefile with 100% similarity]
drivers/net/wireless/ti/wl1251/acx.c [moved from drivers/net/wireless/wl1251/acx.c with 100% similarity]
drivers/net/wireless/ti/wl1251/acx.h [moved from drivers/net/wireless/wl1251/acx.h with 100% similarity]
drivers/net/wireless/ti/wl1251/boot.c [moved from drivers/net/wireless/wl1251/boot.c with 100% similarity]
drivers/net/wireless/ti/wl1251/boot.h [moved from drivers/net/wireless/wl1251/boot.h with 100% similarity]
drivers/net/wireless/ti/wl1251/cmd.c [moved from drivers/net/wireless/wl1251/cmd.c with 100% similarity]
drivers/net/wireless/ti/wl1251/cmd.h [moved from drivers/net/wireless/wl1251/cmd.h with 100% similarity]
drivers/net/wireless/ti/wl1251/debugfs.c [moved from drivers/net/wireless/wl1251/debugfs.c with 100% similarity]
drivers/net/wireless/ti/wl1251/debugfs.h [moved from drivers/net/wireless/wl1251/debugfs.h with 100% similarity]
drivers/net/wireless/ti/wl1251/event.c [moved from drivers/net/wireless/wl1251/event.c with 100% similarity]
drivers/net/wireless/ti/wl1251/event.h [moved from drivers/net/wireless/wl1251/event.h with 100% similarity]
drivers/net/wireless/ti/wl1251/init.c [moved from drivers/net/wireless/wl1251/init.c with 100% similarity]
drivers/net/wireless/ti/wl1251/init.h [moved from drivers/net/wireless/wl1251/init.h with 100% similarity]
drivers/net/wireless/ti/wl1251/io.c [moved from drivers/net/wireless/wl1251/io.c with 100% similarity]
drivers/net/wireless/ti/wl1251/io.h [moved from drivers/net/wireless/wl1251/io.h with 100% similarity]
drivers/net/wireless/ti/wl1251/main.c [moved from drivers/net/wireless/wl1251/main.c with 100% similarity]
drivers/net/wireless/ti/wl1251/ps.c [moved from drivers/net/wireless/wl1251/ps.c with 100% similarity]
drivers/net/wireless/ti/wl1251/ps.h [moved from drivers/net/wireless/wl1251/ps.h with 100% similarity]
drivers/net/wireless/ti/wl1251/reg.h [moved from drivers/net/wireless/wl1251/reg.h with 100% similarity]
drivers/net/wireless/ti/wl1251/rx.c [moved from drivers/net/wireless/wl1251/rx.c with 100% similarity]
drivers/net/wireless/ti/wl1251/rx.h [moved from drivers/net/wireless/wl1251/rx.h with 100% similarity]
drivers/net/wireless/ti/wl1251/sdio.c [moved from drivers/net/wireless/wl1251/sdio.c with 100% similarity]
drivers/net/wireless/ti/wl1251/spi.c [moved from drivers/net/wireless/wl1251/spi.c with 100% similarity]
drivers/net/wireless/ti/wl1251/spi.h [moved from drivers/net/wireless/wl1251/spi.h with 100% similarity]
drivers/net/wireless/ti/wl1251/tx.c [moved from drivers/net/wireless/wl1251/tx.c with 100% similarity]
drivers/net/wireless/ti/wl1251/tx.h [moved from drivers/net/wireless/wl1251/tx.h with 100% similarity]
drivers/net/wireless/ti/wl1251/wl1251.h [moved from drivers/net/wireless/wl1251/wl1251.h with 100% similarity]
drivers/net/wireless/ti/wl1251/wl12xx_80211.h [moved from drivers/net/wireless/wl1251/wl12xx_80211.h with 100% similarity]
drivers/net/wireless/ti/wl12xx/Kconfig [new file with mode: 0644]
drivers/net/wireless/ti/wl12xx/Makefile [new file with mode: 0644]
drivers/net/wireless/ti/wl12xx/acx.c [new file with mode: 0644]
drivers/net/wireless/ti/wl12xx/acx.h [new file with mode: 0644]
drivers/net/wireless/ti/wl12xx/cmd.c [new file with mode: 0644]
drivers/net/wireless/ti/wl12xx/cmd.h [new file with mode: 0644]
drivers/net/wireless/ti/wl12xx/conf.h [new file with mode: 0644]
drivers/net/wireless/ti/wl12xx/main.c [new file with mode: 0644]
drivers/net/wireless/ti/wl12xx/reg.h [moved from drivers/net/wireless/wl12xx/reg.h with 71% similarity]
drivers/net/wireless/ti/wl12xx/wl12xx.h [new file with mode: 0644]
drivers/net/wireless/ti/wlcore/Kconfig [new file with mode: 0644]
drivers/net/wireless/ti/wlcore/Makefile [new file with mode: 0644]
drivers/net/wireless/ti/wlcore/acx.c [moved from drivers/net/wireless/wl12xx/acx.c with 97% similarity]
drivers/net/wireless/ti/wlcore/acx.h [moved from drivers/net/wireless/wl12xx/acx.h with 99% similarity]
drivers/net/wireless/ti/wlcore/boot.c [new file with mode: 0644]
drivers/net/wireless/ti/wlcore/boot.h [new file with mode: 0644]
drivers/net/wireless/ti/wlcore/cmd.c [moved from drivers/net/wireless/wl12xx/cmd.c with 84% similarity]
drivers/net/wireless/ti/wlcore/cmd.h [moved from drivers/net/wireless/wl12xx/cmd.h with 87% similarity]
drivers/net/wireless/ti/wlcore/conf.h [moved from drivers/net/wireless/wl12xx/conf.h with 94% similarity]
drivers/net/wireless/ti/wlcore/debug.h [moved from drivers/net/wireless/wl12xx/debug.h with 99% similarity]
drivers/net/wireless/ti/wlcore/debugfs.c [moved from drivers/net/wireless/wl12xx/debugfs.c with 99% similarity]
drivers/net/wireless/ti/wlcore/debugfs.h [moved from drivers/net/wireless/wl12xx/debugfs.h with 98% similarity]
drivers/net/wireless/ti/wlcore/event.c [moved from drivers/net/wireless/wl12xx/event.c with 91% similarity]
drivers/net/wireless/ti/wlcore/event.h [moved from drivers/net/wireless/wl12xx/event.h with 98% similarity]
drivers/net/wireless/ti/wlcore/hw_ops.h [new file with mode: 0644]
drivers/net/wireless/ti/wlcore/ini.h [moved from drivers/net/wireless/wl12xx/ini.h with 100% similarity]
drivers/net/wireless/ti/wlcore/init.c [moved from drivers/net/wireless/wl12xx/init.c with 93% similarity]
drivers/net/wireless/ti/wlcore/init.h [moved from drivers/net/wireless/wl12xx/init.h with 98% similarity]
drivers/net/wireless/ti/wlcore/io.c [moved from drivers/net/wireless/wl12xx/io.c with 55% similarity]
drivers/net/wireless/ti/wlcore/io.h [moved from drivers/net/wireless/wl12xx/io.h with 71% similarity]
drivers/net/wireless/ti/wlcore/main.c [moved from drivers/net/wireless/wl12xx/main.c with 85% similarity]
drivers/net/wireless/ti/wlcore/ps.c [moved from drivers/net/wireless/wl12xx/ps.c with 97% similarity]
drivers/net/wireless/ti/wlcore/ps.h [moved from drivers/net/wireless/wl12xx/ps.h with 98% similarity]
drivers/net/wireless/ti/wlcore/rx.c [moved from drivers/net/wireless/wl12xx/rx.c with 69% similarity]
drivers/net/wireless/ti/wlcore/rx.h [moved from drivers/net/wireless/wl12xx/rx.h with 92% similarity]
drivers/net/wireless/ti/wlcore/scan.c [moved from drivers/net/wireless/wl12xx/scan.c with 95% similarity]
drivers/net/wireless/ti/wlcore/scan.h [moved from drivers/net/wireless/wl12xx/scan.h with 98% similarity]
drivers/net/wireless/ti/wlcore/sdio.c [moved from drivers/net/wireless/wl12xx/sdio.c with 98% similarity]
drivers/net/wireless/ti/wlcore/spi.c [moved from drivers/net/wireless/wl12xx/spi.c with 99% similarity]
drivers/net/wireless/ti/wlcore/testmode.c [moved from drivers/net/wireless/wl12xx/testmode.c with 99% similarity]
drivers/net/wireless/ti/wlcore/testmode.h [moved from drivers/net/wireless/wl12xx/testmode.h with 100% similarity]
drivers/net/wireless/ti/wlcore/tx.c [moved from drivers/net/wireless/wl12xx/tx.c with 90% similarity]
drivers/net/wireless/ti/wlcore/tx.h [moved from drivers/net/wireless/wl12xx/tx.h with 97% similarity]
drivers/net/wireless/ti/wlcore/wl12xx.h [moved from drivers/net/wireless/wl12xx/wl12xx.h with 68% similarity]
drivers/net/wireless/ti/wlcore/wl12xx_80211.h [moved from drivers/net/wireless/wl12xx/wl12xx_80211.h with 100% similarity]
drivers/net/wireless/ti/wlcore/wl12xx_platform_data.c [moved from drivers/net/wireless/wl12xx/wl12xx_platform_data.c with 100% similarity]
drivers/net/wireless/ti/wlcore/wlcore.h [new file with mode: 0644]
drivers/net/wireless/wl12xx/Kconfig [deleted file]
drivers/net/wireless/wl12xx/Makefile [deleted file]
drivers/net/wireless/wl12xx/boot.c [deleted file]
drivers/net/wireless/wl12xx/boot.h [deleted file]

index 6010b9d13b477fff1df776e7ee1f6a62e731529f..fa96459fa01f12d775730f5138e8402b0a8cb8e0 100644 (file)
@@ -6669,6 +6669,16 @@ L:       alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Maintained
 F:     sound/soc/codecs/twl4030*
 
+TI WILINK WIRELESS DRIVERS
+M:     Luciano Coelho <coelho@ti.com>
+L:     linux-wireless@vger.kernel.org
+W:     http://wireless.kernel.org/en/users/Drivers/wl12xx
+W:     http://wireless.kernel.org/en/users/Drivers/wl1251
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx.git
+S:     Maintained
+F:     drivers/net/wireless/ti/
+F:     include/linux/wl12xx.h
+
 TIPC NETWORK LAYER
 M:     Jon Maloy <jon.maloy@ericsson.com>
 M:     Allan Stephens <allan.stephens@windriver.com>
@@ -7425,23 +7435,6 @@ M:       Miloslav Trmac <mitr@volny.cz>
 S:     Maintained
 F:     drivers/input/misc/wistron_btns.c
 
-WL1251 WIRELESS DRIVER
-M:     Luciano Coelho <coelho@ti.com>
-L:     linux-wireless@vger.kernel.org
-W:     http://wireless.kernel.org/en/users/Drivers/wl1251
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
-S:     Maintained
-F:     drivers/net/wireless/wl1251/*
-
-WL1271 WIRELESS DRIVER
-M:     Luciano Coelho <coelho@ti.com>
-L:     linux-wireless@vger.kernel.org
-W:     http://wireless.kernel.org/en/users/Drivers/wl12xx
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx.git
-S:     Maintained
-F:     drivers/net/wireless/wl12xx/
-F:     include/linux/wl12xx.h
-
 WL3501 WIRELESS PCMCIA CARD DRIVER
 M:     Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
 L:     linux-wireless@vger.kernel.org
index abd3b71cd4abf8535ee33c1239a0c15ddf9a0f5f..5f58fa53238cc2496eb9658e6d83f87559b11d66 100644 (file)
@@ -282,8 +282,7 @@ source "drivers/net/wireless/orinoco/Kconfig"
 source "drivers/net/wireless/p54/Kconfig"
 source "drivers/net/wireless/rt2x00/Kconfig"
 source "drivers/net/wireless/rtlwifi/Kconfig"
-source "drivers/net/wireless/wl1251/Kconfig"
-source "drivers/net/wireless/wl12xx/Kconfig"
+source "drivers/net/wireless/ti/Kconfig"
 source "drivers/net/wireless/zd1211rw/Kconfig"
 source "drivers/net/wireless/mwifiex/Kconfig"
 
index 98db76196b59d448ae7d11ba33e46cc8f9339d74..0ce218b931d4091a7f377cbb7866c603b8ede36f 100644 (file)
@@ -51,9 +51,7 @@ obj-$(CONFIG_ATH_COMMON)      += ath/
 
 obj-$(CONFIG_MAC80211_HWSIM)   += mac80211_hwsim.o
 
-obj-$(CONFIG_WL1251)   += wl1251/
-obj-$(CONFIG_WL12XX)   += wl12xx/
-obj-$(CONFIG_WL12XX_PLATFORM_DATA)     += wl12xx/
+obj-$(CONFIG_WL_TI)    += ti/
 
 obj-$(CONFIG_IWM)      += iwmc3200wifi/
 
diff --git a/drivers/net/wireless/ti/Kconfig b/drivers/net/wireless/ti/Kconfig
new file mode 100644 (file)
index 0000000..1a72932
--- /dev/null
@@ -0,0 +1,14 @@
+menuconfig WL_TI
+       bool "TI Wireless LAN support"
+       ---help---
+         This section contains support for all the wireless drivers
+         for Texas Instruments WLAN chips, such as wl1251 and the wl12xx
+         family.
+
+if WL_TI
+source "drivers/net/wireless/ti/wl1251/Kconfig"
+source "drivers/net/wireless/ti/wl12xx/Kconfig"
+
+# keep last for automatic dependencies
+source "drivers/net/wireless/ti/wlcore/Kconfig"
+endif # WL_TI
diff --git a/drivers/net/wireless/ti/Makefile b/drivers/net/wireless/ti/Makefile
new file mode 100644 (file)
index 0000000..0a56562
--- /dev/null
@@ -0,0 +1,4 @@
+obj-$(CONFIG_WLCORE)                   += wlcore/
+obj-$(CONFIG_WL12XX)                   += wl12xx/
+obj-$(CONFIG_WL12XX_PLATFORM_DATA)     += wlcore/
+obj-$(CONFIG_WL1251)                   += wl1251/
diff --git a/drivers/net/wireless/ti/wl12xx/Kconfig b/drivers/net/wireless/ti/wl12xx/Kconfig
new file mode 100644 (file)
index 0000000..5b92329
--- /dev/null
@@ -0,0 +1,8 @@
+config WL12XX
+       tristate "TI wl12xx support"
+       select WLCORE
+       ---help---
+         This module adds support for wireless adapters based on TI wl1271,
+         wl1273, wl1281 and wl1283 chipsets. This module does *not* include
+         support for wl1251.  For wl1251 support, use the separate homonymous
+          driver instead.
diff --git a/drivers/net/wireless/ti/wl12xx/Makefile b/drivers/net/wireless/ti/wl12xx/Makefile
new file mode 100644 (file)
index 0000000..87f64b1
--- /dev/null
@@ -0,0 +1,3 @@
+wl12xx-objs    = main.o cmd.o acx.o
+
+obj-$(CONFIG_WL12XX)           += wl12xx.o
diff --git a/drivers/net/wireless/ti/wl12xx/acx.c b/drivers/net/wireless/ti/wl12xx/acx.c
new file mode 100644 (file)
index 0000000..bea06b2
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * This file is part of wl12xx
+ *
+ * Copyright (C) 2008-2009 Nokia Corporation
+ * Copyright (C) 2011 Texas Instruments Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include "../wlcore/cmd.h"
+#include "../wlcore/debug.h"
+#include "../wlcore/acx.h"
+
+#include "acx.h"
+
+int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap)
+{
+       struct wl1271_acx_host_config_bitmap *bitmap_conf;
+       int ret;
+
+       bitmap_conf = kzalloc(sizeof(*bitmap_conf), GFP_KERNEL);
+       if (!bitmap_conf) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       bitmap_conf->host_cfg_bitmap = cpu_to_le32(host_cfg_bitmap);
+
+       ret = wl1271_cmd_configure(wl, ACX_HOST_IF_CFG_BITMAP,
+                                  bitmap_conf, sizeof(*bitmap_conf));
+       if (ret < 0) {
+               wl1271_warning("wl1271 bitmap config opt failed: %d", ret);
+               goto out;
+       }
+
+out:
+       kfree(bitmap_conf);
+
+       return ret;
+}
diff --git a/drivers/net/wireless/ti/wl12xx/acx.h b/drivers/net/wireless/ti/wl12xx/acx.h
new file mode 100644 (file)
index 0000000..d1f5aba
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * This file is part of wl12xx
+ *
+ * Copyright (C) 1998-2009, 2011 Texas Instruments. All rights reserved.
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __WL12XX_ACX_H__
+#define __WL12XX_ACX_H__
+
+#include "../wlcore/wlcore.h"
+
+struct wl1271_acx_host_config_bitmap {
+       struct acx_header header;
+
+       __le32 host_cfg_bitmap;
+} __packed;
+
+int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap);
+
+#endif /* __WL12XX_ACX_H__ */
diff --git a/drivers/net/wireless/ti/wl12xx/cmd.c b/drivers/net/wireless/ti/wl12xx/cmd.c
new file mode 100644 (file)
index 0000000..8ffaeb5
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ * This file is part of wl12xx
+ *
+ * Copyright (C) 2009-2010 Nokia Corporation
+ * Copyright (C) 2011 Texas Instruments Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include "../wlcore/cmd.h"
+#include "../wlcore/debug.h"
+
+#include "wl12xx.h"
+#include "cmd.h"
+
+int wl1271_cmd_ext_radio_parms(struct wl1271 *wl)
+{
+       struct wl1271_ext_radio_parms_cmd *ext_radio_parms;
+       struct wl12xx_priv *priv = wl->priv;
+       struct wl12xx_conf_rf *rf = &priv->conf.rf;
+       int ret;
+
+       if (!wl->nvs)
+               return -ENODEV;
+
+       ext_radio_parms = kzalloc(sizeof(*ext_radio_parms), GFP_KERNEL);
+       if (!ext_radio_parms)
+               return -ENOMEM;
+
+       ext_radio_parms->test.id = TEST_CMD_INI_FILE_RF_EXTENDED_PARAM;
+
+       memcpy(ext_radio_parms->tx_per_channel_power_compensation_2,
+              rf->tx_per_channel_power_compensation_2,
+              CONF_TX_PWR_COMPENSATION_LEN_2);
+       memcpy(ext_radio_parms->tx_per_channel_power_compensation_5,
+              rf->tx_per_channel_power_compensation_5,
+              CONF_TX_PWR_COMPENSATION_LEN_5);
+
+       wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_EXT_RADIO_PARAM: ",
+                   ext_radio_parms, sizeof(*ext_radio_parms));
+
+       ret = wl1271_cmd_test(wl, ext_radio_parms, sizeof(*ext_radio_parms), 0);
+       if (ret < 0)
+               wl1271_warning("TEST_CMD_INI_FILE_RF_EXTENDED_PARAM failed");
+
+       kfree(ext_radio_parms);
+       return ret;
+}
+
+int wl1271_cmd_general_parms(struct wl1271 *wl)
+{
+       struct wl1271_general_parms_cmd *gen_parms;
+       struct wl1271_ini_general_params *gp =
+               &((struct wl1271_nvs_file *)wl->nvs)->general_params;
+       bool answer = false;
+       int ret;
+
+       if (!wl->nvs)
+               return -ENODEV;
+
+       if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
+               wl1271_warning("FEM index from INI out of bounds");
+               return -EINVAL;
+       }
+
+       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;
+
+       /* Override the REF CLK from the NVS with the one from platform data */
+       gen_parms->general_params.ref_clock = wl->ref_clock;
+
+       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;
+
+       if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
+               wl1271_warning("FEM index from FW out of bounds");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       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;
+
+       if (!wl->nvs)
+               return -ENODEV;
+
+       if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
+               wl1271_warning("FEM index from ini out of bounds");
+               return -EINVAL;
+       }
+
+       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;
+
+       /* Replace REF and TCXO CLKs with the ones from platform data */
+       gen_parms->general_params.ref_clock = wl->ref_clock;
+       gen_parms->general_params.tcxo_ref_clock = wl->tcxo_clock;
+
+       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;
+
+       if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
+               wl1271_warning("FEM index from FW out of bounds");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       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 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 = &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 wl1271_ini_band_params_2));
+       memcpy(&radio_parms->dyn_params_2,
+              &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,
+              &nvs->stat_radio_params_5,
+              sizeof(struct wl1271_ini_band_params_5));
+       memcpy(&radio_parms->dyn_params_5,
+              &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: ",
+                   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 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;
+}
diff --git a/drivers/net/wireless/ti/wl12xx/cmd.h b/drivers/net/wireless/ti/wl12xx/cmd.h
new file mode 100644 (file)
index 0000000..140a0e8
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * This file is part of wl12xx
+ *
+ * Copyright (C) 1998-2009, 2011 Texas Instruments. All rights reserved.
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __WL12XX_CMD_H__
+#define __WL12XX_CMD_H__
+
+#include "conf.h"
+
+#define TEST_CMD_INI_FILE_RADIO_PARAM       0x19
+#define TEST_CMD_INI_FILE_GENERAL_PARAM     0x1E
+
+struct wl1271_general_parms_cmd {
+       struct wl1271_cmd_header header;
+
+       struct wl1271_cmd_test_header test;
+
+       struct wl1271_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 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;
+
+       struct wl1271_cmd_test_header test;
+
+       /* Static radio parameters */
+       struct wl1271_ini_band_params_2 static_params_2;
+       struct wl1271_ini_band_params_5 static_params_5;
+
+       /* Dynamic radio parameters */
+       struct wl1271_ini_fem_params_2 dyn_params_2;
+       u8 padding2;
+       struct wl1271_ini_fem_params_5 dyn_params_5;
+       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;
+
+#define TEST_CMD_INI_FILE_RF_EXTENDED_PARAM 0x26
+
+struct wl1271_ext_radio_parms_cmd {
+       struct wl1271_cmd_header header;
+
+       struct wl1271_cmd_test_header test;
+
+       u8 tx_per_channel_power_compensation_2[CONF_TX_PWR_COMPENSATION_LEN_2];
+       u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5];
+       u8 padding[3];
+} __packed;
+
+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);
+
+#endif /* __WL12XX_CMD_H__ */
diff --git a/drivers/net/wireless/ti/wl12xx/conf.h b/drivers/net/wireless/ti/wl12xx/conf.h
new file mode 100644 (file)
index 0000000..75e2989
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * This file is part of wl12xx
+ *
+ * Copyright (C) 2011 Texas Instruments Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __WL12XX_CONF_H__
+#define __WL12XX_CONF_H__
+
+/* these are number of channels on the band divided by two, rounded up */
+#define CONF_TX_PWR_COMPENSATION_LEN_2 7
+#define CONF_TX_PWR_COMPENSATION_LEN_5 18
+
+struct wl12xx_conf_rf {
+       /*
+        * Per channel power compensation for 2.4GHz
+        *
+        * Range: s8
+        */
+       u8 tx_per_channel_power_compensation_2[CONF_TX_PWR_COMPENSATION_LEN_2];
+
+       /*
+        * Per channel power compensation for 5GHz
+        *
+        * Range: s8
+        */
+       u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5];
+};
+
+struct wl12xx_priv_conf {
+       struct wl12xx_conf_rf rf;
+       struct conf_memory_settings mem_wl127x;
+};
+
+#endif /* __WL12XX_CONF_H__ */
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
new file mode 100644 (file)
index 0000000..d7dd3de
--- /dev/null
@@ -0,0 +1,1388 @@
+/*
+ * This file is part of wl1271
+ *
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <linux/err.h>
+
+#include <linux/wl12xx.h>
+
+#include "../wlcore/wlcore.h"
+#include "../wlcore/debug.h"
+#include "../wlcore/io.h"
+#include "../wlcore/acx.h"
+#include "../wlcore/tx.h"
+#include "../wlcore/rx.h"
+#include "../wlcore/io.h"
+#include "../wlcore/boot.h"
+
+#include "wl12xx.h"
+#include "reg.h"
+#include "cmd.h"
+#include "acx.h"
+
+static struct wlcore_conf wl12xx_conf = {
+       .sg = {
+               .params = {
+                       [CONF_SG_ACL_BT_MASTER_MIN_BR] = 10,
+                       [CONF_SG_ACL_BT_MASTER_MAX_BR] = 180,
+                       [CONF_SG_ACL_BT_SLAVE_MIN_BR] = 10,
+                       [CONF_SG_ACL_BT_SLAVE_MAX_BR] = 180,
+                       [CONF_SG_ACL_BT_MASTER_MIN_EDR] = 10,
+                       [CONF_SG_ACL_BT_MASTER_MAX_EDR] = 80,
+                       [CONF_SG_ACL_BT_SLAVE_MIN_EDR] = 10,
+                       [CONF_SG_ACL_BT_SLAVE_MAX_EDR] = 80,
+                       [CONF_SG_ACL_WLAN_PS_MASTER_BR] = 8,
+                       [CONF_SG_ACL_WLAN_PS_SLAVE_BR] = 8,
+                       [CONF_SG_ACL_WLAN_PS_MASTER_EDR] = 20,
+                       [CONF_SG_ACL_WLAN_PS_SLAVE_EDR] = 20,
+                       [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_BR] = 20,
+                       [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_BR] = 35,
+                       [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_BR] = 16,
+                       [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_BR] = 35,
+                       [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_EDR] = 32,
+                       [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_EDR] = 50,
+                       [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_EDR] = 28,
+                       [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_EDR] = 50,
+                       [CONF_SG_ACL_ACTIVE_SCAN_WLAN_BR] = 10,
+                       [CONF_SG_ACL_ACTIVE_SCAN_WLAN_EDR] = 20,
+                       [CONF_SG_ACL_PASSIVE_SCAN_BT_BR] = 75,
+                       [CONF_SG_ACL_PASSIVE_SCAN_WLAN_BR] = 15,
+                       [CONF_SG_ACL_PASSIVE_SCAN_BT_EDR] = 27,
+                       [CONF_SG_ACL_PASSIVE_SCAN_WLAN_EDR] = 17,
+                       /* active scan params */
+                       [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170,
+                       [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50,
+                       [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100,
+                       /* passive scan params */
+                       [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_BR] = 800,
+                       [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_EDR] = 200,
+                       [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200,
+                       /* passive scan in dual antenna params */
+                       [CONF_SG_CONSECUTIVE_HV3_IN_PASSIVE_SCAN] = 0,
+                       [CONF_SG_BCN_HV3_COLLISION_THRESH_IN_PASSIVE_SCAN] = 0,
+                       [CONF_SG_TX_RX_PROTECTION_BWIDTH_IN_PASSIVE_SCAN] = 0,
+                       /* general params */
+                       [CONF_SG_STA_FORCE_PS_IN_BT_SCO] = 1,
+                       [CONF_SG_ANTENNA_CONFIGURATION] = 0,
+                       [CONF_SG_BEACON_MISS_PERCENT] = 60,
+                       [CONF_SG_DHCP_TIME] = 5000,
+                       [CONF_SG_RXT] = 1200,
+                       [CONF_SG_TXT] = 1000,
+                       [CONF_SG_ADAPTIVE_RXT_TXT] = 1,
+                       [CONF_SG_GENERAL_USAGE_BIT_MAP] = 3,
+                       [CONF_SG_HV3_MAX_SERVED] = 6,
+                       [CONF_SG_PS_POLL_TIMEOUT] = 10,
+                       [CONF_SG_UPSD_TIMEOUT] = 10,
+                       [CONF_SG_CONSECUTIVE_CTS_THRESHOLD] = 2,
+                       [CONF_SG_STA_RX_WINDOW_AFTER_DTIM] = 5,
+                       [CONF_SG_STA_CONNECTION_PROTECTION_TIME] = 30,
+                       /* AP params */
+                       [CONF_AP_BEACON_MISS_TX] = 3,
+                       [CONF_AP_RX_WINDOW_AFTER_BEACON] = 10,
+                       [CONF_AP_BEACON_WINDOW_INTERVAL] = 2,
+                       [CONF_AP_CONNECTION_PROTECTION_TIME] = 0,
+                       [CONF_AP_BT_ACL_VAL_BT_SERVE_TIME] = 25,
+                       [CONF_AP_BT_ACL_VAL_WL_SERVE_TIME] = 25,
+                       /* CTS Diluting params */
+                       [CONF_SG_CTS_DILUTED_BAD_RX_PACKETS_TH] = 0,
+                       [CONF_SG_CTS_CHOP_IN_DUAL_ANT_SCO_MASTER] = 0,
+               },
+               .state = CONF_SG_PROTECTIVE,
+       },
+       .rx = {
+               .rx_msdu_life_time           = 512000,
+               .packet_detection_threshold  = 0,
+               .ps_poll_timeout             = 15,
+               .upsd_timeout                = 15,
+               .rts_threshold               = IEEE80211_MAX_RTS_THRESHOLD,
+               .rx_cca_threshold            = 0,
+               .irq_blk_threshold           = 0xFFFF,
+               .irq_pkt_threshold           = 0,
+               .irq_timeout                 = 600,
+               .queue_type                  = CONF_RX_QUEUE_TYPE_LOW_PRIORITY,
+       },
+       .tx = {
+               .tx_energy_detection         = 0,
+               .sta_rc_conf                 = {
+                       .enabled_rates       = 0,
+                       .short_retry_limit   = 10,
+                       .long_retry_limit    = 10,
+                       .aflags              = 0,
+               },
+               .ac_conf_count               = 4,
+               .ac_conf                     = {
+                       [CONF_TX_AC_BE] = {
+                               .ac          = CONF_TX_AC_BE,
+                               .cw_min      = 15,
+                               .cw_max      = 63,
+                               .aifsn       = 3,
+                               .tx_op_limit = 0,
+                       },
+                       [CONF_TX_AC_BK] = {
+                               .ac          = CONF_TX_AC_BK,
+                               .cw_min      = 15,
+                               .cw_max      = 63,
+                               .aifsn       = 7,
+                               .tx_op_limit = 0,
+                       },
+                       [CONF_TX_AC_VI] = {
+                               .ac          = CONF_TX_AC_VI,
+                               .cw_min      = 15,
+                               .cw_max      = 63,
+                               .aifsn       = CONF_TX_AIFS_PIFS,
+                               .tx_op_limit = 3008,
+                       },
+                       [CONF_TX_AC_VO] = {
+                               .ac          = CONF_TX_AC_VO,
+                               .cw_min      = 15,
+                               .cw_max      = 63,
+                               .aifsn       = CONF_TX_AIFS_PIFS,
+                               .tx_op_limit = 1504,
+                       },
+               },
+               .max_tx_retries = 100,
+               .ap_aging_period = 300,
+               .tid_conf_count = 4,
+               .tid_conf = {
+                       [CONF_TX_AC_BE] = {
+                               .queue_id    = CONF_TX_AC_BE,
+                               .channel_type = CONF_CHANNEL_TYPE_EDCF,
+                               .tsid        = CONF_TX_AC_BE,
+                               .ps_scheme   = CONF_PS_SCHEME_LEGACY,
+                               .ack_policy  = CONF_ACK_POLICY_LEGACY,
+                               .apsd_conf   = {0, 0},
+                       },
+                       [CONF_TX_AC_BK] = {
+                               .queue_id    = CONF_TX_AC_BK,
+                               .channel_type = CONF_CHANNEL_TYPE_EDCF,
+                               .tsid        = CONF_TX_AC_BK,
+                               .ps_scheme   = CONF_PS_SCHEME_LEGACY,
+                               .ack_policy  = CONF_ACK_POLICY_LEGACY,
+                               .apsd_conf   = {0, 0},
+                       },
+                       [CONF_TX_AC_VI] = {
+                               .queue_id    = CONF_TX_AC_VI,
+                               .channel_type = CONF_CHANNEL_TYPE_EDCF,
+                               .tsid        = CONF_TX_AC_VI,
+                               .ps_scheme   = CONF_PS_SCHEME_LEGACY,
+                               .ack_policy  = CONF_ACK_POLICY_LEGACY,
+                               .apsd_conf   = {0, 0},
+                       },
+                       [CONF_TX_AC_VO] = {
+                               .queue_id    = CONF_TX_AC_VO,
+                               .channel_type = CONF_CHANNEL_TYPE_EDCF,
+                               .tsid        = CONF_TX_AC_VO,
+                               .ps_scheme   = CONF_PS_SCHEME_LEGACY,
+                               .ack_policy  = CONF_ACK_POLICY_LEGACY,
+                               .apsd_conf   = {0, 0},
+                       },
+               },
+               .frag_threshold              = IEEE80211_MAX_FRAG_THRESHOLD,
+               .tx_compl_timeout            = 700,
+               .tx_compl_threshold          = 4,
+               .basic_rate                  = CONF_HW_BIT_RATE_1MBPS,
+               .basic_rate_5                = CONF_HW_BIT_RATE_6MBPS,
+               .tmpl_short_retry_limit      = 10,
+               .tmpl_long_retry_limit       = 10,
+               .tx_watchdog_timeout         = 5000,
+       },
+       .conn = {
+               .wake_up_event               = CONF_WAKE_UP_EVENT_DTIM,
+               .listen_interval             = 1,
+               .suspend_wake_up_event       = CONF_WAKE_UP_EVENT_N_DTIM,
+               .suspend_listen_interval     = 3,
+               .bcn_filt_mode               = CONF_BCN_FILT_MODE_ENABLED,
+               .bcn_filt_ie_count           = 2,
+               .bcn_filt_ie = {
+                       [0] = {
+                               .ie          = WLAN_EID_CHANNEL_SWITCH,
+                               .rule        = CONF_BCN_RULE_PASS_ON_APPEARANCE,
+                       },
+                       [1] = {
+                               .ie          = WLAN_EID_HT_OPERATION,
+                               .rule        = CONF_BCN_RULE_PASS_ON_CHANGE,
+                       },
+               },
+               .synch_fail_thold            = 10,
+               .bss_lose_timeout            = 100,
+               .beacon_rx_timeout           = 10000,
+               .broadcast_timeout           = 20000,
+               .rx_broadcast_in_ps          = 1,
+               .ps_poll_threshold           = 10,
+               .bet_enable                  = CONF_BET_MODE_ENABLE,
+               .bet_max_consecutive         = 50,
+               .psm_entry_retries           = 8,
+               .psm_exit_retries            = 16,
+               .psm_entry_nullfunc_retries  = 3,
+               .dynamic_ps_timeout          = 40,
+               .forced_ps                   = false,
+               .keep_alive_interval         = 55000,
+               .max_listen_interval         = 20,
+       },
+       .itrim = {
+               .enable = false,
+               .timeout = 50000,
+       },
+       .pm_config = {
+               .host_clk_settling_time = 5000,
+               .host_fast_wakeup_support = false
+       },
+       .roam_trigger = {
+               .trigger_pacing               = 1,
+               .avg_weight_rssi_beacon       = 20,
+               .avg_weight_rssi_data         = 10,
+               .avg_weight_snr_beacon        = 20,
+               .avg_weight_snr_data          = 10,
+       },
+       .scan = {
+               .min_dwell_time_active        = 7500,
+               .max_dwell_time_active        = 30000,
+               .min_dwell_time_passive       = 100000,
+               .max_dwell_time_passive       = 100000,
+               .num_probe_reqs               = 2,
+               .split_scan_timeout           = 50000,
+       },
+       .sched_scan = {
+               /*
+                * Values are in TU/1000 but since sched scan FW command
+                * params are in TUs rounding up may occur.
+                */
+               .base_dwell_time                = 7500,
+               .max_dwell_time_delta           = 22500,
+               /* based on 250bits per probe @1Mbps */
+               .dwell_time_delta_per_probe     = 2000,
+               /* based on 250bits per probe @6Mbps (plus a bit more) */
+               .dwell_time_delta_per_probe_5   = 350,
+               .dwell_time_passive             = 100000,
+               .dwell_time_dfs                 = 150000,
+               .num_probe_reqs                 = 2,
+               .rssi_threshold                 = -90,
+               .snr_threshold                  = 0,
+       },
+       .ht = {
+               .rx_ba_win_size = 8,
+               .tx_ba_win_size = 64,
+               .inactivity_timeout = 10000,
+               .tx_ba_tid_bitmap = CONF_TX_BA_ENABLED_TID_BITMAP,
+       },
+       /*
+        * Memory config for wl127x chips is given in the
+        * wl12xx_default_priv_conf struct. The below configuration is
+        * for wl128x chips.
+        */
+       .mem = {
+               .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,
+       },
+       .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 */
+       },
+       .rx_streaming = {
+               .duration                      = 150,
+               .queues                        = 0x1,
+               .interval                      = 20,
+               .always                        = 0,
+       },
+       .fwlog = {
+               .mode                         = WL12XX_FWLOG_ON_DEMAND,
+               .mem_blocks                   = 2,
+               .severity                     = 0,
+               .timestamp                    = WL12XX_FWLOG_TIMESTAMP_DISABLED,
+               .output                       = WL12XX_FWLOG_OUTPUT_HOST,
+               .threshold                    = 0,
+       },
+       .rate = {
+               .rate_retry_score = 32000,
+               .per_add = 8192,
+               .per_th1 = 2048,
+               .per_th2 = 4096,
+               .max_per = 8100,
+               .inverse_curiosity_factor = 5,
+               .tx_fail_low_th = 4,
+               .tx_fail_high_th = 10,
+               .per_alpha_shift = 4,
+               .per_add_shift = 13,
+               .per_beta1_shift = 10,
+               .per_beta2_shift = 8,
+               .rate_check_up = 2,
+               .rate_check_down = 12,
+               .rate_retry_policy = {
+                       0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00,
+               },
+       },
+       .hangover = {
+               .recover_time               = 0,
+               .hangover_period            = 20,
+               .dynamic_mode               = 1,
+               .early_termination_mode     = 1,
+               .max_period                 = 20,
+               .min_period                 = 1,
+               .increase_delta             = 1,
+               .decrease_delta             = 2,
+               .quiet_time                 = 4,
+               .increase_time              = 1,
+               .window_size                = 16,
+       },
+};
+
+static struct wl12xx_priv_conf wl12xx_default_priv_conf = {
+       .rf = {
+               .tx_per_channel_power_compensation_2 = {
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+               },
+               .tx_per_channel_power_compensation_5 = {
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+               },
+       },
+       .mem_wl127x = {
+               .num_stations                 = 1,
+               .ssid_profiles                = 1,
+               .rx_block_num                 = 70,
+               .tx_min_block_num             = 40,
+               .dynamic_memory               = 1,
+               .min_req_tx_blocks            = 100,
+               .min_req_rx_blocks            = 22,
+               .tx_min                       = 27,
+       },
+
+};
+
+#define WL12XX_TX_HW_BLOCK_SPARE_DEFAULT        1
+#define WL12XX_TX_HW_BLOCK_GEM_SPARE            2
+#define WL12XX_TX_HW_BLOCK_SIZE                 252
+
+static const u8 wl12xx_rate_to_idx_2ghz[] = {
+       /* MCS rates are used only with 11n */
+       7,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS7_SGI */
+       7,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS7 */
+       6,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS6 */
+       5,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS5 */
+       4,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS4 */
+       3,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS3 */
+       2,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS2 */
+       1,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS1 */
+       0,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS0 */
+
+       11,                            /* WL12XX_CONF_HW_RXTX_RATE_54   */
+       10,                            /* WL12XX_CONF_HW_RXTX_RATE_48   */
+       9,                             /* WL12XX_CONF_HW_RXTX_RATE_36   */
+       8,                             /* WL12XX_CONF_HW_RXTX_RATE_24   */
+
+       /* TI-specific rate */
+       CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL12XX_CONF_HW_RXTX_RATE_22   */
+
+       7,                             /* WL12XX_CONF_HW_RXTX_RATE_18   */
+       6,                             /* WL12XX_CONF_HW_RXTX_RATE_12   */
+       3,                             /* WL12XX_CONF_HW_RXTX_RATE_11   */
+       5,                             /* WL12XX_CONF_HW_RXTX_RATE_9    */
+       4,                             /* WL12XX_CONF_HW_RXTX_RATE_6    */
+       2,                             /* WL12XX_CONF_HW_RXTX_RATE_5_5  */
+       1,                             /* WL12XX_CONF_HW_RXTX_RATE_2    */
+       0                              /* WL12XX_CONF_HW_RXTX_RATE_1    */
+};
+
+static const u8 wl12xx_rate_to_idx_5ghz[] = {
+       /* MCS rates are used only with 11n */
+       7,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS7_SGI */
+       7,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS7 */
+       6,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS6 */
+       5,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS5 */
+       4,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS4 */
+       3,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS3 */
+       2,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS2 */
+       1,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS1 */
+       0,                             /* WL12XX_CONF_HW_RXTX_RATE_MCS0 */
+
+       7,                             /* WL12XX_CONF_HW_RXTX_RATE_54   */
+       6,                             /* WL12XX_CONF_HW_RXTX_RATE_48   */
+       5,                             /* WL12XX_CONF_HW_RXTX_RATE_36   */
+       4,                             /* WL12XX_CONF_HW_RXTX_RATE_24   */
+
+       /* TI-specific rate */
+       CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL12XX_CONF_HW_RXTX_RATE_22   */
+
+       3,                             /* WL12XX_CONF_HW_RXTX_RATE_18   */
+       2,                             /* WL12XX_CONF_HW_RXTX_RATE_12   */
+       CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL12XX_CONF_HW_RXTX_RATE_11   */
+       1,                             /* WL12XX_CONF_HW_RXTX_RATE_9    */
+       0,                             /* WL12XX_CONF_HW_RXTX_RATE_6    */
+       CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL12XX_CONF_HW_RXTX_RATE_5_5  */
+       CONF_HW_RXTX_RATE_UNSUPPORTED, /* WL12XX_CONF_HW_RXTX_RATE_2    */
+       CONF_HW_RXTX_RATE_UNSUPPORTED  /* WL12XX_CONF_HW_RXTX_RATE_1    */
+};
+
+static const u8 *wl12xx_band_rate_to_idx[] = {
+       [IEEE80211_BAND_2GHZ] = wl12xx_rate_to_idx_2ghz,
+       [IEEE80211_BAND_5GHZ] = wl12xx_rate_to_idx_5ghz
+};
+
+enum wl12xx_hw_rates {
+       WL12XX_CONF_HW_RXTX_RATE_MCS7_SGI = 0,
+       WL12XX_CONF_HW_RXTX_RATE_MCS7,
+       WL12XX_CONF_HW_RXTX_RATE_MCS6,
+       WL12XX_CONF_HW_RXTX_RATE_MCS5,
+       WL12XX_CONF_HW_RXTX_RATE_MCS4,
+       WL12XX_CONF_HW_RXTX_RATE_MCS3,
+       WL12XX_CONF_HW_RXTX_RATE_MCS2,
+       WL12XX_CONF_HW_RXTX_RATE_MCS1,
+       WL12XX_CONF_HW_RXTX_RATE_MCS0,
+       WL12XX_CONF_HW_RXTX_RATE_54,
+       WL12XX_CONF_HW_RXTX_RATE_48,
+       WL12XX_CONF_HW_RXTX_RATE_36,
+       WL12XX_CONF_HW_RXTX_RATE_24,
+       WL12XX_CONF_HW_RXTX_RATE_22,
+       WL12XX_CONF_HW_RXTX_RATE_18,
+       WL12XX_CONF_HW_RXTX_RATE_12,
+       WL12XX_CONF_HW_RXTX_RATE_11,
+       WL12XX_CONF_HW_RXTX_RATE_9,
+       WL12XX_CONF_HW_RXTX_RATE_6,
+       WL12XX_CONF_HW_RXTX_RATE_5_5,
+       WL12XX_CONF_HW_RXTX_RATE_2,
+       WL12XX_CONF_HW_RXTX_RATE_1,
+       WL12XX_CONF_HW_RXTX_RATE_MAX,
+};
+
+static struct wlcore_partition_set wl12xx_ptable[PART_TABLE_LEN] = {
+       [PART_DOWN] = {
+               .mem = {
+                       .start = 0x00000000,
+                       .size  = 0x000177c0
+               },
+               .reg = {
+                       .start = REGISTERS_BASE,
+                       .size  = 0x00008800
+               },
+               .mem2 = {
+                       .start = 0x00000000,
+                       .size  = 0x00000000
+               },
+               .mem3 = {
+                       .start = 0x00000000,
+                       .size  = 0x00000000
+               },
+       },
+
+       [PART_BOOT] = { /* in wl12xx we can use a mix of work and down
+                        * partition here */
+               .mem = {
+                       .start = 0x00040000,
+                       .size  = 0x00014fc0
+               },
+               .reg = {
+                       .start = REGISTERS_BASE,
+                       .size  = 0x00008800
+               },
+               .mem2 = {
+                       .start = 0x00000000,
+                       .size  = 0x00000000
+               },
+               .mem3 = {
+                       .start = 0x00000000,
+                       .size  = 0x00000000
+               },
+       },
+
+       [PART_WORK] = {
+               .mem = {
+                       .start = 0x00040000,
+                       .size  = 0x00014fc0
+               },
+               .reg = {
+                       .start = REGISTERS_BASE,
+                       .size  = 0x0000a000
+               },
+               .mem2 = {
+                       .start = 0x003004f8,
+                       .size  = 0x00000004
+               },
+               .mem3 = {
+                       .start = 0x00040404,
+                       .size  = 0x00000000
+               },
+       },
+
+       [PART_DRPW] = {
+               .mem = {
+                       .start = 0x00040000,
+                       .size  = 0x00014fc0
+               },
+               .reg = {
+                       .start = DRPW_BASE,
+                       .size  = 0x00006000
+               },
+               .mem2 = {
+                       .start = 0x00000000,
+                       .size  = 0x00000000
+               },
+               .mem3 = {
+                       .start = 0x00000000,
+                       .size  = 0x00000000
+               }
+       }
+};
+
+static const int wl12xx_rtable[REG_TABLE_LEN] = {
+       [REG_ECPU_CONTROL]              = WL12XX_REG_ECPU_CONTROL,
+       [REG_INTERRUPT_NO_CLEAR]        = WL12XX_REG_INTERRUPT_NO_CLEAR,
+       [REG_INTERRUPT_ACK]             = WL12XX_REG_INTERRUPT_ACK,
+       [REG_COMMAND_MAILBOX_PTR]       = WL12XX_REG_COMMAND_MAILBOX_PTR,
+       [REG_EVENT_MAILBOX_PTR]         = WL12XX_REG_EVENT_MAILBOX_PTR,
+       [REG_INTERRUPT_TRIG]            = WL12XX_REG_INTERRUPT_TRIG,
+       [REG_INTERRUPT_MASK]            = WL12XX_REG_INTERRUPT_MASK,
+       [REG_PC_ON_RECOVERY]            = WL12XX_SCR_PAD4,
+       [REG_CHIP_ID_B]                 = WL12XX_CHIP_ID_B,
+       [REG_CMD_MBOX_ADDRESS]          = WL12XX_CMD_MBOX_ADDRESS,
+
+       /* data access memory addresses, used with partition translation */
+       [REG_SLV_MEM_DATA]              = WL1271_SLV_MEM_DATA,
+       [REG_SLV_REG_DATA]              = WL1271_SLV_REG_DATA,
+
+       /* raw data access memory addresses */
+       [REG_RAW_FW_STATUS_ADDR]        = FW_STATUS_ADDR,
+};
+
+/* TODO: maybe move to a new header file? */
+#define WL127X_FW_NAME_MULTI   "ti-connectivity/wl127x-fw-4-mr.bin"
+#define WL127X_FW_NAME_SINGLE  "ti-connectivity/wl127x-fw-4-sr.bin"
+#define WL127X_PLT_FW_NAME     "ti-connectivity/wl127x-fw-4-plt.bin"
+
+#define WL128X_FW_NAME_MULTI   "ti-connectivity/wl128x-fw-4-mr.bin"
+#define WL128X_FW_NAME_SINGLE  "ti-connectivity/wl128x-fw-4-sr.bin"
+#define WL128X_PLT_FW_NAME     "ti-connectivity/wl128x-fw-4-plt.bin"
+
+static void wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len)
+{
+       if (wl->chip.id != CHIP_ID_1283_PG20) {
+               struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map;
+               struct wl1271_rx_mem_pool_addr rx_mem_addr;
+
+               /*
+                * 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.
+                */
+               u32 mem_block = rx_desc & RX_MEM_BLOCK_MASK;
+
+               rx_mem_addr.addr = (mem_block << 8) +
+                       le32_to_cpu(wl_mem_map->packet_memory_pool_start);
+
+               rx_mem_addr.addr_extra = rx_mem_addr.addr + 4;
+
+               wl1271_write(wl, WL1271_SLV_REG_DATA,
+                            &rx_mem_addr, sizeof(rx_mem_addr), false);
+       }
+}
+
+static int wl12xx_identify_chip(struct wl1271 *wl)
+{
+       int ret = 0;
+
+       switch (wl->chip.id) {
+       case CHIP_ID_1271_PG10:
+               wl1271_warning("chip id 0x%x (1271 PG10) support is obsolete",
+                              wl->chip.id);
+
+               /* clear the alignment quirk, since we don't support it */
+               wl->quirks &= ~WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN;
+
+               wl->quirks |= WLCORE_QUIRK_LEGACY_NVS;
+               wl->sr_fw_name = WL127X_FW_NAME_SINGLE;
+               wl->mr_fw_name = WL127X_FW_NAME_MULTI;
+               memcpy(&wl->conf.mem, &wl12xx_default_priv_conf.mem_wl127x,
+                      sizeof(wl->conf.mem));
+
+               /* read data preparation is only needed by wl127x */
+               wl->ops->prepare_read = wl127x_prepare_read;
+
+               break;
+
+       case CHIP_ID_1271_PG20:
+               wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)",
+                            wl->chip.id);
+
+               /* clear the alignment quirk, since we don't support it */
+               wl->quirks &= ~WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN;
+
+               wl->quirks |= WLCORE_QUIRK_LEGACY_NVS;
+               wl->plt_fw_name = WL127X_PLT_FW_NAME;
+               wl->sr_fw_name = WL127X_FW_NAME_SINGLE;
+               wl->mr_fw_name = WL127X_FW_NAME_MULTI;
+               memcpy(&wl->conf.mem, &wl12xx_default_priv_conf.mem_wl127x,
+                      sizeof(wl->conf.mem));
+
+               /* read data preparation is only needed by wl127x */
+               wl->ops->prepare_read = wl127x_prepare_read;
+
+               break;
+
+       case CHIP_ID_1283_PG20:
+               wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1283 PG20)",
+                            wl->chip.id);
+               wl->plt_fw_name = WL128X_PLT_FW_NAME;
+               wl->sr_fw_name = WL128X_FW_NAME_SINGLE;
+               wl->mr_fw_name = WL128X_FW_NAME_MULTI;
+               break;
+       case CHIP_ID_1283_PG10:
+       default:
+               wl1271_warning("unsupported chip id: 0x%x", wl->chip.id);
+               ret = -ENODEV;
+               goto out;
+       }
+
+out:
+       return ret;
+}
+
+static void wl12xx_top_reg_write(struct wl1271 *wl, int addr, u16 val)
+{
+       /* write address >> 1 + 0x30000 to OCP_POR_CTR */
+       addr = (addr >> 1) + 0x30000;
+       wl1271_write32(wl, WL12XX_OCP_POR_CTR, addr);
+
+       /* write value to OCP_POR_WDATA */
+       wl1271_write32(wl, WL12XX_OCP_DATA_WRITE, val);
+
+       /* write 1 to OCP_CMD */
+       wl1271_write32(wl, WL12XX_OCP_CMD, OCP_CMD_WRITE);
+}
+
+static u16 wl12xx_top_reg_read(struct wl1271 *wl, int addr)
+{
+       u32 val;
+       int timeout = OCP_CMD_LOOP;
+
+       /* write address >> 1 + 0x30000 to OCP_POR_CTR */
+       addr = (addr >> 1) + 0x30000;
+       wl1271_write32(wl, WL12XX_OCP_POR_CTR, addr);
+
+       /* write 2 to OCP_CMD */
+       wl1271_write32(wl, WL12XX_OCP_CMD, OCP_CMD_READ);
+
+       /* poll for data ready */
+       do {
+               val = wl1271_read32(wl, WL12XX_OCP_DATA_READ);
+       } while (!(val & OCP_READY_MASK) && --timeout);
+
+       if (!timeout) {
+               wl1271_warning("Top register access timed out.");
+               return 0xffff;
+       }
+
+       /* check data status and return if OK */
+       if ((val & OCP_STATUS_MASK) == OCP_STATUS_OK)
+               return val & 0xffff;
+       else {
+               wl1271_warning("Top register access returned error.");
+               return 0xffff;
+       }
+}
+
+static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl)
+{
+       u16 spare_reg;
+
+       /* Mask bits [2] & [8:4] in the sys_clk_cfg register */
+       spare_reg = wl12xx_top_reg_read(wl, WL_SPARE_REG);
+       if (spare_reg == 0xFFFF)
+               return -EFAULT;
+       spare_reg |= (BIT(3) | BIT(5) | BIT(6));
+       wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg);
+
+       /* Enable FREF_CLK_REQ & mux MCS and coex PLLs to FREF */
+       wl12xx_top_reg_write(wl, SYS_CLK_CFG_REG,
+                            WL_CLK_REQ_TYPE_PG2 | MCS_PLL_CLK_SEL_FREF);
+
+       /* Delay execution for 15msec, to let the HW settle */
+       mdelay(15);
+
+       return 0;
+}
+
+static bool wl128x_is_tcxo_valid(struct wl1271 *wl)
+{
+       u16 tcxo_detection;
+
+       tcxo_detection = wl12xx_top_reg_read(wl, TCXO_CLK_DETECT_REG);
+       if (tcxo_detection & TCXO_DET_FAILED)
+               return false;
+
+       return true;
+}
+
+static bool wl128x_is_fref_valid(struct wl1271 *wl)
+{
+       u16 fref_detection;
+
+       fref_detection = wl12xx_top_reg_read(wl, FREF_CLK_DETECT_REG);
+       if (fref_detection & FREF_CLK_DETECT_FAIL)
+               return false;
+
+       return true;
+}
+
+static int wl128x_manually_configure_mcs_pll(struct wl1271 *wl)
+{
+       wl12xx_top_reg_write(wl, MCS_PLL_M_REG, MCS_PLL_M_REG_VAL);
+       wl12xx_top_reg_write(wl, MCS_PLL_N_REG, MCS_PLL_N_REG_VAL);
+       wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG, MCS_PLL_CONFIG_REG_VAL);
+
+       return 0;
+}
+
+static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk)
+{
+       u16 spare_reg;
+       u16 pll_config;
+       u8 input_freq;
+
+       /* Mask bits [3:1] in the sys_clk_cfg register */
+       spare_reg = wl12xx_top_reg_read(wl, WL_SPARE_REG);
+       if (spare_reg == 0xFFFF)
+               return -EFAULT;
+       spare_reg |= BIT(2);
+       wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg);
+
+       /* Handle special cases of the TCXO clock */
+       if (wl->tcxo_clock == WL12XX_TCXOCLOCK_16_8 ||
+           wl->tcxo_clock == WL12XX_TCXOCLOCK_33_6)
+               return wl128x_manually_configure_mcs_pll(wl);
+
+       /* Set the input frequency according to the selected clock source */
+       input_freq = (clk & 1) + 1;
+
+       pll_config = wl12xx_top_reg_read(wl, MCS_PLL_CONFIG_REG);
+       if (pll_config == 0xFFFF)
+               return -EFAULT;
+       pll_config |= (input_freq << MCS_SEL_IN_FREQ_SHIFT);
+       pll_config |= MCS_PLL_ENABLE_HP;
+       wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG, pll_config);
+
+       return 0;
+}
+
+/*
+ * WL128x has two clocks input - TCXO and FREF.
+ * TCXO is the main clock of the device, while FREF is used to sync
+ * between the GPS and the cellular modem.
+ * In cases where TCXO is 32.736MHz or 16.368MHz, the FREF will be used
+ * as the WLAN/BT main clock.
+ */
+static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock)
+{
+       u16 sys_clk_cfg;
+
+       /* For XTAL-only modes, FREF will be used after switching from TCXO */
+       if (wl->ref_clock == WL12XX_REFCLOCK_26_XTAL ||
+           wl->ref_clock == WL12XX_REFCLOCK_38_XTAL) {
+               if (!wl128x_switch_tcxo_to_fref(wl))
+                       return -EINVAL;
+               goto fref_clk;
+       }
+
+       /* Query the HW, to determine which clock source we should use */
+       sys_clk_cfg = wl12xx_top_reg_read(wl, SYS_CLK_CFG_REG);
+       if (sys_clk_cfg == 0xFFFF)
+               return -EINVAL;
+       if (sys_clk_cfg & PRCM_CM_EN_MUX_WLAN_FREF)
+               goto fref_clk;
+
+       /* If TCXO is either 32.736MHz or 16.368MHz, switch to FREF */
+       if (wl->tcxo_clock == WL12XX_TCXOCLOCK_16_368 ||
+           wl->tcxo_clock == WL12XX_TCXOCLOCK_32_736) {
+               if (!wl128x_switch_tcxo_to_fref(wl))
+                       return -EINVAL;
+               goto fref_clk;
+       }
+
+       /* TCXO clock is selected */
+       if (!wl128x_is_tcxo_valid(wl))
+               return -EINVAL;
+       *selected_clock = wl->tcxo_clock;
+       goto config_mcs_pll;
+
+fref_clk:
+       /* FREF clock is selected */
+       if (!wl128x_is_fref_valid(wl))
+               return -EINVAL;
+       *selected_clock = wl->ref_clock;
+
+config_mcs_pll:
+       return wl128x_configure_mcs_pll(wl, *selected_clock);
+}
+
+static int wl127x_boot_clk(struct wl1271 *wl)
+{
+       u32 pause;
+       u32 clk;
+
+       if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3)
+               wl->quirks |= WLCORE_QUIRK_END_OF_TRANSACTION;
+
+       if (wl->ref_clock == CONF_REF_CLK_19_2_E ||
+           wl->ref_clock == CONF_REF_CLK_38_4_E ||
+           wl->ref_clock == CONF_REF_CLK_38_4_M_XTAL)
+               /* ref clk: 19.2/38.4/38.4-XTAL */
+               clk = 0x3;
+       else if (wl->ref_clock == CONF_REF_CLK_26_E ||
+                wl->ref_clock == CONF_REF_CLK_52_E)
+               /* ref clk: 26/52 */
+               clk = 0x5;
+       else
+               return -EINVAL;
+
+       if (wl->ref_clock != CONF_REF_CLK_19_2_E) {
+               u16 val;
+               /* Set clock type (open drain) */
+               val = wl12xx_top_reg_read(wl, OCP_REG_CLK_TYPE);
+               val &= FREF_CLK_TYPE_BITS;
+               wl12xx_top_reg_write(wl, OCP_REG_CLK_TYPE, val);
+
+               /* Set clock pull mode (no pull) */
+               val = wl12xx_top_reg_read(wl, OCP_REG_CLK_PULL);
+               val |= NO_PULL;
+               wl12xx_top_reg_write(wl, OCP_REG_CLK_PULL, val);
+       } else {
+               u16 val;
+               /* Set clock polarity */
+               val = wl12xx_top_reg_read(wl, OCP_REG_CLK_POLARITY);
+               val &= FREF_CLK_POLARITY_BITS;
+               val |= CLK_REQ_OUTN_SEL;
+               wl12xx_top_reg_write(wl, OCP_REG_CLK_POLARITY, val);
+       }
+
+       wl1271_write32(wl, WL12XX_PLL_PARAMETERS, clk);
+
+       pause = wl1271_read32(wl, WL12XX_PLL_PARAMETERS);
+
+       wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause);
+
+       pause &= ~(WU_COUNTER_PAUSE_VAL);
+       pause |= WU_COUNTER_PAUSE_VAL;
+       wl1271_write32(wl, WL12XX_WU_COUNTER_PAUSE, pause);
+
+       return 0;
+}
+
+static int wl1271_boot_soft_reset(struct wl1271 *wl)
+{
+       unsigned long timeout;
+       u32 boot_data;
+
+       /* perform soft reset */
+       wl1271_write32(wl, WL12XX_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT);
+
+       /* SOFT_RESET is self clearing */
+       timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME);
+       while (1) {
+               boot_data = wl1271_read32(wl, WL12XX_SLV_SOFT_RESET);
+               wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data);
+               if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0)
+                       break;
+
+               if (time_after(jiffies, timeout)) {
+                       /* 1.2 check pWhalBus->uSelfClearTime if the
+                        * timeout was reached */
+                       wl1271_error("soft reset timeout");
+                       return -1;
+               }
+
+               udelay(SOFT_RESET_STALL_TIME);
+       }
+
+       /* disable Rx/Tx */
+       wl1271_write32(wl, WL12XX_ENABLE, 0x0);
+
+       /* disable auto calibration on start*/
+       wl1271_write32(wl, WL12XX_SPARE_A2, 0xffff);
+
+       return 0;
+}
+
+static int wl12xx_pre_boot(struct wl1271 *wl)
+{
+       int ret = 0;
+       u32 clk;
+       int selected_clock = -1;
+
+       if (wl->chip.id == CHIP_ID_1283_PG20) {
+               ret = wl128x_boot_clk(wl, &selected_clock);
+               if (ret < 0)
+                       goto out;
+       } else {
+               ret = wl127x_boot_clk(wl);
+               if (ret < 0)
+                       goto out;
+       }
+
+       /* Continue the ELP wake up sequence */
+       wl1271_write32(wl, WL12XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
+       udelay(500);
+
+       wlcore_set_partition(wl, &wl->ptable[PART_DRPW]);
+
+       /* Read-modify-write DRPW_SCRATCH_START register (see next state)
+          to be used by DRPw FW. The RTRIM value will be added by the FW
+          before taking DRPw out of reset */
+
+       clk = wl1271_read32(wl, WL12XX_DRPW_SCRATCH_START);
+
+       wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk);
+
+       if (wl->chip.id == CHIP_ID_1283_PG20)
+               clk |= ((selected_clock & 0x3) << 1) << 4;
+       else
+               clk |= (wl->ref_clock << 1) << 4;
+
+       wl1271_write32(wl, WL12XX_DRPW_SCRATCH_START, clk);
+
+       wlcore_set_partition(wl, &wl->ptable[PART_WORK]);
+
+       /* Disable interrupts */
+       wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
+
+       ret = wl1271_boot_soft_reset(wl);
+       if (ret < 0)
+               goto out;
+
+out:
+       return ret;
+}
+
+static void wl12xx_pre_upload(struct wl1271 *wl)
+{
+       u32 tmp;
+
+       /* write firmware's last address (ie. it's length) to
+        * ACX_EEPROMLESS_IND_REG */
+       wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG");
+
+       wl1271_write32(wl, WL12XX_EEPROMLESS_IND, WL12XX_EEPROMLESS_IND);
+
+       tmp = wlcore_read_reg(wl, REG_CHIP_ID_B);
+
+       wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp);
+
+       /* 6. read the EEPROM parameters */
+       tmp = wl1271_read32(wl, WL12XX_SCR_PAD2);
+
+       /* WL1271: The reference driver skips steps 7 to 10 (jumps directly
+        * to upload_fw) */
+
+       if (wl->chip.id == CHIP_ID_1283_PG20)
+               wl12xx_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA);
+}
+
+static void wl12xx_enable_interrupts(struct wl1271 *wl)
+{
+       u32 polarity;
+
+       polarity = wl12xx_top_reg_read(wl, OCP_REG_POLARITY);
+
+       /* We use HIGH polarity, so unset the LOW bit */
+       polarity &= ~POLARITY_LOW;
+       wl12xx_top_reg_write(wl, OCP_REG_POLARITY, polarity);
+
+       wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_ALL_EVENTS_VECTOR);
+
+       wlcore_enable_interrupts(wl);
+       wlcore_write_reg(wl, REG_INTERRUPT_MASK,
+                        WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
+
+       wl1271_write32(wl, WL12XX_HI_CFG, HI_CFG_DEF_VAL);
+}
+
+static int wl12xx_boot(struct wl1271 *wl)
+{
+       int ret;
+
+       ret = wl12xx_pre_boot(wl);
+       if (ret < 0)
+               goto out;
+
+       ret = wlcore_boot_upload_nvs(wl);
+       if (ret < 0)
+               goto out;
+
+       wl12xx_pre_upload(wl);
+
+       ret = wlcore_boot_upload_firmware(wl);
+       if (ret < 0)
+               goto out;
+
+       ret = wlcore_boot_run_firmware(wl);
+       if (ret < 0)
+               goto out;
+
+       wl12xx_enable_interrupts(wl);
+
+out:
+       return ret;
+}
+
+static void wl12xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr,
+                              void *buf, size_t len)
+{
+       wl1271_write(wl, cmd_box_addr, buf, len, false);
+       wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_CMD);
+}
+
+static void wl12xx_ack_event(struct wl1271 *wl)
+{
+       wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_EVENT_ACK);
+}
+
+static u32 wl12xx_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks)
+{
+       u32 blk_size = WL12XX_TX_HW_BLOCK_SIZE;
+       u32 align_len = wlcore_calc_packet_alignment(wl, len);
+
+       return (align_len + blk_size - 1) / blk_size + spare_blks;
+}
+
+static void
+wl12xx_set_tx_desc_blocks(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc,
+                         u32 blks, u32 spare_blks)
+{
+       if (wl->chip.id == CHIP_ID_1283_PG20) {
+               desc->wl128x_mem.total_mem_blocks = blks;
+       } else {
+               desc->wl127x_mem.extra_blocks = spare_blks;
+               desc->wl127x_mem.total_mem_blocks = blks;
+       }
+}
+
+static void
+wl12xx_set_tx_desc_data_len(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc,
+                           struct sk_buff *skb)
+{
+       u32 aligned_len = wlcore_calc_packet_alignment(wl, skb->len);
+
+       if (wl->chip.id == CHIP_ID_1283_PG20) {
+               desc->wl128x_mem.extra_bytes = aligned_len - skb->len;
+               desc->length = cpu_to_le16(aligned_len >> 2);
+
+               wl1271_debug(DEBUG_TX,
+                            "tx_fill_hdr: hlid: %d len: %d life: %d mem: %d extra: %d",
+                            desc->hlid,
+                            le16_to_cpu(desc->length),
+                            le16_to_cpu(desc->life_time),
+                            desc->wl128x_mem.total_mem_blocks,
+                            desc->wl128x_mem.extra_bytes);
+       } else {
+               /* calculate number of padding bytes */
+               int pad = aligned_len - skb->len;
+               desc->tx_attr |=
+                       cpu_to_le16(pad << TX_HW_ATTR_OFST_LAST_WORD_PAD);
+
+               /* Store the aligned length in terms of words */
+               desc->length = cpu_to_le16(aligned_len >> 2);
+
+               wl1271_debug(DEBUG_TX,
+                            "tx_fill_hdr: pad: %d hlid: %d len: %d life: %d mem: %d",
+                            pad, desc->hlid,
+                            le16_to_cpu(desc->length),
+                            le16_to_cpu(desc->life_time),
+                            desc->wl127x_mem.total_mem_blocks);
+       }
+}
+
+static enum wl_rx_buf_align
+wl12xx_get_rx_buf_align(struct wl1271 *wl, u32 rx_desc)
+{
+       if (rx_desc & RX_BUF_UNALIGNED_PAYLOAD)
+               return WLCORE_RX_BUF_UNALIGNED;
+
+       return WLCORE_RX_BUF_ALIGNED;
+}
+
+static u32 wl12xx_get_rx_packet_len(struct wl1271 *wl, void *rx_data,
+                                   u32 data_len)
+{
+       struct wl1271_rx_descriptor *desc = rx_data;
+
+       /* invalid packet */
+       if (data_len < sizeof(*desc) ||
+           data_len < sizeof(*desc) + desc->pad_len)
+               return 0;
+
+       return data_len - sizeof(*desc) - desc->pad_len;
+}
+
+static void wl12xx_tx_delayed_compl(struct wl1271 *wl)
+{
+       if (wl->fw_status->tx_results_counter == (wl->tx_results_count & 0xff))
+               return;
+
+       wl1271_tx_complete(wl);
+}
+
+static int wl12xx_hw_init(struct wl1271 *wl)
+{
+       int ret;
+
+       if (wl->chip.id == CHIP_ID_1283_PG20) {
+               u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE;
+
+               ret = wl128x_cmd_general_parms(wl);
+               if (ret < 0)
+                       goto out;
+               ret = wl128x_cmd_radio_parms(wl);
+               if (ret < 0)
+                       goto out;
+
+               if (wl->quirks & WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN)
+                       /* 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;
+       } else {
+               ret = wl1271_cmd_general_parms(wl);
+               if (ret < 0)
+                       goto out;
+               ret = wl1271_cmd_radio_parms(wl);
+               if (ret < 0)
+                       goto out;
+               ret = wl1271_cmd_ext_radio_parms(wl);
+               if (ret < 0)
+                       goto out;
+       }
+out:
+       return ret;
+}
+
+static u32 wl12xx_sta_get_ap_rate_mask(struct wl1271 *wl,
+                                      struct wl12xx_vif *wlvif)
+{
+       return wlvif->rate_set;
+}
+
+static int wl12xx_identify_fw(struct wl1271 *wl)
+{
+       unsigned int *fw_ver = wl->chip.fw_ver;
+
+       /* Only new station firmwares support routing fw logs to the host */
+       if ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) &&
+           (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_FWLOG_STA_MIN))
+               wl->quirks |= WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED;
+
+       /* This feature is not yet supported for AP mode */
+       if (fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP)
+               wl->quirks |= WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED;
+
+       return 0;
+}
+
+static void wl12xx_conf_init(struct wl1271 *wl)
+{
+       struct wl12xx_priv *priv = wl->priv;
+
+       /* apply driver default configuration */
+       memcpy(&wl->conf, &wl12xx_conf, sizeof(wl12xx_conf));
+
+       /* apply default private configuration */
+       memcpy(&priv->conf, &wl12xx_default_priv_conf, sizeof(priv->conf));
+}
+
+static bool wl12xx_mac_in_fuse(struct wl1271 *wl)
+{
+       bool supported = false;
+       u8 major, minor;
+
+       if (wl->chip.id == CHIP_ID_1283_PG20) {
+               major = WL128X_PG_GET_MAJOR(wl->hw_pg_ver);
+               minor = WL128X_PG_GET_MINOR(wl->hw_pg_ver);
+
+               /* in wl128x we have the MAC address if the PG is >= (2, 1) */
+               if (major > 2 || (major == 2 && minor >= 1))
+                       supported = true;
+       } else {
+               major = WL127X_PG_GET_MAJOR(wl->hw_pg_ver);
+               minor = WL127X_PG_GET_MINOR(wl->hw_pg_ver);
+
+               /* in wl127x we have the MAC address if the PG is >= (3, 1) */
+               if (major == 3 && minor >= 1)
+                       supported = true;
+       }
+
+       wl1271_debug(DEBUG_PROBE,
+                    "PG Ver major = %d minor = %d, MAC %s present",
+                    major, minor, supported ? "is" : "is not");
+
+       return supported;
+}
+
+static void wl12xx_get_fuse_mac(struct wl1271 *wl)
+{
+       u32 mac1, mac2;
+
+       wlcore_set_partition(wl, &wl->ptable[PART_DRPW]);
+
+       mac1 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_1);
+       mac2 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_2);
+
+       /* these are the two parts of the BD_ADDR */
+       wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) +
+               ((mac1 & 0xff000000) >> 24);
+       wl->fuse_nic_addr = mac1 & 0xffffff;
+
+       wlcore_set_partition(wl, &wl->ptable[PART_DOWN]);
+}
+
+static s8 wl12xx_get_pg_ver(struct wl1271 *wl)
+{
+       u32 die_info;
+
+       if (wl->chip.id == CHIP_ID_1283_PG20)
+               die_info = wl12xx_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1);
+       else
+               die_info = wl12xx_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1);
+
+       return (s8) (die_info & PG_VER_MASK) >> PG_VER_OFFSET;
+}
+
+static void wl12xx_get_mac(struct wl1271 *wl)
+{
+       if (wl12xx_mac_in_fuse(wl))
+               wl12xx_get_fuse_mac(wl);
+}
+
+static struct wlcore_ops wl12xx_ops = {
+       .identify_chip          = wl12xx_identify_chip,
+       .identify_fw            = wl12xx_identify_fw,
+       .boot                   = wl12xx_boot,
+       .trigger_cmd            = wl12xx_trigger_cmd,
+       .ack_event              = wl12xx_ack_event,
+       .calc_tx_blocks         = wl12xx_calc_tx_blocks,
+       .set_tx_desc_blocks     = wl12xx_set_tx_desc_blocks,
+       .set_tx_desc_data_len   = wl12xx_set_tx_desc_data_len,
+       .get_rx_buf_align       = wl12xx_get_rx_buf_align,
+       .get_rx_packet_len      = wl12xx_get_rx_packet_len,
+       .tx_immediate_compl     = NULL,
+       .tx_delayed_compl       = wl12xx_tx_delayed_compl,
+       .hw_init                = wl12xx_hw_init,
+       .init_vif               = NULL,
+       .sta_get_ap_rate_mask   = wl12xx_sta_get_ap_rate_mask,
+       .get_pg_ver             = wl12xx_get_pg_ver,
+       .get_mac                = wl12xx_get_mac,
+};
+
+static struct ieee80211_sta_ht_cap wl12xx_ht_cap = {
+       .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 |
+              (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT),
+       .ht_supported = true,
+       .ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K,
+       .ampdu_density = IEEE80211_HT_MPDU_DENSITY_8,
+       .mcs = {
+               .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
+               .rx_highest = cpu_to_le16(72),
+               .tx_params = IEEE80211_HT_MCS_TX_DEFINED,
+               },
+};
+
+static int __devinit wl12xx_probe(struct platform_device *pdev)
+{
+       struct wl1271 *wl;
+       struct ieee80211_hw *hw;
+       struct wl12xx_priv *priv;
+
+       hw = wlcore_alloc_hw(sizeof(*priv));
+       if (IS_ERR(hw)) {
+               wl1271_error("can't allocate hw");
+               return PTR_ERR(hw);
+       }
+
+       wl = hw->priv;
+       wl->ops = &wl12xx_ops;
+       wl->ptable = wl12xx_ptable;
+       wl->rtable = wl12xx_rtable;
+       wl->num_tx_desc = 16;
+       wl->normal_tx_spare = WL12XX_TX_HW_BLOCK_SPARE_DEFAULT;
+       wl->gem_tx_spare = WL12XX_TX_HW_BLOCK_GEM_SPARE;
+       wl->band_rate_to_idx = wl12xx_band_rate_to_idx;
+       wl->hw_tx_rate_tbl_size = WL12XX_CONF_HW_RXTX_RATE_MAX;
+       wl->hw_min_ht_rate = WL12XX_CONF_HW_RXTX_RATE_MCS0;
+       wl->fw_status_priv_len = 0;
+       memcpy(&wl->ht_cap, &wl12xx_ht_cap, sizeof(wl12xx_ht_cap));
+       wl12xx_conf_init(wl);
+
+       return wlcore_probe(wl, pdev);
+}
+
+static const struct platform_device_id wl12xx_id_table[] __devinitconst = {
+       { "wl12xx", 0 },
+       {  } /* Terminating Entry */
+};
+MODULE_DEVICE_TABLE(platform, wl12xx_id_table);
+
+static struct platform_driver wl12xx_driver = {
+       .probe          = wl12xx_probe,
+       .remove         = __devexit_p(wlcore_remove),
+       .id_table       = wl12xx_id_table,
+       .driver = {
+               .name   = "wl12xx_driver",
+               .owner  = THIS_MODULE,
+       }
+};
+
+static int __init wl12xx_init(void)
+{
+       return platform_driver_register(&wl12xx_driver);
+}
+module_init(wl12xx_init);
+
+static void __exit wl12xx_exit(void)
+{
+       platform_driver_unregister(&wl12xx_driver);
+}
+module_exit(wl12xx_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
+MODULE_FIRMWARE(WL127X_FW_NAME_SINGLE);
+MODULE_FIRMWARE(WL127X_FW_NAME_MULTI);
+MODULE_FIRMWARE(WL127X_PLT_FW_NAME);
+MODULE_FIRMWARE(WL128X_FW_NAME_SINGLE);
+MODULE_FIRMWARE(WL128X_FW_NAME_MULTI);
+MODULE_FIRMWARE(WL128X_PLT_FW_NAME);
similarity index 71%
rename from drivers/net/wireless/wl12xx/reg.h
rename to drivers/net/wireless/ti/wl12xx/reg.h
index 340db324bc26016933b68afe8abb031d2302513d..79ede02e25870d862387a96dd6f15ee47531079e 100644 (file)
 #define REGISTERS_DOWN_SIZE 0x00008800
 #define REGISTERS_WORK_SIZE 0x0000b000
 
-#define HW_ACCESS_ELP_CTRL_REG_ADDR         0x1FFFC
 #define FW_STATUS_ADDR                      (0x14FC0 + 0xA000)
 
-/* ELP register commands */
-#define ELPCTRL_WAKE_UP             0x1
-#define ELPCTRL_WAKE_UP_WLAN_READY  0x5
-#define ELPCTRL_SLEEP               0x0
-/* ELP WLAN_READY bit */
-#define ELPCTRL_WLAN_READY          0x2
-
 /*===============================================
    Host Software Reset - 32bit RW
  ------------------------------------------
     (not self-clearing), the Wlan hardware
     exits the software reset state.
 ===============================================*/
-#define ACX_REG_SLV_SOFT_RESET         (REGISTERS_BASE + 0x0000)
+#define WL12XX_SLV_SOFT_RESET          (REGISTERS_BASE + 0x0000)
 
 #define WL1271_SLV_REG_DATA            (REGISTERS_BASE + 0x0008)
 #define WL1271_SLV_REG_ADATA           (REGISTERS_BASE + 0x000c)
 #define WL1271_SLV_MEM_DATA            (REGISTERS_BASE + 0x0018)
 
-#define ACX_REG_INTERRUPT_TRIG         (REGISTERS_BASE + 0x0474)
-#define ACX_REG_INTERRUPT_TRIG_H       (REGISTERS_BASE + 0x0478)
+#define WL12XX_REG_INTERRUPT_TRIG         (REGISTERS_BASE + 0x0474)
+#define WL12XX_REG_INTERRUPT_TRIG_H       (REGISTERS_BASE + 0x0478)
 
 /*=============================================
   Host Interrupt Mask Register - 32bit (RW)
@@ -94,7 +86,7 @@
  21-                   -
  Default: 0x0001
 *==============================================*/
-#define ACX_REG_INTERRUPT_MASK         (REGISTERS_BASE + 0x04DC)
+#define WL12XX_REG_INTERRUPT_MASK         (REGISTERS_BASE + 0x04DC)
 
 /*=============================================
   Host Interrupt Mask Set 16bit, (Write only)
  Reading this register doesn't
  effect its content.
 =============================================*/
-#define ACX_REG_INTERRUPT_NO_CLEAR     (REGISTERS_BASE + 0x04E8)
+#define WL12XX_REG_INTERRUPT_NO_CLEAR     (REGISTERS_BASE + 0x04E8)
 
 /*=============================================
   Host Interrupt Status Clear on Read  Register
  HINT_STS_ND registers, thus making the
  assotiated interrupt inactive. (0-no effect)
 ==============================================*/
-#define ACX_REG_INTERRUPT_ACK          (REGISTERS_BASE + 0x04F0)
+#define WL12XX_REG_INTERRUPT_ACK          (REGISTERS_BASE + 0x04F0)
 
-#define RX_DRIVER_COUNTER_ADDRESS      (REGISTERS_BASE + 0x0538)
+#define WL12XX_REG_RX_DRIVER_COUNTER   (REGISTERS_BASE + 0x0538)
 
 /* Device Configuration registers*/
 #define SOR_CFG                        (REGISTERS_BASE + 0x0800)
  1 halt eCPU
  0 enable eCPU
  ===============================================*/
-#define ACX_REG_ECPU_CONTROL           (REGISTERS_BASE + 0x0804)
+#define WL12XX_REG_ECPU_CONTROL           (REGISTERS_BASE + 0x0804)
 
-#define HI_CFG                         (REGISTERS_BASE + 0x0808)
+#define WL12XX_HI_CFG                  (REGISTERS_BASE + 0x0808)
 
 /*===============================================
  EEPROM Burst Read Start  - 32bit RW
 *================================================*/
 #define ACX_REG_EE_START               (REGISTERS_BASE + 0x080C)
 
-#define OCP_POR_CTR                    (REGISTERS_BASE + 0x09B4)
-#define OCP_DATA_WRITE                 (REGISTERS_BASE + 0x09B8)
-#define OCP_DATA_READ                  (REGISTERS_BASE + 0x09BC)
-#define OCP_CMD                        (REGISTERS_BASE + 0x09C0)
-
-#define WL1271_HOST_WR_ACCESS          (REGISTERS_BASE + 0x09F8)
+#define WL12XX_OCP_POR_CTR             (REGISTERS_BASE + 0x09B4)
+#define WL12XX_OCP_DATA_WRITE          (REGISTERS_BASE + 0x09B8)
+#define WL12XX_OCP_DATA_READ           (REGISTERS_BASE + 0x09BC)
+#define WL12XX_OCP_CMD                 (REGISTERS_BASE + 0x09C0)
 
-#define CHIP_ID_B                      (REGISTERS_BASE + 0x5674)
+#define WL12XX_HOST_WR_ACCESS          (REGISTERS_BASE + 0x09F8)
 
-#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 WL12XX_CHIP_ID_B               (REGISTERS_BASE + 0x5674)
 
-#define ENABLE                         (REGISTERS_BASE + 0x5450)
+#define WL12XX_ENABLE                  (REGISTERS_BASE + 0x5450)
 
 /* Power Management registers */
-#define ELP_CFG_MODE                   (REGISTERS_BASE + 0x5804)
-#define ELP_CMD                        (REGISTERS_BASE + 0x5808)
-#define PLL_CAL_TIME                   (REGISTERS_BASE + 0x5810)
-#define CLK_REQ_TIME                   (REGISTERS_BASE + 0x5814)
-#define CLK_BUF_TIME                   (REGISTERS_BASE + 0x5818)
+#define WL12XX_ELP_CFG_MODE            (REGISTERS_BASE + 0x5804)
+#define WL12XX_ELP_CMD                 (REGISTERS_BASE + 0x5808)
+#define WL12XX_PLL_CAL_TIME            (REGISTERS_BASE + 0x5810)
+#define WL12XX_CLK_REQ_TIME            (REGISTERS_BASE + 0x5814)
+#define WL12XX_CLK_BUF_TIME            (REGISTERS_BASE + 0x5818)
 
-#define CFG_PLL_SYNC_CNT               (REGISTERS_BASE + 0x5820)
+#define WL12XX_CFG_PLL_SYNC_CNT                (REGISTERS_BASE + 0x5820)
 
 /* Scratch Pad registers*/
-#define SCR_PAD0                       (REGISTERS_BASE + 0x5608)
-#define SCR_PAD1                       (REGISTERS_BASE + 0x560C)
-#define SCR_PAD2                       (REGISTERS_BASE + 0x5610)
-#define SCR_PAD3                       (REGISTERS_BASE + 0x5614)
-#define SCR_PAD4                       (REGISTERS_BASE + 0x5618)
-#define SCR_PAD4_SET                   (REGISTERS_BASE + 0x561C)
-#define SCR_PAD4_CLR                   (REGISTERS_BASE + 0x5620)
-#define SCR_PAD5                       (REGISTERS_BASE + 0x5624)
-#define SCR_PAD5_SET                   (REGISTERS_BASE + 0x5628)
-#define SCR_PAD5_CLR                   (REGISTERS_BASE + 0x562C)
-#define SCR_PAD6                       (REGISTERS_BASE + 0x5630)
-#define SCR_PAD7                       (REGISTERS_BASE + 0x5634)
-#define SCR_PAD8                       (REGISTERS_BASE + 0x5638)
-#define SCR_PAD9                       (REGISTERS_BASE + 0x563C)
+#define WL12XX_SCR_PAD0                        (REGISTERS_BASE + 0x5608)
+#define WL12XX_SCR_PAD1                        (REGISTERS_BASE + 0x560C)
+#define WL12XX_SCR_PAD2                        (REGISTERS_BASE + 0x5610)
+#define WL12XX_SCR_PAD3                        (REGISTERS_BASE + 0x5614)
+#define WL12XX_SCR_PAD4                        (REGISTERS_BASE + 0x5618)
+#define WL12XX_SCR_PAD4_SET            (REGISTERS_BASE + 0x561C)
+#define WL12XX_SCR_PAD4_CLR            (REGISTERS_BASE + 0x5620)
+#define WL12XX_SCR_PAD5                        (REGISTERS_BASE + 0x5624)
+#define WL12XX_SCR_PAD5_SET            (REGISTERS_BASE + 0x5628)
+#define WL12XX_SCR_PAD5_CLR            (REGISTERS_BASE + 0x562C)
+#define WL12XX_SCR_PAD6                        (REGISTERS_BASE + 0x5630)
+#define WL12XX_SCR_PAD7                        (REGISTERS_BASE + 0x5634)
+#define WL12XX_SCR_PAD8                        (REGISTERS_BASE + 0x5638)
+#define WL12XX_SCR_PAD9                        (REGISTERS_BASE + 0x563C)
 
 /* Spare registers*/
-#define SPARE_A1                       (REGISTERS_BASE + 0x0994)
-#define SPARE_A2                       (REGISTERS_BASE + 0x0998)
-#define SPARE_A3                       (REGISTERS_BASE + 0x099C)
-#define SPARE_A4                       (REGISTERS_BASE + 0x09A0)
-#define SPARE_A5                       (REGISTERS_BASE + 0x09A4)
-#define SPARE_A6                       (REGISTERS_BASE + 0x09A8)
-#define SPARE_A7                       (REGISTERS_BASE + 0x09AC)
-#define SPARE_A8                       (REGISTERS_BASE + 0x09B0)
-#define SPARE_B1                       (REGISTERS_BASE + 0x5420)
-#define SPARE_B2                       (REGISTERS_BASE + 0x5424)
-#define SPARE_B3                       (REGISTERS_BASE + 0x5428)
-#define SPARE_B4                       (REGISTERS_BASE + 0x542C)
-#define SPARE_B5                       (REGISTERS_BASE + 0x5430)
-#define SPARE_B6                       (REGISTERS_BASE + 0x5434)
-#define SPARE_B7                       (REGISTERS_BASE + 0x5438)
-#define SPARE_B8                       (REGISTERS_BASE + 0x543C)
-
-#define PLL_PARAMETERS                 (REGISTERS_BASE + 0x6040)
-#define WU_COUNTER_PAUSE               (REGISTERS_BASE + 0x6008)
-#define WELP_ARM_COMMAND               (REGISTERS_BASE + 0x6100)
-#define DRPW_SCRATCH_START             (DRPW_BASE + 0x002C)
-
-
-#define ACX_SLV_SOFT_RESET_BIT   BIT(1)
+#define WL12XX_SPARE_A1                        (REGISTERS_BASE + 0x0994)
+#define WL12XX_SPARE_A2                        (REGISTERS_BASE + 0x0998)
+#define WL12XX_SPARE_A3                        (REGISTERS_BASE + 0x099C)
+#define WL12XX_SPARE_A4                        (REGISTERS_BASE + 0x09A0)
+#define WL12XX_SPARE_A5                        (REGISTERS_BASE + 0x09A4)
+#define WL12XX_SPARE_A6                        (REGISTERS_BASE + 0x09A8)
+#define WL12XX_SPARE_A7                        (REGISTERS_BASE + 0x09AC)
+#define WL12XX_SPARE_A8                        (REGISTERS_BASE + 0x09B0)
+#define WL12XX_SPARE_B1                        (REGISTERS_BASE + 0x5420)
+#define WL12XX_SPARE_B2                        (REGISTERS_BASE + 0x5424)
+#define WL12XX_SPARE_B3                        (REGISTERS_BASE + 0x5428)
+#define WL12XX_SPARE_B4                        (REGISTERS_BASE + 0x542C)
+#define WL12XX_SPARE_B5                        (REGISTERS_BASE + 0x5430)
+#define WL12XX_SPARE_B6                        (REGISTERS_BASE + 0x5434)
+#define WL12XX_SPARE_B7                        (REGISTERS_BASE + 0x5438)
+#define WL12XX_SPARE_B8                        (REGISTERS_BASE + 0x543C)
+
+#define WL12XX_PLL_PARAMETERS          (REGISTERS_BASE + 0x6040)
+#define WL12XX_WU_COUNTER_PAUSE                (REGISTERS_BASE + 0x6008)
+#define WL12XX_WELP_ARM_COMMAND                (REGISTERS_BASE + 0x6100)
+#define WL12XX_DRPW_SCRATCH_START      (DRPW_BASE + 0x002C)
+
+#define WL12XX_CMD_MBOX_ADDRESS                0x407B4
+
 #define ACX_REG_EEPROM_START_BIT BIT(1)
 
 /* Command/Information Mailbox Pointers */
  the host receives the Init Complete interrupt from
  the Wlan hardware.
  ===============================================*/
-#define REG_COMMAND_MAILBOX_PTR                                (SCR_PAD0)
+#define WL12XX_REG_COMMAND_MAILBOX_PTR         (WL12XX_SCR_PAD0)
 
 /*===============================================
   Information Mailbox Pointer - 32bit RW
  until after the host receives the Init Complete interrupt from
  the Wlan hardware.
  ===============================================*/
-#define REG_EVENT_MAILBOX_PTR                          (SCR_PAD1)
+#define WL12XX_REG_EVENT_MAILBOX_PTR           (WL12XX_SCR_PAD1)
 
 /*===============================================
  EEPROM Read/Write Request 32bit RW
 #define ACX_CONT_WIND_MIN_MASK   0x0000007f
 #define ACX_CONT_WIND_MAX        0x03ff0000
 
-/*===============================================
-  HI_CFG Interface Configuration Register Values
-  ------------------------------------------
-  ===============================================*/
-#define HI_CFG_UART_ENABLE          0x00000004
-#define HI_CFG_RST232_ENABLE        0x00000008
-#define HI_CFG_CLOCK_REQ_SELECT     0x00000010
-#define HI_CFG_HOST_INT_ENABLE      0x00000020
-#define HI_CFG_VLYNQ_OUTPUT_ENABLE  0x00000040
-#define HI_CFG_HOST_INT_ACTIVE_LOW  0x00000080
-#define HI_CFG_UART_TX_OUT_GPIO_15  0x00000100
-#define HI_CFG_UART_TX_OUT_GPIO_14  0x00000200
-#define HI_CFG_UART_TX_OUT_GPIO_7   0x00000400
-
-#define HI_CFG_DEF_VAL              \
-       (HI_CFG_UART_ENABLE |        \
-       HI_CFG_RST232_ENABLE |      \
-       HI_CFG_CLOCK_REQ_SELECT |   \
-       HI_CFG_HOST_INT_ENABLE)
-
 #define REF_FREQ_19_2                       0
 #define REF_FREQ_26_0                       1
 #define REF_FREQ_38_4                       2
 #define LUT_PARAM_BB_PLL_LOOP_FILTER        5
 #define LUT_PARAM_NUM                       6
 
-#define ACX_EEPROMLESS_IND_REG              (SCR_PAD4)
+#define WL12XX_EEPROMLESS_IND          (WL12XX_SCR_PAD4)
 #define USE_EEPROM                          0
-#define SOFT_RESET_MAX_TIME                 1000000
-#define SOFT_RESET_STALL_TIME               1000
 #define NVS_DATA_BUNDARY_ALIGNMENT          4
 
-
-/* Firmware image load chunk size */
-#define CHUNK_SIZE     16384
-
 /* Firmware image header size */
 #define FW_HDR_SIZE 8
 
-#define ECPU_CONTROL_HALT                                      0x00000101
-
-
 /******************************************************************************
 
     CHANNELS, BAND & REG DOMAINS definitions
 
 ******************************************************************************/
 
-
-enum {
-       RADIO_BAND_2_4GHZ = 0,  /* 2.4 Ghz band */
-       RADIO_BAND_5GHZ = 1,    /* 5 Ghz band */
-       RADIO_BAND_JAPAN_4_9_GHZ = 2,
-       DEFAULT_BAND = RADIO_BAND_2_4GHZ,
-       INVALID_BAND = 0xFE,
-       MAX_RADIO_BANDS = 0xFF
-};
-
 #define SHORT_PREAMBLE_BIT   BIT(0) /* CCK or Barker depending on the rate */
 #define OFDM_RATE_BIT        BIT(6)
 #define PBCC_RATE_BIT        BIT(7)
@@ -465,14 +413,82 @@ b12-b0 - Supported Rate indicator bits as defined below.
 
 ******************************************************************************/
 
+#define OCP_CMD_LOOP           32
+#define OCP_CMD_WRITE          0x1
+#define OCP_CMD_READ           0x2
+#define OCP_READY_MASK         BIT(18)
+#define OCP_STATUS_MASK                (BIT(16) | BIT(17))
+#define OCP_STATUS_NO_RESP     0x00000
+#define OCP_STATUS_OK          0x10000
+#define OCP_STATUS_REQ_FAILED  0x20000
+#define OCP_STATUS_RESP_ERROR  0x30000
+
+#define OCP_REG_POLARITY     0x0064
+#define OCP_REG_CLK_TYPE     0x0448
+#define OCP_REG_CLK_POLARITY 0x0cb2
+#define OCP_REG_CLK_PULL     0x0cb4
+
+#define POLARITY_LOW         BIT(1)
+#define NO_PULL              (BIT(14) | BIT(15))
+
+#define FREF_CLK_TYPE_BITS     0xfffffe7f
+#define CLK_REQ_PRCM           0x100
+#define FREF_CLK_POLARITY_BITS 0xfffff8ff
+#define CLK_REQ_OUTN_SEL       0x700
+
+#define WU_COUNTER_PAUSE_VAL 0x3FF
+
+/* PLL configuration algorithm for wl128x */
+#define SYS_CLK_CFG_REG              0x2200
+/* Bit[0]   -  0-TCXO,  1-FREF */
+#define MCS_PLL_CLK_SEL_FREF         BIT(0)
+/* Bit[3:2] - 01-TCXO, 10-FREF */
+#define WL_CLK_REQ_TYPE_FREF         BIT(3)
+#define WL_CLK_REQ_TYPE_PG2          (BIT(3) | BIT(2))
+/* Bit[4]   -  0-TCXO,  1-FREF */
+#define PRCM_CM_EN_MUX_WLAN_FREF     BIT(4)
+
+#define TCXO_ILOAD_INT_REG           0x2264
+#define TCXO_CLK_DETECT_REG          0x2266
+
+#define TCXO_DET_FAILED              BIT(4)
+
+#define FREF_ILOAD_INT_REG           0x2084
+#define FREF_CLK_DETECT_REG          0x2086
+#define FREF_CLK_DETECT_FAIL         BIT(4)
+
+/* Use this reg for masking during driver access */
+#define WL_SPARE_REG                 0x2320
+#define WL_SPARE_VAL                 BIT(2)
+/* Bit[6:5:3] -  mask wl write SYS_CLK_CFG[8:5:2:4] */
+#define WL_SPARE_MASK_8526           (BIT(6) | BIT(5) | BIT(3))
+
+#define PLL_LOCK_COUNTERS_REG        0xD8C
+#define PLL_LOCK_COUNTERS_COEX       0x0F
+#define PLL_LOCK_COUNTERS_MCS        0xF0
+#define MCS_PLL_OVERRIDE_REG         0xD90
+#define MCS_PLL_CONFIG_REG           0xD92
+#define MCS_SEL_IN_FREQ_MASK         0x0070
+#define MCS_SEL_IN_FREQ_SHIFT        4
+#define MCS_PLL_CONFIG_REG_VAL       0x73
+#define MCS_PLL_ENABLE_HP            (BIT(0) | BIT(1))
+
+#define MCS_PLL_M_REG                0xD94
+#define MCS_PLL_N_REG                0xD96
+#define MCS_PLL_M_REG_VAL            0xC8
+#define MCS_PLL_N_REG_VAL            0x07
+
+#define SDIO_IO_DS                   0xd14
+
+/* SDIO/wSPI DS configuration values */
+enum {
+       HCI_IO_DS_8MA = 0,
+       HCI_IO_DS_4MA = 1, /* default */
+       HCI_IO_DS_6MA = 2,
+       HCI_IO_DS_2MA = 3,
+};
 
-/*************************************************************************
-
-    Interrupt Trigger Register (Host -> WiLink)
-
-**************************************************************************/
-
-/* Hardware to Embedded CPU Interrupts - first 32-bit register set */
+/* end PLL configuration algorithm for wl128x */
 
 /*
  * Host Command Interrupt. Setting this bit masks
@@ -480,7 +496,7 @@ b12-b0 - Supported Rate indicator bits as defined below.
  * the FW that it has sent a command
  * to the Wlan hardware Command Mailbox.
  */
-#define INTR_TRIG_CMD       BIT(0)
+#define WL12XX_INTR_TRIG_CMD           BIT(0)
 
 /*
  * Host Event Acknowlegde Interrupt. The host
@@ -488,42 +504,27 @@ b12-b0 - Supported Rate indicator bits as defined below.
  * the unsolicited information from the event
  * mailbox.
  */
-#define INTR_TRIG_EVENT_ACK BIT(1)
-
-/*
- * The host sets this bit to inform the Wlan
- * FW that a TX packet is in the XFER
- * Buffer #0.
- */
-#define INTR_TRIG_TX_PROC0 BIT(2)
-
-/*
- * The host sets this bit to inform the FW
- * that it read a packet from RX XFER
- * Buffer #0.
- */
-#define INTR_TRIG_RX_PROC0 BIT(3)
-
-#define INTR_TRIG_DEBUG_ACK BIT(4)
+#define WL12XX_INTR_TRIG_EVENT_ACK     BIT(1)
 
-#define INTR_TRIG_STATE_CHANGED BIT(5)
-
-
-/* Hardware to Embedded CPU Interrupts - second 32-bit register set */
-
-/*
- * The host sets this bit to inform the FW
- * that it read a packet from RX XFER
- * Buffer #1.
- */
-#define INTR_TRIG_RX_PROC1 BIT(17)
+/*===============================================
+  HI_CFG Interface Configuration Register Values
+  ------------------------------------------
+  ===============================================*/
+#define HI_CFG_UART_ENABLE          0x00000004
+#define HI_CFG_RST232_ENABLE        0x00000008
+#define HI_CFG_CLOCK_REQ_SELECT     0x00000010
+#define HI_CFG_HOST_INT_ENABLE      0x00000020
+#define HI_CFG_VLYNQ_OUTPUT_ENABLE  0x00000040
+#define HI_CFG_HOST_INT_ACTIVE_LOW  0x00000080
+#define HI_CFG_UART_TX_OUT_GPIO_15  0x00000100
+#define HI_CFG_UART_TX_OUT_GPIO_14  0x00000200
+#define HI_CFG_UART_TX_OUT_GPIO_7   0x00000400
 
-/*
- * The host sets this bit to inform the Wlan
- * hardware that a TX packet is in the XFER
- * Buffer #1.
- */
-#define INTR_TRIG_TX_PROC1 BIT(18)
+#define HI_CFG_DEF_VAL              \
+       (HI_CFG_UART_ENABLE |        \
+       HI_CFG_RST232_ENABLE |      \
+       HI_CFG_CLOCK_REQ_SELECT |   \
+       HI_CFG_HOST_INT_ENABLE)
 
 #define WL127X_REG_FUSE_DATA_2_1       0x050a
 #define WL128X_REG_FUSE_DATA_2_1       0x2152
diff --git a/drivers/net/wireless/ti/wl12xx/wl12xx.h b/drivers/net/wireless/ti/wl12xx/wl12xx.h
new file mode 100644 (file)
index 0000000..74cd332
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * This file is part of wl12xx
+ *
+ * Copyright (C) 2011 Texas Instruments Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __WL12XX_PRIV_H__
+#define __WL12XX_PRIV_H__
+
+#include "conf.h"
+
+struct wl12xx_priv {
+       struct wl12xx_priv_conf conf;
+};
+
+#endif /* __WL12XX_PRIV_H__ */
diff --git a/drivers/net/wireless/ti/wlcore/Kconfig b/drivers/net/wireless/ti/wlcore/Kconfig
new file mode 100644 (file)
index 0000000..9d04c38
--- /dev/null
@@ -0,0 +1,41 @@
+config WLCORE
+       tristate "TI wlcore support"
+       depends on WL_TI && GENERIC_HARDIRQS
+       depends on INET
+       select FW_LOADER
+       ---help---
+         This module contains the main code for TI WLAN chips.  It abstracts
+         hardware-specific differences among different chipset families.
+         Each chipset family needs to implement its own lower-level module
+         that will depend on this module for the common code.
+
+         If you choose to build a module, it will be called wlcore. Say N if
+         unsure.
+
+config WLCORE_SPI
+       tristate "TI wlcore SPI support"
+       depends on WLCORE && SPI_MASTER
+       select CRC7
+       ---help---
+         This module adds support for the SPI interface of adapters using
+         TI WLAN chipsets.  Select this if your platform is using
+         the SPI bus.
+
+         If you choose to build a module, it'll be called wlcore_spi.
+         Say N if unsure.
+
+config WLCORE_SDIO
+       tristate "TI wlcore SDIO support"
+       depends on WLCORE && MMC
+       ---help---
+         This module adds support for the SDIO interface of adapters using
+         TI WLAN chipsets.  Select this if your platform is using
+         the SDIO bus.
+
+         If you choose to build a module, it'll be called wlcore_sdio.
+         Say N if unsure.
+
+config WL12XX_PLATFORM_DATA
+       bool
+       depends on WLCORE_SDIO != n || WL1251_SDIO != n
+       default y
diff --git a/drivers/net/wireless/ti/wlcore/Makefile b/drivers/net/wireless/ti/wlcore/Makefile
new file mode 100644 (file)
index 0000000..d9fba9e
--- /dev/null
@@ -0,0 +1,15 @@
+wlcore-objs            = main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \
+                         boot.o init.o debugfs.o scan.o
+
+wlcore_spi-objs        = spi.o
+wlcore_sdio-objs       = sdio.o
+
+wlcore-$(CONFIG_NL80211_TESTMODE)      += testmode.o
+obj-$(CONFIG_WLCORE)                   += wlcore.o
+obj-$(CONFIG_WLCORE_SPI)               += wlcore_spi.o
+obj-$(CONFIG_WLCORE_SDIO)              += wlcore_sdio.o
+
+# small builtin driver bit
+obj-$(CONFIG_WL12XX_PLATFORM_DATA)     += wl12xx_platform_data.o
+
+ccflags-y += -D__CHECK_ENDIAN__
similarity index 97%
rename from drivers/net/wireless/wl12xx/acx.c
rename to drivers/net/wireless/ti/wlcore/acx.c
index bc96db0683a5ce99d9fe58d3480813a529675e1a..5912541a925ef5c831f87730605b48a94c965958 100644 (file)
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
 
-#include "wl12xx.h"
+#include "wlcore.h"
 #include "debug.h"
 #include "wl12xx_80211.h"
-#include "reg.h"
 #include "ps.h"
+#include "hw_ops.h"
 
 int wl1271_acx_wake_up_conditions(struct wl1271 *wl, struct wl12xx_vif *wlvif,
                                  u8 wake_up_event, u8 listen_interval)
@@ -757,7 +757,10 @@ int wl1271_acx_sta_rate_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif)
 
        /* configure one AP supported rate class */
        acx->rate_policy_idx = cpu_to_le32(wlvif->sta.ap_rate_idx);
-       acx->rate_policy.enabled_rates = cpu_to_le32(wlvif->rate_set);
+
+       /* the AP policy is HW specific */
+       acx->rate_policy.enabled_rates =
+               cpu_to_le32(wlcore_hw_sta_get_ap_rate_mask(wl, wlvif));
        acx->rate_policy.short_retry_limit = c->short_retry_limit;
        acx->rate_policy.long_retry_limit = c->long_retry_limit;
        acx->rate_policy.aflags = c->aflags;
@@ -969,17 +972,14 @@ int wl12xx_acx_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;
+       mem = &wl->conf.mem;
 
        /* memory config */
        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->total_tx_descriptors = cpu_to_le32(wl->num_tx_desc);
        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;
@@ -998,32 +998,6 @@ out:
        return ret;
 }
 
-int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap)
-{
-       struct wl1271_acx_host_config_bitmap *bitmap_conf;
-       int ret;
-
-       bitmap_conf = kzalloc(sizeof(*bitmap_conf), GFP_KERNEL);
-       if (!bitmap_conf) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       bitmap_conf->host_cfg_bitmap = cpu_to_le32(host_cfg_bitmap);
-
-       ret = wl1271_cmd_configure(wl, ACX_HOST_IF_CFG_BITMAP,
-                                  bitmap_conf, sizeof(*bitmap_conf));
-       if (ret < 0) {
-               wl1271_warning("wl1271 bitmap config opt failed: %d", ret);
-               goto out;
-       }
-
-out:
-       kfree(bitmap_conf);
-
-       return ret;
-}
-
 int wl1271_acx_init_mem_config(struct wl1271 *wl)
 {
        int ret;
similarity index 99%
rename from drivers/net/wireless/wl12xx/acx.h
rename to drivers/net/wireless/ti/wlcore/acx.h
index a28fc044034c8e194a4e8bf82649a88a6231d4d0..b2f88831b7a98018f6231fd7b105aa62c7fb0fb5 100644 (file)
@@ -25,7 +25,7 @@
 #ifndef __ACX_H__
 #define __ACX_H__
 
-#include "wl12xx.h"
+#include "wlcore.h"
 #include "cmd.h"
 
 /*************************************************************************
@@ -824,16 +824,11 @@ struct wl1271_acx_keep_alive_config {
        __le32 period;
 } __packed;
 
+/* TODO: maybe this needs to be moved somewhere else? */
 #define HOST_IF_CFG_RX_FIFO_ENABLE     BIT(0)
 #define HOST_IF_CFG_TX_EXTRA_BLKS_SWAP BIT(1)
 #define HOST_IF_CFG_TX_PAD_TO_SDIO_BLK BIT(3)
 
-struct wl1271_acx_host_config_bitmap {
-       struct acx_header header;
-
-       __le32 host_cfg_bitmap;
-} __packed;
-
 enum {
        WL1271_ACX_TRIG_TYPE_LEVEL = 0,
        WL1271_ACX_TRIG_TYPE_EDGE,
@@ -1274,7 +1269,6 @@ int wl1271_acx_frag_threshold(struct wl1271 *wl, u32 frag_threshold);
 int wl1271_acx_tx_config_options(struct wl1271 *wl);
 int wl12xx_acx_mem_cfg(struct wl1271 *wl);
 int wl1271_acx_init_mem_config(struct wl1271 *wl);
-int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap);
 int wl1271_acx_init_rx_interrupt(struct wl1271 *wl);
 int wl1271_acx_smart_reflex(struct wl1271 *wl);
 int wl1271_acx_bet_enable(struct wl1271 *wl, struct wl12xx_vif *wlvif,
diff --git a/drivers/net/wireless/ti/wlcore/boot.c b/drivers/net/wireless/ti/wlcore/boot.c
new file mode 100644 (file)
index 0000000..3a2207d
--- /dev/null
@@ -0,0 +1,443 @@
+/*
+ * This file is part of wl1271
+ *
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Contact: Luciano Coelho <luciano.coelho@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/wl12xx.h>
+#include <linux/export.h>
+
+#include "debug.h"
+#include "acx.h"
+#include "boot.h"
+#include "io.h"
+#include "event.h"
+#include "rx.h"
+#include "hw_ops.h"
+
+static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)
+{
+       u32 cpu_ctrl;
+
+       /* 10.5.0 run the firmware (I) */
+       cpu_ctrl = wlcore_read_reg(wl, REG_ECPU_CONTROL);
+
+       /* 10.5.1 run the firmware (II) */
+       cpu_ctrl |= flag;
+       wlcore_write_reg(wl, REG_ECPU_CONTROL, cpu_ctrl);
+}
+
+static int wlcore_parse_fw_ver(struct wl1271 *wl)
+{
+       int ret;
+
+       ret = sscanf(wl->chip.fw_ver_str + 4, "%u.%u.%u.%u.%u",
+                    &wl->chip.fw_ver[0], &wl->chip.fw_ver[1],
+                    &wl->chip.fw_ver[2], &wl->chip.fw_ver[3],
+                    &wl->chip.fw_ver[4]);
+
+       if (ret != 5) {
+               wl1271_warning("fw version incorrect value");
+               memset(wl->chip.fw_ver, 0, sizeof(wl->chip.fw_ver));
+               return -EINVAL;
+       }
+
+       ret = wlcore_identify_fw(wl);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static int wlcore_boot_fw_version(struct wl1271 *wl)
+{
+       struct wl1271_static_data *static_data;
+       int ret;
+
+       static_data = kmalloc(sizeof(*static_data), GFP_DMA);
+       if (!static_data) {
+               wl1271_error("Couldn't allocate memory for static data!");
+               return -ENOMEM;
+       }
+
+       wl1271_read(wl, wl->cmd_box_addr, static_data, sizeof(*static_data),
+                   false);
+
+       strncpy(wl->chip.fw_ver_str, static_data->fw_version,
+               sizeof(wl->chip.fw_ver_str));
+
+       kfree(static_data);
+
+       /* make sure the string is NULL-terminated */
+       wl->chip.fw_ver_str[sizeof(wl->chip.fw_ver_str) - 1] = '\0';
+
+       ret = wlcore_parse_fw_ver(wl);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
+                                            size_t fw_data_len, u32 dest)
+{
+       struct wlcore_partition_set partition;
+       int addr, chunk_num, partition_limit;
+       u8 *p, *chunk;
+
+       /* whal_FwCtrl_LoadFwImageSm() */
+
+       wl1271_debug(DEBUG_BOOT, "starting firmware upload");
+
+       wl1271_debug(DEBUG_BOOT, "fw_data_len %zd chunk_size %d",
+                    fw_data_len, CHUNK_SIZE);
+
+       if ((fw_data_len % 4) != 0) {
+               wl1271_error("firmware length not multiple of four");
+               return -EIO;
+       }
+
+       chunk = kmalloc(CHUNK_SIZE, GFP_KERNEL);
+       if (!chunk) {
+               wl1271_error("allocation for firmware upload chunk failed");
+               return -ENOMEM;
+       }
+
+       memcpy(&partition, &wl->ptable[PART_DOWN], sizeof(partition));
+       partition.mem.start = dest;
+       wlcore_set_partition(wl, &partition);
+
+       /* 10.1 set partition limit and chunk num */
+       chunk_num = 0;
+       partition_limit = wl->ptable[PART_DOWN].mem.size;
+
+       while (chunk_num < fw_data_len / CHUNK_SIZE) {
+               /* 10.2 update partition, if needed */
+               addr = dest + (chunk_num + 2) * CHUNK_SIZE;
+               if (addr > partition_limit) {
+                       addr = dest + chunk_num * CHUNK_SIZE;
+                       partition_limit = chunk_num * CHUNK_SIZE +
+                               wl->ptable[PART_DOWN].mem.size;
+                       partition.mem.start = addr;
+                       wlcore_set_partition(wl, &partition);
+               }
+
+               /* 10.3 upload the chunk */
+               addr = dest + chunk_num * CHUNK_SIZE;
+               p = buf + chunk_num * CHUNK_SIZE;
+               memcpy(chunk, p, CHUNK_SIZE);
+               wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x",
+                            p, addr);
+               wl1271_write(wl, addr, chunk, CHUNK_SIZE, false);
+
+               chunk_num++;
+       }
+
+       /* 10.4 upload the last chunk */
+       addr = dest + chunk_num * CHUNK_SIZE;
+       p = buf + chunk_num * CHUNK_SIZE;
+       memcpy(chunk, p, fw_data_len % CHUNK_SIZE);
+       wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x",
+                    fw_data_len % CHUNK_SIZE, p, addr);
+       wl1271_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE, false);
+
+       kfree(chunk);
+       return 0;
+}
+
+int wlcore_boot_upload_firmware(struct wl1271 *wl)
+{
+       u32 chunks, addr, len;
+       int ret = 0;
+       u8 *fw;
+
+       fw = wl->fw;
+       chunks = be32_to_cpup((__be32 *) fw);
+       fw += sizeof(u32);
+
+       wl1271_debug(DEBUG_BOOT, "firmware chunks to be uploaded: %u", chunks);
+
+       while (chunks--) {
+               addr = be32_to_cpup((__be32 *) fw);
+               fw += sizeof(u32);
+               len = be32_to_cpup((__be32 *) fw);
+               fw += sizeof(u32);
+
+               if (len > 300000) {
+                       wl1271_info("firmware chunk too long: %u", len);
+                       return -EINVAL;
+               }
+               wl1271_debug(DEBUG_BOOT, "chunk %d addr 0x%x len %u",
+                            chunks, addr, len);
+               ret = wl1271_boot_upload_firmware_chunk(wl, fw, len, addr);
+               if (ret != 0)
+                       break;
+               fw += len;
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(wlcore_boot_upload_firmware);
+
+int wlcore_boot_upload_nvs(struct wl1271 *wl)
+{
+       size_t nvs_len, burst_len;
+       int i;
+       u32 dest_addr, val;
+       u8 *nvs_ptr, *nvs_aligned;
+
+       if (wl->nvs == NULL)
+               return -ENODEV;
+
+       if (wl->quirks & WLCORE_QUIRK_LEGACY_NVS) {
+               struct wl1271_nvs_file *nvs =
+                       (struct wl1271_nvs_file *)wl->nvs;
+               /*
+                * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz
+                * band configurations) can be removed when those NVS files stop
+                * floating around.
+                */
+               if (wl->nvs_len == sizeof(struct wl1271_nvs_file) ||
+                   wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) {
+                       if (nvs->general_params.dual_mode_select)
+                               wl->enable_11a = true;
+               }
+
+               if (wl->nvs_len != sizeof(struct wl1271_nvs_file) &&
+                   (wl->nvs_len != WL1271_INI_LEGACY_NVS_FILE_SIZE ||
+                    wl->enable_11a)) {
+                       wl1271_error("nvs size is not as expected: %zu != %zu",
+                               wl->nvs_len, sizeof(struct wl1271_nvs_file));
+                       kfree(wl->nvs);
+                       wl->nvs = NULL;
+                       wl->nvs_len = 0;
+                       return -EILSEQ;
+               }
+
+               /* only the first part of the NVS needs to be uploaded */
+               nvs_len = sizeof(nvs->nvs);
+               nvs_ptr = (u8 *) nvs->nvs;
+       } else {
+               struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs;
+
+               if (wl->nvs_len == sizeof(struct wl128x_nvs_file)) {
+                       if (nvs->general_params.dual_mode_select)
+                               wl->enable_11a = true;
+               } else {
+                       wl1271_error("nvs size is not as expected: %zu != %zu",
+                                    wl->nvs_len,
+                                    sizeof(struct wl128x_nvs_file));
+                       kfree(wl->nvs);
+                       wl->nvs = NULL;
+                       wl->nvs_len = 0;
+                       return -EILSEQ;
+               }
+
+               /* only the first part of the NVS needs to be uploaded */
+               nvs_len = sizeof(nvs->nvs);
+               nvs_ptr = (u8 *)nvs->nvs;
+       }
+
+       /* update current MAC address to NVS */
+       nvs_ptr[11] = wl->addresses[0].addr[0];
+       nvs_ptr[10] = wl->addresses[0].addr[1];
+       nvs_ptr[6] = wl->addresses[0].addr[2];
+       nvs_ptr[5] = wl->addresses[0].addr[3];
+       nvs_ptr[4] = wl->addresses[0].addr[4];
+       nvs_ptr[3] = wl->addresses[0].addr[5];
+
+       /*
+        * Layout before the actual NVS tables:
+        * 1 byte : burst length.
+        * 2 bytes: destination address.
+        * n bytes: data to burst copy.
+        *
+        * This is ended by a 0 length, then the NVS tables.
+        */
+
+       /* FIXME: Do we need to check here whether the LSB is 1? */
+       while (nvs_ptr[0]) {
+               burst_len = nvs_ptr[0];
+               dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8));
+
+               /*
+                * Due to our new wl1271_translate_reg_addr function,
+                * we need to add the register partition start address
+                * to the destination
+                */
+               dest_addr += wl->curr_part.reg.start;
+
+               /* We move our pointer to the data */
+               nvs_ptr += 3;
+
+               for (i = 0; i < burst_len; i++) {
+                       if (nvs_ptr + 3 >= (u8 *) wl->nvs + nvs_len)
+                               goto out_badnvs;
+
+                       val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
+                              | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));
+
+                       wl1271_debug(DEBUG_BOOT,
+                                    "nvs burst write 0x%x: 0x%x",
+                                    dest_addr, val);
+                       wl1271_write32(wl, dest_addr, val);
+
+                       nvs_ptr += 4;
+                       dest_addr += 4;
+               }
+
+               if (nvs_ptr >= (u8 *) wl->nvs + nvs_len)
+                       goto out_badnvs;
+       }
+
+       /*
+        * We've reached the first zero length, the first NVS table
+        * is located at an aligned offset which is at least 7 bytes further.
+        * NOTE: The wl->nvs->nvs element must be first, in order to
+        * simplify the casting, we assume it is at the beginning of
+        * the wl->nvs structure.
+        */
+       nvs_ptr = (u8 *)wl->nvs +
+                       ALIGN(nvs_ptr - (u8 *)wl->nvs + 7, 4);
+
+       if (nvs_ptr >= (u8 *) wl->nvs + nvs_len)
+               goto out_badnvs;
+
+       nvs_len -= nvs_ptr - (u8 *)wl->nvs;
+
+       /* Now we must set the partition correctly */
+       wlcore_set_partition(wl, &wl->ptable[PART_WORK]);
+
+       /* Copy the NVS tables to a new block to ensure alignment */
+       nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL);
+       if (!nvs_aligned)
+               return -ENOMEM;
+
+       /* And finally we upload the NVS tables */
+       wlcore_write_data(wl, REG_CMD_MBOX_ADDRESS,
+                         nvs_aligned, nvs_len, false);
+
+       kfree(nvs_aligned);
+       return 0;
+
+out_badnvs:
+       wl1271_error("nvs data is malformed");
+       return -EILSEQ;
+}
+EXPORT_SYMBOL_GPL(wlcore_boot_upload_nvs);
+
+int wlcore_boot_run_firmware(struct wl1271 *wl)
+{
+       int loop, ret;
+       u32 chip_id, intr;
+
+       /* Make sure we have the boot partition */
+       wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
+
+       wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT);
+
+       chip_id = wlcore_read_reg(wl, REG_CHIP_ID_B);
+
+       wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id);
+
+       if (chip_id != wl->chip.id) {
+               wl1271_error("chip id doesn't match after firmware boot");
+               return -EIO;
+       }
+
+       /* wait for init to complete */
+       loop = 0;
+       while (loop++ < INIT_LOOP) {
+               udelay(INIT_LOOP_DELAY);
+               intr = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR);
+
+               if (intr == 0xffffffff) {
+                       wl1271_error("error reading hardware complete "
+                                    "init indication");
+                       return -EIO;
+               }
+               /* check that ACX_INTR_INIT_COMPLETE is enabled */
+               else if (intr & WL1271_ACX_INTR_INIT_COMPLETE) {
+                       wlcore_write_reg(wl, REG_INTERRUPT_ACK,
+                                        WL1271_ACX_INTR_INIT_COMPLETE);
+                       break;
+               }
+       }
+
+       if (loop > INIT_LOOP) {
+               wl1271_error("timeout waiting for the hardware to "
+                            "complete initialization");
+               return -EIO;
+       }
+
+       /* get hardware config command mail box */
+       wl->cmd_box_addr = wlcore_read_reg(wl, REG_COMMAND_MAILBOX_PTR);
+
+       wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x", wl->cmd_box_addr);
+
+       /* get hardware config event mail box */
+       wl->mbox_ptr[0] = wlcore_read_reg(wl, REG_EVENT_MAILBOX_PTR);
+       wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox);
+
+       wl1271_debug(DEBUG_MAILBOX, "MBOX ptrs: 0x%x 0x%x",
+                    wl->mbox_ptr[0], wl->mbox_ptr[1]);
+
+       ret = wlcore_boot_fw_version(wl);
+       if (ret < 0) {
+               wl1271_error("couldn't boot firmware");
+               return ret;
+       }
+
+       /*
+        * in case of full asynchronous mode the firmware event must be
+        * ready to receive event from the command mailbox
+        */
+
+       /* unmask required mbox events  */
+       wl->event_mask = BSS_LOSE_EVENT_ID |
+               SCAN_COMPLETE_EVENT_ID |
+               ROLE_STOP_COMPLETE_EVENT_ID |
+               RSSI_SNR_TRIGGER_0_EVENT_ID |
+               PSPOLL_DELIVERY_FAILURE_EVENT_ID |
+               SOFT_GEMINI_SENSE_EVENT_ID |
+               PERIODIC_SCAN_REPORT_EVENT_ID |
+               PERIODIC_SCAN_COMPLETE_EVENT_ID |
+               DUMMY_PACKET_EVENT_ID |
+               PEER_REMOVE_COMPLETE_EVENT_ID |
+               BA_SESSION_RX_CONSTRAINT_EVENT_ID |
+               REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID |
+               INACTIVE_STA_EVENT_ID |
+               MAX_TX_RETRY_EVENT_ID |
+               CHANNEL_SWITCH_COMPLETE_EVENT_ID;
+
+       ret = wl1271_event_unmask(wl);
+       if (ret < 0) {
+               wl1271_error("EVENT mask setting failed");
+               return ret;
+       }
+
+       /* set the working partition to its "running" mode offset */
+       wlcore_set_partition(wl, &wl->ptable[PART_WORK]);
+
+       /* firmware startup completed */
+       return 0;
+}
+EXPORT_SYMBOL_GPL(wlcore_boot_run_firmware);
diff --git a/drivers/net/wireless/ti/wlcore/boot.h b/drivers/net/wireless/ti/wlcore/boot.h
new file mode 100644 (file)
index 0000000..094981d
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * This file is part of wl1271
+ *
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Contact: Luciano Coelho <luciano.coelho@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __BOOT_H__
+#define __BOOT_H__
+
+#include "wlcore.h"
+
+int wlcore_boot_upload_firmware(struct wl1271 *wl);
+int wlcore_boot_upload_nvs(struct wl1271 *wl);
+int wlcore_boot_run_firmware(struct wl1271 *wl);
+
+#define WL1271_NO_SUBBANDS 8
+#define WL1271_NO_POWER_LEVELS 4
+#define WL1271_FW_VERSION_MAX_LEN 20
+
+struct wl1271_static_data {
+       u8 mac_address[ETH_ALEN];
+       u8 padding[2];
+       u8 fw_version[WL1271_FW_VERSION_MAX_LEN];
+       u32 hw_version;
+       u8 tx_power_table[WL1271_NO_SUBBANDS][WL1271_NO_POWER_LEVELS];
+};
+
+/* number of times we try to read the INIT interrupt */
+#define INIT_LOOP 20000
+
+/* delay between retries */
+#define INIT_LOOP_DELAY 50
+
+#define WU_COUNTER_PAUSE_VAL 0x3FF
+#define WELP_ARM_COMMAND_VAL 0x4
+
+#endif
similarity index 84%
rename from drivers/net/wireless/wl12xx/cmd.c
rename to drivers/net/wireless/ti/wlcore/cmd.c
index 3414fc11e9ba71da93eb4723d252bac693871899..5c4716c6f04057e9cee9226ec9f8274588d852bf 100644 (file)
@@ -28,9 +28,8 @@
 #include <linux/ieee80211.h>
 #include <linux/slab.h>
 
-#include "wl12xx.h"
+#include "wlcore.h"
 #include "debug.h"
-#include "reg.h"
 #include "io.h"
 #include "acx.h"
 #include "wl12xx_80211.h"
@@ -67,11 +66,15 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
 
        wl1271_write(wl, wl->cmd_box_addr, buf, len, false);
 
-       wl1271_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD);
+       /*
+        * TODO: we just need this because one bit is in a different
+        * place.  Is there any better way?
+        */
+       wl->ops->trigger_cmd(wl, wl->cmd_box_addr, buf, len);
 
        timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT);
 
-       intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
+       intr = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR);
        while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) {
                if (time_after(jiffies, timeout)) {
                        wl1271_error("command complete timeout");
@@ -85,7 +88,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
                else
                        msleep(1);
 
-               intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
+               intr = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR);
        }
 
        /* read back the status code of the command */
@@ -100,8 +103,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
                goto fail;
        }
 
-       wl1271_write32(wl, ACX_REG_INTERRUPT_ACK,
-                      WL1271_ACX_INTR_CMD_COMPLETE);
+       wlcore_write_reg(wl, REG_INTERRUPT_ACK, WL1271_ACX_INTR_CMD_COMPLETE);
        return 0;
 
 fail:
@@ -110,240 +112,18 @@ fail:
        return ret;
 }
 
-int wl1271_cmd_general_parms(struct wl1271 *wl)
-{
-       struct wl1271_general_parms_cmd *gen_parms;
-       struct wl1271_ini_general_params *gp =
-               &((struct wl1271_nvs_file *)wl->nvs)->general_params;
-       bool answer = false;
-       int ret;
-
-       if (!wl->nvs)
-               return -ENODEV;
-
-       if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
-               wl1271_warning("FEM index from INI out of bounds");
-               return -EINVAL;
-       }
-
-       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;
-
-       /* Override the REF CLK from the NVS with the one from platform data */
-       gen_parms->general_params.ref_clock = wl->ref_clock;
-
-       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;
-
-       if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
-               wl1271_warning("FEM index from FW out of bounds");
-               ret = -EINVAL;
-               goto out;
-       }
-
-       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;
-
-       if (!wl->nvs)
-               return -ENODEV;
-
-       if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
-               wl1271_warning("FEM index from ini out of bounds");
-               return -EINVAL;
-       }
-
-       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;
-
-       /* Replace REF and TCXO CLKs with the ones from platform data */
-       gen_parms->general_params.ref_clock = wl->ref_clock;
-       gen_parms->general_params.tcxo_ref_clock = wl->tcxo_clock;
-
-       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;
-
-       if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
-               wl1271_warning("FEM index from FW out of bounds");
-               ret = -EINVAL;
-               goto out;
-       }
-
-       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 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 = &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 wl1271_ini_band_params_2));
-       memcpy(&radio_parms->dyn_params_2,
-              &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,
-              &nvs->stat_radio_params_5,
-              sizeof(struct wl1271_ini_band_params_5));
-       memcpy(&radio_parms->dyn_params_5,
-              &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: ",
-                   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 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;
-       struct conf_rf_settings *rf = &wl->conf.rf;
-       int ret;
-
-       if (!wl->nvs)
-               return -ENODEV;
-
-       ext_radio_parms = kzalloc(sizeof(*ext_radio_parms), GFP_KERNEL);
-       if (!ext_radio_parms)
-               return -ENOMEM;
-
-       ext_radio_parms->test.id = TEST_CMD_INI_FILE_RF_EXTENDED_PARAM;
-
-       memcpy(ext_radio_parms->tx_per_channel_power_compensation_2,
-              rf->tx_per_channel_power_compensation_2,
-              CONF_TX_PWR_COMPENSATION_LEN_2);
-       memcpy(ext_radio_parms->tx_per_channel_power_compensation_5,
-              rf->tx_per_channel_power_compensation_5,
-              CONF_TX_PWR_COMPENSATION_LEN_5);
-
-       wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_EXT_RADIO_PARAM: ",
-                   ext_radio_parms, sizeof(*ext_radio_parms));
-
-       ret = wl1271_cmd_test(wl, ext_radio_parms, sizeof(*ext_radio_parms), 0);
-       if (ret < 0)
-               wl1271_warning("TEST_CMD_INI_FILE_RF_EXTENDED_PARAM failed");
-
-       kfree(ext_radio_parms);
-       return ret;
-}
-
 /*
  * Poll the mailbox event field until any of the bits in the mask is set or a
  * timeout occurs (WL1271_EVENT_TIMEOUT in msecs)
  */
 static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl, u32 mask)
 {
-       u32 events_vector, event;
+       u32 *events_vector;
+       u32 event;
        unsigned long timeout;
+       int ret = 0;
+
+       events_vector = kmalloc(sizeof(*events_vector), GFP_DMA);
 
        timeout = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT);
 
@@ -351,21 +131,24 @@ static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl, u32 mask)
                if (time_after(jiffies, timeout)) {
                        wl1271_debug(DEBUG_CMD, "timeout waiting for event %d",
                                     (int)mask);
-                       return -ETIMEDOUT;
+                       ret = -ETIMEDOUT;
+                       goto out;
                }
 
                msleep(1);
 
                /* read from both event fields */
-               wl1271_read(wl, wl->mbox_ptr[0], &events_vector,
-                           sizeof(events_vector), false);
-               event = events_vector & mask;
-               wl1271_read(wl, wl->mbox_ptr[1], &events_vector,
-                           sizeof(events_vector), false);
-               event |= events_vector & mask;
+               wl1271_read(wl, wl->mbox_ptr[0], events_vector,
+                           sizeof(*events_vector), false);
+               event = *events_vector & mask;
+               wl1271_read(wl, wl->mbox_ptr[1], events_vector,
+                           sizeof(*events_vector), false);
+               event |= *events_vector & mask;
        } while (!event);
 
-       return 0;
+out:
+       kfree(events_vector);
+       return ret;
 }
 
 static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
@@ -522,7 +305,7 @@ static int wl12xx_cmd_role_start_dev(struct wl1271 *wl,
 
        cmd->role_id = wlvif->dev_role_id;
        if (wlvif->band == IEEE80211_BAND_5GHZ)
-               cmd->band = WL12XX_BAND_5GHZ;
+               cmd->band = WLCORE_BAND_5GHZ;
        cmd->channel = wlvif->channel;
 
        if (wlvif->dev_hlid == WL12XX_INVALID_LINK_ID) {
@@ -613,7 +396,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif)
 
        cmd->role_id = wlvif->role_id;
        if (wlvif->band == IEEE80211_BAND_5GHZ)
-               cmd->band = WL12XX_BAND_5GHZ;
+               cmd->band = WLCORE_BAND_5GHZ;
        cmd->channel = wlvif->channel;
        cmd->sta.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set);
        cmd->sta.beacon_interval = cpu_to_le16(wlvif->beacon_int);
@@ -750,14 +533,14 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif)
 
        switch (wlvif->band) {
        case IEEE80211_BAND_2GHZ:
-               cmd->band = RADIO_BAND_2_4GHZ;
+               cmd->band = WLCORE_BAND_2_4GHZ;
                break;
        case IEEE80211_BAND_5GHZ:
-               cmd->band = RADIO_BAND_5GHZ;
+               cmd->band = WLCORE_BAND_5GHZ;
                break;
        default:
                wl1271_warning("ap start - unknown band: %d", (int)wlvif->band);
-               cmd->band = RADIO_BAND_2_4GHZ;
+               cmd->band = WLCORE_BAND_2_4GHZ;
                break;
        }
 
@@ -830,7 +613,7 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif)
 
        cmd->role_id = wlvif->role_id;
        if (wlvif->band == IEEE80211_BAND_5GHZ)
-               cmd->band = WL12XX_BAND_5GHZ;
+               cmd->band = WLCORE_BAND_5GHZ;
        cmd->channel = wlvif->channel;
        cmd->ibss.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set);
        cmd->ibss.beacon_interval = cpu_to_le16(wlvif->beacon_int);
@@ -904,6 +687,7 @@ int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer)
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(wl1271_cmd_test);
 
 /**
  * read acx from firmware
@@ -960,6 +744,7 @@ int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len)
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(wl1271_cmd_configure);
 
 int wl1271_cmd_data_path(struct wl1271 *wl, bool enable)
 {
@@ -1730,10 +1515,10 @@ static int wl12xx_cmd_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif,
        cmd->channel = wlvif->channel;
        switch (wlvif->band) {
        case IEEE80211_BAND_2GHZ:
-               cmd->band = RADIO_BAND_2_4GHZ;
+               cmd->band = WLCORE_BAND_2_4GHZ;
                break;
        case IEEE80211_BAND_5GHZ:
-               cmd->band = RADIO_BAND_5GHZ;
+               cmd->band = WLCORE_BAND_5GHZ;
                break;
        default:
                wl1271_error("roc - unknown band: %d", (int)wlvif->band);
similarity index 87%
rename from drivers/net/wireless/wl12xx/cmd.h
rename to drivers/net/wireless/ti/wlcore/cmd.h
index de217d92516b4efede360f4c1f187b156b76a294..a46ae07cb77eb8243a27251c7c5859916de908f4 100644 (file)
 #ifndef __CMD_H__
 #define __CMD_H__
 
-#include "wl12xx.h"
+#include "wlcore.h"
 
 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 wl12xx_cmd_role_enable(struct wl1271 *wl, u8 *addr, u8 role_type,
                           u8 *role_id);
 int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id);
@@ -262,13 +257,13 @@ struct wl12xx_cmd_role_disable {
        u8 padding[3];
 } __packed;
 
-enum wl12xx_band {
-       WL12XX_BAND_2_4GHZ              = 0,
-       WL12XX_BAND_5GHZ                = 1,
-       WL12XX_BAND_JAPAN_4_9_GHZ       = 2,
-       WL12XX_BAND_DEFAULT             = WL12XX_BAND_2_4GHZ,
-       WL12XX_BAND_INVALID             = 0x7E,
-       WL12XX_BAND_MAX_RADIO           = 0x7F,
+enum wlcore_band {
+       WLCORE_BAND_2_4GHZ              = 0,
+       WLCORE_BAND_5GHZ                = 1,
+       WLCORE_BAND_JAPAN_4_9_GHZ       = 2,
+       WLCORE_BAND_DEFAULT             = WLCORE_BAND_2_4GHZ,
+       WLCORE_BAND_INVALID             = 0x7E,
+       WLCORE_BAND_MAX_RADIO           = 0x7F,
 };
 
 struct wl12xx_cmd_role_start {
@@ -494,83 +489,6 @@ enum wl1271_channel_tune_bands {
 
 #define WL1271_PD_REFERENCE_POINT_BAND_B_G  0
 
-#define TEST_CMD_INI_FILE_RADIO_PARAM       0x19
-#define TEST_CMD_INI_FILE_GENERAL_PARAM     0x1E
-#define TEST_CMD_INI_FILE_RF_EXTENDED_PARAM 0x26
-
-struct wl1271_general_parms_cmd {
-       struct wl1271_cmd_header header;
-
-       struct wl1271_cmd_test_header test;
-
-       struct wl1271_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 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;
-
-       struct wl1271_cmd_test_header test;
-
-       /* Static radio parameters */
-       struct wl1271_ini_band_params_2 static_params_2;
-       struct wl1271_ini_band_params_5 static_params_5;
-
-       /* Dynamic radio parameters */
-       struct wl1271_ini_fem_params_2 dyn_params_2;
-       u8 padding2;
-       struct wl1271_ini_fem_params_5 dyn_params_5;
-       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;
-
-       struct wl1271_cmd_test_header test;
-
-       u8 tx_per_channel_power_compensation_2[CONF_TX_PWR_COMPENSATION_LEN_2];
-       u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5];
-       u8 padding[3];
-} __packed;
-
 /*
  * There are three types of disconnections:
  *
similarity index 94%
rename from drivers/net/wireless/wl12xx/conf.h
rename to drivers/net/wireless/ti/wlcore/conf.h
index 3e581e19424c85f68afc272e7ec33ba458f1baf3..fef0db4213bc4c83d3cf51b5092d8fbe004bfe0e 100644 (file)
@@ -65,36 +65,7 @@ enum {
        CONF_HW_RATE_INDEX_MAX     = CONF_HW_RATE_INDEX_54MBPS,
 };
 
-enum {
-       CONF_HW_RXTX_RATE_MCS7_SGI = 0,
-       CONF_HW_RXTX_RATE_MCS7,
-       CONF_HW_RXTX_RATE_MCS6,
-       CONF_HW_RXTX_RATE_MCS5,
-       CONF_HW_RXTX_RATE_MCS4,
-       CONF_HW_RXTX_RATE_MCS3,
-       CONF_HW_RXTX_RATE_MCS2,
-       CONF_HW_RXTX_RATE_MCS1,
-       CONF_HW_RXTX_RATE_MCS0,
-       CONF_HW_RXTX_RATE_54,
-       CONF_HW_RXTX_RATE_48,
-       CONF_HW_RXTX_RATE_36,
-       CONF_HW_RXTX_RATE_24,
-       CONF_HW_RXTX_RATE_22,
-       CONF_HW_RXTX_RATE_18,
-       CONF_HW_RXTX_RATE_12,
-       CONF_HW_RXTX_RATE_11,
-       CONF_HW_RXTX_RATE_9,
-       CONF_HW_RXTX_RATE_6,
-       CONF_HW_RXTX_RATE_5_5,
-       CONF_HW_RXTX_RATE_2,
-       CONF_HW_RXTX_RATE_1,
-       CONF_HW_RXTX_RATE_MAX,
-       CONF_HW_RXTX_RATE_UNSUPPORTED = 0xff
-};
-
-/* Rates between and including these are MCS rates */
-#define CONF_HW_RXTX_RATE_MCS_MIN CONF_HW_RXTX_RATE_MCS7_SGI
-#define CONF_HW_RXTX_RATE_MCS_MAX CONF_HW_RXTX_RATE_MCS0
+#define CONF_HW_RXTX_RATE_UNSUPPORTED 0xff
 
 enum {
        CONF_SG_DISABLE = 0,
@@ -1096,16 +1067,31 @@ struct conf_scan_settings {
 };
 
 struct conf_sched_scan_settings {
-       /* minimum time to wait on the channel for active scans (in TUs) */
-       u16 min_dwell_time_active;
+       /*
+        * The base time to wait on the channel for active scans (in TU/1000).
+        * The minimum dwell time is calculated according to this:
+        * min_dwell_time = base + num_of_probes_to_be_sent * delta_per_probe
+        * The maximum dwell time is calculated according to this:
+        * max_dwell_time = min_dwell_time + max_dwell_time_delta
+        */
+       u32 base_dwell_time;
 
-       /* maximum time to wait on the channel for active scans (in TUs) */
-       u16 max_dwell_time_active;
+       /* The delta between the min dwell time and max dwell time for
+        * active scans (in TU/1000s). The max dwell time is used by the FW once
+        * traffic is detected on the channel.
+        */
+       u32 max_dwell_time_delta;
+
+       /* Delta added to min dwell time per each probe in 2.4 GHz (TU/1000) */
+       u32 dwell_time_delta_per_probe;
 
-       /* time to wait on the channel for passive scans (in TUs) */
+       /* Delta added to min dwell time per each probe in 5 GHz (TU/1000) */
+       u32 dwell_time_delta_per_probe_5;
+
+       /* time to wait on the channel for passive scans (in TU/1000) */
        u32 dwell_time_passive;
 
-       /* time to wait on the channel for DFS scans (in TUs) */
+       /* time to wait on the channel for DFS scans (in TU/1000) */
        u32 dwell_time_dfs;
 
        /* number of probe requests to send on each channel in active scans */
@@ -1118,26 +1104,6 @@ struct conf_sched_scan_settings {
        s8 snr_threshold;
 };
 
-/* these are number of channels on the band divided by two, rounded up */
-#define CONF_TX_PWR_COMPENSATION_LEN_2 7
-#define CONF_TX_PWR_COMPENSATION_LEN_5 18
-
-struct conf_rf_settings {
-       /*
-        * Per channel power compensation for 2.4GHz
-        *
-        * Range: s8
-        */
-       u8 tx_per_channel_power_compensation_2[CONF_TX_PWR_COMPENSATION_LEN_2];
-
-       /*
-        * Per channel power compensation for 5GHz
-        *
-        * Range: s8
-        */
-       u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5];
-};
-
 struct conf_ht_setting {
        u8 rx_ba_win_size;
        u8 tx_ba_win_size;
@@ -1286,7 +1252,7 @@ struct conf_hangover_settings {
        u8 window_size;
 };
 
-struct conf_drv_settings {
+struct wlcore_conf {
        struct conf_sg_settings sg;
        struct conf_rx_settings rx;
        struct conf_tx_settings tx;
@@ -1296,16 +1262,13 @@ struct conf_drv_settings {
        struct conf_roam_trigger_settings roam_trigger;
        struct conf_scan_settings scan;
        struct conf_sched_scan_settings sched_scan;
-       struct conf_rf_settings rf;
        struct conf_ht_setting ht;
-       struct conf_memory_settings mem_wl127x;
-       struct conf_memory_settings mem_wl128x;
+       struct conf_memory_settings mem;
        struct conf_fm_coex fm_coex;
        struct conf_rx_streaming_settings rx_streaming;
        struct conf_fwlog fwlog;
        struct conf_rate_policy_settings rate;
        struct conf_hangover_settings hangover;
-       u8 hci_io_ds;
 };
 
 #endif
similarity index 99%
rename from drivers/net/wireless/wl12xx/debug.h
rename to drivers/net/wireless/ti/wlcore/debug.h
index ec0fdc25b28027c58a39d711fc846c25b356eaee..6b800b3cbea59fdeb7be9fbe395aea2988fbd682 100644 (file)
@@ -52,6 +52,7 @@ enum {
        DEBUG_ADHOC     = BIT(16),
        DEBUG_AP        = BIT(17),
        DEBUG_PROBE     = BIT(18),
+       DEBUG_IO        = BIT(19),
        DEBUG_MASTER    = (DEBUG_ADHOC | DEBUG_AP),
        DEBUG_ALL       = ~0,
 };
similarity index 99%
rename from drivers/net/wireless/wl12xx/debugfs.c
rename to drivers/net/wireless/ti/wlcore/debugfs.c
index 564d49575c94d49cc98f5d718db2aa22c986adb0..d5aea1ff5ad196a693930cd4b66fc3376ba4fdc4 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/skbuff.h>
 #include <linux/slab.h>
 
-#include "wl12xx.h"
+#include "wlcore.h"
 #include "debug.h"
 #include "acx.h"
 #include "ps.h"
@@ -647,6 +647,7 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf,
                VIF_STATE_PRINT_INT(last_rssi_event);
                VIF_STATE_PRINT_INT(ba_support);
                VIF_STATE_PRINT_INT(ba_allowed);
+               VIF_STATE_PRINT_INT(is_gem);
                VIF_STATE_PRINT_LLHEX(tx_security_seq);
                VIF_STATE_PRINT_INT(tx_security_last_seq_lsb);
        }
similarity index 98%
rename from drivers/net/wireless/wl12xx/debugfs.h
rename to drivers/net/wireless/ti/wlcore/debugfs.h
index 254c5b292cf69382cefcea5db30de9b2080cd72e..a8d3aef011ffc6274f97bfe505ea2d6defca1d47 100644 (file)
@@ -24,7 +24,7 @@
 #ifndef __DEBUGFS_H__
 #define __DEBUGFS_H__
 
-#include "wl12xx.h"
+#include "wlcore.h"
 
 int wl1271_debugfs_init(struct wl1271 *wl);
 void wl1271_debugfs_exit(struct wl1271 *wl);
similarity index 91%
rename from drivers/net/wireless/wl12xx/event.c
rename to drivers/net/wireless/ti/wlcore/event.c
index c953717f38ebab69ed3acdbd117563925916a139..292632ddf8901c641a3df880bbb7d34c369a3942 100644 (file)
@@ -21,9 +21,8 @@
  *
  */
 
-#include "wl12xx.h"
+#include "wlcore.h"
 #include "debug.h"
-#include "reg.h"
 #include "io.h"
 #include "event.h"
 #include "ps.h"
@@ -98,8 +97,9 @@ static void wl1271_event_mbox_dump(struct event_mailbox *mbox)
        wl1271_debug(DEBUG_EVENT, "\tmask: 0x%x", mbox->events_mask);
 }
 
-static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
+static int wl1271_event_process(struct wl1271 *wl)
 {
+       struct event_mailbox *mbox = wl->mbox;
        struct ieee80211_vif *vif;
        struct wl12xx_vif *wlvif;
        u32 vector;
@@ -196,7 +196,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
                        bool success;
 
                        if (!test_and_clear_bit(WLVIF_FLAG_CS_PROGRESS,
-                                               &wl->flags))
+                                               &wlvif->flags))
                                continue;
 
                        success = mbox->channel_switch_status ? false : true;
@@ -278,18 +278,8 @@ int wl1271_event_unmask(struct wl1271 *wl)
        return 0;
 }
 
-void wl1271_event_mbox_config(struct wl1271 *wl)
-{
-       wl->mbox_ptr[0] = wl1271_read32(wl, REG_EVENT_MAILBOX_PTR);
-       wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox);
-
-       wl1271_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x",
-                    wl->mbox_ptr[0], wl->mbox_ptr[1]);
-}
-
 int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
 {
-       struct event_mailbox mbox;
        int ret;
 
        wl1271_debug(DEBUG_EVENT, "EVENT on mbox %d", mbox_num);
@@ -298,16 +288,19 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
                return -EINVAL;
 
        /* first we read the mbox descriptor */
-       wl1271_read(wl, wl->mbox_ptr[mbox_num], &mbox,
-                   sizeof(struct event_mailbox), false);
+       wl1271_read(wl, wl->mbox_ptr[mbox_num], wl->mbox,
+                   sizeof(*wl->mbox), false);
 
        /* process the descriptor */
-       ret = wl1271_event_process(wl, &mbox);
+       ret = wl1271_event_process(wl);
        if (ret < 0)
                return ret;
 
-       /* then we let the firmware know it can go on...*/
-       wl1271_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK);
+       /*
+        * TODO: we just need this because one bit is in a different
+        * place.  Is there any better way?
+        */
+       wl->ops->ack_event(wl);
 
        return 0;
 }
similarity index 98%
rename from drivers/net/wireless/wl12xx/event.h
rename to drivers/net/wireless/ti/wlcore/event.h
index 057d193d3525c39adce0b26e4ac170b8688c08bc..8adf18d6c58f74c9bbdaa90474a83466ece2b50b 100644 (file)
@@ -132,8 +132,9 @@ struct event_mailbox {
        u8 reserved_8[9];
 } __packed;
 
+struct wl1271;
+
 int wl1271_event_unmask(struct wl1271 *wl);
-void wl1271_event_mbox_config(struct wl1271 *wl);
 int wl1271_event_handle(struct wl1271 *wl, u8 mbox);
 
 #endif
diff --git a/drivers/net/wireless/ti/wlcore/hw_ops.h b/drivers/net/wireless/ti/wlcore/hw_ops.h
new file mode 100644 (file)
index 0000000..9384b4d
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * This file is part of wlcore
+ *
+ * Copyright (C) 2011 Texas Instruments Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __WLCORE_HW_OPS_H__
+#define __WLCORE_HW_OPS_H__
+
+#include "wlcore.h"
+#include "rx.h"
+
+static inline u32
+wlcore_hw_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks)
+{
+       if (!wl->ops->calc_tx_blocks)
+               BUG_ON(1);
+
+       return wl->ops->calc_tx_blocks(wl, len, spare_blks);
+}
+
+static inline void
+wlcore_hw_set_tx_desc_blocks(struct wl1271 *wl, struct wl1271_tx_hw_descr *desc,
+                            u32 blks, u32 spare_blks)
+{
+       if (!wl->ops->set_tx_desc_blocks)
+               BUG_ON(1);
+
+       return wl->ops->set_tx_desc_blocks(wl, desc, blks, spare_blks);
+}
+
+static inline void
+wlcore_hw_set_tx_desc_data_len(struct wl1271 *wl,
+                              struct wl1271_tx_hw_descr *desc,
+                              struct sk_buff *skb)
+{
+       if (!wl->ops->set_tx_desc_data_len)
+               BUG_ON(1);
+
+       wl->ops->set_tx_desc_data_len(wl, desc, skb);
+}
+
+static inline enum wl_rx_buf_align
+wlcore_hw_get_rx_buf_align(struct wl1271 *wl, u32 rx_desc)
+{
+
+       if (!wl->ops->get_rx_buf_align)
+               BUG_ON(1);
+
+       return wl->ops->get_rx_buf_align(wl, rx_desc);
+}
+
+static inline void
+wlcore_hw_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len)
+{
+       if (wl->ops->prepare_read)
+               wl->ops->prepare_read(wl, rx_desc, len);
+}
+
+static inline u32
+wlcore_hw_get_rx_packet_len(struct wl1271 *wl, void *rx_data, u32 data_len)
+{
+       if (!wl->ops->get_rx_packet_len)
+               BUG_ON(1);
+
+       return wl->ops->get_rx_packet_len(wl, rx_data, data_len);
+}
+
+static inline void wlcore_hw_tx_delayed_compl(struct wl1271 *wl)
+{
+       if (wl->ops->tx_delayed_compl)
+               wl->ops->tx_delayed_compl(wl);
+}
+
+static inline void wlcore_hw_tx_immediate_compl(struct wl1271 *wl)
+{
+       if (wl->ops->tx_immediate_compl)
+               wl->ops->tx_immediate_compl(wl);
+}
+
+static inline int
+wlcore_hw_init_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif)
+{
+       if (wl->ops->init_vif)
+               return wl->ops->init_vif(wl, wlvif);
+
+       return 0;
+}
+
+static inline u32
+wlcore_hw_sta_get_ap_rate_mask(struct wl1271 *wl, struct wl12xx_vif *wlvif)
+{
+       if (!wl->ops->sta_get_ap_rate_mask)
+               BUG_ON(1);
+
+       return wl->ops->sta_get_ap_rate_mask(wl, wlvif);
+}
+
+static inline int wlcore_identify_fw(struct wl1271 *wl)
+{
+       if (wl->ops->identify_fw)
+               return wl->ops->identify_fw(wl);
+
+       return 0;
+}
+
+#endif
similarity index 93%
rename from drivers/net/wireless/wl12xx/init.c
rename to drivers/net/wireless/ti/wlcore/init.c
index 203fbebf09eb472e8fa49a9178264181c0b15b3b..9f89255eb6e616e6fd47c2544121584f32156e06 100644 (file)
@@ -30,9 +30,9 @@
 #include "wl12xx_80211.h"
 #include "acx.h"
 #include "cmd.h"
-#include "reg.h"
 #include "tx.h"
 #include "io.h"
+#include "hw_ops.h"
 
 int wl1271_init_templates_config(struct wl1271 *wl)
 {
@@ -319,7 +319,7 @@ static int wl12xx_init_fwlog(struct wl1271 *wl)
 {
        int ret;
 
-       if (wl->quirks & WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED)
+       if (wl->quirks & WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED)
                return 0;
 
        ret = wl12xx_cmd_config_fwlog(wl);
@@ -494,26 +494,6 @@ static int wl1271_set_ba_policies(struct wl1271 *wl, struct wl12xx_vif *wlvif)
        return wl12xx_acx_set_ba_initiator_policy(wl, wlvif);
 }
 
-int wl1271_chip_specific_init(struct wl1271 *wl)
-{
-       int ret = 0;
-
-       if (wl->chip.id == CHIP_ID_1283_PG20) {
-               u32 host_cfg_bitmap = HOST_IF_CFG_RX_FIFO_ENABLE;
-
-               if (!(wl->quirks & WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT))
-                       /* Enable SDIO padding */
-                       host_cfg_bitmap |= HOST_IF_CFG_TX_PAD_TO_SDIO_BLK;
-
-               /* Must be before wl1271_acx_init_mem_config() */
-               ret = wl1271_acx_host_if_cfg_bitmap(wl, host_cfg_bitmap);
-               if (ret < 0)
-                       goto out;
-       }
-out:
-       return ret;
-}
-
 /* vif-specifc initialization */
 static int wl12xx_init_sta_role(struct wl1271 *wl, struct wl12xx_vif *wlvif)
 {
@@ -582,10 +562,17 @@ int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif)
                        if (ret < 0)
                                return ret;
                } else if (!wl->sta_count) {
-                       /* Configure for ELP power saving */
-                       ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
-                       if (ret < 0)
-                               return ret;
+                       if (wl->quirks & WLCORE_QUIRK_NO_ELP) {
+                               /* Configure for power always on */
+                               ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
+                               if (ret < 0)
+                                       return ret;
+                       } else {
+                               /* Configure for ELP power saving */
+                               ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
+                               if (ret < 0)
+                                       return ret;
+                       }
                }
        }
 
@@ -652,6 +639,10 @@ int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif)
        if (ret < 0)
                return ret;
 
+       ret = wlcore_hw_init_vif(wl, wlvif);
+       if (ret < 0)
+               return ret;
+
        return 0;
 }
 
@@ -659,27 +650,8 @@ int wl1271_hw_init(struct wl1271 *wl)
 {
        int ret;
 
-       if (wl->chip.id == CHIP_ID_1283_PG20) {
-               ret = wl128x_cmd_general_parms(wl);
-               if (ret < 0)
-                       return ret;
-               ret = wl128x_cmd_radio_parms(wl);
-               if (ret < 0)
-                       return ret;
-       } else {
-               ret = wl1271_cmd_general_parms(wl);
-               if (ret < 0)
-                       return ret;
-               ret = wl1271_cmd_radio_parms(wl);
-               if (ret < 0)
-                       return ret;
-               ret = wl1271_cmd_ext_radio_parms(wl);
-               if (ret < 0)
-                       return ret;
-       }
-
-       /* Chip-specific init */
-       ret = wl1271_chip_specific_init(wl);
+       /* Chip-specific hw init */
+       ret = wl->ops->hw_init(wl);
        if (ret < 0)
                return ret;
 
similarity index 98%
rename from drivers/net/wireless/wl12xx/init.h
rename to drivers/net/wireless/ti/wlcore/init.h
index 2da0f404ef6e44df9c076b7e98b4d1c5ba53132d..a45fbfddec192e67791be7cb23ac419c2b3a82ba 100644 (file)
@@ -24,7 +24,7 @@
 #ifndef __INIT_H__
 #define __INIT_H__
 
-#include "wl12xx.h"
+#include "wlcore.h"
 
 int wl1271_hw_init_power_auth(struct wl1271 *wl);
 int wl1271_init_templates_config(struct wl1271 *wl);
similarity index 55%
rename from drivers/net/wireless/wl12xx/io.c
rename to drivers/net/wireless/ti/wlcore/io.c
index c574a3b31e3127e514d74ab7d09a3e8e9664f15f..7cd0081aede5f77cf6279045240d4622afe389cb 100644 (file)
 #include <linux/spi/spi.h>
 #include <linux/interrupt.h>
 
-#include "wl12xx.h"
+#include "wlcore.h"
 #include "debug.h"
 #include "wl12xx_80211.h"
 #include "io.h"
 #include "tx.h"
 
-#define OCP_CMD_LOOP  32
-
-#define OCP_CMD_WRITE 0x1
-#define OCP_CMD_READ  0x2
-
-#define OCP_READY_MASK  BIT(18)
-#define OCP_STATUS_MASK (BIT(16) | BIT(17))
-
-#define OCP_STATUS_NO_RESP    0x00000
-#define OCP_STATUS_OK         0x10000
-#define OCP_STATUS_REQ_FAILED 0x20000
-#define OCP_STATUS_RESP_ERROR 0x30000
-
-struct wl1271_partition_set wl12xx_part_table[PART_TABLE_LEN] = {
-       [PART_DOWN] = {
-               .mem = {
-                       .start = 0x00000000,
-                       .size  = 0x000177c0
-               },
-               .reg = {
-                       .start = REGISTERS_BASE,
-                       .size  = 0x00008800
-               },
-               .mem2 = {
-                       .start = 0x00000000,
-                       .size  = 0x00000000
-               },
-               .mem3 = {
-                       .start = 0x00000000,
-                       .size  = 0x00000000
-               },
-       },
-
-       [PART_WORK] = {
-               .mem = {
-                       .start = 0x00040000,
-                       .size  = 0x00014fc0
-               },
-               .reg = {
-                       .start = REGISTERS_BASE,
-                       .size  = 0x0000a000
-               },
-               .mem2 = {
-                       .start = 0x003004f8,
-                       .size  = 0x00000004
-               },
-               .mem3 = {
-                       .start = 0x00040404,
-                       .size  = 0x00000000
-               },
-       },
-
-       [PART_DRPW] = {
-               .mem = {
-                       .start = 0x00040000,
-                       .size  = 0x00014fc0
-               },
-               .reg = {
-                       .start = DRPW_BASE,
-                       .size  = 0x00006000
-               },
-               .mem2 = {
-                       .start = 0x00000000,
-                       .size  = 0x00000000
-               },
-               .mem3 = {
-                       .start = 0x00000000,
-                       .size  = 0x00000000
-               }
-       }
-};
-
 bool wl1271_set_block_size(struct wl1271 *wl)
 {
        if (wl->if_ops->set_block_size) {
@@ -114,17 +42,53 @@ bool wl1271_set_block_size(struct wl1271 *wl)
        return false;
 }
 
-void wl1271_disable_interrupts(struct wl1271 *wl)
+void wlcore_disable_interrupts(struct wl1271 *wl)
 {
        disable_irq(wl->irq);
 }
+EXPORT_SYMBOL_GPL(wlcore_disable_interrupts);
 
-void wl1271_enable_interrupts(struct wl1271 *wl)
+void wlcore_enable_interrupts(struct wl1271 *wl)
 {
        enable_irq(wl->irq);
 }
+EXPORT_SYMBOL_GPL(wlcore_enable_interrupts);
 
-/* Set the SPI partitions to access the chip addresses
+int wlcore_translate_addr(struct wl1271 *wl, int addr)
+{
+       struct wlcore_partition_set *part = &wl->curr_part;
+
+       /*
+        * To translate, first check to which window of addresses the
+        * particular address belongs. Then subtract the starting address
+        * of that window from the address. Then, add offset of the
+        * translated region.
+        *
+        * The translated regions occur next to each other in physical device
+        * memory, so just add the sizes of the preceding address regions to
+        * get the offset to the new region.
+        */
+       if ((addr >= part->mem.start) &&
+           (addr < part->mem.start + part->mem.size))
+               return addr - part->mem.start;
+       else if ((addr >= part->reg.start) &&
+                (addr < part->reg.start + part->reg.size))
+               return addr - part->reg.start + part->mem.size;
+       else if ((addr >= part->mem2.start) &&
+                (addr < part->mem2.start + part->mem2.size))
+               return addr - part->mem2.start + part->mem.size +
+                       part->reg.size;
+       else if ((addr >= part->mem3.start) &&
+                (addr < part->mem3.start + part->mem3.size))
+               return addr - part->mem3.start + part->mem.size +
+                       part->reg.size + part->mem2.size;
+
+       WARN(1, "HW address 0x%x out of range", addr);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(wlcore_translate_addr);
+
+/* Set the partitions to access the chip addresses
  *
  * To simplify driver code, a fixed (virtual) memory map is defined for
  * register and memory addresses. Because in the chipset, in different stages
@@ -158,33 +122,43 @@ void wl1271_enable_interrupts(struct wl1271 *wl)
  *                                    |    |
  *
  */
-int wl1271_set_partition(struct wl1271 *wl,
-                        struct wl1271_partition_set *p)
+void wlcore_set_partition(struct wl1271 *wl,
+                         const struct wlcore_partition_set *p)
 {
        /* copy partition info */
-       memcpy(&wl->part, p, sizeof(*p));
+       memcpy(&wl->curr_part, p, sizeof(*p));
 
-       wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
+       wl1271_debug(DEBUG_IO, "mem_start %08X mem_size %08X",
                     p->mem.start, p->mem.size);
-       wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
+       wl1271_debug(DEBUG_IO, "reg_start %08X reg_size %08X",
                     p->reg.start, p->reg.size);
-       wl1271_debug(DEBUG_SPI, "mem2_start %08X mem2_size %08X",
+       wl1271_debug(DEBUG_IO, "mem2_start %08X mem2_size %08X",
                     p->mem2.start, p->mem2.size);
-       wl1271_debug(DEBUG_SPI, "mem3_start %08X mem3_size %08X",
+       wl1271_debug(DEBUG_IO, "mem3_start %08X mem3_size %08X",
                     p->mem3.start, p->mem3.size);
 
-       /* write partition info to the chipset */
        wl1271_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start);
        wl1271_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size);
        wl1271_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start);
        wl1271_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size);
        wl1271_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start);
        wl1271_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size);
+       /*
+        * We don't need the size of the last partition, as it is
+        * automatically calculated based on the total memory size and
+        * the sizes of the previous partitions.
+        */
        wl1271_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start);
+}
+EXPORT_SYMBOL_GPL(wlcore_set_partition);
 
-       return 0;
+void wlcore_select_partition(struct wl1271 *wl, u8 part)
+{
+       wl1271_debug(DEBUG_IO, "setting partition %d", part);
+
+       wlcore_set_partition(wl, &wl->ptable[part]);
 }
-EXPORT_SYMBOL_GPL(wl1271_set_partition);
+EXPORT_SYMBOL_GPL(wlcore_select_partition);
 
 void wl1271_io_reset(struct wl1271 *wl)
 {
@@ -197,48 +171,3 @@ void wl1271_io_init(struct wl1271 *wl)
        if (wl->if_ops->init)
                wl->if_ops->init(wl->dev);
 }
-
-void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val)
-{
-       /* write address >> 1 + 0x30000 to OCP_POR_CTR */
-       addr = (addr >> 1) + 0x30000;
-       wl1271_write32(wl, OCP_POR_CTR, addr);
-
-       /* write value to OCP_POR_WDATA */
-       wl1271_write32(wl, OCP_DATA_WRITE, val);
-
-       /* write 1 to OCP_CMD */
-       wl1271_write32(wl, OCP_CMD, OCP_CMD_WRITE);
-}
-
-u16 wl1271_top_reg_read(struct wl1271 *wl, int addr)
-{
-       u32 val;
-       int timeout = OCP_CMD_LOOP;
-
-       /* write address >> 1 + 0x30000 to OCP_POR_CTR */
-       addr = (addr >> 1) + 0x30000;
-       wl1271_write32(wl, OCP_POR_CTR, addr);
-
-       /* write 2 to OCP_CMD */
-       wl1271_write32(wl, OCP_CMD, OCP_CMD_READ);
-
-       /* poll for data ready */
-       do {
-               val = wl1271_read32(wl, OCP_DATA_READ);
-       } while (!(val & OCP_READY_MASK) && --timeout);
-
-       if (!timeout) {
-               wl1271_warning("Top register access timed out.");
-               return 0xffff;
-       }
-
-       /* check data status and return if OK */
-       if ((val & OCP_STATUS_MASK) == OCP_STATUS_OK)
-               return val & 0xffff;
-       else {
-               wl1271_warning("Top register access returned error.");
-               return 0xffff;
-       }
-}
-
similarity index 71%
rename from drivers/net/wireless/wl12xx/io.h
rename to drivers/net/wireless/ti/wlcore/io.h
index 4fb3dab8c3b2124516ccac22ef9f71d82a9a50e2..8942954b56a0f435a5cdccfc6e7d96f7ccbf9dc7 100644 (file)
@@ -26,7 +26,6 @@
 #define __IO_H__
 
 #include <linux/irqreturn.h>
-#include "reg.h"
 
 #define HW_ACCESS_MEMORY_MAX_RANGE     0x1FFC0
 
 
 #define HW_ACCESS_PRAM_MAX_RANGE       0x3c000
 
-extern struct wl1271_partition_set wl12xx_part_table[PART_TABLE_LEN];
-
 struct wl1271;
 
-void wl1271_disable_interrupts(struct wl1271 *wl);
-void wl1271_enable_interrupts(struct wl1271 *wl);
+void wlcore_disable_interrupts(struct wl1271 *wl);
+void wlcore_enable_interrupts(struct wl1271 *wl);
 
 void wl1271_io_reset(struct wl1271 *wl);
 void wl1271_io_init(struct wl1271 *wl);
+int wlcore_translate_addr(struct wl1271 *wl, int addr);
 
 /* Raw target IO, address is not translated */
 static inline void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf,
@@ -66,6 +64,18 @@ static inline void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf,
        wl->if_ops->read(wl->dev, addr, buf, len, fixed);
 }
 
+static inline void wlcore_raw_read_data(struct wl1271 *wl, int reg, void *buf,
+                                       size_t len, bool fixed)
+{
+       wl1271_raw_read(wl, wl->rtable[reg], buf, len, fixed);
+}
+
+static inline void wlcore_raw_write_data(struct wl1271 *wl, int reg, void *buf,
+                                        size_t len, bool fixed)
+{
+       wl1271_raw_write(wl, wl->rtable[reg], buf, len, fixed);
+}
+
 static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr)
 {
        wl1271_raw_read(wl, addr, &wl->buffer_32,
@@ -81,36 +91,12 @@ static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val)
                             sizeof(wl->buffer_32), false);
 }
 
-/* Translated target IO */
-static inline int wl1271_translate_addr(struct wl1271 *wl, int addr)
-{
-       /*
-        * To translate, first check to which window of addresses the
-        * particular address belongs. Then subtract the starting address
-        * of that window from the address. Then, add offset of the
-        * translated region.
-        *
-        * The translated regions occur next to each other in physical device
-        * memory, so just add the sizes of the preceding address regions to
-        * get the offset to the new region.
-        *
-        * Currently, only the two first regions are addressed, and the
-        * assumption is that all addresses will fall into either of those
-        * two.
-        */
-       if ((addr >= wl->part.reg.start) &&
-           (addr < wl->part.reg.start + wl->part.reg.size))
-               return addr - wl->part.reg.start + wl->part.mem.size;
-       else
-               return addr - wl->part.mem.start;
-}
-
 static inline void wl1271_read(struct wl1271 *wl, int addr, void *buf,
                               size_t len, bool fixed)
 {
        int physical;
 
-       physical = wl1271_translate_addr(wl, addr);
+       physical = wlcore_translate_addr(wl, addr);
 
        wl1271_raw_read(wl, physical, buf, len, fixed);
 }
@@ -120,11 +106,23 @@ static inline void wl1271_write(struct wl1271 *wl, int addr, void *buf,
 {
        int physical;
 
-       physical = wl1271_translate_addr(wl, addr);
+       physical = wlcore_translate_addr(wl, addr);
 
        wl1271_raw_write(wl, physical, buf, len, fixed);
 }
 
+static inline void wlcore_write_data(struct wl1271 *wl, int reg, void *buf,
+                                    size_t len, bool fixed)
+{
+       wl1271_write(wl, wl->rtable[reg], buf, len, fixed);
+}
+
+static inline void wlcore_read_data(struct wl1271 *wl, int reg, void *buf,
+                                   size_t len, bool fixed)
+{
+       wl1271_read(wl, wl->rtable[reg], buf, len, fixed);
+}
+
 static inline void wl1271_read_hwaddr(struct wl1271 *wl, int hwaddr,
                                      void *buf, size_t len, bool fixed)
 {
@@ -134,19 +132,30 @@ static inline void wl1271_read_hwaddr(struct wl1271 *wl, int hwaddr,
        /* Addresses are stored internally as addresses to 32 bytes blocks */
        addr = hwaddr << 5;
 
-       physical = wl1271_translate_addr(wl, addr);
+       physical = wlcore_translate_addr(wl, addr);
 
        wl1271_raw_read(wl, physical, buf, len, fixed);
 }
 
 static inline u32 wl1271_read32(struct wl1271 *wl, int addr)
 {
-       return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr));
+       return wl1271_raw_read32(wl, wlcore_translate_addr(wl, addr));
 }
 
 static inline void wl1271_write32(struct wl1271 *wl, int addr, u32 val)
 {
-       wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val);
+       wl1271_raw_write32(wl, wlcore_translate_addr(wl, addr), val);
+}
+
+static inline u32 wlcore_read_reg(struct wl1271 *wl, int reg)
+{
+       return wl1271_raw_read32(wl,
+                                wlcore_translate_addr(wl, wl->rtable[reg]));
+}
+
+static inline void wlcore_write_reg(struct wl1271 *wl, int reg, u32 val)
+{
+       wl1271_raw_write32(wl, wlcore_translate_addr(wl, wl->rtable[reg]), val);
 }
 
 static inline void wl1271_power_off(struct wl1271 *wl)
@@ -164,13 +173,8 @@ static inline int wl1271_power_on(struct wl1271 *wl)
        return ret;
 }
 
-
-/* Top Register IO */
-void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val);
-u16 wl1271_top_reg_read(struct wl1271 *wl, int addr);
-
-int wl1271_set_partition(struct wl1271 *wl,
-                        struct wl1271_partition_set *p);
+void wlcore_set_partition(struct wl1271 *wl,
+                         const struct wlcore_partition_set *p);
 
 bool wl1271_set_block_size(struct wl1271 *wl);
 
@@ -178,4 +182,6 @@ bool wl1271_set_block_size(struct wl1271 *wl);
 
 int wl1271_tx_dummy_packet(struct wl1271 *wl);
 
+void wlcore_select_partition(struct wl1271 *wl, u8 part);
+
 #endif
similarity index 85%
rename from drivers/net/wireless/wl12xx/main.c
rename to drivers/net/wireless/ti/wlcore/main.c
index 362ff1a7067ec732965350bd6b69f24fba7a4bc2..2b0f987660c69b49af30703cd2fb2f02ed413775 100644 (file)
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 
-#include "wl12xx.h"
+#include "wlcore.h"
 #include "debug.h"
 #include "wl12xx_80211.h"
-#include "reg.h"
 #include "io.h"
 #include "event.h"
 #include "tx.h"
 #include "boot.h"
 #include "testmode.h"
 #include "scan.h"
+#include "hw_ops.h"
 
 #define WL1271_BOOT_RETRIES 3
 
-static struct conf_drv_settings default_conf = {
-       .sg = {
-               .params = {
-                       [CONF_SG_ACL_BT_MASTER_MIN_BR] = 10,
-                       [CONF_SG_ACL_BT_MASTER_MAX_BR] = 180,
-                       [CONF_SG_ACL_BT_SLAVE_MIN_BR] = 10,
-                       [CONF_SG_ACL_BT_SLAVE_MAX_BR] = 180,
-                       [CONF_SG_ACL_BT_MASTER_MIN_EDR] = 10,
-                       [CONF_SG_ACL_BT_MASTER_MAX_EDR] = 80,
-                       [CONF_SG_ACL_BT_SLAVE_MIN_EDR] = 10,
-                       [CONF_SG_ACL_BT_SLAVE_MAX_EDR] = 80,
-                       [CONF_SG_ACL_WLAN_PS_MASTER_BR] = 8,
-                       [CONF_SG_ACL_WLAN_PS_SLAVE_BR] = 8,
-                       [CONF_SG_ACL_WLAN_PS_MASTER_EDR] = 20,
-                       [CONF_SG_ACL_WLAN_PS_SLAVE_EDR] = 20,
-                       [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_BR] = 20,
-                       [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_BR] = 35,
-                       [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_BR] = 16,
-                       [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_BR] = 35,
-                       [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_EDR] = 32,
-                       [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_EDR] = 50,
-                       [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_EDR] = 28,
-                       [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_EDR] = 50,
-                       [CONF_SG_ACL_ACTIVE_SCAN_WLAN_BR] = 10,
-                       [CONF_SG_ACL_ACTIVE_SCAN_WLAN_EDR] = 20,
-                       [CONF_SG_ACL_PASSIVE_SCAN_BT_BR] = 75,
-                       [CONF_SG_ACL_PASSIVE_SCAN_WLAN_BR] = 15,
-                       [CONF_SG_ACL_PASSIVE_SCAN_BT_EDR] = 27,
-                       [CONF_SG_ACL_PASSIVE_SCAN_WLAN_EDR] = 17,
-                       /* active scan params */
-                       [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170,
-                       [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50,
-                       [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100,
-                       /* passive scan params */
-                       [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_BR] = 800,
-                       [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_EDR] = 200,
-                       [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200,
-                       /* passive scan in dual antenna params */
-                       [CONF_SG_CONSECUTIVE_HV3_IN_PASSIVE_SCAN] = 0,
-                       [CONF_SG_BCN_HV3_COLLISION_THRESH_IN_PASSIVE_SCAN] = 0,
-                       [CONF_SG_TX_RX_PROTECTION_BWIDTH_IN_PASSIVE_SCAN] = 0,
-                       /* general params */
-                       [CONF_SG_STA_FORCE_PS_IN_BT_SCO] = 1,
-                       [CONF_SG_ANTENNA_CONFIGURATION] = 0,
-                       [CONF_SG_BEACON_MISS_PERCENT] = 60,
-                       [CONF_SG_DHCP_TIME] = 5000,
-                       [CONF_SG_RXT] = 1200,
-                       [CONF_SG_TXT] = 1000,
-                       [CONF_SG_ADAPTIVE_RXT_TXT] = 1,
-                       [CONF_SG_GENERAL_USAGE_BIT_MAP] = 3,
-                       [CONF_SG_HV3_MAX_SERVED] = 6,
-                       [CONF_SG_PS_POLL_TIMEOUT] = 10,
-                       [CONF_SG_UPSD_TIMEOUT] = 10,
-                       [CONF_SG_CONSECUTIVE_CTS_THRESHOLD] = 2,
-                       [CONF_SG_STA_RX_WINDOW_AFTER_DTIM] = 5,
-                       [CONF_SG_STA_CONNECTION_PROTECTION_TIME] = 30,
-                       /* AP params */
-                       [CONF_AP_BEACON_MISS_TX] = 3,
-                       [CONF_AP_RX_WINDOW_AFTER_BEACON] = 10,
-                       [CONF_AP_BEACON_WINDOW_INTERVAL] = 2,
-                       [CONF_AP_CONNECTION_PROTECTION_TIME] = 0,
-                       [CONF_AP_BT_ACL_VAL_BT_SERVE_TIME] = 25,
-                       [CONF_AP_BT_ACL_VAL_WL_SERVE_TIME] = 25,
-                       /* CTS Diluting params */
-                       [CONF_SG_CTS_DILUTED_BAD_RX_PACKETS_TH] = 0,
-                       [CONF_SG_CTS_CHOP_IN_DUAL_ANT_SCO_MASTER] = 0,
-               },
-               .state = CONF_SG_PROTECTIVE,
-       },
-       .rx = {
-               .rx_msdu_life_time           = 512000,
-               .packet_detection_threshold  = 0,
-               .ps_poll_timeout             = 15,
-               .upsd_timeout                = 15,
-               .rts_threshold               = IEEE80211_MAX_RTS_THRESHOLD,
-               .rx_cca_threshold            = 0,
-               .irq_blk_threshold           = 0xFFFF,
-               .irq_pkt_threshold           = 0,
-               .irq_timeout                 = 600,
-               .queue_type                  = CONF_RX_QUEUE_TYPE_LOW_PRIORITY,
-       },
-       .tx = {
-               .tx_energy_detection         = 0,
-               .sta_rc_conf                 = {
-                       .enabled_rates       = 0,
-                       .short_retry_limit   = 10,
-                       .long_retry_limit    = 10,
-                       .aflags              = 0,
-               },
-               .ac_conf_count               = 4,
-               .ac_conf                     = {
-                       [CONF_TX_AC_BE] = {
-                               .ac          = CONF_TX_AC_BE,
-                               .cw_min      = 15,
-                               .cw_max      = 63,
-                               .aifsn       = 3,
-                               .tx_op_limit = 0,
-                       },
-                       [CONF_TX_AC_BK] = {
-                               .ac          = CONF_TX_AC_BK,
-                               .cw_min      = 15,
-                               .cw_max      = 63,
-                               .aifsn       = 7,
-                               .tx_op_limit = 0,
-                       },
-                       [CONF_TX_AC_VI] = {
-                               .ac          = CONF_TX_AC_VI,
-                               .cw_min      = 15,
-                               .cw_max      = 63,
-                               .aifsn       = CONF_TX_AIFS_PIFS,
-                               .tx_op_limit = 3008,
-                       },
-                       [CONF_TX_AC_VO] = {
-                               .ac          = CONF_TX_AC_VO,
-                               .cw_min      = 15,
-                               .cw_max      = 63,
-                               .aifsn       = CONF_TX_AIFS_PIFS,
-                               .tx_op_limit = 1504,
-                       },
-               },
-               .max_tx_retries = 100,
-               .ap_aging_period = 300,
-               .tid_conf_count = 4,
-               .tid_conf = {
-                       [CONF_TX_AC_BE] = {
-                               .queue_id    = CONF_TX_AC_BE,
-                               .channel_type = CONF_CHANNEL_TYPE_EDCF,
-                               .tsid        = CONF_TX_AC_BE,
-                               .ps_scheme   = CONF_PS_SCHEME_LEGACY,
-                               .ack_policy  = CONF_ACK_POLICY_LEGACY,
-                               .apsd_conf   = {0, 0},
-                       },
-                       [CONF_TX_AC_BK] = {
-                               .queue_id    = CONF_TX_AC_BK,
-                               .channel_type = CONF_CHANNEL_TYPE_EDCF,
-                               .tsid        = CONF_TX_AC_BK,
-                               .ps_scheme   = CONF_PS_SCHEME_LEGACY,
-                               .ack_policy  = CONF_ACK_POLICY_LEGACY,
-                               .apsd_conf   = {0, 0},
-                       },
-                       [CONF_TX_AC_VI] = {
-                               .queue_id    = CONF_TX_AC_VI,
-                               .channel_type = CONF_CHANNEL_TYPE_EDCF,
-                               .tsid        = CONF_TX_AC_VI,
-                               .ps_scheme   = CONF_PS_SCHEME_LEGACY,
-                               .ack_policy  = CONF_ACK_POLICY_LEGACY,
-                               .apsd_conf   = {0, 0},
-                       },
-                       [CONF_TX_AC_VO] = {
-                               .queue_id    = CONF_TX_AC_VO,
-                               .channel_type = CONF_CHANNEL_TYPE_EDCF,
-                               .tsid        = CONF_TX_AC_VO,
-                               .ps_scheme   = CONF_PS_SCHEME_LEGACY,
-                               .ack_policy  = CONF_ACK_POLICY_LEGACY,
-                               .apsd_conf   = {0, 0},
-                       },
-               },
-               .frag_threshold              = IEEE80211_MAX_FRAG_THRESHOLD,
-               .tx_compl_timeout            = 700,
-               .tx_compl_threshold          = 4,
-               .basic_rate                  = CONF_HW_BIT_RATE_1MBPS,
-               .basic_rate_5                = CONF_HW_BIT_RATE_6MBPS,
-               .tmpl_short_retry_limit      = 10,
-               .tmpl_long_retry_limit       = 10,
-               .tx_watchdog_timeout         = 5000,
-       },
-       .conn = {
-               .wake_up_event               = CONF_WAKE_UP_EVENT_DTIM,
-               .listen_interval             = 1,
-               .suspend_wake_up_event       = CONF_WAKE_UP_EVENT_N_DTIM,
-               .suspend_listen_interval     = 3,
-               .bcn_filt_mode               = CONF_BCN_FILT_MODE_ENABLED,
-               .bcn_filt_ie_count           = 2,
-               .bcn_filt_ie = {
-                       [0] = {
-                               .ie          = WLAN_EID_CHANNEL_SWITCH,
-                               .rule        = CONF_BCN_RULE_PASS_ON_APPEARANCE,
-                       },
-                       [1] = {
-                               .ie          = WLAN_EID_HT_OPERATION,
-                               .rule        = CONF_BCN_RULE_PASS_ON_CHANGE,
-                       },
-               },
-               .synch_fail_thold            = 10,
-               .bss_lose_timeout            = 100,
-               .beacon_rx_timeout           = 10000,
-               .broadcast_timeout           = 20000,
-               .rx_broadcast_in_ps          = 1,
-               .ps_poll_threshold           = 10,
-               .bet_enable                  = CONF_BET_MODE_ENABLE,
-               .bet_max_consecutive         = 50,
-               .psm_entry_retries           = 8,
-               .psm_exit_retries            = 16,
-               .psm_entry_nullfunc_retries  = 3,
-               .dynamic_ps_timeout          = 200,
-               .forced_ps                   = false,
-               .keep_alive_interval         = 55000,
-               .max_listen_interval         = 20,
-       },
-       .itrim = {
-               .enable = false,
-               .timeout = 50000,
-       },
-       .pm_config = {
-               .host_clk_settling_time = 5000,
-               .host_fast_wakeup_support = false
-       },
-       .roam_trigger = {
-               .trigger_pacing               = 1,
-               .avg_weight_rssi_beacon       = 20,
-               .avg_weight_rssi_data         = 10,
-               .avg_weight_snr_beacon        = 20,
-               .avg_weight_snr_data          = 10,
-       },
-       .scan = {
-               .min_dwell_time_active        = 7500,
-               .max_dwell_time_active        = 30000,
-               .min_dwell_time_passive       = 100000,
-               .max_dwell_time_passive       = 100000,
-               .num_probe_reqs               = 2,
-               .split_scan_timeout           = 50000,
-       },
-       .sched_scan = {
-               /* sched_scan requires dwell times in TU instead of TU/1000 */
-               .min_dwell_time_active = 30,
-               .max_dwell_time_active = 60,
-               .dwell_time_passive    = 100,
-               .dwell_time_dfs        = 150,
-               .num_probe_reqs        = 2,
-               .rssi_threshold        = -90,
-               .snr_threshold         = 0,
-       },
-       .rf = {
-               .tx_per_channel_power_compensation_2 = {
-                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-               },
-               .tx_per_channel_power_compensation_5 = {
-                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-               },
-       },
-       .ht = {
-               .rx_ba_win_size = 8,
-               .tx_ba_win_size = 64,
-               .inactivity_timeout = 10000,
-               .tx_ba_tid_bitmap = CONF_TX_BA_ENABLED_TID_BITMAP,
-       },
-       .mem_wl127x = {
-               .num_stations                 = 1,
-               .ssid_profiles                = 1,
-               .rx_block_num                 = 70,
-               .tx_min_block_num             = 40,
-               .dynamic_memory               = 1,
-               .min_req_tx_blocks            = 100,
-               .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,
-       },
-       .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 */
-       },
-       .rx_streaming = {
-               .duration                      = 150,
-               .queues                        = 0x1,
-               .interval                      = 20,
-               .always                        = 0,
-       },
-       .fwlog = {
-               .mode                         = WL12XX_FWLOG_ON_DEMAND,
-               .mem_blocks                   = 2,
-               .severity                     = 0,
-               .timestamp                    = WL12XX_FWLOG_TIMESTAMP_DISABLED,
-               .output                       = WL12XX_FWLOG_OUTPUT_HOST,
-               .threshold                    = 0,
-       },
-       .hci_io_ds = HCI_IO_DS_6MA,
-       .rate = {
-               .rate_retry_score = 32000,
-               .per_add = 8192,
-               .per_th1 = 2048,
-               .per_th2 = 4096,
-               .max_per = 8100,
-               .inverse_curiosity_factor = 5,
-               .tx_fail_low_th = 4,
-               .tx_fail_high_th = 10,
-               .per_alpha_shift = 4,
-               .per_add_shift = 13,
-               .per_beta1_shift = 10,
-               .per_beta2_shift = 8,
-               .rate_check_up = 2,
-               .rate_check_down = 12,
-               .rate_retry_policy = {
-                       0x00, 0x00, 0x00, 0x00, 0x00,
-                       0x00, 0x00, 0x00, 0x00, 0x00,
-                       0x00, 0x00, 0x00,
-               },
-       },
-       .hangover = {
-               .recover_time               = 0,
-               .hangover_period            = 20,
-               .dynamic_mode               = 1,
-               .early_termination_mode     = 1,
-               .max_period                 = 20,
-               .min_period                 = 1,
-               .increase_delta             = 1,
-               .decrease_delta             = 2,
-               .quiet_time                 = 4,
-               .increase_time              = 1,
-               .window_size                = 16,
-       },
-};
+#define WL1271_BOOT_RETRIES 3
 
 static char *fwlog_param;
 static bool bug_on_recovery;
+static bool no_recovery;
 
 static void __wl1271_op_remove_interface(struct wl1271 *wl,
                                         struct ieee80211_vif *vif,
@@ -628,22 +300,8 @@ out:
        mutex_unlock(&wl->mutex);
 }
 
-static void wl1271_conf_init(struct wl1271 *wl)
+static void wlcore_adjust_conf(struct wl1271 *wl)
 {
-
-       /*
-        * This function applies the default configuration to the driver. This
-        * function is invoked upon driver load (spi probe.)
-        *
-        * The configuration is stored in a run-time structure in order to
-        * facilitate for run-time adjustment of any of the parameters. Making
-        * changes to the configuration structure will apply the new values on
-        * the next interface up (wl1271_op_start.)
-        */
-
-       /* apply driver default configuration */
-       memcpy(&wl->conf, &default_conf, sizeof(default_conf));
-
        /* Adjust settings according to optional module parameters */
        if (fwlog_param) {
                if (!strcmp(fwlog_param, "continuous")) {
@@ -666,28 +324,7 @@ static int wl1271_plt_init(struct wl1271 *wl)
 {
        int ret;
 
-       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;
-
-       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;
-
-       if (wl->chip.id != CHIP_ID_1283_PG20) {
-               ret = wl1271_cmd_ext_radio_parms(wl);
-               if (ret < 0)
-                       return ret;
-       }
-
-       /* Chip-specific initializations */
-       ret = wl1271_chip_specific_init(wl);
+       ret = wl->ops->hw_init(wl);
        if (ret < 0)
                return ret;
 
@@ -750,7 +387,7 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl,
 
 static void wl12xx_irq_update_links_status(struct wl1271 *wl,
                                           struct wl12xx_vif *wlvif,
-                                          struct wl12xx_fw_status *status)
+                                          struct wl_fw_status *status)
 {
        struct wl1271_link *lnk;
        u32 cur_fw_ps_map;
@@ -770,9 +407,10 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl,
 
        for_each_set_bit(hlid, wlvif->ap.sta_hlid_map, WL12XX_MAX_LINKS) {
                lnk = &wl->links[hlid];
-               cnt = status->tx_lnk_free_pkts[hlid] - lnk->prev_freed_pkts;
+               cnt = status->counters.tx_lnk_free_pkts[hlid] -
+                       lnk->prev_freed_pkts;
 
-               lnk->prev_freed_pkts = status->tx_lnk_free_pkts[hlid];
+               lnk->prev_freed_pkts = status->counters.tx_lnk_free_pkts[hlid];
                lnk->allocated_pkts -= cnt;
 
                wl12xx_irq_ps_regulate_link(wl, wlvif, hlid,
@@ -781,15 +419,19 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl,
 }
 
 static void wl12xx_fw_status(struct wl1271 *wl,
-                            struct wl12xx_fw_status *status)
+                            struct wl_fw_status *status)
 {
        struct wl12xx_vif *wlvif;
        struct timespec ts;
        u32 old_tx_blk_count = wl->tx_blocks_available;
        int avail, freed_blocks;
        int i;
+       size_t status_len;
+
+       status_len = sizeof(*status) + wl->fw_status_priv_len;
 
-       wl1271_raw_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false);
+       wlcore_raw_read_data(wl, REG_RAW_FW_STATUS_ADDR, status,
+                            status_len, false);
 
        wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
                     "drv_rx_counter = %d, tx_results_counter = %d)",
@@ -801,10 +443,10 @@ static void wl12xx_fw_status(struct wl1271 *wl,
        for (i = 0; i < NUM_TX_QUEUES; i++) {
                /* prevent wrap-around in freed-packets counter */
                wl->tx_allocated_pkts[i] -=
-                               (status->tx_released_pkts[i] -
+                               (status->counters.tx_released_pkts[i] -
                                wl->tx_pkts_freed[i]) & 0xff;
 
-               wl->tx_pkts_freed[i] = status->tx_released_pkts[i];
+               wl->tx_pkts_freed[i] = status->counters.tx_released_pkts[i];
        }
 
        /* prevent wrap-around in total blocks counter */
@@ -927,6 +569,9 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
                smp_mb__after_clear_bit();
 
                wl12xx_fw_status(wl, wl->fw_status);
+
+               wlcore_hw_tx_immediate_compl(wl);
+
                intr = le32_to_cpu(wl->fw_status->intr);
                intr &= WL1271_INTR_MASK;
                if (!intr) {
@@ -963,9 +608,7 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
                        }
 
                        /* check for tx results */
-                       if (wl->fw_status->tx_results_counter !=
-                           (wl->tx_results_count & 0xff))
-                               wl1271_tx_complete(wl);
+                       wlcore_hw_tx_delayed_compl(wl);
 
                        /* Make sure the deferred queues don't get too long */
                        defer_count = skb_queue_len(&wl->deferred_tx_queue) +
@@ -1046,10 +689,7 @@ static int wl12xx_fetch_firmware(struct wl1271 *wl, bool plt)
 
        if (plt) {
                fw_type = WL12XX_FW_TYPE_PLT;
-               if (wl->chip.id == CHIP_ID_1283_PG20)
-                       fw_name = WL128X_PLT_FW_NAME;
-               else
-                       fw_name = WL127X_PLT_FW_NAME;
+               fw_name = wl->plt_fw_name;
        } else {
                /*
                 * we can't call wl12xx_get_vif_count() here because
@@ -1057,16 +697,10 @@ static int wl12xx_fetch_firmware(struct wl1271 *wl, bool plt)
                 */
                if (wl->last_vif_count > 1) {
                        fw_type = WL12XX_FW_TYPE_MULTI;
-                       if (wl->chip.id == CHIP_ID_1283_PG20)
-                               fw_name = WL128X_FW_NAME_MULTI;
-                       else
-                               fw_name = WL127X_FW_NAME_MULTI;
+                       fw_name = wl->mr_fw_name;
                } else {
                        fw_type = WL12XX_FW_TYPE_NORMAL;
-                       if (wl->chip.id == CHIP_ID_1283_PG20)
-                               fw_name = WL128X_FW_NAME_SINGLE;
-                       else
-                               fw_name = WL127X_FW_NAME_SINGLE;
+                       fw_name = wl->sr_fw_name;
                }
        }
 
@@ -1173,7 +807,7 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl)
        u32 first_addr;
        u8 *block;
 
-       if ((wl->quirks & WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED) ||
+       if ((wl->quirks & WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED) ||
            (wl->conf.fwlog.mode != WL12XX_FWLOG_ON_DEMAND) ||
            (wl->conf.fwlog.mem_blocks == 0))
                return;
@@ -1239,11 +873,20 @@ static void wl1271_recovery_work(struct work_struct *work)
        wl12xx_read_fwlog_panic(wl);
 
        wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x",
-                   wl->chip.fw_ver_str, wl1271_read32(wl, SCR_PAD4));
+                   wl->chip.fw_ver_str,
+                   wlcore_read_reg(wl, REG_PC_ON_RECOVERY));
 
        BUG_ON(bug_on_recovery &&
               !test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags));
 
+       if (no_recovery) {
+               wl1271_info("No recovery (chosen on module load). Fw will remain stuck.");
+               clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags);
+               goto out_unlock;
+       }
+
+       BUG_ON(bug_on_recovery);
+
        /*
         * Advance security sequence number to overcome potential progress
         * in the firmware during recovery. This doens't hurt if the network is
@@ -1290,10 +933,7 @@ out_unlock:
 
 static void wl1271_fw_wakeup(struct wl1271 *wl)
 {
-       u32 elp_reg;
-
-       elp_reg = ELPCTRL_WAKE_UP;
-       wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg);
+       wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP);
 }
 
 static int wl1271_setup(struct wl1271 *wl)
@@ -1323,7 +963,7 @@ static int wl12xx_set_power_on(struct wl1271 *wl)
        wl1271_io_reset(wl);
        wl1271_io_init(wl);
 
-       wl1271_set_partition(wl, &wl12xx_part_table[PART_DOWN]);
+       wlcore_set_partition(wl, &wl->ptable[PART_BOOT]);
 
        /* ELP module wake up */
        wl1271_fw_wakeup(wl);
@@ -1348,44 +988,18 @@ static int wl12xx_chip_wakeup(struct wl1271 *wl, bool plt)
         * negligible, we use the same block size for all different
         * chip types.
         */
-       if (!wl1271_set_block_size(wl))
-               wl->quirks |= WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT;
-
-       switch (wl->chip.id) {
-       case CHIP_ID_1271_PG10:
-               wl1271_warning("chip id 0x%x (1271 PG10) support is obsolete",
-                              wl->chip.id);
+       if (wl1271_set_block_size(wl))
+               wl->quirks |= WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN;
 
-               ret = wl1271_setup(wl);
-               if (ret < 0)
-                       goto out;
-               wl->quirks |= WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT;
-               break;
-
-       case CHIP_ID_1271_PG20:
-               wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)",
-                            wl->chip.id);
-
-               ret = wl1271_setup(wl);
-               if (ret < 0)
-                       goto out;
-               wl->quirks |= WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT;
-               break;
+       ret = wl->ops->identify_chip(wl);
+       if (ret < 0)
+               goto out;
 
-       case CHIP_ID_1283_PG20:
-               wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1283 PG20)",
-                            wl->chip.id);
+       /* TODO: make sure the lower driver has set things up correctly */
 
-               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;
+       ret = wl1271_setup(wl);
+       if (ret < 0)
                goto out;
-       }
 
        ret = wl12xx_fetch_firmware(wl, plt);
        if (ret < 0)
@@ -1425,7 +1039,7 @@ int wl1271_plt_start(struct wl1271 *wl)
                if (ret < 0)
                        goto power_off;
 
-               ret = wl1271_boot(wl);
+               ret = wl->ops->boot(wl);
                if (ret < 0)
                        goto power_off;
 
@@ -1454,7 +1068,7 @@ irq_disable:
                   work function will not do anything.) Also, any other
                   possible concurrent operations will fail due to the
                   current state, hence the wl1271 struct should be safe. */
-               wl1271_disable_interrupts(wl);
+               wlcore_disable_interrupts(wl);
                wl1271_flush_deferred_work(wl);
                cancel_work_sync(&wl->netstack_work);
                mutex_lock(&wl->mutex);
@@ -1481,7 +1095,7 @@ int wl1271_plt_stop(struct wl1271 *wl)
         * Otherwise, the interrupt handler might be called and exit without
         * reading the interrupt status.
         */
-       wl1271_disable_interrupts(wl);
+       wlcore_disable_interrupts(wl);
        mutex_lock(&wl->mutex);
        if (!wl->plt) {
                mutex_unlock(&wl->mutex);
@@ -1491,7 +1105,7 @@ int wl1271_plt_stop(struct wl1271 *wl)
                 * may have been disabled when op_stop was called. It will,
                 * however, balance the above call to disable_interrupts().
                 */
-               wl1271_enable_interrupts(wl);
+               wlcore_enable_interrupts(wl);
 
                wl1271_error("cannot power down because not in PLT "
                             "state: %d", wl->state);
@@ -1652,14 +1266,12 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl,
 {
        int ret = 0;
 
-       mutex_lock(&wl->mutex);
-
        if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
-               goto out_unlock;
+               goto out;
 
        ret = wl1271_ps_elp_wakeup(wl);
        if (ret < 0)
-               goto out_unlock;
+               goto out;
 
        ret = wl1271_acx_wake_up_conditions(wl, wlvif,
                                    wl->conf.conn.suspend_wake_up_event,
@@ -1668,11 +1280,9 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl,
        if (ret < 0)
                wl1271_error("suspend: set wake up conditions failed: %d", ret);
 
-
        wl1271_ps_elp_sleep(wl);
 
-out_unlock:
-       mutex_unlock(&wl->mutex);
+out:
        return ret;
 
 }
@@ -1682,20 +1292,17 @@ static int wl1271_configure_suspend_ap(struct wl1271 *wl,
 {
        int ret = 0;
 
-       mutex_lock(&wl->mutex);
-
        if (!test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags))
-               goto out_unlock;
+               goto out;
 
        ret = wl1271_ps_elp_wakeup(wl);
        if (ret < 0)
-               goto out_unlock;
+               goto out;
 
        ret = wl1271_acx_beacon_filter_opt(wl, wlvif, true);
 
        wl1271_ps_elp_sleep(wl);
-out_unlock:
-       mutex_unlock(&wl->mutex);
+out:
        return ret;
 
 }
@@ -1720,10 +1327,9 @@ static void wl1271_configure_resume(struct wl1271 *wl,
        if ((!is_ap) && (!is_sta))
                return;
 
-       mutex_lock(&wl->mutex);
        ret = wl1271_ps_elp_wakeup(wl);
        if (ret < 0)
-               goto out;
+               return;
 
        if (is_sta) {
                ret = wl1271_acx_wake_up_conditions(wl, wlvif,
@@ -1739,8 +1345,6 @@ static void wl1271_configure_resume(struct wl1271 *wl,
        }
 
        wl1271_ps_elp_sleep(wl);
-out:
-       mutex_unlock(&wl->mutex);
 }
 
 static int wl1271_op_suspend(struct ieee80211_hw *hw,
@@ -1755,6 +1359,7 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw,
 
        wl1271_tx_flush(wl);
 
+       mutex_lock(&wl->mutex);
        wl->wow_enabled = true;
        wl12xx_for_each_wlvif(wl, wlvif) {
                ret = wl1271_configure_suspend(wl, wlvif);
@@ -1763,6 +1368,7 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw,
                        return ret;
                }
        }
+       mutex_unlock(&wl->mutex);
        /* flush any remaining work */
        wl1271_debug(DEBUG_MAC80211, "flushing remaining works");
 
@@ -1770,7 +1376,7 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw,
         * disable and re-enable interrupts in order to flush
         * the threaded_irq
         */
-       wl1271_disable_interrupts(wl);
+       wlcore_disable_interrupts(wl);
 
        /*
         * set suspended flag to avoid triggering a new threaded_irq
@@ -1778,7 +1384,7 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw,
         */
        set_bit(WL1271_FLAG_SUSPENDED, &wl->flags);
 
-       wl1271_enable_interrupts(wl);
+       wlcore_enable_interrupts(wl);
        flush_work(&wl->tx_work);
        flush_delayed_work(&wl->elp_work);
 
@@ -1810,12 +1416,15 @@ static int wl1271_op_resume(struct ieee80211_hw *hw)
                wl1271_debug(DEBUG_MAC80211,
                             "run postponed irq_work directly");
                wl1271_irq(0, wl);
-               wl1271_enable_interrupts(wl);
+               wlcore_enable_interrupts(wl);
        }
+
+       mutex_lock(&wl->mutex);
        wl12xx_for_each_wlvif(wl, wlvif) {
                wl1271_configure_resume(wl, wlvif);
        }
        wl->wow_enabled = false;
+       mutex_unlock(&wl->mutex);
 
        return 0;
 }
@@ -1851,7 +1460,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
         * Otherwise, the interrupt handler might be called and exit without
         * reading the interrupt status.
         */
-       wl1271_disable_interrupts(wl);
+       wlcore_disable_interrupts(wl);
        mutex_lock(&wl->mutex);
        if (wl->state == WL1271_STATE_OFF) {
                mutex_unlock(&wl->mutex);
@@ -1861,7 +1470,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
                 * may have been disabled when op_stop was called. It will,
                 * however, balance the above call to disable_interrupts().
                 */
-               wl1271_enable_interrupts(wl);
+               wlcore_enable_interrupts(wl);
                return;
        }
 
@@ -1894,7 +1503,6 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
        wl->tx_results_count = 0;
        wl->tx_packets_count = 0;
        wl->time_offset = 0;
-       wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
        wl->ap_fw_ps_map = 0;
        wl->ap_ps_map = 0;
        wl->sched_scanning = false;
@@ -2067,7 +1675,7 @@ static bool wl12xx_init_fw(struct wl1271 *wl)
                if (ret < 0)
                        goto power_off;
 
-               ret = wl1271_boot(wl);
+               ret = wl->ops->boot(wl);
                if (ret < 0)
                        goto power_off;
 
@@ -2087,7 +1695,7 @@ irq_disable:
                   work function will not do anything.) Also, any other
                   possible concurrent operations will fail due to the
                   current state, hence the wl1271 struct should be safe. */
-               wl1271_disable_interrupts(wl);
+               wlcore_disable_interrupts(wl);
                wl1271_flush_deferred_work(wl);
                cancel_work_sync(&wl->netstack_work);
                mutex_lock(&wl->mutex);
@@ -2360,10 +1968,12 @@ deinit:
                for (i = 0; i < CONF_TX_MAX_AC_COUNT; i++)
                        wl12xx_free_rate_policy(wl,
                                                &wlvif->ap.ucast_rate_idx[i]);
+               wl1271_free_ap_keys(wl, wlvif);
        }
 
+       dev_kfree_skb(wlvif->probereq);
+       wlvif->probereq = NULL;
        wl12xx_tx_reset_wlvif(wl, wlvif);
-       wl1271_free_ap_keys(wl, wlvif);
        if (wl->last_wlvif == wlvif)
                wl->last_wlvif = NULL;
        list_del(&wlvif->list);
@@ -2946,6 +2556,17 @@ static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif,
        int ret;
        bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS);
 
+       /*
+        * A role set to GEM cipher requires different Tx settings (namely
+        * spare blocks). Note when we are in this mode so the HW can adjust.
+        */
+       if (key_type == KEY_GEM) {
+               if (action == KEY_ADD_OR_REPLACE)
+                       wlvif->is_gem = true;
+               else if (action == KEY_REMOVE)
+                       wlvif->is_gem = false;
+       }
+
        if (is_ap) {
                struct wl1271_station *wl_sta;
                u8 hlid;
@@ -2984,17 +2605,6 @@ static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif,
                        0xff, 0xff, 0xff, 0xff, 0xff, 0xff
                };
 
-               /*
-                * A STA set to GEM cipher requires 2 tx spare blocks.
-                * Return to default value when GEM cipher key is removed
-                */
-               if (key_type == KEY_GEM) {
-                       if (action == KEY_ADD_OR_REPLACE)
-                               wl->tx_spare_blocks = 2;
-                       else if (action == KEY_REMOVE)
-                               wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
-               }
-
                addr = sta ? sta->addr : bcast_addr;
 
                if (is_zero_ether_addr(addr)) {
@@ -3791,8 +3401,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
                wlvif->rssi_thold = bss_conf->cqm_rssi_thold;
        }
 
-       if (changed & BSS_CHANGED_BSSID &&
-           (is_ibss || bss_conf->assoc))
+       if (changed & BSS_CHANGED_BSSID)
                if (!is_zero_ether_addr(bss_conf->bssid)) {
                        ret = wl12xx_cmd_build_null_data(wl, wlvif);
                        if (ret < 0)
@@ -3801,9 +3410,6 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
                        ret = wl1271_build_qos_null_data(wl, vif);
                        if (ret < 0)
                                goto out;
-
-                       /* Need to update the BSSID (for filtering etc) */
-                       do_join = true;
                }
 
        if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_HT)) {
@@ -3830,6 +3436,7 @@ sta_not_found:
                        int ieoffset;
                        wlvif->aid = bss_conf->aid;
                        wlvif->beacon_int = bss_conf->beacon_int;
+                       do_join = true;
                        set_assoc = true;
 
                        /*
@@ -4662,60 +4269,12 @@ static struct ieee80211_channel wl1271_channels[] = {
        { .hw_value = 14, .center_freq = 2484, .max_power = 25 },
 };
 
-/* mapping to indexes for wl1271_rates */
-static const u8 wl1271_rate_to_idx_2ghz[] = {
-       /* MCS rates are used only with 11n */
-       7,                            /* CONF_HW_RXTX_RATE_MCS7_SGI */
-       7,                            /* CONF_HW_RXTX_RATE_MCS7 */
-       6,                            /* CONF_HW_RXTX_RATE_MCS6 */
-       5,                            /* CONF_HW_RXTX_RATE_MCS5 */
-       4,                            /* CONF_HW_RXTX_RATE_MCS4 */
-       3,                            /* CONF_HW_RXTX_RATE_MCS3 */
-       2,                            /* CONF_HW_RXTX_RATE_MCS2 */
-       1,                            /* CONF_HW_RXTX_RATE_MCS1 */
-       0,                            /* CONF_HW_RXTX_RATE_MCS0 */
-
-       11,                            /* CONF_HW_RXTX_RATE_54   */
-       10,                            /* CONF_HW_RXTX_RATE_48   */
-       9,                             /* CONF_HW_RXTX_RATE_36   */
-       8,                             /* CONF_HW_RXTX_RATE_24   */
-
-       /* TI-specific rate */
-       CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_22   */
-
-       7,                             /* CONF_HW_RXTX_RATE_18   */
-       6,                             /* CONF_HW_RXTX_RATE_12   */
-       3,                             /* CONF_HW_RXTX_RATE_11   */
-       5,                             /* CONF_HW_RXTX_RATE_9    */
-       4,                             /* CONF_HW_RXTX_RATE_6    */
-       2,                             /* CONF_HW_RXTX_RATE_5_5  */
-       1,                             /* CONF_HW_RXTX_RATE_2    */
-       0                              /* CONF_HW_RXTX_RATE_1    */
-};
-
-/* 11n STA capabilities */
-#define HW_RX_HIGHEST_RATE     72
-
-#define WL12XX_HT_CAP { \
-       .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 | \
-              (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT), \
-       .ht_supported = true, \
-       .ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K, \
-       .ampdu_density = IEEE80211_HT_MPDU_DENSITY_8, \
-       .mcs = { \
-               .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, \
-               .rx_highest = cpu_to_le16(HW_RX_HIGHEST_RATE), \
-               .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \
-               }, \
-}
-
 /* can't be const, mac80211 writes to this */
 static struct ieee80211_supported_band wl1271_band_2ghz = {
        .channels = wl1271_channels,
        .n_channels = ARRAY_SIZE(wl1271_channels),
        .bitrates = wl1271_rates,
        .n_bitrates = ARRAY_SIZE(wl1271_rates),
-       .ht_cap = WL12XX_HT_CAP,
 };
 
 /* 5 GHz data rates for WL1273 */
@@ -4784,48 +4343,11 @@ static struct ieee80211_channel wl1271_channels_5ghz[] = {
        { .hw_value = 165, .center_freq = 5825, .max_power = 25 },
 };
 
-/* mapping to indexes for wl1271_rates_5ghz */
-static const u8 wl1271_rate_to_idx_5ghz[] = {
-       /* MCS rates are used only with 11n */
-       7,                            /* CONF_HW_RXTX_RATE_MCS7_SGI */
-       7,                            /* CONF_HW_RXTX_RATE_MCS7 */
-       6,                            /* CONF_HW_RXTX_RATE_MCS6 */
-       5,                            /* CONF_HW_RXTX_RATE_MCS5 */
-       4,                            /* CONF_HW_RXTX_RATE_MCS4 */
-       3,                            /* CONF_HW_RXTX_RATE_MCS3 */
-       2,                            /* CONF_HW_RXTX_RATE_MCS2 */
-       1,                            /* CONF_HW_RXTX_RATE_MCS1 */
-       0,                            /* CONF_HW_RXTX_RATE_MCS0 */
-
-       7,                             /* CONF_HW_RXTX_RATE_54   */
-       6,                             /* CONF_HW_RXTX_RATE_48   */
-       5,                             /* CONF_HW_RXTX_RATE_36   */
-       4,                             /* CONF_HW_RXTX_RATE_24   */
-
-       /* TI-specific rate */
-       CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_22   */
-
-       3,                             /* CONF_HW_RXTX_RATE_18   */
-       2,                             /* CONF_HW_RXTX_RATE_12   */
-       CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_11   */
-       1,                             /* CONF_HW_RXTX_RATE_9    */
-       0,                             /* CONF_HW_RXTX_RATE_6    */
-       CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_5_5  */
-       CONF_HW_RXTX_RATE_UNSUPPORTED, /* CONF_HW_RXTX_RATE_2    */
-       CONF_HW_RXTX_RATE_UNSUPPORTED  /* CONF_HW_RXTX_RATE_1    */
-};
-
 static struct ieee80211_supported_band wl1271_band_5ghz = {
        .channels = wl1271_channels_5ghz,
        .n_channels = ARRAY_SIZE(wl1271_channels_5ghz),
        .bitrates = wl1271_rates_5ghz,
        .n_bitrates = ARRAY_SIZE(wl1271_rates_5ghz),
-       .ht_cap = WL12XX_HT_CAP,
-};
-
-static const u8 *wl1271_band_rate_to_idx[] = {
-       [IEEE80211_BAND_2GHZ] = wl1271_rate_to_idx_2ghz,
-       [IEEE80211_BAND_5GHZ] = wl1271_rate_to_idx_5ghz
 };
 
 static const struct ieee80211_ops wl1271_ops = {
@@ -4862,18 +4384,18 @@ static const struct ieee80211_ops wl1271_ops = {
 };
 
 
-u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band)
+u8 wlcore_rate_to_idx(struct wl1271 *wl, u8 rate, enum ieee80211_band band)
 {
        u8 idx;
 
-       BUG_ON(band >= sizeof(wl1271_band_rate_to_idx)/sizeof(u8 *));
+       BUG_ON(band >= 2);
 
-       if (unlikely(rate >= CONF_HW_RXTX_RATE_MAX)) {
+       if (unlikely(rate >= wl->hw_tx_rate_tbl_size)) {
                wl1271_error("Illegal RX rate from HW: %d", rate);
                return 0;
        }
 
-       idx = wl1271_band_rate_to_idx[band][rate];
+       idx = wl->band_rate_to_idx[band][rate];
        if (unlikely(idx == CONF_HW_RXTX_RATE_UNSUPPORTED)) {
                wl1271_error("Unsupported RX rate from HW: %d", rate);
                return 0;
@@ -5027,34 +4549,6 @@ static struct bin_attribute fwlog_attr = {
        .read = wl1271_sysfs_read_fwlog,
 };
 
-static bool wl12xx_mac_in_fuse(struct wl1271 *wl)
-{
-       bool supported = false;
-       u8 major, minor;
-
-       if (wl->chip.id == CHIP_ID_1283_PG20) {
-               major = WL128X_PG_GET_MAJOR(wl->hw_pg_ver);
-               minor = WL128X_PG_GET_MINOR(wl->hw_pg_ver);
-
-               /* in wl128x we have the MAC address if the PG is >= (2, 1) */
-               if (major > 2 || (major == 2 && minor >= 1))
-                       supported = true;
-       } else {
-               major = WL127X_PG_GET_MAJOR(wl->hw_pg_ver);
-               minor = WL127X_PG_GET_MINOR(wl->hw_pg_ver);
-
-               /* in wl127x we have the MAC address if the PG is >= (3, 1) */
-               if (major == 3 && minor >= 1)
-                       supported = true;
-       }
-
-       wl1271_debug(DEBUG_PROBE,
-                    "PG Ver major = %d minor = %d, MAC %s present",
-                    major, minor, supported ? "is" : "is not");
-
-       return supported;
-}
-
 static void wl12xx_derive_mac_addresses(struct wl1271 *wl,
                                        u32 oui, u32 nic, int n)
 {
@@ -5080,47 +4574,23 @@ static void wl12xx_derive_mac_addresses(struct wl1271 *wl,
        wl->hw->wiphy->addresses = wl->addresses;
 }
 
-static void wl12xx_get_fuse_mac(struct wl1271 *wl)
-{
-       u32 mac1, mac2;
-
-       wl1271_set_partition(wl, &wl12xx_part_table[PART_DRPW]);
-
-       mac1 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_1);
-       mac2 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_2);
-
-       /* these are the two parts of the BD_ADDR */
-       wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) +
-               ((mac1 & 0xff000000) >> 24);
-       wl->fuse_nic_addr = mac1 & 0xffffff;
-
-       wl1271_set_partition(wl, &wl12xx_part_table[PART_DOWN]);
-}
-
 static int wl12xx_get_hw_info(struct wl1271 *wl)
 {
        int ret;
-       u32 die_info;
 
        ret = wl12xx_set_power_on(wl);
        if (ret < 0)
                goto out;
 
-       wl->chip.id = wl1271_read32(wl, CHIP_ID_B);
+       wl->chip.id = wlcore_read_reg(wl, REG_CHIP_ID_B);
 
-       if (wl->chip.id == CHIP_ID_1283_PG20)
-               die_info = wl1271_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1);
-       else
-               die_info = wl1271_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1);
+       wl->fuse_oui_addr = 0;
+       wl->fuse_nic_addr = 0;
 
-       wl->hw_pg_ver = (s8) (die_info & PG_VER_MASK) >> PG_VER_OFFSET;
+       wl->hw_pg_ver = wl->ops->get_pg_ver(wl);
 
-       if (!wl12xx_mac_in_fuse(wl)) {
-               wl->fuse_oui_addr = 0;
-               wl->fuse_nic_addr = 0;
-       } else {
-               wl12xx_get_fuse_mac(wl);
-       }
+       if (wl->ops->get_mac)
+               wl->ops->get_mac(wl);
 
        wl1271_power_off(wl);
 out:
@@ -5255,8 +4725,12 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
         */
        memcpy(&wl->bands[IEEE80211_BAND_2GHZ], &wl1271_band_2ghz,
               sizeof(wl1271_band_2ghz));
+       memcpy(&wl->bands[IEEE80211_BAND_2GHZ].ht_cap, &wl->ht_cap,
+              sizeof(wl->ht_cap));
        memcpy(&wl->bands[IEEE80211_BAND_5GHZ], &wl1271_band_5ghz,
               sizeof(wl1271_band_5ghz));
+       memcpy(&wl->bands[IEEE80211_BAND_5GHZ].ht_cap, &wl->ht_cap,
+              sizeof(wl->ht_cap));
 
        wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
                &wl->bands[IEEE80211_BAND_2GHZ];
@@ -5280,14 +4754,14 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
        wl->hw->sta_data_size = sizeof(struct wl1271_station);
        wl->hw->vif_data_size = sizeof(struct wl12xx_vif);
 
-       wl->hw->max_rx_aggregation_subframes = 8;
+       wl->hw->max_rx_aggregation_subframes = wl->conf.ht.rx_ba_win_size;
 
        return 0;
 }
 
 #define WL1271_DEFAULT_CHANNEL 0
 
-static struct ieee80211_hw *wl1271_alloc_hw(void)
+struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size)
 {
        struct ieee80211_hw *hw;
        struct wl1271 *wl;
@@ -5306,6 +4780,13 @@ static struct ieee80211_hw *wl1271_alloc_hw(void)
        wl = hw->priv;
        memset(wl, 0, sizeof(*wl));
 
+       wl->priv = kzalloc(priv_size, GFP_KERNEL);
+       if (!wl->priv) {
+               wl1271_error("could not alloc wl priv");
+               ret = -ENOMEM;
+               goto err_priv_alloc;
+       }
+
        INIT_LIST_HEAD(&wl->wlvif_list);
 
        wl->hw = hw;
@@ -5342,7 +4823,6 @@ static struct ieee80211_hw *wl1271_alloc_hw(void)
        wl->quirks = 0;
        wl->platform_quirks = 0;
        wl->sched_scanning = false;
-       wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
        wl->system_hlid = WL12XX_SYSTEM_HLID;
        wl->active_sta_count = 0;
        wl->fwlog_size = 0;
@@ -5352,7 +4832,7 @@ static struct ieee80211_hw *wl1271_alloc_hw(void)
        __set_bit(WL12XX_SYSTEM_HLID, wl->links_map);
 
        memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map));
-       for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
+       for (i = 0; i < wl->num_tx_desc; i++)
                wl->tx_frames[i] = NULL;
 
        spin_lock_init(&wl->wl_lock);
@@ -5361,9 +4841,6 @@ static struct ieee80211_hw *wl1271_alloc_hw(void)
        wl->fw_type = WL12XX_FW_TYPE_NONE;
        mutex_init(&wl->mutex);
 
-       /* Apply default driver configuration. */
-       wl1271_conf_init(wl);
-
        order = get_order(WL1271_AGGR_BUFFER_SIZE);
        wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order);
        if (!wl->aggr_buf) {
@@ -5384,8 +4861,17 @@ static struct ieee80211_hw *wl1271_alloc_hw(void)
                goto err_dummy_packet;
        }
 
+       wl->mbox = kmalloc(sizeof(*wl->mbox), GFP_DMA);
+       if (!wl->mbox) {
+               ret = -ENOMEM;
+               goto err_fwlog;
+       }
+
        return hw;
 
+err_fwlog:
+       free_page((unsigned long)wl->fwlog);
+
 err_dummy_packet:
        dev_kfree_skb(wl->dummy_packet);
 
@@ -5397,14 +4883,18 @@ err_wq:
 
 err_hw:
        wl1271_debugfs_exit(wl);
+       kfree(wl->priv);
+
+err_priv_alloc:
        ieee80211_free_hw(hw);
 
 err_hw_alloc:
 
        return ERR_PTR(ret);
 }
+EXPORT_SYMBOL_GPL(wlcore_alloc_hw);
 
-static int wl1271_free_hw(struct wl1271 *wl)
+int wlcore_free_hw(struct wl1271 *wl)
 {
        /* Unblock any fwlog readers */
        mutex_lock(&wl->mutex);
@@ -5434,10 +4924,12 @@ static int wl1271_free_hw(struct wl1271 *wl)
        kfree(wl->tx_res_if);
        destroy_workqueue(wl->freezable_wq);
 
+       kfree(wl->priv);
        ieee80211_free_hw(wl->hw);
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(wlcore_free_hw);
 
 static irqreturn_t wl12xx_hardirq(int irq, void *cookie)
 {
@@ -5468,22 +4960,22 @@ static irqreturn_t wl12xx_hardirq(int irq, void *cookie)
        return IRQ_WAKE_THREAD;
 }
 
-static int __devinit wl12xx_probe(struct platform_device *pdev)
+int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev)
 {
        struct wl12xx_platform_data *pdata = pdev->dev.platform_data;
-       struct ieee80211_hw *hw;
-       struct wl1271 *wl;
        unsigned long irqflags;
-       int ret = -ENODEV;
+       int ret;
 
-       hw = wl1271_alloc_hw();
-       if (IS_ERR(hw)) {
-               wl1271_error("can't allocate hw");
-               ret = PTR_ERR(hw);
-               goto out;
+       if (!wl->ops || !wl->ptable) {
+               ret = -EINVAL;
+               goto out_free_hw;
        }
 
-       wl = hw->priv;
+       BUG_ON(wl->num_tx_desc > WLCORE_MAX_TX_DESCRIPTORS);
+
+       /* adjust some runtime configuration parameters */
+       wlcore_adjust_conf(wl);
+
        wl->irq = platform_get_irq(pdev, 0);
        wl->ref_clock = pdata->board_ref_clock;
        wl->tcxo_clock = pdata->board_tcxo_clock;
@@ -5512,7 +5004,7 @@ static int __devinit wl12xx_probe(struct platform_device *pdev)
                wl->irq_wake_enabled = true;
                device_init_wakeup(wl->dev, 1);
                if (pdata->pwr_in_suspend)
-                       hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY;
+                       wl->hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY;
 
        }
        disable_irq(wl->irq);
@@ -5546,7 +5038,7 @@ static int __devinit wl12xx_probe(struct platform_device *pdev)
                goto out_hw_pg_ver;
        }
 
-       return 0;
+       goto out;
 
 out_hw_pg_ver:
        device_remove_file(wl->dev, &dev_attr_hw_pg_ver);
@@ -5558,13 +5050,14 @@ out_irq:
        free_irq(wl->irq, wl);
 
 out_free_hw:
-       wl1271_free_hw(wl);
+       wlcore_free_hw(wl);
 
 out:
        return ret;
 }
+EXPORT_SYMBOL_GPL(wlcore_probe);
 
-static int __devexit wl12xx_remove(struct platform_device *pdev)
+int __devexit wlcore_remove(struct platform_device *pdev)
 {
        struct wl1271 *wl = platform_get_drvdata(pdev);
 
@@ -5574,38 +5067,11 @@ static int __devexit wl12xx_remove(struct platform_device *pdev)
        }
        wl1271_unregister_hw(wl);
        free_irq(wl->irq, wl);
-       wl1271_free_hw(wl);
+       wlcore_free_hw(wl);
 
        return 0;
 }
-
-static const struct platform_device_id wl12xx_id_table[] __devinitconst = {
-       { "wl12xx", 0 },
-       {  } /* Terminating Entry */
-};
-MODULE_DEVICE_TABLE(platform, wl12xx_id_table);
-
-static struct platform_driver wl12xx_driver = {
-       .probe          = wl12xx_probe,
-       .remove         = __devexit_p(wl12xx_remove),
-       .id_table       = wl12xx_id_table,
-       .driver = {
-               .name   = "wl12xx_driver",
-               .owner  = THIS_MODULE,
-       }
-};
-
-static int __init wl12xx_init(void)
-{
-       return platform_driver_register(&wl12xx_driver);
-}
-module_init(wl12xx_init);
-
-static void __exit wl12xx_exit(void)
-{
-       platform_driver_unregister(&wl12xx_driver);
-}
-module_exit(wl12xx_exit);
+EXPORT_SYMBOL_GPL(wlcore_remove);
 
 u32 wl12xx_debug_level = DEBUG_NONE;
 EXPORT_SYMBOL_GPL(wl12xx_debug_level);
@@ -5619,6 +5085,9 @@ MODULE_PARM_DESC(fwlog,
 module_param(bug_on_recovery, bool, S_IRUSR | S_IWUSR);
 MODULE_PARM_DESC(bug_on_recovery, "BUG() on fw recovery");
 
+module_param(no_recovery, bool, S_IRUSR | S_IWUSR);
+MODULE_PARM_DESC(no_recovery, "Prevent HW recovery. FW will remain stuck.");
+
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
 MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
similarity index 97%
rename from drivers/net/wireless/wl12xx/ps.c
rename to drivers/net/wireless/ti/wlcore/ps.c
index 78f598b4f97b977cbc747a0bd93b0877bc900ff0..756eee2257b4bc51d857f3068c46b06cc5844907 100644 (file)
@@ -21,7 +21,6 @@
  *
  */
 
-#include "reg.h"
 #include "ps.h"
 #include "io.h"
 #include "tx.h"
@@ -62,7 +61,7 @@ void wl1271_elp_work(struct work_struct *work)
        }
 
        wl1271_debug(DEBUG_PSM, "chip to elp");
-       wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP);
+       wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_SLEEP);
        set_bit(WL1271_FLAG_IN_ELP, &wl->flags);
 
 out:
@@ -74,6 +73,9 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl)
 {
        struct wl12xx_vif *wlvif;
 
+       if (wl->quirks & WLCORE_QUIRK_NO_ELP)
+               return;
+
        /* we shouldn't get consecutive sleep requests */
        if (WARN_ON(test_and_set_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags)))
                return;
@@ -125,7 +127,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl)
                wl->elp_compl = &compl;
        spin_unlock_irqrestore(&wl->wl_lock, flags);
 
-       wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP);
+       wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP);
 
        if (!pending) {
                ret = wait_for_completion_timeout(
similarity index 98%
rename from drivers/net/wireless/wl12xx/ps.h
rename to drivers/net/wireless/ti/wlcore/ps.h
index 5f19d4fbbf27e88345dd7d4fb406d1ad37e2bf0b..de4f9da8ed26b77e13c20437b8e16263192af8f1 100644 (file)
@@ -24,7 +24,7 @@
 #ifndef __PS_H__
 #define __PS_H__
 
-#include "wl12xx.h"
+#include "wlcore.h"
 #include "acx.h"
 
 int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
similarity index 69%
rename from drivers/net/wireless/wl12xx/rx.c
rename to drivers/net/wireless/ti/wlcore/rx.c
index cfa6071704c591d3be1100b469a140302da95489..89bd9385e90be4a1ca4d4659a769cab01a120bd6 100644 (file)
 #include <linux/gfp.h>
 #include <linux/sched.h>
 
-#include "wl12xx.h"
+#include "wlcore.h"
 #include "debug.h"
 #include "acx.h"
-#include "reg.h"
 #include "rx.h"
 #include "tx.h"
 #include "io.h"
+#include "hw_ops.h"
 
-static u8 wl12xx_rx_get_mem_block(struct wl12xx_fw_status *status,
-                                 u32 drv_rx_counter)
-{
-       return le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
-               RX_MEM_BLOCK_MASK;
-}
+/*
+ * TODO: this is here just for now, it must be removed when the data
+ * operations are in place.
+ */
+#include "../wl12xx/reg.h"
 
-static u32 wl12xx_rx_get_buf_size(struct wl12xx_fw_status *status,
-                                u32 drv_rx_counter)
+static u32 wlcore_rx_get_buf_size(struct wl1271 *wl,
+                                 u32 rx_pkt_desc)
 {
-       return (le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
-               RX_BUF_SIZE_MASK) >> RX_BUF_SIZE_SHIFT_DIV;
+       if (wl->quirks & WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN)
+               return (rx_pkt_desc & ALIGNED_RX_BUF_SIZE_MASK) >>
+                      ALIGNED_RX_BUF_SIZE_SHIFT;
+
+       return (rx_pkt_desc & RX_BUF_SIZE_MASK) >> RX_BUF_SIZE_SHIFT_DIV;
 }
 
-static bool wl12xx_rx_get_unaligned(struct wl12xx_fw_status *status,
-                                   u32 drv_rx_counter)
+static u32 wlcore_rx_get_align_buf_size(struct wl1271 *wl, u32 pkt_len)
 {
-       /* Convert the value to bool */
-       return !!(le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
-               RX_BUF_UNALIGNED_PAYLOAD);
+       if (wl->quirks & WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN)
+               return ALIGN(pkt_len, WL12XX_BUS_BLOCK_SIZE);
+
+       return pkt_len;
 }
 
 static void wl1271_rx_status(struct wl1271 *wl,
@@ -66,10 +68,10 @@ static void wl1271_rx_status(struct wl1271 *wl,
        else
                status->band = IEEE80211_BAND_5GHZ;
 
-       status->rate_idx = wl1271_rate_to_idx(desc->rate, status->band);
+       status->rate_idx = wlcore_rate_to_idx(wl, desc->rate, status->band);
 
        /* 11n support */
-       if (desc->rate <= CONF_HW_RXTX_RATE_MCS0)
+       if (desc->rate <= wl->hw_min_ht_rate)
                status->flag |= RX_FLAG_HT;
 
        status->signal = desc->rssi;
@@ -98,7 +100,7 @@ static void wl1271_rx_status(struct wl1271 *wl,
 }
 
 static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
-                                bool unaligned, u8 *hlid)
+                                enum wl_rx_buf_align rx_align, u8 *hlid)
 {
        struct wl1271_rx_descriptor *desc;
        struct sk_buff *skb;
@@ -106,8 +108,9 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
        u8 *buf;
        u8 beacon = 0;
        u8 is_data = 0;
-       u8 reserved = unaligned ? NET_IP_ALIGN : 0;
+       u8 reserved = 0;
        u16 seq_num;
+       u32 pkt_data_len;
 
        /*
         * In PLT mode we seem to get frames and mac80211 warns about them,
@@ -116,6 +119,16 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
        if (unlikely(wl->plt))
                return -EINVAL;
 
+       pkt_data_len = wlcore_hw_get_rx_packet_len(wl, data, length);
+       if (!pkt_data_len) {
+               wl1271_error("Invalid packet arrived from HW. length %d",
+                            length);
+               return -EINVAL;
+       }
+
+       if (rx_align == WLCORE_RX_BUF_UNALIGNED)
+               reserved = NET_IP_ALIGN;
+
        /* the data read starts with the descriptor */
        desc = (struct wl1271_rx_descriptor *) data;
 
@@ -142,8 +155,8 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
                return -EINVAL;
        }
 
-       /* skb length not included rx descriptor */
-       skb = __dev_alloc_skb(length + reserved - sizeof(*desc), GFP_KERNEL);
+       /* skb length not including rx descriptor */
+       skb = __dev_alloc_skb(pkt_data_len + reserved, GFP_KERNEL);
        if (!skb) {
                wl1271_error("Couldn't allocate RX frame");
                return -ENOMEM;
@@ -152,7 +165,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
        /* reserve the unaligned payload(if any) */
        skb_reserve(skb, reserved);
 
-       buf = skb_put(skb, length - sizeof(*desc));
+       buf = skb_put(skb, pkt_data_len);
 
        /*
         * Copy packets from aggregation buffer to the skbs without rx
@@ -160,7 +173,10 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
         * packets copy the packets in offset of 2 bytes guarantee IP header
         * payload aligned to 4 bytes.
         */
-       memcpy(buf, data + sizeof(*desc), length - sizeof(*desc));
+       memcpy(buf, data + sizeof(*desc), pkt_data_len);
+       if (rx_align == WLCORE_RX_BUF_PADDED)
+               skb_pull(skb, NET_IP_ALIGN);
+
        *hlid = desc->hlid;
 
        hdr = (struct ieee80211_hdr *)skb->data;
@@ -177,36 +193,35 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
                     beacon ? "beacon" : "",
                     seq_num, *hlid);
 
-       skb_trim(skb, skb->len - desc->pad_len);
-
        skb_queue_tail(&wl->deferred_rx_queue, skb);
        queue_work(wl->freezable_wq, &wl->netstack_work);
 
        return is_data;
 }
 
-void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
+void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status *status)
 {
-       struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map;
        unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0};
        u32 buf_size;
        u32 fw_rx_counter  = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
        u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
        u32 rx_counter;
-       u32 mem_block;
-       u32 pkt_length;
-       u32 pkt_offset;
+       u32 pkt_len, align_pkt_len;
+       u32 pkt_offset, des;
        u8 hlid;
-       bool unaligned = false;
+       enum wl_rx_buf_align rx_align;
 
        while (drv_rx_counter != fw_rx_counter) {
                buf_size = 0;
                rx_counter = drv_rx_counter;
                while (rx_counter != fw_rx_counter) {
-                       pkt_length = wl12xx_rx_get_buf_size(status, rx_counter);
-                       if (buf_size + pkt_length > WL1271_AGGR_BUFFER_SIZE)
+                       des = le32_to_cpu(status->rx_pkt_descs[rx_counter]);
+                       pkt_len = wlcore_rx_get_buf_size(wl, des);
+                       align_pkt_len = wlcore_rx_get_align_buf_size(wl,
+                                                                    pkt_len);
+                       if (buf_size + align_pkt_len > WL1271_AGGR_BUFFER_SIZE)
                                break;
-                       buf_size += pkt_length;
+                       buf_size += align_pkt_len;
                        rx_counter++;
                        rx_counter &= NUM_RX_PKT_DESC_MOD_MASK;
                }
@@ -216,38 +231,18 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
                        break;
                }
 
-               if (wl->chip.id != CHIP_ID_1283_PG20) {
-                       /*
-                        * Choose the block we want to read
-                        * For aggregated packets, only the first memory block
-                        * should be retrieved. The FW takes care of the rest.
-                        */
-                       mem_block = wl12xx_rx_get_mem_block(status,
-                                                           drv_rx_counter);
-
-                       wl->rx_mem_pool_addr.addr = (mem_block << 8) +
-                          le32_to_cpu(wl_mem_map->packet_memory_pool_start);
-
-                       wl->rx_mem_pool_addr.addr_extra =
-                               wl->rx_mem_pool_addr.addr + 4;
-
-                       wl1271_write(wl, WL1271_SLV_REG_DATA,
-                                    &wl->rx_mem_pool_addr,
-                                    sizeof(wl->rx_mem_pool_addr), false);
-               }
-
                /* Read all available packets at once */
-               wl1271_read(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf,
-                               buf_size, true);
+               des = le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]);
+               wlcore_hw_prepare_read(wl, des, buf_size);
+               wlcore_read_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf,
+                                buf_size, true);
 
                /* Split data into separate packets */
                pkt_offset = 0;
                while (pkt_offset < buf_size) {
-                       pkt_length = wl12xx_rx_get_buf_size(status,
-                                       drv_rx_counter);
-
-                       unaligned = wl12xx_rx_get_unaligned(status,
-                                       drv_rx_counter);
+                       des = le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]);
+                       pkt_len = wlcore_rx_get_buf_size(wl, des);
+                       rx_align = wlcore_hw_get_rx_buf_align(wl, des);
 
                        /*
                         * the handle data call can only fail in memory-outage
@@ -256,7 +251,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
                         */
                        if (wl1271_rx_handle_data(wl,
                                                  wl->aggr_buf + pkt_offset,
-                                                 pkt_length, unaligned,
+                                                 pkt_len, rx_align,
                                                  &hlid) == 1) {
                                if (hlid < WL12XX_MAX_LINKS)
                                        __set_bit(hlid, active_hlids);
@@ -269,7 +264,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
                        wl->rx_counter++;
                        drv_rx_counter++;
                        drv_rx_counter &= NUM_RX_PKT_DESC_MOD_MASK;
-                       pkt_offset += pkt_length;
+                       pkt_offset += wlcore_rx_get_align_buf_size(wl, pkt_len);
                }
        }
 
@@ -277,8 +272,9 @@ void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_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)
-               wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
+       if (wl->quirks & WLCORE_QUIRK_END_OF_TRANSACTION)
+               wl1271_write32(wl, WL12XX_REG_RX_DRIVER_COUNTER,
+                              wl->rx_counter);
 
        wl12xx_rearm_rx_streaming(wl, active_hlids);
 }
similarity index 92%
rename from drivers/net/wireless/wl12xx/rx.h
rename to drivers/net/wireless/ti/wlcore/rx.h
index 86ba6b1d0cdc42a59889cb364d95f29d6c911d2b..6e129e2a85465a5521468268bdeec56f2326fb96 100644 (file)
 #define RX_MEM_BLOCK_MASK            0xFF
 #define RX_BUF_SIZE_MASK             0xFFF00
 #define RX_BUF_SIZE_SHIFT_DIV        6
+#define ALIGNED_RX_BUF_SIZE_MASK     0xFFFF00
+#define ALIGNED_RX_BUF_SIZE_SHIFT    8
+
 /* If set, the start of IP payload is not 4 bytes aligned */
 #define RX_BUF_UNALIGNED_PAYLOAD     BIT(20)
 
+/* Describes the alignment state of a Rx buffer */
+enum wl_rx_buf_align {
+       WLCORE_RX_BUF_ALIGNED,
+       WLCORE_RX_BUF_UNALIGNED,
+       WLCORE_RX_BUF_PADDED,
+};
+
 enum {
        WL12XX_RX_CLASS_UNKNOWN,
        WL12XX_RX_CLASS_MANAGEMENT,
@@ -126,7 +136,7 @@ struct wl1271_rx_descriptor {
        u8  reserved;
 } __packed;
 
-void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status);
+void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status *status);
 u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
 
 #endif
similarity index 95%
rename from drivers/net/wireless/wl12xx/scan.c
rename to drivers/net/wireless/ti/wlcore/scan.c
index fcba055ef196a050023796152d66cafb550c68e2..ade21a011c458dcee0e67fccd8c54756f3e30332 100644 (file)
@@ -23,7 +23,7 @@
 
 #include <linux/ieee80211.h>
 
-#include "wl12xx.h"
+#include "wlcore.h"
 #include "debug.h"
 #include "cmd.h"
 #include "scan.h"
@@ -417,6 +417,23 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl,
        int i, j;
        u32 flags;
        bool force_passive = !req->n_ssids;
+       u32 min_dwell_time_active, max_dwell_time_active, delta_per_probe;
+       u32 dwell_time_passive, dwell_time_dfs;
+
+       if (band == IEEE80211_BAND_5GHZ)
+               delta_per_probe = c->dwell_time_delta_per_probe_5;
+       else
+               delta_per_probe = c->dwell_time_delta_per_probe;
+
+       min_dwell_time_active = c->base_dwell_time +
+                req->n_ssids * c->num_probe_reqs * delta_per_probe;
+
+       max_dwell_time_active = min_dwell_time_active + c->max_dwell_time_delta;
+
+       min_dwell_time_active = DIV_ROUND_UP(min_dwell_time_active, 1000);
+       max_dwell_time_active = DIV_ROUND_UP(max_dwell_time_active, 1000);
+       dwell_time_passive = DIV_ROUND_UP(c->dwell_time_passive, 1000);
+       dwell_time_dfs = DIV_ROUND_UP(c->dwell_time_dfs, 1000);
 
        for (i = 0, j = start;
             i < req->n_channels && j < max_channels;
@@ -440,21 +457,24 @@ wl1271_scan_get_sched_scan_channels(struct wl1271 *wl,
                                     req->channels[i]->flags);
                        wl1271_debug(DEBUG_SCAN, "max_power %d",
                                     req->channels[i]->max_power);
+                       wl1271_debug(DEBUG_SCAN, "min_dwell_time %d max dwell time %d",
+                                    min_dwell_time_active,
+                                    max_dwell_time_active);
 
                        if (flags & IEEE80211_CHAN_RADAR) {
                                channels[j].flags |= SCAN_CHANNEL_FLAGS_DFS;
 
                                channels[j].passive_duration =
-                                       cpu_to_le16(c->dwell_time_dfs);
+                                       cpu_to_le16(dwell_time_dfs);
                        } else {
                                channels[j].passive_duration =
-                                       cpu_to_le16(c->dwell_time_passive);
+                                       cpu_to_le16(dwell_time_passive);
                        }
 
                        channels[j].min_duration =
-                               cpu_to_le16(c->min_dwell_time_active);
+                               cpu_to_le16(min_dwell_time_active);
                        channels[j].max_duration =
-                               cpu_to_le16(c->max_dwell_time_active);
+                               cpu_to_le16(max_dwell_time_active);
 
                        channels[j].tx_power_att = req->channels[i]->max_power;
                        channels[j].channel = req->channels[i]->hw_value;
similarity index 98%
rename from drivers/net/wireless/wl12xx/scan.h
rename to drivers/net/wireless/ti/wlcore/scan.h
index 96ff457a3a0bee224996788195d9fcdb49bdb31b..81ee36ac20785f23d364e2a3b3ef45674ba537f8 100644 (file)
@@ -24,7 +24,7 @@
 #ifndef __SCAN_H__
 #define __SCAN_H__
 
-#include "wl12xx.h"
+#include "wlcore.h"
 
 int wl1271_scan(struct wl1271 *wl, struct ieee80211_vif *vif,
                const u8 *ssid, size_t ssid_len,
@@ -55,7 +55,7 @@ void wl1271_scan_sched_scan_results(struct wl1271 *wl);
 #define WL1271_SCAN_BAND_2_4_GHZ 0
 #define WL1271_SCAN_BAND_5_GHZ 1
 
-#define WL1271_SCAN_TIMEOUT    10000 /* msec */
+#define WL1271_SCAN_TIMEOUT    30000 /* msec */
 
 enum {
        WL1271_SCAN_STATE_IDLE,
similarity index 98%
rename from drivers/net/wireless/wl12xx/sdio.c
rename to drivers/net/wireless/ti/wlcore/sdio.c
index 4b3c32774baee1978a45bb5ee95d62f0840a041c..0a72347cfc4c79e3184e04607803105d202f9452 100644 (file)
@@ -33,7 +33,7 @@
 #include <linux/wl12xx.h>
 #include <linux/pm_runtime.h>
 
-#include "wl12xx.h"
+#include "wlcore.h"
 #include "wl12xx_80211.h"
 #include "io.h"
 
@@ -76,7 +76,7 @@ static void wl12xx_sdio_raw_read(struct device *child, int addr, void *buf,
 
        sdio_claim_host(func);
 
-       if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) {
+       if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG)) {
                ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret);
                dev_dbg(child->parent, "sdio read 52 addr 0x%x, byte 0x%02x\n",
                        addr, ((u8 *)buf)[0]);
@@ -105,7 +105,7 @@ static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf,
 
        sdio_claim_host(func);
 
-       if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) {
+       if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG)) {
                sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret);
                dev_dbg(child->parent, "sdio write 52 addr 0x%x, byte 0x%02x\n",
                        addr, ((u8 *)buf)[0]);
similarity index 99%
rename from drivers/net/wireless/wl12xx/spi.c
rename to drivers/net/wireless/ti/wlcore/spi.c
index 2fc18a8dcce8329436805a38d0582578325a8368..553cd3cbb98c0a7f054db94383b422d9c65f5870 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 
-#include "wl12xx.h"
+#include "wlcore.h"
 #include "wl12xx_80211.h"
 #include "io.h"
 
-#include "reg.h"
-
 #define WSPI_CMD_READ                 0x40000000
 #define WSPI_CMD_WRITE                0x00000000
 #define WSPI_CMD_FIXED                0x20000000
similarity index 99%
rename from drivers/net/wireless/wl12xx/testmode.c
rename to drivers/net/wireless/ti/wlcore/testmode.c
index 1e93bb9c0246cfa02e44f6160851909b422b14ec..9cda706e4e3f83bf107e1889b2a12873aa4000ac 100644 (file)
 #include <linux/slab.h>
 #include <net/genetlink.h>
 
-#include "wl12xx.h"
+#include "wlcore.h"
 #include "debug.h"
 #include "acx.h"
-#include "reg.h"
 #include "ps.h"
 #include "io.h"
 
similarity index 90%
rename from drivers/net/wireless/wl12xx/tx.c
rename to drivers/net/wireless/ti/wlcore/tx.c
index 43ae49143d68bf47a4fa98c25f15b5d3b20cd3a9..6893bc2079941e93c8d1d07e265508a30199e9ee 100644 (file)
 #include <linux/module.h>
 #include <linux/etherdevice.h>
 
-#include "wl12xx.h"
+#include "wlcore.h"
 #include "debug.h"
 #include "io.h"
-#include "reg.h"
 #include "ps.h"
 #include "tx.h"
 #include "event.h"
+#include "hw_ops.h"
+
+/*
+ * TODO: this is here just for now, it must be removed when the data
+ * operations are in place.
+ */
+#include "../wl12xx/reg.h"
 
 static int wl1271_set_default_wep_key(struct wl1271 *wl,
                                      struct wl12xx_vif *wlvif, u8 id)
@@ -56,8 +62,8 @@ static int wl1271_alloc_tx_id(struct wl1271 *wl, struct sk_buff *skb)
 {
        int id;
 
-       id = find_first_zero_bit(wl->tx_frames_map, ACX_TX_DESCRIPTORS);
-       if (id >= ACX_TX_DESCRIPTORS)
+       id = find_first_zero_bit(wl->tx_frames_map, wl->num_tx_desc);
+       if (id >= wl->num_tx_desc)
                return -EBUSY;
 
        __set_bit(id, wl->tx_frames_map);
@@ -69,7 +75,7 @@ static int wl1271_alloc_tx_id(struct wl1271 *wl, struct sk_buff *skb)
 static void wl1271_free_tx_id(struct wl1271 *wl, int id)
 {
        if (__test_and_clear_bit(id, wl->tx_frames_map)) {
-               if (unlikely(wl->tx_frames_cnt == ACX_TX_DESCRIPTORS))
+               if (unlikely(wl->tx_frames_cnt == wl->num_tx_desc))
                        clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags);
 
                wl->tx_frames[id] = NULL;
@@ -167,14 +173,15 @@ u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif,
                return wlvif->dev_hlid;
 }
 
-static unsigned int wl12xx_calc_packet_alignment(struct wl1271 *wl,
-                                               unsigned int packet_length)
+unsigned int wlcore_calc_packet_alignment(struct wl1271 *wl,
+                                         unsigned int packet_length)
 {
-       if (wl->quirks & WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT)
-               return ALIGN(packet_length, WL1271_TX_ALIGN_TO);
-       else
+       if (wl->quirks & WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN)
                return ALIGN(packet_length, WL12XX_BUS_BLOCK_SIZE);
+       else
+               return ALIGN(packet_length, WL1271_TX_ALIGN_TO);
 }
+EXPORT_SYMBOL(wlcore_calc_packet_alignment);
 
 static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif,
                              struct sk_buff *skb, u32 extra, u32 buf_offset,
@@ -182,10 +189,9 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif,
 {
        struct wl1271_tx_hw_descr *desc;
        u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra;
-       u32 len;
        u32 total_blocks;
        int id, ret = -EBUSY, ac;
-       u32 spare_blocks = wl->tx_spare_blocks;
+       u32 spare_blocks = wl->normal_tx_spare;
        bool is_dummy = false;
 
        if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE)
@@ -196,30 +202,19 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif,
        if (id < 0)
                return id;
 
-       /* approximate the number of blocks required for this packet
-          in the firmware */
-       len = wl12xx_calc_packet_alignment(wl, total_len);
-
-       /* in case of a dummy packet, use default amount of spare mem blocks */
-       if (unlikely(wl12xx_is_dummy_packet(wl, skb))) {
+       if (unlikely(wl12xx_is_dummy_packet(wl, skb)))
                is_dummy = true;
-               spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
-       }
+       else if (wlvif->is_gem)
+               spare_blocks = wl->gem_tx_spare;
 
-       total_blocks = (len + TX_HW_BLOCK_SIZE - 1) / TX_HW_BLOCK_SIZE +
-               spare_blocks;
+       total_blocks = wlcore_hw_calc_tx_blocks(wl, total_len, spare_blocks);
 
        if (total_blocks <= wl->tx_blocks_available) {
                desc = (struct wl1271_tx_hw_descr *)skb_push(
                        skb, total_len - skb->len);
 
-               /* 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 = spare_blocks;
-                       desc->wl127x_mem.total_mem_blocks = total_blocks;
-               }
+               wlcore_hw_set_tx_desc_blocks(wl, desc, total_blocks,
+                                            spare_blocks);
 
                desc->id = id;
 
@@ -256,7 +251,7 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif,
 {
        struct timespec ts;
        struct wl1271_tx_hw_descr *desc;
-       int aligned_len, ac, rate_idx;
+       int ac, rate_idx;
        s64 hosttime;
        u16 tx_attr = 0;
        __le16 frame_control;
@@ -329,44 +324,16 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif,
        }
 
        tx_attr |= rate_idx << TX_HW_ATTR_OFST_RATE_POLICY;
-       desc->reserved = 0;
-
-       aligned_len = wl12xx_calc_packet_alignment(wl, skb->len);
-
-       if (wl->chip.id == CHIP_ID_1283_PG20) {
-               desc->wl128x_mem.extra_bytes = aligned_len - skb->len;
-               desc->length = cpu_to_le16(aligned_len >> 2);
-
-               wl1271_debug(DEBUG_TX, "tx_fill_hdr: hlid: %d "
-                            "tx_attr: 0x%x len: %d life: %d mem: %d",
-                            desc->hlid, tx_attr,
-                            le16_to_cpu(desc->length),
-                            le16_to_cpu(desc->life_time),
-                            desc->wl128x_mem.total_mem_blocks);
-       } else {
-               int pad;
-
-               /* Store the aligned length in terms of words */
-               desc->length = cpu_to_le16(aligned_len >> 2);
-
-               /* calculate number of padding bytes */
-               pad = aligned_len - skb->len;
-               tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD;
-
-               wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d hlid: %d "
-                            "tx_attr: 0x%x len: %d life: %d mem: %d", pad,
-                            desc->hlid, tx_attr,
-                            le16_to_cpu(desc->length),
-                            le16_to_cpu(desc->life_time),
-                            desc->wl127x_mem.total_mem_blocks);
-       }
 
        /* for WEP shared auth - no fw encryption is needed */
        if (ieee80211_is_auth(frame_control) &&
            ieee80211_has_protected(frame_control))
                tx_attr |= TX_HW_ATTR_HOST_ENCRYPT;
 
+       desc->reserved = 0;
        desc->tx_attr = cpu_to_le16(tx_attr);
+
+       wlcore_hw_set_tx_desc_data_len(wl, desc, skb);
 }
 
 /* caller must hold wl->mutex */
@@ -432,7 +399,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif,
         * In special cases, we want to align to a specific block size
         * (eg. for wl128x with SDIO we align to 256).
         */
-       total_len = wl12xx_calc_packet_alignment(wl, skb->len);
+       total_len = wlcore_calc_packet_alignment(wl, skb->len);
 
        memcpy(wl->aggr_buf + buf_offset, skb->data, skb->len);
        memset(wl->aggr_buf + buf_offset + skb->len, 0, total_len - skb->len);
@@ -718,8 +685,8 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
                         * Flush buffer and try again.
                         */
                        wl1271_skb_queue_head(wl, wlvif, skb);
-                       wl1271_write(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf,
-                                    buf_offset, true);
+                       wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf,
+                                         buf_offset, true);
                        sent_packets = true;
                        buf_offset = 0;
                        continue;
@@ -753,8 +720,8 @@ void wl1271_tx_work_locked(struct wl1271 *wl)
 
 out_ack:
        if (buf_offset) {
-               wl1271_write(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf,
-                               buf_offset, true);
+               wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf,
+                                 buf_offset, true);
                sent_packets = true;
        }
        if (sent_packets) {
@@ -762,8 +729,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)
-                       wl1271_write32(wl, WL1271_HOST_WR_ACCESS,
+               if (wl->quirks & WLCORE_QUIRK_END_OF_TRANSACTION)
+                       wl1271_write32(wl, WL12XX_HOST_WR_ACCESS,
                                       wl->tx_packets_count);
 
                wl1271_handle_tx_low_watermark(wl);
@@ -792,11 +759,20 @@ static u8 wl1271_tx_get_rate_flags(u8 rate_class_index)
 {
        u8 flags = 0;
 
-       if (rate_class_index >= CONF_HW_RXTX_RATE_MCS_MIN &&
-           rate_class_index <= CONF_HW_RXTX_RATE_MCS_MAX)
+       /*
+        * TODO: use wl12xx constants when this code is moved to wl12xx, as
+        * only it uses Tx-completion.
+        */
+       if (rate_class_index <= 8)
                flags |= IEEE80211_TX_RC_MCS;
-       if (rate_class_index == CONF_HW_RXTX_RATE_MCS7_SGI)
+
+       /*
+        * TODO: use wl12xx constants when this code is moved to wl12xx, as
+        * only it uses Tx-completion.
+        */
+       if (rate_class_index == 0)
                flags |= IEEE80211_TX_RC_SHORT_GI;
+
        return flags;
 }
 
@@ -813,7 +789,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
        u8 retries = 0;
 
        /* check for id legality */
-       if (unlikely(id >= ACX_TX_DESCRIPTORS || wl->tx_frames[id] == NULL)) {
+       if (unlikely(id >= wl->num_tx_desc || wl->tx_frames[id] == NULL)) {
                wl1271_warning("TX result illegal id: %d", id);
                return;
        }
@@ -834,7 +810,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
        if (result->status == TX_SUCCESS) {
                if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
                        info->flags |= IEEE80211_TX_STAT_ACK;
-               rate = wl1271_rate_to_idx(result->rate_class_index,
+               rate = wlcore_rate_to_idx(wl, result->rate_class_index,
                                          wlvif->band);
                rate_flags = wl1271_tx_get_rate_flags(result->rate_class_index);
                retries = result->ack_failures;
@@ -929,6 +905,7 @@ void wl1271_tx_complete(struct wl1271 *wl)
                wl->tx_results_count++;
        }
 }
+EXPORT_SYMBOL(wl1271_tx_complete);
 
 void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid)
 {
@@ -1006,7 +983,7 @@ void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
        if (reset_tx_queues)
                wl1271_handle_tx_low_watermark(wl);
 
-       for (i = 0; i < ACX_TX_DESCRIPTORS; i++) {
+       for (i = 0; i < wl->num_tx_desc; i++) {
                if (wl->tx_frames[i] == NULL)
                        continue;
 
similarity index 97%
rename from drivers/net/wireless/wl12xx/tx.h
rename to drivers/net/wireless/ti/wlcore/tx.h
index 5cf8c32d40d14e1915a6e65eaa2e980b35ecaef3..2fd6e5dc6f7567324d5e75c9dabd9975eb238c56 100644 (file)
@@ -25,9 +25,6 @@
 #ifndef __TX_H__
 #define __TX_H__
 
-#define TX_HW_BLOCK_SPARE_DEFAULT        1
-#define TX_HW_BLOCK_SIZE                 252
-
 #define TX_HW_MGMT_PKT_LIFETIME_TU       2000
 #define TX_HW_AP_MODE_PKT_LIFETIME_TU    8000
 
@@ -212,7 +209,7 @@ void wl1271_tx_complete(struct wl1271 *wl);
 void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif);
 void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues);
 void wl1271_tx_flush(struct wl1271 *wl);
-u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
+u8 wlcore_rate_to_idx(struct wl1271 *wl, u8 rate, enum ieee80211_band band);
 u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set,
                                enum ieee80211_band rate_band);
 u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set);
@@ -224,6 +221,8 @@ void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid);
 void wl1271_handle_tx_low_watermark(struct wl1271 *wl);
 bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb);
 void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids);
+unsigned int wlcore_calc_packet_alignment(struct wl1271 *wl,
+                                         unsigned int packet_length);
 
 /* from main.c */
 void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid);
similarity index 68%
rename from drivers/net/wireless/wl12xx/wl12xx.h
rename to drivers/net/wireless/ti/wlcore/wl12xx.h
index 749a15a75d384c763b5bf68a06b038a3961e2af0..a9b220c43e54c91400c392e7f1d6b777a9ec2c7e 100644 (file)
@@ -89,8 +89,6 @@
 #define WL1271_AP_BSS_INDEX        0
 #define WL1271_AP_DEF_BEACON_EXP   20
 
-#define ACX_TX_DESCRIPTORS         16
-
 #define WL1271_AGGR_BUFFER_SIZE (4 * PAGE_SIZE)
 
 enum wl1271_state {
@@ -105,26 +103,6 @@ enum wl12xx_fw_type {
        WL12XX_FW_TYPE_PLT,
 };
 
-enum wl1271_partition_type {
-       PART_DOWN,
-       PART_WORK,
-       PART_DRPW,
-
-       PART_TABLE_LEN
-};
-
-struct wl1271_partition {
-       u32 size;
-       u32 start;
-};
-
-struct wl1271_partition_set {
-       struct wl1271_partition mem;
-       struct wl1271_partition reg;
-       struct wl1271_partition mem2;
-       struct wl1271_partition mem3;
-};
-
 struct wl1271;
 
 enum {
@@ -167,8 +145,21 @@ struct wl1271_stats {
 
 #define AP_MAX_STATIONS            8
 
+struct wl_fw_packet_counters {
+       /* Cumulative counter of released packets per AC */
+       u8 tx_released_pkts[NUM_TX_QUEUES];
+
+       /* Cumulative counter of freed packets per HLID */
+       u8 tx_lnk_free_pkts[WL12XX_MAX_LINKS];
+
+       /* Cumulative counter of released Voice memory blocks */
+       u8 tx_voice_released_blks;
+
+       u8 padding[3];
+} __packed;
+
 /* FW status registers */
-struct wl12xx_fw_status {
+struct wl_fw_status {
        __le32 intr;
        u8  fw_rx_counter;
        u8  drv_rx_counter;
@@ -195,16 +186,12 @@ struct wl12xx_fw_status {
        /* Size (in Memory Blocks) of TX pool */
        __le32 tx_total;
 
-       /* Cumulative counter of released packets per AC */
-       u8 tx_released_pkts[NUM_TX_QUEUES];
+       struct wl_fw_packet_counters counters;
 
-       /* Cumulative counter of freed packets per HLID */
-       u8 tx_lnk_free_pkts[WL12XX_MAX_LINKS];
-
-       /* Cumulative counter of released Voice memory blocks */
-       u8 tx_voice_released_blks;
-       u8 padding_1[3];
        __le32 log_start_addr;
+
+       /* Private status to be used by the lower drivers */
+       u8 priv[0];
 } __packed;
 
 struct wl1271_rx_mem_pool_addr {
@@ -292,214 +279,6 @@ struct wl1271_link {
        u8 ba_bitmap;
 };
 
-struct wl1271 {
-       struct ieee80211_hw *hw;
-       bool mac80211_registered;
-
-       struct device *dev;
-
-       void *if_priv;
-
-       struct wl1271_if_operations *if_ops;
-
-       void (*set_power)(bool enable);
-       int irq;
-       int ref_clock;
-
-       spinlock_t wl_lock;
-
-       enum wl1271_state state;
-       enum wl12xx_fw_type fw_type;
-       bool plt;
-       u8 last_vif_count;
-       struct mutex mutex;
-
-       unsigned long flags;
-
-       struct wl1271_partition_set part;
-
-       struct wl1271_chip chip;
-
-       int cmd_box_addr;
-       int event_box_addr;
-
-       u8 *fw;
-       size_t fw_len;
-       void *nvs;
-       size_t nvs_len;
-
-       s8 hw_pg_ver;
-
-       /* address read from the fuse ROM */
-       u32 fuse_oui_addr;
-       u32 fuse_nic_addr;
-
-       /* we have up to 2 MAC addresses */
-       struct mac_address addresses[2];
-       int channel;
-       u8 system_hlid;
-
-       unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)];
-       unsigned long roles_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];
-       unsigned long roc_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];
-       unsigned long rate_policies_map[
-                       BITS_TO_LONGS(WL12XX_MAX_RATE_POLICIES)];
-
-       struct list_head wlvif_list;
-
-       u8 sta_count;
-       u8 ap_count;
-
-       struct wl1271_acx_mem_map *target_mem_map;
-
-       /* Accounting for allocated / available TX blocks on HW */
-       u32 tx_blocks_freed;
-       u32 tx_blocks_available;
-       u32 tx_allocated_blocks;
-       u32 tx_results_count;
-
-       /* amount of spare TX blocks to use */
-       u32 tx_spare_blocks;
-
-       /* Accounting for allocated / available Tx packets in HW */
-       u32 tx_pkts_freed[NUM_TX_QUEUES];
-       u32 tx_allocated_pkts[NUM_TX_QUEUES];
-
-       /* Transmitted TX packets counter for chipset interface */
-       u32 tx_packets_count;
-
-       /* Time-offset between host and chipset clocks */
-       s64 time_offset;
-
-       /* Frames scheduled for transmission, not handled yet */
-       int tx_queue_count[NUM_TX_QUEUES];
-       long stopped_queues_map;
-
-       /* Frames received, not handled yet by mac80211 */
-       struct sk_buff_head deferred_rx_queue;
-
-       /* Frames sent, not returned yet to mac80211 */
-       struct sk_buff_head deferred_tx_queue;
-
-       struct work_struct tx_work;
-       struct workqueue_struct *freezable_wq;
-
-       /* Pending TX frames */
-       unsigned long tx_frames_map[BITS_TO_LONGS(ACX_TX_DESCRIPTORS)];
-       struct sk_buff *tx_frames[ACX_TX_DESCRIPTORS];
-       int tx_frames_cnt;
-
-       /* FW Rx counter */
-       u32 rx_counter;
-
-       /* Rx memory pool address */
-       struct wl1271_rx_mem_pool_addr rx_mem_pool_addr;
-
-       /* Intermediate buffer, used for packet aggregation */
-       u8 *aggr_buf;
-
-       /* Reusable dummy packet template */
-       struct sk_buff *dummy_packet;
-
-       /* Network stack work  */
-       struct work_struct netstack_work;
-
-       /* FW log buffer */
-       u8 *fwlog;
-
-       /* Number of valid bytes in the FW log buffer */
-       ssize_t fwlog_size;
-
-       /* Sysfs FW log entry readers wait queue */
-       wait_queue_head_t fwlog_waitq;
-
-       /* Hardware recovery work */
-       struct work_struct recovery_work;
-
-       /* The mbox event mask */
-       u32 event_mask;
-
-       /* Mailbox pointers */
-       u32 mbox_ptr[2];
-
-       /* Are we currently scanning */
-       struct ieee80211_vif *scan_vif;
-       struct wl1271_scan scan;
-       struct delayed_work scan_complete_work;
-
-       bool sched_scanning;
-
-       /* The current band */
-       enum ieee80211_band band;
-
-       struct completion *elp_compl;
-       struct delayed_work elp_work;
-
-       /* in dBm */
-       int power_level;
-
-       struct wl1271_stats stats;
-
-       __le32 buffer_32;
-       u32 buffer_cmd;
-       u32 buffer_busyword[WL1271_BUSY_WORD_CNT];
-
-       struct wl12xx_fw_status *fw_status;
-       struct wl1271_tx_hw_res_if *tx_res_if;
-
-       /* Current chipset configuration */
-       struct conf_drv_settings conf;
-
-       bool sg_enabled;
-
-       bool enable_11a;
-
-       /* Most recently reported noise in dBm */
-       s8 noise;
-
-       /* bands supported by this instance of wl12xx */
-       struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
-
-       int tcxo_clock;
-
-       /*
-        * wowlan trigger was configured during suspend.
-        * (currently, only "ANY" trigger is supported)
-        */
-       bool wow_enabled;
-       bool irq_wake_enabled;
-
-       /*
-        * AP-mode - links indexed by HLID. The global and broadcast links
-        * are always active.
-        */
-       struct wl1271_link links[WL12XX_MAX_LINKS];
-
-       /* AP-mode - a bitmap of links currently in PS mode according to FW */
-       u32 ap_fw_ps_map;
-
-       /* AP-mode - a bitmap of links currently in PS mode in mac80211 */
-       unsigned long ap_ps_map;
-
-       /* Quirks of specific hardware revisions */
-       unsigned int quirks;
-
-       /* Platform limitations */
-       unsigned int platform_quirks;
-
-       /* number of currently active RX BA sessions */
-       int ba_rx_session_count;
-
-       /* AP-mode - number of currently connected stations */
-       int active_sta_count;
-
-       /* last wlvif we transmitted from */
-       struct wl12xx_vif *last_wlvif;
-
-       /* work to fire when Tx is stuck */
-       struct delayed_work tx_watchdog_work;
-};
-
 struct wl1271_station {
        u8 hlid;
 };
@@ -605,6 +384,9 @@ struct wl12xx_vif {
        struct work_struct rx_streaming_disable_work;
        struct timer_list rx_streaming_timer;
 
+       /* does the current role use GEM for encryption (AP or STA) */
+       bool is_gem;
+
        /*
         * This struct must be last!
         * data that has to be saved acrossed reconfigs (e.g. recovery)
@@ -679,17 +461,6 @@ size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen);
 #define HW_BG_RATES_MASK       0xffff
 #define HW_HT_RATES_OFFSET     16
 
-/* Quirks */
-
-/* Each RX/TX transaction requires an end-of-transaction transfer */
-#define WL12XX_QUIRK_END_OF_TRANSACTION                BIT(0)
-
-/* wl127x and SPI don't support SDIO block size alignment */
-#define WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT    BIT(2)
-
-/* Older firmwares did not implement the FW logger over bus feature */
-#define WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED     BIT(4)
-
 #define WL12XX_HW_BLOCK_SIZE   256
 
 #endif
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
new file mode 100644 (file)
index 0000000..39f9fad
--- /dev/null
@@ -0,0 +1,448 @@
+/*
+ * This file is part of wlcore
+ *
+ * Copyright (C) 2011 Texas Instruments Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __WLCORE_H__
+#define __WLCORE_H__
+
+#include <linux/platform_device.h>
+
+#include "wl12xx.h"
+#include "event.h"
+
+/* The maximum number of Tx descriptors in all chip families */
+#define WLCORE_MAX_TX_DESCRIPTORS 32
+
+/* forward declaration */
+struct wl1271_tx_hw_descr;
+enum wl_rx_buf_align;
+
+struct wlcore_ops {
+       int (*identify_chip)(struct wl1271 *wl);
+       int (*identify_fw)(struct wl1271 *wl);
+       int (*boot)(struct wl1271 *wl);
+       void (*trigger_cmd)(struct wl1271 *wl, int cmd_box_addr,
+                           void *buf, size_t len);
+       void (*ack_event)(struct wl1271 *wl);
+       u32 (*calc_tx_blocks)(struct wl1271 *wl, u32 len, u32 spare_blks);
+       void (*set_tx_desc_blocks)(struct wl1271 *wl,
+                                  struct wl1271_tx_hw_descr *desc,
+                                  u32 blks, u32 spare_blks);
+       void (*set_tx_desc_data_len)(struct wl1271 *wl,
+                                    struct wl1271_tx_hw_descr *desc,
+                                    struct sk_buff *skb);
+       enum wl_rx_buf_align (*get_rx_buf_align)(struct wl1271 *wl,
+                                                u32 rx_desc);
+       void (*prepare_read)(struct wl1271 *wl, u32 rx_desc, u32 len);
+       u32 (*get_rx_packet_len)(struct wl1271 *wl, void *rx_data,
+                                u32 data_len);
+       void (*tx_delayed_compl)(struct wl1271 *wl);
+       void (*tx_immediate_compl)(struct wl1271 *wl);
+       int (*hw_init)(struct wl1271 *wl);
+       int (*init_vif)(struct wl1271 *wl, struct wl12xx_vif *wlvif);
+       u32 (*sta_get_ap_rate_mask)(struct wl1271 *wl,
+                                   struct wl12xx_vif *wlvif);
+       s8 (*get_pg_ver)(struct wl1271 *wl);
+       void (*get_mac)(struct wl1271 *wl);
+};
+
+enum wlcore_partitions {
+       PART_DOWN,
+       PART_WORK,
+       PART_BOOT,
+       PART_DRPW,
+       PART_TOP_PRCM_ELP_SOC,
+       PART_PHY_INIT,
+
+       PART_TABLE_LEN,
+};
+
+struct wlcore_partition {
+       u32 size;
+       u32 start;
+};
+
+struct wlcore_partition_set {
+       struct wlcore_partition mem;
+       struct wlcore_partition reg;
+       struct wlcore_partition mem2;
+       struct wlcore_partition mem3;
+};
+
+enum wlcore_registers {
+       /* register addresses, used with partition translation */
+       REG_ECPU_CONTROL,
+       REG_INTERRUPT_NO_CLEAR,
+       REG_INTERRUPT_ACK,
+       REG_COMMAND_MAILBOX_PTR,
+       REG_EVENT_MAILBOX_PTR,
+       REG_INTERRUPT_TRIG,
+       REG_INTERRUPT_MASK,
+       REG_PC_ON_RECOVERY,
+       REG_CHIP_ID_B,
+       REG_CMD_MBOX_ADDRESS,
+
+       /* data access memory addresses, used with partition translation */
+       REG_SLV_MEM_DATA,
+       REG_SLV_REG_DATA,
+
+       /* raw data access memory addresses */
+       REG_RAW_FW_STATUS_ADDR,
+
+       REG_TABLE_LEN,
+};
+
+struct wl1271 {
+       struct ieee80211_hw *hw;
+       bool mac80211_registered;
+
+       struct device *dev;
+
+       void *if_priv;
+
+       struct wl1271_if_operations *if_ops;
+
+       void (*set_power)(bool enable);
+       int irq;
+       int ref_clock;
+
+       spinlock_t wl_lock;
+
+       enum wl1271_state state;
+       enum wl12xx_fw_type fw_type;
+       bool plt;
+       u8 last_vif_count;
+       struct mutex mutex;
+
+       unsigned long flags;
+
+       struct wlcore_partition_set curr_part;
+
+       struct wl1271_chip chip;
+
+       int cmd_box_addr;
+
+       u8 *fw;
+       size_t fw_len;
+       void *nvs;
+       size_t nvs_len;
+
+       s8 hw_pg_ver;
+
+       /* address read from the fuse ROM */
+       u32 fuse_oui_addr;
+       u32 fuse_nic_addr;
+
+       /* we have up to 2 MAC addresses */
+       struct mac_address addresses[2];
+       int channel;
+       u8 system_hlid;
+
+       unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)];
+       unsigned long roles_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];
+       unsigned long roc_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];
+       unsigned long rate_policies_map[
+                       BITS_TO_LONGS(WL12XX_MAX_RATE_POLICIES)];
+
+       struct list_head wlvif_list;
+
+       u8 sta_count;
+       u8 ap_count;
+
+       struct wl1271_acx_mem_map *target_mem_map;
+
+       /* Accounting for allocated / available TX blocks on HW */
+       u32 tx_blocks_freed;
+       u32 tx_blocks_available;
+       u32 tx_allocated_blocks;
+       u32 tx_results_count;
+
+       /* Accounting for allocated / available Tx packets in HW */
+       u32 tx_pkts_freed[NUM_TX_QUEUES];
+       u32 tx_allocated_pkts[NUM_TX_QUEUES];
+
+       /* Transmitted TX packets counter for chipset interface */
+       u32 tx_packets_count;
+
+       /* Time-offset between host and chipset clocks */
+       s64 time_offset;
+
+       /* Frames scheduled for transmission, not handled yet */
+       int tx_queue_count[NUM_TX_QUEUES];
+       long stopped_queues_map;
+
+       /* Frames received, not handled yet by mac80211 */
+       struct sk_buff_head deferred_rx_queue;
+
+       /* Frames sent, not returned yet to mac80211 */
+       struct sk_buff_head deferred_tx_queue;
+
+       struct work_struct tx_work;
+       struct workqueue_struct *freezable_wq;
+
+       /* Pending TX frames */
+       unsigned long tx_frames_map[BITS_TO_LONGS(WLCORE_MAX_TX_DESCRIPTORS)];
+       struct sk_buff *tx_frames[WLCORE_MAX_TX_DESCRIPTORS];
+       int tx_frames_cnt;
+
+       /* FW Rx counter */
+       u32 rx_counter;
+
+       /* Rx memory pool address */
+       struct wl1271_rx_mem_pool_addr rx_mem_pool_addr;
+
+       /* Intermediate buffer, used for packet aggregation */
+       u8 *aggr_buf;
+
+       /* Reusable dummy packet template */
+       struct sk_buff *dummy_packet;
+
+       /* Network stack work  */
+       struct work_struct netstack_work;
+
+       /* FW log buffer */
+       u8 *fwlog;
+
+       /* Number of valid bytes in the FW log buffer */
+       ssize_t fwlog_size;
+
+       /* Sysfs FW log entry readers wait queue */
+       wait_queue_head_t fwlog_waitq;
+
+       /* Hardware recovery work */
+       struct work_struct recovery_work;
+
+       /* Pointer that holds DMA-friendly block for the mailbox */
+       struct event_mailbox *mbox;
+
+       /* The mbox event mask */
+       u32 event_mask;
+
+       /* Mailbox pointers */
+       u32 mbox_ptr[2];
+
+       /* Are we currently scanning */
+       struct ieee80211_vif *scan_vif;
+       struct wl1271_scan scan;
+       struct delayed_work scan_complete_work;
+
+       bool sched_scanning;
+
+       /* The current band */
+       enum ieee80211_band band;
+
+       struct completion *elp_compl;
+       struct delayed_work elp_work;
+
+       /* in dBm */
+       int power_level;
+
+       struct wl1271_stats stats;
+
+       __le32 buffer_32;
+       u32 buffer_cmd;
+       u32 buffer_busyword[WL1271_BUSY_WORD_CNT];
+
+       struct wl_fw_status *fw_status;
+       struct wl1271_tx_hw_res_if *tx_res_if;
+
+       /* Current chipset configuration */
+       struct wlcore_conf conf;
+
+       bool sg_enabled;
+
+       bool enable_11a;
+
+       /* Most recently reported noise in dBm */
+       s8 noise;
+
+       /* bands supported by this instance of wl12xx */
+       struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
+
+       int tcxo_clock;
+
+       /*
+        * wowlan trigger was configured during suspend.
+        * (currently, only "ANY" trigger is supported)
+        */
+       bool wow_enabled;
+       bool irq_wake_enabled;
+
+       /*
+        * AP-mode - links indexed by HLID. The global and broadcast links
+        * are always active.
+        */
+       struct wl1271_link links[WL12XX_MAX_LINKS];
+
+       /* AP-mode - a bitmap of links currently in PS mode according to FW */
+       u32 ap_fw_ps_map;
+
+       /* AP-mode - a bitmap of links currently in PS mode in mac80211 */
+       unsigned long ap_ps_map;
+
+       /* Quirks of specific hardware revisions */
+       unsigned int quirks;
+
+       /* Platform limitations */
+       unsigned int platform_quirks;
+
+       /* number of currently active RX BA sessions */
+       int ba_rx_session_count;
+
+       /* AP-mode - number of currently connected stations */
+       int active_sta_count;
+
+       /* last wlvif we transmitted from */
+       struct wl12xx_vif *last_wlvif;
+
+       /* work to fire when Tx is stuck */
+       struct delayed_work tx_watchdog_work;
+
+       struct wlcore_ops *ops;
+       /* pointer to the lower driver partition table */
+       const struct wlcore_partition_set *ptable;
+       /* pointer to the lower driver register table */
+       const int *rtable;
+       /* name of the firmwares to load - for PLT, single role, multi-role */
+       const char *plt_fw_name;
+       const char *sr_fw_name;
+       const char *mr_fw_name;
+
+       /* per-chip-family private structure */
+       void *priv;
+
+       /* number of TX descriptors the HW supports. */
+       u32 num_tx_desc;
+
+       /* spare Tx blocks for normal/GEM operating modes */
+       u32 normal_tx_spare;
+       u32 gem_tx_spare;
+
+       /* translate HW Tx rates to standard rate-indices */
+       const u8 **band_rate_to_idx;
+
+       /* size of table for HW rates that can be received from chip */
+       u8 hw_tx_rate_tbl_size;
+
+       /* this HW rate and below are considered HT rates for this chip */
+       u8 hw_min_ht_rate;
+
+       /* HW HT (11n) capabilities */
+       struct ieee80211_sta_ht_cap ht_cap;
+
+       /* size of the private FW status data */
+       size_t fw_status_priv_len;
+};
+
+int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev);
+int __devexit wlcore_remove(struct platform_device *pdev);
+struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size);
+int wlcore_free_hw(struct wl1271 *wl);
+
+/* Firmware image load chunk size */
+#define CHUNK_SIZE     16384
+
+/* Quirks */
+
+/* Each RX/TX transaction requires an end-of-transaction transfer */
+#define WLCORE_QUIRK_END_OF_TRANSACTION                BIT(0)
+
+/* wl127x and SPI don't support SDIO block size alignment */
+#define WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN                BIT(2)
+
+/* means aggregated Rx packets are aligned to a SDIO block */
+#define WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN                BIT(3)
+
+/* Older firmwares did not implement the FW logger over bus feature */
+#define WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED     BIT(4)
+
+/* Older firmwares use an old NVS format */
+#define WLCORE_QUIRK_LEGACY_NVS                        BIT(5)
+
+/* Some firmwares may not support ELP */
+#define WLCORE_QUIRK_NO_ELP                    BIT(6)
+
+/* TODO: move to the lower drivers when all usages are abstracted */
+#define CHIP_ID_1271_PG10              (0x4030101)
+#define CHIP_ID_1271_PG20              (0x4030111)
+#define CHIP_ID_1283_PG10              (0x05030101)
+#define CHIP_ID_1283_PG20              (0x05030111)
+
+/* TODO: move all these common registers and values elsewhere */
+#define HW_ACCESS_ELP_CTRL_REG         0x1FFFC
+
+/* ELP register commands */
+#define ELPCTRL_WAKE_UP             0x1
+#define ELPCTRL_WAKE_UP_WLAN_READY  0x5
+#define ELPCTRL_SLEEP               0x0
+/* ELP WLAN_READY bit */
+#define ELPCTRL_WLAN_READY          0x2
+
+/*************************************************************************
+
+    Interrupt Trigger Register (Host -> WiLink)
+
+**************************************************************************/
+
+/* Hardware to Embedded CPU Interrupts - first 32-bit register set */
+
+/*
+ * The host sets this bit to inform the Wlan
+ * FW that a TX packet is in the XFER
+ * Buffer #0.
+ */
+#define INTR_TRIG_TX_PROC0 BIT(2)
+
+/*
+ * The host sets this bit to inform the FW
+ * that it read a packet from RX XFER
+ * Buffer #0.
+ */
+#define INTR_TRIG_RX_PROC0 BIT(3)
+
+#define INTR_TRIG_DEBUG_ACK BIT(4)
+
+#define INTR_TRIG_STATE_CHANGED BIT(5)
+
+/* Hardware to Embedded CPU Interrupts - second 32-bit register set */
+
+/*
+ * The host sets this bit to inform the FW
+ * that it read a packet from RX XFER
+ * Buffer #1.
+ */
+#define INTR_TRIG_RX_PROC1 BIT(17)
+
+/*
+ * The host sets this bit to inform the Wlan
+ * hardware that a TX packet is in the XFER
+ * Buffer #1.
+ */
+#define INTR_TRIG_TX_PROC1 BIT(18)
+
+#define ACX_SLV_SOFT_RESET_BIT BIT(1)
+#define SOFT_RESET_MAX_TIME    1000000
+#define SOFT_RESET_STALL_TIME  1000
+
+#define ECPU_CONTROL_HALT      0x00000101
+
+#define WELP_ARM_COMMAND_VAL   0x4
+
+#endif /* __WLCORE_H__ */
diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig
deleted file mode 100644 (file)
index af08c86..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-menuconfig WL12XX_MENU
-       tristate "TI wl12xx driver support"
-       depends on MAC80211 && EXPERIMENTAL
-       ---help---
-         This will enable TI wl12xx driver support for the following chips:
-         wl1271, wl1273, wl1281 and wl1283.
-         The drivers make use of the mac80211 stack.
-
-config WL12XX
-       tristate "TI wl12xx support"
-       depends on WL12XX_MENU && GENERIC_HARDIRQS
-       depends on INET
-       select FW_LOADER
-       ---help---
-         This module adds support for wireless adapters based on TI wl1271 and
-         TI wl1273 chipsets. This module does *not* include support for wl1251.
-         For wl1251 support, use the separate homonymous driver instead.
-
-         If you choose to build a module, it will be called wl12xx. Say N if
-         unsure.
-
-config WL12XX_SPI
-       tristate "TI wl12xx SPI support"
-       depends on WL12XX && SPI_MASTER
-       select CRC7
-       ---help---
-         This module adds support for the SPI interface of adapters using
-         TI wl12xx chipsets.  Select this if your platform is using
-         the SPI bus.
-
-         If you choose to build a module, it'll be called wl12xx_spi.
-         Say N if unsure.
-
-config WL12XX_SDIO
-       tristate "TI wl12xx SDIO support"
-       depends on WL12XX && MMC
-       ---help---
-         This module adds support for the SDIO interface of adapters using
-         TI wl12xx chipsets.  Select this if your platform is using
-         the SDIO bus.
-
-         If you choose to build a module, it'll be called wl12xx_sdio.
-         Say N if unsure.
-
-config WL12XX_PLATFORM_DATA
-       bool
-       depends on WL12XX_SDIO != n || WL1251_SDIO != n
-       default y
diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile
deleted file mode 100644 (file)
index 98f289c..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-wl12xx-objs            = main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \
-                         boot.o init.o debugfs.o scan.o
-
-wl12xx_spi-objs        = spi.o
-wl12xx_sdio-objs       = sdio.o
-
-wl12xx-$(CONFIG_NL80211_TESTMODE)      += testmode.o
-obj-$(CONFIG_WL12XX)                   += wl12xx.o
-obj-$(CONFIG_WL12XX_SPI)               += wl12xx_spi.o
-obj-$(CONFIG_WL12XX_SDIO)              += wl12xx_sdio.o
-
-# small builtin driver bit
-obj-$(CONFIG_WL12XX_PLATFORM_DATA)     += wl12xx_platform_data.o
-
-ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
deleted file mode 100644 (file)
index 954101d..0000000
+++ /dev/null
@@ -1,786 +0,0 @@
-/*
- * This file is part of wl1271
- *
- * Copyright (C) 2008-2010 Nokia Corporation
- *
- * Contact: Luciano Coelho <luciano.coelho@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/slab.h>
-#include <linux/wl12xx.h>
-#include <linux/export.h>
-
-#include "debug.h"
-#include "acx.h"
-#include "reg.h"
-#include "boot.h"
-#include "io.h"
-#include "event.h"
-#include "rx.h"
-
-static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)
-{
-       u32 cpu_ctrl;
-
-       /* 10.5.0 run the firmware (I) */
-       cpu_ctrl = wl1271_read32(wl, ACX_REG_ECPU_CONTROL);
-
-       /* 10.5.1 run the firmware (II) */
-       cpu_ctrl |= flag;
-       wl1271_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
-}
-
-static unsigned int wl12xx_get_fw_ver_quirks(struct wl1271 *wl)
-{
-       unsigned int quirks = 0;
-       unsigned int *fw_ver = wl->chip.fw_ver;
-
-       /* Only new station firmwares support routing fw logs to the host */
-       if ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) &&
-           (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_FWLOG_STA_MIN))
-               quirks |= WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED;
-
-       /* This feature is not yet supported for AP mode */
-       if (fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP)
-               quirks |= WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED;
-
-       return quirks;
-}
-
-static void wl1271_parse_fw_ver(struct wl1271 *wl)
-{
-       int ret;
-
-       ret = sscanf(wl->chip.fw_ver_str + 4, "%u.%u.%u.%u.%u",
-                    &wl->chip.fw_ver[0], &wl->chip.fw_ver[1],
-                    &wl->chip.fw_ver[2], &wl->chip.fw_ver[3],
-                    &wl->chip.fw_ver[4]);
-
-       if (ret != 5) {
-               wl1271_warning("fw version incorrect value");
-               memset(wl->chip.fw_ver, 0, sizeof(wl->chip.fw_ver));
-               return;
-       }
-
-       /* Check if any quirks are needed with older fw versions */
-       wl->quirks |= wl12xx_get_fw_ver_quirks(wl);
-}
-
-static void wl1271_boot_fw_version(struct wl1271 *wl)
-{
-       struct wl1271_static_data static_data;
-
-       wl1271_read(wl, wl->cmd_box_addr, &static_data, sizeof(static_data),
-                   false);
-
-       strncpy(wl->chip.fw_ver_str, static_data.fw_version,
-               sizeof(wl->chip.fw_ver_str));
-
-       /* make sure the string is NULL-terminated */
-       wl->chip.fw_ver_str[sizeof(wl->chip.fw_ver_str) - 1] = '\0';
-
-       wl1271_parse_fw_ver(wl);
-}
-
-static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
-                                            size_t fw_data_len, u32 dest)
-{
-       struct wl1271_partition_set partition;
-       int addr, chunk_num, partition_limit;
-       u8 *p, *chunk;
-
-       /* whal_FwCtrl_LoadFwImageSm() */
-
-       wl1271_debug(DEBUG_BOOT, "starting firmware upload");
-
-       wl1271_debug(DEBUG_BOOT, "fw_data_len %zd chunk_size %d",
-                    fw_data_len, CHUNK_SIZE);
-
-       if ((fw_data_len % 4) != 0) {
-               wl1271_error("firmware length not multiple of four");
-               return -EIO;
-       }
-
-       chunk = kmalloc(CHUNK_SIZE, GFP_KERNEL);
-       if (!chunk) {
-               wl1271_error("allocation for firmware upload chunk failed");
-               return -ENOMEM;
-       }
-
-       memcpy(&partition, &wl12xx_part_table[PART_DOWN], sizeof(partition));
-       partition.mem.start = dest;
-       wl1271_set_partition(wl, &partition);
-
-       /* 10.1 set partition limit and chunk num */
-       chunk_num = 0;
-       partition_limit = wl12xx_part_table[PART_DOWN].mem.size;
-
-       while (chunk_num < fw_data_len / CHUNK_SIZE) {
-               /* 10.2 update partition, if needed */
-               addr = dest + (chunk_num + 2) * CHUNK_SIZE;
-               if (addr > partition_limit) {
-                       addr = dest + chunk_num * CHUNK_SIZE;
-                       partition_limit = chunk_num * CHUNK_SIZE +
-                               wl12xx_part_table[PART_DOWN].mem.size;
-                       partition.mem.start = addr;
-                       wl1271_set_partition(wl, &partition);
-               }
-
-               /* 10.3 upload the chunk */
-               addr = dest + chunk_num * CHUNK_SIZE;
-               p = buf + chunk_num * CHUNK_SIZE;
-               memcpy(chunk, p, CHUNK_SIZE);
-               wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x",
-                            p, addr);
-               wl1271_write(wl, addr, chunk, CHUNK_SIZE, false);
-
-               chunk_num++;
-       }
-
-       /* 10.4 upload the last chunk */
-       addr = dest + chunk_num * CHUNK_SIZE;
-       p = buf + chunk_num * CHUNK_SIZE;
-       memcpy(chunk, p, fw_data_len % CHUNK_SIZE);
-       wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x",
-                    fw_data_len % CHUNK_SIZE, p, addr);
-       wl1271_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE, false);
-
-       kfree(chunk);
-       return 0;
-}
-
-static int wl1271_boot_upload_firmware(struct wl1271 *wl)
-{
-       u32 chunks, addr, len;
-       int ret = 0;
-       u8 *fw;
-
-       fw = wl->fw;
-       chunks = be32_to_cpup((__be32 *) fw);
-       fw += sizeof(u32);
-
-       wl1271_debug(DEBUG_BOOT, "firmware chunks to be uploaded: %u", chunks);
-
-       while (chunks--) {
-               addr = be32_to_cpup((__be32 *) fw);
-               fw += sizeof(u32);
-               len = be32_to_cpup((__be32 *) fw);
-               fw += sizeof(u32);
-
-               if (len > 300000) {
-                       wl1271_info("firmware chunk too long: %u", len);
-                       return -EINVAL;
-               }
-               wl1271_debug(DEBUG_BOOT, "chunk %d addr 0x%x len %u",
-                            chunks, addr, len);
-               ret = wl1271_boot_upload_firmware_chunk(wl, fw, len, addr);
-               if (ret != 0)
-                       break;
-               fw += len;
-       }
-
-       return ret;
-}
-
-static int wl1271_boot_upload_nvs(struct wl1271 *wl)
-{
-       size_t nvs_len, burst_len;
-       int i;
-       u32 dest_addr, val;
-       u8 *nvs_ptr, *nvs_aligned;
-
-       if (wl->nvs == NULL)
-               return -ENODEV;
-
-       if (wl->chip.id == CHIP_ID_1283_PG20) {
-               struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs;
-
-               if (wl->nvs_len == sizeof(struct wl128x_nvs_file)) {
-                       if (nvs->general_params.dual_mode_select)
-                               wl->enable_11a = true;
-               } else {
-                       wl1271_error("nvs size is not as expected: %zu != %zu",
-                                    wl->nvs_len,
-                                    sizeof(struct wl128x_nvs_file));
-                       kfree(wl->nvs);
-                       wl->nvs = NULL;
-                       wl->nvs_len = 0;
-                       return -EILSEQ;
-               }
-
-               /* only the first part of the NVS needs to be uploaded */
-               nvs_len = sizeof(nvs->nvs);
-               nvs_ptr = (u8 *)nvs->nvs;
-
-       } else {
-               struct wl1271_nvs_file *nvs =
-                       (struct wl1271_nvs_file *)wl->nvs;
-               /*
-                * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz
-                * band configurations) can be removed when those NVS files stop
-                * floating around.
-                */
-               if (wl->nvs_len == sizeof(struct wl1271_nvs_file) ||
-                   wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) {
-                       if (nvs->general_params.dual_mode_select)
-                               wl->enable_11a = true;
-               }
-
-               if (wl->nvs_len != sizeof(struct wl1271_nvs_file) &&
-                   (wl->nvs_len != WL1271_INI_LEGACY_NVS_FILE_SIZE ||
-                    wl->enable_11a)) {
-                       wl1271_error("nvs size is not as expected: %zu != %zu",
-                               wl->nvs_len, sizeof(struct wl1271_nvs_file));
-                       kfree(wl->nvs);
-                       wl->nvs = NULL;
-                       wl->nvs_len = 0;
-                       return -EILSEQ;
-               }
-
-               /* only the first part of the NVS needs to be uploaded */
-               nvs_len = sizeof(nvs->nvs);
-               nvs_ptr = (u8 *) nvs->nvs;
-       }
-
-       /* update current MAC address to NVS */
-       nvs_ptr[11] = wl->addresses[0].addr[0];
-       nvs_ptr[10] = wl->addresses[0].addr[1];
-       nvs_ptr[6] = wl->addresses[0].addr[2];
-       nvs_ptr[5] = wl->addresses[0].addr[3];
-       nvs_ptr[4] = wl->addresses[0].addr[4];
-       nvs_ptr[3] = wl->addresses[0].addr[5];
-
-       /*
-        * Layout before the actual NVS tables:
-        * 1 byte : burst length.
-        * 2 bytes: destination address.
-        * n bytes: data to burst copy.
-        *
-        * This is ended by a 0 length, then the NVS tables.
-        */
-
-       /* FIXME: Do we need to check here whether the LSB is 1? */
-       while (nvs_ptr[0]) {
-               burst_len = nvs_ptr[0];
-               dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8));
-
-               /*
-                * Due to our new wl1271_translate_reg_addr function,
-                * we need to add the REGISTER_BASE to the destination
-                */
-               dest_addr += REGISTERS_BASE;
-
-               /* We move our pointer to the data */
-               nvs_ptr += 3;
-
-               for (i = 0; i < burst_len; i++) {
-                       if (nvs_ptr + 3 >= (u8 *) wl->nvs + nvs_len)
-                               goto out_badnvs;
-
-                       val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
-                              | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));
-
-                       wl1271_debug(DEBUG_BOOT,
-                                    "nvs burst write 0x%x: 0x%x",
-                                    dest_addr, val);
-                       wl1271_write32(wl, dest_addr, val);
-
-                       nvs_ptr += 4;
-                       dest_addr += 4;
-               }
-
-               if (nvs_ptr >= (u8 *) wl->nvs + nvs_len)
-                       goto out_badnvs;
-       }
-
-       /*
-        * We've reached the first zero length, the first NVS table
-        * is located at an aligned offset which is at least 7 bytes further.
-        * NOTE: The wl->nvs->nvs element must be first, in order to
-        * simplify the casting, we assume it is at the beginning of
-        * the wl->nvs structure.
-        */
-       nvs_ptr = (u8 *)wl->nvs +
-                       ALIGN(nvs_ptr - (u8 *)wl->nvs + 7, 4);
-
-       if (nvs_ptr >= (u8 *) wl->nvs + nvs_len)
-               goto out_badnvs;
-
-       nvs_len -= nvs_ptr - (u8 *)wl->nvs;
-
-       /* Now we must set the partition correctly */
-       wl1271_set_partition(wl, &wl12xx_part_table[PART_WORK]);
-
-       /* Copy the NVS tables to a new block to ensure alignment */
-       nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL);
-       if (!nvs_aligned)
-               return -ENOMEM;
-
-       /* And finally we upload the NVS tables */
-       wl1271_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, false);
-
-       kfree(nvs_aligned);
-       return 0;
-
-out_badnvs:
-       wl1271_error("nvs data is malformed");
-       return -EILSEQ;
-}
-
-static void wl1271_boot_enable_interrupts(struct wl1271 *wl)
-{
-       wl1271_enable_interrupts(wl);
-       wl1271_write32(wl, ACX_REG_INTERRUPT_MASK,
-                      WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
-       wl1271_write32(wl, HI_CFG, HI_CFG_DEF_VAL);
-}
-
-static int wl1271_boot_soft_reset(struct wl1271 *wl)
-{
-       unsigned long timeout;
-       u32 boot_data;
-
-       /* perform soft reset */
-       wl1271_write32(wl, ACX_REG_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT);
-
-       /* SOFT_RESET is self clearing */
-       timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME);
-       while (1) {
-               boot_data = wl1271_read32(wl, ACX_REG_SLV_SOFT_RESET);
-               wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data);
-               if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0)
-                       break;
-
-               if (time_after(jiffies, timeout)) {
-                       /* 1.2 check pWhalBus->uSelfClearTime if the
-                        * timeout was reached */
-                       wl1271_error("soft reset timeout");
-                       return -1;
-               }
-
-               udelay(SOFT_RESET_STALL_TIME);
-       }
-
-       /* disable Rx/Tx */
-       wl1271_write32(wl, ENABLE, 0x0);
-
-       /* disable auto calibration on start*/
-       wl1271_write32(wl, SPARE_A2, 0xffff);
-
-       return 0;
-}
-
-static int wl1271_boot_run_firmware(struct wl1271 *wl)
-{
-       int loop, ret;
-       u32 chip_id, intr;
-
-       wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT);
-
-       chip_id = wl1271_read32(wl, CHIP_ID_B);
-
-       wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id);
-
-       if (chip_id != wl->chip.id) {
-               wl1271_error("chip id doesn't match after firmware boot");
-               return -EIO;
-       }
-
-       /* wait for init to complete */
-       loop = 0;
-       while (loop++ < INIT_LOOP) {
-               udelay(INIT_LOOP_DELAY);
-               intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
-
-               if (intr == 0xffffffff) {
-                       wl1271_error("error reading hardware complete "
-                                    "init indication");
-                       return -EIO;
-               }
-               /* check that ACX_INTR_INIT_COMPLETE is enabled */
-               else if (intr & WL1271_ACX_INTR_INIT_COMPLETE) {
-                       wl1271_write32(wl, ACX_REG_INTERRUPT_ACK,
-                                      WL1271_ACX_INTR_INIT_COMPLETE);
-                       break;
-               }
-       }
-
-       if (loop > INIT_LOOP) {
-               wl1271_error("timeout waiting for the hardware to "
-                            "complete initialization");
-               return -EIO;
-       }
-
-       /* get hardware config command mail box */
-       wl->cmd_box_addr = wl1271_read32(wl, REG_COMMAND_MAILBOX_PTR);
-
-       /* get hardware config event mail box */
-       wl->event_box_addr = wl1271_read32(wl, REG_EVENT_MAILBOX_PTR);
-
-       /* set the working partition to its "running" mode offset */
-       wl1271_set_partition(wl, &wl12xx_part_table[PART_WORK]);
-
-       wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x event_box_addr 0x%x",
-                    wl->cmd_box_addr, wl->event_box_addr);
-
-       wl1271_boot_fw_version(wl);
-
-       /*
-        * in case of full asynchronous mode the firmware event must be
-        * ready to receive event from the command mailbox
-        */
-
-       /* unmask required mbox events  */
-       wl->event_mask = BSS_LOSE_EVENT_ID |
-               SCAN_COMPLETE_EVENT_ID |
-               ROLE_STOP_COMPLETE_EVENT_ID |
-               RSSI_SNR_TRIGGER_0_EVENT_ID |
-               PSPOLL_DELIVERY_FAILURE_EVENT_ID |
-               SOFT_GEMINI_SENSE_EVENT_ID |
-               PERIODIC_SCAN_REPORT_EVENT_ID |
-               PERIODIC_SCAN_COMPLETE_EVENT_ID |
-               DUMMY_PACKET_EVENT_ID |
-               PEER_REMOVE_COMPLETE_EVENT_ID |
-               BA_SESSION_RX_CONSTRAINT_EVENT_ID |
-               REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID |
-               INACTIVE_STA_EVENT_ID |
-               MAX_TX_RETRY_EVENT_ID |
-               CHANNEL_SWITCH_COMPLETE_EVENT_ID;
-
-       ret = wl1271_event_unmask(wl);
-       if (ret < 0) {
-               wl1271_error("EVENT mask setting failed");
-               return ret;
-       }
-
-       wl1271_event_mbox_config(wl);
-
-       /* firmware startup completed */
-       return 0;
-}
-
-static int wl1271_boot_write_irq_polarity(struct wl1271 *wl)
-{
-       u32 polarity;
-
-       polarity = wl1271_top_reg_read(wl, OCP_REG_POLARITY);
-
-       /* We use HIGH polarity, so unset the LOW bit */
-       polarity &= ~POLARITY_LOW;
-       wl1271_top_reg_write(wl, OCP_REG_POLARITY, polarity);
-
-       return 0;
-}
-
-static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl)
-{
-       u16 spare_reg;
-
-       /* Mask bits [2] & [8:4] in the sys_clk_cfg register */
-       spare_reg = wl1271_top_reg_read(wl, WL_SPARE_REG);
-       if (spare_reg == 0xFFFF)
-               return -EFAULT;
-       spare_reg |= (BIT(3) | BIT(5) | BIT(6));
-       wl1271_top_reg_write(wl, WL_SPARE_REG, spare_reg);
-
-       /* Enable FREF_CLK_REQ & mux MCS and coex PLLs to FREF */
-       wl1271_top_reg_write(wl, SYS_CLK_CFG_REG,
-                            WL_CLK_REQ_TYPE_PG2 | MCS_PLL_CLK_SEL_FREF);
-
-       /* Delay execution for 15msec, to let the HW settle */
-       mdelay(15);
-
-       return 0;
-}
-
-static bool wl128x_is_tcxo_valid(struct wl1271 *wl)
-{
-       u16 tcxo_detection;
-
-       tcxo_detection = wl1271_top_reg_read(wl, TCXO_CLK_DETECT_REG);
-       if (tcxo_detection & TCXO_DET_FAILED)
-               return false;
-
-       return true;
-}
-
-static bool wl128x_is_fref_valid(struct wl1271 *wl)
-{
-       u16 fref_detection;
-
-       fref_detection = wl1271_top_reg_read(wl, FREF_CLK_DETECT_REG);
-       if (fref_detection & FREF_CLK_DETECT_FAIL)
-               return false;
-
-       return true;
-}
-
-static int wl128x_manually_configure_mcs_pll(struct wl1271 *wl)
-{
-       wl1271_top_reg_write(wl, MCS_PLL_M_REG, MCS_PLL_M_REG_VAL);
-       wl1271_top_reg_write(wl, MCS_PLL_N_REG, MCS_PLL_N_REG_VAL);
-       wl1271_top_reg_write(wl, MCS_PLL_CONFIG_REG, MCS_PLL_CONFIG_REG_VAL);
-
-       return 0;
-}
-
-static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk)
-{
-       u16 spare_reg;
-       u16 pll_config;
-       u8 input_freq;
-
-       /* Mask bits [3:1] in the sys_clk_cfg register */
-       spare_reg = wl1271_top_reg_read(wl, WL_SPARE_REG);
-       if (spare_reg == 0xFFFF)
-               return -EFAULT;
-       spare_reg |= BIT(2);
-       wl1271_top_reg_write(wl, WL_SPARE_REG, spare_reg);
-
-       /* Handle special cases of the TCXO clock */
-       if (wl->tcxo_clock == WL12XX_TCXOCLOCK_16_8 ||
-           wl->tcxo_clock == WL12XX_TCXOCLOCK_33_6)
-               return wl128x_manually_configure_mcs_pll(wl);
-
-       /* Set the input frequency according to the selected clock source */
-       input_freq = (clk & 1) + 1;
-
-       pll_config = wl1271_top_reg_read(wl, MCS_PLL_CONFIG_REG);
-       if (pll_config == 0xFFFF)
-               return -EFAULT;
-       pll_config |= (input_freq << MCS_SEL_IN_FREQ_SHIFT);
-       pll_config |= MCS_PLL_ENABLE_HP;
-       wl1271_top_reg_write(wl, MCS_PLL_CONFIG_REG, pll_config);
-
-       return 0;
-}
-
-/*
- * WL128x has two clocks input - TCXO and FREF.
- * TCXO is the main clock of the device, while FREF is used to sync
- * between the GPS and the cellular modem.
- * In cases where TCXO is 32.736MHz or 16.368MHz, the FREF will be used
- * as the WLAN/BT main clock.
- */
-static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock)
-{
-       u16 sys_clk_cfg;
-
-       /* For XTAL-only modes, FREF will be used after switching from TCXO */
-       if (wl->ref_clock == WL12XX_REFCLOCK_26_XTAL ||
-           wl->ref_clock == WL12XX_REFCLOCK_38_XTAL) {
-               if (!wl128x_switch_tcxo_to_fref(wl))
-                       return -EINVAL;
-               goto fref_clk;
-       }
-
-       /* Query the HW, to determine which clock source we should use */
-       sys_clk_cfg = wl1271_top_reg_read(wl, SYS_CLK_CFG_REG);
-       if (sys_clk_cfg == 0xFFFF)
-               return -EINVAL;
-       if (sys_clk_cfg & PRCM_CM_EN_MUX_WLAN_FREF)
-               goto fref_clk;
-
-       /* If TCXO is either 32.736MHz or 16.368MHz, switch to FREF */
-       if (wl->tcxo_clock == WL12XX_TCXOCLOCK_16_368 ||
-           wl->tcxo_clock == WL12XX_TCXOCLOCK_32_736) {
-               if (!wl128x_switch_tcxo_to_fref(wl))
-                       return -EINVAL;
-               goto fref_clk;
-       }
-
-       /* TCXO clock is selected */
-       if (!wl128x_is_tcxo_valid(wl))
-               return -EINVAL;
-       *selected_clock = wl->tcxo_clock;
-       goto config_mcs_pll;
-
-fref_clk:
-       /* FREF clock is selected */
-       if (!wl128x_is_fref_valid(wl))
-               return -EINVAL;
-       *selected_clock = wl->ref_clock;
-
-config_mcs_pll:
-       return wl128x_configure_mcs_pll(wl, *selected_clock);
-}
-
-static int wl127x_boot_clk(struct wl1271 *wl)
-{
-       u32 pause;
-       u32 clk;
-
-       if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3)
-               wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION;
-
-       if (wl->ref_clock == CONF_REF_CLK_19_2_E ||
-           wl->ref_clock == CONF_REF_CLK_38_4_E ||
-           wl->ref_clock == CONF_REF_CLK_38_4_M_XTAL)
-               /* ref clk: 19.2/38.4/38.4-XTAL */
-               clk = 0x3;
-       else if (wl->ref_clock == CONF_REF_CLK_26_E ||
-                wl->ref_clock == CONF_REF_CLK_52_E)
-               /* ref clk: 26/52 */
-               clk = 0x5;
-       else
-               return -EINVAL;
-
-       if (wl->ref_clock != CONF_REF_CLK_19_2_E) {
-               u16 val;
-               /* Set clock type (open drain) */
-               val = wl1271_top_reg_read(wl, OCP_REG_CLK_TYPE);
-               val &= FREF_CLK_TYPE_BITS;
-               wl1271_top_reg_write(wl, OCP_REG_CLK_TYPE, val);
-
-               /* Set clock pull mode (no pull) */
-               val = wl1271_top_reg_read(wl, OCP_REG_CLK_PULL);
-               val |= NO_PULL;
-               wl1271_top_reg_write(wl, OCP_REG_CLK_PULL, val);
-       } else {
-               u16 val;
-               /* Set clock polarity */
-               val = wl1271_top_reg_read(wl, OCP_REG_CLK_POLARITY);
-               val &= FREF_CLK_POLARITY_BITS;
-               val |= CLK_REQ_OUTN_SEL;
-               wl1271_top_reg_write(wl, OCP_REG_CLK_POLARITY, val);
-       }
-
-       wl1271_write32(wl, PLL_PARAMETERS, clk);
-
-       pause = wl1271_read32(wl, PLL_PARAMETERS);
-
-       wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause);
-
-       pause &= ~(WU_COUNTER_PAUSE_VAL);
-       pause |= WU_COUNTER_PAUSE_VAL;
-       wl1271_write32(wl, WU_COUNTER_PAUSE, pause);
-
-       return 0;
-}
-
-/* uploads NVS and firmware */
-int wl1271_load_firmware(struct wl1271 *wl)
-{
-       int ret = 0;
-       u32 tmp, clk;
-       int selected_clock = -1;
-
-       if (wl->chip.id == CHIP_ID_1283_PG20) {
-               ret = wl128x_boot_clk(wl, &selected_clock);
-               if (ret < 0)
-                       goto out;
-       } else {
-               ret = wl127x_boot_clk(wl);
-               if (ret < 0)
-                       goto out;
-       }
-
-       /* Continue the ELP wake up sequence */
-       wl1271_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
-       udelay(500);
-
-       wl1271_set_partition(wl, &wl12xx_part_table[PART_DRPW]);
-
-       /* Read-modify-write DRPW_SCRATCH_START register (see next state)
-          to be used by DRPw FW. The RTRIM value will be added by the FW
-          before taking DRPw out of reset */
-
-       wl1271_debug(DEBUG_BOOT, "DRPW_SCRATCH_START %08x", DRPW_SCRATCH_START);
-       clk = wl1271_read32(wl, DRPW_SCRATCH_START);
-
-       wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk);
-
-       if (wl->chip.id == CHIP_ID_1283_PG20) {
-               clk |= ((selected_clock & 0x3) << 1) << 4;
-       } else {
-               clk |= (wl->ref_clock << 1) << 4;
-       }
-
-       wl1271_write32(wl, DRPW_SCRATCH_START, clk);
-
-       wl1271_set_partition(wl, &wl12xx_part_table[PART_WORK]);
-
-       /* Disable interrupts */
-       wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
-
-       ret = wl1271_boot_soft_reset(wl);
-       if (ret < 0)
-               goto out;
-
-       /* 2. start processing NVS file */
-       ret = wl1271_boot_upload_nvs(wl);
-       if (ret < 0)
-               goto out;
-
-       /* write firmware's last address (ie. it's length) to
-        * ACX_EEPROMLESS_IND_REG */
-       wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG");
-
-       wl1271_write32(wl, ACX_EEPROMLESS_IND_REG, ACX_EEPROMLESS_IND_REG);
-
-       tmp = wl1271_read32(wl, CHIP_ID_B);
-
-       wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp);
-
-       /* 6. read the EEPROM parameters */
-       tmp = wl1271_read32(wl, SCR_PAD2);
-
-       /* WL1271: The reference driver skips steps 7 to 10 (jumps directly
-        * to upload_fw) */
-
-       if (wl->chip.id == CHIP_ID_1283_PG20)
-               wl1271_top_reg_write(wl, SDIO_IO_DS, wl->conf.hci_io_ds);
-
-       ret = wl1271_boot_upload_firmware(wl);
-       if (ret < 0)
-               goto out;
-
-out:
-       return ret;
-}
-EXPORT_SYMBOL_GPL(wl1271_load_firmware);
-
-int wl1271_boot(struct wl1271 *wl)
-{
-       int ret;
-
-       /* upload NVS and firmware */
-       ret = wl1271_load_firmware(wl);
-       if (ret)
-               return ret;
-
-       /* 10.5 start firmware */
-       ret = wl1271_boot_run_firmware(wl);
-       if (ret < 0)
-               goto out;
-
-       ret = wl1271_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);
-
-       wl1271_event_mbox_config(wl);
-
-out:
-       return ret;
-}
diff --git a/drivers/net/wireless/wl12xx/boot.h b/drivers/net/wireless/wl12xx/boot.h
deleted file mode 100644 (file)
index c3adc09..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * This file is part of wl1271
- *
- * Copyright (C) 2008-2009 Nokia Corporation
- *
- * Contact: Luciano Coelho <luciano.coelho@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#ifndef __BOOT_H__
-#define __BOOT_H__
-
-#include "wl12xx.h"
-
-int wl1271_boot(struct wl1271 *wl);
-int wl1271_load_firmware(struct wl1271 *wl);
-
-#define WL1271_NO_SUBBANDS 8
-#define WL1271_NO_POWER_LEVELS 4
-#define WL1271_FW_VERSION_MAX_LEN 20
-
-struct wl1271_static_data {
-       u8 mac_address[ETH_ALEN];
-       u8 padding[2];
-       u8 fw_version[WL1271_FW_VERSION_MAX_LEN];
-       u32 hw_version;
-       u8 tx_power_table[WL1271_NO_SUBBANDS][WL1271_NO_POWER_LEVELS];
-};
-
-/* number of times we try to read the INIT interrupt */
-#define INIT_LOOP 20000
-
-/* delay between retries */
-#define INIT_LOOP_DELAY 50
-
-#define WU_COUNTER_PAUSE_VAL 0x3FF
-#define WELP_ARM_COMMAND_VAL 0x4
-
-#define OCP_REG_POLARITY     0x0064
-#define OCP_REG_CLK_TYPE     0x0448
-#define OCP_REG_CLK_POLARITY 0x0cb2
-#define OCP_REG_CLK_PULL     0x0cb4
-
-#define CMD_MBOX_ADDRESS     0x407B4
-
-#define POLARITY_LOW         BIT(1)
-#define NO_PULL              (BIT(14) | BIT(15))
-
-#define FREF_CLK_TYPE_BITS     0xfffffe7f
-#define CLK_REQ_PRCM           0x100
-#define FREF_CLK_POLARITY_BITS 0xfffff8ff
-#define CLK_REQ_OUTN_SEL       0x700
-
-/* PLL configuration algorithm for wl128x */
-#define SYS_CLK_CFG_REG              0x2200
-/* Bit[0]   -  0-TCXO,  1-FREF */
-#define MCS_PLL_CLK_SEL_FREF         BIT(0)
-/* Bit[3:2] - 01-TCXO, 10-FREF */
-#define WL_CLK_REQ_TYPE_FREF         BIT(3)
-#define WL_CLK_REQ_TYPE_PG2          (BIT(3) | BIT(2))
-/* Bit[4]   -  0-TCXO,  1-FREF */
-#define PRCM_CM_EN_MUX_WLAN_FREF     BIT(4)
-
-#define TCXO_ILOAD_INT_REG           0x2264
-#define TCXO_CLK_DETECT_REG          0x2266
-
-#define TCXO_DET_FAILED              BIT(4)
-
-#define FREF_ILOAD_INT_REG           0x2084
-#define FREF_CLK_DETECT_REG          0x2086
-#define FREF_CLK_DETECT_FAIL         BIT(4)
-
-/* Use this reg for masking during driver access */
-#define WL_SPARE_REG                 0x2320
-#define WL_SPARE_VAL                 BIT(2)
-/* Bit[6:5:3] -  mask wl write SYS_CLK_CFG[8:5:2:4] */
-#define WL_SPARE_MASK_8526           (BIT(6) | BIT(5) | BIT(3))
-
-#define PLL_LOCK_COUNTERS_REG        0xD8C
-#define PLL_LOCK_COUNTERS_COEX       0x0F
-#define PLL_LOCK_COUNTERS_MCS        0xF0
-#define MCS_PLL_OVERRIDE_REG         0xD90
-#define MCS_PLL_CONFIG_REG           0xD92
-#define MCS_SEL_IN_FREQ_MASK         0x0070
-#define MCS_SEL_IN_FREQ_SHIFT        4
-#define MCS_PLL_CONFIG_REG_VAL       0x73
-#define MCS_PLL_ENABLE_HP            (BIT(0) | BIT(1))
-
-#define MCS_PLL_M_REG                0xD94
-#define MCS_PLL_N_REG                0xD96
-#define MCS_PLL_M_REG_VAL            0xC8
-#define MCS_PLL_N_REG_VAL            0x07
-
-#define SDIO_IO_DS                   0xd14
-
-/* SDIO/wSPI DS configuration values */
-enum {
-       HCI_IO_DS_8MA = 0,
-       HCI_IO_DS_4MA = 1, /* default */
-       HCI_IO_DS_6MA = 2,
-       HCI_IO_DS_2MA = 3,
-};
-
-/* end PLL configuration algorithm for wl128x */
-
-#endif