diff --git a/hal/wifi3.0/hal_api.h b/hal/wifi3.0/hal_api.h index 1cee9e2bcdd5..c0f1bf28342d 100644 --- a/hal/wifi3.0/hal_api.h +++ b/hal/wifi3.0/hal_api.h @@ -31,12 +31,89 @@ #define _HAL_API_H_ #include "qdf_types.h" +#include "qdf_util.h" #include "hal_internal.h" #include "hif_io32.h" #include "rx_msdu_link.h" #include "rx_reo_queue.h" #include "rx_reo_queue_ext.h" +#define MAX_UNWINDOWED_ADDRESS 0x80000 +#define WINDOW_ENABLE_BIT 0x80000000 +#define WINDOW_REG_ADDRESS 0x310C +#define WINDOW_SHIFT 19 +#define WINDOW_VALUE_MASK 0x1F +#define WINDOW_START MAX_UNWINDOWED_ADDRESS +#define WINDOW_RANGE_MASK 0x7FFFF + +static inline void hal_select_window(struct hal_soc *hal_soc, uint32_t offset) +{ + uint32_t window = (offset >> WINDOW_SHIFT) & WINDOW_VALUE_MASK; + if (window != hal_soc->register_window) { + qdf_iowrite32(hal_soc->dev_base_addr + WINDOW_REG_ADDRESS, + WINDOW_ENABLE_BIT | window); + hal_soc->register_window = window; + } +} + +/** + * note1: WINDOW_RANGE_MASK = (1 << WINDOW_SHIFT) -1 + * note2: 1 << WINDOW_SHIFT = MAX_UNWINDOWED_ADDRESS + * note3: WINDOW_VALUE_MASK = big enough that trying to write past that window + * would be a bug + */ +static inline void hal_write32_mb(struct hal_soc *hal_soc, uint32_t offset, + uint32_t value) +{ + + if (!hal_soc->use_register_windowing || + offset < MAX_UNWINDOWED_ADDRESS) { + qdf_iowrite32(hal_soc->dev_base_addr + offset, value); + } else { + qdf_spin_lock_irqsave(&hal_soc->register_access_lock); + hal_select_window(hal_soc, offset); + qdf_iowrite32(hal_soc->dev_base_addr + WINDOW_START + + (offset & WINDOW_RANGE_MASK), value); + qdf_spin_unlock_irqrestore(&hal_soc->register_access_lock); + } +} + +/** + * hal_write_address_32_mb - write a value to a register + * + */ +static inline void hal_write_address_32_mb(struct hal_soc *hal_soc, + void __iomem *addr, uint32_t value) +{ + uint32_t offset; + + if (!hal_soc->use_register_windowing) + return qdf_iowrite32(addr, value); + + offset = addr - hal_soc->dev_base_addr; + hal_write32_mb(hal_soc, offset, value); +} + +static inline uint32_t hal_read32_mb(struct hal_soc *hal_soc, uint32_t offset) +{ + uint32_t ret; + + if (!hal_soc->use_register_windowing || + offset < MAX_UNWINDOWED_ADDRESS) { + return qdf_ioread32(hal_soc->dev_base_addr + offset); + } + + qdf_spin_lock_irqsave(&hal_soc->register_access_lock); + hal_select_window(hal_soc, offset); + ret = qdf_ioread32(hal_soc->dev_base_addr + WINDOW_START + + (offset & WINDOW_RANGE_MASK)); + qdf_spin_unlock_irqrestore(&hal_soc->register_access_lock); + + return ret; +} + +#include "hif_io32.h" + /** * hal_attach - Initalize HAL layer * @hif_handle: Opaque HIF handle diff --git a/hal/wifi3.0/hal_internal.h b/hal/wifi3.0/hal_internal.h index d845e0ba16b0..b2547acd9864 100644 --- a/hal/wifi3.0/hal_internal.h +++ b/hal/wifi3.0/hal_internal.h @@ -322,6 +322,9 @@ struct hal_soc { /* shadow register configuration */ struct pld_shadow_reg_v2_cfg shadow_config[MAX_SHADOW_REGISTERS]; int num_shadow_registers_configured; + bool use_register_windowing; + uint32_t register_window; + qdf_spinlock_t register_access_lock; }; /* TODO: Check if the following can be provided directly by HW headers */ @@ -345,9 +348,9 @@ struct hal_soc { (_reg ## _ ## _fld ## _SHFT)) #define HAL_REG_WRITE(_soc, _reg, _value) \ - hif_write32_mb((_soc)->dev_base_addr + (_reg), (_value)) + hal_write32_mb(_soc, (_reg), (_value)) #define HAL_REG_READ(_soc, _offset) \ - hif_read32_mb((_soc)->dev_base_addr + (_offset)) + hal_read32_mb(_soc, (_offset)) #endif /* _HAL_INTERNAL_H_ */ diff --git a/hal/wifi3.0/hal_srng.c b/hal/wifi3.0/hal_srng.c index 3c85d5aa5338..b30ed62395ef 100644 --- a/hal/wifi3.0/hal_srng.c +++ b/hal/wifi3.0/hal_srng.c @@ -671,6 +671,20 @@ error: return; } +static void hal_target_based_configure(struct hal_soc *hal) +{ + struct hif_target_info *tgt_info = + hif_get_target_info_handle(hal->hif_handle); + + switch (tgt_info->target_type) { + case TARGET_TYPE_QCA6290: + hal->use_register_windowing = true; + break; + default: + break; + } +} + /** * hal_attach - Initalize HAL layer * @hif_handle: Opaque HIF handle @@ -724,6 +738,11 @@ void *hal_attach(void *hif_handle, qdf_device_t qdf_dev) hal->srng_list[i].ring_id = i; } + qdf_spinlock_create(&hal->register_access_lock); + hal->register_window = 0; + + hal_target_based_configure(hal); + return (void *)hal; fail2: