Browse Source

qcacmn: Provide hal io apis to support register windowing

Use windowing for register read/write.  This allows
for pci based devices to reduce the mapped bar size.
Required for QCA6290.

Change-Id: Ifb173095c135e9eca454f2ba6132b5c54ea8fc4b
CRs-Fixed: 2032131
Houston Hoffman 8 years ago
parent
commit
61dad49aa3
3 changed files with 101 additions and 2 deletions
  1. 77 0
      hal/wifi3.0/hal_api.h
  2. 5 2
      hal/wifi3.0/hal_internal.h
  3. 19 0
      hal/wifi3.0/hal_srng.c

+ 77 - 0
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

+ 5 - 2
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_ */

+ 19 - 0
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: