Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.30-rc7 628 lines 19 kB view raw
1/* 2 3 Broadcom B43 wireless driver 4 IEEE 802.11n PHY support 5 6 Copyright (c) 2008 Michael Buesch <mb@bu3sch.de> 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; see the file COPYING. If not, write to 20 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, 21 Boston, MA 02110-1301, USA. 22 23*/ 24 25#include <linux/delay.h> 26#include <linux/types.h> 27 28#include "b43.h" 29#include "phy_n.h" 30#include "tables_nphy.h" 31 32 33void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna) 34{//TODO 35} 36 37static void b43_nphy_op_adjust_txpower(struct b43_wldev *dev) 38{//TODO 39} 40 41static enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev, 42 bool ignore_tssi) 43{//TODO 44 return B43_TXPWR_RES_DONE; 45} 46 47static void b43_chantab_radio_upload(struct b43_wldev *dev, 48 const struct b43_nphy_channeltab_entry *e) 49{ 50 b43_radio_write16(dev, B2055_PLL_REF, e->radio_pll_ref); 51 b43_radio_write16(dev, B2055_RF_PLLMOD0, e->radio_rf_pllmod0); 52 b43_radio_write16(dev, B2055_RF_PLLMOD1, e->radio_rf_pllmod1); 53 b43_radio_write16(dev, B2055_VCO_CAPTAIL, e->radio_vco_captail); 54 b43_radio_write16(dev, B2055_VCO_CAL1, e->radio_vco_cal1); 55 b43_radio_write16(dev, B2055_VCO_CAL2, e->radio_vco_cal2); 56 b43_radio_write16(dev, B2055_PLL_LFC1, e->radio_pll_lfc1); 57 b43_radio_write16(dev, B2055_PLL_LFR1, e->radio_pll_lfr1); 58 b43_radio_write16(dev, B2055_PLL_LFC2, e->radio_pll_lfc2); 59 b43_radio_write16(dev, B2055_LGBUF_CENBUF, e->radio_lgbuf_cenbuf); 60 b43_radio_write16(dev, B2055_LGEN_TUNE1, e->radio_lgen_tune1); 61 b43_radio_write16(dev, B2055_LGEN_TUNE2, e->radio_lgen_tune2); 62 b43_radio_write16(dev, B2055_C1_LGBUF_ATUNE, e->radio_c1_lgbuf_atune); 63 b43_radio_write16(dev, B2055_C1_LGBUF_GTUNE, e->radio_c1_lgbuf_gtune); 64 b43_radio_write16(dev, B2055_C1_RX_RFR1, e->radio_c1_rx_rfr1); 65 b43_radio_write16(dev, B2055_C1_TX_PGAPADTN, e->radio_c1_tx_pgapadtn); 66 b43_radio_write16(dev, B2055_C1_TX_MXBGTRIM, e->radio_c1_tx_mxbgtrim); 67 b43_radio_write16(dev, B2055_C2_LGBUF_ATUNE, e->radio_c2_lgbuf_atune); 68 b43_radio_write16(dev, B2055_C2_LGBUF_GTUNE, e->radio_c2_lgbuf_gtune); 69 b43_radio_write16(dev, B2055_C2_RX_RFR1, e->radio_c2_rx_rfr1); 70 b43_radio_write16(dev, B2055_C2_TX_PGAPADTN, e->radio_c2_tx_pgapadtn); 71 b43_radio_write16(dev, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim); 72} 73 74static void b43_chantab_phy_upload(struct b43_wldev *dev, 75 const struct b43_nphy_channeltab_entry *e) 76{ 77 b43_phy_write(dev, B43_NPHY_BW1A, e->phy_bw1a); 78 b43_phy_write(dev, B43_NPHY_BW2, e->phy_bw2); 79 b43_phy_write(dev, B43_NPHY_BW3, e->phy_bw3); 80 b43_phy_write(dev, B43_NPHY_BW4, e->phy_bw4); 81 b43_phy_write(dev, B43_NPHY_BW5, e->phy_bw5); 82 b43_phy_write(dev, B43_NPHY_BW6, e->phy_bw6); 83} 84 85static void b43_nphy_tx_power_fix(struct b43_wldev *dev) 86{ 87 //TODO 88} 89 90/* Tune the hardware to a new channel. */ 91static int nphy_channel_switch(struct b43_wldev *dev, unsigned int channel) 92{ 93 const struct b43_nphy_channeltab_entry *tabent; 94 95 tabent = b43_nphy_get_chantabent(dev, channel); 96 if (!tabent) 97 return -ESRCH; 98 99 //FIXME enable/disable band select upper20 in RXCTL 100 if (0 /*FIXME 5Ghz*/) 101 b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, 0x20); 102 else 103 b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, 0x50); 104 b43_chantab_radio_upload(dev, tabent); 105 udelay(50); 106 b43_radio_write16(dev, B2055_VCO_CAL10, 5); 107 b43_radio_write16(dev, B2055_VCO_CAL10, 45); 108 b43_radio_write16(dev, B2055_VCO_CAL10, 65); 109 udelay(300); 110 if (0 /*FIXME 5Ghz*/) 111 b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ); 112 else 113 b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ); 114 b43_chantab_phy_upload(dev, tabent); 115 b43_nphy_tx_power_fix(dev); 116 117 return 0; 118} 119 120static void b43_radio_init2055_pre(struct b43_wldev *dev) 121{ 122 b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, 123 ~B43_NPHY_RFCTL_CMD_PORFORCE); 124 b43_phy_set(dev, B43_NPHY_RFCTL_CMD, 125 B43_NPHY_RFCTL_CMD_CHIP0PU | 126 B43_NPHY_RFCTL_CMD_OEPORFORCE); 127 b43_phy_set(dev, B43_NPHY_RFCTL_CMD, 128 B43_NPHY_RFCTL_CMD_PORFORCE); 129} 130 131static void b43_radio_init2055_post(struct b43_wldev *dev) 132{ 133 struct ssb_sprom *sprom = &(dev->dev->bus->sprom); 134 struct ssb_boardinfo *binfo = &(dev->dev->bus->boardinfo); 135 int i; 136 u16 val; 137 138 b43_radio_mask(dev, B2055_MASTER1, 0xFFF3); 139 msleep(1); 140 if ((sprom->revision != 4) || !(sprom->boardflags_hi & 0x0002)) { 141 if ((binfo->vendor != PCI_VENDOR_ID_BROADCOM) || 142 (binfo->type != 0x46D) || 143 (binfo->rev < 0x41)) { 144 b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F); 145 b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F); 146 msleep(1); 147 } 148 } 149 b43_radio_maskset(dev, B2055_RRCCAL_NOPTSEL, 0x3F, 0x2C); 150 msleep(1); 151 b43_radio_write16(dev, B2055_CAL_MISC, 0x3C); 152 msleep(1); 153 b43_radio_mask(dev, B2055_CAL_MISC, 0xFFBE); 154 msleep(1); 155 b43_radio_set(dev, B2055_CAL_LPOCTL, 0x80); 156 msleep(1); 157 b43_radio_set(dev, B2055_CAL_MISC, 0x1); 158 msleep(1); 159 b43_radio_set(dev, B2055_CAL_MISC, 0x40); 160 msleep(1); 161 for (i = 0; i < 100; i++) { 162 val = b43_radio_read16(dev, B2055_CAL_COUT2); 163 if (val & 0x80) 164 break; 165 udelay(10); 166 } 167 msleep(1); 168 b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F); 169 msleep(1); 170 nphy_channel_switch(dev, dev->phy.channel); 171 b43_radio_write16(dev, B2055_C1_RX_BB_LPF, 0x9); 172 b43_radio_write16(dev, B2055_C2_RX_BB_LPF, 0x9); 173 b43_radio_write16(dev, B2055_C1_RX_BB_MIDACHP, 0x83); 174 b43_radio_write16(dev, B2055_C2_RX_BB_MIDACHP, 0x83); 175} 176 177/* Initialize a Broadcom 2055 N-radio */ 178static void b43_radio_init2055(struct b43_wldev *dev) 179{ 180 b43_radio_init2055_pre(dev); 181 if (b43_status(dev) < B43_STAT_INITIALIZED) 182 b2055_upload_inittab(dev, 0, 1); 183 else 184 b2055_upload_inittab(dev, 0/*FIXME on 5ghz band*/, 0); 185 b43_radio_init2055_post(dev); 186} 187 188void b43_nphy_radio_turn_on(struct b43_wldev *dev) 189{ 190 b43_radio_init2055(dev); 191} 192 193void b43_nphy_radio_turn_off(struct b43_wldev *dev) 194{ 195 b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, 196 ~B43_NPHY_RFCTL_CMD_EN); 197} 198 199#define ntab_upload(dev, offset, data) do { \ 200 unsigned int i; \ 201 for (i = 0; i < (offset##_SIZE); i++) \ 202 b43_ntab_write(dev, (offset) + i, (data)[i]); \ 203 } while (0) 204 205/* Upload the N-PHY tables. */ 206static void b43_nphy_tables_init(struct b43_wldev *dev) 207{ 208 /* Static tables */ 209 ntab_upload(dev, B43_NTAB_FRAMESTRUCT, b43_ntab_framestruct); 210 ntab_upload(dev, B43_NTAB_FRAMELT, b43_ntab_framelookup); 211 ntab_upload(dev, B43_NTAB_TMAP, b43_ntab_tmap); 212 ntab_upload(dev, B43_NTAB_TDTRN, b43_ntab_tdtrn); 213 ntab_upload(dev, B43_NTAB_INTLEVEL, b43_ntab_intlevel); 214 ntab_upload(dev, B43_NTAB_PILOT, b43_ntab_pilot); 215 ntab_upload(dev, B43_NTAB_PILOTLT, b43_ntab_pilotlt); 216 ntab_upload(dev, B43_NTAB_TDI20A0, b43_ntab_tdi20a0); 217 ntab_upload(dev, B43_NTAB_TDI20A1, b43_ntab_tdi20a1); 218 ntab_upload(dev, B43_NTAB_TDI40A0, b43_ntab_tdi40a0); 219 ntab_upload(dev, B43_NTAB_TDI40A1, b43_ntab_tdi40a1); 220 ntab_upload(dev, B43_NTAB_BDI, b43_ntab_bdi); 221 ntab_upload(dev, B43_NTAB_CHANEST, b43_ntab_channelest); 222 ntab_upload(dev, B43_NTAB_MCS, b43_ntab_mcs); 223 224 /* Volatile tables */ 225 ntab_upload(dev, B43_NTAB_NOISEVAR10, b43_ntab_noisevar10); 226 ntab_upload(dev, B43_NTAB_NOISEVAR11, b43_ntab_noisevar11); 227 ntab_upload(dev, B43_NTAB_C0_ESTPLT, b43_ntab_estimatepowerlt0); 228 ntab_upload(dev, B43_NTAB_C1_ESTPLT, b43_ntab_estimatepowerlt1); 229 ntab_upload(dev, B43_NTAB_C0_ADJPLT, b43_ntab_adjustpower0); 230 ntab_upload(dev, B43_NTAB_C1_ADJPLT, b43_ntab_adjustpower1); 231 ntab_upload(dev, B43_NTAB_C0_GAINCTL, b43_ntab_gainctl0); 232 ntab_upload(dev, B43_NTAB_C1_GAINCTL, b43_ntab_gainctl1); 233 ntab_upload(dev, B43_NTAB_C0_IQLT, b43_ntab_iqlt0); 234 ntab_upload(dev, B43_NTAB_C1_IQLT, b43_ntab_iqlt1); 235 ntab_upload(dev, B43_NTAB_C0_LOFEEDTH, b43_ntab_loftlt0); 236 ntab_upload(dev, B43_NTAB_C1_LOFEEDTH, b43_ntab_loftlt1); 237} 238 239static void b43_nphy_workarounds(struct b43_wldev *dev) 240{ 241 struct b43_phy *phy = &dev->phy; 242 unsigned int i; 243 244 b43_phy_set(dev, B43_NPHY_IQFLIP, 245 B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2); 246 if (1 /* FIXME band is 2.4GHz */) { 247 b43_phy_set(dev, B43_NPHY_CLASSCTL, 248 B43_NPHY_CLASSCTL_CCKEN); 249 } else { 250 b43_phy_mask(dev, B43_NPHY_CLASSCTL, 251 ~B43_NPHY_CLASSCTL_CCKEN); 252 } 253 b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8); 254 b43_phy_write(dev, B43_NPHY_TXFRAMEDELAY, 8); 255 256 /* Fixup some tables */ 257 b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0xA); 258 b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0xA); 259 b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA); 260 b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA); 261 b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0); 262 b43_ntab_write(dev, B43_NTAB16(8, 0x18), 0); 263 b43_ntab_write(dev, B43_NTAB16(8, 0x07), 0x7AAB); 264 b43_ntab_write(dev, B43_NTAB16(8, 0x17), 0x7AAB); 265 b43_ntab_write(dev, B43_NTAB16(8, 0x06), 0x800); 266 b43_ntab_write(dev, B43_NTAB16(8, 0x16), 0x800); 267 268 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8); 269 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301); 270 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8); 271 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301); 272 273 //TODO set RF sequence 274 275 /* Set narrowband clip threshold */ 276 b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, 66); 277 b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, 66); 278 279 /* Set wideband clip 2 threshold */ 280 b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES, 281 ~B43_NPHY_C1_CLIPWBTHRES_CLIP2, 282 21 << B43_NPHY_C1_CLIPWBTHRES_CLIP2_SHIFT); 283 b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES, 284 ~B43_NPHY_C2_CLIPWBTHRES_CLIP2, 285 21 << B43_NPHY_C2_CLIPWBTHRES_CLIP2_SHIFT); 286 287 /* Set Clip 2 detect */ 288 b43_phy_set(dev, B43_NPHY_C1_CGAINI, 289 B43_NPHY_C1_CGAINI_CL2DETECT); 290 b43_phy_set(dev, B43_NPHY_C2_CGAINI, 291 B43_NPHY_C2_CGAINI_CL2DETECT); 292 293 if (0 /*FIXME*/) { 294 /* Set dwell lengths */ 295 b43_phy_write(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 43); 296 b43_phy_write(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 43); 297 b43_phy_write(dev, B43_NPHY_W1CLIP1_DWELL_LEN, 9); 298 b43_phy_write(dev, B43_NPHY_W1CLIP2_DWELL_LEN, 9); 299 300 /* Set gain backoff */ 301 b43_phy_maskset(dev, B43_NPHY_C1_CGAINI, 302 ~B43_NPHY_C1_CGAINI_GAINBKOFF, 303 1 << B43_NPHY_C1_CGAINI_GAINBKOFF_SHIFT); 304 b43_phy_maskset(dev, B43_NPHY_C2_CGAINI, 305 ~B43_NPHY_C2_CGAINI_GAINBKOFF, 306 1 << B43_NPHY_C2_CGAINI_GAINBKOFF_SHIFT); 307 308 /* Set HPVGA2 index */ 309 b43_phy_maskset(dev, B43_NPHY_C1_INITGAIN, 310 ~B43_NPHY_C1_INITGAIN_HPVGA2, 311 6 << B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT); 312 b43_phy_maskset(dev, B43_NPHY_C2_INITGAIN, 313 ~B43_NPHY_C2_INITGAIN_HPVGA2, 314 6 << B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT); 315 316 //FIXME verify that the specs really mean to use autoinc here. 317 for (i = 0; i < 3; i++) 318 b43_ntab_write(dev, B43_NTAB16(7, 0x106) + i, 0x673); 319 } 320 321 /* Set minimum gain value */ 322 b43_phy_maskset(dev, B43_NPHY_C1_MINMAX_GAIN, 323 ~B43_NPHY_C1_MINGAIN, 324 23 << B43_NPHY_C1_MINGAIN_SHIFT); 325 b43_phy_maskset(dev, B43_NPHY_C2_MINMAX_GAIN, 326 ~B43_NPHY_C2_MINGAIN, 327 23 << B43_NPHY_C2_MINGAIN_SHIFT); 328 329 if (phy->rev < 2) { 330 b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL, 331 ~B43_NPHY_SCRAM_SIGCTL_SCM); 332 } 333 334 /* Set phase track alpha and beta */ 335 b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125); 336 b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3); 337 b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105); 338 b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E); 339 b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD); 340 b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20); 341} 342 343static void b43_nphy_reset_cca(struct b43_wldev *dev) 344{ 345 u16 bbcfg; 346 347 ssb_write32(dev->dev, SSB_TMSLOW, 348 ssb_read32(dev->dev, SSB_TMSLOW) | SSB_TMSLOW_FGC); 349 bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG); 350 b43_phy_set(dev, B43_NPHY_BBCFG, B43_NPHY_BBCFG_RSTCCA); 351 b43_phy_write(dev, B43_NPHY_BBCFG, 352 bbcfg & ~B43_NPHY_BBCFG_RSTCCA); 353 ssb_write32(dev->dev, SSB_TMSLOW, 354 ssb_read32(dev->dev, SSB_TMSLOW) & ~SSB_TMSLOW_FGC); 355} 356 357enum b43_nphy_rf_sequence { 358 B43_RFSEQ_RX2TX, 359 B43_RFSEQ_TX2RX, 360 B43_RFSEQ_RESET2RX, 361 B43_RFSEQ_UPDATE_GAINH, 362 B43_RFSEQ_UPDATE_GAINL, 363 B43_RFSEQ_UPDATE_GAINU, 364}; 365 366static void b43_nphy_force_rf_sequence(struct b43_wldev *dev, 367 enum b43_nphy_rf_sequence seq) 368{ 369 static const u16 trigger[] = { 370 [B43_RFSEQ_RX2TX] = B43_NPHY_RFSEQTR_RX2TX, 371 [B43_RFSEQ_TX2RX] = B43_NPHY_RFSEQTR_TX2RX, 372 [B43_RFSEQ_RESET2RX] = B43_NPHY_RFSEQTR_RST2RX, 373 [B43_RFSEQ_UPDATE_GAINH] = B43_NPHY_RFSEQTR_UPGH, 374 [B43_RFSEQ_UPDATE_GAINL] = B43_NPHY_RFSEQTR_UPGL, 375 [B43_RFSEQ_UPDATE_GAINU] = B43_NPHY_RFSEQTR_UPGU, 376 }; 377 int i; 378 379 B43_WARN_ON(seq >= ARRAY_SIZE(trigger)); 380 381 b43_phy_set(dev, B43_NPHY_RFSEQMODE, 382 B43_NPHY_RFSEQMODE_CAOVER | B43_NPHY_RFSEQMODE_TROVER); 383 b43_phy_set(dev, B43_NPHY_RFSEQTR, trigger[seq]); 384 for (i = 0; i < 200; i++) { 385 if (!(b43_phy_read(dev, B43_NPHY_RFSEQST) & trigger[seq])) 386 goto ok; 387 msleep(1); 388 } 389 b43err(dev->wl, "RF sequence status timeout\n"); 390ok: 391 b43_phy_mask(dev, B43_NPHY_RFSEQMODE, 392 ~(B43_NPHY_RFSEQMODE_CAOVER | B43_NPHY_RFSEQMODE_TROVER)); 393} 394 395static void b43_nphy_bphy_init(struct b43_wldev *dev) 396{ 397 unsigned int i; 398 u16 val; 399 400 val = 0x1E1F; 401 for (i = 0; i < 14; i++) { 402 b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val); 403 val -= 0x202; 404 } 405 val = 0x3E3F; 406 for (i = 0; i < 16; i++) { 407 b43_phy_write(dev, B43_PHY_N_BMODE(0x97 + i), val); 408 val -= 0x202; 409 } 410 b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668); 411} 412 413/* RSSI Calibration */ 414static void b43_nphy_rssi_cal(struct b43_wldev *dev, u8 type) 415{ 416 //TODO 417} 418 419int b43_phy_initn(struct b43_wldev *dev) 420{ 421 struct b43_phy *phy = &dev->phy; 422 u16 tmp; 423 424 //TODO: Spectral management 425 b43_nphy_tables_init(dev); 426 427 /* Clear all overrides */ 428 b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0); 429 b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, 0); 430 b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, 0); 431 b43_phy_write(dev, B43_NPHY_RFCTL_INTC3, 0); 432 b43_phy_write(dev, B43_NPHY_RFCTL_INTC4, 0); 433 b43_phy_mask(dev, B43_NPHY_RFSEQMODE, 434 ~(B43_NPHY_RFSEQMODE_CAOVER | 435 B43_NPHY_RFSEQMODE_TROVER)); 436 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, 0); 437 438 tmp = (phy->rev < 2) ? 64 : 59; 439 b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, 440 ~B43_NPHY_BPHY_CTL3_SCALE, 441 tmp << B43_NPHY_BPHY_CTL3_SCALE_SHIFT); 442 443 b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20); 444 b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20); 445 446 b43_phy_write(dev, B43_NPHY_TXREALFD, 184); 447 b43_phy_write(dev, B43_NPHY_MIMO_CRSTXEXT, 200); 448 b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 80); 449 b43_phy_write(dev, B43_NPHY_C2_BCLIPBKOFF, 511); 450 451 //TODO MIMO-Config 452 //TODO Update TX/RX chain 453 454 if (phy->rev < 2) { 455 b43_phy_write(dev, B43_NPHY_DUP40_GFBL, 0xAA8); 456 b43_phy_write(dev, B43_NPHY_DUP40_BL, 0x9A4); 457 } 458 b43_nphy_workarounds(dev); 459 b43_nphy_reset_cca(dev); 460 461 ssb_write32(dev->dev, SSB_TMSLOW, 462 ssb_read32(dev->dev, SSB_TMSLOW) | B43_TMSLOW_MACPHYCLKEN); 463 b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX); 464 b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); 465 466 b43_phy_read(dev, B43_NPHY_CLASSCTL); /* dummy read */ 467 //TODO read core1/2 clip1 thres regs 468 469 if (1 /* FIXME Band is 2.4GHz */) 470 b43_nphy_bphy_init(dev); 471 //TODO disable TX power control 472 //TODO Fix the TX power settings 473 //TODO Init periodic calibration with reason 3 474 b43_nphy_rssi_cal(dev, 2); 475 b43_nphy_rssi_cal(dev, 0); 476 b43_nphy_rssi_cal(dev, 1); 477 //TODO get TX gain 478 //TODO init superswitch 479 //TODO calibrate LO 480 //TODO idle TSSI TX pctl 481 //TODO TX power control power setup 482 //TODO table writes 483 //TODO TX power control coefficients 484 //TODO enable TX power control 485 //TODO control antenna selection 486 //TODO init radar detection 487 //TODO reset channel if changed 488 489 b43err(dev->wl, "IEEE 802.11n devices are not supported, yet.\n"); 490 return 0; 491} 492 493static int b43_nphy_op_allocate(struct b43_wldev *dev) 494{ 495 struct b43_phy_n *nphy; 496 497 nphy = kzalloc(sizeof(*nphy), GFP_KERNEL); 498 if (!nphy) 499 return -ENOMEM; 500 dev->phy.n = nphy; 501 502 return 0; 503} 504 505static void b43_nphy_op_prepare_structs(struct b43_wldev *dev) 506{ 507 struct b43_phy *phy = &dev->phy; 508 struct b43_phy_n *nphy = phy->n; 509 510 memset(nphy, 0, sizeof(*nphy)); 511 512 //TODO init struct b43_phy_n 513} 514 515static void b43_nphy_op_free(struct b43_wldev *dev) 516{ 517 struct b43_phy *phy = &dev->phy; 518 struct b43_phy_n *nphy = phy->n; 519 520 kfree(nphy); 521 phy->n = NULL; 522} 523 524static int b43_nphy_op_init(struct b43_wldev *dev) 525{ 526 return b43_phy_initn(dev); 527} 528 529static inline void check_phyreg(struct b43_wldev *dev, u16 offset) 530{ 531#if B43_DEBUG 532 if ((offset & B43_PHYROUTE) == B43_PHYROUTE_OFDM_GPHY) { 533 /* OFDM registers are onnly available on A/G-PHYs */ 534 b43err(dev->wl, "Invalid OFDM PHY access at " 535 "0x%04X on N-PHY\n", offset); 536 dump_stack(); 537 } 538 if ((offset & B43_PHYROUTE) == B43_PHYROUTE_EXT_GPHY) { 539 /* Ext-G registers are only available on G-PHYs */ 540 b43err(dev->wl, "Invalid EXT-G PHY access at " 541 "0x%04X on N-PHY\n", offset); 542 dump_stack(); 543 } 544#endif /* B43_DEBUG */ 545} 546 547static u16 b43_nphy_op_read(struct b43_wldev *dev, u16 reg) 548{ 549 check_phyreg(dev, reg); 550 b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); 551 return b43_read16(dev, B43_MMIO_PHY_DATA); 552} 553 554static void b43_nphy_op_write(struct b43_wldev *dev, u16 reg, u16 value) 555{ 556 check_phyreg(dev, reg); 557 b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); 558 b43_write16(dev, B43_MMIO_PHY_DATA, value); 559} 560 561static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg) 562{ 563 /* Register 1 is a 32-bit register. */ 564 B43_WARN_ON(reg == 1); 565 /* N-PHY needs 0x100 for read access */ 566 reg |= 0x100; 567 568 b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); 569 return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW); 570} 571 572static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value) 573{ 574 /* Register 1 is a 32-bit register. */ 575 B43_WARN_ON(reg == 1); 576 577 b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); 578 b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value); 579} 580 581static void b43_nphy_op_software_rfkill(struct b43_wldev *dev, 582 enum rfkill_state state) 583{//TODO 584} 585 586static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on) 587{ 588 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, 589 on ? 0 : 0x7FFF); 590} 591 592static int b43_nphy_op_switch_channel(struct b43_wldev *dev, 593 unsigned int new_channel) 594{ 595 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { 596 if ((new_channel < 1) || (new_channel > 14)) 597 return -EINVAL; 598 } else { 599 if (new_channel > 200) 600 return -EINVAL; 601 } 602 603 return nphy_channel_switch(dev, new_channel); 604} 605 606static unsigned int b43_nphy_op_get_default_chan(struct b43_wldev *dev) 607{ 608 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) 609 return 1; 610 return 36; 611} 612 613const struct b43_phy_operations b43_phyops_n = { 614 .allocate = b43_nphy_op_allocate, 615 .free = b43_nphy_op_free, 616 .prepare_structs = b43_nphy_op_prepare_structs, 617 .init = b43_nphy_op_init, 618 .phy_read = b43_nphy_op_read, 619 .phy_write = b43_nphy_op_write, 620 .radio_read = b43_nphy_op_radio_read, 621 .radio_write = b43_nphy_op_radio_write, 622 .software_rfkill = b43_nphy_op_software_rfkill, 623 .switch_analog = b43_nphy_op_switch_analog, 624 .switch_channel = b43_nphy_op_switch_channel, 625 .get_default_chan = b43_nphy_op_get_default_chan, 626 .recalc_txpower = b43_nphy_op_recalc_txpower, 627 .adjust_txpower = b43_nphy_op_adjust_txpower, 628};