diff options
Diffstat (limited to 'drivers/net/wireless/b43/phy_lp.c')
-rw-r--r-- | drivers/net/wireless/b43/phy_lp.c | 768 |
1 files changed, 755 insertions, 13 deletions
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index aa1486a1354b..cfb8337d3859 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c | |||
@@ -59,9 +59,126 @@ static void b43_lpphy_op_free(struct b43_wldev *dev) | |||
59 | dev->phy.lp = NULL; | 59 | dev->phy.lp = NULL; |
60 | } | 60 | } |
61 | 61 | ||
62 | static void lpphy_read_band_sprom(struct b43_wldev *dev) | ||
63 | { | ||
64 | struct b43_phy_lp *lpphy = dev->phy.lp; | ||
65 | struct ssb_bus *bus = dev->dev->bus; | ||
66 | u16 cckpo, maxpwr; | ||
67 | u32 ofdmpo; | ||
68 | int i; | ||
69 | |||
70 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | ||
71 | lpphy->tx_isolation_med_band = bus->sprom.tri2g; | ||
72 | lpphy->bx_arch = bus->sprom.bxa2g; | ||
73 | lpphy->rx_pwr_offset = bus->sprom.rxpo2g; | ||
74 | lpphy->rssi_vf = bus->sprom.rssismf2g; | ||
75 | lpphy->rssi_vc = bus->sprom.rssismc2g; | ||
76 | lpphy->rssi_gs = bus->sprom.rssisav2g; | ||
77 | lpphy->txpa[0] = bus->sprom.pa0b0; | ||
78 | lpphy->txpa[1] = bus->sprom.pa0b1; | ||
79 | lpphy->txpa[2] = bus->sprom.pa0b2; | ||
80 | maxpwr = bus->sprom.maxpwr_bg; | ||
81 | lpphy->max_tx_pwr_med_band = maxpwr; | ||
82 | cckpo = bus->sprom.cck2gpo; | ||
83 | ofdmpo = bus->sprom.ofdm2gpo; | ||
84 | if (cckpo) { | ||
85 | for (i = 0; i < 4; i++) { | ||
86 | lpphy->tx_max_rate[i] = | ||
87 | maxpwr - (ofdmpo & 0xF) * 2; | ||
88 | ofdmpo >>= 4; | ||
89 | } | ||
90 | ofdmpo = bus->sprom.ofdm2gpo; | ||
91 | for (i = 4; i < 15; i++) { | ||
92 | lpphy->tx_max_rate[i] = | ||
93 | maxpwr - (ofdmpo & 0xF) * 2; | ||
94 | ofdmpo >>= 4; | ||
95 | } | ||
96 | } else { | ||
97 | ofdmpo &= 0xFF; | ||
98 | for (i = 0; i < 4; i++) | ||
99 | lpphy->tx_max_rate[i] = maxpwr; | ||
100 | for (i = 4; i < 15; i++) | ||
101 | lpphy->tx_max_rate[i] = maxpwr - ofdmpo; | ||
102 | } | ||
103 | } else { /* 5GHz */ | ||
104 | lpphy->tx_isolation_low_band = bus->sprom.tri5gl; | ||
105 | lpphy->tx_isolation_med_band = bus->sprom.tri5g; | ||
106 | lpphy->tx_isolation_hi_band = bus->sprom.tri5gh; | ||
107 | lpphy->bx_arch = bus->sprom.bxa5g; | ||
108 | lpphy->rx_pwr_offset = bus->sprom.rxpo5g; | ||
109 | lpphy->rssi_vf = bus->sprom.rssismf5g; | ||
110 | lpphy->rssi_vc = bus->sprom.rssismc5g; | ||
111 | lpphy->rssi_gs = bus->sprom.rssisav5g; | ||
112 | lpphy->txpa[0] = bus->sprom.pa1b0; | ||
113 | lpphy->txpa[1] = bus->sprom.pa1b1; | ||
114 | lpphy->txpa[2] = bus->sprom.pa1b2; | ||
115 | lpphy->txpal[0] = bus->sprom.pa1lob0; | ||
116 | lpphy->txpal[1] = bus->sprom.pa1lob1; | ||
117 | lpphy->txpal[2] = bus->sprom.pa1lob2; | ||
118 | lpphy->txpah[0] = bus->sprom.pa1hib0; | ||
119 | lpphy->txpah[1] = bus->sprom.pa1hib1; | ||
120 | lpphy->txpah[2] = bus->sprom.pa1hib2; | ||
121 | maxpwr = bus->sprom.maxpwr_al; | ||
122 | ofdmpo = bus->sprom.ofdm5glpo; | ||
123 | lpphy->max_tx_pwr_low_band = maxpwr; | ||
124 | for (i = 4; i < 12; i++) { | ||
125 | lpphy->tx_max_ratel[i] = maxpwr - (ofdmpo & 0xF) * 2; | ||
126 | ofdmpo >>= 4; | ||
127 | } | ||
128 | maxpwr = bus->sprom.maxpwr_a; | ||
129 | ofdmpo = bus->sprom.ofdm5gpo; | ||
130 | lpphy->max_tx_pwr_med_band = maxpwr; | ||
131 | for (i = 4; i < 12; i++) { | ||
132 | lpphy->tx_max_rate[i] = maxpwr - (ofdmpo & 0xF) * 2; | ||
133 | ofdmpo >>= 4; | ||
134 | } | ||
135 | maxpwr = bus->sprom.maxpwr_ah; | ||
136 | ofdmpo = bus->sprom.ofdm5ghpo; | ||
137 | lpphy->max_tx_pwr_hi_band = maxpwr; | ||
138 | for (i = 4; i < 12; i++) { | ||
139 | lpphy->tx_max_rateh[i] = maxpwr - (ofdmpo & 0xF) * 2; | ||
140 | ofdmpo >>= 4; | ||
141 | } | ||
142 | } | ||
143 | } | ||
144 | |||
145 | static void lpphy_adjust_gain_table(struct b43_wldev *dev) | ||
146 | { | ||
147 | struct b43_phy_lp *lpphy = dev->phy.lp; | ||
148 | u32 freq = dev->wl->hw->conf.channel->center_freq; | ||
149 | u16 temp[3]; | ||
150 | u16 isolation; | ||
151 | |||
152 | B43_WARN_ON(dev->phy.rev >= 2); | ||
153 | |||
154 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) | ||
155 | isolation = lpphy->tx_isolation_med_band; | ||
156 | else if (freq <= 5320) | ||
157 | isolation = lpphy->tx_isolation_low_band; | ||
158 | else if (freq <= 5700) | ||
159 | isolation = lpphy->tx_isolation_med_band; | ||
160 | else | ||
161 | isolation = lpphy->tx_isolation_hi_band; | ||
162 | |||
163 | temp[0] = ((isolation - 26) / 12) << 12; | ||
164 | temp[1] = temp[0] + 0x1000; | ||
165 | temp[2] = temp[0] + 0x2000; | ||
166 | |||
167 | b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0), 3, temp); | ||
168 | b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0), 3, temp); | ||
169 | } | ||
170 | |||
62 | static void lpphy_table_init(struct b43_wldev *dev) | 171 | static void lpphy_table_init(struct b43_wldev *dev) |
63 | { | 172 | { |
64 | //TODO | 173 | if (dev->phy.rev < 2) |
174 | lpphy_rev0_1_table_init(dev); | ||
175 | else | ||
176 | lpphy_rev2plus_table_init(dev); | ||
177 | |||
178 | lpphy_init_tx_gain_table(dev); | ||
179 | |||
180 | if (dev->phy.rev < 2) | ||
181 | lpphy_adjust_gain_table(dev); | ||
65 | } | 182 | } |
66 | 183 | ||
67 | static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev) | 184 | static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev) |
@@ -130,7 +247,7 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev) | |||
130 | b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x0006); | 247 | b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x0006); |
131 | b43_phy_write(dev, B43_LPPHY_GPIO_SELECT, 0x0005); | 248 | b43_phy_write(dev, B43_LPPHY_GPIO_SELECT, 0x0005); |
132 | b43_phy_write(dev, B43_LPPHY_GPIO_OUTEN, 0xFFFF); | 249 | b43_phy_write(dev, B43_LPPHY_GPIO_OUTEN, 0xFFFF); |
133 | b43_hf_write(dev, b43_hf_read(dev) | 0x0800ULL << 32); | 250 | b43_hf_write(dev, b43_hf_read(dev) | B43_HF_PR45960W); |
134 | } | 251 | } |
135 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | 252 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { |
136 | b43_phy_set(dev, B43_LPPHY_LP_PHY_CTL, 0x8000); | 253 | b43_phy_set(dev, B43_LPPHY_LP_PHY_CTL, 0x8000); |
@@ -161,6 +278,56 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev) | |||
161 | } | 278 | } |
162 | } | 279 | } |
163 | 280 | ||
281 | static void lpphy_save_dig_flt_state(struct b43_wldev *dev) | ||
282 | { | ||
283 | static const u16 addr[] = { | ||
284 | B43_PHY_OFDM(0xC1), | ||
285 | B43_PHY_OFDM(0xC2), | ||
286 | B43_PHY_OFDM(0xC3), | ||
287 | B43_PHY_OFDM(0xC4), | ||
288 | B43_PHY_OFDM(0xC5), | ||
289 | B43_PHY_OFDM(0xC6), | ||
290 | B43_PHY_OFDM(0xC7), | ||
291 | B43_PHY_OFDM(0xC8), | ||
292 | B43_PHY_OFDM(0xCF), | ||
293 | }; | ||
294 | |||
295 | static const u16 coefs[] = { | ||
296 | 0xDE5E, 0xE832, 0xE331, 0x4D26, | ||
297 | 0x0026, 0x1420, 0x0020, 0xFE08, | ||
298 | 0x0008, | ||
299 | }; | ||
300 | |||
301 | struct b43_phy_lp *lpphy = dev->phy.lp; | ||
302 | int i; | ||
303 | |||
304 | for (i = 0; i < ARRAY_SIZE(addr); i++) { | ||
305 | lpphy->dig_flt_state[i] = b43_phy_read(dev, addr[i]); | ||
306 | b43_phy_write(dev, addr[i], coefs[i]); | ||
307 | } | ||
308 | } | ||
309 | |||
310 | static void lpphy_restore_dig_flt_state(struct b43_wldev *dev) | ||
311 | { | ||
312 | static const u16 addr[] = { | ||
313 | B43_PHY_OFDM(0xC1), | ||
314 | B43_PHY_OFDM(0xC2), | ||
315 | B43_PHY_OFDM(0xC3), | ||
316 | B43_PHY_OFDM(0xC4), | ||
317 | B43_PHY_OFDM(0xC5), | ||
318 | B43_PHY_OFDM(0xC6), | ||
319 | B43_PHY_OFDM(0xC7), | ||
320 | B43_PHY_OFDM(0xC8), | ||
321 | B43_PHY_OFDM(0xCF), | ||
322 | }; | ||
323 | |||
324 | struct b43_phy_lp *lpphy = dev->phy.lp; | ||
325 | int i; | ||
326 | |||
327 | for (i = 0; i < ARRAY_SIZE(addr); i++) | ||
328 | b43_phy_write(dev, addr[i], lpphy->dig_flt_state[i]); | ||
329 | } | ||
330 | |||
164 | static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev) | 331 | static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev) |
165 | { | 332 | { |
166 | struct ssb_bus *bus = dev->dev->bus; | 333 | struct ssb_bus *bus = dev->dev->bus; |
@@ -175,7 +342,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev) | |||
175 | b43_phy_write(dev, B43_PHY_OFDM(0xF9), 0); | 342 | b43_phy_write(dev, B43_PHY_OFDM(0xF9), 0); |
176 | b43_phy_write(dev, B43_LPPHY_TR_LOOKUP_1, 0); | 343 | b43_phy_write(dev, B43_LPPHY_TR_LOOKUP_1, 0); |
177 | b43_phy_set(dev, B43_LPPHY_ADC_COMPENSATION_CTL, 0x10); | 344 | b43_phy_set(dev, B43_LPPHY_ADC_COMPENSATION_CTL, 0x10); |
178 | b43_phy_maskset(dev, B43_LPPHY_OFDMSYNCTHRESH0, 0xFF00, 0x78); | 345 | b43_phy_maskset(dev, B43_LPPHY_OFDMSYNCTHRESH0, 0xFF00, 0xB4); |
179 | b43_phy_maskset(dev, B43_LPPHY_DCOFFSETTRANSIENT, 0xF8FF, 0x200); | 346 | b43_phy_maskset(dev, B43_LPPHY_DCOFFSETTRANSIENT, 0xF8FF, 0x200); |
180 | b43_phy_maskset(dev, B43_LPPHY_DCOFFSETTRANSIENT, 0xFF00, 0x7F); | 347 | b43_phy_maskset(dev, B43_LPPHY_DCOFFSETTRANSIENT, 0xFF00, 0x7F); |
181 | b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xFF0F, 0x40); | 348 | b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xFF0F, 0x40); |
@@ -183,7 +350,12 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev) | |||
183 | b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x4000); | 350 | b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x4000); |
184 | b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x2000); | 351 | b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x2000); |
185 | b43_phy_set(dev, B43_PHY_OFDM(0x10A), 0x1); | 352 | b43_phy_set(dev, B43_PHY_OFDM(0x10A), 0x1); |
186 | b43_phy_maskset(dev, B43_PHY_OFDM(0x10A), 0xFF01, 0x10); | 353 | if (bus->boardinfo.rev >= 0x18) { |
354 | b43_lptab_write(dev, B43_LPTAB32(17, 65), 0xEC); | ||
355 | b43_phy_maskset(dev, B43_PHY_OFDM(0x10A), 0xFF01, 0x14); | ||
356 | } else { | ||
357 | b43_phy_maskset(dev, B43_PHY_OFDM(0x10A), 0xFF01, 0x10); | ||
358 | } | ||
187 | b43_phy_maskset(dev, B43_PHY_OFDM(0xDF), 0xFF00, 0xF4); | 359 | b43_phy_maskset(dev, B43_PHY_OFDM(0xDF), 0xFF00, 0xF4); |
188 | b43_phy_maskset(dev, B43_PHY_OFDM(0xDF), 0x00FF, 0xF100); | 360 | b43_phy_maskset(dev, B43_PHY_OFDM(0xDF), 0x00FF, 0xF100); |
189 | b43_phy_write(dev, B43_LPPHY_CLIPTHRESH, 0x48); | 361 | b43_phy_write(dev, B43_LPPHY_CLIPTHRESH, 0x48); |
@@ -213,8 +385,10 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev) | |||
213 | b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFFE0, 0x12); | 385 | b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFFE0, 0x12); |
214 | b43_phy_maskset(dev, B43_LPPHY_GAINMISMATCH, 0x0FFF, 0x9000); | 386 | b43_phy_maskset(dev, B43_LPPHY_GAINMISMATCH, 0x0FFF, 0x9000); |
215 | 387 | ||
216 | b43_lptab_write(dev, B43_LPTAB16(0x08, 0x14), 0); | 388 | if ((bus->chip_id == 0x4325) && (bus->chip_rev == 1)) { |
217 | b43_lptab_write(dev, B43_LPTAB16(0x08, 0x12), 0x40); | 389 | b43_lptab_write(dev, B43_LPTAB16(0x08, 0x14), 0); |
390 | b43_lptab_write(dev, B43_LPTAB16(0x08, 0x12), 0x40); | ||
391 | } | ||
218 | 392 | ||
219 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | 393 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { |
220 | b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x40); | 394 | b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x40); |
@@ -234,6 +408,14 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev) | |||
234 | b43_phy_write(dev, B43_LPPHY_AFE_RSSI_CTL_1, | 408 | b43_phy_write(dev, B43_LPPHY_AFE_RSSI_CTL_1, |
235 | 0x2000 | ((u16)lpphy->rssi_gs << 10) | | 409 | 0x2000 | ((u16)lpphy->rssi_gs << 10) | |
236 | ((u16)lpphy->rssi_vc << 4) | lpphy->rssi_vf); | 410 | ((u16)lpphy->rssi_vc << 4) | lpphy->rssi_vf); |
411 | |||
412 | if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) { | ||
413 | b43_phy_set(dev, B43_LPPHY_AFE_ADC_CTL_0, 0x1C); | ||
414 | b43_phy_maskset(dev, B43_LPPHY_AFE_CTL, 0x00FF, 0x8800); | ||
415 | b43_phy_maskset(dev, B43_LPPHY_AFE_ADC_CTL_1, 0xFC3C, 0x0400); | ||
416 | } | ||
417 | |||
418 | lpphy_save_dig_flt_state(dev); | ||
237 | } | 419 | } |
238 | 420 | ||
239 | static void lpphy_baseband_init(struct b43_wldev *dev) | 421 | static void lpphy_baseband_init(struct b43_wldev *dev) |
@@ -333,12 +515,73 @@ static void lpphy_2062_init(struct b43_wldev *dev) | |||
333 | /* Initialize the 2063 radio. */ | 515 | /* Initialize the 2063 radio. */ |
334 | static void lpphy_2063_init(struct b43_wldev *dev) | 516 | static void lpphy_2063_init(struct b43_wldev *dev) |
335 | { | 517 | { |
336 | //TODO | 518 | b2063_upload_init_table(dev); |
519 | b43_radio_write(dev, B2063_LOGEN_SP5, 0); | ||
520 | b43_radio_set(dev, B2063_COMM8, 0x38); | ||
521 | b43_radio_write(dev, B2063_REG_SP1, 0x56); | ||
522 | b43_radio_mask(dev, B2063_RX_BB_CTL2, ~0x2); | ||
523 | b43_radio_write(dev, B2063_PA_SP7, 0); | ||
524 | b43_radio_write(dev, B2063_TX_RF_SP6, 0x20); | ||
525 | b43_radio_write(dev, B2063_TX_RF_SP9, 0x40); | ||
526 | b43_radio_write(dev, B2063_PA_SP3, 0xa0); | ||
527 | b43_radio_write(dev, B2063_PA_SP4, 0xa0); | ||
528 | b43_radio_write(dev, B2063_PA_SP2, 0x18); | ||
337 | } | 529 | } |
338 | 530 | ||
531 | struct lpphy_stx_table_entry { | ||
532 | u16 phy_offset; | ||
533 | u16 phy_shift; | ||
534 | u16 rf_addr; | ||
535 | u16 rf_shift; | ||
536 | u16 mask; | ||
537 | }; | ||
538 | |||
539 | static const struct lpphy_stx_table_entry lpphy_stx_table[] = { | ||
540 | { .phy_offset = 2, .phy_shift = 6, .rf_addr = 0x3d, .rf_shift = 3, .mask = 0x01, }, | ||
541 | { .phy_offset = 1, .phy_shift = 12, .rf_addr = 0x4c, .rf_shift = 1, .mask = 0x01, }, | ||
542 | { .phy_offset = 1, .phy_shift = 8, .rf_addr = 0x50, .rf_shift = 0, .mask = 0x7f, }, | ||
543 | { .phy_offset = 0, .phy_shift = 8, .rf_addr = 0x44, .rf_shift = 0, .mask = 0xff, }, | ||
544 | { .phy_offset = 1, .phy_shift = 0, .rf_addr = 0x4a, .rf_shift = 0, .mask = 0xff, }, | ||
545 | { .phy_offset = 0, .phy_shift = 4, .rf_addr = 0x4d, .rf_shift = 0, .mask = 0xff, }, | ||
546 | { .phy_offset = 1, .phy_shift = 4, .rf_addr = 0x4e, .rf_shift = 0, .mask = 0xff, }, | ||
547 | { .phy_offset = 0, .phy_shift = 12, .rf_addr = 0x4f, .rf_shift = 0, .mask = 0x0f, }, | ||
548 | { .phy_offset = 1, .phy_shift = 0, .rf_addr = 0x4f, .rf_shift = 4, .mask = 0x0f, }, | ||
549 | { .phy_offset = 3, .phy_shift = 0, .rf_addr = 0x49, .rf_shift = 0, .mask = 0x0f, }, | ||
550 | { .phy_offset = 4, .phy_shift = 3, .rf_addr = 0x46, .rf_shift = 4, .mask = 0x07, }, | ||
551 | { .phy_offset = 3, .phy_shift = 15, .rf_addr = 0x46, .rf_shift = 0, .mask = 0x01, }, | ||
552 | { .phy_offset = 4, .phy_shift = 0, .rf_addr = 0x46, .rf_shift = 1, .mask = 0x07, }, | ||
553 | { .phy_offset = 3, .phy_shift = 8, .rf_addr = 0x48, .rf_shift = 4, .mask = 0x07, }, | ||
554 | { .phy_offset = 3, .phy_shift = 11, .rf_addr = 0x48, .rf_shift = 0, .mask = 0x0f, }, | ||
555 | { .phy_offset = 3, .phy_shift = 4, .rf_addr = 0x49, .rf_shift = 4, .mask = 0x0f, }, | ||
556 | { .phy_offset = 2, .phy_shift = 15, .rf_addr = 0x45, .rf_shift = 0, .mask = 0x01, }, | ||
557 | { .phy_offset = 5, .phy_shift = 13, .rf_addr = 0x52, .rf_shift = 4, .mask = 0x07, }, | ||
558 | { .phy_offset = 6, .phy_shift = 0, .rf_addr = 0x52, .rf_shift = 7, .mask = 0x01, }, | ||
559 | { .phy_offset = 5, .phy_shift = 3, .rf_addr = 0x41, .rf_shift = 5, .mask = 0x07, }, | ||
560 | { .phy_offset = 5, .phy_shift = 6, .rf_addr = 0x41, .rf_shift = 0, .mask = 0x0f, }, | ||
561 | { .phy_offset = 5, .phy_shift = 10, .rf_addr = 0x42, .rf_shift = 5, .mask = 0x07, }, | ||
562 | { .phy_offset = 4, .phy_shift = 15, .rf_addr = 0x42, .rf_shift = 0, .mask = 0x01, }, | ||
563 | { .phy_offset = 5, .phy_shift = 0, .rf_addr = 0x42, .rf_shift = 1, .mask = 0x07, }, | ||
564 | { .phy_offset = 4, .phy_shift = 11, .rf_addr = 0x43, .rf_shift = 4, .mask = 0x0f, }, | ||
565 | { .phy_offset = 4, .phy_shift = 7, .rf_addr = 0x43, .rf_shift = 0, .mask = 0x0f, }, | ||
566 | { .phy_offset = 4, .phy_shift = 6, .rf_addr = 0x45, .rf_shift = 1, .mask = 0x01, }, | ||
567 | { .phy_offset = 2, .phy_shift = 7, .rf_addr = 0x40, .rf_shift = 4, .mask = 0x0f, }, | ||
568 | { .phy_offset = 2, .phy_shift = 11, .rf_addr = 0x40, .rf_shift = 0, .mask = 0x0f, }, | ||
569 | }; | ||
570 | |||
339 | static void lpphy_sync_stx(struct b43_wldev *dev) | 571 | static void lpphy_sync_stx(struct b43_wldev *dev) |
340 | { | 572 | { |
341 | //TODO | 573 | const struct lpphy_stx_table_entry *e; |
574 | unsigned int i; | ||
575 | u16 tmp; | ||
576 | |||
577 | for (i = 0; i < ARRAY_SIZE(lpphy_stx_table); i++) { | ||
578 | e = &lpphy_stx_table[i]; | ||
579 | tmp = b43_radio_read(dev, e->rf_addr); | ||
580 | tmp >>= e->rf_shift; | ||
581 | tmp <<= e->phy_shift; | ||
582 | b43_phy_maskset(dev, B43_PHY_OFDM(0xF2 + e->phy_offset), | ||
583 | ~(e->mask << e->phy_shift), tmp); | ||
584 | } | ||
342 | } | 585 | } |
343 | 586 | ||
344 | static void lpphy_radio_init(struct b43_wldev *dev) | 587 | static void lpphy_radio_init(struct b43_wldev *dev) |
@@ -356,8 +599,343 @@ static void lpphy_radio_init(struct b43_wldev *dev) | |||
356 | lpphy_sync_stx(dev); | 599 | lpphy_sync_stx(dev); |
357 | b43_phy_write(dev, B43_PHY_OFDM(0xF0), 0x5F80); | 600 | b43_phy_write(dev, B43_PHY_OFDM(0xF0), 0x5F80); |
358 | b43_phy_write(dev, B43_PHY_OFDM(0xF1), 0); | 601 | b43_phy_write(dev, B43_PHY_OFDM(0xF1), 0); |
359 | //TODO Do something on the backplane | 602 | if (dev->dev->bus->chip_id == 0x4325) { |
603 | // TODO SSB PMU recalibration | ||
604 | } | ||
605 | } | ||
606 | } | ||
607 | |||
608 | struct lpphy_iq_est { u32 iq_prod, i_pwr, q_pwr; }; | ||
609 | |||
610 | static void lpphy_set_rc_cap(struct b43_wldev *dev) | ||
611 | { | ||
612 | u8 rc_cap = dev->phy.lp->rc_cap; | ||
613 | |||
614 | b43_radio_write(dev, B2062_N_RXBB_CALIB2, max_t(u8, rc_cap-4, 0x80)); | ||
615 | b43_radio_write(dev, B2062_N_TX_CTL_A, ((rc_cap & 0x1F) >> 1) | 0x80); | ||
616 | b43_radio_write(dev, B2062_S_RXG_CNT16, ((rc_cap & 0x1F) >> 2) | 0x80); | ||
617 | } | ||
618 | |||
619 | static u8 lpphy_get_bb_mult(struct b43_wldev *dev) | ||
620 | { | ||
621 | return (b43_lptab_read(dev, B43_LPTAB16(0, 87)) & 0xFF00) >> 8; | ||
622 | } | ||
623 | |||
624 | static void lpphy_set_bb_mult(struct b43_wldev *dev, u8 bb_mult) | ||
625 | { | ||
626 | b43_lptab_write(dev, B43_LPTAB16(0, 87), (u16)bb_mult << 8); | ||
627 | } | ||
628 | |||
629 | static void lpphy_disable_crs(struct b43_wldev *dev) | ||
630 | { | ||
631 | b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x80); | ||
632 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, 0x1); | ||
633 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3); | ||
634 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFB); | ||
635 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x4); | ||
636 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFF7); | ||
637 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8); | ||
638 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x10); | ||
639 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10); | ||
640 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFDF); | ||
641 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x20); | ||
642 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFBF); | ||
643 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40); | ||
644 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x7); | ||
645 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x38); | ||
646 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFF3F); | ||
647 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x100); | ||
648 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFDFF); | ||
649 | b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL0, 0); | ||
650 | b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL1, 1); | ||
651 | b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL2, 0x20); | ||
652 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFBFF); | ||
653 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xF7FF); | ||
654 | b43_phy_write(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL, 0); | ||
655 | b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45AF); | ||
656 | b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, 0x3FF); | ||
657 | } | ||
658 | |||
659 | static void lpphy_restore_crs(struct b43_wldev *dev) | ||
660 | { | ||
661 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) | ||
662 | b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x60); | ||
663 | else | ||
664 | b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x20); | ||
665 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFF80); | ||
666 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFC00); | ||
667 | } | ||
668 | |||
669 | struct lpphy_tx_gains { u16 gm, pga, pad, dac; }; | ||
670 | |||
671 | static struct lpphy_tx_gains lpphy_get_tx_gains(struct b43_wldev *dev) | ||
672 | { | ||
673 | struct lpphy_tx_gains gains; | ||
674 | u16 tmp; | ||
675 | |||
676 | gains.dac = (b43_phy_read(dev, B43_LPPHY_AFE_DAC_CTL) & 0x380) >> 7; | ||
677 | if (dev->phy.rev < 2) { | ||
678 | tmp = b43_phy_read(dev, | ||
679 | B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7FF; | ||
680 | gains.gm = tmp & 0x0007; | ||
681 | gains.pga = (tmp & 0x0078) >> 3; | ||
682 | gains.pad = (tmp & 0x780) >> 7; | ||
683 | } else { | ||
684 | tmp = b43_phy_read(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL); | ||
685 | gains.pad = b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0xFF; | ||
686 | gains.gm = tmp & 0xFF; | ||
687 | gains.pga = (tmp >> 8) & 0xFF; | ||
688 | } | ||
689 | |||
690 | return gains; | ||
691 | } | ||
692 | |||
693 | static void lpphy_set_dac_gain(struct b43_wldev *dev, u16 dac) | ||
694 | { | ||
695 | u16 ctl = b43_phy_read(dev, B43_LPPHY_AFE_DAC_CTL) & 0xC7F; | ||
696 | ctl |= dac << 7; | ||
697 | b43_phy_maskset(dev, B43_LPPHY_AFE_DAC_CTL, 0xF000, ctl); | ||
698 | } | ||
699 | |||
700 | static void lpphy_set_tx_gains(struct b43_wldev *dev, | ||
701 | struct lpphy_tx_gains gains) | ||
702 | { | ||
703 | u16 rf_gain, pa_gain; | ||
704 | |||
705 | if (dev->phy.rev < 2) { | ||
706 | rf_gain = (gains.pad << 7) | (gains.pga << 3) | gains.gm; | ||
707 | b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL, | ||
708 | 0xF800, rf_gain); | ||
709 | } else { | ||
710 | pa_gain = b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0x7F00; | ||
711 | b43_phy_write(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL, | ||
712 | (gains.pga << 8) | gains.gm); | ||
713 | b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL, | ||
714 | 0x8000, gains.pad | pa_gain); | ||
715 | b43_phy_write(dev, B43_PHY_OFDM(0xFC), | ||
716 | (gains.pga << 8) | gains.gm); | ||
717 | b43_phy_maskset(dev, B43_PHY_OFDM(0xFD), | ||
718 | 0x8000, gains.pad | pa_gain); | ||
719 | } | ||
720 | lpphy_set_dac_gain(dev, gains.dac); | ||
721 | if (dev->phy.rev < 2) { | ||
722 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF, 1 << 8); | ||
723 | } else { | ||
724 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFF7F, 1 << 7); | ||
725 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xBFFF, 1 << 14); | ||
726 | } | ||
727 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFFBF, 1 << 4); | ||
728 | } | ||
729 | |||
730 | static void lpphy_rev0_1_set_rx_gain(struct b43_wldev *dev, u32 gain) | ||
731 | { | ||
732 | u16 trsw = gain & 0x1; | ||
733 | u16 lna = (gain & 0xFFFC) | ((gain & 0xC) >> 2); | ||
734 | u16 ext_lna = (gain & 2) >> 1; | ||
735 | |||
736 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFE, trsw); | ||
737 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, | ||
738 | 0xFBFF, ext_lna << 10); | ||
739 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, | ||
740 | 0xF7FF, ext_lna << 11); | ||
741 | b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, lna); | ||
742 | } | ||
743 | |||
744 | static void lpphy_rev2plus_set_rx_gain(struct b43_wldev *dev, u32 gain) | ||
745 | { | ||
746 | u16 low_gain = gain & 0xFFFF; | ||
747 | u16 high_gain = (gain >> 16) & 0xF; | ||
748 | u16 ext_lna = (gain >> 21) & 0x1; | ||
749 | u16 trsw = ~(gain >> 20) & 0x1; | ||
750 | u16 tmp; | ||
751 | |||
752 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFE, trsw); | ||
753 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, | ||
754 | 0xFDFF, ext_lna << 9); | ||
755 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, | ||
756 | 0xFBFF, ext_lna << 10); | ||
757 | b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain); | ||
758 | b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFF0, high_gain); | ||
759 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | ||
760 | tmp = (gain >> 2) & 0x3; | ||
761 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, | ||
762 | 0xE7FF, tmp<<11); | ||
763 | b43_phy_maskset(dev, B43_PHY_OFDM(0xE6), 0xFFE7, tmp << 3); | ||
764 | } | ||
765 | } | ||
766 | |||
767 | static void lpphy_enable_rx_gain_override(struct b43_wldev *dev) | ||
768 | { | ||
769 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFFE); | ||
770 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFEF); | ||
771 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFBF); | ||
772 | if (dev->phy.rev >= 2) { | ||
773 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF); | ||
774 | if (b43_current_band(dev->wl) != IEEE80211_BAND_2GHZ) | ||
775 | return; | ||
776 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFBFF); | ||
777 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFFF7); | ||
778 | } else { | ||
779 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFDFF); | ||
780 | } | ||
781 | } | ||
782 | |||
783 | static void lpphy_disable_rx_gain_override(struct b43_wldev *dev) | ||
784 | { | ||
785 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1); | ||
786 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10); | ||
787 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40); | ||
788 | if (dev->phy.rev >= 2) { | ||
789 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x100); | ||
790 | if (b43_current_band(dev->wl) != IEEE80211_BAND_2GHZ) | ||
791 | return; | ||
792 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x400); | ||
793 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x8); | ||
794 | } else { | ||
795 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x200); | ||
796 | } | ||
797 | } | ||
798 | |||
799 | static void lpphy_set_rx_gain(struct b43_wldev *dev, u32 gain) | ||
800 | { | ||
801 | if (dev->phy.rev < 2) | ||
802 | lpphy_rev0_1_set_rx_gain(dev, gain); | ||
803 | else | ||
804 | lpphy_rev2plus_set_rx_gain(dev, gain); | ||
805 | lpphy_enable_rx_gain_override(dev); | ||
806 | } | ||
807 | |||
808 | static void lpphy_set_rx_gain_by_index(struct b43_wldev *dev, u16 idx) | ||
809 | { | ||
810 | u32 gain = b43_lptab_read(dev, B43_LPTAB16(12, idx)); | ||
811 | lpphy_set_rx_gain(dev, gain); | ||
812 | } | ||
813 | |||
814 | static void lpphy_stop_ddfs(struct b43_wldev *dev) | ||
815 | { | ||
816 | b43_phy_mask(dev, B43_LPPHY_AFE_DDFS, 0xFFFD); | ||
817 | b43_phy_mask(dev, B43_LPPHY_LP_PHY_CTL, 0xFFDF); | ||
818 | } | ||
819 | |||
820 | static void lpphy_run_ddfs(struct b43_wldev *dev, int i_on, int q_on, | ||
821 | int incr1, int incr2, int scale_idx) | ||
822 | { | ||
823 | lpphy_stop_ddfs(dev); | ||
824 | b43_phy_mask(dev, B43_LPPHY_AFE_DDFS_POINTER_INIT, 0xFF80); | ||
825 | b43_phy_mask(dev, B43_LPPHY_AFE_DDFS_POINTER_INIT, 0x80FF); | ||
826 | b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS_INCR_INIT, 0xFF80, incr1); | ||
827 | b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS_INCR_INIT, 0x80FF, incr2 << 8); | ||
828 | b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFF7, i_on << 3); | ||
829 | b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFEF, q_on << 4); | ||
830 | b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFF9F, scale_idx << 5); | ||
831 | b43_phy_mask(dev, B43_LPPHY_AFE_DDFS, 0xFFFB); | ||
832 | b43_phy_set(dev, B43_LPPHY_AFE_DDFS, 0x2); | ||
833 | b43_phy_set(dev, B43_LPPHY_AFE_DDFS, 0x20); | ||
834 | } | ||
835 | |||
836 | static bool lpphy_rx_iq_est(struct b43_wldev *dev, u16 samples, u8 time, | ||
837 | struct lpphy_iq_est *iq_est) | ||
838 | { | ||
839 | int i; | ||
840 | |||
841 | b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFF7); | ||
842 | b43_phy_write(dev, B43_LPPHY_IQ_NUM_SMPLS_ADDR, samples); | ||
843 | b43_phy_maskset(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xFF00, time); | ||
844 | b43_phy_mask(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xFEFF); | ||
845 | b43_phy_set(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xFDFF); | ||
846 | |||
847 | for (i = 0; i < 500; i++) { | ||
848 | if (!(b43_phy_read(dev, | ||
849 | B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) | ||
850 | break; | ||
851 | msleep(1); | ||
852 | } | ||
853 | |||
854 | if ((b43_phy_read(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) { | ||
855 | b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x8); | ||
856 | return false; | ||
857 | } | ||
858 | |||
859 | iq_est->iq_prod = b43_phy_read(dev, B43_LPPHY_IQ_ACC_HI_ADDR); | ||
860 | iq_est->iq_prod <<= 16; | ||
861 | iq_est->iq_prod |= b43_phy_read(dev, B43_LPPHY_IQ_ACC_LO_ADDR); | ||
862 | |||
863 | iq_est->i_pwr = b43_phy_read(dev, B43_LPPHY_IQ_I_PWR_ACC_HI_ADDR); | ||
864 | iq_est->i_pwr <<= 16; | ||
865 | iq_est->i_pwr |= b43_phy_read(dev, B43_LPPHY_IQ_I_PWR_ACC_LO_ADDR); | ||
866 | |||
867 | iq_est->q_pwr = b43_phy_read(dev, B43_LPPHY_IQ_Q_PWR_ACC_HI_ADDR); | ||
868 | iq_est->q_pwr <<= 16; | ||
869 | iq_est->q_pwr |= b43_phy_read(dev, B43_LPPHY_IQ_Q_PWR_ACC_LO_ADDR); | ||
870 | |||
871 | b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x8); | ||
872 | return true; | ||
873 | } | ||
874 | |||
875 | static int lpphy_loopback(struct b43_wldev *dev) | ||
876 | { | ||
877 | struct lpphy_iq_est iq_est; | ||
878 | int i, index = -1; | ||
879 | u32 tmp; | ||
880 | |||
881 | memset(&iq_est, 0, sizeof(iq_est)); | ||
882 | |||
883 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, 0x3); | ||
884 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3); | ||
885 | b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xFFFE); | ||
886 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x800); | ||
887 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x800); | ||
888 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8); | ||
889 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x8); | ||
890 | b43_radio_write(dev, B2062_N_TX_CTL_A, 0x80); | ||
891 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x80); | ||
892 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x80); | ||
893 | for (i = 0; i < 32; i++) { | ||
894 | lpphy_set_rx_gain_by_index(dev, i); | ||
895 | lpphy_run_ddfs(dev, 1, 1, 5, 5, 0); | ||
896 | if (!(lpphy_rx_iq_est(dev, 1000, 32, &iq_est))) | ||
897 | continue; | ||
898 | tmp = (iq_est.i_pwr + iq_est.q_pwr) / 1000; | ||
899 | if ((tmp > 4000) && (tmp < 10000)) { | ||
900 | index = i; | ||
901 | break; | ||
902 | } | ||
360 | } | 903 | } |
904 | lpphy_stop_ddfs(dev); | ||
905 | return index; | ||
906 | } | ||
907 | |||
908 | static u32 lpphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision) | ||
909 | { | ||
910 | u32 quotient, remainder, rbit, roundup, tmp; | ||
911 | |||
912 | if (divisor == 0) { | ||
913 | quotient = 0; | ||
914 | remainder = 0; | ||
915 | } else { | ||
916 | quotient = dividend / divisor; | ||
917 | remainder = dividend % divisor; | ||
918 | } | ||
919 | |||
920 | rbit = divisor & 0x1; | ||
921 | roundup = (divisor >> 1) + rbit; | ||
922 | precision--; | ||
923 | |||
924 | while (precision != 0xFF) { | ||
925 | tmp = remainder - roundup; | ||
926 | quotient <<= 1; | ||
927 | remainder <<= 1; | ||
928 | if (remainder >= roundup) { | ||
929 | remainder = (tmp << 1) + rbit; | ||
930 | quotient--; | ||
931 | } | ||
932 | precision--; | ||
933 | } | ||
934 | |||
935 | if (remainder >= roundup) | ||
936 | quotient++; | ||
937 | |||
938 | return quotient; | ||
361 | } | 939 | } |
362 | 940 | ||
363 | /* Read the TX power control mode from hardware. */ | 941 | /* Read the TX power control mode from hardware. */ |
@@ -444,6 +1022,170 @@ static void lpphy_set_tx_power_control(struct b43_wldev *dev, | |||
444 | lpphy_write_tx_pctl_mode_to_hardware(dev); | 1022 | lpphy_write_tx_pctl_mode_to_hardware(dev); |
445 | } | 1023 | } |
446 | 1024 | ||
1025 | static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev) | ||
1026 | { | ||
1027 | struct b43_phy_lp *lpphy = dev->phy.lp; | ||
1028 | struct lpphy_iq_est iq_est; | ||
1029 | struct lpphy_tx_gains tx_gains; | ||
1030 | static const u32 ideal_pwr_table[22] = { | ||
1031 | 0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64, | ||
1032 | 0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35, | ||
1033 | 0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088, | ||
1034 | 0x0004c, 0x0002c, 0x0001a, 0xc0006, | ||
1035 | }; | ||
1036 | bool old_txg_ovr; | ||
1037 | u8 old_bbmult; | ||
1038 | u16 old_rf_ovr, old_rf_ovrval, old_afe_ovr, old_afe_ovrval, | ||
1039 | old_rf2_ovr, old_rf2_ovrval, old_phy_ctl, old_txpctl; | ||
1040 | u32 normal_pwr, ideal_pwr, mean_sq_pwr, tmp = 0, mean_sq_pwr_min = 0; | ||
1041 | int loopback, i, j, inner_sum; | ||
1042 | |||
1043 | memset(&iq_est, 0, sizeof(iq_est)); | ||
1044 | |||
1045 | b43_switch_channel(dev, 7); | ||
1046 | old_txg_ovr = (b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) >> 6) & 1; | ||
1047 | old_bbmult = lpphy_get_bb_mult(dev); | ||
1048 | if (old_txg_ovr) | ||
1049 | tx_gains = lpphy_get_tx_gains(dev); | ||
1050 | old_rf_ovr = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_0); | ||
1051 | old_rf_ovrval = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_VAL_0); | ||
1052 | old_afe_ovr = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR); | ||
1053 | old_afe_ovrval = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVRVAL); | ||
1054 | old_rf2_ovr = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_2); | ||
1055 | old_rf2_ovrval = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_2_VAL); | ||
1056 | old_phy_ctl = b43_phy_read(dev, B43_LPPHY_LP_PHY_CTL); | ||
1057 | old_txpctl = b43_phy_read(dev, B43_LPPHY_TX_PWR_CTL_CMD) & | ||
1058 | B43_LPPHY_TX_PWR_CTL_CMD_MODE; | ||
1059 | |||
1060 | lpphy_set_tx_power_control(dev, B43_LPPHY_TX_PWR_CTL_CMD_MODE_OFF); | ||
1061 | lpphy_disable_crs(dev); | ||
1062 | loopback = lpphy_loopback(dev); | ||
1063 | if (loopback == -1) | ||
1064 | goto finish; | ||
1065 | lpphy_set_rx_gain_by_index(dev, loopback); | ||
1066 | b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xFFBF, 0x40); | ||
1067 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFFF8, 0x1); | ||
1068 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFFC7, 0x8); | ||
1069 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFF3F, 0xC0); | ||
1070 | for (i = 128; i <= 159; i++) { | ||
1071 | b43_radio_write(dev, B2062_N_RXBB_CALIB2, i); | ||
1072 | inner_sum = 0; | ||
1073 | for (j = 5; j <= 25; j++) { | ||
1074 | lpphy_run_ddfs(dev, 1, 1, j, j, 0); | ||
1075 | if (!(lpphy_rx_iq_est(dev, 1000, 32, &iq_est))) | ||
1076 | goto finish; | ||
1077 | mean_sq_pwr = iq_est.i_pwr + iq_est.q_pwr; | ||
1078 | if (j == 5) | ||
1079 | tmp = mean_sq_pwr; | ||
1080 | ideal_pwr = ((ideal_pwr_table[j-5] >> 3) + 1) >> 1; | ||
1081 | normal_pwr = lpphy_qdiv_roundup(mean_sq_pwr, tmp, 12); | ||
1082 | mean_sq_pwr = ideal_pwr - normal_pwr; | ||
1083 | mean_sq_pwr *= mean_sq_pwr; | ||
1084 | inner_sum += mean_sq_pwr; | ||
1085 | if ((i = 128) || (inner_sum < mean_sq_pwr_min)) { | ||
1086 | lpphy->rc_cap = i; | ||
1087 | mean_sq_pwr_min = inner_sum; | ||
1088 | } | ||
1089 | } | ||
1090 | } | ||
1091 | lpphy_stop_ddfs(dev); | ||
1092 | |||
1093 | finish: | ||
1094 | lpphy_restore_crs(dev); | ||
1095 | b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, old_rf_ovrval); | ||
1096 | b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_0, old_rf_ovr); | ||
1097 | b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVRVAL, old_afe_ovrval); | ||
1098 | b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVR, old_afe_ovr); | ||
1099 | b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, old_rf2_ovrval); | ||
1100 | b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, old_rf2_ovr); | ||
1101 | b43_phy_write(dev, B43_LPPHY_LP_PHY_CTL, old_phy_ctl); | ||
1102 | |||
1103 | lpphy_set_bb_mult(dev, old_bbmult); | ||
1104 | if (old_txg_ovr) { | ||
1105 | /* | ||
1106 | * SPEC FIXME: The specs say "get_tx_gains" here, which is | ||
1107 | * illogical. According to lwfinger, vendor driver v4.150.10.5 | ||
1108 | * has a Set here, while v4.174.64.19 has a Get - regression in | ||
1109 | * the vendor driver? This should be tested this once the code | ||
1110 | * is testable. | ||
1111 | */ | ||
1112 | lpphy_set_tx_gains(dev, tx_gains); | ||
1113 | } | ||
1114 | lpphy_set_tx_power_control(dev, old_txpctl); | ||
1115 | if (lpphy->rc_cap) | ||
1116 | lpphy_set_rc_cap(dev); | ||
1117 | } | ||
1118 | |||
1119 | static void lpphy_rev2plus_rc_calib(struct b43_wldev *dev) | ||
1120 | { | ||
1121 | struct ssb_bus *bus = dev->dev->bus; | ||
1122 | u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000; | ||
1123 | u8 tmp = b43_radio_read(dev, B2063_RX_BB_SP8) & 0xFF; | ||
1124 | int i; | ||
1125 | |||
1126 | b43_radio_write(dev, B2063_RX_BB_SP8, 0x0); | ||
1127 | b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E); | ||
1128 | b43_radio_mask(dev, B2063_PLL_SP1, 0xF7); | ||
1129 | b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7C); | ||
1130 | b43_radio_write(dev, B2063_RC_CALIB_CTL2, 0x15); | ||
1131 | b43_radio_write(dev, B2063_RC_CALIB_CTL3, 0x70); | ||
1132 | b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0x52); | ||
1133 | b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x1); | ||
1134 | b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7D); | ||
1135 | |||
1136 | for (i = 0; i < 10000; i++) { | ||
1137 | if (b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2) | ||
1138 | break; | ||
1139 | msleep(1); | ||
1140 | } | ||
1141 | |||
1142 | if (!(b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2)) | ||
1143 | b43_radio_write(dev, B2063_RX_BB_SP8, tmp); | ||
1144 | |||
1145 | tmp = b43_radio_read(dev, B2063_TX_BB_SP3) & 0xFF; | ||
1146 | |||
1147 | b43_radio_write(dev, B2063_TX_BB_SP3, 0x0); | ||
1148 | b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E); | ||
1149 | b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7C); | ||
1150 | b43_radio_write(dev, B2063_RC_CALIB_CTL2, 0x55); | ||
1151 | b43_radio_write(dev, B2063_RC_CALIB_CTL3, 0x76); | ||
1152 | |||
1153 | if (crystal_freq == 24000000) { | ||
1154 | b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0xFC); | ||
1155 | b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x0); | ||
1156 | } else { | ||
1157 | b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0x13); | ||
1158 | b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x1); | ||
1159 | } | ||
1160 | |||
1161 | b43_radio_write(dev, B2063_PA_SP7, 0x7D); | ||
1162 | |||
1163 | for (i = 0; i < 10000; i++) { | ||
1164 | if (b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2) | ||
1165 | break; | ||
1166 | msleep(1); | ||
1167 | } | ||
1168 | |||
1169 | if (!(b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2)) | ||
1170 | b43_radio_write(dev, B2063_TX_BB_SP3, tmp); | ||
1171 | |||
1172 | b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E); | ||
1173 | } | ||
1174 | |||
1175 | static void lpphy_calibrate_rc(struct b43_wldev *dev) | ||
1176 | { | ||
1177 | struct b43_phy_lp *lpphy = dev->phy.lp; | ||
1178 | |||
1179 | if (dev->phy.rev >= 2) { | ||
1180 | lpphy_rev2plus_rc_calib(dev); | ||
1181 | } else if (!lpphy->rc_cap) { | ||
1182 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) | ||
1183 | lpphy_rev0_1_rc_calib(dev); | ||
1184 | } else { | ||
1185 | lpphy_set_rc_cap(dev); | ||
1186 | } | ||
1187 | } | ||
1188 | |||
447 | static void lpphy_set_tx_power_by_index(struct b43_wldev *dev, u8 index) | 1189 | static void lpphy_set_tx_power_by_index(struct b43_wldev *dev, u8 index) |
448 | { | 1190 | { |
449 | struct b43_phy_lp *lpphy = dev->phy.lp; | 1191 | struct b43_phy_lp *lpphy = dev->phy.lp; |
@@ -532,13 +1274,14 @@ static void lpphy_tx_pctl_init(struct b43_wldev *dev) | |||
532 | 1274 | ||
533 | static int b43_lpphy_op_init(struct b43_wldev *dev) | 1275 | static int b43_lpphy_op_init(struct b43_wldev *dev) |
534 | { | 1276 | { |
535 | /* TODO: band SPROM */ | 1277 | lpphy_read_band_sprom(dev); //FIXME should this be in prepare_structs? |
536 | lpphy_baseband_init(dev); | 1278 | lpphy_baseband_init(dev); |
537 | lpphy_radio_init(dev); | 1279 | lpphy_radio_init(dev); |
538 | //TODO calibrate RC | 1280 | lpphy_calibrate_rc(dev); |
539 | //TODO set channel | 1281 | //TODO set channel |
540 | lpphy_tx_pctl_init(dev); | 1282 | lpphy_tx_pctl_init(dev); |
541 | //TODO full calib | 1283 | lpphy_calibration(dev); |
1284 | //TODO ACI init | ||
542 | 1285 | ||
543 | return 0; | 1286 | return 0; |
544 | } | 1287 | } |
@@ -616,7 +1359,6 @@ static enum b43_txpwr_result b43_lpphy_op_recalc_txpower(struct b43_wldev *dev, | |||
616 | return B43_TXPWR_RES_DONE; | 1359 | return B43_TXPWR_RES_DONE; |
617 | } | 1360 | } |
618 | 1361 | ||
619 | |||
620 | const struct b43_phy_operations b43_phyops_lp = { | 1362 | const struct b43_phy_operations b43_phyops_lp = { |
621 | .allocate = b43_lpphy_op_allocate, | 1363 | .allocate = b43_lpphy_op_allocate, |
622 | .free = b43_lpphy_op_free, | 1364 | .free = b43_lpphy_op_free, |