Skip to contentSkip to conversation

support for antenna configuration profiles

PATCH In review Daniel Golle 1 participant 1 message Nov 28, 2011 Qualcomm Atheros ATH9K wireless driver

lore
Share & tools
lore
#0 lore raw

PATCH 3/3 support for antenna configuration profiles

This adds support for controlling AR_PHY_SWITCH_COM of the AR9285 by using antenna configuration profiles to ath9k.

---
 drivers/net/wireless/ath/ath9k/ar9002_phy.c    |   13 ++++
 drivers/net/wireless/ath/ath9k/ar9003_eeprom.c |    8 ++-
 drivers/net/wireless/ath/ath9k/eeprom.h        |    1 +
 drivers/net/wireless/ath/ath9k/eeprom_4k.c     |   29 +++++++-
 drivers/net/wireless/ath/ath9k/eeprom_9287.c   |    8 ++-
 drivers/net/wireless/ath/ath9k/eeprom_def.c    |    8 ++-
 drivers/net/wireless/ath/ath9k/hw.h            |   28 +++++++
 drivers/net/wireless/ath/ath9k/init.c          |   93 ++++++++++++++++++++++++
 drivers/net/wireless/ath/ath9k/main.c          |   36 +++++++++
 include/linux/ath9k_platform.h                 |    6 ++
 10 files changed, 225 insertions(+), 5 deletions(-)
drivers/net/wireless/ath/ath9k/ar9002_phy.c +13 -0
index 3cbbb03..babf8b0 100644
@@ -556,6 +556,16 @@ static void ar9002_hw_antdiv_comb_conf_set(struct ath_hw *ah,
 	REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regval);
 }
 
+static void ar9002_hw_extant_switchcom_set(struct ath_hw *ah, u32 switch_com_value)
+{
+	REG_WRITE(ah, AR_PHY_SWITCH_COM, switch_com_value);
+}
+
+static u32 ar9002_hw_extant_switchcom_get(struct ath_hw *ah)
+{
+	return REG_READ(ah, AR_PHY_SWITCH_COM);
+}
+
 void ar9002_hw_attach_phy_ops(struct ath_hw *ah)
 {
 	struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
@@ -573,5 +583,8 @@ void ar9002_hw_attach_phy_ops(struct ath_hw *ah)
 	ops->antdiv_comb_conf_get = ar9002_hw_antdiv_comb_conf_get;
 	ops->antdiv_comb_conf_set = ar9002_hw_antdiv_comb_conf_set;
 
+	ops->extant_switchcom_set = ar9002_hw_extant_switchcom_set;
+	ops->extant_switchcom_get = ar9002_hw_extant_switchcom_get;
+
 	ar9002_hw_set_nf_limits(ah);
 }
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +7 -1
index a93bd63..85196de 100644
@@ -5140,6 +5140,11 @@ unsigned int ar9003_get_paprd_scale_factor(struct ath_hw *ah,
 	}
 }
 
+static u32 ath9k_hw_ar9300_get_switch_com(struct ath_hw *ah)
+{
+	return 0;
+}
+
 const struct eeprom_ops eep_ar9300_ops = {
 	.check_eeprom = ath9k_hw_ar9300_check_eeprom,
 	.get_eeprom = ath9k_hw_ar9300_get_eeprom,
@@ -5150,5 +5155,6 @@ const struct eeprom_ops eep_ar9300_ops = {
 	.set_board_values = ath9k_hw_ar9300_set_board_values,
 	.set_addac = ath9k_hw_ar9300_set_addac,
 	.set_txpower = ath9k_hw_ar9300_set_txpower,
-	.get_spur_channel = ath9k_hw_ar9300_get_spur_channel
+	.get_spur_channel = ath9k_hw_ar9300_get_spur_channel,
+	.get_switch_com = ath9k_hw_ar9300_get_switch_com
 };
drivers/net/wireless/ath/ath9k/eeprom.h +1 -0
index 5ff7ab9..98da6c5 100644
@@ -656,6 +656,7 @@ struct eeprom_ops {
 			   u16 cfgCtl, u8 twiceAntennaReduction,
 			   u8 powerLimit, bool test);
 	u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz);
+	u32 (*get_switch_com)(struct ath_hw *ah);
 };
 
 void ath9k_hw_analog_shift_regwrite(struct ath_hw *ah, u32 reg, u32 val);
drivers/net/wireless/ath/ath9k/eeprom_4k.c +27 -2
index 9a7520f..b295ac0 100644
@@ -815,6 +815,30 @@ static void ath9k_hw_4k_set_gain(struct ath_hw *ah,
 }
 
 /*
+ * Get common antenna configuration bits
+ */
+static u32 ath9k_hw_4k_get_switch_com(struct ath_hw *ah)
+{
+	struct ath_hw_switch_com_profile *easp;
+	struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
+	struct modal_eep_4k_header *pModal = &eep->modalHeader;
+
+	/* return value from eeprom if there are no profiles */
+	if (!ah->switch_com_profiles)
+		return pModal->antCtrlCommon;
+
+	/* find matching value for profile id */
+	for(easp = ah->switch_com_profiles;easp->id >= 0; easp++) {
+		if ( easp->id == ah->selected_extant_profile )
+			return easp->switch_com_value;
+	}
+
+	/* invalid profile selected, return an error */
+	return 1;
+}
+
+
+/*
  * Read EEPROM header info and program the device for correct operation
  * given the channel value.
  */
@@ -833,7 +857,7 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
 	pModal = &eep->modalHeader;
 	txRxAttenLocal = 23;
 
-	REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon);
+	REG_WRITE(ah, AR_PHY_SWITCH_COM, ath9k_hw_4k_get_switch_com(ah));
 
 	/* Single chain for 4K EEPROM*/
 	ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal);
@@ -1112,5 +1136,6 @@ const struct eeprom_ops eep_4k_ops = {
 	.get_eeprom_rev		= ath9k_hw_4k_get_eeprom_rev,
 	.set_board_values	= ath9k_hw_4k_set_board_values,
 	.set_txpower		= ath9k_hw_4k_set_txpower,
-	.get_spur_channel	= ath9k_hw_4k_get_spur_channel
+	.get_spur_channel	= ath9k_hw_4k_get_spur_channel,
+	.get_switch_com		= ath9k_hw_4k_get_switch_com
 };
drivers/net/wireless/ath/ath9k/eeprom_9287.c +7 -1
index 4f5c50a..cf634a7 100644
@@ -1062,6 +1062,11 @@ static u16 ath9k_hw_ar9287_get_spur_channel(struct ath_hw *ah,
 #undef EEP_MAP9287_SPURCHAN
 }
 
+static u32 ath9k_hw_ar9287_get_switch_com(struct ath_hw *ah)
+{
+	return 0;
+}
+
 const struct eeprom_ops eep_ar9287_ops = {
 	.check_eeprom		= ath9k_hw_ar9287_check_eeprom,
 	.get_eeprom		= ath9k_hw_ar9287_get_eeprom,
@@ -1071,5 +1076,6 @@ const struct eeprom_ops eep_ar9287_ops = {
 	.get_eeprom_rev		= ath9k_hw_ar9287_get_eeprom_rev,
 	.set_board_values	= ath9k_hw_ar9287_set_board_values,
 	.set_txpower		= ath9k_hw_ar9287_set_txpower,
-	.get_spur_channel	= ath9k_hw_ar9287_get_spur_channel
+	.get_spur_channel	= ath9k_hw_ar9287_get_spur_channel,
+	.get_switch_com		= ath9k_hw_ar9287_get_switch_com
 };
drivers/net/wireless/ath/ath9k/eeprom_def.c +7 -1
index 81e6296..37f60d3 100644
@@ -1420,6 +1420,11 @@ static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
 #undef EEP_DEF_SPURCHAN
 }
 
+static u32 ath9k_hw_def_get_switch_com(struct ath_hw *ah)
+{
+	return 0;
+}
+
 const struct eeprom_ops eep_def_ops = {
 	.check_eeprom		= ath9k_hw_def_check_eeprom,
 	.get_eeprom		= ath9k_hw_def_get_eeprom,
@@ -1430,5 +1435,6 @@ const struct eeprom_ops eep_def_ops = {
 	.set_board_values	= ath9k_hw_def_set_board_values,
 	.set_addac		= ath9k_hw_def_set_addac,
 	.set_txpower		= ath9k_hw_def_set_txpower,
-	.get_spur_channel	= ath9k_hw_def_get_spur_channel
+	.get_spur_channel	= ath9k_hw_def_get_spur_channel,
+	.get_switch_com		= ath9k_hw_def_get_switch_com
 };
drivers/net/wireless/ath/ath9k/hw.h +28 -0
index 3cb878c..a33e355 100644
@@ -545,6 +545,25 @@ struct ath_hw_radar_conf {
 	bool ext_channel;
 };
 
+
+/**
+ * struct ath_hw_switch_com_profile - external antenna switch settings
+ *
+ * This structure holds a platform_data-supplied alternative value
+ * of AR_PHY_SWITCH_COM.
+ *
+ * @id: unique identifier
+ * @switch_com_value: bit-field to be set in register AR_PHY_SWITCH_COM
+ * @name: profile name
+ * @desc: profile description
+ */
+struct ath_hw_switch_com_profile {
+	int id;
+	u32 switch_com_value;
+	char *name;
+	char *desc;
+};
+
 /**
  * struct ath_hw_private_ops - callbacks used internally by hardware code
  *
@@ -643,6 +662,9 @@ struct ath_hw_ops {
 	void (*antdiv_comb_conf_set)(struct ath_hw *ah,
 			struct ath_hw_antcomb_conf *antconf);
 
+	u32 (*extant_switchcom_get)(struct ath_hw *ah);
+	void (*extant_switchcom_set)(struct ath_hw *ah,
+			u32 switch_com_value);
 };
 
 struct ath_nf_limits {
@@ -882,6 +904,12 @@ struct ath_hw {
 	bool is_clk_25mhz;
 	int (*get_mac_revision)(void);
 	int (*external_reset)(void);
+
+	/*
+	 * External antenna switch configuration profiles
+	 */
+	struct ath_hw_switch_com_profile *switch_com_profiles;
+	u32 selected_extant_profile;
 };
 
 struct ath_bus_ops {
drivers/net/wireless/ath/ath9k/init.c +93 -0

140 lines not on this page · raw message

drivers/net/wireless/ath/ath9k/main.c +36 -0
index e43c41c..8f03642 100644
@@ -2484,6 +2484,40 @@ static int ath9k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
 	return 0;
 }
 
+static int ath9k_set_extant(struct ieee80211_hw *hw, u32 extant)
+{
+	struct ath_softc *sc = hw->priv;
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_common *common = ath9k_hw_common(ah);
+	u32 backup_extant = ah->selected_extant_profile;
+	u32 switch_com_value = 0;
+
+	ath_dbg(common, ATH_DBG_CONFIG, "entering set_extant(%d)\n", extant);
+
+	ah->selected_extant_profile = extant;
+	switch_com_value = ah->eep_ops->get_switch_com(ah);
+	if (switch_com_value & 0xf)
+		goto invalid_profile;
+
+	ath_dbg(common, ATH_DBG_CONFIG, "switch_com: %08x\n", switch_com_value);
+	return 0;
+
+invalid_profile:
+	ath_dbg(common, ATH_DBG_CONFIG, "invalid profile (%08x)\n", switch_com_value);
+	ah->selected_extant_profile = backup_extant;
+	return -EINVAL;
+}
+
+static int ath9k_get_extant(struct ieee80211_hw *hw, u32 *extant)
+{
+	struct ath_softc *sc = hw->priv;
+	struct ath_hw *ah = sc->sc_ah;
+	if (!ah->switch_com_profiles)
+		return -EINVAL;
+	*extant = ah->selected_extant_profile;
+	return 0;
+}
+
 struct ieee80211_ops ath9k_ops = {
 	.tx 		    = ath9k_tx,
 	.start 		    = ath9k_start,
@@ -2512,4 +2546,6 @@ struct ieee80211_ops ath9k_ops = {
 	.get_stats	    = ath9k_get_stats,
 	.set_antenna	    = ath9k_set_antenna,
 	.get_antenna	    = ath9k_get_antenna,
+	.set_extant	    = ath9k_set_extant,
+	.get_extant	    = ath9k_get_extant,
 };
include/linux/ath9k_platform.h +6 -0
index 6e3f54f..1bfe926 100644
@@ -20,6 +20,7 @@
 #define _LINUX_ATH9K_PLATFORM_H
 
 #define ATH9K_PLAT_EEP_MAX_WORDS	2048
+#define ATH9K_PLAT_MAX_SWITCH_COM_PROFILES	4
 
 struct ath9k_platform_data {
 	u16 eeprom_data[ATH9K_PLAT_EEP_MAX_WORDS];
@@ -32,6 +33,11 @@ struct ath9k_platform_data {
 	bool is_clk_25mhz;
 	int (*get_mac_revision)(void);
 	int (*external_reset)(void);
+	struct {
+		u32 val;
+		char *name;
+		char *desc;
+	} switch_com_profiles[ATH9K_PLAT_MAX_SWITCH_COM_PROFILES];
 };
 
 #endif /* _LINUX_ATH9K_PLATFORM_H */
Signature · 1 line
1.7.4.1