From 3e38d3daf881a78ac13e93504a8ac5777040797e Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 8 Jul 2013 11:25:53 +0200 Subject: rt2x00: rt2800lib: introduce local EEPROM access functions The patch adds rt2800 specific functions for EEPROM data access and changes the code to use these instead of the generic rt2x00_eeprom_* variants. To avoid functional changes, the new functions are wrappers around the corresponding generic rt2x00_eeprom_* routines for now. Functional changes will be implemented in additional patches. Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 165 ++++++++++++++++++-------------- 1 file changed, 95 insertions(+), 70 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 1f80ea5e29dd..522f0b19cd14 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -221,6 +221,24 @@ static void rt2800_rf_write(struct rt2x00_dev *rt2x00dev, mutex_unlock(&rt2x00dev->csr_mutex); } +static void *rt2800_eeprom_addr(struct rt2x00_dev *rt2x00dev, + const enum rt2800_eeprom_word word) +{ + return rt2x00_eeprom_addr(rt2x00dev, word); +} + +static void rt2800_eeprom_read(struct rt2x00_dev *rt2x00dev, + const enum rt2800_eeprom_word word, u16 *data) +{ + rt2x00_eeprom_read(rt2x00dev, word, data); +} + +static void rt2800_eeprom_write(struct rt2x00_dev *rt2x00dev, + const enum rt2800_eeprom_word word, u16 data) +{ + rt2x00_eeprom_write(rt2x00dev, word, data); +} + static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev) { u32 reg; @@ -609,16 +627,16 @@ static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, u32 rxwi_w2) u8 offset2; if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { - rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &eeprom); offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET0); offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET1); - rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom); offset2 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_OFFSET2); } else { - rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &eeprom); offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A_OFFSET0); offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A_OFFSET1); - rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom); offset2 = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_OFFSET2); } @@ -890,6 +908,9 @@ const struct rt2x00debug rt2800_rt2x00debug = { .word_count = CSR_REG_SIZE / sizeof(u32), }, .eeprom = { + /* NOTE: The local EEPROM access functions can't + * be used here, use the generic versions instead. + */ .read = rt2x00_eeprom_read, .write = rt2x00_eeprom_write, .word_base = EEPROM_BASE, @@ -1547,7 +1568,7 @@ static void rt2800_config_3572bt_ant(struct rt2x00_dev *rt2x00dev) led_r_mode = rt2x00_get_field32(reg, LED_CFG_LED_POLAR) ? 0 : 3; if (led_g_mode != rt2x00_get_field32(reg, LED_CFG_G_LED_MODE) || led_r_mode != rt2x00_get_field32(reg, LED_CFG_R_LED_MODE)) { - rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); led_ctrl = rt2x00_get_field16(eeprom, EEPROM_FREQ_LED_MODE); if (led_ctrl == 0 || led_ctrl > 0x40) { rt2x00_set_field32(®, LED_CFG_G_LED_MODE, led_g_mode); @@ -1622,7 +1643,7 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant) rt2x00_rt(rt2x00dev, RT3090) || rt2x00_rt(rt2x00dev, RT3352) || rt2x00_rt(rt2x00dev, RT3390)) { - rt2x00_eeprom_read(rt2x00dev, + rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_ANT_DIVERSITY)) @@ -1659,16 +1680,16 @@ static void rt2800_config_lna_gain(struct rt2x00_dev *rt2x00dev, short lna_gain; if (libconf->rf.channel <= 14) { - rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_BG); } else if (libconf->rf.channel <= 64) { - rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0); } else if (libconf->rf.channel <= 128) { - rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom); lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_LNA_A1); } else { - rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom); lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_LNA_A2); } @@ -2798,62 +2819,62 @@ static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev) * Example TSSI bounds 0xF0 0xD0 0xB5 0xA0 0x88 0x45 0x25 0x15 0x00 */ if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { - rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG1, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG1, &eeprom); tssi_bounds[0] = rt2x00_get_field16(eeprom, EEPROM_TSSI_BOUND_BG1_MINUS4); tssi_bounds[1] = rt2x00_get_field16(eeprom, EEPROM_TSSI_BOUND_BG1_MINUS3); - rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG2, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG2, &eeprom); tssi_bounds[2] = rt2x00_get_field16(eeprom, EEPROM_TSSI_BOUND_BG2_MINUS2); tssi_bounds[3] = rt2x00_get_field16(eeprom, EEPROM_TSSI_BOUND_BG2_MINUS1); - rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG3, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG3, &eeprom); tssi_bounds[4] = rt2x00_get_field16(eeprom, EEPROM_TSSI_BOUND_BG3_REF); tssi_bounds[5] = rt2x00_get_field16(eeprom, EEPROM_TSSI_BOUND_BG3_PLUS1); - rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG4, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG4, &eeprom); tssi_bounds[6] = rt2x00_get_field16(eeprom, EEPROM_TSSI_BOUND_BG4_PLUS2); tssi_bounds[7] = rt2x00_get_field16(eeprom, EEPROM_TSSI_BOUND_BG4_PLUS3); - rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG5, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_BG5, &eeprom); tssi_bounds[8] = rt2x00_get_field16(eeprom, EEPROM_TSSI_BOUND_BG5_PLUS4); step = rt2x00_get_field16(eeprom, EEPROM_TSSI_BOUND_BG5_AGC_STEP); } else { - rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A1, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A1, &eeprom); tssi_bounds[0] = rt2x00_get_field16(eeprom, EEPROM_TSSI_BOUND_A1_MINUS4); tssi_bounds[1] = rt2x00_get_field16(eeprom, EEPROM_TSSI_BOUND_A1_MINUS3); - rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A2, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A2, &eeprom); tssi_bounds[2] = rt2x00_get_field16(eeprom, EEPROM_TSSI_BOUND_A2_MINUS2); tssi_bounds[3] = rt2x00_get_field16(eeprom, EEPROM_TSSI_BOUND_A2_MINUS1); - rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A3, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A3, &eeprom); tssi_bounds[4] = rt2x00_get_field16(eeprom, EEPROM_TSSI_BOUND_A3_REF); tssi_bounds[5] = rt2x00_get_field16(eeprom, EEPROM_TSSI_BOUND_A3_PLUS1); - rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A4, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A4, &eeprom); tssi_bounds[6] = rt2x00_get_field16(eeprom, EEPROM_TSSI_BOUND_A4_PLUS2); tssi_bounds[7] = rt2x00_get_field16(eeprom, EEPROM_TSSI_BOUND_A4_PLUS3); - rt2x00_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A5, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_TSSI_BOUND_A5, &eeprom); tssi_bounds[8] = rt2x00_get_field16(eeprom, EEPROM_TSSI_BOUND_A5_PLUS4); @@ -2899,7 +2920,7 @@ static int rt2800_get_txpower_bw_comp(struct rt2x00_dev *rt2x00dev, u8 comp_type; int comp_value = 0; - rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_DELTA, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_TXPOWER_DELTA, &eeprom); /* * HT40 compensation not required. @@ -2974,12 +2995,12 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b, * .11b data rate need add additional 4dbm * when calculating eirp txpower. */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + 1, + rt2800_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + 1, &eeprom); criterion = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); - rt2x00_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER, + rt2800_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER, &eeprom); if (band == IEEE80211_BAND_2GHZ) @@ -3080,7 +3101,7 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, rt2800_register_read(rt2x00dev, offset, ®); /* read the next four txpower values */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + i, + rt2800_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + i, &eeprom); is_rate_b = i ? 0 : 1; @@ -3129,7 +3150,7 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, TX_PWR_CFG_RATE3, txpower); /* read the next four txpower values */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + i + 1, + rt2800_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + i + 1, &eeprom); is_rate_b = 0; @@ -3528,7 +3549,8 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) || rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) { - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, + &eeprom); if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_DAC_TEST)) rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x0000002c); @@ -3989,7 +4011,7 @@ static void rt2800_disable_unused_dac_adc(struct rt2x00_dev *rt2x00dev) u8 value; rt2800_bbp_read(rt2x00dev, 138, &value); - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1) value |= 0x20; if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1) @@ -4402,7 +4424,7 @@ static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) rt2800_disable_unused_dac_adc(rt2x00dev); - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); div_mode = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_ANT_DIVERSITY); ant = (div_mode == 3) ? 1 : 0; @@ -4488,7 +4510,7 @@ static void rt2800_init_bbp_5592(struct rt2x00_dev *rt2x00dev) rt2800_bbp4_mac_if_ctrl(rt2x00dev); - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); div_mode = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_ANT_DIVERSITY); ant = (div_mode == 3) ? 1 : 0; rt2800_bbp_read(rt2x00dev, 152, &value); @@ -4557,7 +4579,7 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) } for (i = 0; i < EEPROM_BBP_SIZE; i++) { - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom); if (eeprom != 0xffff && eeprom != 0x0000) { reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID); @@ -4728,7 +4750,7 @@ static void rt2800_normal_mode_setup_3xxx(struct rt2x00_dev *rt2x00dev) if (rt2x00_rt(rt2x00dev, RT3090)) { /* Turn off unused DAC1 and ADC1 to reduce power consumption */ rt2800_bbp_read(rt2x00dev, 138, &bbp); - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1) rt2x00_set_field8(&bbp, BBP138_RX_ADC1, 0); if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1) @@ -4778,7 +4800,7 @@ static void rt2800_normal_mode_setup_5xxx(struct rt2x00_dev *rt2x00dev) /* Turn off unused DAC1 and ADC1 to reduce power consumption */ rt2800_bbp_read(rt2x00dev, 138, ®); - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1) rt2x00_set_field8(®, BBP138_RX_ADC1, 0); if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1) @@ -4884,7 +4906,8 @@ static void rt2800_init_rfcsr_30xx(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) || rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E)) { - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, + &eeprom); if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_DAC_TEST)) rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 3); else @@ -5456,15 +5479,15 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev) /* * Initialize LED control */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_LED_AG_CONF, &word); + rt2800_eeprom_read(rt2x00dev, EEPROM_LED_AG_CONF, &word); rt2800_mcu_request(rt2x00dev, MCU_LED_AG_CONF, 0xff, word & 0xff, (word >> 8) & 0xff); - rt2x00_eeprom_read(rt2x00dev, EEPROM_LED_ACT_CONF, &word); + rt2800_eeprom_read(rt2x00dev, EEPROM_LED_ACT_CONF, &word); rt2800_mcu_request(rt2x00dev, MCU_LED_ACT_CONF, 0xff, word & 0xff, (word >> 8) & 0xff); - rt2x00_eeprom_read(rt2x00dev, EEPROM_LED_POLARITY, &word); + rt2800_eeprom_read(rt2x00dev, EEPROM_LED_POLARITY, &word); rt2800_mcu_request(rt2x00dev, MCU_LED_LED_POLARITY, 0xff, word & 0xff, (word >> 8) & 0xff); @@ -5578,18 +5601,18 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) /* * Start validation of the data that has been read. */ - mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); + mac = rt2800_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); if (!is_valid_ether_addr(mac)) { eth_random_addr(mac); rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", mac); } - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &word); + rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &word); if (word == 0xffff) { rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RXPATH, 2); rt2x00_set_field16(&word, EEPROM_NIC_CONF0_TXPATH, 1); rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RF_TYPE, RF2820); - rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word); + rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word); rt2x00_eeprom_dbg(rt2x00dev, "Antenna: 0x%04x\n", word); } else if (rt2x00_rt(rt2x00dev, RT2860) || rt2x00_rt(rt2x00dev, RT2872)) { @@ -5598,10 +5621,10 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) */ if (rt2x00_get_field16(word, EEPROM_NIC_CONF0_RXPATH) > 2) rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RXPATH, 2); - rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word); + rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word); } - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &word); + rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &word); if (word == 0xffff) { rt2x00_set_field16(&word, EEPROM_NIC_CONF1_HW_RADIO, 0); rt2x00_set_field16(&word, EEPROM_NIC_CONF1_EXTERNAL_TX_ALC, 0); @@ -5618,24 +5641,24 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_set_field16(&word, EEPROM_NIC_CONF1_INTERNAL_TX_ALC, 0); rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BT_COEXIST, 0); rt2x00_set_field16(&word, EEPROM_NIC_CONF1_DAC_TEST, 0); - rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC_CONF1, word); + rt2800_eeprom_write(rt2x00dev, EEPROM_NIC_CONF1, word); rt2x00_eeprom_dbg(rt2x00dev, "NIC: 0x%04x\n", word); } - rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word); + rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ, &word); if ((word & 0x00ff) == 0x00ff) { rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0); - rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word); + rt2800_eeprom_write(rt2x00dev, EEPROM_FREQ, word); rt2x00_eeprom_dbg(rt2x00dev, "Freq: 0x%04x\n", word); } if ((word & 0xff00) == 0xff00) { rt2x00_set_field16(&word, EEPROM_FREQ_LED_MODE, LED_MODE_TXRX_ACTIVITY); rt2x00_set_field16(&word, EEPROM_FREQ_LED_POLARITY, 0); - rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word); - rt2x00_eeprom_write(rt2x00dev, EEPROM_LED_AG_CONF, 0x5555); - rt2x00_eeprom_write(rt2x00dev, EEPROM_LED_ACT_CONF, 0x2221); - rt2x00_eeprom_write(rt2x00dev, EEPROM_LED_POLARITY, 0xa9f8); + rt2800_eeprom_write(rt2x00dev, EEPROM_FREQ, word); + rt2800_eeprom_write(rt2x00dev, EEPROM_LED_AG_CONF, 0x5555); + rt2800_eeprom_write(rt2x00dev, EEPROM_LED_ACT_CONF, 0x2221); + rt2800_eeprom_write(rt2x00dev, EEPROM_LED_POLARITY, 0xa9f8); rt2x00_eeprom_dbg(rt2x00dev, "Led Mode: 0x%04x\n", word); } @@ -5644,17 +5667,17 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) * lna0 as correct value. Note that EEPROM_LNA * is never validated. */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &word); + rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &word); default_lna_gain = rt2x00_get_field16(word, EEPROM_LNA_A0); - rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &word); + rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &word); if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET0)) > 10) rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET0, 0); if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET1)) > 10) rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET1, 0); - rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG, word); + rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_BG, word); - rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &word); + rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &word); if ((word & 0x00ff) != 0x00ff) { drv_data->txmixer_gain_24g = rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_BG_VAL); @@ -5662,16 +5685,16 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) drv_data->txmixer_gain_24g = 0; } - rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word); + rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word); if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10) rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0); if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 || rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff) rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1, default_lna_gain); - rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG2, word); + rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_BG2, word); - rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A, &word); + rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A, &word); if ((word & 0x00ff) != 0x00ff) { drv_data->txmixer_gain_5g = rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_A_VAL); @@ -5679,21 +5702,21 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) drv_data->txmixer_gain_5g = 0; } - rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word); + rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word); if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET0)) > 10) rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET0, 0); if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET1)) > 10) rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET1, 0); - rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A, word); + rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A, word); - rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word); + rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word); if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A2_OFFSET2)) > 10) rt2x00_set_field16(&word, EEPROM_RSSI_A2_OFFSET2, 0); if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 || rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff) rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2, default_lna_gain); - rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word); + rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word); return 0; } @@ -5707,7 +5730,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) /* * Read EEPROM word for configuration. */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); /* * Identify RF chipset by EEPROM value @@ -5717,7 +5740,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) if (rt2x00_rt(rt2x00dev, RT3290) || rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5392)) - rt2x00_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf); + rt2800_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &rf); else rf = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE); @@ -5757,7 +5780,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00dev->default_ant.rx_chain_num = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH); - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); if (rt2x00_rt(rt2x00dev, RT3070) || rt2x00_rt(rt2x00dev, RT3090) || @@ -5810,7 +5833,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) /* * Read frequency offset and RF programming sequence. */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET); /* @@ -5827,7 +5850,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) /* * Check if support EIRP tx power limit feature. */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER, &eeprom); if (rt2x00_get_field16(eeprom, EEPROM_EIRP_MAX_TX_POWER_2GHZ) < EIRP_MAX_TX_POWER_LIMIT) @@ -6148,7 +6171,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, - rt2x00_eeprom_addr(rt2x00dev, + rt2800_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0)); /* @@ -6164,7 +6187,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) rt2x00dev->hw->max_report_rates = 7; rt2x00dev->hw->max_rate_tries = 1; - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); + rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom); /* * Initialize hw_mode information. @@ -6264,8 +6287,8 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) spec->channels_info = info; - default_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1); - default_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2); + default_power1 = rt2800_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1); + default_power2 = rt2800_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2); for (i = 0; i < 14; i++) { info[i].default_power1 = default_power1[i]; @@ -6273,8 +6296,10 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) } if (spec->num_channels > 14) { - default_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1); - default_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2); + default_power1 = rt2800_eeprom_addr(rt2x00dev, + EEPROM_TXPOWER_A1); + default_power2 = rt2800_eeprom_addr(rt2x00dev, + EEPROM_TXPOWER_A2); for (i = 14; i < spec->num_channels; i++) { info[i].default_power1 = default_power1[i - 14]; -- cgit From 022138ca93f016374d5d3f69c070c75596c5ecac Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 8 Jul 2013 11:25:54 +0200 Subject: rt2x00: rt2800lib: introduce rt2800_eeprom_read_from_array helper Add a new helper function and use that for reading single elements of various arrays in the EEPROM. The patch does not change the current behaviour, but it allows to use sequential values for the rt2800_eeprom_word enums. The conversion will be implemented in a subsequent change. Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 522f0b19cd14..b59772a71b8b 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -239,6 +239,14 @@ static void rt2800_eeprom_write(struct rt2x00_dev *rt2x00dev, rt2x00_eeprom_write(rt2x00dev, word, data); } +static void rt2800_eeprom_read_from_array(struct rt2x00_dev *rt2x00dev, + const enum rt2800_eeprom_word array, + unsigned int offset, + u16 *data) +{ + rt2x00_eeprom_read(rt2x00dev, array + offset, data); +} + static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev) { u32 reg; @@ -2995,8 +3003,8 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b, * .11b data rate need add additional 4dbm * when calculating eirp txpower. */ - rt2800_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + 1, - &eeprom); + rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, + 1, &eeprom); criterion = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); @@ -3101,8 +3109,8 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, rt2800_register_read(rt2x00dev, offset, ®); /* read the next four txpower values */ - rt2800_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + i, - &eeprom); + rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, + i, &eeprom); is_rate_b = i ? 0 : 1; /* @@ -3150,8 +3158,8 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, TX_PWR_CFG_RATE3, txpower); /* read the next four txpower values */ - rt2800_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + i + 1, - &eeprom); + rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, + i + 1, &eeprom); is_rate_b = 0; /* @@ -4579,7 +4587,8 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) } for (i = 0; i < EEPROM_BBP_SIZE; i++) { - rt2800_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom); + rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_BBP_START, i, + &eeprom); if (eeprom != 0xffff && eeprom != 0x0000) { reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID); -- cgit From 379448fe34e289fdcc473399d4f6cac19e757fb8 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 8 Jul 2013 11:25:55 +0200 Subject: rt2x00: rt2800lib: introduce rt2800_eeprom_word_index helper Instead of assign the offset value to the enum directly use a new helper function to convert a rt2800_eeprom_word enum into an index of the rt2x00_dev->eeprom array. The patch does not change the existing behaviour, but makes it possible to add support for three-chain devices which are using a different EEPROM layout. Signed-off-by: Gabor Juhos Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800.h | 76 ++++++++++++++-------------- drivers/net/wireless/rt2x00/rt2800lib.c | 87 +++++++++++++++++++++++++++++++-- 2 files changed, 122 insertions(+), 41 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 064703933f7c..bc5c69558ea2 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -2207,43 +2207,45 @@ struct mac_iveiv_entry { */ enum rt2800_eeprom_word { - EEPROM_CHIP_ID = 0x0000, - EEPROM_VERSION = 0x0001, - EEPROM_MAC_ADDR_0 = 0x0002, - EEPROM_MAC_ADDR_1 = 0x0003, - EEPROM_MAC_ADDR_2 = 0x0004, - EEPROM_NIC_CONF0 = 0x001a, - EEPROM_NIC_CONF1 = 0x001b, - EEPROM_FREQ = 0x001d, - EEPROM_LED_AG_CONF = 0x001e, - EEPROM_LED_ACT_CONF = 0x001f, - EEPROM_LED_POLARITY = 0x0020, - EEPROM_NIC_CONF2 = 0x0021, - EEPROM_LNA = 0x0022, - EEPROM_RSSI_BG = 0x0023, - EEPROM_RSSI_BG2 = 0x0024, - EEPROM_TXMIXER_GAIN_BG = 0x0024, /* overlaps with RSSI_BG2 */ - EEPROM_RSSI_A = 0x0025, - EEPROM_RSSI_A2 = 0x0026, - EEPROM_TXMIXER_GAIN_A = 0x0026, /* overlaps with RSSI_A2 */ - EEPROM_EIRP_MAX_TX_POWER = 0x0027, - EEPROM_TXPOWER_DELTA = 0x0028, - EEPROM_TXPOWER_BG1 = 0x0029, - EEPROM_TXPOWER_BG2 = 0x0030, - EEPROM_TSSI_BOUND_BG1 = 0x0037, - EEPROM_TSSI_BOUND_BG2 = 0x0038, - EEPROM_TSSI_BOUND_BG3 = 0x0039, - EEPROM_TSSI_BOUND_BG4 = 0x003a, - EEPROM_TSSI_BOUND_BG5 = 0x003b, - EEPROM_TXPOWER_A1 = 0x003c, - EEPROM_TXPOWER_A2 = 0x0053, - EEPROM_TSSI_BOUND_A1 = 0x006a, - EEPROM_TSSI_BOUND_A2 = 0x006b, - EEPROM_TSSI_BOUND_A3 = 0x006c, - EEPROM_TSSI_BOUND_A4 = 0x006d, - EEPROM_TSSI_BOUND_A5 = 0x006e, - EEPROM_TXPOWER_BYRATE = 0x006f, - EEPROM_BBP_START = 0x0078, + EEPROM_CHIP_ID = 0, + EEPROM_VERSION, + EEPROM_MAC_ADDR_0, + EEPROM_MAC_ADDR_1, + EEPROM_MAC_ADDR_2, + EEPROM_NIC_CONF0, + EEPROM_NIC_CONF1, + EEPROM_FREQ, + EEPROM_LED_AG_CONF, + EEPROM_LED_ACT_CONF, + EEPROM_LED_POLARITY, + EEPROM_NIC_CONF2, + EEPROM_LNA, + EEPROM_RSSI_BG, + EEPROM_RSSI_BG2, + EEPROM_TXMIXER_GAIN_BG, + EEPROM_RSSI_A, + EEPROM_RSSI_A2, + EEPROM_TXMIXER_GAIN_A, + EEPROM_EIRP_MAX_TX_POWER, + EEPROM_TXPOWER_DELTA, + EEPROM_TXPOWER_BG1, + EEPROM_TXPOWER_BG2, + EEPROM_TSSI_BOUND_BG1, + EEPROM_TSSI_BOUND_BG2, + EEPROM_TSSI_BOUND_BG3, + EEPROM_TSSI_BOUND_BG4, + EEPROM_TSSI_BOUND_BG5, + EEPROM_TXPOWER_A1, + EEPROM_TXPOWER_A2, + EEPROM_TSSI_BOUND_A1, + EEPROM_TSSI_BOUND_A2, + EEPROM_TSSI_BOUND_A3, + EEPROM_TSSI_BOUND_A4, + EEPROM_TSSI_BOUND_A5, + EEPROM_TXPOWER_BYRATE, + EEPROM_BBP_START, + /* New values must be added before this */ + EEPROM_WORD_COUNT }; /* diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index b59772a71b8b..41a34de4a3e2 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -221,22 +221,98 @@ static void rt2800_rf_write(struct rt2x00_dev *rt2x00dev, mutex_unlock(&rt2x00dev->csr_mutex); } +static const unsigned int rt2800_eeprom_map[EEPROM_WORD_COUNT] = { + [EEPROM_CHIP_ID] = 0x0000, + [EEPROM_VERSION] = 0x0001, + [EEPROM_MAC_ADDR_0] = 0x0002, + [EEPROM_MAC_ADDR_1] = 0x0003, + [EEPROM_MAC_ADDR_2] = 0x0004, + [EEPROM_NIC_CONF0] = 0x001a, + [EEPROM_NIC_CONF1] = 0x001b, + [EEPROM_FREQ] = 0x001d, + [EEPROM_LED_AG_CONF] = 0x001e, + [EEPROM_LED_ACT_CONF] = 0x001f, + [EEPROM_LED_POLARITY] = 0x0020, + [EEPROM_NIC_CONF2] = 0x0021, + [EEPROM_LNA] = 0x0022, + [EEPROM_RSSI_BG] = 0x0023, + [EEPROM_RSSI_BG2] = 0x0024, + [EEPROM_TXMIXER_GAIN_BG] = 0x0024, /* overlaps with RSSI_BG2 */ + [EEPROM_RSSI_A] = 0x0025, + [EEPROM_RSSI_A2] = 0x0026, + [EEPROM_TXMIXER_GAIN_A] = 0x0026, /* overlaps with RSSI_A2 */ + [EEPROM_EIRP_MAX_TX_POWER] = 0x0027, + [EEPROM_TXPOWER_DELTA] = 0x0028, + [EEPROM_TXPOWER_BG1] = 0x0029, + [EEPROM_TXPOWER_BG2] = 0x0030, + [EEPROM_TSSI_BOUND_BG1] = 0x0037, + [EEPROM_TSSI_BOUND_BG2] = 0x0038, + [EEPROM_TSSI_BOUND_BG3] = 0x0039, + [EEPROM_TSSI_BOUND_BG4] = 0x003a, + [EEPROM_TSSI_BOUND_BG5] = 0x003b, + [EEPROM_TXPOWER_A1] = 0x003c, + [EEPROM_TXPOWER_A2] = 0x0053, + [EEPROM_TSSI_BOUND_A1] = 0x006a, + [EEPROM_TSSI_BOUND_A2] = 0x006b, + [EEPROM_TSSI_BOUND_A3] = 0x006c, + [EEPROM_TSSI_BOUND_A4] = 0x006d, + [EEPROM_TSSI_BOUND_A5] = 0x006e, + [EEPROM_TXPOWER_BYRATE] = 0x006f, + [EEPROM_BBP_START] = 0x0078, +}; + +static unsigned int rt2800_eeprom_word_index(struct rt2x00_dev *rt2x00dev, + const enum rt2800_eeprom_word word) +{ + const unsigned int *map; + unsigned int index; + + if (WARN_ONCE(word >= EEPROM_WORD_COUNT, + "%s: invalid EEPROM word %d\n", + wiphy_name(rt2x00dev->hw->wiphy), word)) + return 0; + + map = rt2800_eeprom_map; + index = map[word]; + + /* Index 0 is valid only for EEPROM_CHIP_ID. + * Otherwise it means that the offset of the + * given word is not initialized in the map, + * or that the field is not usable on the + * actual chipset. + */ + WARN_ONCE(word != EEPROM_CHIP_ID && index == 0, + "%s: invalid access of EEPROM word %d\n", + wiphy_name(rt2x00dev->hw->wiphy), word); + + return index; +} + static void *rt2800_eeprom_addr(struct rt2x00_dev *rt2x00dev, const enum rt2800_eeprom_word word) { - return rt2x00_eeprom_addr(rt2x00dev, word); + unsigned int index; + + index = rt2800_eeprom_word_index(rt2x00dev, word); + return rt2x00_eeprom_addr(rt2x00dev, index); } static void rt2800_eeprom_read(struct rt2x00_dev *rt2x00dev, const enum rt2800_eeprom_word word, u16 *data) { - rt2x00_eeprom_read(rt2x00dev, word, data); + unsigned int index; + + index = rt2800_eeprom_word_index(rt2x00dev, word); + rt2x00_eeprom_read(rt2x00dev, index, data); } static void rt2800_eeprom_write(struct rt2x00_dev *rt2x00dev, const enum rt2800_eeprom_word word, u16 data) { - rt2x00_eeprom_write(rt2x00dev, word, data); + unsigned int index; + + index = rt2800_eeprom_word_index(rt2x00dev, word); + rt2x00_eeprom_write(rt2x00dev, index, data); } static void rt2800_eeprom_read_from_array(struct rt2x00_dev *rt2x00dev, @@ -244,7 +320,10 @@ static void rt2800_eeprom_read_from_array(struct rt2x00_dev *rt2x00dev, unsigned int offset, u16 *data) { - rt2x00_eeprom_read(rt2x00dev, array + offset, data); + unsigned int index; + + index = rt2800_eeprom_word_index(rt2x00dev, array); + rt2x00_eeprom_read(rt2x00dev, index + offset, data); } static int rt2800_enable_wlan_rt3290(struct rt2x00_dev *rt2x00dev) -- cgit From fa31d157f83ef71b6530aacf0400bafe7816acbd Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 8 Jul 2013 11:25:56 +0200 Subject: rt2x00: rt2800lib: add EEPROM map for the RT3593 chipset Three-chain devices are using a different EEPROM layout than the rest of the chipsets. Add a new map which describes the new layout and use that for the RT3593 chipset. The index values has been computed from the EEPROM_EXT_* defines, which can be found in the 'include/chip/rt3593.h' file in the Ralink DPO_RT5572_LinuxSTA_2.6.0.1_20120629 driver. Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800.h | 6 +++++ drivers/net/wireless/rt2x00/rt2800lib.c | 48 ++++++++++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index bc5c69558ea2..92168347125b 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -2244,6 +2244,12 @@ enum rt2800_eeprom_word { EEPROM_TSSI_BOUND_A5, EEPROM_TXPOWER_BYRATE, EEPROM_BBP_START, + + /* IDs for extended EEPROM format used by three-chain devices */ + EEPROM_EXT_LNA2, + EEPROM_EXT_TXPOWER_BG3, + EEPROM_EXT_TXPOWER_A3, + /* New values must be added before this */ EEPROM_WORD_COUNT }; diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 41a34de4a3e2..d325ca202865 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -261,6 +261,48 @@ static const unsigned int rt2800_eeprom_map[EEPROM_WORD_COUNT] = { [EEPROM_BBP_START] = 0x0078, }; +static const unsigned int rt2800_eeprom_map_ext[EEPROM_WORD_COUNT] = { + [EEPROM_CHIP_ID] = 0x0000, + [EEPROM_VERSION] = 0x0001, + [EEPROM_MAC_ADDR_0] = 0x0002, + [EEPROM_MAC_ADDR_1] = 0x0003, + [EEPROM_MAC_ADDR_2] = 0x0004, + [EEPROM_NIC_CONF0] = 0x001a, + [EEPROM_NIC_CONF1] = 0x001b, + [EEPROM_NIC_CONF2] = 0x001c, + [EEPROM_EIRP_MAX_TX_POWER] = 0x0020, + [EEPROM_FREQ] = 0x0022, + [EEPROM_LED_AG_CONF] = 0x0023, + [EEPROM_LED_ACT_CONF] = 0x0024, + [EEPROM_LED_POLARITY] = 0x0025, + [EEPROM_LNA] = 0x0026, + [EEPROM_EXT_LNA2] = 0x0027, + [EEPROM_RSSI_BG] = 0x0028, + [EEPROM_TXPOWER_DELTA] = 0x0028, /* Overlaps with RSSI_BG */ + [EEPROM_RSSI_BG2] = 0x0029, + [EEPROM_TXMIXER_GAIN_BG] = 0x0029, /* Overlaps with RSSI_BG2 */ + [EEPROM_RSSI_A] = 0x002a, + [EEPROM_RSSI_A2] = 0x002b, + [EEPROM_TXMIXER_GAIN_A] = 0x002b, /* Overlaps with RSSI_A2 */ + [EEPROM_TXPOWER_BG1] = 0x0030, + [EEPROM_TXPOWER_BG2] = 0x0037, + [EEPROM_EXT_TXPOWER_BG3] = 0x003e, + [EEPROM_TSSI_BOUND_BG1] = 0x0045, + [EEPROM_TSSI_BOUND_BG2] = 0x0046, + [EEPROM_TSSI_BOUND_BG3] = 0x0047, + [EEPROM_TSSI_BOUND_BG4] = 0x0048, + [EEPROM_TSSI_BOUND_BG5] = 0x0049, + [EEPROM_TXPOWER_A1] = 0x004b, + [EEPROM_TXPOWER_A2] = 0x0065, + [EEPROM_EXT_TXPOWER_A3] = 0x007f, + [EEPROM_TSSI_BOUND_A1] = 0x009a, + [EEPROM_TSSI_BOUND_A2] = 0x009b, + [EEPROM_TSSI_BOUND_A3] = 0x009c, + [EEPROM_TSSI_BOUND_A4] = 0x009d, + [EEPROM_TSSI_BOUND_A5] = 0x009e, + [EEPROM_TXPOWER_BYRATE] = 0x00a0, +}; + static unsigned int rt2800_eeprom_word_index(struct rt2x00_dev *rt2x00dev, const enum rt2800_eeprom_word word) { @@ -272,7 +314,11 @@ static unsigned int rt2800_eeprom_word_index(struct rt2x00_dev *rt2x00dev, wiphy_name(rt2x00dev->hw->wiphy), word)) return 0; - map = rt2800_eeprom_map; + if (rt2x00_rt(rt2x00dev, RT3593)) + map = rt2800_eeprom_map_ext; + else + map = rt2800_eeprom_map; + index = map[word]; /* Index 0 is valid only for EEPROM_CHIP_ID. -- cgit From 1706d15d82f4a579119b419cd673987af60f1d9b Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 8 Jul 2013 16:08:16 +0200 Subject: rt2x00: rt2800lib: add MAC register initialization for RT3593 Based on the Ralink DPO_RT5572_LinuxSTA_2.6.0.1_20120629 driver. Reference: NICInitRT3593MacRegisters in chips/rt3593.c Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800.h | 1 + drivers/net/wireless/rt2x00/rt2800lib.c | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 92168347125b..02bc80dc7b5f 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -88,6 +88,7 @@ #define REV_RT3071E 0x0211 #define REV_RT3090E 0x0211 #define REV_RT3390E 0x0211 +#define REV_RT3593E 0x0211 #define REV_RT5390F 0x0502 #define REV_RT5390R 0x1502 #define REV_RT5592C 0x0221 diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index d325ca202865..bfeca299acb9 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -3714,6 +3714,23 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) } else if (rt2x00_rt(rt2x00dev, RT3572)) { rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); + } else if (rt2x00_rt(rt2x00dev, RT3593)) { + rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000402); + rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); + if (rt2x00_rt_rev_lt(rt2x00dev, RT3593, REV_RT3593E)) { + rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, + &eeprom); + if (rt2x00_get_field16(eeprom, + EEPROM_NIC_CONF1_DAC_TEST)) + rt2800_register_write(rt2x00dev, TX_SW_CFG2, + 0x0000001f); + else + rt2800_register_write(rt2x00dev, TX_SW_CFG2, + 0x0000000f); + } else { + rt2800_register_write(rt2x00dev, TX_SW_CFG2, + 0x00000000); + } } else if (rt2x00_rt(rt2x00dev, RT5390) || rt2x00_rt(rt2x00dev, RT5392) || rt2x00_rt(rt2x00dev, RT5592)) { -- cgit From b189a1814135bc52f516ca61a1fa161914d57a54 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 8 Jul 2013 16:08:17 +0200 Subject: rt2x00: rt2800lib: add BBP register initialization for RT3593 Based on the Ralink DPO_RT5572_LinuxSTA_2.6.0.1_20120629 driver. References: NICInitRT3593BbpRegisters in chips/rt3593.c NICInitBBP in common/rtmp_init.c NICInitAsicFromEEPROM in common/rtmp_init.c Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index bfeca299acb9..53ebdb96818d 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -4504,6 +4504,22 @@ static void rt2800_init_bbp_3572(struct rt2x00_dev *rt2x00dev) rt2800_disable_unused_dac_adc(rt2x00dev); } +static void rt2800_init_bbp_3593(struct rt2x00_dev *rt2x00dev) +{ + rt2800_init_bbp_early(rt2x00dev); + + rt2800_bbp_write(rt2x00dev, 79, 0x13); + rt2800_bbp_write(rt2x00dev, 80, 0x05); + rt2800_bbp_write(rt2x00dev, 81, 0x33); + rt2800_bbp_write(rt2x00dev, 137, 0x0f); + + rt2800_bbp_write(rt2x00dev, 84, 0x19); + + /* Enable DC filter */ + if (rt2x00_rt_rev_gte(rt2x00dev, RT3593, REV_RT3593E)) + rt2800_bbp_write(rt2x00dev, 103, 0xc0); +} + static void rt2800_init_bbp_53xx(struct rt2x00_dev *rt2x00dev) { int ant, div_mode; @@ -4719,6 +4735,9 @@ static void rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) case RT3572: rt2800_init_bbp_3572(rt2x00dev); break; + case RT3593: + rt2800_init_bbp_3593(rt2x00dev); + return; case RT5390: case RT5392: rt2800_init_bbp_53xx(rt2x00dev); -- cgit From ab7078ac3d920e0d49b17e92f327f3ada25600e8 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 8 Jul 2013 16:08:18 +0200 Subject: rt2x00: rt2800lib: add RFCSR register initialization for RT3593 Based on the Ralink DPO_RT5572_LinuxSTA_2.6.0.1_20120629 driver. References: NICInitRT3593RFRegisters in chips/rt3593.c RT3593LoadRFNormalModeSetup in chips/rt3593.c Signed-off-by: Gabor Juhos Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800.h | 10 +++ drivers/net/wireless/rt2x00/rt2800lib.c | 122 ++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 02bc80dc7b5f..47aceaea5d66 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -2093,6 +2093,10 @@ struct mac_iveiv_entry { #define RFCSR17_R FIELD8(0x20) #define RFCSR17_CODE FIELD8(0x7f) +/* RFCSR 18 */ +#define RFCSR18_XO_TUNE_BYPASS FIELD8(0x40) + + /* * RFCSR 20: */ @@ -2174,6 +2178,12 @@ struct mac_iveiv_entry { */ #define RFCSR50_TX FIELD8(0x3f) #define RFCSR50_EP FIELD8(0xc0) +/* bits for RT3593*/ +#define RFCSR50_TX_LO2_EN FIELD8(0x10) + +/* RFCSR 51 */ +/* bits for RT3593*/ +#define RFCSR51_BITS24 FIELD8(0x1c) /* * RF registers diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 53ebdb96818d..b6505699629a 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -4963,6 +4963,42 @@ static void rt2800_normal_mode_setup_3xxx(struct rt2x00_dev *rt2x00dev) } } +static void rt2800_normal_mode_setup_3593(struct rt2x00_dev *rt2x00dev) +{ + struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; + u8 rfcsr; + u8 tx_gain; + + rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR50_TX_LO2_EN, 0); + rt2800_rfcsr_write(rt2x00dev, 50, rfcsr); + + rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr); + tx_gain = rt2x00_get_field8(drv_data->txmixer_gain_24g, + RFCSR17_TXMIXER_GAIN); + rt2x00_set_field8(&rfcsr, RFCSR51_BITS24, tx_gain); + rt2800_rfcsr_write(rt2x00dev, 51, rfcsr); + + rt2800_rfcsr_read(rt2x00dev, 38, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR38_RX_LO1_EN, 0); + rt2800_rfcsr_write(rt2x00dev, 38, rfcsr); + + rt2800_rfcsr_read(rt2x00dev, 39, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR39_RX_LO2_EN, 0); + rt2800_rfcsr_write(rt2x00dev, 39, rfcsr); + + rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1); + rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1); + rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); + + rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR30_RX_VCM, 2); + rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); + + /* TODO: enable stream mode */ +} + static void rt2800_normal_mode_setup_5xxx(struct rt2x00_dev *rt2x00dev) { u8 reg; @@ -5345,6 +5381,89 @@ static void rt2800_init_rfcsr_3572(struct rt2x00_dev *rt2x00dev) rt2800_normal_mode_setup_3xxx(rt2x00dev); } +static void rt2800_init_rfcsr_3593(struct rt2x00_dev *rt2x00dev) +{ + struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; + u32 reg; + u8 rfcsr; + + /* Disable GPIO #4 and #7 function for LAN PE control */ + rt2800_register_read(rt2x00dev, GPIO_SWITCH, ®); + rt2x00_set_field32(®, GPIO_SWITCH_4, 0); + rt2x00_set_field32(®, GPIO_SWITCH_7, 0); + rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg); + + /* Initialize default register values */ + rt2800_rfcsr_write(rt2x00dev, 1, 0x03); + rt2800_rfcsr_write(rt2x00dev, 3, 0x80); + rt2800_rfcsr_write(rt2x00dev, 5, 0x00); + rt2800_rfcsr_write(rt2x00dev, 6, 0x40); + rt2800_rfcsr_write(rt2x00dev, 8, 0xf1); + rt2800_rfcsr_write(rt2x00dev, 9, 0x02); + rt2800_rfcsr_write(rt2x00dev, 10, 0xd3); + rt2800_rfcsr_write(rt2x00dev, 11, 0x40); + rt2800_rfcsr_write(rt2x00dev, 12, 0x4e); + rt2800_rfcsr_write(rt2x00dev, 13, 0x12); + rt2800_rfcsr_write(rt2x00dev, 18, 0x40); + rt2800_rfcsr_write(rt2x00dev, 22, 0x20); + rt2800_rfcsr_write(rt2x00dev, 30, 0x10); + rt2800_rfcsr_write(rt2x00dev, 31, 0x80); + rt2800_rfcsr_write(rt2x00dev, 32, 0x78); + rt2800_rfcsr_write(rt2x00dev, 33, 0x3b); + rt2800_rfcsr_write(rt2x00dev, 34, 0x3c); + rt2800_rfcsr_write(rt2x00dev, 35, 0xe0); + rt2800_rfcsr_write(rt2x00dev, 38, 0x86); + rt2800_rfcsr_write(rt2x00dev, 39, 0x23); + rt2800_rfcsr_write(rt2x00dev, 44, 0xd3); + rt2800_rfcsr_write(rt2x00dev, 45, 0xbb); + rt2800_rfcsr_write(rt2x00dev, 46, 0x60); + rt2800_rfcsr_write(rt2x00dev, 49, 0x8e); + rt2800_rfcsr_write(rt2x00dev, 50, 0x86); + rt2800_rfcsr_write(rt2x00dev, 51, 0x75); + rt2800_rfcsr_write(rt2x00dev, 52, 0x45); + rt2800_rfcsr_write(rt2x00dev, 53, 0x18); + rt2800_rfcsr_write(rt2x00dev, 54, 0x18); + rt2800_rfcsr_write(rt2x00dev, 55, 0x18); + rt2800_rfcsr_write(rt2x00dev, 56, 0xdb); + rt2800_rfcsr_write(rt2x00dev, 57, 0x6e); + + /* Initiate calibration */ + /* TODO: use rt2800_rf_init_calibration ? */ + rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1); + rt2800_rfcsr_write(rt2x00dev, 2, rfcsr); + + rt2800_adjust_freq_offset(rt2x00dev); + + rt2800_rfcsr_read(rt2x00dev, 18, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR18_XO_TUNE_BYPASS, 1); + rt2800_rfcsr_write(rt2x00dev, 18, rfcsr); + + rt2800_register_read(rt2x00dev, LDO_CFG0, ®); + rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 3); + rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1); + rt2800_register_write(rt2x00dev, LDO_CFG0, reg); + usleep_range(1000, 1500); + rt2800_register_read(rt2x00dev, LDO_CFG0, ®); + rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 0); + rt2800_register_write(rt2x00dev, LDO_CFG0, reg); + + /* Set initial values for RX filter calibration */ + drv_data->calibration_bw20 = 0x1f; + drv_data->calibration_bw40 = 0x2f; + + /* Save BBP 25 & 26 values for later use in channel switching */ + rt2800_bbp_read(rt2x00dev, 25, &drv_data->bbp25); + rt2800_bbp_read(rt2x00dev, 26, &drv_data->bbp26); + + rt2800_led_open_drain_enable(rt2x00dev); + rt2800_normal_mode_setup_3593(rt2x00dev); + + /* TODO: post BBP initialization */ + + /* TODO: enable stream mode support */ +} + static void rt2800_init_rfcsr_5390(struct rt2x00_dev *rt2x00dev) { rt2800_rf_init_calibration(rt2x00dev, 2); @@ -5573,6 +5692,9 @@ static void rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) case RT3572: rt2800_init_rfcsr_3572(rt2x00dev); break; + case RT3593: + rt2800_init_rfcsr_3593(rt2x00dev); + break; case RT5390: rt2800_init_rfcsr_5390(rt2x00dev); break; -- cgit From d63f7e8ca560dc9a76a15c323cb9cba14b25f430 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 8 Jul 2013 16:08:19 +0200 Subject: rt2x00: rt2800lib: add BBP post initialization for RT3593 Based on the Ralink DPO_RT5572_LinuxSTA_2.6.0.1_20120629 driver. Reference: RT3593_PostBBPInitialization in chips/rt3553.c Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 48 ++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index b6505699629a..7b5c593b6118 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -5381,6 +5381,52 @@ static void rt2800_init_rfcsr_3572(struct rt2x00_dev *rt2x00dev) rt2800_normal_mode_setup_3xxx(rt2x00dev); } +static void rt3593_post_bbp_init(struct rt2x00_dev *rt2x00dev) +{ + u8 bbp; + bool txbf_enabled = false; /* FIXME */ + + rt2800_bbp_read(rt2x00dev, 105, &bbp); + if (rt2x00dev->default_ant.rx_chain_num == 1) + rt2x00_set_field8(&bbp, BBP105_MLD, 0); + else + rt2x00_set_field8(&bbp, BBP105_MLD, 1); + rt2800_bbp_write(rt2x00dev, 105, bbp); + + rt2800_bbp4_mac_if_ctrl(rt2x00dev); + + rt2800_bbp_write(rt2x00dev, 92, 0x02); + rt2800_bbp_write(rt2x00dev, 82, 0x82); + rt2800_bbp_write(rt2x00dev, 106, 0x05); + rt2800_bbp_write(rt2x00dev, 104, 0x92); + rt2800_bbp_write(rt2x00dev, 88, 0x90); + rt2800_bbp_write(rt2x00dev, 148, 0xc8); + rt2800_bbp_write(rt2x00dev, 47, 0x48); + rt2800_bbp_write(rt2x00dev, 120, 0x50); + + if (txbf_enabled) + rt2800_bbp_write(rt2x00dev, 163, 0xbd); + else + rt2800_bbp_write(rt2x00dev, 163, 0x9d); + + /* SNR mapping */ + rt2800_bbp_write(rt2x00dev, 142, 6); + rt2800_bbp_write(rt2x00dev, 143, 160); + rt2800_bbp_write(rt2x00dev, 142, 7); + rt2800_bbp_write(rt2x00dev, 143, 161); + rt2800_bbp_write(rt2x00dev, 142, 8); + rt2800_bbp_write(rt2x00dev, 143, 162); + + /* ADC/DAC control */ + rt2800_bbp_write(rt2x00dev, 31, 0x08); + + /* RX AGC energy lower bound in log2 */ + rt2800_bbp_write(rt2x00dev, 68, 0x0b); + + /* FIXME: BBP 105 owerwrite? */ + rt2800_bbp_write(rt2x00dev, 105, 0x04); +} + static void rt2800_init_rfcsr_3593(struct rt2x00_dev *rt2x00dev) { struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; @@ -5459,7 +5505,7 @@ static void rt2800_init_rfcsr_3593(struct rt2x00_dev *rt2x00dev) rt2800_led_open_drain_enable(rt2x00dev); rt2800_normal_mode_setup_3593(rt2x00dev); - /* TODO: post BBP initialization */ + rt3593_post_bbp_init(rt2x00dev); /* TODO: enable stream mode support */ } -- cgit From 34542ff5a665061d548c3f860807df341f718adf Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 8 Jul 2013 16:08:20 +0200 Subject: rt2x00: rt2800lib: add TX power configuration for RT3593 Based on the Ralink DPO_RT5572_LinuxSTA_2.6.0.1_20120629 driver. References: RTMPReadTxPwrPerRateExt in chips/rt3593.c RT3593_AsicGetTxPowerOffset in chips/rt3593.c Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800.h | 116 +++++++++ drivers/net/wireless/rt2x00/rt2800lib.c | 425 +++++++++++++++++++++++++++++++- 2 files changed, 538 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 47aceaea5d66..7b7caeb01e5a 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -1083,6 +1083,15 @@ #define TX_PWR_CFG_0_9MBS FIELD32(0x00f00000) #define TX_PWR_CFG_0_12MBS FIELD32(0x0f000000) #define TX_PWR_CFG_0_18MBS FIELD32(0xf0000000) +/* bits for 3T devices */ +#define TX_PWR_CFG_0_CCK1_CH0 FIELD32(0x0000000f) +#define TX_PWR_CFG_0_CCK1_CH1 FIELD32(0x000000f0) +#define TX_PWR_CFG_0_CCK5_CH0 FIELD32(0x00000f00) +#define TX_PWR_CFG_0_CCK5_CH1 FIELD32(0x0000f000) +#define TX_PWR_CFG_0_OFDM6_CH0 FIELD32(0x000f0000) +#define TX_PWR_CFG_0_OFDM6_CH1 FIELD32(0x00f00000) +#define TX_PWR_CFG_0_OFDM12_CH0 FIELD32(0x0f000000) +#define TX_PWR_CFG_0_OFDM12_CH1 FIELD32(0xf0000000) /* * TX_PWR_CFG_1: @@ -1096,6 +1105,15 @@ #define TX_PWR_CFG_1_MCS1 FIELD32(0x00f00000) #define TX_PWR_CFG_1_MCS2 FIELD32(0x0f000000) #define TX_PWR_CFG_1_MCS3 FIELD32(0xf0000000) +/* bits for 3T devices */ +#define TX_PWR_CFG_1_OFDM24_CH0 FIELD32(0x0000000f) +#define TX_PWR_CFG_1_OFDM24_CH1 FIELD32(0x000000f0) +#define TX_PWR_CFG_1_OFDM48_CH0 FIELD32(0x00000f00) +#define TX_PWR_CFG_1_OFDM48_CH1 FIELD32(0x0000f000) +#define TX_PWR_CFG_1_MCS0_CH0 FIELD32(0x000f0000) +#define TX_PWR_CFG_1_MCS0_CH1 FIELD32(0x00f00000) +#define TX_PWR_CFG_1_MCS2_CH0 FIELD32(0x0f000000) +#define TX_PWR_CFG_1_MCS2_CH1 FIELD32(0xf0000000) /* * TX_PWR_CFG_2: @@ -1109,6 +1127,15 @@ #define TX_PWR_CFG_2_MCS9 FIELD32(0x00f00000) #define TX_PWR_CFG_2_MCS10 FIELD32(0x0f000000) #define TX_PWR_CFG_2_MCS11 FIELD32(0xf0000000) +/* bits for 3T devices */ +#define TX_PWR_CFG_2_MCS4_CH0 FIELD32(0x0000000f) +#define TX_PWR_CFG_2_MCS4_CH1 FIELD32(0x000000f0) +#define TX_PWR_CFG_2_MCS6_CH0 FIELD32(0x00000f00) +#define TX_PWR_CFG_2_MCS6_CH1 FIELD32(0x0000f000) +#define TX_PWR_CFG_2_MCS8_CH0 FIELD32(0x000f0000) +#define TX_PWR_CFG_2_MCS8_CH1 FIELD32(0x00f00000) +#define TX_PWR_CFG_2_MCS10_CH0 FIELD32(0x0f000000) +#define TX_PWR_CFG_2_MCS10_CH1 FIELD32(0xf0000000) /* * TX_PWR_CFG_3: @@ -1122,6 +1149,15 @@ #define TX_PWR_CFG_3_UKNOWN2 FIELD32(0x00f00000) #define TX_PWR_CFG_3_UKNOWN3 FIELD32(0x0f000000) #define TX_PWR_CFG_3_UKNOWN4 FIELD32(0xf0000000) +/* bits for 3T devices */ +#define TX_PWR_CFG_3_MCS12_CH0 FIELD32(0x0000000f) +#define TX_PWR_CFG_3_MCS12_CH1 FIELD32(0x000000f0) +#define TX_PWR_CFG_3_MCS14_CH0 FIELD32(0x00000f00) +#define TX_PWR_CFG_3_MCS14_CH1 FIELD32(0x0000f000) +#define TX_PWR_CFG_3_STBC0_CH0 FIELD32(0x000f0000) +#define TX_PWR_CFG_3_STBC0_CH1 FIELD32(0x00f00000) +#define TX_PWR_CFG_3_STBC2_CH0 FIELD32(0x0f000000) +#define TX_PWR_CFG_3_STBC2_CH1 FIELD32(0xf0000000) /* * TX_PWR_CFG_4: @@ -1131,6 +1167,11 @@ #define TX_PWR_CFG_4_UKNOWN6 FIELD32(0x000000f0) #define TX_PWR_CFG_4_UKNOWN7 FIELD32(0x00000f00) #define TX_PWR_CFG_4_UKNOWN8 FIELD32(0x0000f000) +/* bits for 3T devices */ +#define TX_PWR_CFG_3_STBC4_CH0 FIELD32(0x0000000f) +#define TX_PWR_CFG_3_STBC4_CH1 FIELD32(0x000000f0) +#define TX_PWR_CFG_3_STBC6_CH0 FIELD32(0x00000f00) +#define TX_PWR_CFG_3_STBC6_CH1 FIELD32(0x0000f000) /* * TX_PIN_CFG: @@ -1452,6 +1493,81 @@ */ #define EXP_ACK_TIME 0x1380 +/* TX_PWR_CFG_5 */ +#define TX_PWR_CFG_5 0x1384 +#define TX_PWR_CFG_5_MCS16_CH0 FIELD32(0x0000000f) +#define TX_PWR_CFG_5_MCS16_CH1 FIELD32(0x000000f0) +#define TX_PWR_CFG_5_MCS16_CH2 FIELD32(0x00000f00) +#define TX_PWR_CFG_5_MCS18_CH0 FIELD32(0x000f0000) +#define TX_PWR_CFG_5_MCS18_CH1 FIELD32(0x00f00000) +#define TX_PWR_CFG_5_MCS18_CH2 FIELD32(0x0f000000) + +/* TX_PWR_CFG_6 */ +#define TX_PWR_CFG_6 0x1388 +#define TX_PWR_CFG_6_MCS20_CH0 FIELD32(0x0000000f) +#define TX_PWR_CFG_6_MCS20_CH1 FIELD32(0x000000f0) +#define TX_PWR_CFG_6_MCS20_CH2 FIELD32(0x00000f00) +#define TX_PWR_CFG_6_MCS22_CH0 FIELD32(0x000f0000) +#define TX_PWR_CFG_6_MCS22_CH1 FIELD32(0x00f00000) +#define TX_PWR_CFG_6_MCS22_CH2 FIELD32(0x0f000000) + +/* TX_PWR_CFG_0_EXT */ +#define TX_PWR_CFG_0_EXT 0x1390 +#define TX_PWR_CFG_0_EXT_CCK1_CH2 FIELD32(0x0000000f) +#define TX_PWR_CFG_0_EXT_CCK5_CH2 FIELD32(0x00000f00) +#define TX_PWR_CFG_0_EXT_OFDM6_CH2 FIELD32(0x000f0000) +#define TX_PWR_CFG_0_EXT_OFDM12_CH2 FIELD32(0x0f000000) + +/* TX_PWR_CFG_1_EXT */ +#define TX_PWR_CFG_1_EXT 0x1394 +#define TX_PWR_CFG_1_EXT_OFDM24_CH2 FIELD32(0x0000000f) +#define TX_PWR_CFG_1_EXT_OFDM48_CH2 FIELD32(0x00000f00) +#define TX_PWR_CFG_1_EXT_MCS0_CH2 FIELD32(0x000f0000) +#define TX_PWR_CFG_1_EXT_MCS2_CH2 FIELD32(0x0f000000) + +/* TX_PWR_CFG_2_EXT */ +#define TX_PWR_CFG_2_EXT 0x1398 +#define TX_PWR_CFG_2_EXT_MCS4_CH2 FIELD32(0x0000000f) +#define TX_PWR_CFG_2_EXT_MCS6_CH2 FIELD32(0x00000f00) +#define TX_PWR_CFG_2_EXT_MCS8_CH2 FIELD32(0x000f0000) +#define TX_PWR_CFG_2_EXT_MCS10_CH2 FIELD32(0x0f000000) + +/* TX_PWR_CFG_3_EXT */ +#define TX_PWR_CFG_3_EXT 0x139c +#define TX_PWR_CFG_3_EXT_MCS12_CH2 FIELD32(0x0000000f) +#define TX_PWR_CFG_3_EXT_MCS14_CH2 FIELD32(0x00000f00) +#define TX_PWR_CFG_3_EXT_STBC0_CH2 FIELD32(0x000f0000) +#define TX_PWR_CFG_3_EXT_STBC2_CH2 FIELD32(0x0f000000) + +/* TX_PWR_CFG_4_EXT */ +#define TX_PWR_CFG_4_EXT 0x13a0 +#define TX_PWR_CFG_4_EXT_STBC4_CH2 FIELD32(0x0000000f) +#define TX_PWR_CFG_4_EXT_STBC6_CH2 FIELD32(0x00000f00) + +/* TX_PWR_CFG_7 */ +#define TX_PWR_CFG_7 0x13d4 +#define TX_PWR_CFG_7_OFDM54_CH0 FIELD32(0x0000000f) +#define TX_PWR_CFG_7_OFDM54_CH1 FIELD32(0x000000f0) +#define TX_PWR_CFG_7_OFDM54_CH2 FIELD32(0x00000f00) +#define TX_PWR_CFG_7_MCS7_CH0 FIELD32(0x000f0000) +#define TX_PWR_CFG_7_MCS7_CH1 FIELD32(0x00f00000) +#define TX_PWR_CFG_7_MCS7_CH2 FIELD32(0x0f000000) + +/* TX_PWR_CFG_8 */ +#define TX_PWR_CFG_8 0x13d8 +#define TX_PWR_CFG_8_MCS15_CH0 FIELD32(0x0000000f) +#define TX_PWR_CFG_8_MCS15_CH1 FIELD32(0x000000f0) +#define TX_PWR_CFG_8_MCS15_CH2 FIELD32(0x00000f00) +#define TX_PWR_CFG_8_MCS23_CH0 FIELD32(0x000f0000) +#define TX_PWR_CFG_8_MCS23_CH1 FIELD32(0x00f00000) +#define TX_PWR_CFG_8_MCS23_CH2 FIELD32(0x0f000000) + +/* TX_PWR_CFG_9 */ +#define TX_PWR_CFG_9 0x13dc +#define TX_PWR_CFG_9_STBC7_CH0 FIELD32(0x0000000f) +#define TX_PWR_CFG_9_STBC7_CH1 FIELD32(0x000000f0) +#define TX_PWR_CFG_9_STBC7_CH2 FIELD32(0x00000f00) + /* * RX_FILTER_CFG: RX configuration register. */ diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 7b5c593b6118..e817278390f6 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -3120,6 +3120,9 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b, u8 eirp_txpower_criterion; u8 reg_limit; + if (rt2x00_rt(rt2x00dev, RT3593)) + return min_t(u8, txpower, 0xc); + if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags)) { /* * Check if eirp txpower exceed txpower_limit. @@ -3155,6 +3158,412 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b, return min_t(u8, txpower, 0xc); } + +enum { + TX_PWR_CFG_0_IDX, + TX_PWR_CFG_1_IDX, + TX_PWR_CFG_2_IDX, + TX_PWR_CFG_3_IDX, + TX_PWR_CFG_4_IDX, + TX_PWR_CFG_5_IDX, + TX_PWR_CFG_6_IDX, + TX_PWR_CFG_7_IDX, + TX_PWR_CFG_8_IDX, + TX_PWR_CFG_9_IDX, + TX_PWR_CFG_0_EXT_IDX, + TX_PWR_CFG_1_EXT_IDX, + TX_PWR_CFG_2_EXT_IDX, + TX_PWR_CFG_3_EXT_IDX, + TX_PWR_CFG_4_EXT_IDX, + TX_PWR_CFG_IDX_COUNT, +}; + +static void rt2800_config_txpower_rt3593(struct rt2x00_dev *rt2x00dev, + struct ieee80211_channel *chan, + int power_level) +{ + u8 txpower; + u16 eeprom; + u32 regs[TX_PWR_CFG_IDX_COUNT]; + unsigned int offset; + enum ieee80211_band band = chan->band; + int delta; + int i; + + memset(regs, '\0', sizeof(regs)); + + /* TODO: adapt TX power reduction from the rt28xx code */ + + /* calculate temperature compensation delta */ + delta = rt2800_get_gain_calibration_delta(rt2x00dev); + + if (band == IEEE80211_BAND_5GHZ) + offset = 16; + else + offset = 0; + + if (test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) + offset += 8; + + /* read the next four txpower values */ + rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, + offset, &eeprom); + + /* CCK 1MBS,2MBS */ + txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); + txpower = rt2800_compensate_txpower(rt2x00dev, 1, band, power_level, + txpower, delta); + rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], + TX_PWR_CFG_0_CCK1_CH0, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], + TX_PWR_CFG_0_CCK1_CH1, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_0_EXT_IDX], + TX_PWR_CFG_0_EXT_CCK1_CH2, txpower); + + /* CCK 5.5MBS,11MBS */ + txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); + txpower = rt2800_compensate_txpower(rt2x00dev, 1, band, power_level, + txpower, delta); + rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], + TX_PWR_CFG_0_CCK5_CH0, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], + TX_PWR_CFG_0_CCK5_CH1, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_0_EXT_IDX], + TX_PWR_CFG_0_EXT_CCK5_CH2, txpower); + + /* OFDM 6MBS,9MBS */ + txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); + txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, + txpower, delta); + rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], + TX_PWR_CFG_0_OFDM6_CH0, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], + TX_PWR_CFG_0_OFDM6_CH1, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_0_EXT_IDX], + TX_PWR_CFG_0_EXT_OFDM6_CH2, txpower); + + /* OFDM 12MBS,18MBS */ + txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3); + txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, + txpower, delta); + rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], + TX_PWR_CFG_0_OFDM12_CH0, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_0_IDX], + TX_PWR_CFG_0_OFDM12_CH1, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_0_EXT_IDX], + TX_PWR_CFG_0_EXT_OFDM12_CH2, txpower); + + /* read the next four txpower values */ + rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, + offset + 1, &eeprom); + + /* OFDM 24MBS,36MBS */ + txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); + txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, + txpower, delta); + rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], + TX_PWR_CFG_1_OFDM24_CH0, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], + TX_PWR_CFG_1_OFDM24_CH1, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_1_EXT_IDX], + TX_PWR_CFG_1_EXT_OFDM24_CH2, txpower); + + /* OFDM 48MBS */ + txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); + txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, + txpower, delta); + rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], + TX_PWR_CFG_1_OFDM48_CH0, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], + TX_PWR_CFG_1_OFDM48_CH1, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_1_EXT_IDX], + TX_PWR_CFG_1_EXT_OFDM48_CH2, txpower); + + /* OFDM 54MBS */ + txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); + txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, + txpower, delta); + rt2x00_set_field32(®s[TX_PWR_CFG_7_IDX], + TX_PWR_CFG_7_OFDM54_CH0, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_7_IDX], + TX_PWR_CFG_7_OFDM54_CH1, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_7_IDX], + TX_PWR_CFG_7_OFDM54_CH2, txpower); + + /* read the next four txpower values */ + rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, + offset + 2, &eeprom); + + /* MCS 0,1 */ + txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); + txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, + txpower, delta); + rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], + TX_PWR_CFG_1_MCS0_CH0, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], + TX_PWR_CFG_1_MCS0_CH1, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_1_EXT_IDX], + TX_PWR_CFG_1_EXT_MCS0_CH2, txpower); + + /* MCS 2,3 */ + txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); + txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, + txpower, delta); + rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], + TX_PWR_CFG_1_MCS2_CH0, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_1_IDX], + TX_PWR_CFG_1_MCS2_CH1, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_1_EXT_IDX], + TX_PWR_CFG_1_EXT_MCS2_CH2, txpower); + + /* MCS 4,5 */ + txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); + txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, + txpower, delta); + rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], + TX_PWR_CFG_2_MCS4_CH0, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], + TX_PWR_CFG_2_MCS4_CH1, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_2_EXT_IDX], + TX_PWR_CFG_2_EXT_MCS4_CH2, txpower); + + /* MCS 6 */ + txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3); + txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, + txpower, delta); + rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], + TX_PWR_CFG_2_MCS6_CH0, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], + TX_PWR_CFG_2_MCS6_CH1, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_2_EXT_IDX], + TX_PWR_CFG_2_EXT_MCS6_CH2, txpower); + + /* read the next four txpower values */ + rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, + offset + 3, &eeprom); + + /* MCS 7 */ + txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); + txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, + txpower, delta); + rt2x00_set_field32(®s[TX_PWR_CFG_7_IDX], + TX_PWR_CFG_7_MCS7_CH0, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_7_IDX], + TX_PWR_CFG_7_MCS7_CH1, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_7_IDX], + TX_PWR_CFG_7_MCS7_CH2, txpower); + + /* MCS 8,9 */ + txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); + txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, + txpower, delta); + rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], + TX_PWR_CFG_2_MCS8_CH0, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], + TX_PWR_CFG_2_MCS8_CH1, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_2_EXT_IDX], + TX_PWR_CFG_2_EXT_MCS8_CH2, txpower); + + /* MCS 10,11 */ + txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); + txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, + txpower, delta); + rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], + TX_PWR_CFG_2_MCS10_CH0, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_2_IDX], + TX_PWR_CFG_2_MCS10_CH1, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_2_EXT_IDX], + TX_PWR_CFG_2_EXT_MCS10_CH2, txpower); + + /* MCS 12,13 */ + txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3); + txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, + txpower, delta); + rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], + TX_PWR_CFG_3_MCS12_CH0, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], + TX_PWR_CFG_3_MCS12_CH1, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_3_EXT_IDX], + TX_PWR_CFG_3_EXT_MCS12_CH2, txpower); + + /* read the next four txpower values */ + rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, + offset + 4, &eeprom); + + /* MCS 14 */ + txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); + txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, + txpower, delta); + rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], + TX_PWR_CFG_3_MCS14_CH0, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], + TX_PWR_CFG_3_MCS14_CH1, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_3_EXT_IDX], + TX_PWR_CFG_3_EXT_MCS14_CH2, txpower); + + /* MCS 15 */ + txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); + txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, + txpower, delta); + rt2x00_set_field32(®s[TX_PWR_CFG_8_IDX], + TX_PWR_CFG_8_MCS15_CH0, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_8_IDX], + TX_PWR_CFG_8_MCS15_CH1, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_8_IDX], + TX_PWR_CFG_8_MCS15_CH2, txpower); + + /* MCS 16,17 */ + txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); + txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, + txpower, delta); + rt2x00_set_field32(®s[TX_PWR_CFG_5_IDX], + TX_PWR_CFG_5_MCS16_CH0, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_5_IDX], + TX_PWR_CFG_5_MCS16_CH1, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_5_IDX], + TX_PWR_CFG_5_MCS16_CH2, txpower); + + /* MCS 18,19 */ + txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3); + txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, + txpower, delta); + rt2x00_set_field32(®s[TX_PWR_CFG_5_IDX], + TX_PWR_CFG_5_MCS18_CH0, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_5_IDX], + TX_PWR_CFG_5_MCS18_CH1, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_5_IDX], + TX_PWR_CFG_5_MCS18_CH2, txpower); + + /* read the next four txpower values */ + rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, + offset + 5, &eeprom); + + /* MCS 20,21 */ + txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); + txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, + txpower, delta); + rt2x00_set_field32(®s[TX_PWR_CFG_6_IDX], + TX_PWR_CFG_6_MCS20_CH0, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_6_IDX], + TX_PWR_CFG_6_MCS20_CH1, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_6_IDX], + TX_PWR_CFG_6_MCS20_CH2, txpower); + + /* MCS 22 */ + txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); + txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, + txpower, delta); + rt2x00_set_field32(®s[TX_PWR_CFG_6_IDX], + TX_PWR_CFG_6_MCS22_CH0, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_6_IDX], + TX_PWR_CFG_6_MCS22_CH1, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_6_IDX], + TX_PWR_CFG_6_MCS22_CH2, txpower); + + /* MCS 23 */ + txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); + txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, + txpower, delta); + rt2x00_set_field32(®s[TX_PWR_CFG_8_IDX], + TX_PWR_CFG_8_MCS23_CH0, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_8_IDX], + TX_PWR_CFG_8_MCS23_CH1, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_8_IDX], + TX_PWR_CFG_8_MCS23_CH2, txpower); + + /* read the next four txpower values */ + rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, + offset + 6, &eeprom); + + /* STBC, MCS 0,1 */ + txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); + txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, + txpower, delta); + rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], + TX_PWR_CFG_3_STBC0_CH0, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], + TX_PWR_CFG_3_STBC0_CH1, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_3_EXT_IDX], + TX_PWR_CFG_3_EXT_STBC0_CH2, txpower); + + /* STBC, MCS 2,3 */ + txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE1); + txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, + txpower, delta); + rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], + TX_PWR_CFG_3_STBC2_CH0, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_3_IDX], + TX_PWR_CFG_3_STBC2_CH1, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_3_EXT_IDX], + TX_PWR_CFG_3_EXT_STBC2_CH2, txpower); + + /* STBC, MCS 4,5 */ + txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE2); + txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, + txpower, delta); + rt2x00_set_field32(®s[TX_PWR_CFG_4_IDX], TX_PWR_CFG_RATE0, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_4_IDX], TX_PWR_CFG_RATE1, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_4_EXT_IDX], TX_PWR_CFG_RATE0, + txpower); + + /* STBC, MCS 6 */ + txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE3); + txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, + txpower, delta); + rt2x00_set_field32(®s[TX_PWR_CFG_4_IDX], TX_PWR_CFG_RATE2, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_4_IDX], TX_PWR_CFG_RATE3, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_4_EXT_IDX], TX_PWR_CFG_RATE2, + txpower); + + /* read the next four txpower values */ + rt2800_eeprom_read_from_array(rt2x00dev, EEPROM_TXPOWER_BYRATE, + offset + 7, &eeprom); + + /* STBC, MCS 7 */ + txpower = rt2x00_get_field16(eeprom, EEPROM_TXPOWER_BYRATE_RATE0); + txpower = rt2800_compensate_txpower(rt2x00dev, 0, band, power_level, + txpower, delta); + rt2x00_set_field32(®s[TX_PWR_CFG_9_IDX], + TX_PWR_CFG_9_STBC7_CH0, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_9_IDX], + TX_PWR_CFG_9_STBC7_CH1, txpower); + rt2x00_set_field32(®s[TX_PWR_CFG_9_IDX], + TX_PWR_CFG_9_STBC7_CH2, txpower); + + rt2800_register_write(rt2x00dev, TX_PWR_CFG_0, regs[TX_PWR_CFG_0_IDX]); + rt2800_register_write(rt2x00dev, TX_PWR_CFG_1, regs[TX_PWR_CFG_1_IDX]); + rt2800_register_write(rt2x00dev, TX_PWR_CFG_2, regs[TX_PWR_CFG_2_IDX]); + rt2800_register_write(rt2x00dev, TX_PWR_CFG_3, regs[TX_PWR_CFG_3_IDX]); + rt2800_register_write(rt2x00dev, TX_PWR_CFG_4, regs[TX_PWR_CFG_4_IDX]); + rt2800_register_write(rt2x00dev, TX_PWR_CFG_5, regs[TX_PWR_CFG_5_IDX]); + rt2800_register_write(rt2x00dev, TX_PWR_CFG_6, regs[TX_PWR_CFG_6_IDX]); + rt2800_register_write(rt2x00dev, TX_PWR_CFG_7, regs[TX_PWR_CFG_7_IDX]); + rt2800_register_write(rt2x00dev, TX_PWR_CFG_8, regs[TX_PWR_CFG_8_IDX]); + rt2800_register_write(rt2x00dev, TX_PWR_CFG_9, regs[TX_PWR_CFG_9_IDX]); + + rt2800_register_write(rt2x00dev, TX_PWR_CFG_0_EXT, + regs[TX_PWR_CFG_0_EXT_IDX]); + rt2800_register_write(rt2x00dev, TX_PWR_CFG_1_EXT, + regs[TX_PWR_CFG_1_EXT_IDX]); + rt2800_register_write(rt2x00dev, TX_PWR_CFG_2_EXT, + regs[TX_PWR_CFG_2_EXT_IDX]); + rt2800_register_write(rt2x00dev, TX_PWR_CFG_3_EXT, + regs[TX_PWR_CFG_3_EXT_IDX]); + rt2800_register_write(rt2x00dev, TX_PWR_CFG_4_EXT, + regs[TX_PWR_CFG_4_EXT_IDX]); + + for (i = 0; i < TX_PWR_CFG_IDX_COUNT; i++) + rt2x00_dbg(rt2x00dev, + "band:%cGHz, BW:%c0MHz, TX_PWR_CFG_%d%s = %08lx\n", + (band == IEEE80211_BAND_5GHZ) ? '5' : '2', + (test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) ? + '4' : '2', + (i > TX_PWR_CFG_9_IDX) ? + (i - TX_PWR_CFG_9_IDX - 1) : i, + (i > TX_PWR_CFG_9_IDX) ? "_EXT" : "", + (unsigned long) regs[i]); +} + /* * We configure transmit power using MAC TX_PWR_CFG_{0,...,N} registers and * BBP R1 register. TX_PWR_CFG_X allow to configure per rate TX power values, @@ -3164,9 +3573,9 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b, * EEPROM_TXPOWER_BYRATE offset. We adjust them and BBP R1 settings according to * current conditions (i.e. band, bandwidth, temperature, user settings). */ -static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, - struct ieee80211_channel *chan, - int power_level) +static void rt2800_config_txpower_rt28xx(struct rt2x00_dev *rt2x00dev, + struct ieee80211_channel *chan, + int power_level) { u8 txpower, r1; u16 eeprom; @@ -3338,6 +3747,16 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, } } +static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, + struct ieee80211_channel *chan, + int power_level) +{ + if (rt2x00_rt(rt2x00dev, RT3593)) + rt2800_config_txpower_rt3593(rt2x00dev, chan, power_level); + else + rt2800_config_txpower_rt28xx(rt2x00dev, chan, power_level); +} + void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev) { rt2800_config_txpower(rt2x00dev, rt2x00dev->hw->conf.chandef.chan, -- cgit From 4788ac1e4842d8ef46ee620cfccf96c426043177 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 8 Jul 2013 16:08:21 +0200 Subject: rt2x00: rt2800lib: fix BBP1_TX_ANTENNA field configuration for 3T devices The field must be set to 2 instead of 0 for devices with three TX chains. Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index e817278390f6..1a6a4eb25202 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1763,7 +1763,7 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant) rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2); break; case 3: - rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0); + rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2); break; } -- cgit From 5cddb3c2d5102d9a6b1b809e1518da54c8be8296 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 8 Jul 2013 16:08:22 +0200 Subject: rt2x00: rt2800lib: fix antenna configuration for RT3593 On the RT3593 chipset, BBP register 86 must be configured by different values based on the RX antenna numbers. Configure this register from the 'rt2800_config_ant' function. Based on the Ralink DPO_RT5572_LinuxSTA_2.6.0.1_20120629 driver. Reference: RT3593_CONFIG_SET_BY_ANTENNA in include/chip/rt3593.h Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 1a6a4eb25202..958215c44485 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1803,6 +1803,13 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant) rt2800_bbp_write(rt2x00dev, 3, r3); rt2800_bbp_write(rt2x00dev, 1, r1); + + if (rt2x00_rt(rt2x00dev, RT3593)) { + if (ant->rx_chain_num == 1) + rt2800_bbp_write(rt2x00dev, 86, 0x00); + else + rt2800_bbp_write(rt2x00dev, 86, 0x46); + } } EXPORT_SYMBOL_GPL(rt2800_config_ant); -- cgit From 97aa03f15e83174df74aa468eea127c5cee480f0 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 8 Jul 2013 16:08:23 +0200 Subject: rt2x00: rt2800lib: add rt2800_txpower_to_dev helper Introduce a new helper function for converting the default TX power values from EEPROM into mac80211 values. The change improves the readability and it makes it easier to add support for other chipsets. Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800.h | 6 ------ drivers/net/wireless/rt2x00/rt2800lib.c | 21 ++++++++++++++------- 2 files changed, 14 insertions(+), 13 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 7b7caeb01e5a..d3e8f6d3531a 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -2887,15 +2887,9 @@ enum rt2800_eeprom_word { #define TXPOWER_G_FROM_DEV(__txpower) \ ((__txpower) > MAX_G_TXPOWER) ? DEFAULT_TXPOWER : (__txpower) -#define TXPOWER_G_TO_DEV(__txpower) \ - clamp_t(char, __txpower, MIN_G_TXPOWER, MAX_G_TXPOWER) - #define TXPOWER_A_FROM_DEV(__txpower) \ ((__txpower) > MAX_A_TXPOWER) ? DEFAULT_TXPOWER : (__txpower) -#define TXPOWER_A_TO_DEV(__txpower) \ - clamp_t(char, __txpower, MIN_A_TXPOWER, MAX_A_TXPOWER) - /* * Board's maximun TX power limitation */ diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 958215c44485..1738a9d232c3 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -2724,6 +2724,16 @@ static void rt2800_iq_calibrate(struct rt2x00_dev *rt2x00dev, int channel) rt2800_bbp_write(rt2x00dev, 159, cal != 0xff ? cal : 0); } +static char rt2800_txpower_to_dev(struct rt2x00_dev *rt2x00dev, + unsigned int channel, + char txpower) +{ + if (channel <= 14) + return clamp_t(char, txpower, MIN_G_TXPOWER, MAX_G_TXPOWER); + else + return clamp_t(char, txpower, MIN_A_TXPOWER, MAX_A_TXPOWER); +} + static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, struct ieee80211_conf *conf, struct rf_channel *rf, @@ -2733,13 +2743,10 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, unsigned int tx_pin; u8 bbp, rfcsr; - if (rf->channel <= 14) { - info->default_power1 = TXPOWER_G_TO_DEV(info->default_power1); - info->default_power2 = TXPOWER_G_TO_DEV(info->default_power2); - } else { - info->default_power1 = TXPOWER_A_TO_DEV(info->default_power1); - info->default_power2 = TXPOWER_A_TO_DEV(info->default_power2); - } + info->default_power1 = rt2800_txpower_to_dev(rt2x00dev, rf->channel, + info->default_power1); + info->default_power2 = rt2800_txpower_to_dev(rt2x00dev, rf->channel, + info->default_power2); switch (rt2x00dev->chip.rf) { case RF2020: -- cgit From fc739cfe0f305647677edbf99a76d9ece96e3795 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 8 Jul 2013 16:08:24 +0200 Subject: rt2x00: rt2800lib: fix default TX power values for RT3593 The TX power values in the EEPROM are using a different format for the RT3593 chip. The default TX power value uses bits 0..4 only. Bits 5..8 contains value for fine grained power control. Additionally, the lower and upper limits of the TX power values are the same for both bands. Improve the rt2800_txpower_to_dev function, in order to compute the correct default power values for the RT3593 chip as well. Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800.h | 7 +++++++ drivers/net/wireless/rt2x00/rt2800lib.c | 7 +++++++ 2 files changed, 14 insertions(+) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index d3e8f6d3531a..69749ba599bc 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -2603,6 +2603,10 @@ enum rt2800_eeprom_word { #define EEPROM_TXPOWER_A_1 FIELD16(0x00ff) #define EEPROM_TXPOWER_A_2 FIELD16(0xff00) +/* EEPROM_TXPOWER_{A,G} fields for RT3593 */ +#define EEPROM_TXPOWER_ALC FIELD8(0x1f) +#define EEPROM_TXPOWER_FINE_CTRL FIELD8(0xe0) + /* * EEPROM temperature compensation boundaries 802.11A * MINUS4: If the actual TSSI is below this boundary, tx power needs to be @@ -2884,6 +2888,9 @@ enum rt2800_eeprom_word { #define MAX_A_TXPOWER 15 #define DEFAULT_TXPOWER 5 +#define MIN_A_TXPOWER_3593 0 +#define MAX_A_TXPOWER_3593 31 + #define TXPOWER_G_FROM_DEV(__txpower) \ ((__txpower) > MAX_G_TXPOWER) ? DEFAULT_TXPOWER : (__txpower) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 1738a9d232c3..b11f0b06cc6d 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -2728,8 +2728,15 @@ static char rt2800_txpower_to_dev(struct rt2x00_dev *rt2x00dev, unsigned int channel, char txpower) { + if (rt2x00_rt(rt2x00dev, RT3593)) + txpower = rt2x00_get_field8(txpower, EEPROM_TXPOWER_ALC); + if (channel <= 14) return clamp_t(char, txpower, MIN_G_TXPOWER, MAX_G_TXPOWER); + + if (rt2x00_rt(rt2x00dev, RT3593)) + return clamp_t(char, txpower, MIN_A_TXPOWER_3593, + MAX_A_TXPOWER_3593); else return clamp_t(char, txpower, MIN_A_TXPOWER, MAX_A_TXPOWER); } -- cgit From a3f1625dae58f06c5df1ec0094b275e9a46fd8b3 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 8 Jul 2013 16:08:25 +0200 Subject: rt2x00: rt2800lib: introduce rt2800_get_txmixer_gain_{24,5}g helpers Move the TX mixer gain reading code into separate helper functions in preparation for RT3593 support. Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 38 +++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 14 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index b11f0b06cc6d..1f327325df52 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -6361,6 +6361,28 @@ int rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev) } EXPORT_SYMBOL_GPL(rt2800_read_eeprom_efuse); +static u8 rt2800_get_txmixer_gain_24g(struct rt2x00_dev *rt2x00dev) +{ + u16 word; + + rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &word); + if ((word & 0x00ff) != 0x00ff) + return rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_BG_VAL); + + return 0; +} + +static u8 rt2800_get_txmixer_gain_5g(struct rt2x00_dev *rt2x00dev) +{ + u16 word; + + rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A, &word); + if ((word & 0x00ff) != 0x00ff) + return rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_A_VAL); + + return 0; +} + static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) { struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; @@ -6455,13 +6477,7 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET1, 0); rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_BG, word); - rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &word); - if ((word & 0x00ff) != 0x00ff) { - drv_data->txmixer_gain_24g = - rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_BG_VAL); - } else { - drv_data->txmixer_gain_24g = 0; - } + drv_data->txmixer_gain_24g = rt2800_get_txmixer_gain_24g(rt2x00dev); rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word); if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10) @@ -6472,13 +6488,7 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) default_lna_gain); rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_BG2, word); - rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A, &word); - if ((word & 0x00ff) != 0x00ff) { - drv_data->txmixer_gain_5g = - rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_A_VAL); - } else { - drv_data->txmixer_gain_5g = 0; - } + drv_data->txmixer_gain_5g = rt2800_get_txmixer_gain_5g(rt2x00dev); rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word); if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET0)) > 10) -- cgit From 6316c786cc8aff762530ea740233bf2da10fea33 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 8 Jul 2013 16:08:26 +0200 Subject: rt2x00: rt2800lib: hardcode TX mixer gain values for RT3593 The reference code uses hardcoded zero TX mixer gain value for RT3593. Do the same in the rt2x00 driver. Based on the Ralink DPO_RT5572_LinuxSTA_2.6.0.1_20120629 driver. Reference: NICReadEEPROMParameters in common/rtmp_init.c Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 1f327325df52..65045e0236fc 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -6365,6 +6365,9 @@ static u8 rt2800_get_txmixer_gain_24g(struct rt2x00_dev *rt2x00dev) { u16 word; + if (rt2x00_rt(rt2x00dev, RT3593)) + return 0; + rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &word); if ((word & 0x00ff) != 0x00ff) return rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_BG_VAL); @@ -6376,6 +6379,9 @@ static u8 rt2800_get_txmixer_gain_5g(struct rt2x00_dev *rt2x00dev) { u16 word; + if (rt2x00_rt(rt2x00dev, RT3593)) + return 0; + rt2800_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_A, &word); if ((word & 0x00ff) != 0x00ff) return rt2x00_get_field16(word, EEPROM_TXMIXER_GAIN_A_VAL); -- cgit From f36bb0ca1be5bcb7148ad32263626f8609dfc0d7 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 8 Jul 2013 16:08:27 +0200 Subject: rt2x00: rt2800lib: fix LNA_A[12] gain values for RT3593 The LNA_A[12] gain values are stored at a different offset in the EEPROM on RT3593 based devices. However the current code unconditionally reads those values from the location used by other chipsets. Fix the code to use the correct EEPROM offset. Based on the DPO_RT5572_LinuxSTA_2.6.0.1_20120629 driver. References: RT3593_EEPROM_RSSI2_OFFSET_ALNAGAIN1_24G_READ in include/chip/rt3593.h RT3593_EEPROM_RSSI2_OFFSET_ALNAGAIN2_5G_READ in include/chip/rt3593.h Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800.h | 4 +++ drivers/net/wireless/rt2x00/rt2800lib.c | 55 ++++++++++++++++++++++++++------- 2 files changed, 47 insertions(+), 12 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 69749ba599bc..7688e1594201 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -2672,6 +2672,10 @@ enum rt2800_eeprom_word { #define EEPROM_BBP_VALUE FIELD16(0x00ff) #define EEPROM_BBP_REG_ID FIELD16(0xff00) +/* EEPROM_EXT_LNA2 */ +#define EEPROM_EXT_LNA2_A1 FIELD16(0x00ff) +#define EEPROM_EXT_LNA2_A2 FIELD16(0xff00) + /* * EEPROM IQ Calibration, unlike other entries those are byte addresses. */ diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 65045e0236fc..419ea05f13a3 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1826,11 +1826,25 @@ static void rt2800_config_lna_gain(struct rt2x00_dev *rt2x00dev, rt2800_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0); } else if (libconf->rf.channel <= 128) { - rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom); - lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_LNA_A1); + if (rt2x00_rt(rt2x00dev, RT3593)) { + rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom); + lna_gain = rt2x00_get_field16(eeprom, + EEPROM_EXT_LNA2_A1); + } else { + rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom); + lna_gain = rt2x00_get_field16(eeprom, + EEPROM_RSSI_BG2_LNA_A1); + } } else { - rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom); - lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_LNA_A2); + if (rt2x00_rt(rt2x00dev, RT3593)) { + rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &eeprom); + lna_gain = rt2x00_get_field16(eeprom, + EEPROM_EXT_LNA2_A2); + } else { + rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom); + lna_gain = rt2x00_get_field16(eeprom, + EEPROM_RSSI_A2_LNA_A2); + } } rt2x00dev->lna_gain = lna_gain; @@ -6488,10 +6502,12 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word); if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10) rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0); - if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 || - rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff) - rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1, - default_lna_gain); + if (!rt2x00_rt(rt2x00dev, RT3593)) { + if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 || + rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff) + rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1, + default_lna_gain); + } rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_BG2, word); drv_data->txmixer_gain_5g = rt2800_get_txmixer_gain_5g(rt2x00dev); @@ -6506,12 +6522,27 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) rt2800_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word); if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A2_OFFSET2)) > 10) rt2x00_set_field16(&word, EEPROM_RSSI_A2_OFFSET2, 0); - if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 || - rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff) - rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2, - default_lna_gain); + if (!rt2x00_rt(rt2x00dev, RT3593)) { + if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 || + rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff) + rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2, + default_lna_gain); + } rt2800_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word); + if (rt2x00_rt(rt2x00dev, RT3593)) { + rt2800_eeprom_read(rt2x00dev, EEPROM_EXT_LNA2, &word); + if (rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0x00 || + rt2x00_get_field16(word, EEPROM_EXT_LNA2_A1) == 0xff) + rt2x00_set_field16(&word, EEPROM_EXT_LNA2_A1, + default_lna_gain); + if (rt2x00_get_field16(word, EEPROM_EXT_LNA2_A2) == 0x00 || + rt2x00_get_field16(word, EEPROM_EXT_LNA2_A2) == 0xff) + rt2x00_set_field16(&word, EEPROM_EXT_LNA2_A1, + default_lna_gain); + rt2800_eeprom_write(rt2x00dev, EEPROM_EXT_LNA2, word); + } + return 0; } -- cgit From c0a14369ebd3e7940e70e397ecc3dd7eaf81e9ab Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 8 Jul 2013 16:08:28 +0200 Subject: rt2x00: rt2800lib: add default_power3 field for three-chain devices The actual code uses two default TX power values. This is enough for 1T and for 2T devices however on 3T devices another value is needed for the third chain. Add a new field to struct channel_info and initialize it from the 'rt2800_probe_hw_mode' function. Also modify the 'rt2800_config_channel' to handle the new field as well. Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 22 ++++++++++++++++++++++ drivers/net/wireless/rt2x00/rt2x00.h | 1 + 2 files changed, 23 insertions(+) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 419ea05f13a3..e3e652db60ac 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -2768,6 +2768,10 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, info->default_power1); info->default_power2 = rt2800_txpower_to_dev(rt2x00dev, rf->channel, info->default_power2); + if (rt2x00dev->default_ant.tx_chain_num > 2) + info->default_power3 = + rt2800_txpower_to_dev(rt2x00dev, rf->channel, + info->default_power3); switch (rt2x00dev->chip.rf) { case RF2020: @@ -6963,6 +6967,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) struct channel_info *info; char *default_power1; char *default_power2; + char *default_power3; unsigned int i; u16 eeprom; u32 reg; @@ -7115,9 +7120,17 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) default_power1 = rt2800_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1); default_power2 = rt2800_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2); + if (rt2x00dev->default_ant.tx_chain_num > 2) + default_power3 = rt2800_eeprom_addr(rt2x00dev, + EEPROM_EXT_TXPOWER_BG3); + else + default_power3 = NULL; + for (i = 0; i < 14; i++) { info[i].default_power1 = default_power1[i]; info[i].default_power2 = default_power2[i]; + if (default_power3) + info[i].default_power3 = default_power3[i]; } if (spec->num_channels > 14) { @@ -7126,9 +7139,18 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) default_power2 = rt2800_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2); + if (rt2x00dev->default_ant.tx_chain_num > 2) + default_power3 = + rt2800_eeprom_addr(rt2x00dev, + EEPROM_EXT_TXPOWER_A3); + else + default_power3 = NULL; + for (i = 14; i < spec->num_channels; i++) { info[i].default_power1 = default_power1[i - 14]; info[i].default_power2 = default_power2[i - 14]; + if (default_power3) + info[i].default_power3 = default_power3[i - 14]; } } diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index ee3fc570b11d..fe4c572db52c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -211,6 +211,7 @@ struct channel_info { short max_power; short default_power1; short default_power2; + short default_power3; }; /* -- cgit From c8b9d3dc83cab569de6054a10e355a143e2b52a0 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 8 Jul 2013 16:08:29 +0200 Subject: rt2x00: rt2800lib: add rf_vals for RF3053 Based on the Ralink DPO_RT5572_LinuxSTA_2.6.0.1_20120629 driver. References: FreqItems3053 in chips/rt3593.c Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 70 +++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index e3e652db60ac..5119bf071936 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -6961,6 +6961,72 @@ static const struct rf_channel rf_vals_5592_xtal40[] = { {196, 83, 0, 12, 1}, }; +static const struct rf_channel rf_vals_3053[] = { + /* Channel, N, R, K */ + {1, 241, 2, 2}, + {2, 241, 2, 7}, + {3, 242, 2, 2}, + {4, 242, 2, 7}, + {5, 243, 2, 2}, + {6, 243, 2, 7}, + {7, 244, 2, 2}, + {8, 244, 2, 7}, + {9, 245, 2, 2}, + {10, 245, 2, 7}, + {11, 246, 2, 2}, + {12, 246, 2, 7}, + {13, 247, 2, 2}, + {14, 248, 2, 4}, + + {36, 0x56, 0, 4}, + {38, 0x56, 0, 6}, + {40, 0x56, 0, 8}, + {44, 0x57, 0, 0}, + {46, 0x57, 0, 2}, + {48, 0x57, 0, 4}, + {52, 0x57, 0, 8}, + {54, 0x57, 0, 10}, + {56, 0x58, 0, 0}, + {60, 0x58, 0, 4}, + {62, 0x58, 0, 6}, + {64, 0x58, 0, 8}, + + {100, 0x5B, 0, 8}, + {102, 0x5B, 0, 10}, + {104, 0x5C, 0, 0}, + {108, 0x5C, 0, 4}, + {110, 0x5C, 0, 6}, + {112, 0x5C, 0, 8}, + + /* NOTE: Channel 114 has been removed intentionally. + * The EEPROM contains no TX power values for that, + * and it is disabled in the vendor driver as well. + */ + + {116, 0x5D, 0, 0}, + {118, 0x5D, 0, 2}, + {120, 0x5D, 0, 4}, + {124, 0x5D, 0, 8}, + {126, 0x5D, 0, 10}, + {128, 0x5E, 0, 0}, + {132, 0x5E, 0, 4}, + {134, 0x5E, 0, 6}, + {136, 0x5E, 0, 8}, + {140, 0x5F, 0, 0}, + + {149, 0x5F, 0, 9}, + {151, 0x5F, 0, 11}, + {153, 0x60, 0, 1}, + {157, 0x60, 0, 5}, + {159, 0x60, 0, 7}, + {161, 0x60, 0, 9}, + {165, 0x61, 0, 1}, + {167, 0x61, 0, 3}, + {169, 0x61, 0, 5}, + {171, 0x61, 0, 7}, + {173, 0x61, 0, 9}, +}; + static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) { struct hw_mode_spec *spec = &rt2x00dev->spec; @@ -7052,6 +7118,10 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) spec->supported_bands |= SUPPORT_BAND_5GHZ; spec->num_channels = ARRAY_SIZE(rf_vals_3x); spec->channels = rf_vals_3x; + } else if (rt2x00_rf(rt2x00dev, RF3053)) { + spec->supported_bands |= SUPPORT_BAND_5GHZ; + spec->num_channels = ARRAY_SIZE(rf_vals_3053); + spec->channels = rf_vals_3053; } else if (rt2x00_rf(rt2x00dev, RF5592)) { spec->supported_bands |= SUPPORT_BAND_5GHZ; -- cgit From f42b046578efb018064302fd9b66586f5da7d75b Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 8 Jul 2013 16:08:30 +0200 Subject: rt2x00: rt2800lib: add channel configuration for RF3053 Based on the Ralink DPO_RT5572_LinuxSTA_2.6.0.1_20120629 driver. Reference: RT3593_ChipSwitchChannel in chips/rt3593.c Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800.h | 46 +++- drivers/net/wireless/rt2x00/rt2800lib.c | 366 +++++++++++++++++++++++++++++++- 2 files changed, 409 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 7688e1594201..1ba797b0e147 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -2092,6 +2092,10 @@ struct mac_iveiv_entry { #define BBP109_TX0_POWER FIELD8(0x0f) #define BBP109_TX1_POWER FIELD8(0xf0) +/* BBP 110 */ +#define BBP110_TX2_POWER FIELD8(0x0f) + + /* * BBP 138: Unknown */ @@ -2141,6 +2145,12 @@ struct mac_iveiv_entry { #define RFCSR3_PA2_CASCODE_BIAS_CCKK FIELD8(0x80) /* Bits for RF3290/RF5360/RF5370/RF5372/RF5390/RF5392 */ #define RFCSR3_VCOCAL_EN FIELD8(0x80) +/* Bits for RF3050 */ +#define RFCSR3_BIT1 FIELD8(0x02) +#define RFCSR3_BIT2 FIELD8(0x04) +#define RFCSR3_BIT3 FIELD8(0x08) +#define RFCSR3_BIT4 FIELD8(0x10) +#define RFCSR3_BIT5 FIELD8(0x20) /* * FRCSR 5: @@ -2153,6 +2163,8 @@ struct mac_iveiv_entry { #define RFCSR6_R1 FIELD8(0x03) #define RFCSR6_R2 FIELD8(0x40) #define RFCSR6_TXDIV FIELD8(0x0c) +/* bits for RF3053 */ +#define RFCSR6_VCO_IC FIELD8(0xc0) /* * RFCSR 7: @@ -2177,7 +2189,12 @@ struct mac_iveiv_entry { * RFCSR 11: */ #define RFCSR11_R FIELD8(0x03) +#define RFCSR11_PLL_MOD FIELD8(0x0c) #define RFCSR11_MOD FIELD8(0xc0) +/* bits for RF3053 */ +/* TODO: verify RFCSR11_MOD usage on other chips */ +#define RFCSR11_PLL_IDOH FIELD8(0x40) + /* * RFCSR 12: @@ -2273,6 +2290,12 @@ struct mac_iveiv_entry { #define RFCSR31_RX_H20M FIELD8(0x20) #define RFCSR31_RX_CALIB FIELD8(0x7f) +/* RFCSR 32 bits for RF3053 */ +#define RFCSR32_TX_AGC_FC FIELD8(0xf8) + +/* RFCSR 36 bits for RF3053 */ +#define RFCSR36_RF_BS FIELD8(0x80) + /* * RFCSR 38: */ @@ -2281,6 +2304,7 @@ struct mac_iveiv_entry { /* * RFCSR 39: */ +#define RFCSR39_RX_DIV FIELD8(0x40) #define RFCSR39_RX_LO2_EN FIELD8(0x80) /* @@ -2288,18 +2312,36 @@ struct mac_iveiv_entry { */ #define RFCSR49_TX FIELD8(0x3f) #define RFCSR49_EP FIELD8(0xc0) +/* bits for RT3593 */ +#define RFCSR49_TX_LO1_IC FIELD8(0x1c) +#define RFCSR49_TX_DIV FIELD8(0x20) /* * RFCSR 50: */ #define RFCSR50_TX FIELD8(0x3f) #define RFCSR50_EP FIELD8(0xc0) -/* bits for RT3593*/ +/* bits for RT3593 */ +#define RFCSR50_TX_LO1_EN FIELD8(0x20) #define RFCSR50_TX_LO2_EN FIELD8(0x10) /* RFCSR 51 */ -/* bits for RT3593*/ +/* bits for RT3593 */ +#define RFCSR51_BITS01 FIELD8(0x03) #define RFCSR51_BITS24 FIELD8(0x1c) +#define RFCSR51_BITS57 FIELD8(0xe0) + +#define RFCSR53_TX_POWER FIELD8(0x3f) +#define RFCSR53_UNKNOWN FIELD8(0xc0) + +#define RFCSR54_TX_POWER FIELD8(0x3f) +#define RFCSR54_UNKNOWN FIELD8(0xc0) + +#define RFCSR55_TX_POWER FIELD8(0x3f) +#define RFCSR55_UNKNOWN FIELD8(0xc0) + +#define RFCSR57_DRV_CC FIELD8(0xfc) + /* * RF registers diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 5119bf071936..e6d6c75dc2ce 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -2168,6 +2168,303 @@ static void rt2800_config_channel_rf3052(struct rt2x00_dev *rt2x00dev, rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); } +static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev, + struct ieee80211_conf *conf, + struct rf_channel *rf, + struct channel_info *info) +{ + struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; + u8 txrx_agc_fc; + u8 txrx_h20m; + u8 rfcsr; + u8 bbp; + const bool txbf_enabled = false; /* TODO */ + + /* TODO: use TX{0,1,2}FinePowerControl values from EEPROM */ + rt2800_bbp_read(rt2x00dev, 109, &bbp); + rt2x00_set_field8(&bbp, BBP109_TX0_POWER, 0); + rt2x00_set_field8(&bbp, BBP109_TX1_POWER, 0); + rt2800_bbp_write(rt2x00dev, 109, bbp); + + rt2800_bbp_read(rt2x00dev, 110, &bbp); + rt2x00_set_field8(&bbp, BBP110_TX2_POWER, 0); + rt2800_bbp_write(rt2x00dev, 110, bbp); + + if (rf->channel <= 14) { + /* Restore BBP 25 & 26 for 2.4 GHz */ + rt2800_bbp_write(rt2x00dev, 25, drv_data->bbp25); + rt2800_bbp_write(rt2x00dev, 26, drv_data->bbp26); + } else { + /* Hard code BBP 25 & 26 for 5GHz */ + + /* Enable IQ Phase correction */ + rt2800_bbp_write(rt2x00dev, 25, 0x09); + /* Setup IQ Phase correction value */ + rt2800_bbp_write(rt2x00dev, 26, 0xff); + } + + rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1); + rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3 & 0xf); + + rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR11_R, (rf->rf2 & 0x3)); + rt2800_rfcsr_write(rt2x00dev, 11, rfcsr); + + rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR11_PLL_IDOH, 1); + if (rf->channel <= 14) + rt2x00_set_field8(&rfcsr, RFCSR11_PLL_MOD, 1); + else + rt2x00_set_field8(&rfcsr, RFCSR11_PLL_MOD, 2); + rt2800_rfcsr_write(rt2x00dev, 11, rfcsr); + + rt2800_rfcsr_read(rt2x00dev, 53, &rfcsr); + if (rf->channel <= 14) { + rfcsr = 0; + rt2x00_set_field8(&rfcsr, RFCSR53_TX_POWER, + info->default_power1 & 0x1f); + } else { + if (rt2x00_is_usb(rt2x00dev)) + rfcsr = 0x40; + + rt2x00_set_field8(&rfcsr, RFCSR53_TX_POWER, + ((info->default_power1 & 0x18) << 1) | + (info->default_power1 & 7)); + } + rt2800_rfcsr_write(rt2x00dev, 53, rfcsr); + + rt2800_rfcsr_read(rt2x00dev, 55, &rfcsr); + if (rf->channel <= 14) { + rfcsr = 0; + rt2x00_set_field8(&rfcsr, RFCSR55_TX_POWER, + info->default_power2 & 0x1f); + } else { + if (rt2x00_is_usb(rt2x00dev)) + rfcsr = 0x40; + + rt2x00_set_field8(&rfcsr, RFCSR55_TX_POWER, + ((info->default_power2 & 0x18) << 1) | + (info->default_power2 & 7)); + } + rt2800_rfcsr_write(rt2x00dev, 55, rfcsr); + + rt2800_rfcsr_read(rt2x00dev, 54, &rfcsr); + if (rf->channel <= 14) { + rfcsr = 0; + rt2x00_set_field8(&rfcsr, RFCSR54_TX_POWER, + info->default_power3 & 0x1f); + } else { + if (rt2x00_is_usb(rt2x00dev)) + rfcsr = 0x40; + + rt2x00_set_field8(&rfcsr, RFCSR54_TX_POWER, + ((info->default_power3 & 0x18) << 1) | + (info->default_power3 & 7)); + } + rt2800_rfcsr_write(rt2x00dev, 54, rfcsr); + + rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 0); + rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 0); + rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 0); + rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 0); + rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 0); + rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 0); + rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1); + rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1); + + switch (rt2x00dev->default_ant.tx_chain_num) { + case 3: + rt2x00_set_field8(&rfcsr, RFCSR1_TX2_PD, 1); + /* fallthrough */ + case 2: + rt2x00_set_field8(&rfcsr, RFCSR1_TX1_PD, 1); + /* fallthrough */ + case 1: + rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1); + break; + } + + switch (rt2x00dev->default_ant.rx_chain_num) { + case 3: + rt2x00_set_field8(&rfcsr, RFCSR1_RX2_PD, 1); + /* fallthrough */ + case 2: + rt2x00_set_field8(&rfcsr, RFCSR1_RX1_PD, 1); + /* fallthrough */ + case 1: + rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1); + break; + } + rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); + + /* TODO: frequency calibration? */ + + if (conf_is_ht40(conf)) { + txrx_agc_fc = rt2x00_get_field8(drv_data->calibration_bw40, + RFCSR24_TX_AGC_FC); + txrx_h20m = rt2x00_get_field8(drv_data->calibration_bw40, + RFCSR24_TX_H20M); + } else { + txrx_agc_fc = rt2x00_get_field8(drv_data->calibration_bw20, + RFCSR24_TX_AGC_FC); + txrx_h20m = rt2x00_get_field8(drv_data->calibration_bw20, + RFCSR24_TX_H20M); + } + + /* NOTE: the reference driver does not writes the new value + * back to RFCSR 32 + */ + rt2800_rfcsr_read(rt2x00dev, 32, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR32_TX_AGC_FC, txrx_agc_fc); + + if (rf->channel <= 14) + rfcsr = 0xa0; + else + rfcsr = 0x80; + rt2800_rfcsr_write(rt2x00dev, 31, rfcsr); + + rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, txrx_h20m); + rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, txrx_h20m); + rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); + + /* Band selection */ + rt2800_rfcsr_read(rt2x00dev, 36, &rfcsr); + if (rf->channel <= 14) + rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 1); + else + rt2x00_set_field8(&rfcsr, RFCSR36_RF_BS, 0); + rt2800_rfcsr_write(rt2x00dev, 36, rfcsr); + + rt2800_rfcsr_read(rt2x00dev, 34, &rfcsr); + if (rf->channel <= 14) + rfcsr = 0x3c; + else + rfcsr = 0x20; + rt2800_rfcsr_write(rt2x00dev, 34, rfcsr); + + rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr); + if (rf->channel <= 14) + rfcsr = 0x1a; + else + rfcsr = 0x12; + rt2800_rfcsr_write(rt2x00dev, 12, rfcsr); + + rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr); + if (rf->channel >= 1 && rf->channel <= 14) + rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 1); + else if (rf->channel >= 36 && rf->channel <= 64) + rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 2); + else if (rf->channel >= 100 && rf->channel <= 128) + rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 2); + else + rt2x00_set_field8(&rfcsr, RFCSR6_VCO_IC, 1); + rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); + + rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR30_RX_VCM, 2); + rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); + + rt2800_rfcsr_write(rt2x00dev, 46, 0x60); + + if (rf->channel <= 14) { + rt2800_rfcsr_write(rt2x00dev, 10, 0xd3); + rt2800_rfcsr_write(rt2x00dev, 13, 0x12); + } else { + rt2800_rfcsr_write(rt2x00dev, 10, 0xd8); + rt2800_rfcsr_write(rt2x00dev, 13, 0x23); + } + + rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR51_BITS01, 1); + rt2800_rfcsr_write(rt2x00dev, 51, rfcsr); + + rt2800_rfcsr_read(rt2x00dev, 51, &rfcsr); + if (rf->channel <= 14) { + rt2x00_set_field8(&rfcsr, RFCSR51_BITS24, 5); + rt2x00_set_field8(&rfcsr, RFCSR51_BITS57, 3); + } else { + rt2x00_set_field8(&rfcsr, RFCSR51_BITS24, 4); + rt2x00_set_field8(&rfcsr, RFCSR51_BITS57, 2); + } + rt2800_rfcsr_write(rt2x00dev, 51, rfcsr); + + rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr); + if (rf->channel <= 14) + rt2x00_set_field8(&rfcsr, RFCSR49_TX_LO1_IC, 3); + else + rt2x00_set_field8(&rfcsr, RFCSR49_TX_LO1_IC, 2); + + if (txbf_enabled) + rt2x00_set_field8(&rfcsr, RFCSR49_TX_DIV, 1); + + rt2800_rfcsr_write(rt2x00dev, 49, rfcsr); + + rt2800_rfcsr_read(rt2x00dev, 50, &rfcsr); + rt2x00_set_field8(&rfcsr, RFCSR50_TX_LO1_EN, 0); + rt2800_rfcsr_write(rt2x00dev, 50, rfcsr); + + rt2800_rfcsr_read(rt2x00dev, 57, &rfcsr); + if (rf->channel <= 14) + rt2x00_set_field8(&rfcsr, RFCSR57_DRV_CC, 0x1b); + else + rt2x00_set_field8(&rfcsr, RFCSR57_DRV_CC, 0x0f); + rt2800_rfcsr_write(rt2x00dev, 57, rfcsr); + + if (rf->channel <= 14) { + rt2800_rfcsr_write(rt2x00dev, 44, 0x93); + rt2800_rfcsr_write(rt2x00dev, 52, 0x45); + } else { + rt2800_rfcsr_write(rt2x00dev, 44, 0x9b); + rt2800_rfcsr_write(rt2x00dev, 52, 0x05); + } + + /* Initiate VCO calibration */ + rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr); + if (rf->channel <= 14) { + rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1); + } else { + rt2x00_set_field8(&rfcsr, RFCSR3_BIT1, 1); + rt2x00_set_field8(&rfcsr, RFCSR3_BIT2, 1); + rt2x00_set_field8(&rfcsr, RFCSR3_BIT3, 1); + rt2x00_set_field8(&rfcsr, RFCSR3_BIT4, 1); + rt2x00_set_field8(&rfcsr, RFCSR3_BIT5, 1); + rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1); + } + rt2800_rfcsr_write(rt2x00dev, 3, rfcsr); + + if (rf->channel >= 1 && rf->channel <= 14) { + rfcsr = 0x23; + if (txbf_enabled) + rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1); + rt2800_rfcsr_write(rt2x00dev, 39, rfcsr); + + rt2800_rfcsr_write(rt2x00dev, 45, 0xbb); + } else if (rf->channel >= 36 && rf->channel <= 64) { + rfcsr = 0x36; + if (txbf_enabled) + rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1); + rt2800_rfcsr_write(rt2x00dev, 39, 0x36); + + rt2800_rfcsr_write(rt2x00dev, 45, 0xeb); + } else if (rf->channel >= 100 && rf->channel <= 128) { + rfcsr = 0x32; + if (txbf_enabled) + rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1); + rt2800_rfcsr_write(rt2x00dev, 39, rfcsr); + + rt2800_rfcsr_write(rt2x00dev, 45, 0xb3); + } else { + rfcsr = 0x30; + if (txbf_enabled) + rt2x00_set_field8(&rfcsr, RFCSR39_RX_DIV, 1); + rt2800_rfcsr_write(rt2x00dev, 39, rfcsr); + + rt2800_rfcsr_write(rt2x00dev, 45, 0x9b); + } +} + #define POWER_BOUND 0x27 #define POWER_BOUND_5G 0x2b #define FREQ_OFFSET_BOUND 0x5f @@ -2784,6 +3081,9 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, case RF3052: rt2800_config_channel_rf3052(rt2x00dev, conf, rf, info); break; + case RF3053: + rt2800_config_channel_rf3053(rt2x00dev, conf, rf, info); + break; case RF3290: rt2800_config_channel_rf3290(rt2x00dev, conf, rf, info); break; @@ -2829,6 +3129,23 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain); rt2800_bbp_write(rt2x00dev, 27, 0x20); rt2800_bbp_write(rt2x00dev, 66, 0x26 + rt2x00dev->lna_gain); + } else if (rt2x00_rt(rt2x00dev, RT3593)) { + if (rf->channel > 14) { + /* Disable CCK Packet detection on 5GHz */ + rt2800_bbp_write(rt2x00dev, 70, 0x00); + } else { + rt2800_bbp_write(rt2x00dev, 70, 0x0a); + } + + if (conf_is_ht40(conf)) + rt2800_bbp_write(rt2x00dev, 105, 0x04); + else + rt2800_bbp_write(rt2x00dev, 105, 0x34); + + rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); + rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); + rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); + rt2800_bbp_write(rt2x00dev, 77, 0x98); } else { rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); @@ -2844,16 +3161,27 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, rt2800_bbp_write(rt2x00dev, 82, 0x62); rt2800_bbp_write(rt2x00dev, 75, 0x46); } else { - rt2800_bbp_write(rt2x00dev, 82, 0x84); + if (rt2x00_rt(rt2x00dev, RT3593)) + rt2800_bbp_write(rt2x00dev, 82, 0x62); + else + rt2800_bbp_write(rt2x00dev, 82, 0x84); rt2800_bbp_write(rt2x00dev, 75, 0x50); } + if (rt2x00_rt(rt2x00dev, RT3593)) + rt2800_bbp_write(rt2x00dev, 83, 0x8a); } + } else { if (rt2x00_rt(rt2x00dev, RT3572)) rt2800_bbp_write(rt2x00dev, 82, 0x94); + else if (rt2x00_rt(rt2x00dev, RT3593)) + rt2800_bbp_write(rt2x00dev, 82, 0x82); else rt2800_bbp_write(rt2x00dev, 82, 0xf2); + if (rt2x00_rt(rt2x00dev, RT3593)) + rt2800_bbp_write(rt2x00dev, 83, 0x9a); + if (test_bit(CAPABILITY_EXTERNAL_LNA_A, &rt2x00dev->cap_flags)) rt2800_bbp_write(rt2x00dev, 75, 0x46); else @@ -2924,6 +3252,41 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, if (rt2x00_rt(rt2x00dev, RT3572)) rt2800_rfcsr_write(rt2x00dev, 8, 0x80); + if (rt2x00_rt(rt2x00dev, RT3593)) { + if (rt2x00_is_usb(rt2x00dev)) { + rt2800_register_read(rt2x00dev, GPIO_CTRL, ®); + + /* Band selection. GPIO #8 controls all paths */ + rt2x00_set_field32(®, GPIO_CTRL_DIR8, 0); + if (rf->channel <= 14) + rt2x00_set_field32(®, GPIO_CTRL_VAL8, 1); + else + rt2x00_set_field32(®, GPIO_CTRL_VAL8, 0); + + rt2x00_set_field32(®, GPIO_CTRL_DIR4, 0); + rt2x00_set_field32(®, GPIO_CTRL_DIR7, 0); + + /* LNA PE control. + * GPIO #4 controls PE0 and PE1, + * GPIO #7 controls PE2 + */ + rt2x00_set_field32(®, GPIO_CTRL_VAL4, 1); + rt2x00_set_field32(®, GPIO_CTRL_VAL7, 1); + + rt2800_register_write(rt2x00dev, GPIO_CTRL, reg); + } + + /* AGC init */ + if (rf->channel <= 14) + reg = 0x1c + 2 * rt2x00dev->lna_gain; + else + reg = 0x22 + ((rt2x00dev->lna_gain * 5) / 3); + + rt2800_bbp_write_with_rx_chain(rt2x00dev, 66, reg); + + usleep_range(1000, 1500); + } + if (rt2x00_rt(rt2x00dev, RT5592)) { rt2800_bbp_write(rt2x00dev, 195, 141); rt2800_bbp_write(rt2x00dev, 196, conf_is_ht40(conf) ? 0x10 : 0x1a); @@ -5883,6 +6246,7 @@ static void rt3593_post_bbp_init(struct rt2x00_dev *rt2x00dev) /* FIXME: BBP 105 owerwrite? */ rt2800_bbp_write(rt2x00dev, 105, 0x04); + } static void rt2800_init_rfcsr_3593(struct rt2x00_dev *rt2x00dev) -- cgit From 1095df07bfc5924e100f1748e6ebc9e5a5881565 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 8 Jul 2013 16:08:31 +0200 Subject: rt2x00: rt2800lib: enable VCO recalibration for RF3053 Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index e6d6c75dc2ce..46d5f429987d 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -4194,6 +4194,7 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev) rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1); rt2800_rfcsr_write(rt2x00dev, 7, rfcsr); break; + case RF3053: case RF3290: case RF5360: case RF5370: @@ -7595,6 +7596,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) case RF3022: case RF3320: case RF3052: + case RF3053: case RF3290: case RF5360: case RF5370: -- cgit From 0f5af26a49c8d6a50ecec2f1b66174069c9f9581 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 8 Jul 2013 16:08:32 +0200 Subject: rt2x00: rt2800lib: enable RF3053 support Support for the RF3053 has been implemented in the previous changes, so it is safe to mark it supported in the driver. Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 46d5f429987d..9ab587edb28b 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -6948,6 +6948,7 @@ static int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) case RF3021: case RF3022: case RF3052: + case RF3053: case RF3290: case RF3320: case RF3322: -- cgit From 2dc2bd2f8aa8eb79184fb3c7e5f530006500897f Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 8 Jul 2013 16:08:33 +0200 Subject: rt2x00: rt2800lib: enable RT3593 support Support for the RT3593 has been implemented in the previous changes, so it is safe to mark it supported in the driver. Signed-off-by: Gabor Juhos Acked-by: Stanislaw Gruszka Acked-by: Gertjan van Wingerde Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 9ab587edb28b..dedc3d4ae365 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -7636,6 +7636,7 @@ static int rt2800_probe_rt(struct rt2x00_dev *rt2x00dev) case RT3352: case RT3390: case RT3572: + case RT3593: case RT5390: case RT5392: case RT5592: -- cgit From ae1b1c5dcdef1ebd4b37a7d56ad767add757a660 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Fri, 16 Aug 2013 10:23:29 +0200 Subject: rt2x00: rt2800lib: introduce rt2800_get_txwi_rxwi_size helper The rt2800pci driver uses the same [RT]XWI size for all chipsets, however some chips requires different values. The size of the [RT]XWI structures is a constant value for a given chipset and it does not depend on the underlying interface. Add a helper function which returns the correct values for the actual chipset and use the new helper both in the rt2800usb and in the rt2800pci drivers. This ensures that both drivers are using the correct values. Signed-off-by: Gabor Juhos Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 23 +++++++++++++++++++++++ drivers/net/wireless/rt2x00/rt2800lib.h | 4 ++++ drivers/net/wireless/rt2x00/rt2800pci.c | 11 ++++++++--- drivers/net/wireless/rt2x00/rt2800usb.c | 11 +---------- 4 files changed, 36 insertions(+), 13 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index dedc3d4ae365..313da6ac2ee4 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -521,6 +521,29 @@ void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev) } EXPORT_SYMBOL_GPL(rt2800_disable_wpdma); +void rt2800_get_txwi_rxwi_size(struct rt2x00_dev *rt2x00dev, + unsigned short *txwi_size, + unsigned short *rxwi_size) +{ + switch (rt2x00dev->chip.rt) { + case RT3593: + *txwi_size = TXWI_DESC_SIZE_4WORDS; + *rxwi_size = RXWI_DESC_SIZE_5WORDS; + break; + + case RT5592: + *txwi_size = TXWI_DESC_SIZE_5WORDS; + *rxwi_size = RXWI_DESC_SIZE_6WORDS; + break; + + default: + *txwi_size = TXWI_DESC_SIZE_4WORDS; + *rxwi_size = RXWI_DESC_SIZE_4WORDS; + break; + } +} +EXPORT_SYMBOL_GPL(rt2800_get_txwi_rxwi_size); + static bool rt2800_check_firmware_crc(const u8 *data, const size_t len) { u16 fw_crc; diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 6ec739466db4..a94ba447e63c 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h @@ -226,4 +226,8 @@ int rt2800_get_survey(struct ieee80211_hw *hw, int idx, struct survey_info *survey); void rt2800_disable_wpdma(struct rt2x00_dev *rt2x00dev); +void rt2800_get_txwi_rxwi_size(struct rt2x00_dev *rt2x00dev, + unsigned short *txwi_size, + unsigned short *rxwi_size); + #endif /* RT2800LIB_H */ diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 00055627eb8d..dcad90c80542 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -1189,12 +1189,17 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { static void rt2800pci_queue_init(struct data_queue *queue) { + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; + unsigned short txwi_size, rxwi_size; + + rt2800_get_txwi_rxwi_size(rt2x00dev, &txwi_size, &rxwi_size); + switch (queue->qid) { case QID_RX: queue->limit = 128; queue->data_size = AGGREGATION_SIZE; queue->desc_size = RXD_DESC_SIZE; - queue->winfo_size = RXWI_DESC_SIZE_4WORDS; + queue->winfo_size = rxwi_size; queue->priv_size = sizeof(struct queue_entry_priv_mmio); break; @@ -1205,7 +1210,7 @@ static void rt2800pci_queue_init(struct data_queue *queue) queue->limit = 64; queue->data_size = AGGREGATION_SIZE; queue->desc_size = TXD_DESC_SIZE; - queue->winfo_size = TXWI_DESC_SIZE_4WORDS; + queue->winfo_size = txwi_size; queue->priv_size = sizeof(struct queue_entry_priv_mmio); break; @@ -1213,7 +1218,7 @@ static void rt2800pci_queue_init(struct data_queue *queue) queue->limit = 8; queue->data_size = 0; /* No DMA required for beacons */ queue->desc_size = TXD_DESC_SIZE; - queue->winfo_size = TXWI_DESC_SIZE_4WORDS; + queue->winfo_size = txwi_size; queue->priv_size = sizeof(struct queue_entry_priv_mmio); break; diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index fc9efdfca8f2..338034e18243 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -854,16 +854,7 @@ static void rt2800usb_queue_init(struct data_queue *queue) struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; unsigned short txwi_size, rxwi_size; - if (rt2x00_rt(rt2x00dev, RT3593)) { - txwi_size = TXWI_DESC_SIZE_4WORDS; - rxwi_size = RXWI_DESC_SIZE_5WORDS; - } else if (rt2x00_rt(rt2x00dev, RT5592)) { - txwi_size = TXWI_DESC_SIZE_5WORDS; - rxwi_size = RXWI_DESC_SIZE_6WORDS; - } else { - txwi_size = TXWI_DESC_SIZE_4WORDS; - rxwi_size = RXWI_DESC_SIZE_4WORDS; - } + rt2800_get_txwi_rxwi_size(rt2x00dev, &txwi_size, &rxwi_size); switch (queue->qid) { case QID_RX: -- cgit From 91a3fa39ddf2f85a15cb20ccc3a54c1f0497af1e Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Sat, 17 Aug 2013 00:15:49 +0200 Subject: rt2x00: rt2800: rename HW_BEACON_OFFSET macro The name of the HW_BEACON_OFFSET macro is a bit confusing. It returns with one of the HW_BEACON_BASE* values, so rename the macro to HW_BEACON_BASE to reflect that. The patch contains no functional changes. Signed-off-by: Gabor Juhos Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800.h | 2 +- drivers/net/wireless/rt2x00/rt2800lib.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index a3132414ac9f..6e69b961909f 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -2019,7 +2019,7 @@ struct mac_iveiv_entry { #define HW_BEACON_BASE6 0x5dc0 #define HW_BEACON_BASE7 0x5bc0 -#define HW_BEACON_OFFSET(__index) \ +#define HW_BEACON_BASE(__index) \ (((__index) < 4) ? (HW_BEACON_BASE0 + (__index * 0x0200)) : \ (((__index) < 6) ? (HW_BEACON_BASE4 + ((__index - 4) * 0x0200)) : \ (HW_BEACON_BASE6 - ((__index - 6) * 0x0200)))) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 313da6ac2ee4..704fcfbca06b 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -992,7 +992,7 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) return; } - beacon_base = HW_BEACON_OFFSET(entry->entry_idx); + beacon_base = HW_BEACON_BASE(entry->entry_idx); rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data, entry->skb->len + padding_len); @@ -1042,7 +1042,7 @@ void rt2800_clear_beacon(struct queue_entry *entry) * Clear beacon. */ rt2800_clear_beacon_register(rt2x00dev, - HW_BEACON_OFFSET(entry->entry_idx)); + HW_BEACON_BASE(entry->entry_idx)); /* * Enabled beaconing again. -- cgit From 77f7c0f3b8f2d464e841c5c35f3da8b4999a885c Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Sat, 17 Aug 2013 00:15:50 +0200 Subject: rt2x00: rt2800lib: pass beacon index to rt2800_clear_beacon_register Instead of precomputing the beacon base in each caller, pass the beacon index to the 'rt2800_clear_beacon_register' function and compute the beacon base in there. This allows to simplify the caller functions a bit. Signed-off-by: Gabor Juhos Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 704fcfbca06b..2f64034606b0 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1011,10 +1011,13 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) EXPORT_SYMBOL_GPL(rt2800_write_beacon); static inline void rt2800_clear_beacon_register(struct rt2x00_dev *rt2x00dev, - unsigned int beacon_base) + unsigned int index) { int i; const int txwi_desc_size = rt2x00dev->bcn->winfo_size; + unsigned int beacon_base; + + beacon_base = HW_BEACON_BASE(index); /* * For the Beacon base registers we only need to clear @@ -1041,8 +1044,7 @@ void rt2800_clear_beacon(struct queue_entry *entry) /* * Clear beacon. */ - rt2800_clear_beacon_register(rt2x00dev, - HW_BEACON_BASE(entry->entry_idx)); + rt2800_clear_beacon_register(rt2x00dev, entry->entry_idx); /* * Enabled beaconing again. @@ -4803,14 +4805,8 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) /* * Clear all beacons */ - rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE0); - rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE1); - rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE2); - rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE3); - rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE4); - rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE5); - rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE6); - rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE7); + for (i = 0; i < 8; i++) + rt2800_clear_beacon_register(rt2x00dev, i); if (rt2x00_is_usb(rt2x00dev)) { rt2800_register_read(rt2x00dev, US_CYC_CNT, ®); -- cgit From c1fada4e5e53d88a8edd3ff01cee9d316cbf6025 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Sat, 17 Aug 2013 14:09:28 +0200 Subject: rt2x00: rt2800lib: fix frequency offset boundary calculation The current code in the 'rt2800_adjust_freq_offset' function limits the device specific frequency offset value to FREQ_BOUND but ignores the fact that the uppermost bit is not part of the frequency offset value. As the result, the driver always uses the FREQ_BOUND value if the uppermost bit is set. Update the code to use the correct source value for calculating the boundary. Based on the DPO_RT5572_LinuxSTA_2.6.0.1_20120629 driver. Reference: RTMPAdjustFrequencyOffset function in common/rt_rf.c Signed-off-by: Gabor Juhos Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 2f64034606b0..de2727774477 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -2496,13 +2496,14 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev, static void rt2800_adjust_freq_offset(struct rt2x00_dev *rt2x00dev) { + u8 freq_offset; u8 rfcsr; + freq_offset = rt2x00_get_field8(rt2x00dev->freq_offset, RFCSR17_CODE); + freq_offset = min_t(u8, freq_offset, FREQ_OFFSET_BOUND); + rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); - if (rt2x00dev->freq_offset > FREQ_OFFSET_BOUND) - rt2x00_set_field8(&rfcsr, RFCSR17_CODE, FREQ_OFFSET_BOUND); - else - rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset); + rt2x00_set_field8(&rfcsr, RFCSR17_CODE, freq_offset); rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); } -- cgit From 6af1bdccabe956a08a37f2ae049d37307ec0c91c Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Sat, 17 Aug 2013 14:09:29 +0200 Subject: rt2x00: rt2800lib: optimize frequency offset adjustment Don't write the new value into the register if it is the same as the old value to avoid unncessary USB bus traffic with USB devices. The change also saves a few cycle on MMIO based devices. Based on the DPO_RT5572_LinuxSTA_2.6.0.1_20120629 driver. Reference: RTMPAdjustFrequencyOffset function in common/rt_rf.c Signed-off-by: Gabor Juhos Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index de2727774477..3407ac911fd6 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -2497,13 +2497,18 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev, static void rt2800_adjust_freq_offset(struct rt2x00_dev *rt2x00dev) { u8 freq_offset; - u8 rfcsr; + u8 rfcsr, prev_rfcsr; freq_offset = rt2x00_get_field8(rt2x00dev->freq_offset, RFCSR17_CODE); freq_offset = min_t(u8, freq_offset, FREQ_OFFSET_BOUND); rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); + prev_rfcsr = rfcsr; + rt2x00_set_field8(&rfcsr, RFCSR17_CODE, freq_offset); + if (rfcsr == prev_rfcsr) + return; + rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); } -- cgit From 76773f301f2210dcc20c466aebda7118062673eb Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Sat, 17 Aug 2013 14:09:30 +0200 Subject: rt2x00: rt2800lib: use a MCU command for frequency adjustment on USB devices According to the Ralink driver, there is an MCU command which can be used to send the frequency offset value directly to the USB device without going through the RFCSR writing sequence. Based on the DPO_RT5572_LinuxSTA_2.6.0.1_20120629 driver. Reference: RTMPAdjustFrequencyOffset function in common/rt_rf.c Signed-off-by: Gabor Juhos Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800.h | 1 + drivers/net/wireless/rt2x00/rt2800lib.c | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index 6e69b961909f..e25e5bf34aa7 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -2794,6 +2794,7 @@ enum rt2800_eeprom_word { #define MCU_RADAR 0x60 #define MCU_BOOT_SIGNAL 0x72 #define MCU_ANT_SELECT 0X73 +#define MCU_FREQ_OFFSET 0x74 #define MCU_BBP_SIGNAL 0x80 #define MCU_POWER_SAVE 0x83 #define MCU_BAND_SELECT 0x91 diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 3407ac911fd6..bebc56f5b849 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -2509,7 +2509,11 @@ static void rt2800_adjust_freq_offset(struct rt2x00_dev *rt2x00dev) if (rfcsr == prev_rfcsr) return; - rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); + if (rt2x00_is_usb(rt2x00dev)) + rt2800_mcu_request(rt2x00dev, MCU_FREQ_OFFSET, 0xff, + freq_offset, prev_rfcsr); + else + rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); } static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev, -- cgit From 8d38eca8e089179b6858ca5f3ea03f571a5892a5 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Sat, 17 Aug 2013 14:09:31 +0200 Subject: rt2x00: rt2800lib: use step-by-step frequency offset adjustment on MMIO devices According to the DPO_RT5572_LinuxSTA_2.6.0.1_20120629 driver, the RFCSR17 register can't be programmed in one step on devices which are using the frequency offset adjustment code. Update the code to use step-by-step adjustment. Reference: RT30xxWriteRFRegister function in common/rt_rf.c Signed-off-by: Gabor Juhos Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index bebc56f5b849..623ad9d21ee5 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -2496,7 +2496,7 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev, static void rt2800_adjust_freq_offset(struct rt2x00_dev *rt2x00dev) { - u8 freq_offset; + u8 freq_offset, prev_freq_offset; u8 rfcsr, prev_rfcsr; freq_offset = rt2x00_get_field8(rt2x00dev->freq_offset, RFCSR17_CODE); @@ -2509,11 +2509,24 @@ static void rt2800_adjust_freq_offset(struct rt2x00_dev *rt2x00dev) if (rfcsr == prev_rfcsr) return; - if (rt2x00_is_usb(rt2x00dev)) + if (rt2x00_is_usb(rt2x00dev)) { rt2800_mcu_request(rt2x00dev, MCU_FREQ_OFFSET, 0xff, freq_offset, prev_rfcsr); - else + return; + } + + prev_freq_offset = rt2x00_get_field8(prev_rfcsr, RFCSR17_CODE); + while (prev_freq_offset != freq_offset) { + if (prev_freq_offset < freq_offset) + prev_freq_offset++; + else + prev_freq_offset--; + + rt2x00_set_field8(&rfcsr, RFCSR17_CODE, prev_freq_offset); rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); + + usleep_range(1000, 1500); + } } static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev, -- cgit From 3f1b8739a498c7570ca2fae6c49fd1561ef2358c Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Sat, 17 Aug 2013 14:09:32 +0200 Subject: rt2x00: rt2800lib: move rt2800_adjust_freq_offset function Move the rt2800_adjust_freq_offset function before the channel configuration functions to make it usable from those without a forward declaration. The patch contains no functional changes. Signed-off-by: Gabor Juhos Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 73 +++++++++++++++++---------------- 1 file changed, 37 insertions(+), 36 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 623ad9d21ee5..1b81fc933f28 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -1875,6 +1875,43 @@ static void rt2800_config_lna_gain(struct rt2x00_dev *rt2x00dev, rt2x00dev->lna_gain = lna_gain; } +#define FREQ_OFFSET_BOUND 0x5f + +static void rt2800_adjust_freq_offset(struct rt2x00_dev *rt2x00dev) +{ + u8 freq_offset, prev_freq_offset; + u8 rfcsr, prev_rfcsr; + + freq_offset = rt2x00_get_field8(rt2x00dev->freq_offset, RFCSR17_CODE); + freq_offset = min_t(u8, freq_offset, FREQ_OFFSET_BOUND); + + rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); + prev_rfcsr = rfcsr; + + rt2x00_set_field8(&rfcsr, RFCSR17_CODE, freq_offset); + if (rfcsr == prev_rfcsr) + return; + + if (rt2x00_is_usb(rt2x00dev)) { + rt2800_mcu_request(rt2x00dev, MCU_FREQ_OFFSET, 0xff, + freq_offset, prev_rfcsr); + return; + } + + prev_freq_offset = rt2x00_get_field8(prev_rfcsr, RFCSR17_CODE); + while (prev_freq_offset != freq_offset) { + if (prev_freq_offset < freq_offset) + prev_freq_offset++; + else + prev_freq_offset--; + + rt2x00_set_field8(&rfcsr, RFCSR17_CODE, prev_freq_offset); + rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); + + usleep_range(1000, 1500); + } +} + static void rt2800_config_channel_rf2xxx(struct rt2x00_dev *rt2x00dev, struct ieee80211_conf *conf, struct rf_channel *rf, @@ -2492,42 +2529,6 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev, #define POWER_BOUND 0x27 #define POWER_BOUND_5G 0x2b -#define FREQ_OFFSET_BOUND 0x5f - -static void rt2800_adjust_freq_offset(struct rt2x00_dev *rt2x00dev) -{ - u8 freq_offset, prev_freq_offset; - u8 rfcsr, prev_rfcsr; - - freq_offset = rt2x00_get_field8(rt2x00dev->freq_offset, RFCSR17_CODE); - freq_offset = min_t(u8, freq_offset, FREQ_OFFSET_BOUND); - - rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr); - prev_rfcsr = rfcsr; - - rt2x00_set_field8(&rfcsr, RFCSR17_CODE, freq_offset); - if (rfcsr == prev_rfcsr) - return; - - if (rt2x00_is_usb(rt2x00dev)) { - rt2800_mcu_request(rt2x00dev, MCU_FREQ_OFFSET, 0xff, - freq_offset, prev_rfcsr); - return; - } - - prev_freq_offset = rt2x00_get_field8(prev_rfcsr, RFCSR17_CODE); - while (prev_freq_offset != freq_offset) { - if (prev_freq_offset < freq_offset) - prev_freq_offset++; - else - prev_freq_offset--; - - rt2x00_set_field8(&rfcsr, RFCSR17_CODE, prev_freq_offset); - rt2800_rfcsr_write(rt2x00dev, 17, rfcsr); - - usleep_range(1000, 1500); - } -} static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev, struct ieee80211_conf *conf, -- cgit From e979a8ab204edbf7b0815162109ee9c85e4d7ea5 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Sat, 17 Aug 2013 14:09:33 +0200 Subject: rt2x00: rt2800lib: adjust frequency offset for RF3053 Along with other chipsets, the Ralink driver uses the frequency adjustment code for RF3053 as well. Remove the bogus place-holder comment from the RF3053 specific channel configuration function and call the frequency adjustment function instead Based on the DPO_RT5572_LinuxSTA_2.6.0.1_20120629 driver. Reference: RT3593_ChipSwitchChannel function in chips/rt3593.c Signed-off-by: Gabor Juhos Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 1b81fc933f28..aa6b6b022547 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -2360,7 +2360,7 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev, } rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); - /* TODO: frequency calibration? */ + rt2800_adjust_freq_offset(rt2x00dev); if (conf_is_ht40(conf)) { txrx_agc_fc = rt2x00_get_field8(drv_data->calibration_bw40, -- cgit From 21c6af6b69b609b7934caaccda1b4535dceb402c Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Thu, 22 Aug 2013 20:53:21 +0200 Subject: rt2x00: rt2800lib: add rt2800_hw_beacon_base helper The HW_BEACON_BASE() macro returns the base address of a given beacon, however the returned values are not usable on all chipsets. On devices which have selectable shared memory parts, some beacon may be located in the high part of the shared memory. Instead of extending the already complicated macro, add a new helper function and use that to get the base address of a given beacon. The actual patch contains no functional changes, the helper function will be extended in a further patch to handle different chipsets' requirements. Signed-off-by: Gabor Juhos Acked-by: Helmut Schaa Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index aa6b6b022547..38606e2f8a52 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -940,6 +940,12 @@ void rt2800_txdone_entry(struct queue_entry *entry, u32 status, __le32 *txwi) } EXPORT_SYMBOL_GPL(rt2800_txdone_entry); +static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev, + unsigned int index) +{ + return HW_BEACON_BASE(index); +} + void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; @@ -992,7 +998,8 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) return; } - beacon_base = HW_BEACON_BASE(entry->entry_idx); + beacon_base = rt2800_hw_beacon_base(rt2x00dev, entry->entry_idx); + rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data, entry->skb->len + padding_len); @@ -1017,7 +1024,7 @@ static inline void rt2800_clear_beacon_register(struct rt2x00_dev *rt2x00dev, const int txwi_desc_size = rt2x00dev->bcn->winfo_size; unsigned int beacon_base; - beacon_base = HW_BEACON_BASE(index); + beacon_base = rt2800_hw_beacon_base(rt2x00dev, index); /* * For the Beacon base registers we only need to clear -- cgit From 634b80595fef79071d82bc231b7f82c4f808a1e8 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Thu, 22 Aug 2013 20:53:22 +0200 Subject: rt2x00: rt2800lib: don't hardcode beacon offsets The values written into the BCN_OFFSET[01] registers are hardcoded in the rt2800_init_register function. Add a macro and a helper function to derive these values directly from the base address of a given beacon, and use the new function instead of the hardcoded numbers. The patch contains no functional changes. The programmed register values are the same before and after the patch. Signed-off-by: Gabor Juhos Acked-by: Helmut Schaa Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800.h | 2 ++ drivers/net/wireless/rt2x00/rt2800lib.c | 30 ++++++++++++++++++++++-------- 2 files changed, 24 insertions(+), 8 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index e25e5bf34aa7..fa33b5edf931 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h @@ -2024,6 +2024,8 @@ struct mac_iveiv_entry { (((__index) < 6) ? (HW_BEACON_BASE4 + ((__index - 4) * 0x0200)) : \ (HW_BEACON_BASE6 - ((__index - 6) * 0x0200)))) +#define BEACON_BASE_TO_OFFSET(_base) (((_base) - 0x4000) / 64) + /* * BBP registers. * The wordsize of the BBP is 8 bits. diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 38606e2f8a52..20243dcd4a6c 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -946,6 +946,12 @@ static unsigned int rt2800_hw_beacon_base(struct rt2x00_dev *rt2x00dev, return HW_BEACON_BASE(index); } +static inline u8 rt2800_get_beacon_offset(struct rt2x00_dev *rt2x00dev, + unsigned int index) +{ + return BEACON_BASE_TO_OFFSET(rt2800_hw_beacon_base(rt2x00dev, index)); +} + void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; @@ -4474,17 +4480,25 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) return ret; rt2800_register_read(rt2x00dev, BCN_OFFSET0, ®); - rt2x00_set_field32(®, BCN_OFFSET0_BCN0, 0xe0); /* 0x3800 */ - rt2x00_set_field32(®, BCN_OFFSET0_BCN1, 0xe8); /* 0x3a00 */ - rt2x00_set_field32(®, BCN_OFFSET0_BCN2, 0xf0); /* 0x3c00 */ - rt2x00_set_field32(®, BCN_OFFSET0_BCN3, 0xf8); /* 0x3e00 */ + rt2x00_set_field32(®, BCN_OFFSET0_BCN0, + rt2800_get_beacon_offset(rt2x00dev, 0)); + rt2x00_set_field32(®, BCN_OFFSET0_BCN1, + rt2800_get_beacon_offset(rt2x00dev, 1)); + rt2x00_set_field32(®, BCN_OFFSET0_BCN2, + rt2800_get_beacon_offset(rt2x00dev, 2)); + rt2x00_set_field32(®, BCN_OFFSET0_BCN3, + rt2800_get_beacon_offset(rt2x00dev, 3)); rt2800_register_write(rt2x00dev, BCN_OFFSET0, reg); rt2800_register_read(rt2x00dev, BCN_OFFSET1, ®); - rt2x00_set_field32(®, BCN_OFFSET1_BCN4, 0xc8); /* 0x3200 */ - rt2x00_set_field32(®, BCN_OFFSET1_BCN5, 0xd0); /* 0x3400 */ - rt2x00_set_field32(®, BCN_OFFSET1_BCN6, 0x77); /* 0x1dc0 */ - rt2x00_set_field32(®, BCN_OFFSET1_BCN7, 0x6f); /* 0x1bc0 */ + rt2x00_set_field32(®, BCN_OFFSET1_BCN4, + rt2800_get_beacon_offset(rt2x00dev, 4)); + rt2x00_set_field32(®, BCN_OFFSET1_BCN5, + rt2800_get_beacon_offset(rt2x00dev, 5)); + rt2x00_set_field32(®, BCN_OFFSET1_BCN6, + rt2800_get_beacon_offset(rt2x00dev, 6)); + rt2x00_set_field32(®, BCN_OFFSET1_BCN7, + rt2800_get_beacon_offset(rt2x00dev, 7)); rt2800_register_write(rt2x00dev, BCN_OFFSET1, reg); rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f); -- cgit From 6e956da2027c767859128b9bfef085cf2a8e233b Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 26 Aug 2013 15:18:53 +0200 Subject: rt2800: fix wrong TX power compensation We should not do temperature compensation on devices without EXTERNAL_TX_ALC bit set (called DynamicTxAgcControl on vendor driver). Such devices can have totally bogus TSSI parameters on the EEPROM, but still threaded by us as valid and result doing wrong TX power calculations. This fix inability to connect to AP on slightly longer distance on some Ralink chips/devices. Reported-and-tested-by: Fabien ADAM Cc: stable@vger.kernel.org Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 20243dcd4a6c..660d7d856186 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -3407,6 +3407,13 @@ static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev) u8 step; int i; + /* + * First check if temperature compensation is supported. + */ + rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); + if (!rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_TX_ALC)) + return 0; + /* * Read TSSI boundaries for temperature compensation from * the EEPROM. -- cgit From f4e1a4d3ecbb9e42bdf8e7869ee8a4ebfa27fb20 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Mon, 9 Sep 2013 12:37:37 +0200 Subject: rt2800: change initialization sequence to fix system freeze My commit commit c630ccf1a127578421a928489d51e99c05037054 Author: Stanislaw Gruszka Date: Sat Mar 16 19:19:46 2013 +0100 rt2800: rearrange bbp/rfcsr initialization make Maxim machine freeze when try to start wireless device. Initialization order and sending MCU_BOOT_SIGNAL request, changed in above commit, is important. Doing things incorrectly make PCIe bus problems, which can froze the machine. This patch change initialization sequence like vendor driver do: function NICInitializeAsic() from 2011_1007_RT5390_RT5392_Linux_STA_V2.5.0.3_DPO (PCI devices) and DPO_RT5572_LinuxSTA_2.6.1.3_20121022 (according Mediatek, latest driver for RT8070/RT3070/RT3370/RT3572/RT5370/RT5372/RT5572 USB devices). It fixes freezes on Maxim system. Resolve: https://bugzilla.redhat.com/show_bug.cgi?id=1000679 Reported-and-tested-by: Maxim Polyakov Bisected-by: Igor Gnatenko Cc: stable@vger.kernel.org # 3.10+ Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless/rt2x00/rt2800lib.c') diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 95e6e61c3de0..88ce656f96cd 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -6659,19 +6659,20 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev) rt2800_init_registers(rt2x00dev))) return -EIO; + if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev))) + return -EIO; + /* * Send signal to firmware during boot time. */ rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0); rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); - if (rt2x00_is_usb(rt2x00dev)) { + if (rt2x00_is_usb(rt2x00dev)) rt2800_register_write(rt2x00dev, H2M_INT_SRC, 0); - rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); - } + rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0, 0, 0); msleep(1); - if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev) || - rt2800_wait_bbp_ready(rt2x00dev))) + if (unlikely(rt2800_wait_bbp_ready(rt2x00dev))) return -EIO; rt2800_init_bbp(rt2x00dev); -- cgit