ar9300_timer.c revision 256281
10Sstevel@tonic-gate/* 20Sstevel@tonic-gate * Copyright (c) 2013 Qualcomm Atheros, Inc. 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * Permission to use, copy, modify, and/or distribute this software for any 50Sstevel@tonic-gate * purpose with or without fee is hereby granted, provided that the above 60Sstevel@tonic-gate * copyright notice and this permission notice appear in all copies. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 90Sstevel@tonic-gate * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 100Sstevel@tonic-gate * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 110Sstevel@tonic-gate * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 120Sstevel@tonic-gate * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 130Sstevel@tonic-gate * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 140Sstevel@tonic-gate * PERFORMANCE OF THIS SOFTWARE. 150Sstevel@tonic-gate */ 160Sstevel@tonic-gate 170Sstevel@tonic-gate#include "opt_ah.h" 180Sstevel@tonic-gate 190Sstevel@tonic-gate#include "ah.h" 200Sstevel@tonic-gate#include "ah_internal.h" 210Sstevel@tonic-gate 220Sstevel@tonic-gate#include "ar9300/ar9300.h" 230Sstevel@tonic-gate#include "ar9300/ar9300reg.h" 240Sstevel@tonic-gate#include "ar9300/ar9300desc.h" 250Sstevel@tonic-gate 260Sstevel@tonic-gatetypedef struct gen_timer_configuation { 270Sstevel@tonic-gate u_int32_t next_addr; 280Sstevel@tonic-gate u_int32_t period_addr; 290Sstevel@tonic-gate u_int32_t mode_addr; 300Sstevel@tonic-gate u_int32_t mode_mask; 310Sstevel@tonic-gate} GEN_TIMER_CONFIGURATION; 320Sstevel@tonic-gate 330Sstevel@tonic-gate#define AR_GEN_TIMERS2_CFG(num) \ 340Sstevel@tonic-gate AR_GEN_TIMERS2_ ## num ## _NEXT, \ 350Sstevel@tonic-gate AR_GEN_TIMERS2_ ## num ## _PERIOD, \ 360Sstevel@tonic-gate AR_GEN_TIMERS2_MODE, \ 370Sstevel@tonic-gate (1 << num) 380Sstevel@tonic-gatestatic const GEN_TIMER_CONFIGURATION gen_timer_configuration[] = 390Sstevel@tonic-gate{ 400Sstevel@tonic-gate {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, 410Sstevel@tonic-gate {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, 420Sstevel@tonic-gate {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, 430Sstevel@tonic-gate {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, 440Sstevel@tonic-gate {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, 450Sstevel@tonic-gate {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, 460Sstevel@tonic-gate {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, 470Sstevel@tonic-gate {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, 480Sstevel@tonic-gate {AR_GEN_TIMERS2_CFG(0)}, 490Sstevel@tonic-gate {AR_GEN_TIMERS2_CFG(1)}, 500Sstevel@tonic-gate {AR_GEN_TIMERS2_CFG(2)}, 510Sstevel@tonic-gate {AR_GEN_TIMERS2_CFG(3)}, 520Sstevel@tonic-gate {AR_GEN_TIMERS2_CFG(4)}, 530Sstevel@tonic-gate {AR_GEN_TIMERS2_CFG(5)}, 540Sstevel@tonic-gate {AR_GEN_TIMERS2_CFG(6)}, 550Sstevel@tonic-gate {AR_GEN_TIMERS2_CFG(7)} 560Sstevel@tonic-gate}; 570Sstevel@tonic-gate 580Sstevel@tonic-gate#define AR_GENTMR_BIT(_index) (1 << (_index)) 590Sstevel@tonic-gate 600Sstevel@tonic-gateint 610Sstevel@tonic-gatear9300_alloc_generic_timer(struct ath_hal *ah, HAL_GEN_TIMER_DOMAIN tsf) 620Sstevel@tonic-gate{ 630Sstevel@tonic-gate struct ath_hal_9300 *ahp = AH9300(ah); 640Sstevel@tonic-gate u_int32_t i, mask; 650Sstevel@tonic-gate u_int32_t avail_timer_start, avail_timer_end; 660Sstevel@tonic-gate 670Sstevel@tonic-gate if (tsf == HAL_GEN_TIMER_TSF) { 680Sstevel@tonic-gate avail_timer_start = AR_FIRST_NDP_TIMER; 690Sstevel@tonic-gate avail_timer_end = AR_GEN_TIMER_BANK_1_LEN; 700Sstevel@tonic-gate } else { 710Sstevel@tonic-gate avail_timer_start = AR_GEN_TIMER_BANK_1_LEN; 720Sstevel@tonic-gate avail_timer_end = AR_NUM_GEN_TIMERS; 730Sstevel@tonic-gate } 740Sstevel@tonic-gate 750Sstevel@tonic-gate /* Find the first availabe timer index */ 760Sstevel@tonic-gate i = avail_timer_start; 770Sstevel@tonic-gate mask = ahp->ah_avail_gen_timers >> i; 780Sstevel@tonic-gate for ( ; mask && (i < avail_timer_end) ; mask >>= 1, i++ ) { 790Sstevel@tonic-gate if (mask & 0x1) { 800Sstevel@tonic-gate ahp->ah_avail_gen_timers &= ~(AR_GENTMR_BIT(i)); 810Sstevel@tonic-gate 820Sstevel@tonic-gate if ((tsf == HAL_GEN_TIMER_TSF2) && !ahp->ah_enable_tsf2) { 830Sstevel@tonic-gate ahp->ah_enable_tsf2 = AH_TRUE; 840Sstevel@tonic-gate ar9300_start_tsf2(ah); 850Sstevel@tonic-gate } 860Sstevel@tonic-gate return i; 87 } 88 } 89 return -1; 90} 91 92void ar9300_start_tsf2(struct ath_hal *ah) 93{ 94 struct ath_hal_9300 *ahp = AH9300(ah); 95 96 if (ahp->ah_enable_tsf2) { 97 /* Delay might be needed after TSF2 reset */ 98 OS_REG_SET_BIT(ah, AR_DIRECT_CONNECT, AR_DC_AP_STA_EN); 99 OS_REG_SET_BIT(ah, AR_RESET_TSF, AR_RESET_TSF2_ONCE); 100 } 101} 102 103void 104ar9300_free_generic_timer(struct ath_hal *ah, int index) 105{ 106 struct ath_hal_9300 *ahp = AH9300(ah); 107 108 ar9300_stop_generic_timer(ah, index); 109 ahp->ah_avail_gen_timers |= AR_GENTMR_BIT(index); 110} 111 112void 113ar9300_start_generic_timer( 114 struct ath_hal *ah, 115 int index, 116 u_int32_t timer_next, 117 u_int32_t timer_period) 118{ 119 if ((index < AR_FIRST_NDP_TIMER) || (index >= AR_NUM_GEN_TIMERS)) { 120 return; 121 } 122 123 /* 124 * Program generic timer registers 125 */ 126 OS_REG_WRITE(ah, gen_timer_configuration[index].next_addr, timer_next); 127 OS_REG_WRITE(ah, gen_timer_configuration[index].period_addr, timer_period); 128 OS_REG_SET_BIT(ah, 129 gen_timer_configuration[index].mode_addr, 130 gen_timer_configuration[index].mode_mask); 131 132 if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) { 133 /* 134 * Starting from Jupiter, each generic timer can select which tsf to 135 * use. But we still follow the old rule, 0 - 7 use tsf and 8 - 15 136 * use tsf2. 137 */ 138 if ((index < AR_GEN_TIMER_BANK_1_LEN)) { 139 OS_REG_CLR_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL, (1 << index)); 140 } 141 else { 142 OS_REG_SET_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL, (1 << index)); 143 } 144 } 145 146 /* Enable both trigger and thresh interrupt masks */ 147 OS_REG_SET_BIT(ah, AR_IMR_S5, 148 (SM(AR_GENTMR_BIT(index), AR_IMR_S5_GENTIMER_THRESH) | 149 SM(AR_GENTMR_BIT(index), AR_IMR_S5_GENTIMER_TRIG))); 150} 151 152void 153ar9300_stop_generic_timer(struct ath_hal *ah, int index) 154{ 155 if ((index < AR_FIRST_NDP_TIMER) || (index >= AR_NUM_GEN_TIMERS)) { 156 return; 157 } 158 159 /* 160 * Clear generic timer enable bits. 161 */ 162 OS_REG_CLR_BIT(ah, 163 gen_timer_configuration[index].mode_addr, 164 gen_timer_configuration[index].mode_mask); 165 166 /* Disable both trigger and thresh interrupt masks */ 167 OS_REG_CLR_BIT(ah, AR_IMR_S5, 168 (SM(AR_GENTMR_BIT(index), AR_IMR_S5_GENTIMER_THRESH) | 169 SM(AR_GENTMR_BIT(index), AR_IMR_S5_GENTIMER_TRIG))); 170} 171 172void 173ar9300_get_gen_timer_interrupts( 174 struct ath_hal *ah, 175 u_int32_t *trigger, 176 u_int32_t *thresh) 177{ 178 struct ath_hal_9300 *ahp = AH9300(ah); 179 *trigger = ahp->ah_intr_gen_timer_trigger; 180 *thresh = ahp->ah_intr_gen_timer_thresh; 181} 182