Path: blob/main/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_timer.c
48526 views
/*1* Copyright (c) 2013 Qualcomm Atheros, Inc.2*3* Permission to use, copy, modify, and/or distribute this software for any4* purpose with or without fee is hereby granted, provided that the above5* copyright notice and this permission notice appear in all copies.6*7* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH8* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY9* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,10* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM11* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR12* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR13* PERFORMANCE OF THIS SOFTWARE.14*/1516#include "opt_ah.h"1718#include "ah.h"19#include "ah_internal.h"2021#include "ar9300/ar9300.h"22#include "ar9300/ar9300reg.h"23#include "ar9300/ar9300desc.h"2425typedef struct gen_timer_configuation {26u_int32_t next_addr;27u_int32_t period_addr;28u_int32_t mode_addr;29u_int32_t mode_mask;30} GEN_TIMER_CONFIGURATION;3132#define AR_GEN_TIMERS2_CFG(num) \33AR_GEN_TIMERS2_ ## num ## _NEXT, \34AR_GEN_TIMERS2_ ## num ## _PERIOD, \35AR_GEN_TIMERS2_MODE, \36(1 << num)37static const GEN_TIMER_CONFIGURATION gen_timer_configuration[] =38{39{AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},40{AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},41{AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080},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_GEN_TIMERS2_CFG(0)},48{AR_GEN_TIMERS2_CFG(1)},49{AR_GEN_TIMERS2_CFG(2)},50{AR_GEN_TIMERS2_CFG(3)},51{AR_GEN_TIMERS2_CFG(4)},52{AR_GEN_TIMERS2_CFG(5)},53{AR_GEN_TIMERS2_CFG(6)},54{AR_GEN_TIMERS2_CFG(7)}55};5657#define AR_GENTMR_BIT(_index) (1 << (_index))5859int60ar9300_alloc_generic_timer(struct ath_hal *ah, HAL_GEN_TIMER_DOMAIN tsf)61{62struct ath_hal_9300 *ahp = AH9300(ah);63u_int32_t i, mask;64u_int32_t avail_timer_start, avail_timer_end;6566if (tsf == HAL_GEN_TIMER_TSF) {67avail_timer_start = AR_FIRST_NDP_TIMER;68avail_timer_end = AR_GEN_TIMER_BANK_1_LEN;69} else {70avail_timer_start = AR_GEN_TIMER_BANK_1_LEN;71avail_timer_end = AR_NUM_GEN_TIMERS;72}7374/* Find the first availabe timer index */75i = avail_timer_start;76mask = ahp->ah_avail_gen_timers >> i;77for ( ; mask && (i < avail_timer_end) ; mask >>= 1, i++ ) {78if (mask & 0x1) {79ahp->ah_avail_gen_timers &= ~(AR_GENTMR_BIT(i));8081if ((tsf == HAL_GEN_TIMER_TSF2) && !ahp->ah_enable_tsf2) {82ahp->ah_enable_tsf2 = AH_TRUE;83ar9300_start_tsf2(ah);84}85return i;86}87}88return -1;89}9091void ar9300_start_tsf2(struct ath_hal *ah)92{93struct ath_hal_9300 *ahp = AH9300(ah);9495if (ahp->ah_enable_tsf2) {96/* Delay might be needed after TSF2 reset */97OS_REG_SET_BIT(ah, AR_DIRECT_CONNECT, AR_DC_AP_STA_EN);98OS_REG_SET_BIT(ah, AR_RESET_TSF, AR_RESET_TSF2_ONCE);99}100}101102void103ar9300_free_generic_timer(struct ath_hal *ah, int index)104{105struct ath_hal_9300 *ahp = AH9300(ah);106107ar9300_stop_generic_timer(ah, index);108ahp->ah_avail_gen_timers |= AR_GENTMR_BIT(index);109}110111void112ar9300_start_generic_timer(113struct ath_hal *ah,114int index,115u_int32_t timer_next,116u_int32_t timer_period)117{118if ((index < AR_FIRST_NDP_TIMER) || (index >= AR_NUM_GEN_TIMERS)) {119return;120}121122/*123* Program generic timer registers124*/125OS_REG_WRITE(ah, gen_timer_configuration[index].next_addr, timer_next);126OS_REG_WRITE(ah, gen_timer_configuration[index].period_addr, timer_period);127OS_REG_SET_BIT(ah,128gen_timer_configuration[index].mode_addr,129gen_timer_configuration[index].mode_mask);130131if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {132/*133* Starting from Jupiter, each generic timer can select which tsf to134* use. But we still follow the old rule, 0 - 7 use tsf and 8 - 15135* use tsf2.136*/137if ((index < AR_GEN_TIMER_BANK_1_LEN)) {138OS_REG_CLR_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL, (1 << index));139}140else {141OS_REG_SET_BIT(ah, AR_MAC_PCU_GEN_TIMER_TSF_SEL, (1 << index));142}143}144145/* Enable both trigger and thresh interrupt masks */146OS_REG_SET_BIT(ah, AR_IMR_S5,147(SM(AR_GENTMR_BIT(index), AR_IMR_S5_GENTIMER_THRESH) |148SM(AR_GENTMR_BIT(index), AR_IMR_S5_GENTIMER_TRIG)));149}150151void152ar9300_stop_generic_timer(struct ath_hal *ah, int index)153{154if ((index < AR_FIRST_NDP_TIMER) || (index >= AR_NUM_GEN_TIMERS)) {155return;156}157158/*159* Clear generic timer enable bits.160*/161OS_REG_CLR_BIT(ah,162gen_timer_configuration[index].mode_addr,163gen_timer_configuration[index].mode_mask);164165/* Disable both trigger and thresh interrupt masks */166OS_REG_CLR_BIT(ah, AR_IMR_S5,167(SM(AR_GENTMR_BIT(index), AR_IMR_S5_GENTIMER_THRESH) |168SM(AR_GENTMR_BIT(index), AR_IMR_S5_GENTIMER_TRIG)));169}170171void172ar9300_get_gen_timer_interrupts(173struct ath_hal *ah,174u_int32_t *trigger,175u_int32_t *thresh)176{177struct ath_hal_9300 *ahp = AH9300(ah);178*trigger = ahp->ah_intr_gen_timer_trigger;179*thresh = ahp->ah_intr_gen_timer_thresh;180}181182183