aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuis R. Rodriguez <lrodriguez@atheros.com>2010-05-13 13:33:43 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-06-02 16:13:00 -0400
commitaea702b70ae0964c16e17944e4a5ce2c2b038ced (patch)
tree8d4bcd9197d442e293a0479fbab3297df95da859
parentec8aa669b8393b6789b1954d587c63264af7ff99 (diff)
ath9k_hw: add support for the AR9003 baseband watchdog
The baseband watchdog will monitor blocks of the baseband through timers and will issue an interrupt when things are detected to be stalled. It is only available on the AR9003 family. Cc: Sam Ng <sam.ng@atheros.com> Cc: Paul Shaw <paul.shaw@atheros.com> Cc: Don Breslin <don.breslin@atheros.com> Cc: Cliff Holden <cliff.holden@atheros.com Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_mac.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_mac.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.c119
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.h66
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h9
-rw-r--r--drivers/net/wireless/ath/ath9k/reg.h1
7 files changed, 169 insertions, 34 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
index 37ba37481a47..40731077cbb4 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
@@ -90,6 +90,8 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
90 MAP_ISR_S2_CST); 90 MAP_ISR_S2_CST);
91 mask2 |= ((isr2 & AR_ISR_S2_TSFOOR) >> 91 mask2 |= ((isr2 & AR_ISR_S2_TSFOOR) >>
92 MAP_ISR_S2_TSFOOR); 92 MAP_ISR_S2_TSFOOR);
93 mask2 |= ((isr2 & AR_ISR_S2_BB_WATCHDOG) >>
94 MAP_ISR_S2_BB_WATCHDOG);
93 95
94 if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { 96 if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
95 REG_WRITE(ah, AR_ISR_S2, isr2); 97 REG_WRITE(ah, AR_ISR_S2, isr2);
@@ -167,6 +169,9 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
167 169
168 (void) REG_READ(ah, AR_ISR); 170 (void) REG_READ(ah, AR_ISR);
169 } 171 }
172
173 if (*masked & ATH9K_INT_BB_WATCHDOG)
174 ar9003_hw_bb_watchdog_read(ah);
170 } 175 }
171 176
172 if (sync_cause) { 177 if (sync_cause) {
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.h b/drivers/net/wireless/ath/ath9k/ar9003_mac.h
index f17558b14539..5a7a286e2773 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.h
@@ -47,6 +47,7 @@
47#define MAP_ISR_S2_DTIMSYNC 7 47#define MAP_ISR_S2_DTIMSYNC 7
48#define MAP_ISR_S2_DTIM 7 48#define MAP_ISR_S2_DTIM 7
49#define MAP_ISR_S2_TSFOOR 4 49#define MAP_ISR_S2_TSFOOR 4
50#define MAP_ISR_S2_BB_WATCHDOG 6
50 51
51#define AR9003TXC_CONST(_ds) ((const struct ar9003_txc *) _ds) 52#define AR9003TXC_CONST(_ds) ((const struct ar9003_txc *) _ds)
52 53
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index 80431a2f6dc1..c714579b5483 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -1132,3 +1132,122 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
1132 priv_ops->do_getnf = ar9003_hw_do_getnf; 1132 priv_ops->do_getnf = ar9003_hw_do_getnf;
1133 priv_ops->loadnf = ar9003_hw_loadnf; 1133 priv_ops->loadnf = ar9003_hw_loadnf;
1134} 1134}
1135
1136void ar9003_hw_bb_watchdog_config(struct ath_hw *ah)
1137{
1138 struct ath_common *common = ath9k_hw_common(ah);
1139 u32 idle_tmo_ms = ah->bb_watchdog_timeout_ms;
1140 u32 val, idle_count;
1141
1142 if (!idle_tmo_ms) {
1143 /* disable IRQ, disable chip-reset for BB panic */
1144 REG_WRITE(ah, AR_PHY_WATCHDOG_CTL_2,
1145 REG_READ(ah, AR_PHY_WATCHDOG_CTL_2) &
1146 ~(AR_PHY_WATCHDOG_RST_ENABLE |
1147 AR_PHY_WATCHDOG_IRQ_ENABLE));
1148
1149 /* disable watchdog in non-IDLE mode, disable in IDLE mode */
1150 REG_WRITE(ah, AR_PHY_WATCHDOG_CTL_1,
1151 REG_READ(ah, AR_PHY_WATCHDOG_CTL_1) &
1152 ~(AR_PHY_WATCHDOG_NON_IDLE_ENABLE |
1153 AR_PHY_WATCHDOG_IDLE_ENABLE));
1154
1155 ath_print(common, ATH_DBG_RESET, "Disabled BB Watchdog\n");
1156 return;
1157 }
1158
1159 /* enable IRQ, disable chip-reset for BB watchdog */
1160 val = REG_READ(ah, AR_PHY_WATCHDOG_CTL_2) & AR_PHY_WATCHDOG_CNTL2_MASK;
1161 REG_WRITE(ah, AR_PHY_WATCHDOG_CTL_2,
1162 (val | AR_PHY_WATCHDOG_IRQ_ENABLE) &
1163 ~AR_PHY_WATCHDOG_RST_ENABLE);
1164
1165 /* bound limit to 10 secs */
1166 if (idle_tmo_ms > 10000)
1167 idle_tmo_ms = 10000;
1168
1169 /*
1170 * The time unit for watchdog event is 2^15 44/88MHz cycles.
1171 *
1172 * For HT20 we have a time unit of 2^15/44 MHz = .74 ms per tick
1173 * For HT40 we have a time unit of 2^15/88 MHz = .37 ms per tick
1174 *
1175 * Given we use fast clock now in 5 GHz, these time units should
1176 * be common for both 2 GHz and 5 GHz.
1177 */
1178 idle_count = (100 * idle_tmo_ms) / 74;
1179 if (ah->curchan && IS_CHAN_HT40(ah->curchan))
1180 idle_count = (100 * idle_tmo_ms) / 37;
1181
1182 /*
1183 * enable watchdog in non-IDLE mode, disable in IDLE mode,
1184 * set idle time-out.
1185 */
1186 REG_WRITE(ah, AR_PHY_WATCHDOG_CTL_1,
1187 AR_PHY_WATCHDOG_NON_IDLE_ENABLE |
1188 AR_PHY_WATCHDOG_IDLE_MASK |
1189 (AR_PHY_WATCHDOG_NON_IDLE_MASK & (idle_count << 2)));
1190
1191 ath_print(common, ATH_DBG_RESET,
1192 "Enabled BB Watchdog timeout (%u ms)\n",
1193 idle_tmo_ms);
1194}
1195
1196void ar9003_hw_bb_watchdog_read(struct ath_hw *ah)
1197{
1198 /*
1199 * we want to avoid printing in ISR context so we save the
1200 * watchdog status to be printed later in bottom half context.
1201 */
1202 ah->bb_watchdog_last_status = REG_READ(ah, AR_PHY_WATCHDOG_STATUS);
1203
1204 /*
1205 * the watchdog timer should reset on status read but to be sure
1206 * sure we write 0 to the watchdog status bit.
1207 */
1208 REG_WRITE(ah, AR_PHY_WATCHDOG_STATUS,
1209 ah->bb_watchdog_last_status & ~AR_PHY_WATCHDOG_STATUS_CLR);
1210}
1211
1212void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah)
1213{
1214 struct ath_common *common = ath9k_hw_common(ah);
1215 u32 rxc_pcnt = 0, rxf_pcnt = 0, txf_pcnt = 0, status;
1216
1217 if (likely(!(common->debug_mask & ATH_DBG_RESET)))
1218 return;
1219
1220 status = ah->bb_watchdog_last_status;
1221 ath_print(common, ATH_DBG_RESET,
1222 "\n==== BB update: BB status=0x%08x ====\n", status);
1223 ath_print(common, ATH_DBG_RESET,
1224 "** BB state: wd=%u det=%u rdar=%u rOFDM=%d "
1225 "rCCK=%u tOFDM=%u tCCK=%u agc=%u src=%u **\n",
1226 MS(status, AR_PHY_WATCHDOG_INFO),
1227 MS(status, AR_PHY_WATCHDOG_DET_HANG),
1228 MS(status, AR_PHY_WATCHDOG_RADAR_SM),
1229 MS(status, AR_PHY_WATCHDOG_RX_OFDM_SM),
1230 MS(status, AR_PHY_WATCHDOG_RX_CCK_SM),
1231 MS(status, AR_PHY_WATCHDOG_TX_OFDM_SM),
1232 MS(status, AR_PHY_WATCHDOG_TX_CCK_SM),
1233 MS(status, AR_PHY_WATCHDOG_AGC_SM),
1234 MS(status,AR_PHY_WATCHDOG_SRCH_SM));
1235
1236 ath_print(common, ATH_DBG_RESET,
1237 "** BB WD cntl: cntl1=0x%08x cntl2=0x%08x **\n",
1238 REG_READ(ah, AR_PHY_WATCHDOG_CTL_1),
1239 REG_READ(ah, AR_PHY_WATCHDOG_CTL_2));
1240 ath_print(common, ATH_DBG_RESET,
1241 "** BB mode: BB_gen_controls=0x%08x **\n",
1242 REG_READ(ah, AR_PHY_GEN_CTRL));
1243
1244 if (ath9k_hw_GetMibCycleCountsPct(ah, &rxc_pcnt, &rxf_pcnt, &txf_pcnt))
1245 ath_print(common, ATH_DBG_RESET,
1246 "** BB busy times: rx_clear=%d%%, "
1247 "rx_frame=%d%%, tx_frame=%d%% **\n",
1248 rxc_pcnt, rxf_pcnt, txf_pcnt);
1249
1250 ath_print(common, ATH_DBG_RESET,
1251 "==== BB update: done ====\n\n");
1252}
1253EXPORT_SYMBOL(ar9003_hw_bb_watchdog_dbg_info);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
index f08cc8bda005..676d3f1123f4 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
@@ -483,10 +483,10 @@
483#define AR_PHY_TX_IQCAL_STATUS_B0 (AR_SM_BASE + 0x48c) 483#define AR_PHY_TX_IQCAL_STATUS_B0 (AR_SM_BASE + 0x48c)
484#define AR_PHY_TX_IQCAL_CORR_COEFF_01_B0 (AR_SM_BASE + 0x450) 484#define AR_PHY_TX_IQCAL_CORR_COEFF_01_B0 (AR_SM_BASE + 0x450)
485 485
486#define AR_PHY_PANIC_WD_STATUS (AR_SM_BASE + 0x5c0) 486#define AR_PHY_WATCHDOG_STATUS (AR_SM_BASE + 0x5c0)
487#define AR_PHY_PANIC_WD_CTL_1 (AR_SM_BASE + 0x5c4) 487#define AR_PHY_WATCHDOG_CTL_1 (AR_SM_BASE + 0x5c4)
488#define AR_PHY_PANIC_WD_CTL_2 (AR_SM_BASE + 0x5c8) 488#define AR_PHY_WATCHDOG_CTL_2 (AR_SM_BASE + 0x5c8)
489#define AR_PHY_BT_CTL (AR_SM_BASE + 0x5cc) 489#define AR_PHY_WATCHDOG_CTL (AR_SM_BASE + 0x5cc)
490#define AR_PHY_ONLY_WARMRESET (AR_SM_BASE + 0x5d0) 490#define AR_PHY_ONLY_WARMRESET (AR_SM_BASE + 0x5d0)
491#define AR_PHY_ONLY_CTL (AR_SM_BASE + 0x5d4) 491#define AR_PHY_ONLY_CTL (AR_SM_BASE + 0x5d4)
492#define AR_PHY_ECO_CTRL (AR_SM_BASE + 0x5dc) 492#define AR_PHY_ECO_CTRL (AR_SM_BASE + 0x5dc)
@@ -812,35 +812,35 @@
812#define AR_PHY_CAL_MEAS_2_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_2_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i))) 812#define AR_PHY_CAL_MEAS_2_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_2_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i)))
813#define AR_PHY_CAL_MEAS_3_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_3_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i))) 813#define AR_PHY_CAL_MEAS_3_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_3_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i)))
814 814
815#define AR_PHY_BB_PANIC_NON_IDLE_ENABLE 0x00000001 815#define AR_PHY_WATCHDOG_NON_IDLE_ENABLE 0x00000001
816#define AR_PHY_BB_PANIC_IDLE_ENABLE 0x00000002 816#define AR_PHY_WATCHDOG_IDLE_ENABLE 0x00000002
817#define AR_PHY_BB_PANIC_IDLE_MASK 0xFFFF0000 817#define AR_PHY_WATCHDOG_IDLE_MASK 0xFFFF0000
818#define AR_PHY_BB_PANIC_NON_IDLE_MASK 0x0000FFFC 818#define AR_PHY_WATCHDOG_NON_IDLE_MASK 0x0000FFFC
819 819
820#define AR_PHY_BB_PANIC_RST_ENABLE 0x00000002 820#define AR_PHY_WATCHDOG_RST_ENABLE 0x00000002
821#define AR_PHY_BB_PANIC_IRQ_ENABLE 0x00000004 821#define AR_PHY_WATCHDOG_IRQ_ENABLE 0x00000004
822#define AR_PHY_BB_PANIC_CNTL2_MASK 0xFFFFFFF9 822#define AR_PHY_WATCHDOG_CNTL2_MASK 0xFFFFFFF9
823 823
824#define AR_PHY_BB_WD_STATUS 0x00000007 824#define AR_PHY_WATCHDOG_INFO 0x00000007
825#define AR_PHY_BB_WD_STATUS_S 0 825#define AR_PHY_WATCHDOG_INFO_S 0
826#define AR_PHY_BB_WD_DET_HANG 0x00000008 826#define AR_PHY_WATCHDOG_DET_HANG 0x00000008
827#define AR_PHY_BB_WD_DET_HANG_S 3 827#define AR_PHY_WATCHDOG_DET_HANG_S 3
828#define AR_PHY_BB_WD_RADAR_SM 0x000000F0 828#define AR_PHY_WATCHDOG_RADAR_SM 0x000000F0
829#define AR_PHY_BB_WD_RADAR_SM_S 4 829#define AR_PHY_WATCHDOG_RADAR_SM_S 4
830#define AR_PHY_BB_WD_RX_OFDM_SM 0x00000F00 830#define AR_PHY_WATCHDOG_RX_OFDM_SM 0x00000F00
831#define AR_PHY_BB_WD_RX_OFDM_SM_S 8 831#define AR_PHY_WATCHDOG_RX_OFDM_SM_S 8
832#define AR_PHY_BB_WD_RX_CCK_SM 0x0000F000 832#define AR_PHY_WATCHDOG_RX_CCK_SM 0x0000F000
833#define AR_PHY_BB_WD_RX_CCK_SM_S 12 833#define AR_PHY_WATCHDOG_RX_CCK_SM_S 12
834#define AR_PHY_BB_WD_TX_OFDM_SM 0x000F0000 834#define AR_PHY_WATCHDOG_TX_OFDM_SM 0x000F0000
835#define AR_PHY_BB_WD_TX_OFDM_SM_S 16 835#define AR_PHY_WATCHDOG_TX_OFDM_SM_S 16
836#define AR_PHY_BB_WD_TX_CCK_SM 0x00F00000 836#define AR_PHY_WATCHDOG_TX_CCK_SM 0x00F00000
837#define AR_PHY_BB_WD_TX_CCK_SM_S 20 837#define AR_PHY_WATCHDOG_TX_CCK_SM_S 20
838#define AR_PHY_BB_WD_AGC_SM 0x0F000000 838#define AR_PHY_WATCHDOG_AGC_SM 0x0F000000
839#define AR_PHY_BB_WD_AGC_SM_S 24 839#define AR_PHY_WATCHDOG_AGC_SM_S 24
840#define AR_PHY_BB_WD_SRCH_SM 0xF0000000 840#define AR_PHY_WATCHDOG_SRCH_SM 0xF0000000
841#define AR_PHY_BB_WD_SRCH_SM_S 28 841#define AR_PHY_WATCHDOG_SRCH_SM_S 28
842 842
843#define AR_PHY_BB_WD_STATUS_CLR 0x00000008 843#define AR_PHY_WATCHDOG_STATUS_CLR 0x00000008
844 844
845void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx); 845void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx);
846 846
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index c33f17dbe6f1..6bfac1ca07fa 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -627,6 +627,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
627 ar9003_hw_set_nf_limits(ah); 627 ar9003_hw_set_nf_limits(ah);
628 628
629 ath9k_init_nfcal_hist_buffer(ah); 629 ath9k_init_nfcal_hist_buffer(ah);
630 ah->bb_watchdog_timeout_ms = 25;
630 631
631 common->state = ATH_HW_INITIALIZED; 632 common->state = ATH_HW_INITIALIZED;
632 633
@@ -1441,6 +1442,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
1441 if (AR_SREV_9300_20_OR_LATER(ah)) { 1442 if (AR_SREV_9300_20_OR_LATER(ah)) {
1442 ath9k_hw_loadnf(ah, curchan); 1443 ath9k_hw_loadnf(ah, curchan);
1443 ath9k_hw_start_nfcal(ah); 1444 ath9k_hw_start_nfcal(ah);
1445 ar9003_hw_bb_watchdog_config(ah);
1444 } 1446 }
1445 1447
1446 return 0; 1448 return 0;
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 77245dff5993..bfecde083a42 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -279,6 +279,7 @@ enum ath9k_int {
279 ATH9K_INT_TX = 0x00000040, 279 ATH9K_INT_TX = 0x00000040,
280 ATH9K_INT_TXDESC = 0x00000080, 280 ATH9K_INT_TXDESC = 0x00000080,
281 ATH9K_INT_TIM_TIMER = 0x00000100, 281 ATH9K_INT_TIM_TIMER = 0x00000100,
282 ATH9K_INT_BB_WATCHDOG = 0x00000400,
282 ATH9K_INT_TXURN = 0x00000800, 283 ATH9K_INT_TXURN = 0x00000800,
283 ATH9K_INT_MIB = 0x00001000, 284 ATH9K_INT_MIB = 0x00001000,
284 ATH9K_INT_RXPHY = 0x00004000, 285 ATH9K_INT_RXPHY = 0x00004000,
@@ -789,6 +790,9 @@ struct ath_hw {
789 u32 ts_paddr_end; 790 u32 ts_paddr_end;
790 u16 ts_tail; 791 u16 ts_tail;
791 u8 ts_size; 792 u8 ts_size;
793
794 u32 bb_watchdog_last_status;
795 u32 bb_watchdog_timeout_ms; /* in ms, 0 to disable */
792}; 796};
793 797
794static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah) 798static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah)
@@ -910,10 +914,13 @@ void ar9002_hw_enable_async_fifo(struct ath_hw *ah);
910void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah); 914void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah);
911 915
912/* 916/*
913 * Code specifric to AR9003, we stuff these here to avoid callbacks 917 * Code specific to AR9003, we stuff these here to avoid callbacks
914 * for older families 918 * for older families
915 */ 919 */
916void ar9003_hw_set_nf_limits(struct ath_hw *ah); 920void ar9003_hw_set_nf_limits(struct ath_hw *ah);
921void ar9003_hw_bb_watchdog_config(struct ath_hw *ah);
922void ar9003_hw_bb_watchdog_read(struct ath_hw *ah);
923void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah);
917 924
918/* Hardware family op attach helpers */ 925/* Hardware family op attach helpers */
919void ar5008_hw_attach_phy_ops(struct ath_hw *ah); 926void ar5008_hw_attach_phy_ops(struct ath_hw *ah);
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index d4371a43bdaa..c9a009fab221 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -222,6 +222,7 @@
222 222
223#define AR_ISR_S2 0x008c 223#define AR_ISR_S2 0x008c
224#define AR_ISR_S2_QCU_TXURN 0x000003FF 224#define AR_ISR_S2_QCU_TXURN 0x000003FF
225#define AR_ISR_S2_BB_WATCHDOG 0x00010000
225#define AR_ISR_S2_CST 0x00400000 226#define AR_ISR_S2_CST 0x00400000
226#define AR_ISR_S2_GTT 0x00800000 227#define AR_ISR_S2_GTT 0x00800000
227#define AR_ISR_S2_TIM 0x01000000 228#define AR_ISR_S2_TIM 0x01000000