qcacmn: Add support to map generic shadow regs

Add apis to map generic registers to shadow region. Existing
logic includes mapping only srng based regs to the shadow
region.
Add support to map REO control regs and WBM2SW2 rel
ring HP reg address to the shadow region in case the direct
reg writes in IPA enable/disable autonomy fail due to UMAC
block being in a power collapsed state.
Shadow reg mapping for these regs is provided to FW during
init. Add stat shadow_reg_write_fail to track shadow reg
write failure and shadow_reg_write_succ to track successful
shadow writes.

Change-Id: I04790765a3de80047689657e2cad0b73123440b9
CRs-Fixed: 2790321
This commit is contained in:
Nisha Menon
2020-10-10 21:05:47 -07:00
committed by snandini
parent 43757caf1b
commit a377301c78
9 changed files with 363 additions and 29 deletions

View File

@@ -27,6 +27,9 @@
#include "hif_io32.h"
#include "qdf_platform.h"
/* Ring index for WBM2SW2 release ring */
#define HAL_IPA_TX_COMP_RING_IDX 2
/* calculate the register address offset from bar0 of shadow register x */
#if defined(QCA_WIFI_QCA6390) || defined(QCA_WIFI_QCA6490)
#define SHADOW_REGISTER_START_ADDRESS_OFFSET 0x000008FC
@@ -597,6 +600,135 @@ uint32_t hal_read32_mb_cmem(struct hal_soc *hal_soc, uint32_t offset)
}
#endif
#ifdef GENERIC_SHADOW_REGISTER_ACCESS_ENABLE
/* To check shadow config index range between 0..31 */
#define HAL_SHADOW_REG_INDEX_LOW 32
/* To check shadow config index range between 32..39 */
#define HAL_SHADOW_REG_INDEX_HIGH 40
/* Dirty bit reg offsets corresponding to shadow config index */
#define HAL_SHADOW_REG_DIRTY_BIT_DATA_LOW_OFFSET 0x30C8
#define HAL_SHADOW_REG_DIRTY_BIT_DATA_HIGH_OFFSET 0x30C4
/* PCIE_PCIE_TOP base addr offset */
#define HAL_PCIE_PCIE_TOP_WRAPPER 0x01E00000
/* Max retry attempts to read the dirty bit reg */
#ifdef HAL_CONFIG_SLUB_DEBUG_ON
#define HAL_SHADOW_DIRTY_BIT_POLL_MAX 10000
#else
#define HAL_SHADOW_DIRTY_BIT_POLL_MAX 2000
#endif
/* Delay in usecs for polling dirty bit reg */
#define HAL_SHADOW_DIRTY_BIT_POLL_DELAY 5
/**
* hal_poll_dirty_bit_reg() - Poll dirty register bit to confirm
* write was successful
* @hal_soc: hal soc handle
* @shadow_config_index: index of shadow reg used to confirm
* write
*
* Return: QDF_STATUS_SUCCESS on success
*/
static inline QDF_STATUS hal_poll_dirty_bit_reg(struct hal_soc *hal,
int shadow_config_index)
{
uint32_t read_value = 0;
int retry_cnt = 0;
uint32_t reg_offset = 0;
if (shadow_config_index > 0 &&
shadow_config_index < HAL_SHADOW_REG_INDEX_LOW) {
reg_offset =
HAL_SHADOW_REG_DIRTY_BIT_DATA_LOW_OFFSET;
} else if (shadow_config_index >= HAL_SHADOW_REG_INDEX_LOW &&
shadow_config_index < HAL_SHADOW_REG_INDEX_HIGH) {
reg_offset =
HAL_SHADOW_REG_DIRTY_BIT_DATA_HIGH_OFFSET;
} else {
hal_err("Invalid shadow_config_index = %d",
shadow_config_index);
return QDF_STATUS_E_INVAL;
}
while (retry_cnt < HAL_SHADOW_DIRTY_BIT_POLL_MAX) {
read_value = hal_read32_mb(
hal, HAL_PCIE_PCIE_TOP_WRAPPER + reg_offset);
/* Check if dirty bit corresponding to shadow_index is set */
if (read_value & BIT(shadow_config_index)) {
/* Dirty reg bit not reset */
qdf_udelay(HAL_SHADOW_DIRTY_BIT_POLL_DELAY);
retry_cnt++;
} else {
hal_debug("Shadow write: offset 0x%x read val 0x%x",
reg_offset, read_value);
return QDF_STATUS_SUCCESS;
}
}
return QDF_STATUS_E_TIMEOUT;
}
/**
* hal_write32_mb_shadow_confirm() - write to shadow reg and
* poll dirty register bit to confirm write
* @hal_soc: hal soc handle
* @reg_offset: target reg offset address from BAR
* @value: value to write
*
* Return: QDF_STATUS_SUCCESS on success
*/
static inline QDF_STATUS hal_write32_mb_shadow_confirm(
struct hal_soc *hal,
uint32_t reg_offset,
uint32_t value)
{
int i;
QDF_STATUS ret;
uint32_t shadow_reg_offset;
uint32_t read_value;
int shadow_config_index;
bool is_reg_offset_present = false;
for (i = 0; i < MAX_GENERIC_SHADOW_REG; i++) {
/* Found the shadow config for the reg_offset */
struct shadow_reg_config *hal_shadow_reg_list =
&hal->list_shadow_reg_config[i];
if (hal_shadow_reg_list->target_register ==
reg_offset) {
shadow_config_index =
hal_shadow_reg_list->shadow_config_index;
shadow_reg_offset =
SHADOW_REGISTER(shadow_config_index);
hal_write32_mb_confirm(
hal, shadow_reg_offset, value);
is_reg_offset_present = true;
break;
}
ret = QDF_STATUS_E_FAILURE;
}
if (is_reg_offset_present) {
ret = hal_poll_dirty_bit_reg(hal, shadow_config_index);
read_value = hal_read32_mb(hal, reg_offset);
hal_info("Shadow retry:reg 0x%x val 0x%x readval 0x%x ret %d",
reg_offset, value, read_value, ret);
if (QDF_IS_STATUS_ERROR(ret)) {
HAL_STATS_INC(hal, shadow_reg_write_fail, 1);
return ret;
}
HAL_STATS_INC(hal, shadow_reg_write_succ, 1);
}
return ret;
}
#else /* GENERIC_SHADOW_REGISTER_ACCESS_ENABLE */
static inline QDF_STATUS hal_write32_mb_shadow_confirm(
struct hal_soc *hal_soc,
uint32_t offset,
uint32_t value)
{
return QDF_STATUS_SUCCESS;
}
#endif /* GENERIC_SHADOW_REGISTER_ACCESS_ENABLE */
/* Max times allowed for register writing retry */
#define HAL_REG_WRITE_RETRY_MAX 5
/* Delay milliseconds for each time retry */
@@ -624,6 +756,7 @@ static inline void hal_write32_mb_confirm_retry(struct hal_soc *hal_soc,
{
uint8_t retry_cnt = 0;
uint32_t read_value;
QDF_STATUS ret;
while (retry_cnt <= HAL_REG_WRITE_RETRY_MAX) {
hal_write32_mb_confirm(hal_soc, offset, value);
@@ -638,8 +771,12 @@ static inline void hal_write32_mb_confirm_retry(struct hal_soc *hal_soc,
retry_cnt++;
}
if (retry_cnt > HAL_REG_WRITE_RETRY_MAX && recovery)
qdf_trigger_self_recovery(NULL, QDF_HAL_REG_WRITE_FAILURE);
if (retry_cnt > HAL_REG_WRITE_RETRY_MAX) {
ret = hal_write32_mb_shadow_confirm(hal_soc, offset, value);
if (QDF_IS_STATUS_ERROR(ret) && recovery)
qdf_trigger_self_recovery(
NULL, QDF_HAL_REG_WRITE_FAILURE);
}
}
#ifdef FEATURE_HAL_DELAYED_REG_WRITE
@@ -889,12 +1026,13 @@ struct hal_srng_params {
uint32_t prefetch_timer;
};
/* hal_construct_shadow_config() - initialize the shadow registers for dp rings
/* hal_construct_srng_shadow_regs() - initialize the shadow
* registers for srngs
* @hal_soc: hal handle
*
* Return: QDF_STATUS_OK on success
*/
extern QDF_STATUS hal_construct_shadow_config(void *hal_soc);
QDF_STATUS hal_construct_srng_shadow_regs(void *hal_soc);
/* hal_set_one_shadow_config() - add a config for the specified ring
* @hal_soc: hal handle
@@ -911,8 +1049,8 @@ extern QDF_STATUS hal_construct_shadow_config(void *hal_soc);
*
* Return: QDF_STATUS_OK on success
*/
extern QDF_STATUS hal_set_one_shadow_config(void *hal_soc, int ring_type,
int ring_num);
QDF_STATUS hal_set_one_shadow_config(void *hal_soc, int ring_type,
int ring_num);
/**
* hal_get_shadow_config() - retrieve the config table
* @hal_soc: hal handle
@@ -1012,10 +1150,13 @@ extern void hal_srng_dst_set_hp_paddr(struct hal_srng *sring, uint64_t paddr);
/**
* hal_srng_dst_init_hp() - Initilaize head pointer with cached head pointer
* @hal_soc: hal_soc handle
* @srng: sring pointer
* @vaddr: virtual address
*/
extern void hal_srng_dst_init_hp(struct hal_srng *srng, uint32_t *vaddr);
void hal_srng_dst_init_hp(struct hal_soc_handle *hal_soc,
struct hal_srng *srng,
uint32_t *vaddr);
/**
* hal_srng_cleanup - Deinitialize HW SRNG ring.
@@ -2415,4 +2556,59 @@ static inline void hal_reo_set_err_dst_remap(hal_soc_handle_t hal_soc_hdl)
if (hal_soc->ops->hal_reo_set_err_dst_remap)
hal_soc->ops->hal_reo_set_err_dst_remap(hal_soc);
}
#ifdef GENERIC_SHADOW_REGISTER_ACCESS_ENABLE
/**
* hal_set_one_target_reg_config() - Populate the target reg
* offset in hal_soc for one non srng related register at the
* given list index
* @hal_soc: hal handle
* @target_reg_offset: target register offset
* @list_index: index in hal list for shadow regs
*
* Return: none
*/
void hal_set_one_target_reg_config(struct hal_soc *hal,
uint32_t target_reg_offset,
int list_index);
/**
* hal_set_shadow_regs() - Populate register offset for
* registers that need to be populated in list_shadow_reg_config
* in order to be sent to FW. These reg offsets will be mapped
* to shadow registers.
* @hal_soc: hal handle
*
* Return: QDF_STATUS_OK on success
*/
QDF_STATUS hal_set_shadow_regs(void *hal_soc);
/**
* hal_construct_shadow_regs() - initialize the shadow registers
* for non-srng related register configs
* @hal_soc: hal handle
*
* Return: QDF_STATUS_OK on success
*/
QDF_STATUS hal_construct_shadow_regs(void *hal_soc);
#else /* GENERIC_SHADOW_REGISTER_ACCESS_ENABLE */
static inline void hal_set_one_target_reg_config(
struct hal_soc *hal,
uint32_t target_reg_offset,
int list_index)
{
}
static inline QDF_STATUS hal_set_shadow_regs(void *hal_soc)
{
return QDF_STATUS_SUCCESS;
}
static inline QDF_STATUS hal_construct_shadow_regs(void *hal_soc)
{
return QDF_STATUS_SUCCESS;
}
#endif /* GENERIC_SHADOW_REGISTER_ACCESS_ENABLE */
#endif /* _HAL_APIH_ */