Files
android_kernel_samsung_sm86…/hal/wifi3.0/hal_generic_api.h
Pavankumar Nandeshwar a2ddd8956b qcacmn: Retain ds ring indices across wifi restart
Retain ds ring indices across wifi restart to avoid
edma hang. Fetch the indices from ds module and set
the corresponding ds ring indices.

Change-Id: Ia299a7006166aef096c7d2c1f65f6bef65415a37
CRs-Fixed: 3332152
2022-11-25 00:08:26 -08:00

683 lines
20 KiB
C

/*
* Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _HAL_GENERIC_API_H_
#define _HAL_GENERIC_API_H_
#include <hal_rx.h>
#define SRNG_ENABLE_BIT 0x40
#define SRNG_IDLE_STATE_BIT 0x80
/**
* hal_get_radiotap_he_gi_ltf() - Convert HE ltf and GI value
* from stats enum to radiotap enum
* @he_gi: HE GI value used in stats
* @he_ltf: HE LTF value used in stats
*
* Return: void
*/
static inline void hal_get_radiotap_he_gi_ltf(uint16_t *he_gi, uint16_t *he_ltf)
{
switch (*he_gi) {
case HE_GI_0_8:
*he_gi = HE_GI_RADIOTAP_0_8;
break;
case HE_GI_1_6:
*he_gi = HE_GI_RADIOTAP_1_6;
break;
case HE_GI_3_2:
*he_gi = HE_GI_RADIOTAP_3_2;
break;
default:
*he_gi = HE_GI_RADIOTAP_RESERVED;
}
switch (*he_ltf) {
case HE_LTF_1_X:
*he_ltf = HE_LTF_RADIOTAP_1_X;
break;
case HE_LTF_2_X:
*he_ltf = HE_LTF_RADIOTAP_2_X;
break;
case HE_LTF_4_X:
*he_ltf = HE_LTF_RADIOTAP_4_X;
break;
default:
*he_ltf = HE_LTF_RADIOTAP_UNKNOWN;
}
}
/* channel number to freq conversion */
#define CHANNEL_NUM_14 14
#define CHANNEL_NUM_15 15
#define CHANNEL_NUM_27 27
#define CHANNEL_NUM_35 35
#define CHANNEL_NUM_182 182
#define CHANNEL_NUM_197 197
#define CHANNEL_FREQ_2484 2484
#define CHANNEL_FREQ_2407 2407
#define CHANNEL_FREQ_2512 2512
#define CHANNEL_FREQ_5000 5000
#define CHANNEL_FREQ_5950 5950
#define CHANNEL_FREQ_4000 4000
#define CHANNEL_FREQ_5150 5150
#define CHANNEL_FREQ_5920 5920
#define CHANNEL_FREQ_5935 5935
#define FREQ_MULTIPLIER_CONST_5MHZ 5
#define FREQ_MULTIPLIER_CONST_20MHZ 20
/**
* hal_rx_radiotap_num_to_freq() - Get frequency from chan number
* @chan_num - Input channel number
* @center_freq - Input Channel Center frequency
*
* Return - Channel frequency in Mhz
*/
static inline uint16_t
hal_rx_radiotap_num_to_freq(uint16_t chan_num, qdf_freq_t center_freq)
{
if (center_freq > CHANNEL_FREQ_5920 && center_freq < CHANNEL_FREQ_5950)
return CHANNEL_FREQ_5935;
if (center_freq < CHANNEL_FREQ_5950) {
if (chan_num == CHANNEL_NUM_14)
return CHANNEL_FREQ_2484;
if (chan_num < CHANNEL_NUM_14)
return CHANNEL_FREQ_2407 +
(chan_num * FREQ_MULTIPLIER_CONST_5MHZ);
if (chan_num < CHANNEL_NUM_27)
return CHANNEL_FREQ_2512 +
((chan_num - CHANNEL_NUM_15) *
FREQ_MULTIPLIER_CONST_20MHZ);
if (chan_num > CHANNEL_NUM_182 &&
chan_num < CHANNEL_NUM_197)
return ((chan_num * FREQ_MULTIPLIER_CONST_5MHZ) +
CHANNEL_FREQ_4000);
return CHANNEL_FREQ_5000 +
(chan_num * FREQ_MULTIPLIER_CONST_5MHZ);
} else {
return CHANNEL_FREQ_5950 +
(chan_num * FREQ_MULTIPLIER_CONST_5MHZ);
}
}
/**
* hal_get_hw_hptp_generic() - Get HW head and tail pointer value for any ring
* @hal_soc: Opaque HAL SOC handle
* @hal_ring: Source ring pointer
* @headp: Head Pointer
* @tailp: Tail Pointer
* @ring: Ring type
*
* Return: Update tail pointer and head pointer in arguments.
*/
static inline
void hal_get_hw_hptp_generic(struct hal_soc *hal_soc,
hal_ring_handle_t hal_ring_hdl,
uint32_t *headp, uint32_t *tailp,
uint8_t ring)
{
struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl;
struct hal_hw_srng_config *ring_config;
enum hal_ring_type ring_type = (enum hal_ring_type)ring;
if (!hal_soc || !srng) {
QDF_TRACE(QDF_MODULE_ID_HAL, QDF_TRACE_LEVEL_ERROR,
"%s: Context is Null", __func__);
return;
}
ring_config = HAL_SRNG_CONFIG(hal_soc, ring_type);
if (!ring_config->lmac_ring) {
if (srng->ring_dir == HAL_SRNG_SRC_RING) {
*headp = SRNG_SRC_REG_READ(srng, HP);
*tailp = SRNG_SRC_REG_READ(srng, TP);
} else {
*headp = SRNG_DST_REG_READ(srng, HP);
*tailp = SRNG_DST_REG_READ(srng, TP);
}
}
}
#if defined(WBM_IDLE_LSB_WRITE_CONFIRM_WAR)
/**
* hal_wbm_idle_lsb_write_confirm() - Check and update WBM_IDLE_LINK ring LSB
* @srng: srng handle
*
* Return: None
*/
static void hal_wbm_idle_lsb_write_confirm(struct hal_srng *srng)
{
if (srng->ring_id == HAL_SRNG_WBM_IDLE_LINK) {
while (SRNG_SRC_REG_READ(srng, BASE_LSB) !=
((unsigned int)srng->ring_base_paddr & 0xffffffff))
SRNG_SRC_REG_WRITE(srng, BASE_LSB,
srng->ring_base_paddr &
0xffffffff);
}
}
#else
static void hal_wbm_idle_lsb_write_confirm(struct hal_srng *srng)
{
}
#endif
#ifdef DP_UMAC_HW_RESET_SUPPORT
/**
* hal_srng_src_hw_write_cons_prefetch_timer() - Write cons prefetch timer reg
* @srng: srng handle
* @value: value to set
*
* Return: None
*/
static inline
void hal_srng_src_hw_write_cons_prefetch_timer(struct hal_srng *srng,
uint32_t value)
{
SRNG_SRC_REG_WRITE(srng, CONSUMER_PREFETCH_TIMER, value);
}
/**
* hal_srng_hw_disable_generic - Private function to disable SRNG
* source ring HW
* @hal_soc: HAL SOC handle
* @srng: SRNG ring pointer
*/
static inline
void hal_srng_hw_disable_generic(struct hal_soc *hal, struct hal_srng *srng)
{
uint32_t reg_val = 0;
if (srng->ring_dir == HAL_SRNG_DST_RING) {
reg_val = SRNG_DST_REG_READ(srng, MISC) & ~(SRNG_ENABLE_BIT);
SRNG_DST_REG_WRITE(srng, MISC, reg_val);
} else {
reg_val = SRNG_SRC_REG_READ(srng, MISC) & ~(SRNG_ENABLE_BIT);
SRNG_SRC_REG_WRITE(srng, MISC, reg_val);
srng->prefetch_timer =
SRNG_SRC_REG_READ(srng, CONSUMER_PREFETCH_TIMER);
hal_srng_src_hw_write_cons_prefetch_timer(srng, 0);
}
}
#else
static inline
void hal_srng_hw_disable_generic(struct hal_soc *hal, struct hal_srng *srng)
{
}
static inline
void hal_srng_src_hw_write_cons_prefetch_timer(struct hal_srng *srng,
uint32_t value)
{
}
#endif
/**
* hal_srng_src_hw_init - Private function to initialize SRNG
* source ring HW
* @hal_soc: HAL SOC handle
* @srng: SRNG ring pointer
* @idle_check: Check if ring is idle
* @idx: ring index
*/
static inline
void hal_srng_src_hw_init_generic(struct hal_soc *hal,
struct hal_srng *srng, bool idle_check,
uint32_t idx)
{
uint32_t reg_val = 0;
uint64_t tp_addr = 0;
if (idle_check) {
reg_val = SRNG_SRC_REG_READ(srng, MISC);
if (!(reg_val & SRNG_IDLE_STATE_BIT)) {
hal_err("ring_id %d not in idle state", srng->ring_id);
qdf_assert_always(0);
}
hal_srng_src_hw_write_cons_prefetch_timer(srng,
srng->prefetch_timer);
}
hal_debug("hw_init srng %d", srng->ring_id);
reg_val = SRNG_SRC_REG_READ(srng, MISC) & ~(SRNG_ENABLE_BIT);
SRNG_SRC_REG_WRITE(srng, MISC, reg_val);
reg_val = 0;
if (srng->flags & HAL_SRNG_MSI_INTR) {
SRNG_SRC_REG_WRITE(srng, MSI1_BASE_LSB,
srng->msi_addr & 0xffffffff);
reg_val = SRNG_SM(SRNG_SRC_FLD(MSI1_BASE_MSB, ADDR),
(uint64_t)(srng->msi_addr) >> 32) |
SRNG_SM(SRNG_SRC_FLD(MSI1_BASE_MSB,
MSI1_ENABLE), 1);
SRNG_SRC_REG_WRITE(srng, MSI1_BASE_MSB, reg_val);
SRNG_SRC_REG_WRITE(srng, MSI1_DATA,
qdf_cpu_to_le32(srng->msi_data));
}
SRNG_SRC_REG_WRITE(srng, BASE_LSB, srng->ring_base_paddr & 0xffffffff);
hal_wbm_idle_lsb_write_confirm(srng);
reg_val = SRNG_SM(SRNG_SRC_FLD(BASE_MSB, RING_BASE_ADDR_MSB),
((uint64_t)(srng->ring_base_paddr) >> 32)) |
SRNG_SM(SRNG_SRC_FLD(BASE_MSB, RING_SIZE),
srng->entry_size * srng->num_entries);
SRNG_SRC_REG_WRITE(srng, BASE_MSB, reg_val);
reg_val = SRNG_SM(SRNG_SRC_FLD(ID, ENTRY_SIZE), srng->entry_size);
SRNG_SRC_REG_WRITE(srng, ID, reg_val);
/**
* Interrupt setup:
* Default interrupt mode is 'pulse'. Need to setup SW_INTERRUPT_MODE
* if level mode is required
*/
reg_val = 0;
/*
* WAR - Hawkeye v1 has a hardware bug which requires timer value to be
* programmed in terms of 1us resolution instead of 8us resolution as
* given in MLD.
*/
if (srng->intr_timer_thres_us) {
reg_val |= SRNG_SM(SRNG_SRC_FLD(CONSUMER_INT_SETUP_IX0,
INTERRUPT_TIMER_THRESHOLD),
srng->intr_timer_thres_us);
/* For HK v2 this should be (srng->intr_timer_thres_us >> 3) */
}
if (srng->intr_batch_cntr_thres_entries) {
reg_val |= SRNG_SM(SRNG_SRC_FLD(CONSUMER_INT_SETUP_IX0,
BATCH_COUNTER_THRESHOLD),
srng->intr_batch_cntr_thres_entries *
srng->entry_size);
}
SRNG_SRC_REG_WRITE(srng, CONSUMER_INT_SETUP_IX0, reg_val);
reg_val = 0;
if (srng->flags & HAL_SRNG_LOW_THRES_INTR_ENABLE) {
reg_val |= SRNG_SM(SRNG_SRC_FLD(CONSUMER_INT_SETUP_IX1,
LOW_THRESHOLD), srng->u.src_ring.low_threshold);
}
SRNG_SRC_REG_WRITE(srng, CONSUMER_INT_SETUP_IX1, reg_val);
/* As per HW team, TP_ADDR and HP_ADDR for Idle link ring should
* remain 0 to avoid some WBM stability issues. Remote head/tail
* pointers are not required since this ring is completely managed
* by WBM HW
*/
reg_val = 0;
if (srng->ring_id != HAL_SRNG_WBM_IDLE_LINK) {
tp_addr = (uint64_t)(hal->shadow_rdptr_mem_paddr +
((unsigned long)(srng->u.src_ring.tp_addr) -
(unsigned long)(hal->shadow_rdptr_mem_vaddr)));
SRNG_SRC_REG_WRITE(srng, TP_ADDR_LSB, tp_addr & 0xffffffff);
SRNG_SRC_REG_WRITE(srng, TP_ADDR_MSB, tp_addr >> 32);
} else {
reg_val |= SRNG_SM(SRNG_SRC_FLD(MISC, RING_ID_DISABLE), 1);
}
/* Initilaize head and tail pointers to indicate ring is empty */
SRNG_SRC_REG_WRITE(srng, HP, idx * srng->entry_size);
SRNG_SRC_REG_WRITE(srng, TP, idx * srng->entry_size);
*srng->u.src_ring.tp_addr = idx * srng->entry_size;
srng->u.src_ring.hp = idx * srng->entry_size;
reg_val |= ((srng->flags & HAL_SRNG_DATA_TLV_SWAP) ?
SRNG_SM(SRNG_SRC_FLD(MISC, DATA_TLV_SWAP_BIT), 1) : 0) |
((srng->flags & HAL_SRNG_RING_PTR_SWAP) ?
SRNG_SM(SRNG_SRC_FLD(MISC, HOST_FW_SWAP_BIT), 1) : 0) |
((srng->flags & HAL_SRNG_MSI_SWAP) ?
SRNG_SM(SRNG_SRC_FLD(MISC, MSI_SWAP_BIT), 1) : 0);
/* Loop count is not used for SRC rings */
reg_val |= SRNG_SM(SRNG_SRC_FLD(MISC, LOOPCNT_DISABLE), 1);
/*
* reg_val |= SRNG_SM(SRNG_SRC_FLD(MISC, SRNG_ENABLE), 1);
* todo: update fw_api and replace with above line
* (when SRNG_ENABLE field for the MISC register is available in fw_api)
* (WCSS_UMAC_CE_0_SRC_WFSS_CE_CHANNEL_SRC_R0_SRC_RING_MISC)
*/
reg_val |= SRNG_ENABLE_BIT;
SRNG_SRC_REG_WRITE(srng, MISC, reg_val);
}
#ifdef WLAN_FEATURE_NEAR_FULL_IRQ
/**
* hal_srng_dst_msi2_setup() - Configure MSI2 register for a SRNG
* @srng: SRNG handle
*
* Return: None
*/
static inline void hal_srng_dst_msi2_setup(struct hal_srng *srng)
{
uint32_t reg_val = 0;
if (srng->u.dst_ring.nf_irq_support) {
SRNG_DST_REG_WRITE(srng, MSI2_BASE_LSB,
srng->msi2_addr & 0xffffffff);
reg_val = SRNG_SM(SRNG_DST_FLD(MSI2_BASE_MSB, ADDR),
(uint64_t)(srng->msi2_addr) >> 32) |
SRNG_SM(SRNG_DST_FLD(MSI2_BASE_MSB,
MSI2_ENABLE), 1);
SRNG_DST_REG_WRITE(srng, MSI2_BASE_MSB, reg_val);
SRNG_DST_REG_WRITE(srng, MSI2_DATA,
qdf_cpu_to_le32(srng->msi2_data));
}
}
/**
* hal_srng_dst_near_full_int_setup() - Configure near-full params for SRNG
* @srng: SRNG handle
*
* Return: None
*/
static inline void hal_srng_dst_near_full_int_setup(struct hal_srng *srng)
{
uint32_t reg_val = 0;
if (srng->u.dst_ring.nf_irq_support) {
if (srng->intr_timer_thres_us) {
reg_val |= SRNG_SM(SRNG_DST_FLD(PRODUCER_INT2_SETUP,
INTERRUPT2_TIMER_THRESHOLD),
srng->intr_timer_thres_us >> 3);
}
reg_val |= SRNG_SM(SRNG_DST_FLD(PRODUCER_INT2_SETUP,
HIGH_THRESHOLD),
srng->u.dst_ring.high_thresh *
srng->entry_size);
}
SRNG_DST_REG_WRITE(srng, PRODUCER_INT2_SETUP, reg_val);
}
#else
static inline void hal_srng_dst_msi2_setup(struct hal_srng *srng)
{
}
static inline void hal_srng_dst_near_full_int_setup(struct hal_srng *srng)
{
}
#endif
/**
* hal_srng_dst_hw_init - Private function to initialize SRNG
* destination ring HW
* @hal_soc: HAL SOC handle
* @srng: SRNG ring pointer
* @idle_check: Check if ring is idle
* @idx: Ring index
*/
static inline
void hal_srng_dst_hw_init_generic(struct hal_soc *hal,
struct hal_srng *srng, bool idle_check,
uint32_t idx)
{
uint32_t reg_val = 0;
uint64_t hp_addr = 0;
if (idle_check) {
reg_val = SRNG_DST_REG_READ(srng, MISC);
if (!(reg_val & SRNG_IDLE_STATE_BIT)) {
hal_err("ring_id %d not in idle state", srng->ring_id);
qdf_assert_always(0);
}
}
hal_debug("hw_init srng %d", srng->ring_id);
reg_val = SRNG_DST_REG_READ(srng, MISC) & ~(SRNG_ENABLE_BIT);
SRNG_DST_REG_WRITE(srng, MISC, reg_val);
reg_val = 0;
if (srng->flags & HAL_SRNG_MSI_INTR) {
SRNG_DST_REG_WRITE(srng, MSI1_BASE_LSB,
srng->msi_addr & 0xffffffff);
reg_val = SRNG_SM(SRNG_DST_FLD(MSI1_BASE_MSB, ADDR),
(uint64_t)(srng->msi_addr) >> 32) |
SRNG_SM(SRNG_DST_FLD(MSI1_BASE_MSB,
MSI1_ENABLE), 1);
SRNG_DST_REG_WRITE(srng, MSI1_BASE_MSB, reg_val);
SRNG_DST_REG_WRITE(srng, MSI1_DATA,
qdf_cpu_to_le32(srng->msi_data));
hal_srng_dst_msi2_setup(srng);
}
SRNG_DST_REG_WRITE(srng, BASE_LSB, srng->ring_base_paddr & 0xffffffff);
reg_val = SRNG_SM(SRNG_DST_FLD(BASE_MSB, RING_BASE_ADDR_MSB),
((uint64_t)(srng->ring_base_paddr) >> 32)) |
SRNG_SM(SRNG_DST_FLD(BASE_MSB, RING_SIZE),
srng->entry_size * srng->num_entries);
SRNG_DST_REG_WRITE(srng, BASE_MSB, reg_val);
reg_val = SRNG_SM(SRNG_DST_FLD(ID, RING_ID), srng->ring_id) |
SRNG_SM(SRNG_DST_FLD(ID, ENTRY_SIZE), srng->entry_size);
SRNG_DST_REG_WRITE(srng, ID, reg_val);
/**
* Interrupt setup:
* Default interrupt mode is 'pulse'. Need to setup SW_INTERRUPT_MODE
* if level mode is required
*/
reg_val = 0;
if (srng->intr_timer_thres_us) {
reg_val |= SRNG_SM(SRNG_DST_FLD(PRODUCER_INT_SETUP,
INTERRUPT_TIMER_THRESHOLD),
srng->intr_timer_thres_us >> 3);
}
if (srng->intr_batch_cntr_thres_entries) {
reg_val |= SRNG_SM(SRNG_DST_FLD(PRODUCER_INT_SETUP,
BATCH_COUNTER_THRESHOLD),
srng->intr_batch_cntr_thres_entries *
srng->entry_size);
}
SRNG_DST_REG_WRITE(srng, PRODUCER_INT_SETUP, reg_val);
/**
* Near-Full Interrupt setup:
* Default interrupt mode is 'pulse'. Need to setup SW_INTERRUPT_MODE
* if level mode is required
*/
hal_srng_dst_near_full_int_setup(srng);
hp_addr = (uint64_t)(hal->shadow_rdptr_mem_paddr +
((unsigned long)(srng->u.dst_ring.hp_addr) -
(unsigned long)(hal->shadow_rdptr_mem_vaddr)));
SRNG_DST_REG_WRITE(srng, HP_ADDR_LSB, hp_addr & 0xffffffff);
SRNG_DST_REG_WRITE(srng, HP_ADDR_MSB, hp_addr >> 32);
/* Initilaize head and tail pointers to indicate ring is empty */
SRNG_DST_REG_WRITE(srng, HP, idx * srng->entry_size);
SRNG_DST_REG_WRITE(srng, TP, idx * srng->entry_size);
*srng->u.dst_ring.hp_addr = idx * srng->entry_size;
srng->u.dst_ring.tp = idx * srng->entry_size;
reg_val = ((srng->flags & HAL_SRNG_DATA_TLV_SWAP) ?
SRNG_SM(SRNG_DST_FLD(MISC, DATA_TLV_SWAP_BIT), 1) : 0) |
((srng->flags & HAL_SRNG_RING_PTR_SWAP) ?
SRNG_SM(SRNG_DST_FLD(MISC, HOST_FW_SWAP_BIT), 1) : 0) |
((srng->flags & HAL_SRNG_MSI_SWAP) ?
SRNG_SM(SRNG_DST_FLD(MISC, MSI_SWAP_BIT), 1) : 0);
/*
* reg_val |= SRNG_SM(SRNG_SRC_FLD(MISC, SRNG_ENABLE), 1);
* todo: update fw_api and replace with above line
* (when SRNG_ENABLE field for the MISC register is available in fw_api)
* (WCSS_UMAC_CE_0_SRC_WFSS_CE_CHANNEL_SRC_R0_SRC_RING_MISC)
*/
reg_val |= 0x40;
SRNG_DST_REG_WRITE(srng, MISC, reg_val);
}
/**
* hal_srng_hw_reg_offset_init_generic() - Initialize the HW srng reg offset
* @hal_soc: HAL Soc handle
*
* Return: None
*/
static inline void hal_srng_hw_reg_offset_init_generic(struct hal_soc *hal_soc)
{
int32_t *hw_reg_offset = hal_soc->hal_hw_reg_offset;
/* dst */
hw_reg_offset[DST_HP] = REG_OFFSET(DST, HP);
hw_reg_offset[DST_TP] = REG_OFFSET(DST, TP);
hw_reg_offset[DST_ID] = REG_OFFSET(DST, ID);
hw_reg_offset[DST_MISC] = REG_OFFSET(DST, MISC);
hw_reg_offset[DST_HP_ADDR_LSB] = REG_OFFSET(DST, HP_ADDR_LSB);
hw_reg_offset[DST_HP_ADDR_MSB] = REG_OFFSET(DST, HP_ADDR_MSB);
hw_reg_offset[DST_MSI1_BASE_LSB] = REG_OFFSET(DST, MSI1_BASE_LSB);
hw_reg_offset[DST_MSI1_BASE_MSB] = REG_OFFSET(DST, MSI1_BASE_MSB);
hw_reg_offset[DST_MSI1_DATA] = REG_OFFSET(DST, MSI1_DATA);
hw_reg_offset[DST_BASE_LSB] = REG_OFFSET(DST, BASE_LSB);
hw_reg_offset[DST_BASE_MSB] = REG_OFFSET(DST, BASE_MSB);
hw_reg_offset[DST_PRODUCER_INT_SETUP] =
REG_OFFSET(DST, PRODUCER_INT_SETUP);
/* src */
hw_reg_offset[SRC_HP] = REG_OFFSET(SRC, HP);
hw_reg_offset[SRC_TP] = REG_OFFSET(SRC, TP);
hw_reg_offset[SRC_ID] = REG_OFFSET(SRC, ID);
hw_reg_offset[SRC_MISC] = REG_OFFSET(SRC, MISC);
hw_reg_offset[SRC_TP_ADDR_LSB] = REG_OFFSET(SRC, TP_ADDR_LSB);
hw_reg_offset[SRC_TP_ADDR_MSB] = REG_OFFSET(SRC, TP_ADDR_MSB);
hw_reg_offset[SRC_MSI1_BASE_LSB] = REG_OFFSET(SRC, MSI1_BASE_LSB);
hw_reg_offset[SRC_MSI1_BASE_MSB] = REG_OFFSET(SRC, MSI1_BASE_MSB);
hw_reg_offset[SRC_MSI1_DATA] = REG_OFFSET(SRC, MSI1_DATA);
hw_reg_offset[SRC_BASE_LSB] = REG_OFFSET(SRC, BASE_LSB);
hw_reg_offset[SRC_BASE_MSB] = REG_OFFSET(SRC, BASE_MSB);
hw_reg_offset[SRC_CONSUMER_INT_SETUP_IX0] =
REG_OFFSET(SRC, CONSUMER_INT_SETUP_IX0);
hw_reg_offset[SRC_CONSUMER_INT_SETUP_IX1] =
REG_OFFSET(SRC, CONSUMER_INT_SETUP_IX1);
#ifdef DP_UMAC_HW_RESET_SUPPORT
hw_reg_offset[SRC_CONSUMER_PREFETCH_TIMER] =
REG_OFFSET(SRC, CONSUMER_PREFETCH_TIMER);
#endif
}
#ifdef FEATURE_DIRECT_LINK
/**
* hal_srng_set_msi_config() - Set the MSI config and enable the SRNG
* @hal_ring_hdl: srng handle
* @params: ring parameters
*
* Return: QDF status
*/
static inline
QDF_STATUS hal_srng_set_msi_config(hal_ring_handle_t ring_hdl,
void *params)
{
struct hal_srng *srng = (struct hal_srng *)ring_hdl;
struct hal_srng_params *ring_params = (struct hal_srng_params *)params;
uint32_t reg_val;
srng->intr_timer_thres_us = ring_params->intr_timer_thres_us;
srng->intr_batch_cntr_thres_entries =
ring_params->intr_batch_cntr_thres_entries;
srng->msi_addr = ring_params->msi_addr;
srng->msi_data = ring_params->msi_data;
if (srng->ring_dir == HAL_SRNG_SRC_RING) {
reg_val = 0;
SRNG_SRC_REG_WRITE(srng, MSI1_BASE_LSB,
srng->msi_addr & 0xffffffff);
reg_val = SRNG_SM(SRNG_SRC_FLD(MSI1_BASE_MSB, ADDR),
(uint64_t)(srng->msi_addr) >> 32) |
SRNG_SM(SRNG_SRC_FLD(MSI1_BASE_MSB,
MSI1_ENABLE), 1);
SRNG_SRC_REG_WRITE(srng, MSI1_BASE_MSB, reg_val);
SRNG_SRC_REG_WRITE(srng, MSI1_DATA,
qdf_cpu_to_le32(srng->msi_data));
reg_val = 0;
if (srng->intr_timer_thres_us) {
reg_val |= SRNG_SM(SRNG_SRC_FLD(CONSUMER_INT_SETUP_IX0,
INTERRUPT_TIMER_THRESHOLD),
srng->intr_timer_thres_us);
}
if (srng->intr_batch_cntr_thres_entries) {
reg_val |= SRNG_SM(SRNG_SRC_FLD(CONSUMER_INT_SETUP_IX0,
BATCH_COUNTER_THRESHOLD),
srng->intr_batch_cntr_thres_entries *
srng->entry_size);
}
SRNG_SRC_REG_WRITE(srng, CONSUMER_INT_SETUP_IX0, reg_val);
} else {
reg_val = 0;
SRNG_DST_REG_WRITE(srng, MSI1_BASE_LSB,
srng->msi_addr & 0xffffffff);
reg_val = SRNG_SM(SRNG_DST_FLD(MSI1_BASE_MSB, ADDR),
(uint64_t)(srng->msi_addr) >> 32) |
SRNG_SM(SRNG_DST_FLD(MSI1_BASE_MSB,
MSI1_ENABLE), 1);
SRNG_DST_REG_WRITE(srng, MSI1_BASE_MSB, reg_val);
SRNG_DST_REG_WRITE(srng, MSI1_DATA,
qdf_cpu_to_le32(srng->msi_data));
reg_val = 0;
if (srng->intr_timer_thres_us) {
reg_val |= SRNG_SM(SRNG_DST_FLD(PRODUCER_INT_SETUP,
INTERRUPT_TIMER_THRESHOLD),
srng->intr_timer_thres_us >> 3);
}
if (srng->intr_batch_cntr_thres_entries) {
reg_val |= SRNG_SM(SRNG_DST_FLD(PRODUCER_INT_SETUP,
BATCH_COUNTER_THRESHOLD),
srng->intr_batch_cntr_thres_entries *
srng->entry_size);
}
SRNG_DST_REG_WRITE(srng, PRODUCER_INT_SETUP, reg_val);
}
return QDF_STATUS_SUCCESS;
}
#else
static inline
QDF_STATUS hal_srng_set_msi_config(hal_ring_handle_t ring_hdl,
void *params)
{
return QDF_STATUS_E_NOSUPPORT;
}
#endif
#endif /* HAL_GENERIC_API_H_ */