📄 bcm43xx_radio.c
字号:
#ifdef stack_restore# undef stack_restore#endif#define stack_save(value) \ do { \ assert(i < ARRAY_SIZE(radio->interfstack)); \ stack[i++] = (value); \ } while (0)#define stack_restore() \ ({ \ assert(i < ARRAY_SIZE(radio->interfstack)); \ stack[i++]; \ })static voidbcm43xx_radio_interference_mitigation_enable(struct bcm43xx_private *bcm, int mode){ struct bcm43xx_phyinfo *phy = bcm->current_core->phy; struct bcm43xx_radioinfo *radio = bcm->current_core->radio; int i = 0; u16 *stack = radio->interfstack; u16 tmp, flipped; switch (mode) { case BCM43xx_RADIO_INTERFMODE_NONWLAN: if (phy->rev != 1) { bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) & 0x0800); bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & ~0x4000); break; } tmp = (bcm43xx_radio_read16(bcm, 0x0078) & 0x001E); flipped = flip_4bit(tmp); if ((flipped >> 1) >= 4) tmp = flipped - 3; tmp = flip_4bit(tmp); bcm43xx_radio_write16(bcm, 0x0078, tmp << 1); bcm43xx_calc_nrssi_threshold(bcm); if (bcm->current_core->rev < 5) { stack_save(bcm43xx_phy_read(bcm, 0x0406)); bcm43xx_phy_write(bcm, 0x0406, 0x7E28); } else { stack_save(bcm43xx_phy_read(bcm, 0x04C0)); stack_save(bcm43xx_phy_read(bcm, 0x04C1)); bcm43xx_phy_write(bcm, 0x04C0, 0x3E04); bcm43xx_phy_write(bcm, 0x04C1, 0x0640); } bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) | 0x0800); bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | 0x1000); stack_save(bcm43xx_phy_read(bcm, 0x04A0)); bcm43xx_phy_write(bcm, 0x04A0, (bcm43xx_phy_read(bcm, 0x04A0) & 0xC0C0) | 0x0008); stack_save(bcm43xx_phy_read(bcm, 0x04A1)); bcm43xx_phy_write(bcm, 0x04A1, (bcm43xx_phy_read(bcm, 0x04A1) & 0xC0C0) | 0x0605); stack_save(bcm43xx_phy_read(bcm, 0x04A2)); bcm43xx_phy_write(bcm, 0x04A2, (bcm43xx_phy_read(bcm, 0x04A2) & 0xC0C0) | 0x0204); stack_save(bcm43xx_phy_read(bcm, 0x04A8)); bcm43xx_phy_write(bcm, 0x04A8, (bcm43xx_phy_read(bcm, 0x04A8) & 0xC0C0) | 0x0403); stack_save(bcm43xx_phy_read(bcm, 0x04AB)); bcm43xx_phy_write(bcm, 0x04AB, (bcm43xx_phy_read(bcm, 0x04AB) & 0xC0C0) | 0x0504); stack_save(bcm43xx_phy_read(bcm, 0x04A7)); bcm43xx_phy_write(bcm, 0x04A7, 0x0002); stack_save(bcm43xx_phy_read(bcm, 0x04A3)); bcm43xx_phy_write(bcm, 0x04A3, 0x287A); stack_save(bcm43xx_phy_read(bcm, 0x04A9)); bcm43xx_phy_write(bcm, 0x04A9, 0x2027); stack_save(bcm43xx_phy_read(bcm, 0x0493)); bcm43xx_phy_write(bcm, 0x0493, 0x32F5); stack_save(bcm43xx_phy_read(bcm, 0x04AA)); bcm43xx_phy_write(bcm, 0x04AA, 0x2027); stack_save(bcm43xx_phy_read(bcm, 0x04AC)); bcm43xx_phy_write(bcm, 0x04AC, 0x32F5); break; case BCM43xx_RADIO_INTERFMODE_MANUALWLAN: if (bcm43xx_phy_read(bcm, 0x0033) == 0x0800) break; radio->aci_enable = 1; stack_save(bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD)); stack_save(bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS)); if (bcm->current_core->rev < 5) { stack_save(bcm43xx_phy_read(bcm, 0x0406)); } else { stack_save(bcm43xx_phy_read(bcm, 0x04C0)); stack_save(bcm43xx_phy_read(bcm, 0x04C1)); } stack_save(bcm43xx_phy_read(bcm, 0x0033)); stack_save(bcm43xx_phy_read(bcm, 0x04A7)); stack_save(bcm43xx_phy_read(bcm, 0x04A3)); stack_save(bcm43xx_phy_read(bcm, 0x04A9)); stack_save(bcm43xx_phy_read(bcm, 0x04AA)); stack_save(bcm43xx_phy_read(bcm, 0x04AC)); stack_save(bcm43xx_phy_read(bcm, 0x0493)); stack_save(bcm43xx_phy_read(bcm, 0x04A1)); stack_save(bcm43xx_phy_read(bcm, 0x04A0)); stack_save(bcm43xx_phy_read(bcm, 0x04A2)); stack_save(bcm43xx_phy_read(bcm, 0x048A)); stack_save(bcm43xx_phy_read(bcm, 0x04A8)); stack_save(bcm43xx_phy_read(bcm, 0x04AB)); bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) & 0xEFFF); bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0xEFFF) | 0x0002); bcm43xx_phy_write(bcm, 0x04A7, 0x0800); bcm43xx_phy_write(bcm, 0x04A3, 0x287A); bcm43xx_phy_write(bcm, 0x04A9, 0x2027); bcm43xx_phy_write(bcm, 0x0493, 0x32F5); bcm43xx_phy_write(bcm, 0x04AA, 0x2027); bcm43xx_phy_write(bcm, 0x04AC, 0x32F5); bcm43xx_phy_write(bcm, 0x04A0, (bcm43xx_phy_read(bcm, 0x04A0) & 0xFFC0) | 0x001A); if (bcm->current_core->rev < 5) { bcm43xx_phy_write(bcm, 0x0406, 0x280D); } else { bcm43xx_phy_write(bcm, 0x04C0, 0x0640); bcm43xx_phy_write(bcm, 0x04C1, 0x00A9); } bcm43xx_phy_write(bcm, 0x04A1, (bcm43xx_phy_read(bcm, 0x04A1) & 0xC0FF) | 0x1800); bcm43xx_phy_write(bcm, 0x04A1, (bcm43xx_phy_read(bcm, 0x04A1) & 0xFFC0) | 0x0016); bcm43xx_phy_write(bcm, 0x04A2, (bcm43xx_phy_read(bcm, 0x04A2) & 0xF0FF) | 0x0900); bcm43xx_phy_write(bcm, 0x04A0, (bcm43xx_phy_read(bcm, 0x04A0) & 0xF0FF) | 0x0700); bcm43xx_phy_write(bcm, 0x04A2, (bcm43xx_phy_read(bcm, 0x04A2) & 0xFFF0) | 0x000D); bcm43xx_phy_write(bcm, 0x04A8, (bcm43xx_phy_read(bcm, 0x04A8) & 0xCFFF) | 0x1000); bcm43xx_phy_write(bcm, 0x04A8, (bcm43xx_phy_read(bcm, 0x04A8) & 0xF0FF) | 0x0A00); bcm43xx_phy_write(bcm, 0x04AB, (bcm43xx_phy_read(bcm, 0x04AB) & 0xCFFF) | 0x1000); bcm43xx_phy_write(bcm, 0x04AB, (bcm43xx_phy_read(bcm, 0x04AB) & 0xF0FF) | 0x0800); bcm43xx_phy_write(bcm, 0x04AB, (bcm43xx_phy_read(bcm, 0x04AB) & 0xFFCF) | 0x0010); bcm43xx_phy_write(bcm, 0x04AB, (bcm43xx_phy_read(bcm, 0x04AB) & 0xFFF0) | 0x0006); bcm43xx_calc_nrssi_slope(bcm); break; default: assert(0); }}static voidbcm43xx_radio_interference_mitigation_disable(struct bcm43xx_private *bcm, int mode){ struct bcm43xx_phyinfo *phy = bcm->current_core->phy; struct bcm43xx_radioinfo *radio = bcm->current_core->radio; int i = 0; u16 *stack = radio->interfstack; u16 tmp, flipped; switch (mode) { case BCM43xx_RADIO_INTERFMODE_NONWLAN: if (phy->rev != 1) { bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) & ~0x0800); bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x4000); break; } tmp = (bcm43xx_radio_read16(bcm, 0x0078) & 0x001E); flipped = flip_4bit(tmp); if ((flipped >> 1) >= 0x000C) tmp = flipped + 3; tmp = flip_4bit(tmp); bcm43xx_radio_write16(bcm, 0x0078, tmp << 1); bcm43xx_calc_nrssi_threshold(bcm); if (bcm->current_core->rev < 5) { bcm43xx_phy_write(bcm, 0x0406, stack_restore()); } else { bcm43xx_phy_write(bcm, 0x04C0, stack_restore()); bcm43xx_phy_write(bcm, 0x04C1, stack_restore()); } bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) & ~0x0800); if (!bcm->bad_frames_preempt) bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) & ~(1 << 11)); bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x4000); bcm43xx_phy_write(bcm, 0x04A0, stack_restore()); bcm43xx_phy_write(bcm, 0x04A1, stack_restore()); bcm43xx_phy_write(bcm, 0x04A2, stack_restore()); bcm43xx_phy_write(bcm, 0x04A8, stack_restore()); bcm43xx_phy_write(bcm, 0x04AB, stack_restore()); bcm43xx_phy_write(bcm, 0x04A7, stack_restore()); bcm43xx_phy_write(bcm, 0x04A3, stack_restore()); bcm43xx_phy_write(bcm, 0x04A9, stack_restore()); bcm43xx_phy_write(bcm, 0x0493, stack_restore()); bcm43xx_phy_write(bcm, 0x04AA, stack_restore()); bcm43xx_phy_write(bcm, 0x04AC, stack_restore()); break; case BCM43xx_RADIO_INTERFMODE_MANUALWLAN: if (bcm43xx_phy_read(bcm, 0x0033) != 0x0800) break; radio->aci_enable = 0; bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, stack_restore()); bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, stack_restore()); if (bcm->current_core->rev < 5) { bcm43xx_phy_write(bcm, 0x0406, stack_restore()); } else { bcm43xx_phy_write(bcm, 0x04C0, stack_restore()); bcm43xx_phy_write(bcm, 0x04C1, stack_restore()); } bcm43xx_phy_write(bcm, 0x0033, stack_restore()); bcm43xx_phy_write(bcm, 0x04A7, stack_restore()); bcm43xx_phy_write(bcm, 0x04A3, stack_restore()); bcm43xx_phy_write(bcm, 0x04A9, stack_restore()); bcm43xx_phy_write(bcm, 0x04AA, stack_restore()); bcm43xx_phy_write(bcm, 0x04AC, stack_restore()); bcm43xx_phy_write(bcm, 0x0493, stack_restore()); bcm43xx_phy_write(bcm, 0x04A1, stack_restore()); bcm43xx_phy_write(bcm, 0x04A0, stack_restore()); bcm43xx_phy_write(bcm, 0x04A2, stack_restore()); bcm43xx_phy_write(bcm, 0x04A8, stack_restore()); bcm43xx_phy_write(bcm, 0x04AB, stack_restore()); bcm43xx_calc_nrssi_slope(bcm); break; default: assert(0); }}#undef stack_save#undef stack_restoreint bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm, int mode){ struct bcm43xx_phyinfo *phy = bcm->current_core->phy; struct bcm43xx_radioinfo *radio = bcm->current_core->radio; int currentmode; if ((phy->type != BCM43xx_PHYTYPE_G) || (phy->rev == 0) || (!phy->connected)) return -ENODEV; radio->aci_wlan_automatic = 0; switch (mode) { case BCM43xx_RADIO_INTERFMODE_AUTOWLAN: radio->aci_wlan_automatic = 1; if (radio->aci_enable) mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN; else mode = BCM43xx_RADIO_INTERFMODE_NONE; break; case BCM43xx_RADIO_INTERFMODE_NONE: case BCM43xx_RADIO_INTERFMODE_NONWLAN: case BCM43xx_RADIO_INTERFMODE_MANUALWLAN: break; default: return -EINVAL; } currentmode = radio->interfmode; if (currentmode == mode) return 0; if (currentmode != BCM43xx_RADIO_INTERFMODE_NONE) bcm43xx_radio_interference_mitigation_disable(bcm, currentmode); if (mode == BCM43xx_RADIO_INTERFMODE_NONE) { radio->aci_enable = 0; radio->aci_hw_rssi = 0; } else bcm43xx_radio_interference_mitigation_enable(bcm, mode); radio->interfmode = mode; return 0;}u16 bcm43xx_radio_calibrationvalue(struct bcm43xx_private *bcm){ u16 reg, index, ret; reg = bcm43xx_radio_read16(bcm, 0x0060); index = (reg & 0x001E) >> 1; ret = rcc_table[index] << 1; ret |= (reg & 0x0001); ret |= 0x0020; return ret;}u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm){ struct bcm43xx_phyinfo *phy = bcm->current_core->phy; struct bcm43xx_radioinfo *radio = bcm->current_core->radio; u16 backup[19] = { 0 }; u16 ret; u16 i, j; u32 tmp1 = 0, tmp2 = 0; backup[0] = bcm43xx_radio_read16(bcm, 0x0043); backup[14] = bcm43xx_radio_read16(bcm, 0x0051); backup[15] = bcm43xx_radio_read16(bcm, 0x0052); backup[1] = bcm43xx_phy_read(bcm, 0x0015); backup[16] = bcm43xx_phy_read(bcm, 0x005A); backup[17] = bcm43xx_phy_read(bcm, 0x0059); backup[18] = bcm43xx_phy_read(bcm, 0x0058); if (phy->type == BCM43xx_PHYTYPE_B) { backup[2] = bcm43xx_phy_read(bcm, 0x0030); backup[3] = bcm43xx_read16(bcm, 0x03EC); bcm43xx_phy_write(bcm, 0x0030, 0x00FF); bcm43xx_write16(bcm, 0x03EC, 0x3F3F); } else { if (phy->connected) { backup[4] = bcm43xx_phy_read(bcm, 0x0811); backup[5] = bcm43xx_phy_read(bcm, 0x0812); backup[6] = bcm43xx_phy_read(bcm, 0x0814); backup[7] = bcm43xx_phy_read(bcm, 0x0815); backup[8] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS); backup[9] = bcm43xx_phy_read(bcm, 0x0802); bcm43xx_phy_write(bcm, 0x0814, (bcm43xx_phy_read(bcm, 0x0814) | 0x0003)); bcm43xx_phy_write(bcm, 0x0815, (bcm43xx_phy_read(bcm, 0x0815) & 0xFFFC)); bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x7FFF)); bcm43xx_phy_write(bcm, 0x0802, (bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC)); bcm43xx_phy_write(bcm, 0x0811, 0x01B3); bcm43xx_phy_write(bcm, 0x0812, 0x0FB2); } bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO, (bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_RADIO) | 0x8000)); } backup[10] = bcm43xx_phy_read(bcm, 0x0035); bcm43xx_phy_write(bcm, 0x0035, (bcm43xx_phy_read(bcm, 0x0035) & 0xFF7F)); backup[11] = bcm43xx_read16(bcm, 0x03E6); backup[12] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT); // Initialization if (phy->version == 0) { bcm43xx_write16(bcm, 0x03E6, 0x0122); } else { if (phy->version >= 2) bcm43xx_write16(bcm, 0x03E6, 0x0040); bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, (bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) | 0x2000)); } ret = bcm43xx_radio_calibrationvalue(bcm); if (phy->type == BCM43xx_PHYTYPE_B) bcm43xx_radio_write16(bcm, 0x0078, 0x0003); bcm43xx_phy_write(bcm, 0x0015, 0xBFAF); bcm43xx_phy_write(bcm, 0x002B, 0x1403); if (phy->connected) bcm43xx_phy_write(bcm, 0x0812, 0x00B2); bcm43xx_phy_write(bcm, 0x0015, 0xBFA0); bcm43xx_radio_write16(bcm, 0x0051, (bcm43xx_radio_read16(bcm, 0x0051) | 0x0004)); bcm43xx_radio_write16(bcm, 0x0052, 0x0000); bcm43xx_radio_write16(bcm, 0x0043, bcm43xx_radio_read16(bcm, 0x0043) | 0x0009); bcm43xx_phy_write(bcm, 0x0058, 0x0000); for (i = 0; i < 16; i++) { bcm43xx_phy_write(bcm, 0x005A, 0x0480); bcm43xx_phy_write(bcm, 0x0059, 0xC810); bcm43xx_phy_write(bcm, 0x0058, 0x000D); if (phy->connected) bcm43xx_phy_write(bcm, 0x0812, 0x30B2); bcm43xx_phy_write(bcm, 0x0015, 0xAFB0); udelay(10); if (phy->connected) bcm43xx_phy_write(bcm, 0x0812, 0x30B2); bcm43xx_phy_write(bcm, 0x0015, 0xEFB0); udelay(10); if (phy->connected) bcm43xx_phy_write(bcm, 0x0812, 0x30B2); bcm43xx_phy_write(bcm, 0x0015, 0xFFF0); udelay(10); tmp1 += bcm43xx_phy_read(bcm, 0x002D); bcm43xx_phy_write(bcm, 0x0058, 0x0000); if (phy->connected) bcm43xx_phy_write(bcm, 0x0812, 0x30B2); bcm43xx_phy_write(bcm, 0x0015, 0xAFB0); } tmp1++; tmp1 >>= 9; udelay(10); bcm43xx_phy_write(bcm, 0x0058, 0x0000); for (i = 0; i < 16; i++) { bcm43xx_radio_write16(bcm, 0x0078, (flip_4bit(i) << 1) | 0x0020); backup[13] = bcm43xx_radio_read16(bcm, 0x0078); udelay(10); for (j = 0; j < 16; j++) { bcm43xx_phy_write(bcm, 0x005A, 0x0D80); bcm43xx_phy_write(bcm, 0x0059, 0xC810); bcm43xx_phy_write(bcm, 0x0058, 0x000D); if (phy->connected) bcm43xx_phy_write(bcm, 0x0812, 0x30B2); bcm43xx_phy_write(bcm, 0x0015, 0xAFB0); udelay(10); if (phy->connected) bcm43xx_phy_write(bcm, 0x0812, 0x30B2); bcm43xx_phy_write(bcm, 0x0015, 0xEFB0); udelay(10); if (phy->connected) bcm43xx_phy_write(bcm, 0x0812, 0x30B3); /* 0x30B3 is not a typo */ bcm43xx_phy_write(bcm, 0x0015, 0xFFF0); udelay(10); tmp2 += bcm43xx_phy_read(bcm, 0x002D); bcm43xx_phy_write(bcm, 0x0058, 0x0000); if (phy->connected)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -