diff options
Diffstat (limited to 'drivers/net/wireless/b43')
-rw-r--r-- | drivers/net/wireless/b43/b43.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/b43/main.c | 26 | ||||
-rw-r--r-- | drivers/net/wireless/b43/phy_n.c | 479 | ||||
-rw-r--r-- | drivers/net/wireless/b43/phy_n.h | 21 | ||||
-rw-r--r-- | drivers/net/wireless/b43/tables_nphy.c | 22 | ||||
-rw-r--r-- | drivers/net/wireless/b43/tables_nphy.h | 37 | ||||
-rw-r--r-- | drivers/net/wireless/b43/xmit.c | 1 |
7 files changed, 452 insertions, 135 deletions
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index b8807fb12c92..3a003e6803a5 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
@@ -104,6 +104,7 @@ | |||
104 | #define B43_MMIO_MACFILTER_CONTROL 0x420 | 104 | #define B43_MMIO_MACFILTER_CONTROL 0x420 |
105 | #define B43_MMIO_MACFILTER_DATA 0x422 | 105 | #define B43_MMIO_MACFILTER_DATA 0x422 |
106 | #define B43_MMIO_RCMTA_COUNT 0x43C | 106 | #define B43_MMIO_RCMTA_COUNT 0x43C |
107 | #define B43_MMIO_PSM_PHY_HDR 0x492 | ||
107 | #define B43_MMIO_RADIO_HWENABLED_LO 0x49A | 108 | #define B43_MMIO_RADIO_HWENABLED_LO 0x49A |
108 | #define B43_MMIO_GPIO_CONTROL 0x49C | 109 | #define B43_MMIO_GPIO_CONTROL 0x49C |
109 | #define B43_MMIO_GPIO_MASK 0x49E | 110 | #define B43_MMIO_GPIO_MASK 0x49E |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 9a374ef83a22..7965b70efbab 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -4349,11 +4349,10 @@ static int b43_wireless_core_init(struct b43_wldev *dev) | |||
4349 | b43_set_phytxctl_defaults(dev); | 4349 | b43_set_phytxctl_defaults(dev); |
4350 | 4350 | ||
4351 | /* Minimum Contention Window */ | 4351 | /* Minimum Contention Window */ |
4352 | if (phy->type == B43_PHYTYPE_B) { | 4352 | if (phy->type == B43_PHYTYPE_B) |
4353 | b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MINCONT, 0x1F); | 4353 | b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MINCONT, 0x1F); |
4354 | } else { | 4354 | else |
4355 | b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MINCONT, 0xF); | 4355 | b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MINCONT, 0xF); |
4356 | } | ||
4357 | /* Maximum Contention Window */ | 4356 | /* Maximum Contention Window */ |
4358 | b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF); | 4357 | b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF); |
4359 | 4358 | ||
@@ -4572,6 +4571,23 @@ static void b43_op_sw_scan_complete_notifier(struct ieee80211_hw *hw) | |||
4572 | mutex_unlock(&wl->mutex); | 4571 | mutex_unlock(&wl->mutex); |
4573 | } | 4572 | } |
4574 | 4573 | ||
4574 | static int b43_op_get_survey(struct ieee80211_hw *hw, int idx, | ||
4575 | struct survey_info *survey) | ||
4576 | { | ||
4577 | struct b43_wl *wl = hw_to_b43_wl(hw); | ||
4578 | struct b43_wldev *dev = wl->current_dev; | ||
4579 | struct ieee80211_conf *conf = &hw->conf; | ||
4580 | |||
4581 | if (idx != 0) | ||
4582 | return -ENOENT; | ||
4583 | |||
4584 | survey->channel = conf->channel; | ||
4585 | survey->filled = SURVEY_INFO_NOISE_DBM; | ||
4586 | survey->noise = dev->stats.link_noise; | ||
4587 | |||
4588 | return 0; | ||
4589 | } | ||
4590 | |||
4575 | static const struct ieee80211_ops b43_hw_ops = { | 4591 | static const struct ieee80211_ops b43_hw_ops = { |
4576 | .tx = b43_op_tx, | 4592 | .tx = b43_op_tx, |
4577 | .conf_tx = b43_op_conf_tx, | 4593 | .conf_tx = b43_op_conf_tx, |
@@ -4591,6 +4607,7 @@ static const struct ieee80211_ops b43_hw_ops = { | |||
4591 | .sta_notify = b43_op_sta_notify, | 4607 | .sta_notify = b43_op_sta_notify, |
4592 | .sw_scan_start = b43_op_sw_scan_start_notifier, | 4608 | .sw_scan_start = b43_op_sw_scan_start_notifier, |
4593 | .sw_scan_complete = b43_op_sw_scan_complete_notifier, | 4609 | .sw_scan_complete = b43_op_sw_scan_complete_notifier, |
4610 | .get_survey = b43_op_get_survey, | ||
4594 | .rfkill_poll = b43_rfkill_poll, | 4611 | .rfkill_poll = b43_rfkill_poll, |
4595 | }; | 4612 | }; |
4596 | 4613 | ||
@@ -4906,8 +4923,7 @@ static int b43_wireless_init(struct ssb_device *dev) | |||
4906 | 4923 | ||
4907 | /* fill hw info */ | 4924 | /* fill hw info */ |
4908 | hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | | 4925 | hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | |
4909 | IEEE80211_HW_SIGNAL_DBM | | 4926 | IEEE80211_HW_SIGNAL_DBM; |
4910 | IEEE80211_HW_NOISE_DBM; | ||
4911 | 4927 | ||
4912 | hw->wiphy->interface_modes = | 4928 | hw->wiphy->interface_modes = |
4913 | BIT(NL80211_IFTYPE_AP) | | 4929 | BIT(NL80211_IFTYPE_AP) | |
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 9c7cd282e46c..3d6b33775964 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c | |||
@@ -73,6 +73,22 @@ static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field, | |||
73 | u16 value, u8 core, bool off); | 73 | u16 value, u8 core, bool off); |
74 | static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field, | 74 | static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field, |
75 | u16 value, u8 core); | 75 | u16 value, u8 core); |
76 | static int nphy_channel_switch(struct b43_wldev *dev, unsigned int channel); | ||
77 | |||
78 | static inline bool b43_empty_chanspec(struct b43_chanspec *chanspec) | ||
79 | { | ||
80 | return !chanspec->channel && !chanspec->sideband && | ||
81 | !chanspec->b_width && !chanspec->b_freq; | ||
82 | } | ||
83 | |||
84 | static inline bool b43_eq_chanspecs(struct b43_chanspec *chanspec1, | ||
85 | struct b43_chanspec *chanspec2) | ||
86 | { | ||
87 | return (chanspec1->channel == chanspec2->channel && | ||
88 | chanspec1->sideband == chanspec2->sideband && | ||
89 | chanspec1->b_width == chanspec2->b_width && | ||
90 | chanspec1->b_freq == chanspec2->b_freq); | ||
91 | } | ||
76 | 92 | ||
77 | void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna) | 93 | void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna) |
78 | {//TODO | 94 | {//TODO |
@@ -89,34 +105,44 @@ static enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev, | |||
89 | } | 105 | } |
90 | 106 | ||
91 | static void b43_chantab_radio_upload(struct b43_wldev *dev, | 107 | static void b43_chantab_radio_upload(struct b43_wldev *dev, |
92 | const struct b43_nphy_channeltab_entry *e) | 108 | const struct b43_nphy_channeltab_entry_rev2 *e) |
93 | { | 109 | { |
94 | b43_radio_write16(dev, B2055_PLL_REF, e->radio_pll_ref); | 110 | b43_radio_write(dev, B2055_PLL_REF, e->radio_pll_ref); |
95 | b43_radio_write16(dev, B2055_RF_PLLMOD0, e->radio_rf_pllmod0); | 111 | b43_radio_write(dev, B2055_RF_PLLMOD0, e->radio_rf_pllmod0); |
96 | b43_radio_write16(dev, B2055_RF_PLLMOD1, e->radio_rf_pllmod1); | 112 | b43_radio_write(dev, B2055_RF_PLLMOD1, e->radio_rf_pllmod1); |
97 | b43_radio_write16(dev, B2055_VCO_CAPTAIL, e->radio_vco_captail); | 113 | b43_radio_write(dev, B2055_VCO_CAPTAIL, e->radio_vco_captail); |
98 | b43_radio_write16(dev, B2055_VCO_CAL1, e->radio_vco_cal1); | 114 | b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ |
99 | b43_radio_write16(dev, B2055_VCO_CAL2, e->radio_vco_cal2); | 115 | |
100 | b43_radio_write16(dev, B2055_PLL_LFC1, e->radio_pll_lfc1); | 116 | b43_radio_write(dev, B2055_VCO_CAL1, e->radio_vco_cal1); |
101 | b43_radio_write16(dev, B2055_PLL_LFR1, e->radio_pll_lfr1); | 117 | b43_radio_write(dev, B2055_VCO_CAL2, e->radio_vco_cal2); |
102 | b43_radio_write16(dev, B2055_PLL_LFC2, e->radio_pll_lfc2); | 118 | b43_radio_write(dev, B2055_PLL_LFC1, e->radio_pll_lfc1); |
103 | b43_radio_write16(dev, B2055_LGBUF_CENBUF, e->radio_lgbuf_cenbuf); | 119 | b43_radio_write(dev, B2055_PLL_LFR1, e->radio_pll_lfr1); |
104 | b43_radio_write16(dev, B2055_LGEN_TUNE1, e->radio_lgen_tune1); | 120 | b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ |
105 | b43_radio_write16(dev, B2055_LGEN_TUNE2, e->radio_lgen_tune2); | 121 | |
106 | b43_radio_write16(dev, B2055_C1_LGBUF_ATUNE, e->radio_c1_lgbuf_atune); | 122 | b43_radio_write(dev, B2055_PLL_LFC2, e->radio_pll_lfc2); |
107 | b43_radio_write16(dev, B2055_C1_LGBUF_GTUNE, e->radio_c1_lgbuf_gtune); | 123 | b43_radio_write(dev, B2055_LGBUF_CENBUF, e->radio_lgbuf_cenbuf); |
108 | b43_radio_write16(dev, B2055_C1_RX_RFR1, e->radio_c1_rx_rfr1); | 124 | b43_radio_write(dev, B2055_LGEN_TUNE1, e->radio_lgen_tune1); |
109 | b43_radio_write16(dev, B2055_C1_TX_PGAPADTN, e->radio_c1_tx_pgapadtn); | 125 | b43_radio_write(dev, B2055_LGEN_TUNE2, e->radio_lgen_tune2); |
110 | b43_radio_write16(dev, B2055_C1_TX_MXBGTRIM, e->radio_c1_tx_mxbgtrim); | 126 | b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ |
111 | b43_radio_write16(dev, B2055_C2_LGBUF_ATUNE, e->radio_c2_lgbuf_atune); | 127 | |
112 | b43_radio_write16(dev, B2055_C2_LGBUF_GTUNE, e->radio_c2_lgbuf_gtune); | 128 | b43_radio_write(dev, B2055_C1_LGBUF_ATUNE, e->radio_c1_lgbuf_atune); |
113 | b43_radio_write16(dev, B2055_C2_RX_RFR1, e->radio_c2_rx_rfr1); | 129 | b43_radio_write(dev, B2055_C1_LGBUF_GTUNE, e->radio_c1_lgbuf_gtune); |
114 | b43_radio_write16(dev, B2055_C2_TX_PGAPADTN, e->radio_c2_tx_pgapadtn); | 130 | b43_radio_write(dev, B2055_C1_RX_RFR1, e->radio_c1_rx_rfr1); |
115 | b43_radio_write16(dev, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim); | 131 | b43_radio_write(dev, B2055_C1_TX_PGAPADTN, e->radio_c1_tx_pgapadtn); |
132 | b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ | ||
133 | |||
134 | b43_radio_write(dev, B2055_C1_TX_MXBGTRIM, e->radio_c1_tx_mxbgtrim); | ||
135 | b43_radio_write(dev, B2055_C2_LGBUF_ATUNE, e->radio_c2_lgbuf_atune); | ||
136 | b43_radio_write(dev, B2055_C2_LGBUF_GTUNE, e->radio_c2_lgbuf_gtune); | ||
137 | b43_radio_write(dev, B2055_C2_RX_RFR1, e->radio_c2_rx_rfr1); | ||
138 | b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ | ||
139 | |||
140 | b43_radio_write(dev, B2055_C2_TX_PGAPADTN, e->radio_c2_tx_pgapadtn); | ||
141 | b43_radio_write(dev, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim); | ||
116 | } | 142 | } |
117 | 143 | ||
118 | static void b43_chantab_phy_upload(struct b43_wldev *dev, | 144 | static void b43_chantab_phy_upload(struct b43_wldev *dev, |
119 | const struct b43_nphy_channeltab_entry *e) | 145 | const struct b43_phy_n_sfo_cfg *e) |
120 | { | 146 | { |
121 | b43_phy_write(dev, B43_NPHY_BW1A, e->phy_bw1a); | 147 | b43_phy_write(dev, B43_NPHY_BW1A, e->phy_bw1a); |
122 | b43_phy_write(dev, B43_NPHY_BW2, e->phy_bw2); | 148 | b43_phy_write(dev, B43_NPHY_BW2, e->phy_bw2); |
@@ -131,34 +157,20 @@ static void b43_nphy_tx_power_fix(struct b43_wldev *dev) | |||
131 | //TODO | 157 | //TODO |
132 | } | 158 | } |
133 | 159 | ||
134 | /* Tune the hardware to a new channel. */ | ||
135 | static int nphy_channel_switch(struct b43_wldev *dev, unsigned int channel) | ||
136 | { | ||
137 | const struct b43_nphy_channeltab_entry *tabent; | ||
138 | 160 | ||
139 | tabent = b43_nphy_get_chantabent(dev, channel); | 161 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */ |
140 | if (!tabent) | 162 | static void b43_radio_2055_setup(struct b43_wldev *dev, |
141 | return -ESRCH; | 163 | const struct b43_nphy_channeltab_entry_rev2 *e) |
164 | { | ||
165 | B43_WARN_ON(dev->phy.rev >= 3); | ||
142 | 166 | ||
143 | //FIXME enable/disable band select upper20 in RXCTL | 167 | b43_chantab_radio_upload(dev, e); |
144 | if (0 /*FIXME 5Ghz*/) | ||
145 | b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, 0x20); | ||
146 | else | ||
147 | b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, 0x50); | ||
148 | b43_chantab_radio_upload(dev, tabent); | ||
149 | udelay(50); | 168 | udelay(50); |
150 | b43_radio_write16(dev, B2055_VCO_CAL10, 5); | 169 | b43_radio_write(dev, B2055_VCO_CAL10, 0x05); |
151 | b43_radio_write16(dev, B2055_VCO_CAL10, 45); | 170 | b43_radio_write(dev, B2055_VCO_CAL10, 0x45); |
152 | b43_radio_write16(dev, B2055_VCO_CAL10, 65); | 171 | b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */ |
172 | b43_radio_write(dev, B2055_VCO_CAL10, 0x65); | ||
153 | udelay(300); | 173 | udelay(300); |
154 | if (0 /*FIXME 5Ghz*/) | ||
155 | b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ); | ||
156 | else | ||
157 | b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ); | ||
158 | b43_chantab_phy_upload(dev, tabent); | ||
159 | b43_nphy_tx_power_fix(dev); | ||
160 | |||
161 | return 0; | ||
162 | } | 174 | } |
163 | 175 | ||
164 | static void b43_radio_init2055_pre(struct b43_wldev *dev) | 176 | static void b43_radio_init2055_pre(struct b43_wldev *dev) |
@@ -174,52 +186,64 @@ static void b43_radio_init2055_pre(struct b43_wldev *dev) | |||
174 | 186 | ||
175 | static void b43_radio_init2055_post(struct b43_wldev *dev) | 187 | static void b43_radio_init2055_post(struct b43_wldev *dev) |
176 | { | 188 | { |
189 | struct b43_phy_n *nphy = dev->phy.n; | ||
177 | struct ssb_sprom *sprom = &(dev->dev->bus->sprom); | 190 | struct ssb_sprom *sprom = &(dev->dev->bus->sprom); |
178 | struct ssb_boardinfo *binfo = &(dev->dev->bus->boardinfo); | 191 | struct ssb_boardinfo *binfo = &(dev->dev->bus->boardinfo); |
179 | int i; | 192 | int i; |
180 | u16 val; | 193 | u16 val; |
194 | bool workaround = false; | ||
195 | |||
196 | if (sprom->revision < 4) | ||
197 | workaround = (binfo->vendor != PCI_VENDOR_ID_BROADCOM || | ||
198 | binfo->type != 0x46D || | ||
199 | binfo->rev < 0x41); | ||
200 | else | ||
201 | workaround = ((sprom->boardflags_hi & B43_BFH_NOPA) == 0); | ||
181 | 202 | ||
182 | b43_radio_mask(dev, B2055_MASTER1, 0xFFF3); | 203 | b43_radio_mask(dev, B2055_MASTER1, 0xFFF3); |
183 | msleep(1); | 204 | if (workaround) { |
184 | if ((sprom->revision != 4) || | 205 | b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F); |
185 | !(sprom->boardflags_hi & B43_BFH_RSSIINV)) { | 206 | b43_radio_mask(dev, B2055_C2_RX_BB_REG, 0x7F); |
186 | if ((binfo->vendor != PCI_VENDOR_ID_BROADCOM) || | ||
187 | (binfo->type != 0x46D) || | ||
188 | (binfo->rev < 0x41)) { | ||
189 | b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F); | ||
190 | b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F); | ||
191 | msleep(1); | ||
192 | } | ||
193 | } | 207 | } |
194 | b43_radio_maskset(dev, B2055_RRCCAL_NOPTSEL, 0x3F, 0x2C); | 208 | b43_radio_maskset(dev, B2055_RRCCAL_NOPTSEL, 0xFFC0, 0x2C); |
195 | msleep(1); | 209 | b43_radio_write(dev, B2055_CAL_MISC, 0x3C); |
196 | b43_radio_write16(dev, B2055_CAL_MISC, 0x3C); | ||
197 | msleep(1); | ||
198 | b43_radio_mask(dev, B2055_CAL_MISC, 0xFFBE); | 210 | b43_radio_mask(dev, B2055_CAL_MISC, 0xFFBE); |
199 | msleep(1); | ||
200 | b43_radio_set(dev, B2055_CAL_LPOCTL, 0x80); | 211 | b43_radio_set(dev, B2055_CAL_LPOCTL, 0x80); |
201 | msleep(1); | ||
202 | b43_radio_set(dev, B2055_CAL_MISC, 0x1); | 212 | b43_radio_set(dev, B2055_CAL_MISC, 0x1); |
203 | msleep(1); | 213 | msleep(1); |
204 | b43_radio_set(dev, B2055_CAL_MISC, 0x40); | 214 | b43_radio_set(dev, B2055_CAL_MISC, 0x40); |
205 | msleep(1); | 215 | for (i = 0; i < 200; i++) { |
206 | for (i = 0; i < 100; i++) { | 216 | val = b43_radio_read(dev, B2055_CAL_COUT2); |
207 | val = b43_radio_read16(dev, B2055_CAL_COUT2); | 217 | if (val & 0x80) { |
208 | if (val & 0x80) | 218 | i = 0; |
209 | break; | 219 | break; |
220 | } | ||
210 | udelay(10); | 221 | udelay(10); |
211 | } | 222 | } |
212 | msleep(1); | 223 | if (i) |
224 | b43err(dev->wl, "radio post init timeout\n"); | ||
213 | b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F); | 225 | b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F); |
214 | msleep(1); | ||
215 | nphy_channel_switch(dev, dev->phy.channel); | 226 | nphy_channel_switch(dev, dev->phy.channel); |
216 | b43_radio_write16(dev, B2055_C1_RX_BB_LPF, 0x9); | 227 | b43_radio_write(dev, B2055_C1_RX_BB_LPF, 0x9); |
217 | b43_radio_write16(dev, B2055_C2_RX_BB_LPF, 0x9); | 228 | b43_radio_write(dev, B2055_C2_RX_BB_LPF, 0x9); |
218 | b43_radio_write16(dev, B2055_C1_RX_BB_MIDACHP, 0x83); | 229 | b43_radio_write(dev, B2055_C1_RX_BB_MIDACHP, 0x83); |
219 | b43_radio_write16(dev, B2055_C2_RX_BB_MIDACHP, 0x83); | 230 | b43_radio_write(dev, B2055_C2_RX_BB_MIDACHP, 0x83); |
231 | b43_radio_maskset(dev, B2055_C1_LNA_GAINBST, 0xFFF8, 0x6); | ||
232 | b43_radio_maskset(dev, B2055_C2_LNA_GAINBST, 0xFFF8, 0x6); | ||
233 | if (!nphy->gain_boost) { | ||
234 | b43_radio_set(dev, B2055_C1_RX_RFSPC1, 0x2); | ||
235 | b43_radio_set(dev, B2055_C2_RX_RFSPC1, 0x2); | ||
236 | } else { | ||
237 | b43_radio_mask(dev, B2055_C1_RX_RFSPC1, 0xFFFD); | ||
238 | b43_radio_mask(dev, B2055_C2_RX_RFSPC1, 0xFFFD); | ||
239 | } | ||
240 | udelay(2); | ||
220 | } | 241 | } |
221 | 242 | ||
222 | /* Initialize a Broadcom 2055 N-radio */ | 243 | /* |
244 | * Initialize a Broadcom 2055 N-radio | ||
245 | * http://bcm-v4.sipsolutions.net/802.11/Radio/2055/Init | ||
246 | */ | ||
223 | static void b43_radio_init2055(struct b43_wldev *dev) | 247 | static void b43_radio_init2055(struct b43_wldev *dev) |
224 | { | 248 | { |
225 | b43_radio_init2055_pre(dev); | 249 | b43_radio_init2055_pre(dev); |
@@ -230,16 +254,15 @@ static void b43_radio_init2055(struct b43_wldev *dev) | |||
230 | b43_radio_init2055_post(dev); | 254 | b43_radio_init2055_post(dev); |
231 | } | 255 | } |
232 | 256 | ||
233 | void b43_nphy_radio_turn_on(struct b43_wldev *dev) | 257 | /* |
258 | * Initialize a Broadcom 2056 N-radio | ||
259 | * http://bcm-v4.sipsolutions.net/802.11/Radio/2056/Init | ||
260 | */ | ||
261 | static void b43_radio_init2056(struct b43_wldev *dev) | ||
234 | { | 262 | { |
235 | b43_radio_init2055(dev); | 263 | /* TODO */ |
236 | } | 264 | } |
237 | 265 | ||
238 | void b43_nphy_radio_turn_off(struct b43_wldev *dev) | ||
239 | { | ||
240 | b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, | ||
241 | ~B43_NPHY_RFCTL_CMD_EN); | ||
242 | } | ||
243 | 266 | ||
244 | /* | 267 | /* |
245 | * Upload the N-PHY tables. | 268 | * Upload the N-PHY tables. |
@@ -647,6 +670,41 @@ static void b43_nphy_read_clip_detection(struct b43_wldev *dev, u16 *clip_st) | |||
647 | clip_st[1] = b43_phy_read(dev, B43_NPHY_C2_CLIP1THRES); | 670 | clip_st[1] = b43_phy_read(dev, B43_NPHY_C2_CLIP1THRES); |
648 | } | 671 | } |
649 | 672 | ||
673 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SuperSwitchInit */ | ||
674 | static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init) | ||
675 | { | ||
676 | if (dev->phy.rev >= 3) { | ||
677 | if (!init) | ||
678 | return; | ||
679 | if (0 /* FIXME */) { | ||
680 | b43_ntab_write(dev, B43_NTAB16(9, 2), 0x211); | ||
681 | b43_ntab_write(dev, B43_NTAB16(9, 3), 0x222); | ||
682 | b43_ntab_write(dev, B43_NTAB16(9, 8), 0x144); | ||
683 | b43_ntab_write(dev, B43_NTAB16(9, 12), 0x188); | ||
684 | } | ||
685 | } else { | ||
686 | b43_phy_write(dev, B43_NPHY_GPIO_LOOEN, 0); | ||
687 | b43_phy_write(dev, B43_NPHY_GPIO_HIOEN, 0); | ||
688 | |||
689 | ssb_chipco_gpio_control(&dev->dev->bus->chipco, 0xFC00, | ||
690 | 0xFC00); | ||
691 | b43_write32(dev, B43_MMIO_MACCTL, | ||
692 | b43_read32(dev, B43_MMIO_MACCTL) & | ||
693 | ~B43_MACCTL_GPOUTSMSK); | ||
694 | b43_write16(dev, B43_MMIO_GPIO_MASK, | ||
695 | b43_read16(dev, B43_MMIO_GPIO_MASK) | 0xFC00); | ||
696 | b43_write16(dev, B43_MMIO_GPIO_CONTROL, | ||
697 | b43_read16(dev, B43_MMIO_GPIO_CONTROL) & ~0xFC00); | ||
698 | |||
699 | if (init) { | ||
700 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8); | ||
701 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301); | ||
702 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8); | ||
703 | b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301); | ||
704 | } | ||
705 | } | ||
706 | } | ||
707 | |||
650 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/classifier */ | 708 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/classifier */ |
651 | static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val) | 709 | static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val) |
652 | { | 710 | { |
@@ -723,7 +781,7 @@ static void b43_nphy_spur_workaround(struct b43_wldev *dev) | |||
723 | { | 781 | { |
724 | struct b43_phy_n *nphy = dev->phy.n; | 782 | struct b43_phy_n *nphy = dev->phy.n; |
725 | 783 | ||
726 | unsigned int channel; | 784 | u8 channel = nphy->radio_chanspec.channel; |
727 | int tone[2] = { 57, 58 }; | 785 | int tone[2] = { 57, 58 }; |
728 | u32 noise[2] = { 0x3FF, 0x3FF }; | 786 | u32 noise[2] = { 0x3FF, 0x3FF }; |
729 | 787 | ||
@@ -732,8 +790,6 @@ static void b43_nphy_spur_workaround(struct b43_wldev *dev) | |||
732 | if (nphy->hang_avoid) | 790 | if (nphy->hang_avoid) |
733 | b43_nphy_stay_in_carrier_search(dev, 1); | 791 | b43_nphy_stay_in_carrier_search(dev, 1); |
734 | 792 | ||
735 | /* FIXME: channel = radio_chanspec */ | ||
736 | |||
737 | if (nphy->gband_spurwar_en) { | 793 | if (nphy->gband_spurwar_en) { |
738 | /* TODO: N PHY Adjust Analog Pfbw (7) */ | 794 | /* TODO: N PHY Adjust Analog Pfbw (7) */ |
739 | if (channel == 11 && dev->phy.is_40mhz) | 795 | if (channel == 11 && dev->phy.is_40mhz) |
@@ -779,6 +835,62 @@ static void b43_nphy_spur_workaround(struct b43_wldev *dev) | |||
779 | b43_nphy_stay_in_carrier_search(dev, 0); | 835 | b43_nphy_stay_in_carrier_search(dev, 0); |
780 | } | 836 | } |
781 | 837 | ||
838 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/AdjustLnaGainTbl */ | ||
839 | static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev) | ||
840 | { | ||
841 | struct b43_phy_n *nphy = dev->phy.n; | ||
842 | |||
843 | u8 i; | ||
844 | s16 tmp; | ||
845 | u16 data[4]; | ||
846 | s16 gain[2]; | ||
847 | u16 minmax[2]; | ||
848 | u16 lna_gain[4] = { -2, 10, 19, 25 }; | ||
849 | |||
850 | if (nphy->hang_avoid) | ||
851 | b43_nphy_stay_in_carrier_search(dev, 1); | ||
852 | |||
853 | if (nphy->gain_boost) { | ||
854 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | ||
855 | gain[0] = 6; | ||
856 | gain[1] = 6; | ||
857 | } else { | ||
858 | tmp = 40370 - 315 * nphy->radio_chanspec.channel; | ||
859 | gain[0] = ((tmp >> 13) + ((tmp >> 12) & 1)); | ||
860 | tmp = 23242 - 224 * nphy->radio_chanspec.channel; | ||
861 | gain[1] = ((tmp >> 13) + ((tmp >> 12) & 1)); | ||
862 | } | ||
863 | } else { | ||
864 | gain[0] = 0; | ||
865 | gain[1] = 0; | ||
866 | } | ||
867 | |||
868 | for (i = 0; i < 2; i++) { | ||
869 | if (nphy->elna_gain_config) { | ||
870 | data[0] = 19 + gain[i]; | ||
871 | data[1] = 25 + gain[i]; | ||
872 | data[2] = 25 + gain[i]; | ||
873 | data[3] = 25 + gain[i]; | ||
874 | } else { | ||
875 | data[0] = lna_gain[0] + gain[i]; | ||
876 | data[1] = lna_gain[1] + gain[i]; | ||
877 | data[2] = lna_gain[2] + gain[i]; | ||
878 | data[3] = lna_gain[3] + gain[i]; | ||
879 | } | ||
880 | b43_ntab_write_bulk(dev, B43_NTAB16(10, 8), 4, data); | ||
881 | |||
882 | minmax[i] = 23 + gain[i]; | ||
883 | } | ||
884 | |||
885 | b43_phy_maskset(dev, B43_NPHY_C1_MINMAX_GAIN, ~B43_NPHY_C1_MINGAIN, | ||
886 | minmax[0] << B43_NPHY_C1_MINGAIN_SHIFT); | ||
887 | b43_phy_maskset(dev, B43_NPHY_C2_MINMAX_GAIN, ~B43_NPHY_C2_MINGAIN, | ||
888 | minmax[1] << B43_NPHY_C2_MINGAIN_SHIFT); | ||
889 | |||
890 | if (nphy->hang_avoid) | ||
891 | b43_nphy_stay_in_carrier_search(dev, 0); | ||
892 | } | ||
893 | |||
782 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */ | 894 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */ |
783 | static void b43_nphy_gain_crtl_workarounds(struct b43_wldev *dev) | 895 | static void b43_nphy_gain_crtl_workarounds(struct b43_wldev *dev) |
784 | { | 896 | { |
@@ -863,7 +975,7 @@ static void b43_nphy_gain_crtl_workarounds(struct b43_wldev *dev) | |||
863 | b43_phy_write(dev, B43_NPHY_TABLE_DATALO, | 975 | b43_phy_write(dev, B43_NPHY_TABLE_DATALO, |
864 | (code << 8 | 0x7C)); | 976 | (code << 8 | 0x7C)); |
865 | 977 | ||
866 | /* TODO: b43_nphy_adjust_lna_gain_table(dev); */ | 978 | b43_nphy_adjust_lna_gain_table(dev); |
867 | 979 | ||
868 | if (nphy->elna_gain_config) { | 980 | if (nphy->elna_gain_config) { |
869 | b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0808); | 981 | b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0808); |
@@ -1970,12 +2082,12 @@ static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev) | |||
1970 | u16 *rssical_phy_regs = NULL; | 2082 | u16 *rssical_phy_regs = NULL; |
1971 | 2083 | ||
1972 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | 2084 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { |
1973 | if (!nphy->rssical_chanspec_2G) | 2085 | if (b43_empty_chanspec(&nphy->rssical_chanspec_2G)) |
1974 | return; | 2086 | return; |
1975 | rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G; | 2087 | rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G; |
1976 | rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G; | 2088 | rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G; |
1977 | } else { | 2089 | } else { |
1978 | if (!nphy->rssical_chanspec_5G) | 2090 | if (b43_empty_chanspec(&nphy->rssical_chanspec_5G)) |
1979 | return; | 2091 | return; |
1980 | rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G; | 2092 | rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G; |
1981 | rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G; | 2093 | rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G; |
@@ -2395,7 +2507,7 @@ static void b43_nphy_save_cal(struct b43_wldev *dev) | |||
2395 | 2507 | ||
2396 | struct b43_phy_n_iq_comp *rxcal_coeffs = NULL; | 2508 | struct b43_phy_n_iq_comp *rxcal_coeffs = NULL; |
2397 | u16 *txcal_radio_regs = NULL; | 2509 | u16 *txcal_radio_regs = NULL; |
2398 | u8 *iqcal_chanspec; | 2510 | struct b43_chanspec *iqcal_chanspec; |
2399 | u16 *table = NULL; | 2511 | u16 *table = NULL; |
2400 | 2512 | ||
2401 | if (nphy->hang_avoid) | 2513 | if (nphy->hang_avoid) |
@@ -2451,12 +2563,12 @@ static void b43_nphy_restore_cal(struct b43_wldev *dev) | |||
2451 | struct b43_phy_n_iq_comp *rxcal_coeffs = NULL; | 2563 | struct b43_phy_n_iq_comp *rxcal_coeffs = NULL; |
2452 | 2564 | ||
2453 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | 2565 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { |
2454 | if (nphy->iqcal_chanspec_2G == 0) | 2566 | if (b43_empty_chanspec(&nphy->iqcal_chanspec_2G)) |
2455 | return; | 2567 | return; |
2456 | table = nphy->cal_cache.txcal_coeffs_2G; | 2568 | table = nphy->cal_cache.txcal_coeffs_2G; |
2457 | loft = &nphy->cal_cache.txcal_coeffs_2G[5]; | 2569 | loft = &nphy->cal_cache.txcal_coeffs_2G[5]; |
2458 | } else { | 2570 | } else { |
2459 | if (nphy->iqcal_chanspec_5G == 0) | 2571 | if (b43_empty_chanspec(&nphy->iqcal_chanspec_5G)) |
2460 | return; | 2572 | return; |
2461 | table = nphy->cal_cache.txcal_coeffs_5G; | 2573 | table = nphy->cal_cache.txcal_coeffs_5G; |
2462 | loft = &nphy->cal_cache.txcal_coeffs_5G[5]; | 2574 | loft = &nphy->cal_cache.txcal_coeffs_5G[5]; |
@@ -2689,7 +2801,7 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, | |||
2689 | } | 2801 | } |
2690 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4, | 2802 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4, |
2691 | buffer); | 2803 | buffer); |
2692 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 101), 2, | 2804 | b43_ntab_read_bulk(dev, B43_NTAB16(15, 101), 2, |
2693 | buffer); | 2805 | buffer); |
2694 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2, | 2806 | b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2, |
2695 | buffer); | 2807 | buffer); |
@@ -2701,8 +2813,7 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, | |||
2701 | b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length, | 2813 | b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length, |
2702 | nphy->txiqlocal_bestc); | 2814 | nphy->txiqlocal_bestc); |
2703 | nphy->txiqlocal_coeffsvalid = true; | 2815 | nphy->txiqlocal_coeffsvalid = true; |
2704 | /* TODO: Set nphy->txiqlocal_chanspec to | 2816 | nphy->txiqlocal_chanspec = nphy->radio_chanspec; |
2705 | the current channel */ | ||
2706 | } else { | 2817 | } else { |
2707 | length = 11; | 2818 | length = 11; |
2708 | if (dev->phy.rev < 3) | 2819 | if (dev->phy.rev < 3) |
@@ -2737,7 +2848,8 @@ static void b43_nphy_reapply_tx_cal_coeffs(struct b43_wldev *dev) | |||
2737 | u16 buffer[7]; | 2848 | u16 buffer[7]; |
2738 | bool equal = true; | 2849 | bool equal = true; |
2739 | 2850 | ||
2740 | if (!nphy->txiqlocal_coeffsvalid || 1 /* FIXME */) | 2851 | if (!nphy->txiqlocal_coeffsvalid || |
2852 | b43_eq_chanspecs(&nphy->txiqlocal_chanspec, &nphy->radio_chanspec)) | ||
2741 | return; | 2853 | return; |
2742 | 2854 | ||
2743 | b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer); | 2855 | b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer); |
@@ -3092,9 +3204,11 @@ int b43_phy_initn(struct b43_wldev *dev) | |||
3092 | do_rssi_cal = false; | 3204 | do_rssi_cal = false; |
3093 | if (phy->rev >= 3) { | 3205 | if (phy->rev >= 3) { |
3094 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) | 3206 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) |
3095 | do_rssi_cal = (nphy->rssical_chanspec_2G == 0); | 3207 | do_rssi_cal = |
3208 | b43_empty_chanspec(&nphy->rssical_chanspec_2G); | ||
3096 | else | 3209 | else |
3097 | do_rssi_cal = (nphy->rssical_chanspec_5G == 0); | 3210 | do_rssi_cal = |
3211 | b43_empty_chanspec(&nphy->rssical_chanspec_5G); | ||
3098 | 3212 | ||
3099 | if (do_rssi_cal) | 3213 | if (do_rssi_cal) |
3100 | b43_nphy_rssi_cal(dev); | 3214 | b43_nphy_rssi_cal(dev); |
@@ -3106,9 +3220,9 @@ int b43_phy_initn(struct b43_wldev *dev) | |||
3106 | 3220 | ||
3107 | if (!((nphy->measure_hold & 0x6) != 0)) { | 3221 | if (!((nphy->measure_hold & 0x6) != 0)) { |
3108 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) | 3222 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) |
3109 | do_cal = (nphy->iqcal_chanspec_2G == 0); | 3223 | do_cal = b43_empty_chanspec(&nphy->iqcal_chanspec_2G); |
3110 | else | 3224 | else |
3111 | do_cal = (nphy->iqcal_chanspec_5G == 0); | 3225 | do_cal = b43_empty_chanspec(&nphy->iqcal_chanspec_5G); |
3112 | 3226 | ||
3113 | if (nphy->mute) | 3227 | if (nphy->mute) |
3114 | do_cal = false; | 3228 | do_cal = false; |
@@ -3117,7 +3231,7 @@ int b43_phy_initn(struct b43_wldev *dev) | |||
3117 | target = b43_nphy_get_tx_gains(dev); | 3231 | target = b43_nphy_get_tx_gains(dev); |
3118 | 3232 | ||
3119 | if (nphy->antsel_type == 2) | 3233 | if (nphy->antsel_type == 2) |
3120 | ;/*TODO NPHY Superswitch Init with argument 1*/ | 3234 | b43_nphy_superswitch_init(dev, true); |
3121 | if (nphy->perical != 2) { | 3235 | if (nphy->perical != 2) { |
3122 | b43_nphy_rssi_cal(dev); | 3236 | b43_nphy_rssi_cal(dev); |
3123 | if (phy->rev >= 3) { | 3237 | if (phy->rev >= 3) { |
@@ -3155,6 +3269,133 @@ int b43_phy_initn(struct b43_wldev *dev) | |||
3155 | return 0; | 3269 | return 0; |
3156 | } | 3270 | } |
3157 | 3271 | ||
3272 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */ | ||
3273 | static void b43_nphy_chanspec_setup(struct b43_wldev *dev, | ||
3274 | const struct b43_phy_n_sfo_cfg *e, | ||
3275 | struct b43_chanspec chanspec) | ||
3276 | { | ||
3277 | struct b43_phy *phy = &dev->phy; | ||
3278 | struct b43_phy_n *nphy = dev->phy.n; | ||
3279 | |||
3280 | u16 tmp; | ||
3281 | u32 tmp32; | ||
3282 | |||
3283 | tmp = b43_phy_read(dev, B43_NPHY_BANDCTL) & B43_NPHY_BANDCTL_5GHZ; | ||
3284 | if (chanspec.b_freq == 1 && tmp == 0) { | ||
3285 | tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR); | ||
3286 | b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4); | ||
3287 | b43_phy_set(dev, B43_PHY_B_BBCFG, 0xC000); | ||
3288 | b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32); | ||
3289 | b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ); | ||
3290 | } else if (chanspec.b_freq == 1) { | ||
3291 | b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ); | ||
3292 | tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR); | ||
3293 | b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4); | ||
3294 | b43_phy_mask(dev, B43_PHY_B_BBCFG, (u16)~0xC000); | ||
3295 | b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32); | ||
3296 | } | ||
3297 | |||
3298 | b43_chantab_phy_upload(dev, e); | ||
3299 | |||
3300 | tmp = chanspec.channel; | ||
3301 | if (chanspec.b_freq == 1) | ||
3302 | tmp |= 0x0100; | ||
3303 | if (chanspec.b_width == 3) | ||
3304 | tmp |= 0x0200; | ||
3305 | b43_shm_write16(dev, B43_SHM_SHARED, 0xA0, tmp); | ||
3306 | |||
3307 | if (nphy->radio_chanspec.channel == 14) { | ||
3308 | b43_nphy_classifier(dev, 2, 0); | ||
3309 | b43_phy_set(dev, B43_PHY_B_TEST, 0x0800); | ||
3310 | } else { | ||
3311 | b43_nphy_classifier(dev, 2, 2); | ||
3312 | if (chanspec.b_freq == 2) | ||
3313 | b43_phy_mask(dev, B43_PHY_B_TEST, ~0x840); | ||
3314 | } | ||
3315 | |||
3316 | if (nphy->txpwrctrl) | ||
3317 | b43_nphy_tx_power_fix(dev); | ||
3318 | |||
3319 | if (dev->phy.rev < 3) | ||
3320 | b43_nphy_adjust_lna_gain_table(dev); | ||
3321 | |||
3322 | b43_nphy_tx_lp_fbw(dev); | ||
3323 | |||
3324 | if (dev->phy.rev >= 3 && 0) { | ||
3325 | /* TODO */ | ||
3326 | } | ||
3327 | |||
3328 | b43_phy_write(dev, B43_NPHY_NDATAT_DUP40, 0x3830); | ||
3329 | |||
3330 | if (phy->rev >= 3) | ||
3331 | b43_nphy_spur_workaround(dev); | ||
3332 | } | ||
3333 | |||
3334 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetChanspec */ | ||
3335 | static int b43_nphy_set_chanspec(struct b43_wldev *dev, | ||
3336 | struct b43_chanspec chanspec) | ||
3337 | { | ||
3338 | struct b43_phy_n *nphy = dev->phy.n; | ||
3339 | |||
3340 | const struct b43_nphy_channeltab_entry_rev2 *tabent_r2; | ||
3341 | const struct b43_nphy_channeltab_entry_rev3 *tabent_r3; | ||
3342 | |||
3343 | u8 tmp; | ||
3344 | u8 channel = chanspec.channel; | ||
3345 | |||
3346 | if (dev->phy.rev >= 3) { | ||
3347 | /* TODO */ | ||
3348 | tabent_r3 = NULL; | ||
3349 | if (!tabent_r3) | ||
3350 | return -ESRCH; | ||
3351 | } else { | ||
3352 | tabent_r2 = b43_nphy_get_chantabent_rev2(dev, channel); | ||
3353 | if (!tabent_r2) | ||
3354 | return -ESRCH; | ||
3355 | } | ||
3356 | |||
3357 | nphy->radio_chanspec = chanspec; | ||
3358 | |||
3359 | if (chanspec.b_width != nphy->b_width) | ||
3360 | ; /* TODO: BMAC BW Set (chanspec.b_width) */ | ||
3361 | |||
3362 | /* TODO: use defines */ | ||
3363 | if (chanspec.b_width == 3) { | ||
3364 | if (chanspec.sideband == 2) | ||
3365 | b43_phy_set(dev, B43_NPHY_RXCTL, | ||
3366 | B43_NPHY_RXCTL_BSELU20); | ||
3367 | else | ||
3368 | b43_phy_mask(dev, B43_NPHY_RXCTL, | ||
3369 | ~B43_NPHY_RXCTL_BSELU20); | ||
3370 | } | ||
3371 | |||
3372 | if (dev->phy.rev >= 3) { | ||
3373 | tmp = (chanspec.b_freq == 1) ? 4 : 0; | ||
3374 | b43_radio_maskset(dev, 0x08, 0xFFFB, tmp); | ||
3375 | /* TODO: PHY Radio2056 Setup (dev, tabent_r3); */ | ||
3376 | b43_nphy_chanspec_setup(dev, &(tabent_r3->phy_regs), chanspec); | ||
3377 | } else { | ||
3378 | tmp = (chanspec.b_freq == 1) ? 0x0020 : 0x0050; | ||
3379 | b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, tmp); | ||
3380 | b43_radio_2055_setup(dev, tabent_r2); | ||
3381 | b43_nphy_chanspec_setup(dev, &(tabent_r2->phy_regs), chanspec); | ||
3382 | } | ||
3383 | |||
3384 | return 0; | ||
3385 | } | ||
3386 | |||
3387 | /* Tune the hardware to a new channel */ | ||
3388 | static int nphy_channel_switch(struct b43_wldev *dev, unsigned int channel) | ||
3389 | { | ||
3390 | struct b43_phy_n *nphy = dev->phy.n; | ||
3391 | |||
3392 | struct b43_chanspec chanspec; | ||
3393 | chanspec = nphy->radio_chanspec; | ||
3394 | chanspec.channel = channel; | ||
3395 | |||
3396 | return b43_nphy_set_chanspec(dev, chanspec); | ||
3397 | } | ||
3398 | |||
3158 | static int b43_nphy_op_allocate(struct b43_wldev *dev) | 3399 | static int b43_nphy_op_allocate(struct b43_wldev *dev) |
3159 | { | 3400 | { |
3160 | struct b43_phy_n *nphy; | 3401 | struct b43_phy_n *nphy; |
@@ -3243,9 +3484,43 @@ static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value) | |||
3243 | b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value); | 3484 | b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value); |
3244 | } | 3485 | } |
3245 | 3486 | ||
3487 | /* http://bcm-v4.sipsolutions.net/802.11/Radio/Switch%20Radio */ | ||
3246 | static void b43_nphy_op_software_rfkill(struct b43_wldev *dev, | 3488 | static void b43_nphy_op_software_rfkill(struct b43_wldev *dev, |
3247 | bool blocked) | 3489 | bool blocked) |
3248 | {//TODO | 3490 | { |
3491 | struct b43_phy_n *nphy = dev->phy.n; | ||
3492 | |||
3493 | if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED) | ||
3494 | b43err(dev->wl, "MAC not suspended\n"); | ||
3495 | |||
3496 | if (blocked) { | ||
3497 | b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, | ||
3498 | ~B43_NPHY_RFCTL_CMD_CHIP0PU); | ||
3499 | if (dev->phy.rev >= 3) { | ||
3500 | b43_radio_mask(dev, 0x09, ~0x2); | ||
3501 | |||
3502 | b43_radio_write(dev, 0x204D, 0); | ||
3503 | b43_radio_write(dev, 0x2053, 0); | ||
3504 | b43_radio_write(dev, 0x2058, 0); | ||
3505 | b43_radio_write(dev, 0x205E, 0); | ||
3506 | b43_radio_mask(dev, 0x2062, ~0xF0); | ||
3507 | b43_radio_write(dev, 0x2064, 0); | ||
3508 | |||
3509 | b43_radio_write(dev, 0x304D, 0); | ||
3510 | b43_radio_write(dev, 0x3053, 0); | ||
3511 | b43_radio_write(dev, 0x3058, 0); | ||
3512 | b43_radio_write(dev, 0x305E, 0); | ||
3513 | b43_radio_mask(dev, 0x3062, ~0xF0); | ||
3514 | b43_radio_write(dev, 0x3064, 0); | ||
3515 | } | ||
3516 | } else { | ||
3517 | if (dev->phy.rev >= 3) { | ||
3518 | b43_radio_init2056(dev); | ||
3519 | b43_nphy_set_chanspec(dev, nphy->radio_chanspec); | ||
3520 | } else { | ||
3521 | b43_radio_init2055(dev); | ||
3522 | } | ||
3523 | } | ||
3249 | } | 3524 | } |
3250 | 3525 | ||
3251 | static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on) | 3526 | static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on) |
diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h index 403aad3f894f..8b6d570dd0aa 100644 --- a/drivers/net/wireless/b43/phy_n.h +++ b/drivers/net/wireless/b43/phy_n.h | |||
@@ -711,6 +711,8 @@ | |||
711 | #define B43_NPHY_PAPD_EN1 B43_PHY_N(0x29B) /* PAPD Enable1 TBD */ | 711 | #define B43_NPHY_PAPD_EN1 B43_PHY_N(0x29B) /* PAPD Enable1 TBD */ |
712 | #define B43_NPHY_EPS_TABLE_ADJ1 B43_PHY_N(0x29C) /* EPS Table Adj1 TBD */ | 712 | #define B43_NPHY_EPS_TABLE_ADJ1 B43_PHY_N(0x29C) /* EPS Table Adj1 TBD */ |
713 | 713 | ||
714 | #define B43_PHY_B_BBCFG B43_PHY_N_BMODE(0x001) /* BB config */ | ||
715 | #define B43_PHY_B_TEST B43_PHY_N_BMODE(0x00A) | ||
714 | 716 | ||
715 | 717 | ||
716 | /* Broadcom 2055 radio registers */ | 718 | /* Broadcom 2055 radio registers */ |
@@ -924,6 +926,13 @@ | |||
924 | 926 | ||
925 | struct b43_wldev; | 927 | struct b43_wldev; |
926 | 928 | ||
929 | struct b43_chanspec { | ||
930 | u8 channel; | ||
931 | u8 sideband; | ||
932 | u8 b_width; | ||
933 | u8 b_freq; | ||
934 | }; | ||
935 | |||
927 | struct b43_phy_n_iq_comp { | 936 | struct b43_phy_n_iq_comp { |
928 | s16 a0; | 937 | s16 a0; |
929 | s16 b0; | 938 | s16 b0; |
@@ -975,7 +984,8 @@ struct b43_phy_n { | |||
975 | u16 papd_epsilon_offset[2]; | 984 | u16 papd_epsilon_offset[2]; |
976 | s32 preamble_override; | 985 | s32 preamble_override; |
977 | u32 bb_mult_save; | 986 | u32 bb_mult_save; |
978 | u16 radio_chanspec; | 987 | u8 b_width; |
988 | struct b43_chanspec radio_chanspec; | ||
979 | 989 | ||
980 | bool gain_boost; | 990 | bool gain_boost; |
981 | bool elna_gain_config; | 991 | bool elna_gain_config; |
@@ -991,6 +1001,7 @@ struct b43_phy_n { | |||
991 | u16 txiqlocal_bestc[11]; | 1001 | u16 txiqlocal_bestc[11]; |
992 | bool txiqlocal_coeffsvalid; | 1002 | bool txiqlocal_coeffsvalid; |
993 | struct b43_phy_n_txpwrindex txpwrindex[2]; | 1003 | struct b43_phy_n_txpwrindex txpwrindex[2]; |
1004 | struct b43_chanspec txiqlocal_chanspec; | ||
994 | 1005 | ||
995 | u8 txrx_chain; | 1006 | u8 txrx_chain; |
996 | u16 tx_rx_cal_phy_saveregs[11]; | 1007 | u16 tx_rx_cal_phy_saveregs[11]; |
@@ -1006,12 +1017,12 @@ struct b43_phy_n { | |||
1006 | bool gband_spurwar_en; | 1017 | bool gband_spurwar_en; |
1007 | 1018 | ||
1008 | bool ipa2g_on; | 1019 | bool ipa2g_on; |
1009 | u8 iqcal_chanspec_2G; | 1020 | struct b43_chanspec iqcal_chanspec_2G; |
1010 | u8 rssical_chanspec_2G; | 1021 | struct b43_chanspec rssical_chanspec_2G; |
1011 | 1022 | ||
1012 | bool ipa5g_on; | 1023 | bool ipa5g_on; |
1013 | u8 iqcal_chanspec_5G; | 1024 | struct b43_chanspec iqcal_chanspec_5G; |
1014 | u8 rssical_chanspec_5G; | 1025 | struct b43_chanspec rssical_chanspec_5G; |
1015 | 1026 | ||
1016 | struct b43_phy_n_rssical_cache rssical_cache; | 1027 | struct b43_phy_n_rssical_cache rssical_cache; |
1017 | struct b43_phy_n_cal_cache cal_cache; | 1028 | struct b43_phy_n_cal_cache cal_cache; |
diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c index a00d509150f7..d96e870ab8fe 100644 --- a/drivers/net/wireless/b43/tables_nphy.c +++ b/drivers/net/wireless/b43/tables_nphy.c | |||
@@ -318,14 +318,14 @@ void b2055_upload_inittab(struct b43_wldev *dev, | |||
318 | .radio_c2_tx_mxbgtrim = r21 | 318 | .radio_c2_tx_mxbgtrim = r21 |
319 | 319 | ||
320 | #define PHYREGS(r0, r1, r2, r3, r4, r5) \ | 320 | #define PHYREGS(r0, r1, r2, r3, r4, r5) \ |
321 | .phy_bw1a = r0, \ | 321 | .phy_regs.phy_bw1a = r0, \ |
322 | .phy_bw2 = r1, \ | 322 | .phy_regs.phy_bw2 = r1, \ |
323 | .phy_bw3 = r2, \ | 323 | .phy_regs.phy_bw3 = r2, \ |
324 | .phy_bw4 = r3, \ | 324 | .phy_regs.phy_bw4 = r3, \ |
325 | .phy_bw5 = r4, \ | 325 | .phy_regs.phy_bw5 = r4, \ |
326 | .phy_bw6 = r5 | 326 | .phy_regs.phy_bw6 = r5 |
327 | 327 | ||
328 | static const struct b43_nphy_channeltab_entry b43_nphy_channeltab[] = { | 328 | static const struct b43_nphy_channeltab_entry_rev2 b43_nphy_channeltab[] = { |
329 | { .channel = 184, | 329 | { .channel = 184, |
330 | .freq = 4920, /* MHz */ | 330 | .freq = 4920, /* MHz */ |
331 | .unk2 = 3280, | 331 | .unk2 = 3280, |
@@ -1320,10 +1320,10 @@ static const struct b43_nphy_channeltab_entry b43_nphy_channeltab[] = { | |||
1320 | }, | 1320 | }, |
1321 | }; | 1321 | }; |
1322 | 1322 | ||
1323 | const struct b43_nphy_channeltab_entry * | 1323 | const struct b43_nphy_channeltab_entry_rev2 * |
1324 | b43_nphy_get_chantabent(struct b43_wldev *dev, u8 channel) | 1324 | b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel) |
1325 | { | 1325 | { |
1326 | const struct b43_nphy_channeltab_entry *e; | 1326 | const struct b43_nphy_channeltab_entry_rev2 *e; |
1327 | unsigned int i; | 1327 | unsigned int i; |
1328 | 1328 | ||
1329 | for (i = 0; i < ARRAY_SIZE(b43_nphy_channeltab); i++) { | 1329 | for (i = 0; i < ARRAY_SIZE(b43_nphy_channeltab); i++) { |
diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h index 9c1c6ecd3672..8fc1da9f8fe5 100644 --- a/drivers/net/wireless/b43/tables_nphy.h +++ b/drivers/net/wireless/b43/tables_nphy.h | |||
@@ -4,9 +4,22 @@ | |||
4 | #include <linux/types.h> | 4 | #include <linux/types.h> |
5 | 5 | ||
6 | 6 | ||
7 | struct b43_nphy_channeltab_entry { | 7 | struct b43_phy_n_sfo_cfg { |
8 | u16 phy_bw1a; | ||
9 | u16 phy_bw2; | ||
10 | u16 phy_bw3; | ||
11 | u16 phy_bw4; | ||
12 | u16 phy_bw5; | ||
13 | u16 phy_bw6; | ||
14 | }; | ||
15 | |||
16 | struct b43_nphy_channeltab_entry_rev2 { | ||
8 | /* The channel number */ | 17 | /* The channel number */ |
9 | u8 channel; | 18 | u8 channel; |
19 | /* The channel frequency in MHz */ | ||
20 | u16 freq; | ||
21 | /* An unknown value */ | ||
22 | u16 unk2; | ||
10 | /* Radio register values on channelswitch */ | 23 | /* Radio register values on channelswitch */ |
11 | u8 radio_pll_ref; | 24 | u8 radio_pll_ref; |
12 | u8 radio_rf_pllmod0; | 25 | u8 radio_rf_pllmod0; |
@@ -31,16 +44,18 @@ struct b43_nphy_channeltab_entry { | |||
31 | u8 radio_c2_tx_pgapadtn; | 44 | u8 radio_c2_tx_pgapadtn; |
32 | u8 radio_c2_tx_mxbgtrim; | 45 | u8 radio_c2_tx_mxbgtrim; |
33 | /* PHY register values on channelswitch */ | 46 | /* PHY register values on channelswitch */ |
34 | u16 phy_bw1a; | 47 | struct b43_phy_n_sfo_cfg phy_regs; |
35 | u16 phy_bw2; | 48 | }; |
36 | u16 phy_bw3; | 49 | |
37 | u16 phy_bw4; | 50 | struct b43_nphy_channeltab_entry_rev3 { |
38 | u16 phy_bw5; | 51 | /* The channel number */ |
39 | u16 phy_bw6; | 52 | u8 channel; |
40 | /* The channel frequency in MHz */ | 53 | /* The channel frequency in MHz */ |
41 | u16 freq; | 54 | u16 freq; |
42 | /* An unknown value */ | 55 | /* Radio register values on channelswitch */ |
43 | u16 unk2; | 56 | /* TODO */ |
57 | /* PHY register values on channelswitch */ | ||
58 | struct b43_phy_n_sfo_cfg phy_regs; | ||
44 | }; | 59 | }; |
45 | 60 | ||
46 | 61 | ||
@@ -77,8 +92,8 @@ void b2055_upload_inittab(struct b43_wldev *dev, | |||
77 | 92 | ||
78 | /* Get the NPHY Channel Switch Table entry for a channel number. | 93 | /* Get the NPHY Channel Switch Table entry for a channel number. |
79 | * Returns NULL on failure to find an entry. */ | 94 | * Returns NULL on failure to find an entry. */ |
80 | const struct b43_nphy_channeltab_entry * | 95 | const struct b43_nphy_channeltab_entry_rev2 * |
81 | b43_nphy_get_chantabent(struct b43_wldev *dev, u8 channel); | 96 | b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel); |
82 | 97 | ||
83 | 98 | ||
84 | /* The N-PHY tables. */ | 99 | /* The N-PHY tables. */ |
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index eda06529ef5f..e6b0528f3b52 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c | |||
@@ -610,7 +610,6 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) | |||
610 | } | 610 | } |
611 | 611 | ||
612 | /* Link quality statistics */ | 612 | /* Link quality statistics */ |
613 | status.noise = dev->stats.link_noise; | ||
614 | if ((chanstat & B43_RX_CHAN_PHYTYPE) == B43_PHYTYPE_N) { | 613 | if ((chanstat & B43_RX_CHAN_PHYTYPE) == B43_PHYTYPE_N) { |
615 | // s8 rssi = max(rxhdr->power0, rxhdr->power1); | 614 | // s8 rssi = max(rxhdr->power0, rxhdr->power1); |
616 | //TODO: Find out what the rssi value is (dBm or percentage?) | 615 | //TODO: Find out what the rssi value is (dBm or percentage?) |