ar9300_timer.c revision 250003
1/* 2 * Copyright (c) 2013 Qualcomm Atheros, Inc. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 13 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14 * PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17#include "opt_ah.h" 18 19#ifdef AH_SUPPORT_AR9300 20 21#include "ah.h" 22#include "ah_internal.h" 23 24#include "ar9300/ar9300.h" 25#include "ar9300/ar9300reg.h" 26#include "ar9300/ar9300desc.h" 27 28typedef struct gen_timer_configuation { 29 u_int32_t next_addr; 30 u_int32_t period_addr; 31 u_int32_t mode_addr; 32 u_int32_t mode_mask; 33} GEN_TIMER_CONFIGURATION; 34 35#define AR_GEN_TIMERS2_CFG(num) \ 36 AR_GEN_TIMERS2_ ## num ## _NEXT, \ 37 AR_GEN_TIMERS2_ ## num ## _PERIOD, \ 38 AR_GEN_TIMERS2_MODE, \ 39 (1 << num) 40static const GEN_TIMER_CONFIGURATION gen_timer_configuration[] = 41{ 42 {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, 43 {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, 44 {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, 45 {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, 46 {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, 47 {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, 48 {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, 49 {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, 50 {AR_GEN_TIMERS2_CFG(0)}, 51 {AR_GEN_TIMERS2_CFG(1)}, 52 {AR_GEN_TIMERS2_CFG(2)}, 53 {AR_GEN_TIMERS2_CFG(3)}, 54 {AR_GEN_TIMERS2_CFG(4)}, 55 {AR_GEN_TIMERS2_CFG(5)}, 56 {AR_GEN_TIMERS2_CFG(6)}, 57 {AR_GEN_TIMERS2_CFG(7)} 58}; 59 60#define AR_GENTMR_BIT(_index) (1 << (_index)) 61 62int 63ar9300_alloc_generic_timer(struct ath_hal *ah, HAL_GEN_TIMER_DOMAIN tsf) 64{ 65 struct ath_hal_9300 *ahp = AH9300(ah); 66 u_int32_t i, mask; 67 u_int32_t avail_timer_start, avail_timer_end; 68 69 if (tsf == HAL_GEN_TIMER_TSF) { 70 avail_timer_start = AR_FIRST_NDP_TIMER; 71 avail_timer_end = AR_GEN_TIMER_BANK_1_LEN; 72 } else { 73 avail_timer_start = AR_GEN_TIMER_BANK_1_LEN; 74 avail_timer_end = AR_NUM_GEN_TIMERS; 75 } 76 77 /* Find the first availabe timer index */ 78 i = avail_timer_start; 79 mask = ahp->ah_avail_gen_timers >> i; 80 for ( ; mask && (i < avail_timer_end) ; mask >>= 1, i++ ) { 81 if (mask & 0x1) { 82 ahp->ah_avail_gen_timers &= ~(AR_GENTMR_BIT(i)); 83 84 if ((tsf == HAL_GEN_TIMER_TSF2) && !ahp->ah_enable_tsf2) { 85 ahp->ah_enable_tsf2 = AH_TRUE; 86 ar9300_start_tsf2(ah); 87 } 88 return i; 89 } 90 } 91 return -1; 92} 93 94void ar9300_start_tsf2(struct ath_hal *ah) 95{ 96 struct ath_hal_9300 *ahp = AH9300(ah); 97 98 if (ahp->ah_enable_tsf2) { 99 /* Delay might be needed after TSF2 reset */ 100 OS_REG_SET_BIT(ah, AR_DIRECT_CONNECT, AR_DC_AP_STA_EN); 101 OS_REG_SET_BIT(ah, AR_RESET_TSF, AR_RESET_TSF2_ONCE); 102 } 103} 104 105void 106ar9300_free_generic_timer(struct ath_hal *ah, int index) 107{ 108 struct ath_hal_9300 *ahp = AH9300(ah); 109 110 ar9300_stop_generic_timer(ah, index); 111 ahp->ah_avail_gen_timers |= AR_GENTMR_BIT(index); 112} 113 114void 115ar9300_start_generic_timer( 116 struct ath_hal *ah, 117 int index, 118 u_int32_t timer_next, 119 u_int32_t timer_period) 120{ 121 if ((index < AR_FIRST_NDP_TIMER) || (index >= AR_NUM_GEN_TIMERS)) { 122 return; 123 } 124 125 /* 126 * Program generic timer registers 127 */ 128 OS_REG_WRITE(ah, gen_timer_configuration[index].next_addr, timer_next); 129 OS_REG_WRITE(ah, gen_timer_configuration[index].period_addr, timer_period); 130 OS_REG_SET_BIT(ah, 131 gen_timer_configuration[index].mode_addr, 132 gen_timer_configuration[index].mode_mask); 133 134 if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) { 135 /* 136 * Starting from Jupiter, each generic timer can select which tsf to 137 * use. But we still follow the old rule, 0 - 7 use tsf and 8 - 15 138 * use tsf2. 139 */ 140 if ((index < AR_GEN_TIMER_BANK_1_LEN)) { 141 OS_REG_CLR_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL, (1 << index)); 142 } 143 else { 144 OS_REG_SET_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL, (1 << index)); 145 } 146 } 147 148 /* Enable both trigger and thresh interrupt masks */ 149 OS_REG_SET_BIT(ah, AR_IMR_S5, 150 (SM(AR_GENTMR_BIT(index), AR_IMR_S5_GENTIMER_THRESH) | 151 SM(AR_GENTMR_BIT(index), AR_IMR_S5_GENTIMER_TRIG))); 152} 153 154void 155ar9300_stop_generic_timer(struct ath_hal *ah, int index) 156{ 157 if ((index < AR_FIRST_NDP_TIMER) || (index >= AR_NUM_GEN_TIMERS)) { 158 return; 159 } 160 161 /* 162 * Clear generic timer enable bits. 163 */ 164 OS_REG_CLR_BIT(ah, 165 gen_timer_configuration[index].mode_addr, 166 gen_timer_configuration[index].mode_mask); 167 168 /* Disable both trigger and thresh interrupt masks */ 169 OS_REG_CLR_BIT(ah, AR_IMR_S5, 170 (SM(AR_GENTMR_BIT(index), AR_IMR_S5_GENTIMER_THRESH) | 171 SM(AR_GENTMR_BIT(index), AR_IMR_S5_GENTIMER_TRIG))); 172} 173 174void 175ar9300_get_gen_timer_interrupts( 176 struct ath_hal *ah, 177 u_int32_t *trigger, 178 u_int32_t *thresh) 179{ 180 struct ath_hal_9300 *ahp = AH9300(ah); 181 *trigger = ahp->ah_intr_gen_timer_trigger; 182 *thresh = ahp->ah_intr_gen_timer_thresh; 183} 184 185#endif /* AH_SUPPORT_AR9300 */ 186