📄 bcm43xx_radio.c
字号:
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;}#define LPD(L, P, D) (((L) << 2) | ((P) << 1) | ((D) << 0))static u16 bcm43xx_get_812_value(struct bcm43xx_private *bcm, u8 lpd){ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 loop_or = 0; u16 adj_loopback_gain = phy->loopback_gain[0]; u8 loop; u16 extern_lna_control; if (!phy->connected) return 0; if (!has_loopback_gain(phy)) { if (phy->rev < 7 || !(bcm->sprom.boardflags & BCM43xx_BFL_EXTLNA)) { switch (lpd) { case LPD(0, 1, 1): return 0x0FB2; case LPD(0, 0, 1): return 0x00B2; case LPD(1, 0, 1): return 0x30B2; case LPD(1, 0, 0): return 0x30B3; default: assert(0); } } else { switch (lpd) { case LPD(0, 1, 1): return 0x8FB2; case LPD(0, 0, 1): return 0x80B2; case LPD(1, 0, 1): return 0x20B2; case LPD(1, 0, 0): return 0x20B3; default: assert(0); } } } else { if (radio->revision == 8) adj_loopback_gain += 0x003E; else adj_loopback_gain += 0x0026; if (adj_loopback_gain >= 0x46) { adj_loopback_gain -= 0x46; extern_lna_control = 0x3000; } else if (adj_loopback_gain >= 0x3A) { adj_loopback_gain -= 0x3A; extern_lna_control = 0x2000; } else if (adj_loopback_gain >= 0x2E) { adj_loopback_gain -= 0x2E; extern_lna_control = 0x1000; } else { adj_loopback_gain -= 0x10; extern_lna_control = 0x0000; } for (loop = 0; loop < 16; loop++) { u16 tmp = adj_loopback_gain - 6 * loop; if (tmp < 6) break; } loop_or = (loop << 8) | extern_lna_control; if (phy->rev >= 7 && bcm->sprom.boardflags & BCM43xx_BFL_EXTLNA) { if (extern_lna_control) loop_or |= 0x8000; switch (lpd) { case LPD(0, 1, 1): return 0x8F92; case LPD(0, 0, 1): return (0x8092 | loop_or); case LPD(1, 0, 1): return (0x2092 | loop_or); case LPD(1, 0, 0): return (0x2093 | loop_or); default: assert(0); } } else { switch (lpd) { case LPD(0, 1, 1): return 0x0F92; case LPD(0, 0, 1): case LPD(1, 0, 1): return (0x0092 | loop_or); case LPD(1, 0, 0): return (0x0093 | loop_or); default: assert(0); } } } return 0;}u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm){ struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 backup[21] = { 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)); if (phy->rev > 1) { /* loopback gain enabled */ backup[19] = bcm43xx_phy_read(bcm, 0x080F); backup[20] = bcm43xx_phy_read(bcm, 0x0810); if (phy->rev >= 3) bcm43xx_phy_write(bcm, 0x080F, 0xC020); else bcm43xx_phy_write(bcm, 0x080F, 0x8020); bcm43xx_phy_write(bcm, 0x0810, 0x0000); } bcm43xx_phy_write(bcm, 0x0812, bcm43xx_get_812_value(bcm, LPD(0, 1, 1))); if (phy->rev < 7 || !(bcm->sprom.boardflags & BCM43xx_BFL_EXTLNA)) bcm43xx_phy_write(bcm, 0x0811, 0x01B3); else bcm43xx_phy_write(bcm, 0x0811, 0x09B3); } } 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->analog == 0) { bcm43xx_write16(bcm, 0x03E6, 0x0122); } else { if (phy->analog >= 2) bcm43xx_phy_write(bcm, 0x0003, (bcm43xx_phy_read(bcm, 0x0003) & 0xFFBF) | 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, 0x0026); if (phy->connected) bcm43xx_phy_write(bcm, 0x0812, bcm43xx_get_812_value(bcm, LPD(0, 1, 1))); bcm43xx_phy_write(bcm, 0x0015, 0xBFAF); bcm43xx_phy_write(bcm, 0x002B, 0x1403); if (phy->connected) bcm43xx_phy_write(bcm, 0x0812, bcm43xx_get_812_value(bcm, LPD(0, 0, 1))); bcm43xx_phy_write(bcm, 0x0015, 0xBFA0); bcm43xx_radio_write16(bcm, 0x0051, (bcm43xx_radio_read16(bcm, 0x0051) | 0x0004)); if (radio->revision == 8) bcm43xx_radio_write16(bcm, 0x0043, 0x001F); else { bcm43xx_radio_write16(bcm, 0x0052, 0x0000); bcm43xx_radio_write16(bcm, 0x0043, (bcm43xx_radio_read16(bcm, 0x0043) & 0xFFF0) | 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, bcm43xx_get_812_value(bcm, LPD(1, 0, 1))); bcm43xx_phy_write(bcm, 0x0015, 0xAFB0); udelay(10); if (phy->connected) bcm43xx_phy_write(bcm, 0x0812, bcm43xx_get_812_value(bcm, LPD(1, 0, 1))); bcm43xx_phy_write(bcm, 0x0015, 0xEFB0); udelay(10); if (phy->connected) bcm43xx_phy_write(bcm, 0x0812, bcm43xx_get_812_value(bcm, LPD(1, 0, 0))); bcm43xx_phy_write(bcm, 0x0015, 0xFFF0); udelay(20); tmp1 += bcm43xx_phy_read(bcm, 0x002D); bcm43xx_phy_write(bcm, 0x0058, 0x0000); if (phy->connected) bcm43xx_phy_write(bcm, 0x0812, bcm43xx_get_812_value(bcm, LPD(1, 0, 1))); 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, bcm43xx_get_812_value(bcm, LPD(1, 0, 1))); bcm43xx_phy_write(bcm, 0x0015, 0xAFB0); udelay(10); if (phy->connected) bcm43xx_phy_write(bcm, 0x0812, bcm43xx_get_812_value(bcm, LPD(1, 0, 1))); bcm43xx_phy_write(bcm, 0x0015, 0xEFB0); udelay(10); if (phy->connected) bcm43xx_phy_write(bcm, 0x0812, bcm43xx_get_812_value(bcm, LPD(1, 0, 0))); bcm43xx_phy_write(bcm, 0x0015, 0xFFF0); udelay(10); tmp2 += bcm43xx_phy_read(bcm, 0x002D); bcm43xx_phy_write(bcm, 0x0058, 0x0000); if (phy->connected) bcm43xx_phy_write(bcm, 0x0812, bcm43xx_get_812_value(bcm, LPD(1, 0, 1))); bcm43xx_phy_write(bcm, 0x0015, 0xAFB0); } tmp2++; tmp2 >>= 8; if (tmp1 < tmp2) break; } /* Restore the registers */ bcm43xx_phy_write(bcm, 0x0015, backup[1]); bcm43xx_radio_write16(bcm, 0x0051, backup[14]); bcm43xx_radio_write16(bcm, 0x0052, backup[15]); bcm43xx_radio_write16(bcm, 0x0043, backup[0]); bcm43xx_phy_write(bcm, 0x005A, backup[16]); bcm43xx_phy_write(bcm, 0x0059, backup[17]); bcm43xx_phy_write(bcm, 0x0058, backup[18]); bcm43xx_write16(bcm, 0x03E6, backup[11]); if (phy->analog != 0) bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, backup[12]); bcm43xx_phy_write(bcm, 0x0035, backup[10]); bcm43xx_radio_selectchannel(bcm, radio->channel, 1); if (phy->type == BCM43xx_PHYTYPE_B) { bcm43xx_phy_write(bcm, 0x0030, backup[2]); bcm43xx_write16(bcm, 0x03EC, backup[3]); } else { if (phy->connected) { bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO, (bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_RADIO) & 0x7FFF)); bcm43xx_phy_write(bcm, 0x0811, backup[4]); bcm43xx_phy_write(bcm, 0x0812, backup[5]); bcm43xx_phy_write(bcm, 0x0814, backup[6]); bcm43xx_phy_write(bcm, 0x0815, backup[7]); bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, backup[8]); bcm43xx_phy_write(bcm, 0x0802, backup[9]); if (phy->rev > 1) { bcm43xx_phy_write(bcm, 0x080F, backup[19]); bcm43xx_phy_write(bcm, 0x0810, backup[20]); } } } if (i >= 15) ret = backup[13]; return ret;}void bcm43xx_radio_init2060(struct bcm43xx_private *bcm){ int err; bcm43xx_radio_write16(bcm, 0x0004, 0x00C0); bcm43xx_radio_write16(bcm, 0x0005, 0x0008); bcm43xx_radio_write16(bcm, 0x0009, 0x0040); bcm43xx_radio_write16(bcm, 0x0005, 0x00AA); bcm43xx_radio_write16(bcm, 0x0032, 0x008F); bcm43xx_radio_write16(bcm, 0x0006, 0x008F); bcm43xx_radio_write16(bcm, 0x0034, 0x008F); bcm43xx_radio_write16(bcm, 0x002C, 0x0007); bcm43xx_radio_write16(bcm, 0x0082, 0x0080); bcm43xx_radio_write16(bcm, 0x0080, 0x0000); bcm43xx_radio_write16(bcm, 0x003F, 0x00DA); bcm43xx_radio_write16(bcm, 0x0005, bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008); bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0010); bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020); bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020); udelay(400); bcm43xx_radio_write16(bcm, 0x0081, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020) | 0x0010); udelay(400); bcm43xx_radio_write16(bcm, 0x0005, (bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008) | 0x0008); bcm43xx_radio_write16(bcm, 0x0085, bcm43xx_radio_read16(bcm, 0x0085) & ~0x0010); bcm43xx_radio_write16(bcm, 0x0005, bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008); bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0040); bcm43xx_radio_write16(bcm, 0x0081, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0040) | 0x0040); bcm43xx_radio_write16(bcm, 0x0005, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0008) | 0x0008); bcm43xx_phy_write(bcm, 0x0063, 0xDDC6); bcm43xx_phy_write(bcm, 0x0069, 0x07BE); bcm43xx_phy_write(bcm, 0x006A, 0x0000); err = bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_A, 0); assert(err == 0); udelay(1000);}static inlineu16 freq_r3A_value(u16 frequency){ u16 value; if (frequency < 5091) value = 0x0040; else if (frequency < 5321) value = 0x0000; else if (frequency < 5806) value = 0x0080; else value = 0x0040; return value;}void bcm43xx_radio_set_tx_iq(struct bcm43xx_private *bcm){ static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 }; static const u8 data_low[5] = { 0x00, 0x01, 0x05, 0x06, 0x0A }; u16 tmp = bcm43xx_radio_read16(bcm, 0x001E); int i, j; for (i = 0; i < 5; i++) { for (j = 0; j < 5; j++) { if (tmp == (data_high[i] | data_low[j])) { bcm43xx_phy_write(bcm, 0x0069, (i - j) << 8 | 0x00C0); return; } } }}int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm, u8 channel, int synthetic_pu_workaround){ struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); u16 r8, tmp; u16 freq;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -