📄 phy.c
字号:
default: rf->att = 5; return; } } rf->att = 5;}static u16 default_tx_control(struct b43_wldev *dev){ struct b43_phy *phy = &dev->phy; if (phy->radio_ver != 0x2050) return 0; if (phy->radio_rev == 1) return B43_TXCTL_PA2DB | B43_TXCTL_TXMIX; if (phy->radio_rev < 6) return B43_TXCTL_PA2DB; if (phy->radio_rev == 8) return B43_TXCTL_TXMIX; return 0;}/* This func is called "PHY calibrate" in the specs... */void b43_phy_early_init(struct b43_wldev *dev){ struct b43_phy *phy = &dev->phy; struct b43_txpower_lo_control *lo = phy->lo_control; default_baseband_attenuation(dev, &phy->bbatt); default_radio_attenuation(dev, &phy->rfatt); phy->tx_control = (default_tx_control(dev) << 4); /* Commit previous writes */ b43_read32(dev, B43_MMIO_MACCTL); if (phy->type == B43_PHYTYPE_B || phy->type == B43_PHYTYPE_G) { generate_rfatt_list(dev, &lo->rfatt_list); generate_bbatt_list(dev, &lo->bbatt_list); } if (phy->type == B43_PHYTYPE_G && phy->rev == 1) { /* Workaround: Temporarly disable gmode through the early init * phase, as the gmode stuff is not needed for phy rev 1 */ phy->gmode = 0; b43_wireless_core_reset(dev, 0); b43_phy_initg(dev); phy->gmode = 1; b43_wireless_core_reset(dev, B43_TMSLOW_GMODE); }}/* GPHY_TSSI_Power_Lookup_Table_Init */static void b43_gphy_tssi_power_lt_init(struct b43_wldev *dev){ struct b43_phy *phy = &dev->phy; int i; u16 value; for (i = 0; i < 32; i++) b43_ofdmtab_write16(dev, 0x3C20, i, phy->tssi2dbm[i]); for (i = 32; i < 64; i++) b43_ofdmtab_write16(dev, 0x3C00, i - 32, phy->tssi2dbm[i]); for (i = 0; i < 64; i += 2) { value = (u16) phy->tssi2dbm[i]; value |= ((u16) phy->tssi2dbm[i + 1]) << 8; b43_phy_write(dev, 0x380 + (i / 2), value); }}/* GPHY_Gain_Lookup_Table_Init */static void b43_gphy_gain_lt_init(struct b43_wldev *dev){ struct b43_phy *phy = &dev->phy; struct b43_txpower_lo_control *lo = phy->lo_control; u16 nr_written = 0; u16 tmp; u8 rf, bb; if (!lo->lo_measured) { b43_phy_write(dev, 0x3FF, 0); return; } for (rf = 0; rf < lo->rfatt_list.len; rf++) { for (bb = 0; bb < lo->bbatt_list.len; bb++) { if (nr_written >= 0x40) return; tmp = lo->bbatt_list.list[bb].att; tmp <<= 8; if (phy->radio_rev == 8) tmp |= 0x50; else tmp |= 0x40; tmp |= lo->rfatt_list.list[rf].att; b43_phy_write(dev, 0x3C0 + nr_written, tmp); nr_written++; } }}/* GPHY_DC_Lookup_Table */void b43_gphy_dc_lt_init(struct b43_wldev *dev){ struct b43_phy *phy = &dev->phy; struct b43_txpower_lo_control *lo = phy->lo_control; struct b43_loctl *loctl0; struct b43_loctl *loctl1; int i; int rf_offset, bb_offset; u16 tmp; for (i = 0; i < lo->rfatt_list.len + lo->bbatt_list.len; i += 2) { rf_offset = i / lo->rfatt_list.len; bb_offset = i % lo->rfatt_list.len; loctl0 = b43_get_lo_g_ctl(dev, &lo->rfatt_list.list[rf_offset], &lo->bbatt_list.list[bb_offset]); if (i + 1 < lo->rfatt_list.len * lo->bbatt_list.len) { rf_offset = (i + 1) / lo->rfatt_list.len; bb_offset = (i + 1) % lo->rfatt_list.len; loctl1 = b43_get_lo_g_ctl(dev, &lo->rfatt_list.list[rf_offset], &lo->bbatt_list.list[bb_offset]); } else loctl1 = loctl0; tmp = ((u16) loctl0->q & 0xF); tmp |= ((u16) loctl0->i & 0xF) << 4; tmp |= ((u16) loctl1->q & 0xF) << 8; tmp |= ((u16) loctl1->i & 0xF) << 12; //FIXME? b43_phy_write(dev, 0x3A0 + (i / 2), tmp); }}static void hardware_pctl_init_aphy(struct b43_wldev *dev){ //TODO}static void hardware_pctl_init_gphy(struct b43_wldev *dev){ struct b43_phy *phy = &dev->phy; b43_phy_write(dev, 0x0036, (b43_phy_read(dev, 0x0036) & 0xFFC0) | (phy->tgt_idle_tssi - phy->cur_idle_tssi)); b43_phy_write(dev, 0x0478, (b43_phy_read(dev, 0x0478) & 0xFF00) | (phy->tgt_idle_tssi - phy->cur_idle_tssi)); b43_gphy_tssi_power_lt_init(dev); b43_gphy_gain_lt_init(dev); b43_phy_write(dev, 0x0060, b43_phy_read(dev, 0x0060) & 0xFFBF); b43_phy_write(dev, 0x0014, 0x0000); B43_WARN_ON(phy->rev < 6); b43_phy_write(dev, 0x0478, b43_phy_read(dev, 0x0478) | 0x0800); b43_phy_write(dev, 0x0478, b43_phy_read(dev, 0x0478) & 0xFEFF); b43_phy_write(dev, 0x0801, b43_phy_read(dev, 0x0801) & 0xFFBF); b43_gphy_dc_lt_init(dev);}/* HardwarePowerControl init for A and G PHY */static void b43_hardware_pctl_init(struct b43_wldev *dev){ struct b43_phy *phy = &dev->phy; if (!b43_has_hardware_pctl(phy)) { /* No hardware power control */ b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_HWPCTL); return; } /* Init the hwpctl related hardware */ switch (phy->type) { case B43_PHYTYPE_A: hardware_pctl_init_aphy(dev); break; case B43_PHYTYPE_G: hardware_pctl_init_gphy(dev); break; default: B43_WARN_ON(1); } /* Enable hardware pctl in firmware. */ b43_hf_write(dev, b43_hf_read(dev) | B43_HF_HWPCTL);}static void b43_hardware_pctl_early_init(struct b43_wldev *dev){ struct b43_phy *phy = &dev->phy; if (!b43_has_hardware_pctl(phy)) { b43_phy_write(dev, 0x047A, 0xC111); return; } b43_phy_write(dev, 0x0036, b43_phy_read(dev, 0x0036) & 0xFEFF); b43_phy_write(dev, 0x002F, 0x0202); b43_phy_write(dev, 0x047C, b43_phy_read(dev, 0x047C) | 0x0002); b43_phy_write(dev, 0x047A, b43_phy_read(dev, 0x047A) | 0xF000); if (phy->radio_ver == 0x2050 && phy->radio_rev == 8) { b43_phy_write(dev, 0x047A, (b43_phy_read(dev, 0x047A) & 0xFF0F) | 0x0010); b43_phy_write(dev, 0x005D, b43_phy_read(dev, 0x005D) | 0x8000); b43_phy_write(dev, 0x004E, (b43_phy_read(dev, 0x004E) & 0xFFC0) | 0x0010); b43_phy_write(dev, 0x002E, 0xC07F); b43_phy_write(dev, 0x0036, b43_phy_read(dev, 0x0036) | 0x0400); } else { b43_phy_write(dev, 0x0036, b43_phy_read(dev, 0x0036) | 0x0200); b43_phy_write(dev, 0x0036, b43_phy_read(dev, 0x0036) | 0x0400); b43_phy_write(dev, 0x005D, b43_phy_read(dev, 0x005D) & 0x7FFF); b43_phy_write(dev, 0x004F, b43_phy_read(dev, 0x004F) & 0xFFFE); b43_phy_write(dev, 0x004E, (b43_phy_read(dev, 0x004E) & 0xFFC0) | 0x0010); b43_phy_write(dev, 0x002E, 0xC07F); b43_phy_write(dev, 0x047A, (b43_phy_read(dev, 0x047A) & 0xFF0F) | 0x0010); }}/* Intialize B/G PHY power control * as described in http://bcm-specs.sipsolutions.net/InitPowerControl */static void b43_phy_init_pctl(struct b43_wldev *dev){ struct ssb_bus *bus = dev->dev->bus; struct b43_phy *phy = &dev->phy; struct b43_rfatt old_rfatt; struct b43_bbatt old_bbatt; u8 old_tx_control = 0; if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) && (bus->boardinfo.type == SSB_BOARD_BU4306)) return; b43_phy_write(dev, 0x0028, 0x8018); /* This does something with the Analog... */ b43_write16(dev, B43_MMIO_PHY0, b43_read16(dev, B43_MMIO_PHY0) & 0xFFDF); if (phy->type == B43_PHYTYPE_G && !phy->gmode) return; b43_hardware_pctl_early_init(dev); if (phy->cur_idle_tssi == 0) { if (phy->radio_ver == 0x2050 && phy->analog == 0) { b43_radio_write16(dev, 0x0076, (b43_radio_read16(dev, 0x0076) & 0x00F7) | 0x0084); } else { struct b43_rfatt rfatt; struct b43_bbatt bbatt; memcpy(&old_rfatt, &phy->rfatt, sizeof(old_rfatt)); memcpy(&old_bbatt, &phy->bbatt, sizeof(old_bbatt)); old_tx_control = phy->tx_control; bbatt.att = 11; if (phy->radio_rev == 8) { rfatt.att = 15; rfatt.with_padmix = 1; } else { rfatt.att = 9; rfatt.with_padmix = 0; } b43_set_txpower_g(dev, &bbatt, &rfatt, 0); } b43_dummy_transmission(dev); phy->cur_idle_tssi = b43_phy_read(dev, B43_PHY_ITSSI); if (B43_DEBUG) { /* Current-Idle-TSSI sanity check. */ if (abs(phy->cur_idle_tssi - phy->tgt_idle_tssi) >= 20) { b43dbg(dev->wl, "!WARNING! Idle-TSSI phy->cur_idle_tssi " "measuring failed. (cur=%d, tgt=%d). Disabling TX power " "adjustment.\n", phy->cur_idle_tssi, phy->tgt_idle_tssi); phy->cur_idle_tssi = 0; } } if (phy->radio_ver == 0x2050 && phy->analog == 0) { b43_radio_write16(dev, 0x0076, b43_radio_read16(dev, 0x0076) & 0xFF7B); } else { b43_set_txpower_g(dev, &old_bbatt, &old_rfatt, old_tx_control); } } b43_hardware_pctl_init(dev); b43_shm_clear_tssi(dev);}static void b43_phy_agcsetup(struct b43_wldev *dev){ struct b43_phy *phy = &dev->phy; u16 offset = 0x0000; if (phy->rev == 1) offset = 0x4C00; b43_ofdmtab_write16(dev, offset, 0, 0x00FE); b43_ofdmtab_write16(dev, offset, 1, 0x000D); b43_ofdmtab_write16(dev, offset, 2, 0x0013); b43_ofdmtab_write16(dev, offset, 3, 0x0019); if (phy->rev == 1) { b43_ofdmtab_write16(dev, 0x1800, 0, 0x2710); b43_ofdmtab_write16(dev, 0x1801, 0, 0x9B83); b43_ofdmtab_write16(dev, 0x1802, 0, 0x9B83); b43_ofdmtab_write16(dev, 0x1803, 0, 0x0F8D); b43_phy_write(dev, 0x0455, 0x0004); } b43_phy_write(dev, 0x04A5, (b43_phy_read(dev, 0x04A5) & 0x00FF) | 0x5700); b43_phy_write(dev, 0x041A, (b43_phy_read(dev, 0x041A) & 0xFF80) | 0x000F); b43_phy_write(dev, 0x041A, (b43_phy_read(dev, 0x041A) & 0xC07F) | 0x2B80); b43_phy_write(dev, 0x048C, (b43_phy_read(dev, 0x048C) & 0xF0FF) | 0x0300); b43_radio_write16(dev, 0x007A, b43_radio_read16(dev, 0x007A) | 0x0008); b43_phy_write(dev, 0x04A0, (b43_phy_read(dev, 0x04A0) & 0xFFF0) | 0x0008); b43_phy_write(dev, 0x04A1, (b43_phy_read(dev, 0x04A1) & 0xF0FF) | 0x0600); b43_phy_write(dev, 0x04A2, (b43_phy_read(dev, 0x04A2) & 0xF0FF) | 0x0700); b43_phy_write(dev, 0x04A0, (b43_phy_read(dev, 0x04A0) & 0xF0FF) | 0x0100); if (phy->rev == 1) { b43_phy_write(dev, 0x04A2, (b43_phy_read(dev, 0x04A2) & 0xFFF0) | 0x0007); } b43_phy_write(dev, 0x0488, (b43_phy_read(dev, 0x0488) & 0xFF00) | 0x001C); b43_phy_write(dev, 0x0488, (b43_phy_read(dev, 0x0488) & 0xC0FF) | 0x0200); b43_phy_write(dev, 0x0496, (b43_phy_read(dev, 0x0496) & 0xFF00) | 0x001C); b43_phy_write(dev, 0x0489, (b43_phy_read(dev, 0x0489) & 0xFF00) | 0x0020); b43_phy_write(dev, 0x0489, (b43_phy_read(dev, 0x0489) & 0xC0FF) | 0x0200); b43_phy_write(dev, 0x0482, (b43_phy_read(dev, 0x0482) & 0xFF00) | 0x002E); b43_phy_write(dev, 0x0496, (b43_phy_read(dev, 0x0496) & 0x00FF) | 0x1A00); b43_phy_write(dev, 0x0481, (b43_phy_read(dev, 0x0481) & 0xFF00) | 0x0028); b43_phy_write(dev, 0x0481, (b43_phy_read(dev, 0x0481) & 0x00FF) | 0x2C00); if (phy->rev == 1) { b43_phy_write(dev, 0x0430, 0x092B); b43_phy_write(dev, 0x041B, (b43_phy_read(dev, 0x041B) & 0xFFE1) | 0x0002); } else { b43_phy_write(dev, 0x041B, b43_phy_read(dev, 0x041B) & 0xFFE1); b43_phy_write(dev, 0x041F, 0x287A); b43_phy_write(dev, 0x0420, (b43_phy_read(dev, 0x0420) & 0xFFF0) | 0x0004); } if (phy->rev >= 6) { b43_phy_write(dev, 0x0422, 0x287A); b43_phy_write(dev, 0x0420, (b43_phy_read(dev, 0x0420) & 0x0FFF) | 0x3000); } b43_phy_write(dev, 0x04A8, (b43_phy_read(dev, 0x04A8) & 0x8080) | 0x7874); b43_phy_write(dev, 0x048E, 0x1C00); offset = 0x0800; if (phy->rev == 1) { offset = 0x5400; b43_phy_write(dev, 0x04AB, (b43_phy_read(dev, 0x04AB) & 0xF0FF) | 0x0600); b43_phy_write(dev, 0x048B, 0x005E); b43_phy_write(dev, 0x048C, (b43_phy_read(dev, 0x048C) & 0xFF00) | 0x001E); b43_phy_write(dev, 0x048D, 0x0002); } b43_ofdmtab_write16(dev, offset, 0, 0x00); b43_ofdmtab_write16(dev, offset, 1, 0x07); b43_ofdmtab_write16(dev, offset, 2, 0x10); b43_ofdmtab_write16(dev, offset, 3, 0x1C); if (phy->rev >= 6) { b43_phy_write(dev, 0x0426, b43_phy_read(dev, 0x0426) & 0xFFFC); b43_phy_write(dev, 0x0426, b43_phy_read(dev, 0x0426) & 0xEFFF); }}static void b43_phy_setupg(struct b43_wldev *dev){ struct ssb_bus *bus = dev->dev->bus; struct b43_phy *phy = &dev->phy; u16 i; B43_WARN_ON(phy->type != B43_PHYTYPE_G); if (phy->rev == 1) { b43_phy_write(dev, 0x0406, 0x4F19); b43_phy_write(dev, B43_PHY_G_CRS, (b43_phy_read(dev, B43_PHY_G_CRS) & 0xFC3F) | 0x0340); b43_phy_write(dev, 0x042C, 0x005A); b43_phy_write(dev, 0x0427, 0x001A); for (i = 0; i < B43_TAB_FINEFREQG_SIZE; i++) b43_ofdmtab_write16(dev, 0x5800, i, b43_tab_finefreqg[i]); for (i = 0; i < B43_TAB_NOISEG1_SIZE; i++) b43_ofdmtab_write16(dev, 0x1800, i, b43_tab_noiseg1[i]); for (i = 0; i < B43_TAB_ROTOR_SIZE; i++) b43_ofdmtab_write16(dev, 0x2000, i, b43_tab_rotor[i]); } else { /* nrssi values are signed 6-bit values. Not sure why we write 0x7654 here... */ b43_nrssi_hw_write(dev, 0xBA98, (s16) 0x7654); if (phy->rev == 2) { b43_phy_write(dev, 0x04C0, 0x1861); b43_phy_write(dev, 0x04C1, 0x0271); } else if (phy->rev > 2) { b43_phy_write(dev, 0x04C0, 0x0098); b43_phy_write(dev, 0x04C1, 0x0070); b43_phy_write(dev, 0x04C9, 0x0080); } b43_phy_write(dev, 0x042B, b43_phy_read(dev, 0x042B) | 0x800); for (i = 0; i < 64; i++) b43_ofdmtab_write16(dev, 0x4000, i, i); for (i = 0; i < B43_TAB_NOISEG2_SIZE; i++) b43_ofdmtab_write16(dev, 0x1800, i, b43_tab_noiseg2[i]); } if (phy->rev <= 2) for (i = 0; i < B43_TAB_NOISESCALEG_SIZE; i++) b43_ofdmtab_write16(dev, 0x1400, i, b43_tab_noisescaleg1[i]); else if ((phy->rev >= 7) && (b43_phy_read(dev, 0x0449) & 0x0200)) for (i = 0; i < B43_TAB_NOISESCALEG_SIZE; i++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -