aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorLuciano Coelho <coelho@ti.com>2011-12-23 02:32:17 -0500
committerLuciano Coelho <coelho@ti.com>2012-02-15 01:38:29 -0500
commit5e037e74802a10a71dddbb05585753b2fcbd8ad7 (patch)
tree4fca005d0d5bdf06ed0d44a095e5bf3c36c27999 /drivers/net
parent30c5dbd1ee191dca1c04c70df0ba1adf0a9769c3 (diff)
wl12xx: use two MAC addresses based on the NVS or from fuse ROM
Add support for two MAC addresses. If the NVS has a valid MAC address, that takes precedence and we use two sequential address starting from the one specified. If the NVS doesn't contain a valid MAC address (ie. if it is set to 00:00:00:00:00:00), we check if the HW PG version in use has the BD_ADDR written in the fuse ROM. If it does, we read it and derive the two subsequent addresses for WLAN. During production, 3 addresses are reserved per device. The first for Bluetooth (burnt in the fuse ROM) and the following two for WLAN. This patch has some code by Igal and Arik (squashed from internal patches). Signed-off-by: Arik Nemtsov <arik@wizery.com> Signed-off-by: Igal Chernobelsky <igalc@ti.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/wl12xx/boot.c14
-rw-r--r--drivers/net/wireless/wl12xx/boot.h10
-rw-r--r--drivers/net/wireless/wl12xx/main.c99
-rw-r--r--drivers/net/wireless/wl12xx/reg.h27
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx.h7
5 files changed, 131 insertions, 26 deletions
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
index 599919e2a60d..32a7f9b69d7c 100644
--- a/drivers/net/wireless/wl12xx/boot.c
+++ b/drivers/net/wireless/wl12xx/boot.c
@@ -258,12 +258,12 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
258 } 258 }
259 259
260 /* update current MAC address to NVS */ 260 /* update current MAC address to NVS */
261 nvs_ptr[11] = wl->mac_addr[0]; 261 nvs_ptr[11] = wl->addresses[0].addr[0];
262 nvs_ptr[10] = wl->mac_addr[1]; 262 nvs_ptr[10] = wl->addresses[0].addr[1];
263 nvs_ptr[6] = wl->mac_addr[2]; 263 nvs_ptr[6] = wl->addresses[0].addr[2];
264 nvs_ptr[5] = wl->mac_addr[3]; 264 nvs_ptr[5] = wl->addresses[0].addr[3];
265 nvs_ptr[4] = wl->mac_addr[4]; 265 nvs_ptr[4] = wl->addresses[0].addr[4];
266 nvs_ptr[3] = wl->mac_addr[5]; 266 nvs_ptr[3] = wl->addresses[0].addr[5];
267 267
268 /* 268 /*
269 * Layout before the actual NVS tables: 269 * Layout before the actual NVS tables:
@@ -626,7 +626,7 @@ static int wl127x_boot_clk(struct wl1271 *wl)
626 u32 pause; 626 u32 pause;
627 u32 clk; 627 u32 clk;
628 628
629 if (((wl->hw_pg_ver & PG_MAJOR_VER_MASK) >> PG_MAJOR_VER_OFFSET) < 3) 629 if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3)
630 wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION; 630 wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION;
631 631
632 if (wl->ref_clock == CONF_REF_CLK_19_2_E || 632 if (wl->ref_clock == CONF_REF_CLK_19_2_E ||
diff --git a/drivers/net/wireless/wl12xx/boot.h b/drivers/net/wireless/wl12xx/boot.h
index 06dad9380fa7..c3adc09f403d 100644
--- a/drivers/net/wireless/wl12xx/boot.h
+++ b/drivers/net/wireless/wl12xx/boot.h
@@ -55,16 +55,6 @@ struct wl1271_static_data {
55#define OCP_REG_CLK_POLARITY 0x0cb2 55#define OCP_REG_CLK_POLARITY 0x0cb2
56#define OCP_REG_CLK_PULL 0x0cb4 56#define OCP_REG_CLK_PULL 0x0cb4
57 57
58#define WL127X_REG_FUSE_DATA_2_1 0x050a
59#define WL128X_REG_FUSE_DATA_2_1 0x2152
60#define PG_VER_MASK 0x3c
61#define PG_VER_OFFSET 2
62
63#define PG_MAJOR_VER_MASK 0x3
64#define PG_MAJOR_VER_OFFSET 0x0
65#define PG_MINOR_VER_MASK 0xc
66#define PG_MINOR_VER_OFFSET 0x2
67
68#define CMD_MBOX_ADDRESS 0x407B4 58#define CMD_MBOX_ADDRESS 0x407B4
69 59
70#define POLARITY_LOW BIT(1) 60#define POLARITY_LOW BIT(1)
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index a41af84f649d..6c92f86217cd 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -2132,7 +2132,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
2132 * we still need this in order to configure the fw 2132 * we still need this in order to configure the fw
2133 * while uploading the nvs 2133 * while uploading the nvs
2134 */ 2134 */
2135 memcpy(wl->mac_addr, vif->addr, ETH_ALEN); 2135 memcpy(wl->addresses[0].addr, vif->addr, ETH_ALEN);
2136 2136
2137 booted = wl12xx_init_fw(wl); 2137 booted = wl12xx_init_fw(wl);
2138 if (!booted) { 2138 if (!booted) {
@@ -4859,6 +4859,76 @@ static struct bin_attribute fwlog_attr = {
4859 .read = wl1271_sysfs_read_fwlog, 4859 .read = wl1271_sysfs_read_fwlog,
4860}; 4860};
4861 4861
4862static bool wl12xx_mac_in_fuse(struct wl1271 *wl)
4863{
4864 bool supported = false;
4865 u8 major, minor;
4866
4867 if (wl->chip.id == CHIP_ID_1283_PG20) {
4868 major = WL128X_PG_GET_MAJOR(wl->hw_pg_ver);
4869 minor = WL128X_PG_GET_MINOR(wl->hw_pg_ver);
4870
4871 /* in wl128x we have the MAC address if the PG is >= (2, 1) */
4872 if (major > 2 || (major == 2 && minor >= 1))
4873 supported = true;
4874 } else {
4875 major = WL127X_PG_GET_MAJOR(wl->hw_pg_ver);
4876 minor = WL127X_PG_GET_MINOR(wl->hw_pg_ver);
4877
4878 /* in wl127x we have the MAC address if the PG is >= (3, 1) */
4879 if (major == 3 && minor >= 1)
4880 supported = true;
4881 }
4882
4883 wl1271_debug(DEBUG_PROBE,
4884 "PG Ver major = %d minor = %d, MAC %s present",
4885 major, minor, supported ? "is" : "is not");
4886
4887 return supported;
4888}
4889
4890static void wl12xx_derive_mac_addresses(struct wl1271 *wl,
4891 u32 oui, u32 nic, int n)
4892{
4893 int i;
4894
4895 wl1271_debug(DEBUG_PROBE, "base address: oui %06x nic %06x, n %d",
4896 oui, nic, n);
4897
4898 if (nic + n - 1 > 0xffffff)
4899 wl1271_warning("NIC part of the MAC address wraps around!");
4900
4901 for (i = 0; i < n; i++) {
4902 wl->addresses[i].addr[0] = (u8)(oui >> 16);
4903 wl->addresses[i].addr[1] = (u8)(oui >> 8);
4904 wl->addresses[i].addr[2] = (u8) oui;
4905 wl->addresses[i].addr[3] = (u8)(nic >> 16);
4906 wl->addresses[i].addr[4] = (u8)(nic >> 8);
4907 wl->addresses[i].addr[5] = (u8) nic;
4908 nic++;
4909 }
4910
4911 wl->hw->wiphy->n_addresses = n;
4912 wl->hw->wiphy->addresses = wl->addresses;
4913}
4914
4915static void wl12xx_get_fuse_mac(struct wl1271 *wl)
4916{
4917 u32 mac1, mac2;
4918
4919 wl1271_set_partition(wl, &wl12xx_part_table[PART_DRPW]);
4920
4921 mac1 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_1);
4922 mac2 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_2);
4923
4924 /* these are the two parts of the BD_ADDR */
4925 wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) +
4926 ((mac1 & 0xff000000) >> 24);
4927 wl->fuse_nic_addr = mac1 & 0xffffff;
4928
4929 wl1271_set_partition(wl, &wl12xx_part_table[PART_DOWN]);
4930}
4931
4862static int wl12xx_get_hw_info(struct wl1271 *wl) 4932static int wl12xx_get_hw_info(struct wl1271 *wl)
4863{ 4933{
4864 int ret; 4934 int ret;
@@ -4877,6 +4947,13 @@ static int wl12xx_get_hw_info(struct wl1271 *wl)
4877 4947
4878 wl->hw_pg_ver = (s8) (die_info & PG_VER_MASK) >> PG_VER_OFFSET; 4948 wl->hw_pg_ver = (s8) (die_info & PG_VER_MASK) >> PG_VER_OFFSET;
4879 4949
4950 if (!wl12xx_mac_in_fuse(wl)) {
4951 wl->fuse_oui_addr = 0;
4952 wl->fuse_nic_addr = 0;
4953 } else {
4954 wl12xx_get_fuse_mac(wl);
4955 }
4956
4880 wl1271_power_off(wl); 4957 wl1271_power_off(wl);
4881out: 4958out:
4882 return ret; 4959 return ret;
@@ -4885,6 +4962,7 @@ out:
4885static int wl1271_register_hw(struct wl1271 *wl) 4962static int wl1271_register_hw(struct wl1271 *wl)
4886{ 4963{
4887 int ret; 4964 int ret;
4965 u32 oui_addr = 0, nic_addr = 0;
4888 4966
4889 if (wl->mac80211_registered) 4967 if (wl->mac80211_registered)
4890 return 0; 4968 return 0;
@@ -4903,15 +4981,20 @@ static int wl1271_register_hw(struct wl1271 *wl)
4903 */ 4981 */
4904 u8 *nvs_ptr = (u8 *)wl->nvs; 4982 u8 *nvs_ptr = (u8 *)wl->nvs;
4905 4983
4906 wl->mac_addr[0] = nvs_ptr[11]; 4984 oui_addr =
4907 wl->mac_addr[1] = nvs_ptr[10]; 4985 (nvs_ptr[11] << 16) + (nvs_ptr[10] << 8) + nvs_ptr[6];
4908 wl->mac_addr[2] = nvs_ptr[6]; 4986 nic_addr =
4909 wl->mac_addr[3] = nvs_ptr[5]; 4987 (nvs_ptr[5] << 16) + (nvs_ptr[4] << 8) + nvs_ptr[3];
4910 wl->mac_addr[4] = nvs_ptr[4]; 4988 }
4911 wl->mac_addr[5] = nvs_ptr[3]; 4989
4990 /* if the MAC address is zeroed in the NVS derive from fuse */
4991 if (oui_addr == 0 && nic_addr == 0) {
4992 oui_addr = wl->fuse_oui_addr;
4993 /* fuse has the BD_ADDR, the WLAN addresses are the next two */
4994 nic_addr = wl->fuse_nic_addr + 1;
4912 } 4995 }
4913 4996
4914 SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); 4997 wl12xx_derive_mac_addresses(wl, oui_addr, nic_addr, 2);
4915 4998
4916 ret = ieee80211_register_hw(wl->hw); 4999 ret = ieee80211_register_hw(wl->hw);
4917 if (ret < 0) { 5000 if (ret < 0) {
diff --git a/drivers/net/wireless/wl12xx/reg.h b/drivers/net/wireless/wl12xx/reg.h
index df34d5977b98..340db324bc26 100644
--- a/drivers/net/wireless/wl12xx/reg.h
+++ b/drivers/net/wireless/wl12xx/reg.h
@@ -525,4 +525,31 @@ b12-b0 - Supported Rate indicator bits as defined below.
525 */ 525 */
526#define INTR_TRIG_TX_PROC1 BIT(18) 526#define INTR_TRIG_TX_PROC1 BIT(18)
527 527
528#define WL127X_REG_FUSE_DATA_2_1 0x050a
529#define WL128X_REG_FUSE_DATA_2_1 0x2152
530#define PG_VER_MASK 0x3c
531#define PG_VER_OFFSET 2
532
533#define WL127X_PG_MAJOR_VER_MASK 0x3
534#define WL127X_PG_MAJOR_VER_OFFSET 0x0
535#define WL127X_PG_MINOR_VER_MASK 0xc
536#define WL127X_PG_MINOR_VER_OFFSET 0x2
537
538#define WL128X_PG_MAJOR_VER_MASK 0xc
539#define WL128X_PG_MAJOR_VER_OFFSET 0x2
540#define WL128X_PG_MINOR_VER_MASK 0x3
541#define WL128X_PG_MINOR_VER_OFFSET 0x0
542
543#define WL127X_PG_GET_MAJOR(pg_ver) ((pg_ver & WL127X_PG_MAJOR_VER_MASK) >> \
544 WL127X_PG_MAJOR_VER_OFFSET)
545#define WL127X_PG_GET_MINOR(pg_ver) ((pg_ver & WL127X_PG_MINOR_VER_MASK) >> \
546 WL127X_PG_MINOR_VER_OFFSET)
547#define WL128X_PG_GET_MAJOR(pg_ver) ((pg_ver & WL128X_PG_MAJOR_VER_MASK) >> \
548 WL128X_PG_MAJOR_VER_OFFSET)
549#define WL128X_PG_GET_MINOR(pg_ver) ((pg_ver & WL128X_PG_MINOR_VER_MASK) >> \
550 WL128X_PG_MINOR_VER_OFFSET)
551
552#define WL12XX_REG_FUSE_BD_ADDR_1 0x00310eb4
553#define WL12XX_REG_FUSE_BD_ADDR_2 0x00310eb8
554
528#endif 555#endif
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index b2b09cd02022..1f629fac02e4 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -313,7 +313,12 @@ struct wl1271 {
313 313
314 s8 hw_pg_ver; 314 s8 hw_pg_ver;
315 315
316 u8 mac_addr[ETH_ALEN]; 316 /* address read from the fuse ROM */
317 u32 fuse_oui_addr;
318 u32 fuse_nic_addr;
319
320 /* we have up to 2 MAC addresses */
321 struct mac_address addresses[2];
317 int channel; 322 int channel;
318 u8 system_hlid; 323 u8 system_hlid;
319 324