/* * Once configured for I/O - set output lines */ HAL_BOOL ar9300GpioSet(struct ath_hal *ah, u_int32_t gpio, u_int32_t val) { HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins); OS_REG_RMW(ah, AR_HOSTIF_REG(ah, AR_GPIO_OUT), ((val&1) << gpio), AR_GPIO_BIT(gpio)); return AH_TRUE; }
/* * Once configured for I/O - set output lines */ HAL_BOOL ar7010GpioSet(struct ath_hal *ah, u_int32_t gpio, u_int32_t val) { HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.hal_num_gpio_pins); OS_REG_RMW(ah, AR7010_GPIO_OUT, ((val&1) << gpio), AR_GPIO_BIT(gpio)); return AH_TRUE; }
/* * Configure GPIO Output lines */ HAL_BOOL ar9300GpioCfgOutput( struct ath_hal *ah, u_int32_t gpio, HAL_GPIO_OUTPUT_MUX_TYPE halSignalType) { #define N(a) (sizeof(a) / sizeof(a[0])) #ifndef AR9340_EMULATION u_int32_t ah_signal_type; u_int32_t gpio_shift; static const u_int32_t MuxSignalConversionTable[] = { /* HAL_GPIO_OUTPUT_MUX_AS_OUTPUT */ AR_GPIO_OUTPUT_MUX_AS_OUTPUT, /* HAL_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED */ AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED, /* HAL_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED */ AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED, /* HAL_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED */ AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED, /* HAL_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED */ AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED, /* HAL_GPIO_OUTPUT_MUX_AS_WLAN_ACTIVE */ AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL, /* HAL_GPIO_OUTPUT_MUX_AS_TX_FRAME */ AR_GPIO_OUTPUT_MUX_AS_TX_FRAME, }; HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins); // Convert HAL signal type definitions to hardware-specific values. if ((halSignalType >= 0) && (halSignalType < N(MuxSignalConversionTable))) { ah_signal_type = MuxSignalConversionTable[halSignalType]; } else { return AH_FALSE; } // Configure the MUX ar9300GpioCfgOutputMux(ah, gpio, ah_signal_type); // 2 bits per output mode gpio_shift = 2*gpio; OS_REG_RMW(ah, AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT), (AR_GPIO_OE_OUT_DRV_ALL << gpio_shift), (AR_GPIO_OE_OUT_DRV << gpio_shift)); #endif return AH_TRUE; #undef N }
/* * Write 16 bits of data from data to the specified EEPROM offset. */ HAL_BOOL ar5416EepromWrite(struct ath_hal *ah, u_int off, u_int16_t data) { u_int32_t status; u_int32_t write_to = 50000; /* write timeout */ u_int32_t eepromValue; eepromValue = (u_int32_t)data & 0xffff; /* Setup EEPROM device to write */ OS_REG_RMW(ah, AR_GPIO_OUTPUT_MUX1, 0, 0x1f << 15); /* Mux GPIO-3 as GPIO */ OS_DELAY(1); OS_REG_RMW(ah, AR_GPIO_OE_OUT, 0xc0, 0xc0); /* Configure GPIO-3 as output */ OS_DELAY(1); OS_REG_RMW(ah, AR_GPIO_IN_OUT, 0, 1 << 3); /* drive GPIO-3 low */ OS_DELAY(1); /* Send write data, as 32 bit data */ OS_REG_WRITE(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S), eepromValue); /* check busy bit to see if eeprom write succeeded */ while (write_to > 0) { status = OS_REG_READ(ah, AR_EEPROM_STATUS_DATA) & (AR_EEPROM_STATUS_DATA_BUSY | AR_EEPROM_STATUS_DATA_BUSY_ACCESS | AR_EEPROM_STATUS_DATA_PROT_ACCESS | AR_EEPROM_STATUS_DATA_ABSENT_ACCESS); if (status == 0) { OS_REG_RMW(ah, AR_GPIO_IN_OUT, 1<<3, 1<<3); /* drive GPIO-3 hi */ return AH_TRUE; } OS_DELAY(1); write_to--; } OS_REG_RMW(ah, AR_GPIO_IN_OUT, 1<<3, 1<<3); /* drive GPIO-3 hi */ return AH_FALSE; }
static void ar9300_setup_test_addac_mode(struct ath_hal *ah) { #if AH_BYTE_ORDER == AH_BIG_ENDIAN /* byteswap Rx/Tx buffer to ensure correct layout */ HDPRINTF(ah, HAL_DBG_RF_PARAM, "%s: big endian - set AR_CFG_SWTB/AR_CFG_SWRB\n", __func__); OS_REG_RMW(ah, AR_CFG, AR_CFG_SWTB | AR_CFG_SWRB, 0); #else /* Rx/Tx buffer should not be byteswaped */ if (OS_REG_READ(ah, AR_CFG) & (AR_CFG_SWTB | AR_CFG_SWRB)) { HDPRINTF(ah, HAL_DBG_UNMASKABLE, "%s: **WARNING: little endian but AR_CFG_SWTB/AR_CFG_SWRB set!\n", __func__); } #endif OS_REG_WRITE(ah, AR_PHY_TEST, 0); OS_REG_WRITE(ah, AR_PHY_TEST_CTL_STATUS, 0); /* cf_bbb_obs_sel=4'b0001 */ OS_REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 0x1); /* cf_rx_obs_sel=5'b00000, this is the 5th bit */ OS_REG_CLR_BIT(ah, AR_PHY_TEST, AR_PHY_TEST_RX_OBS_SEL_BIT5); /* cf_tx_obs_sel=3'b111 */ OS_REG_RMW_FIELD( ah, AR_PHY_TEST_CTL_STATUS, AR_PHY_TEST_CTL_TX_OBS_SEL, 0x7); /* cf_tx_obs_mux_sel=2'b11 */ OS_REG_RMW_FIELD( ah, AR_PHY_TEST_CTL_STATUS, AR_PHY_TEST_CTL_TX_OBS_MUX_SEL, 0x3); /* enable TSTADC */ OS_REG_SET_BIT(ah, AR_PHY_TEST_CTL_STATUS, AR_PHY_TEST_CTL_TSTDAC_EN); /* cf_rx_obs_sel=5'b00000, these are the first 4 bits */ OS_REG_RMW_FIELD( ah, AR_PHY_TEST_CTL_STATUS, AR_PHY_TEST_CTL_RX_OBS_SEL, 0x0); /* tstdac_out_sel=2'b01 */ OS_REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_CHAIN_SEL, 0x1); }
/* * Configure GPIO Output Mux control */ static void cfgOutputMux(struct ath_hal *ah, uint32_t gpio, uint32_t type) { int addr; uint32_t gpio_shift, tmp; HALDEBUG(ah, HAL_DEBUG_GPIO, "%s: gpio=%d, type=%d\n", __func__, gpio, type); /* each MUX controls 6 GPIO pins */ if (gpio > 11) addr = AR_GPIO_OUTPUT_MUX3; else if (gpio > 5) addr = AR_GPIO_OUTPUT_MUX2; else addr = AR_GPIO_OUTPUT_MUX1; /* * 5 bits per GPIO pin. Bits 0..4 for 1st pin in that mux, * bits 5..9 for 2nd pin, etc. */ gpio_shift = (gpio % 6) * 5; /* * From Owl to Merlin 1.0, the value read from MUX1 bit 4 to bit * 9 are wrong. Here is hardware's coding: * PRDATA[4:0] <= gpio_output_mux[0]; * PRDATA[9:4] <= gpio_output_mux[1]; * <==== Bit 4 is used by both gpio_output_mux[0] [1]. * Currently the max value for gpio_output_mux[] is 6. So bit 4 * will never be used. So it should be fine that bit 4 won't be * able to recover. */ if (AR_SREV_MERLIN_20_OR_LATER(ah) || (addr != AR_GPIO_OUTPUT_MUX1)) { OS_REG_RMW(ah, addr, (type << gpio_shift), (0x1f << gpio_shift)); } else { tmp = OS_REG_READ(ah, addr); tmp = ((tmp & 0x1F0) << 1) | (tmp & ~0x1F0); tmp &= ~(0x1f << gpio_shift); tmp |= type << gpio_shift; OS_REG_WRITE(ah, addr, tmp); } }
/* * Configure GPIO Input lines */ HAL_BOOL ar7010GpioCfgInput(struct ath_hal *ah, u_int32_t gpio) { u_int32_t gpio_shift; HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.hal_num_gpio_pins); /* If configured as input, set output to tristate */ gpio_shift = gpio; /* Per bit output enable. 1: enable the input driver */ OS_REG_RMW(ah, AR7010_GPIO_OE, (AR7010_GPIO_OE_AS_INPUT << gpio_shift), (AR7010_GPIO_OE_MASK << gpio_shift)); return AH_TRUE; }
/* * Configure GPIO Input lines */ HAL_BOOL ar5416GpioCfgInput(struct ath_hal *ah, u_int32_t gpio) { u_int32_t gpio_shift; HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.hal_num_gpio_pins); /* TODO: configure input mux for AR5416 */ /* If configured as input, set output to tristate */ gpio_shift = 2*gpio; OS_REG_RMW(ah, AR_GPIO_OE_OUT, (AR_GPIO_OE_OUT_DRV_NO << gpio_shift), (AR_GPIO_OE_OUT_DRV << gpio_shift)); return AH_TRUE; }
/* * Configure GPIO Input lines */ HAL_BOOL ar9300GpioCfgInput(struct ath_hal *ah, u_int32_t gpio) { #ifndef AR9340_EMULATION u_int32_t gpio_shift; HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.halNumGpioPins); /* TODO: configure input mux for AR9300 */ /* If configured as input, set output to tristate */ gpio_shift = 2*gpio; OS_REG_RMW(ah, AR_HOSTIF_REG(ah, AR_GPIO_OE_OUT), (AR_GPIO_OE_OUT_DRV_NO << gpio_shift), (AR_GPIO_OE_OUT_DRV << gpio_shift)); #endif return AH_TRUE; }
/* * Configure GPIO Output Mux control */ static void ar5416GpioCfgOutputMux(struct ath_hal *ah, u_int32_t gpio, u_int32_t type) { int addr; u_int32_t gpio_shift, tmp; // each MUX controls 6 GPIO pins if (gpio > 11) { addr = AR_GPIO_OUTPUT_MUX3; } else if (gpio > 5) { addr = AR_GPIO_OUTPUT_MUX2; } else { addr = AR_GPIO_OUTPUT_MUX1; } // 5 bits per GPIO pin. Bits 0..4 for 1st pin in that mux, bits 5..9 for 2nd pin, etc. gpio_shift = (gpio % 6) * 5; /* * From Owl to Merlin 1.0, the value read from MUX1 bit 4 to bit 9 are wrong. * Here is hardware's coding: * PRDATA[4:0] <= gpio_output_mux[0]; * PRDATA[9:4] <= gpio_output_mux[1]; <==== Bit 4 is used by both gpio_output_mux[0] [1]. * Currently the max value for gpio_output_mux[] is 6. So bit 4 will never be used. * So it should be fine that bit 4 won't be able to recover. */ if (AR_SREV_MERLIN_20_OR_LATER(ah) || (addr != AR_GPIO_OUTPUT_MUX1)) { OS_REG_RMW(ah, addr, (type << gpio_shift), (0x1f << gpio_shift)); } else { tmp = OS_REG_READ(ah, addr); tmp = ((tmp & 0x1F0) << 1) | (tmp & ~0x1F0); tmp &= ~(0x1f << gpio_shift); tmp |= (type << gpio_shift); OS_REG_WRITE(ah, addr, tmp); } }
/* * Configure GPIO Output lines */ HAL_BOOL ar7010GpioCfgOutput(struct ath_hal *ah, u_int32_t gpio, HAL_GPIO_OUTPUT_MUX_TYPE halSignalType) { u_int32_t gpio_shift; HALASSERT(gpio < AH_PRIVATE(ah)->ah_caps.hal_num_gpio_pins); /* Magpie only support GPIO normal output */ if (halSignalType > HAL_GPIO_OUTPUT_MUX_AS_OUTPUT) { return AH_FALSE; } /* 1 bits per output mode */ gpio_shift = gpio; /* Per bit output enable. 0: enable the output driver */ OS_REG_RMW(ah, AR7010_GPIO_OE, (AR7010_GPIO_OE_AS_OUTPUT<< gpio_shift), (AR7010_GPIO_OE_MASK << gpio_shift)); return AH_TRUE; }
static void ar9300GpioCfgOutputMux(struct ath_hal *ah, u_int32_t gpio, u_int32_t type) { int addr; u_int32_t gpio_shift; // each MUX controls 6 GPIO pins if (gpio > 11) { addr = AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX3); } else if (gpio > 5) { addr = AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX2); } else { addr = AR_HOSTIF_REG(ah, AR_GPIO_OUTPUT_MUX1); } /* * 5 bits per GPIO pin. * Bits 0..4 for 1st pin in that mux, * bits 5..9 for 2nd pin, etc. */ gpio_shift = (gpio % 6) * 5; OS_REG_RMW(ah, addr, (type << gpio_shift), (0x1f << gpio_shift)); }
/* * This is specific to Kite. * * Kiwi and others don't have antenna diversity like this. */ void ar9285BTCoexAntennaDiversity(struct ath_hal *ah) { struct ath_hal_5416 *ahp = AH5416(ah); u_int32_t regVal; u_int8_t ant_div_control1, ant_div_control2; if ((ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_ANT_DIV_ALLOW) || (AH5212(ah)->ah_diversity != HAL_ANT_VARIABLE)) { if ((ahp->ah_btCoexFlag & HAL_BT_COEX_FLAG_ANT_DIV_ENABLE) && (AH5212(ah)->ah_diversity == HAL_ANT_VARIABLE)) { /* Enable antenna diversity */ ant_div_control1 = HAL_BT_COEX_ANTDIV_CONTROL1_ENABLE; ant_div_control2 = HAL_BT_COEX_ANTDIV_CONTROL2_ENABLE; /* Don't disable BT ant to allow BB to control SWCOM */ ahp->ah_btCoexMode2 &= (~(AR_BT_DISABLE_BT_ANT)); OS_REG_WRITE(ah, AR_BT_COEX_MODE2, ahp->ah_btCoexMode2); /* Program the correct SWCOM table */ OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, HAL_BT_COEX_ANT_DIV_SWITCH_COM); OS_REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, 0, 0xf0000000); } else if (AH5212(ah)->ah_diversity == HAL_ANT_FIXED_B) { /* Disable antenna diversity. Use antenna B(LNA2) only. */ ant_div_control1 = HAL_BT_COEX_ANTDIV_CONTROL1_FIXED_B; ant_div_control2 = HAL_BT_COEX_ANTDIV_CONTROL2_FIXED_B; /* Disable BT ant to allow concurrent BT and WLAN receive */ ahp->ah_btCoexMode2 |= AR_BT_DISABLE_BT_ANT; OS_REG_WRITE(ah, AR_BT_COEX_MODE2, ahp->ah_btCoexMode2); /* Program SWCOM talbe to make sure RF switch always parks at WLAN side */ OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, HAL_BT_COEX_ANT_DIV_SWITCH_COM); OS_REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, 0x60000000, 0xf0000000); } else { /* Disable antenna diversity. Use antenna A(LNA1) only */ ant_div_control1 = HAL_BT_COEX_ANTDIV_CONTROL1_FIXED_A; ant_div_control2 = HAL_BT_COEX_ANTDIV_CONTROL2_FIXED_A; /* Disable BT ant to allow concurrent BT and WLAN receive */ ahp->ah_btCoexMode2 |= AR_BT_DISABLE_BT_ANT; OS_REG_WRITE(ah, AR_BT_COEX_MODE2, ahp->ah_btCoexMode2); /* Program SWCOM talbe to make sure RF switch always parks at BT side */ OS_REG_WRITE(ah, AR_PHY_SWITCH_COM, 0); OS_REG_RMW(ah, AR_PHY_SWITCH_CHAIN_0, 0, 0xf0000000); } regVal = OS_REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); regVal &= (~(AR_PHY_9285_ANT_DIV_CTL_ALL)); /* Clear ant_fast_div_bias [14:9] since for Janus the main LNA is always LNA1. */ regVal &= (~(AR_PHY_9285_FAST_DIV_BIAS)); regVal |= SM(ant_div_control1, AR_PHY_9285_ANT_DIV_CTL); regVal |= SM(ant_div_control2, AR_PHY_9285_ANT_DIV_ALT_LNACONF); regVal |= SM((ant_div_control2 >> 2), AR_PHY_9285_ANT_DIV_MAIN_LNACONF); regVal |= SM((ant_div_control1 >> 1), AR_PHY_9285_ANT_DIV_ALT_GAINTB); regVal |= SM((ant_div_control1 >> 2), AR_PHY_9285_ANT_DIV_MAIN_GAINTB); OS_REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regVal); regVal = OS_REG_READ(ah, AR_PHY_CCK_DETECT); regVal &= (~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); regVal |= SM((ant_div_control1 >> 3), AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); OS_REG_WRITE(ah, AR_PHY_CCK_DETECT, regVal); } }