diff options
Diffstat (limited to 'drivers/net/wireless/b43/main.c')
-rw-r--r-- | drivers/net/wireless/b43/main.c | 149 |
1 files changed, 118 insertions, 31 deletions
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 15aaeb132a32..d7055febe119 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -210,6 +210,9 @@ static struct ieee80211_channel b43_2ghz_chantable[] = { | |||
210 | CHAN2G(13, 2472, 0), | 210 | CHAN2G(13, 2472, 0), |
211 | CHAN2G(14, 2484, 0), | 211 | CHAN2G(14, 2484, 0), |
212 | }; | 212 | }; |
213 | |||
214 | /* No support for the last 3 channels (12, 13, 14) */ | ||
215 | #define b43_2ghz_chantable_limited_size 11 | ||
213 | #undef CHAN2G | 216 | #undef CHAN2G |
214 | 217 | ||
215 | #define CHAN4G(_channel, _flags) { \ | 218 | #define CHAN4G(_channel, _flags) { \ |
@@ -287,6 +290,14 @@ static struct ieee80211_channel b43_5ghz_nphy_chantable[] = { | |||
287 | CHAN5G(182, 0), | 290 | CHAN5G(182, 0), |
288 | }; | 291 | }; |
289 | 292 | ||
293 | static struct ieee80211_channel b43_5ghz_nphy_chantable_limited[] = { | ||
294 | CHAN5G(36, 0), CHAN5G(40, 0), | ||
295 | CHAN5G(44, 0), CHAN5G(48, 0), | ||
296 | CHAN5G(149, 0), CHAN5G(153, 0), | ||
297 | CHAN5G(157, 0), CHAN5G(161, 0), | ||
298 | CHAN5G(165, 0), | ||
299 | }; | ||
300 | |||
290 | static struct ieee80211_channel b43_5ghz_aphy_chantable[] = { | 301 | static struct ieee80211_channel b43_5ghz_aphy_chantable[] = { |
291 | CHAN5G(34, 0), CHAN5G(36, 0), | 302 | CHAN5G(34, 0), CHAN5G(36, 0), |
292 | CHAN5G(38, 0), CHAN5G(40, 0), | 303 | CHAN5G(38, 0), CHAN5G(40, 0), |
@@ -319,6 +330,14 @@ static struct ieee80211_supported_band b43_band_5GHz_nphy = { | |||
319 | .n_bitrates = b43_a_ratetable_size, | 330 | .n_bitrates = b43_a_ratetable_size, |
320 | }; | 331 | }; |
321 | 332 | ||
333 | static struct ieee80211_supported_band b43_band_5GHz_nphy_limited = { | ||
334 | .band = IEEE80211_BAND_5GHZ, | ||
335 | .channels = b43_5ghz_nphy_chantable_limited, | ||
336 | .n_channels = ARRAY_SIZE(b43_5ghz_nphy_chantable_limited), | ||
337 | .bitrates = b43_a_ratetable, | ||
338 | .n_bitrates = b43_a_ratetable_size, | ||
339 | }; | ||
340 | |||
322 | static struct ieee80211_supported_band b43_band_5GHz_aphy = { | 341 | static struct ieee80211_supported_band b43_band_5GHz_aphy = { |
323 | .band = IEEE80211_BAND_5GHZ, | 342 | .band = IEEE80211_BAND_5GHZ, |
324 | .channels = b43_5ghz_aphy_chantable, | 343 | .channels = b43_5ghz_aphy_chantable, |
@@ -335,6 +354,14 @@ static struct ieee80211_supported_band b43_band_2GHz = { | |||
335 | .n_bitrates = b43_g_ratetable_size, | 354 | .n_bitrates = b43_g_ratetable_size, |
336 | }; | 355 | }; |
337 | 356 | ||
357 | static struct ieee80211_supported_band b43_band_2ghz_limited = { | ||
358 | .band = IEEE80211_BAND_2GHZ, | ||
359 | .channels = b43_2ghz_chantable, | ||
360 | .n_channels = b43_2ghz_chantable_limited_size, | ||
361 | .bitrates = b43_g_ratetable, | ||
362 | .n_bitrates = b43_g_ratetable_size, | ||
363 | }; | ||
364 | |||
338 | static void b43_wireless_core_exit(struct b43_wldev *dev); | 365 | static void b43_wireless_core_exit(struct b43_wldev *dev); |
339 | static int b43_wireless_core_init(struct b43_wldev *dev); | 366 | static int b43_wireless_core_init(struct b43_wldev *dev); |
340 | static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev); | 367 | static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev); |
@@ -2953,6 +2980,45 @@ void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on) | |||
2953 | } | 2980 | } |
2954 | } | 2981 | } |
2955 | 2982 | ||
2983 | /* brcms_b_switch_macfreq */ | ||
2984 | void b43_mac_switch_freq(struct b43_wldev *dev, u8 spurmode) | ||
2985 | { | ||
2986 | u16 chip_id = dev->dev->chip_id; | ||
2987 | |||
2988 | if (chip_id == BCMA_CHIP_ID_BCM43217 || | ||
2989 | chip_id == BCMA_CHIP_ID_BCM43222 || | ||
2990 | chip_id == BCMA_CHIP_ID_BCM43224 || | ||
2991 | chip_id == BCMA_CHIP_ID_BCM43225 || | ||
2992 | chip_id == BCMA_CHIP_ID_BCM43227 || | ||
2993 | chip_id == BCMA_CHIP_ID_BCM43228) { | ||
2994 | switch (spurmode) { | ||
2995 | case 2: /* 126 Mhz */ | ||
2996 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x2082); | ||
2997 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8); | ||
2998 | break; | ||
2999 | case 1: /* 123 Mhz */ | ||
3000 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x5341); | ||
3001 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8); | ||
3002 | break; | ||
3003 | default: /* 120 Mhz */ | ||
3004 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x8889); | ||
3005 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8); | ||
3006 | break; | ||
3007 | } | ||
3008 | } else if (dev->phy.type == B43_PHYTYPE_LCN) { | ||
3009 | switch (spurmode) { | ||
3010 | case 1: /* 82 Mhz */ | ||
3011 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x7CE0); | ||
3012 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC); | ||
3013 | break; | ||
3014 | default: /* 80 Mhz */ | ||
3015 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0xCCCD); | ||
3016 | b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC); | ||
3017 | break; | ||
3018 | } | ||
3019 | } | ||
3020 | } | ||
3021 | |||
2956 | static void b43_adjust_opmode(struct b43_wldev *dev) | 3022 | static void b43_adjust_opmode(struct b43_wldev *dev) |
2957 | { | 3023 | { |
2958 | struct b43_wl *wl = dev->wl; | 3024 | struct b43_wl *wl = dev->wl; |
@@ -4335,8 +4401,9 @@ static int b43_phy_versioning(struct b43_wldev *dev) | |||
4335 | u8 phy_type; | 4401 | u8 phy_type; |
4336 | u8 phy_rev; | 4402 | u8 phy_rev; |
4337 | u16 radio_manuf; | 4403 | u16 radio_manuf; |
4338 | u16 radio_ver; | 4404 | u16 radio_id; |
4339 | u16 radio_rev; | 4405 | u16 radio_rev; |
4406 | u8 radio_ver; | ||
4340 | int unsupported = 0; | 4407 | int unsupported = 0; |
4341 | 4408 | ||
4342 | /* Get PHY versioning */ | 4409 | /* Get PHY versioning */ |
@@ -4360,7 +4427,7 @@ static int b43_phy_versioning(struct b43_wldev *dev) | |||
4360 | #endif | 4427 | #endif |
4361 | #ifdef CONFIG_B43_PHY_N | 4428 | #ifdef CONFIG_B43_PHY_N |
4362 | case B43_PHYTYPE_N: | 4429 | case B43_PHYTYPE_N: |
4363 | if (phy_rev > 9) | 4430 | if (phy_rev >= 19) |
4364 | unsupported = 1; | 4431 | unsupported = 1; |
4365 | break; | 4432 | break; |
4366 | #endif | 4433 | #endif |
@@ -4402,7 +4469,9 @@ static int b43_phy_versioning(struct b43_wldev *dev) | |||
4402 | radio_rev = b43_read16(dev, B43_MMIO_RADIO24_DATA); | 4469 | radio_rev = b43_read16(dev, B43_MMIO_RADIO24_DATA); |
4403 | 4470 | ||
4404 | b43_write16(dev, B43_MMIO_RADIO24_CONTROL, 1); | 4471 | b43_write16(dev, B43_MMIO_RADIO24_CONTROL, 1); |
4405 | radio_ver = b43_read16(dev, B43_MMIO_RADIO24_DATA); | 4472 | radio_id = b43_read16(dev, B43_MMIO_RADIO24_DATA); |
4473 | |||
4474 | radio_ver = 0; /* Is there version somewhere? */ | ||
4406 | } else if (core_rev >= 24) { | 4475 | } else if (core_rev >= 24) { |
4407 | u16 radio24[3]; | 4476 | u16 radio24[3]; |
4408 | 4477 | ||
@@ -4411,12 +4480,10 @@ static int b43_phy_versioning(struct b43_wldev *dev) | |||
4411 | radio24[tmp] = b43_read16(dev, B43_MMIO_RADIO24_DATA); | 4480 | radio24[tmp] = b43_read16(dev, B43_MMIO_RADIO24_DATA); |
4412 | } | 4481 | } |
4413 | 4482 | ||
4414 | /* Broadcom uses "id" for our "ver" and has separated "ver" */ | ||
4415 | /* radio_ver = (radio24[0] & 0xF0) >> 4; */ | ||
4416 | |||
4417 | radio_manuf = 0x17F; | 4483 | radio_manuf = 0x17F; |
4418 | radio_ver = (radio24[2] << 8) | radio24[1]; | 4484 | radio_id = (radio24[2] << 8) | radio24[1]; |
4419 | radio_rev = (radio24[0] & 0xF); | 4485 | radio_rev = (radio24[0] & 0xF); |
4486 | radio_ver = (radio24[0] & 0xF0) >> 4; | ||
4420 | } else { | 4487 | } else { |
4421 | if (dev->dev->chip_id == 0x4317) { | 4488 | if (dev->dev->chip_id == 0x4317) { |
4422 | if (dev->dev->chip_rev == 0) | 4489 | if (dev->dev->chip_rev == 0) |
@@ -4435,15 +4502,16 @@ static int b43_phy_versioning(struct b43_wldev *dev) | |||
4435 | << 16; | 4502 | << 16; |
4436 | } | 4503 | } |
4437 | radio_manuf = (tmp & 0x00000FFF); | 4504 | radio_manuf = (tmp & 0x00000FFF); |
4438 | radio_ver = (tmp & 0x0FFFF000) >> 12; | 4505 | radio_id = (tmp & 0x0FFFF000) >> 12; |
4439 | radio_rev = (tmp & 0xF0000000) >> 28; | 4506 | radio_rev = (tmp & 0xF0000000) >> 28; |
4507 | radio_ver = 0; /* Probably not available on old hw */ | ||
4440 | } | 4508 | } |
4441 | 4509 | ||
4442 | if (radio_manuf != 0x17F /* Broadcom */) | 4510 | if (radio_manuf != 0x17F /* Broadcom */) |
4443 | unsupported = 1; | 4511 | unsupported = 1; |
4444 | switch (phy_type) { | 4512 | switch (phy_type) { |
4445 | case B43_PHYTYPE_A: | 4513 | case B43_PHYTYPE_A: |
4446 | if (radio_ver != 0x2060) | 4514 | if (radio_id != 0x2060) |
4447 | unsupported = 1; | 4515 | unsupported = 1; |
4448 | if (radio_rev != 1) | 4516 | if (radio_rev != 1) |
4449 | unsupported = 1; | 4517 | unsupported = 1; |
@@ -4451,43 +4519,49 @@ static int b43_phy_versioning(struct b43_wldev *dev) | |||
4451 | unsupported = 1; | 4519 | unsupported = 1; |
4452 | break; | 4520 | break; |
4453 | case B43_PHYTYPE_B: | 4521 | case B43_PHYTYPE_B: |
4454 | if ((radio_ver & 0xFFF0) != 0x2050) | 4522 | if ((radio_id & 0xFFF0) != 0x2050) |
4455 | unsupported = 1; | 4523 | unsupported = 1; |
4456 | break; | 4524 | break; |
4457 | case B43_PHYTYPE_G: | 4525 | case B43_PHYTYPE_G: |
4458 | if (radio_ver != 0x2050) | 4526 | if (radio_id != 0x2050) |
4459 | unsupported = 1; | 4527 | unsupported = 1; |
4460 | break; | 4528 | break; |
4461 | case B43_PHYTYPE_N: | 4529 | case B43_PHYTYPE_N: |
4462 | if (radio_ver != 0x2055 && radio_ver != 0x2056) | 4530 | if (radio_id != 0x2055 && radio_id != 0x2056 && |
4531 | radio_id != 0x2057) | ||
4532 | unsupported = 1; | ||
4533 | if (radio_id == 0x2057 && | ||
4534 | !(radio_rev == 9 || radio_rev == 14)) | ||
4463 | unsupported = 1; | 4535 | unsupported = 1; |
4464 | break; | 4536 | break; |
4465 | case B43_PHYTYPE_LP: | 4537 | case B43_PHYTYPE_LP: |
4466 | if (radio_ver != 0x2062 && radio_ver != 0x2063) | 4538 | if (radio_id != 0x2062 && radio_id != 0x2063) |
4467 | unsupported = 1; | 4539 | unsupported = 1; |
4468 | break; | 4540 | break; |
4469 | case B43_PHYTYPE_HT: | 4541 | case B43_PHYTYPE_HT: |
4470 | if (radio_ver != 0x2059) | 4542 | if (radio_id != 0x2059) |
4471 | unsupported = 1; | 4543 | unsupported = 1; |
4472 | break; | 4544 | break; |
4473 | case B43_PHYTYPE_LCN: | 4545 | case B43_PHYTYPE_LCN: |
4474 | if (radio_ver != 0x2064) | 4546 | if (radio_id != 0x2064) |
4475 | unsupported = 1; | 4547 | unsupported = 1; |
4476 | break; | 4548 | break; |
4477 | default: | 4549 | default: |
4478 | B43_WARN_ON(1); | 4550 | B43_WARN_ON(1); |
4479 | } | 4551 | } |
4480 | if (unsupported) { | 4552 | if (unsupported) { |
4481 | b43err(dev->wl, "FOUND UNSUPPORTED RADIO " | 4553 | b43err(dev->wl, |
4482 | "(Manuf 0x%X, Version 0x%X, Revision %u)\n", | 4554 | "FOUND UNSUPPORTED RADIO (Manuf 0x%X, ID 0x%X, Revision %u, Version %u)\n", |
4483 | radio_manuf, radio_ver, radio_rev); | 4555 | radio_manuf, radio_id, radio_rev, radio_ver); |
4484 | return -EOPNOTSUPP; | 4556 | return -EOPNOTSUPP; |
4485 | } | 4557 | } |
4486 | b43dbg(dev->wl, "Found Radio: Manuf 0x%X, Version 0x%X, Revision %u\n", | 4558 | b43info(dev->wl, |
4487 | radio_manuf, radio_ver, radio_rev); | 4559 | "Found Radio: Manuf 0x%X, ID 0x%X, Revision %u, Version %u\n", |
4560 | radio_manuf, radio_id, radio_rev, radio_ver); | ||
4488 | 4561 | ||
4562 | /* FIXME: b43 treats "id" as "ver" and ignores the real "ver" */ | ||
4489 | phy->radio_manuf = radio_manuf; | 4563 | phy->radio_manuf = radio_manuf; |
4490 | phy->radio_ver = radio_ver; | 4564 | phy->radio_ver = radio_id; |
4491 | phy->radio_rev = radio_rev; | 4565 | phy->radio_rev = radio_rev; |
4492 | 4566 | ||
4493 | phy->analog = analog_type; | 4567 | phy->analog = analog_type; |
@@ -5095,12 +5169,24 @@ static int b43_setup_bands(struct b43_wldev *dev, | |||
5095 | bool have_2ghz_phy, bool have_5ghz_phy) | 5169 | bool have_2ghz_phy, bool have_5ghz_phy) |
5096 | { | 5170 | { |
5097 | struct ieee80211_hw *hw = dev->wl->hw; | 5171 | struct ieee80211_hw *hw = dev->wl->hw; |
5172 | struct b43_phy *phy = &dev->phy; | ||
5173 | bool limited_2g; | ||
5174 | bool limited_5g; | ||
5175 | |||
5176 | /* We don't support all 2 GHz channels on some devices */ | ||
5177 | limited_2g = phy->radio_ver == 0x2057 && | ||
5178 | (phy->radio_rev == 9 || phy->radio_rev == 14); | ||
5179 | limited_5g = phy->radio_ver == 0x2057 && | ||
5180 | phy->radio_rev == 9; | ||
5098 | 5181 | ||
5099 | if (have_2ghz_phy) | 5182 | if (have_2ghz_phy) |
5100 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &b43_band_2GHz; | 5183 | hw->wiphy->bands[IEEE80211_BAND_2GHZ] = limited_2g ? |
5184 | &b43_band_2ghz_limited : &b43_band_2GHz; | ||
5101 | if (dev->phy.type == B43_PHYTYPE_N) { | 5185 | if (dev->phy.type == B43_PHYTYPE_N) { |
5102 | if (have_5ghz_phy) | 5186 | if (have_5ghz_phy) |
5103 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_nphy; | 5187 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = limited_5g ? |
5188 | &b43_band_5GHz_nphy_limited : | ||
5189 | &b43_band_5GHz_nphy; | ||
5104 | } else { | 5190 | } else { |
5105 | if (have_5ghz_phy) | 5191 | if (have_5ghz_phy) |
5106 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_aphy; | 5192 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_aphy; |
@@ -5248,14 +5334,15 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) | |||
5248 | b43_supported_bands(dev, &have_2ghz_phy, &have_5ghz_phy); | 5334 | b43_supported_bands(dev, &have_2ghz_phy, &have_5ghz_phy); |
5249 | 5335 | ||
5250 | /* We don't support 5 GHz on some PHYs yet */ | 5336 | /* We don't support 5 GHz on some PHYs yet */ |
5251 | switch (dev->phy.type) { | 5337 | if (have_5ghz_phy) { |
5252 | case B43_PHYTYPE_A: | 5338 | switch (dev->phy.type) { |
5253 | case B43_PHYTYPE_G: | 5339 | case B43_PHYTYPE_A: |
5254 | case B43_PHYTYPE_N: | 5340 | case B43_PHYTYPE_G: |
5255 | case B43_PHYTYPE_LP: | 5341 | case B43_PHYTYPE_LP: |
5256 | case B43_PHYTYPE_HT: | 5342 | case B43_PHYTYPE_HT: |
5257 | b43warn(wl, "5 GHz band is unsupported on this PHY\n"); | 5343 | b43warn(wl, "5 GHz band is unsupported on this PHY\n"); |
5258 | have_5ghz_phy = false; | 5344 | have_5ghz_phy = false; |
5345 | } | ||
5259 | } | 5346 | } |
5260 | 5347 | ||
5261 | if (!have_2ghz_phy && !have_5ghz_phy) { | 5348 | if (!have_2ghz_phy && !have_5ghz_phy) { |