📄 bcm43xx_radio.c
字号:
bcm43xx_phy_write(bcm, 0x0814, backup[3]); bcm43xx_phy_write(bcm, 0x0815, backup[4]); bcm43xx_phy_write(bcm, 0x005A, backup[5]); bcm43xx_phy_write(bcm, 0x0059, backup[6]); bcm43xx_phy_write(bcm, 0x0058, backup[7]); bcm43xx_phy_write(bcm, 0x000A, backup[8]); bcm43xx_phy_write(bcm, 0x0003, backup[9]); bcm43xx_radio_write16(bcm, 0x0043, backup[11]); bcm43xx_radio_write16(bcm, 0x007A, backup[10]); bcm43xx_phy_write(bcm, 0x0802, bcm43xx_phy_read(bcm, 0x0802) | 0x1 | 0x2); bcm43xx_phy_write(bcm, 0x0429, bcm43xx_phy_read(bcm, 0x0429) | 0x8000); bcm43xx_set_original_gains(bcm); if (phy->rev >= 6) { bcm43xx_phy_write(bcm, 0x0801, backup[16]); bcm43xx_phy_write(bcm, 0x0060, backup[17]); bcm43xx_phy_write(bcm, 0x0014, backup[18]); bcm43xx_phy_write(bcm, 0x0478, backup[19]); } bcm43xx_phy_write(bcm, 0x0001, backup[0]); bcm43xx_phy_write(bcm, 0x0812, backup[2]); bcm43xx_phy_write(bcm, 0x0811, backup[1]);}void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm){ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 backup[18] = { 0 }; u16 tmp; s16 nrssi0, nrssi1; switch (phy->type) { case BCM43xx_PHYTYPE_B: backup[0] = bcm43xx_radio_read16(bcm, 0x007A); backup[1] = bcm43xx_radio_read16(bcm, 0x0052); backup[2] = bcm43xx_radio_read16(bcm, 0x0043); backup[3] = bcm43xx_phy_read(bcm, 0x0030); backup[4] = bcm43xx_phy_read(bcm, 0x0026); backup[5] = bcm43xx_phy_read(bcm, 0x0015); backup[6] = bcm43xx_phy_read(bcm, 0x002A); backup[7] = bcm43xx_phy_read(bcm, 0x0020); backup[8] = bcm43xx_phy_read(bcm, 0x005A); backup[9] = bcm43xx_phy_read(bcm, 0x0059); backup[10] = bcm43xx_phy_read(bcm, 0x0058); backup[11] = bcm43xx_read16(bcm, 0x03E2); backup[12] = bcm43xx_read16(bcm, 0x03E6); backup[13] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT); tmp = bcm43xx_radio_read16(bcm, 0x007A); tmp &= (phy->rev >= 5) ? 0x007F : 0x000F; bcm43xx_radio_write16(bcm, 0x007A, tmp); bcm43xx_phy_write(bcm, 0x0030, 0x00FF); bcm43xx_write16(bcm, 0x03EC, 0x7F7F); bcm43xx_phy_write(bcm, 0x0026, 0x0000); bcm43xx_phy_write(bcm, 0x0015, bcm43xx_phy_read(bcm, 0x0015) | 0x0020); bcm43xx_phy_write(bcm, 0x002A, 0x08A3); bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) | 0x0080); nrssi0 = (s16)bcm43xx_phy_read(bcm, 0x0027); bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) & 0x007F); if (phy->analog >= 2) { bcm43xx_write16(bcm, 0x03E6, 0x0040); } else if (phy->analog == 0) { bcm43xx_write16(bcm, 0x03E6, 0x0122); } else { bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) & 0x2000); } bcm43xx_phy_write(bcm, 0x0020, 0x3F3F); bcm43xx_phy_write(bcm, 0x0015, 0xF330); bcm43xx_radio_write16(bcm, 0x005A, 0x0060); bcm43xx_radio_write16(bcm, 0x0043, bcm43xx_radio_read16(bcm, 0x0043) & 0x00F0); bcm43xx_phy_write(bcm, 0x005A, 0x0480); bcm43xx_phy_write(bcm, 0x0059, 0x0810); bcm43xx_phy_write(bcm, 0x0058, 0x000D); udelay(20); nrssi1 = (s16)bcm43xx_phy_read(bcm, 0x0027); bcm43xx_phy_write(bcm, 0x0030, backup[3]); bcm43xx_radio_write16(bcm, 0x007A, backup[0]); bcm43xx_write16(bcm, 0x03E2, backup[11]); bcm43xx_phy_write(bcm, 0x0026, backup[4]); bcm43xx_phy_write(bcm, 0x0015, backup[5]); bcm43xx_phy_write(bcm, 0x002A, backup[6]); bcm43xx_synth_pu_workaround(bcm, radio->channel); if (phy->analog != 0) bcm43xx_write16(bcm, 0x03F4, backup[13]); bcm43xx_phy_write(bcm, 0x0020, backup[7]); bcm43xx_phy_write(bcm, 0x005A, backup[8]); bcm43xx_phy_write(bcm, 0x0059, backup[9]); bcm43xx_phy_write(bcm, 0x0058, backup[10]); bcm43xx_radio_write16(bcm, 0x0052, backup[1]); bcm43xx_radio_write16(bcm, 0x0043, backup[2]); if (nrssi0 == nrssi1) radio->nrssislope = 0x00010000; else radio->nrssislope = 0x00400000 / (nrssi0 - nrssi1); if (nrssi0 <= -4) { radio->nrssi[0] = nrssi0; radio->nrssi[1] = nrssi1; } break; case BCM43xx_PHYTYPE_G: if (radio->revision >= 9) return; if (radio->revision == 8) bcm43xx_calc_nrssi_offset(bcm); 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); backup[7] = bcm43xx_read16(bcm, 0x03E2); bcm43xx_write16(bcm, 0x03E2, bcm43xx_read16(bcm, 0x03E2) | 0x8000); backup[0] = bcm43xx_radio_read16(bcm, 0x007A); backup[1] = bcm43xx_radio_read16(bcm, 0x0052); backup[2] = bcm43xx_radio_read16(bcm, 0x0043); backup[3] = bcm43xx_phy_read(bcm, 0x0015); backup[4] = bcm43xx_phy_read(bcm, 0x005A); backup[5] = bcm43xx_phy_read(bcm, 0x0059); backup[6] = bcm43xx_phy_read(bcm, 0x0058); backup[8] = bcm43xx_read16(bcm, 0x03E6); backup[9] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT); if (phy->rev >= 3) { backup[10] = bcm43xx_phy_read(bcm, 0x002E); backup[11] = bcm43xx_phy_read(bcm, 0x002F); backup[12] = bcm43xx_phy_read(bcm, 0x080F); backup[13] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_LO_CONTROL); backup[14] = bcm43xx_phy_read(bcm, 0x0801); backup[15] = bcm43xx_phy_read(bcm, 0x0060); backup[16] = bcm43xx_phy_read(bcm, 0x0014); backup[17] = bcm43xx_phy_read(bcm, 0x0478); bcm43xx_phy_write(bcm, 0x002E, 0); bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, 0); switch (phy->rev) { case 4: case 6: case 7: bcm43xx_phy_write(bcm, 0x0478, bcm43xx_phy_read(bcm, 0x0478) | 0x0100); bcm43xx_phy_write(bcm, 0x0801, bcm43xx_phy_read(bcm, 0x0801) | 0x0040); break; case 3: case 5: bcm43xx_phy_write(bcm, 0x0801, bcm43xx_phy_read(bcm, 0x0801) & 0xFFBF); break; } bcm43xx_phy_write(bcm, 0x0060, bcm43xx_phy_read(bcm, 0x0060) | 0x0040); bcm43xx_phy_write(bcm, 0x0014, bcm43xx_phy_read(bcm, 0x0014) | 0x0200); } bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) | 0x0070); bcm43xx_set_all_gains(bcm, 0, 8, 0); bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) & 0x00F7); if (phy->rev >= 2) { bcm43xx_phy_write(bcm, 0x0811, (bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF) | 0x0030); bcm43xx_phy_write(bcm, 0x0812, (bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF) | 0x0010); } bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) | 0x0080); udelay(20); nrssi0 = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F); if (nrssi0 >= 0x0020) nrssi0 -= 0x0040; bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) & 0x007F); if (phy->analog >= 2) { bcm43xx_phy_write(bcm, 0x0003, (bcm43xx_phy_read(bcm, 0x0003) & 0xFF9F) | 0x0040); } bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) | 0x2000); bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) | 0x000F); bcm43xx_phy_write(bcm, 0x0015, 0xF330); if (phy->rev >= 2) { bcm43xx_phy_write(bcm, 0x0812, (bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF) | 0x0020); bcm43xx_phy_write(bcm, 0x0811, (bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF) | 0x0020); } bcm43xx_set_all_gains(bcm, 3, 0, 1); if (radio->revision == 8) { bcm43xx_radio_write16(bcm, 0x0043, 0x001F); } else { tmp = bcm43xx_radio_read16(bcm, 0x0052) & 0xFF0F; bcm43xx_radio_write16(bcm, 0x0052, tmp | 0x0060); tmp = bcm43xx_radio_read16(bcm, 0x0043) & 0xFFF0; bcm43xx_radio_write16(bcm, 0x0043, tmp | 0x0009); } bcm43xx_phy_write(bcm, 0x005A, 0x0480); bcm43xx_phy_write(bcm, 0x0059, 0x0810); bcm43xx_phy_write(bcm, 0x0058, 0x000D); udelay(20); nrssi1 = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F); if (nrssi1 >= 0x0020) nrssi1 -= 0x0040; if (nrssi0 == nrssi1) radio->nrssislope = 0x00010000; else radio->nrssislope = 0x00400000 / (nrssi0 - nrssi1); if (nrssi0 >= -4) { radio->nrssi[0] = nrssi1; radio->nrssi[1] = nrssi0; } if (phy->rev >= 3) { bcm43xx_phy_write(bcm, 0x002E, backup[10]); bcm43xx_phy_write(bcm, 0x002F, backup[11]); bcm43xx_phy_write(bcm, 0x080F, backup[12]); bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, backup[13]); } if (phy->rev >= 2) { bcm43xx_phy_write(bcm, 0x0812, bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF); bcm43xx_phy_write(bcm, 0x0811, bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF); } bcm43xx_radio_write16(bcm, 0x007A, backup[0]); bcm43xx_radio_write16(bcm, 0x0052, backup[1]); bcm43xx_radio_write16(bcm, 0x0043, backup[2]); bcm43xx_write16(bcm, 0x03E2, backup[7]); bcm43xx_write16(bcm, 0x03E6, backup[8]); bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, backup[9]); bcm43xx_phy_write(bcm, 0x0015, backup[3]); bcm43xx_phy_write(bcm, 0x005A, backup[4]); bcm43xx_phy_write(bcm, 0x0059, backup[5]); bcm43xx_phy_write(bcm, 0x0058, backup[6]); bcm43xx_synth_pu_workaround(bcm, radio->channel); bcm43xx_phy_write(bcm, 0x0802, bcm43xx_phy_read(bcm, 0x0802) | (0x0001 | 0x0002)); bcm43xx_set_original_gains(bcm); bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x8000); if (phy->rev >= 3) { bcm43xx_phy_write(bcm, 0x0801, backup[14]); bcm43xx_phy_write(bcm, 0x0060, backup[15]); bcm43xx_phy_write(bcm, 0x0014, backup[16]); bcm43xx_phy_write(bcm, 0x0478, backup[17]); } bcm43xx_nrssi_mem_update(bcm); bcm43xx_calc_nrssi_threshold(bcm); break; default: assert(0); }}void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm){ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); s32 threshold; s32 a, b; s16 tmp16; u16 tmp_u16; switch (phy->type) { case BCM43xx_PHYTYPE_B: { if (radio->version != 0x2050) return; if (!(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) return; if (radio->revision >= 6) { threshold = (radio->nrssi[1] - radio->nrssi[0]) * 32; threshold += 20 * (radio->nrssi[0] + 1); threshold /= 40; } else threshold = radio->nrssi[1] - 5; threshold = limit_value(threshold, 0, 0x3E); bcm43xx_phy_read(bcm, 0x0020); /* dummy read */ bcm43xx_phy_write(bcm, 0x0020, (((u16)threshold) << 8) | 0x001C); if (radio->revision >= 6) { bcm43xx_phy_write(bcm, 0x0087, 0x0E0D); bcm43xx_phy_write(bcm, 0x0086, 0x0C0B); bcm43xx_phy_write(bcm, 0x0085, 0x0A09); bcm43xx_phy_write(bcm, 0x0084, 0x0808); bcm43xx_phy_write(bcm, 0x0083, 0x0808); bcm43xx_phy_write(bcm, 0x0082, 0x0604); bcm43xx_phy_write(bcm, 0x0081, 0x0302); bcm43xx_phy_write(bcm, 0x0080, 0x0100); } break; } case BCM43xx_PHYTYPE_G: if (!phy->connected || !(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) { tmp16 = bcm43xx_nrssi_hw_read(bcm, 0x20); if (tmp16 >= 0x20) tmp16 -= 0x40; if (tmp16 < 3) { bcm43xx_phy_write(bcm, 0x048A, (bcm43xx_phy_read(bcm, 0x048A) & 0xF000) | 0x09EB); } else { bcm43xx_phy_write(bcm, 0x048A, (bcm43xx_phy_read(bcm, 0x048A) & 0xF000) | 0x0AED); } } else { if (radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN) { a = 0xE; b = 0xA; } else if (!radio->aci_wlan_automatic && radio->aci_enable) { a = 0x13; b = 0x12; } else { a = 0xE; b = 0x11; } a = a * (radio->nrssi[1] - radio->nrssi[0]); a += (radio->nrssi[0] << 6); if (a < 32) a += 31; else a += 32; a = a >> 6; a = limit_value(a, -31, 31); b = b * (radio->nrssi[1] - radio->nrssi[0]); b += (radio->nrssi[0] << 6); if (b < 32) b += 31; else b += 32; b = b >> 6; b = limit_value(b, -31, 31); tmp_u16 = bcm43xx_phy_read(bcm, 0x048A) & 0xF000; tmp_u16 |= ((u32)b & 0x0000003F); tmp_u16 |= (((u32)a & 0x0000003F) << 6); bcm43xx_phy_write(bcm, 0x048A, tmp_u16); } break; default: assert(0); }}/* Stack implementation to save/restore values from the * interference mitigation code. * It is save to restore values in random order. */static void _stack_save(u32 *_stackptr, size_t *stackidx, u8 id, u16 offset, u16 value){ u32 *stackptr = &(_stackptr[*stackidx]); assert((offset & 0xE000) == 0x0000); assert((id & 0xF8) == 0x00); *stackptr = offset; *stackptr |= ((u32)id) << 13; *stackptr |= ((u32)value) << 16; (*stackidx)++; assert(*stackidx < BCM43xx_INTERFSTACK_SIZE);}static u16 _stack_restore(u32 *stackptr, u8 id, u16 offset){ size_t i; assert((offset & 0xE000) == 0x0000); assert((id & 0xF8) == 0x00); for (i = 0; i < BCM43xx_INTERFSTACK_SIZE; i++, stackptr++) { if ((*stackptr & 0x00001FFF) != offset) continue; if (((*stackptr & 0x00007000) >> 13) != id) continue; return ((*stackptr & 0xFFFF0000) >> 16); } assert(0); return 0;}#define phy_stacksave(offset) \ do { \ _stack_save(stack, &stackidx, 0x1, (offset), \ bcm43xx_phy_read(bcm, (offset))); \ } while (0)#define phy_stackrestore(offset) \ do { \ bcm43xx_phy_write(bcm, (offset), \ _stack_restore(stack, 0x1, \ (offset))); \ } while (0)#define radio_stacksave(offset) \ do { \ _stack_save(stack, &stackidx, 0x2, (offset), \ bcm43xx_radio_read16(bcm, (offset))); \ } while (0)#define radio_stackrestore(offset) \ do { \ bcm43xx_radio_write16(bcm, (offset), \ _stack_restore(stack, 0x2, \ (offset))); \ } while (0)#define ilt_stacksave(offset) \ do { \ _stack_save(stack, &stackidx, 0x3, (offset), \ bcm43xx_ilt_read(bcm, (offset))); \ } while (0)#define ilt_stackrestore(offset) \ do { \ bcm43xx_ilt_write(bcm, (offset), \ _stack_restore(stack, 0x3, \ (offset))); \ } while (0)static voidbcm43xx_radio_interference_mitigation_enable(struct bcm43xx_private *bcm, int mode){ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 tmp, flipped; u32 tmp32; size_t stackidx = 0; u32 *stack = radio->interfstack; 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; } radio_stacksave(0x0078); tmp = (bcm43xx_radio_read16(bcm, 0x0078) & 0x001E); flipped = flip_4bit(tmp); if (flipped < 10 && flipped >= 8) flipped = 7; else if (flipped >= 10) flipped -= 3; flipped = flip_4bit(flipped); flipped = (flipped << 1) | 0x0020; bcm43xx_radio_write16(bcm, 0x0078, flipped); bcm43xx_calc_nrssi_threshold(bcm); phy_stacksave(0x0406); bcm43xx_phy_write(bcm, 0x0406, 0x7E28); 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); phy_stacksave(0x04A0); bcm43xx_phy_write(bcm, 0x04A0, (bcm43xx_phy_read(bcm, 0x04A0) & 0xC0C0) | 0x0008); phy_stacksave(0x04A1); bcm43xx_phy_write(bcm, 0x04A1, (bcm43xx_phy_read(bcm, 0x04A1) & 0xC0C0) | 0x0605); phy_stacksave(0x04A2); bcm43xx_phy_write(bcm, 0x04A2, (bcm43xx_phy_read(bcm, 0x04A2) & 0xC0C0) | 0x0204); phy_stacksave(0x04A8); bcm43xx_phy_write(bcm, 0x04A8, (bcm43xx_phy_read(bcm, 0x04A8) & 0xC0C0) | 0x0803); phy_stacksave(0x04AB); bcm43xx_phy_write(bcm, 0x04AB, (bcm43xx_phy_read(bcm, 0x04AB) & 0xC0C0) | 0x0605); phy_stacksave(0x04A7); bcm43xx_phy_write(bcm, 0x04A7, 0x0002); phy_stacksave(0x04A3); bcm43xx_phy_write(bcm, 0x04A3, 0x287A); phy_stacksave(0x04A9); bcm43xx_phy_write(bcm, 0x04A9, 0x2027); phy_stacksave(0x0493); bcm43xx_phy_write(bcm, 0x0493, 0x32F5); phy_stacksave(0x04AA); bcm43xx_phy_write(bcm, 0x04AA, 0x2027); phy_stacksave(0x04AC);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -