📄 adm8211.c
字号:
ADM8211_CSR_WRITE(SYNRF, ADM8211_SYNRF_WRITE_SYNDATA_0); \ ADM8211_CSR_READ(SYNRF); \ } \ \ for (i = 0; i <= bits; i++) { \ if (bitbuf & (1 << (bits - i))) \ reg = ADM8211_SYNRF_WRITE_SYNDATA_1; \ else \ reg = ADM8211_SYNRF_WRITE_SYNDATA_0; \ \ ADM8211_CSR_WRITE(SYNRF, reg); \ ADM8211_CSR_READ(SYNRF); \ \ ADM8211_CSR_WRITE(SYNRF, reg | ADM8211_SYNRF_WRITE_CLOCK_1); \ ADM8211_CSR_READ(SYNRF); \ ADM8211_CSR_WRITE(SYNRF, reg | ADM8211_SYNRF_WRITE_CLOCK_0); \ ADM8211_CSR_READ(SYNRF); \ } \ \ if (postwrite == 1) { \ ADM8211_CSR_WRITE(SYNRF, reg | ADM8211_SYNRF_IF_SELECT_0); \ ADM8211_CSR_READ(SYNRF); \ } \ if (postwrite == 2) { \ ADM8211_CSR_WRITE(SYNRF, reg | ADM8211_SYNRF_IF_SELECT_1); \ ADM8211_CSR_READ(SYNRF); \ } \ \ ADM8211_CSR_WRITE(SYNRF, 0); \ ADM8211_CSR_READ(SYNRF); \}WRITE_SYN(max2820, 0x00FFF, 0, 0x0F, 12, 15, 1, 1)WRITE_SYN(al2210l, 0xFFFFF, 4, 0x0F, 0, 23, 1, 1)WRITE_SYN(rfmd2958, 0x3FFFF, 0, 0x1F, 18, 23, 0, 1)WRITE_SYN(rfmd2948, 0x0FFFF, 4, 0x0F, 0, 21, 0, 2)#undef WRITE_SYNstatic int adm8211_write_bbp(struct ieee80211_hw *dev, u8 addr, u8 data){ struct adm8211_priv *priv = dev->priv; unsigned int timeout; u32 reg; timeout = 10; while (timeout > 0) { reg = ADM8211_CSR_READ(BBPCTL); if (!(reg & (ADM8211_BBPCTL_WR | ADM8211_BBPCTL_RD))) break; timeout--; msleep(2); } if (timeout == 0) { printk(KERN_DEBUG "%s: adm8211_write_bbp(%d,%d) failed" " prewrite (reg=0x%08x)\n", wiphy_name(dev->wiphy), addr, data, reg); return -ETIMEDOUT; } switch (priv->bbp_type) { case ADM8211_TYPE_INTERSIL: reg = ADM8211_BBPCTL_MMISEL; /* three wire interface */ break; case ADM8211_TYPE_RFMD: reg = (0x20 << 24) | ADM8211_BBPCTL_TXCE | ADM8211_BBPCTL_CCAP | (0x01 << 18); break; case ADM8211_TYPE_ADMTEK: reg = (0x20 << 24) | ADM8211_BBPCTL_TXCE | ADM8211_BBPCTL_CCAP | (0x05 << 18); break; } reg |= ADM8211_BBPCTL_WR | (addr << 8) | data; ADM8211_CSR_WRITE(BBPCTL, reg); timeout = 10; while (timeout > 0) { reg = ADM8211_CSR_READ(BBPCTL); if (!(reg & ADM8211_BBPCTL_WR)) break; timeout--; msleep(2); } if (timeout == 0) { ADM8211_CSR_WRITE(BBPCTL, ADM8211_CSR_READ(BBPCTL) & ~ADM8211_BBPCTL_WR); printk(KERN_DEBUG "%s: adm8211_write_bbp(%d,%d) failed" " postwrite (reg=0x%08x)\n", wiphy_name(dev->wiphy), addr, data, reg); return -ETIMEDOUT; } return 0;}static int adm8211_rf_set_channel(struct ieee80211_hw *dev, unsigned int chan){ static const u32 adm8211_rfmd2958_reg5[] = {0x22BD, 0x22D2, 0x22E8, 0x22FE, 0x2314, 0x232A, 0x2340, 0x2355, 0x236B, 0x2381, 0x2397, 0x23AD, 0x23C2, 0x23F7}; static const u32 adm8211_rfmd2958_reg6[] = {0x05D17, 0x3A2E8, 0x2E8BA, 0x22E8B, 0x1745D, 0x0BA2E, 0x00000, 0x345D1, 0x28BA2, 0x1D174, 0x11745, 0x05D17, 0x3A2E8, 0x11745}; struct adm8211_priv *priv = dev->priv; u8 ant_power = priv->ant_power > 0x3F ? priv->eeprom->antenna_power[chan - 1] : priv->ant_power; u8 tx_power = priv->tx_power > 0x3F ? priv->eeprom->tx_power[chan - 1] : priv->tx_power; u8 lpf_cutoff = priv->lpf_cutoff == 0xFF ? priv->eeprom->lpf_cutoff[chan - 1] : priv->lpf_cutoff; u8 lnags_thresh = priv->lnags_threshold == 0xFF ? priv->eeprom->lnags_threshold[chan - 1] : priv->lnags_threshold; u32 reg; ADM8211_IDLE(); /* Program synthesizer to new channel */ switch (priv->transceiver_type) { case ADM8211_RFMD2958: case ADM8211_RFMD2958_RF3000_CONTROL_POWER: adm8211_rf_write_syn_rfmd2958(dev, 0x00, 0x04007); adm8211_rf_write_syn_rfmd2958(dev, 0x02, 0x00033); adm8211_rf_write_syn_rfmd2958(dev, 0x05, adm8211_rfmd2958_reg5[chan - 1]); adm8211_rf_write_syn_rfmd2958(dev, 0x06, adm8211_rfmd2958_reg6[chan - 1]); break; case ADM8211_RFMD2948: adm8211_rf_write_syn_rfmd2948(dev, SI4126_MAIN_CONF, SI4126_MAIN_XINDIV2); adm8211_rf_write_syn_rfmd2948(dev, SI4126_POWERDOWN, SI4126_POWERDOWN_PDIB | SI4126_POWERDOWN_PDRB); adm8211_rf_write_syn_rfmd2948(dev, SI4126_PHASE_DET_GAIN, 0); adm8211_rf_write_syn_rfmd2948(dev, SI4126_RF2_N_DIV, (chan == 14 ? 2110 : (2033 + (chan * 5)))); adm8211_rf_write_syn_rfmd2948(dev, SI4126_IF_N_DIV, 1496); adm8211_rf_write_syn_rfmd2948(dev, SI4126_RF2_R_DIV, 44); adm8211_rf_write_syn_rfmd2948(dev, SI4126_IF_R_DIV, 44); break; case ADM8211_MAX2820: adm8211_rf_write_syn_max2820(dev, 0x3, (chan == 14 ? 0x054 : (0x7 + (chan * 5)))); break; case ADM8211_AL2210L: adm8211_rf_write_syn_al2210l(dev, 0x0, (chan == 14 ? 0x229B4 : (0x22967 + (chan * 5)))); break; default: printk(KERN_DEBUG "%s: unsupported transceiver type %d\n", wiphy_name(dev->wiphy), priv->transceiver_type); break; } /* write BBP regs */ if (priv->bbp_type == ADM8211_TYPE_RFMD) { /* SMC 2635W specific? adm8211b doesn't use the 2948 though.. */ /* TODO: remove if SMC 2635W doesn't need this */ if (priv->transceiver_type == ADM8211_RFMD2948) { reg = ADM8211_CSR_READ(GPIO); reg &= 0xfffc0000; reg |= ADM8211_CSR_GPIO_EN0; if (chan != 14) reg |= ADM8211_CSR_GPIO_O0; ADM8211_CSR_WRITE(GPIO, reg); } if (priv->transceiver_type == ADM8211_RFMD2958) { /* set PCNT2 */ adm8211_rf_write_syn_rfmd2958(dev, 0x0B, 0x07100); /* set PCNT1 P_DESIRED/MID_BIAS */ reg = le16_to_cpu(priv->eeprom->cr49); reg >>= 13; reg <<= 15; reg |= ant_power << 9; adm8211_rf_write_syn_rfmd2958(dev, 0x0A, reg); /* set TXRX TX_GAIN */ adm8211_rf_write_syn_rfmd2958(dev, 0x09, 0x00050 | (priv->pdev->revision < ADM8211_REV_CA ? tx_power : 0)); } else { reg = ADM8211_CSR_READ(PLCPHD); reg &= 0xff00ffff; reg |= tx_power << 18; ADM8211_CSR_WRITE(PLCPHD, reg); } ADM8211_CSR_WRITE(SYNRF, ADM8211_SYNRF_SELRF | ADM8211_SYNRF_PE1 | ADM8211_SYNRF_PHYRST); ADM8211_CSR_READ(SYNRF); msleep(30); /* RF3000 BBP */ if (priv->transceiver_type != ADM8211_RFMD2958) adm8211_write_bbp(dev, RF3000_TX_VAR_GAIN__TX_LEN_EXT, tx_power<<2); adm8211_write_bbp(dev, RF3000_LOW_GAIN_CALIB, lpf_cutoff); adm8211_write_bbp(dev, RF3000_HIGH_GAIN_CALIB, lnags_thresh); adm8211_write_bbp(dev, 0x1c, priv->pdev->revision == ADM8211_REV_BA ? priv->eeprom->cr28 : 0); adm8211_write_bbp(dev, 0x1d, priv->eeprom->cr29); ADM8211_CSR_WRITE(SYNRF, 0); /* Nothing to do for ADMtek BBP */ } else if (priv->bbp_type != ADM8211_TYPE_ADMTEK) printk(KERN_DEBUG "%s: unsupported BBP type %d\n", wiphy_name(dev->wiphy), priv->bbp_type); ADM8211_RESTORE(); /* update current channel for adhoc (and maybe AP mode) */ reg = ADM8211_CSR_READ(CAP0); reg &= ~0xF; reg |= chan; ADM8211_CSR_WRITE(CAP0, reg); return 0;}static void adm8211_update_mode(struct ieee80211_hw *dev){ struct adm8211_priv *priv = dev->priv; ADM8211_IDLE(); priv->soft_rx_crc = 0; switch (priv->mode) { case IEEE80211_IF_TYPE_STA: priv->nar &= ~(ADM8211_NAR_PR | ADM8211_NAR_EA); priv->nar |= ADM8211_NAR_ST | ADM8211_NAR_SR; break; case IEEE80211_IF_TYPE_IBSS: priv->nar &= ~ADM8211_NAR_PR; priv->nar |= ADM8211_NAR_EA | ADM8211_NAR_ST | ADM8211_NAR_SR; /* don't trust the error bits on rev 0x20 and up in adhoc */ if (priv->pdev->revision >= ADM8211_REV_BA) priv->soft_rx_crc = 1; break; case IEEE80211_IF_TYPE_MNTR: priv->nar &= ~(ADM8211_NAR_EA | ADM8211_NAR_ST); priv->nar |= ADM8211_NAR_PR | ADM8211_NAR_SR; break; } ADM8211_RESTORE();}static void adm8211_hw_init_syn(struct ieee80211_hw *dev){ struct adm8211_priv *priv = dev->priv; switch (priv->transceiver_type) { case ADM8211_RFMD2958: case ADM8211_RFMD2958_RF3000_CONTROL_POWER: /* comments taken from ADMtek vendor driver */ /* Reset RF2958 after power on */ adm8211_rf_write_syn_rfmd2958(dev, 0x1F, 0x00000); /* Initialize RF VCO Core Bias to maximum */ adm8211_rf_write_syn_rfmd2958(dev, 0x0C, 0x3001F); /* Initialize IF PLL */ adm8211_rf_write_syn_rfmd2958(dev, 0x01, 0x29C03); /* Initialize IF PLL Coarse Tuning */ adm8211_rf_write_syn_rfmd2958(dev, 0x03, 0x1FF6F); /* Initialize RF PLL */ adm8211_rf_write_syn_rfmd2958(dev, 0x04, 0x29403); /* Initialize RF PLL Coarse Tuning */ adm8211_rf_write_syn_rfmd2958(dev, 0x07, 0x1456F); /* Initialize TX gain and filter BW (R9) */ adm8211_rf_write_syn_rfmd2958(dev, 0x09, (priv->transceiver_type == ADM8211_RFMD2958 ? 0x10050 : 0x00050)); /* Initialize CAL register */ adm8211_rf_write_syn_rfmd2958(dev, 0x08, 0x3FFF8); break; case ADM8211_MAX2820: adm8211_rf_write_syn_max2820(dev, 0x1, 0x01E); adm8211_rf_write_syn_max2820(dev, 0x2, 0x001); adm8211_rf_write_syn_max2820(dev, 0x3, 0x054); adm8211_rf_write_syn_max2820(dev, 0x4, 0x310); adm8211_rf_write_syn_max2820(dev, 0x5, 0x000); break; case ADM8211_AL2210L: adm8211_rf_write_syn_al2210l(dev, 0x0, 0x0196C); adm8211_rf_write_syn_al2210l(dev, 0x1, 0x007CB); adm8211_rf_write_syn_al2210l(dev, 0x2, 0x3582F); adm8211_rf_write_syn_al2210l(dev, 0x3, 0x010A9); adm8211_rf_write_syn_al2210l(dev, 0x4, 0x77280); adm8211_rf_write_syn_al2210l(dev, 0x5, 0x45641); adm8211_rf_write_syn_al2210l(dev, 0x6, 0xEA130); adm8211_rf_write_syn_al2210l(dev, 0x7, 0x80000); adm8211_rf_write_syn_al2210l(dev, 0x8, 0x7850F); adm8211_rf_write_syn_al2210l(dev, 0x9, 0xF900C); adm8211_rf_write_syn_al2210l(dev, 0xA, 0x00000); adm8211_rf_write_syn_al2210l(dev, 0xB, 0x00000); break; case ADM8211_RFMD2948: default: break; }}static int adm8211_hw_init_bbp(struct ieee80211_hw *dev){ struct adm8211_priv *priv = dev->priv; u32 reg; /* write addresses */ if (priv->bbp_type == ADM8211_TYPE_INTERSIL) { ADM8211_CSR_WRITE(MMIWA, 0x100E0C0A); ADM8211_CSR_WRITE(MMIRD0, 0x00007C7E); ADM8211_CSR_WRITE(MMIRD1, 0x00100000); } else if (priv->bbp_type == ADM8211_TYPE_RFMD || priv->bbp_type == ADM8211_TYPE_ADMTEK) { /* check specific BBP type */ switch (priv->specific_bbptype) { case ADM8211_BBP_RFMD3000: case ADM8211_BBP_RFMD3002: ADM8211_CSR_WRITE(MMIWA, 0x00009101); ADM8211_CSR_WRITE(MMIRD0, 0x00000301); break; case ADM8211_BBP_ADM8011: ADM8211_CSR_WRITE(MMIWA, 0x00008903); ADM8211_CSR_WRITE(MMIRD0, 0x00001716); reg = ADM8211_CSR_READ(BBPCTL); reg &= ~ADM8211_BBPCTL_TYPE; reg |= 0x5 << 18; ADM8211_CSR_WRITE(BBPCTL, reg); break; } switch (priv->pdev->revision) { case ADM8211_REV_CA: if (priv->transceiver_type == ADM8211_RFMD2958 || priv->transceiver_type == ADM8211_RFMD2958_RF3000_CONTROL_POWER || priv->transceiver_type == ADM8211_RFMD2948) ADM8211_CSR_WRITE(SYNCTL, 0x1 << 22); else if (priv->transceiver_type == ADM8211_MAX2820 || priv->transceiver_type == ADM8211_AL2210L) ADM8211_CSR_WRITE(SYNCTL, 0x3 << 22); break; case ADM8211_REV_BA: reg = ADM8211_CSR_READ(MMIRD1); reg &= 0x0000FFFF; reg |= 0x7e100000; ADM8211_CSR_WRITE(MMIRD1, reg); break; case ADM8211_REV_AB: case ADM8211_REV_AF: default: ADM8211_CSR_WRITE(MMIRD1, 0x7e100000); break; } /* For RFMD */ ADM8211_CSR_WRITE(MACTEST, 0x800); } adm8211_hw_init_syn(dev); /* Set RF Power control IF pin to PE1+PHYRST# */ ADM8211_CSR_WRITE(SYNRF, ADM8211_SYNRF_SELRF | ADM8211_SYNRF_PE1 | ADM8211_SYNRF_PHYRST); ADM8211_CSR_READ(SYNRF); msleep(20); /* write BBP regs */ if (priv->bbp_type == ADM8211_TYPE_RFMD) { /* RF3000 BBP */ /* another set: * 11: c8 * 14: 14 * 15: 50 (chan 1..13; chan 14: d0) * 1c: 00 * 1d: 84 */ adm8211_write_bbp(dev, RF3000_CCA_CTRL, 0x80); /* antenna selection: diversity */ adm8211_write_bbp(dev, RF3000_DIVERSITY__RSSI, 0x80); adm8211_write_bbp(dev, RF3000_TX_VAR_GAIN__TX_LEN_EXT, 0x74); adm8211_write_bbp(dev, RF3000_LOW_GAIN_CALIB, 0x38); adm8211_write_bbp(dev, RF3000_HIGH_GAIN_CALIB, 0x40); if (priv->eeprom->major_version < 2) { adm8211_write_bbp(dev, 0x1c, 0x00); adm8211_write_bbp(dev, 0x1d, 0x80); } else { if (priv->pdev->revision == ADM8211_REV_BA) adm8211_write_bbp(dev, 0x1c, priv->eeprom->cr28); else adm8211_write_bbp(dev, 0x1c, 0x00); adm8211_write_bbp(dev, 0x1d, priv->eeprom->cr29); } } else if (priv->bbp_type == ADM8211_TYPE_ADMTEK) { /* reset baseband */ adm8211_write_bbp(dev, 0x00, 0xFF); /* antenna selection: diversity */ adm8211_write_bbp(dev, 0x07, 0x0A); /* TODO: find documentation for this */ switch (priv->transceiver_type) { case ADM8211_RFMD2958: case ADM8211_RFMD2958_RF3000_CONTROL_POWER: adm8211_write_bbp(dev, 0x00, 0x00); adm8211_write_bbp(dev, 0x01, 0x00); adm8211_write_bbp(dev, 0x02, 0x00); adm8211_write_bbp(dev, 0x03, 0x00); adm8211_write_bbp(dev, 0x06, 0x0f); adm8211_write_bbp(dev, 0x09, 0x00); adm8211_write_bbp(dev, 0x0a, 0x00); adm8211_write_bbp(dev, 0x0b, 0x00); adm8211_write_bbp(dev, 0x0c, 0x00); adm8211_write_bbp(dev, 0x0f, 0xAA); adm8211_write_bbp(dev, 0x10, 0x8c); adm8211_write_bbp(dev, 0x11, 0x43); adm8211_write_bbp(dev, 0x18, 0x40); adm8211_write_bbp(dev, 0x20, 0x23); adm8211_write_bbp(dev, 0x21, 0x02); adm8211_write_bbp(dev, 0x22, 0x28); adm8211_write_bbp(dev, 0x23, 0x30); adm8211_write_bbp(dev, 0x24, 0x2d); adm8211_write_bbp(dev, 0x28, 0x35); adm8211_write_bbp(dev, 0x2a, 0x8c); adm8211_write_bbp(dev, 0x2b, 0x81); adm8211_write_bbp(dev, 0x2c, 0x44); adm8211_write_bbp(dev, 0x2d, 0x0A); adm8211_write_bbp(dev, 0x29, 0x40); adm8211_write_bbp(dev, 0x60, 0x08); adm8211_write_bbp(dev, 0x64, 0x01); break; case ADM8211_MAX2820: adm8211_write_bbp(dev, 0x00, 0x00); adm8211_write_bbp(dev, 0x01, 0x00); adm8211_write_bbp(dev, 0x02, 0x00); adm8211_write_bbp(dev, 0x03, 0x00); adm8211_write_bbp(dev, 0x06, 0x0f); adm8211_write_bbp(dev, 0x09, 0x05); adm8211_write_bbp(dev, 0x0a, 0x02); adm8211_write_bbp(dev, 0x0b, 0x00); adm8211_write_bbp(dev, 0x0c, 0x0f); adm8211_write_bbp(dev, 0x0f, 0x55); adm8211_write_bbp(dev, 0x10, 0x8d); adm8211_write_bbp(dev, 0x11, 0x43); adm8211_write_bbp(dev, 0x18, 0x4a); adm8211_write_bbp(dev, 0x20, 0x20); adm8211_write_bbp(dev, 0x21, 0x02); adm8211_write_bbp(dev, 0x22, 0x23); adm8211_write_bbp(dev, 0x23, 0x30); adm8211_write_bbp(dev, 0x24, 0x2d); adm8211_write_bbp(dev, 0x2a, 0x8c); adm8211_write_bbp(dev, 0x2b, 0x81); adm8211_write_bbp(dev, 0x2c, 0x44); adm8211_write_bbp(dev, 0x29, 0x4a); adm8211_write_bbp(dev, 0x60, 0x2b); adm8211_write_bbp(dev, 0x64, 0x01); break; case ADM8211_AL2210L: adm8211_write_bbp(dev, 0x00, 0x00); adm8211_write_bbp(dev, 0x01, 0x00); adm8211_write_bbp(dev, 0x02, 0x00); adm8211_write_bbp(dev, 0x03, 0x00); adm8211_write_bbp(dev, 0x06, 0x0f); adm8211_write_bbp(dev, 0x07, 0x05); adm8211_write_bbp(dev, 0x08, 0x03); adm8211_write_bbp(dev, 0x09, 0x00); adm8211_write_bbp(dev, 0x0a, 0x00); adm8211_write_bbp(dev, 0x0b, 0x00); adm8211_write_bbp(dev, 0x0c, 0x10); adm8211_write_bbp(dev, 0x0f, 0x55); adm8211_write_bbp(dev, 0x10, 0x8d); adm8211_write_bbp(dev, 0x11, 0x43); adm8211_write_bbp(dev, 0x18, 0x4a); adm8211_write_bbp(dev, 0x20, 0x20); adm8211_write_bbp(dev, 0x21, 0x02); adm8211_write_bbp(dev, 0x22, 0x23); adm8211_write_bbp(dev, 0x23, 0x30); adm8211_write_bbp(dev, 0x24, 0x2d); adm8211_write_bbp(dev, 0x2a, 0xaa); adm8211_write_bbp(dev, 0x2b, 0x81); adm8211_write_bbp(dev, 0x2c, 0x44); adm8211_write_bbp(dev, 0x29, 0xfa); adm8211_write_bbp(dev, 0x60, 0x2d); adm8211_write_bbp(dev, 0x64, 0x01); break; case ADM8211_RFMD2948: break; default: printk(KERN_DEBUG "%s: unsupported transceiver %d\n", wiphy_name(dev->wiphy), priv->transceiver_type);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -