wifi: ath11k: remap ce register space for IPQ5018
authorSriram R <quic_srirrama@quicinc.com>
Fri, 2 Dec 2022 21:37:14 +0000 (23:37 +0200)
committerKalle Valo <quic_kvalo@quicinc.com>
Wed, 7 Dec 2022 17:16:53 +0000 (19:16 +0200)
In IPQ5018 ce register space is moved out of wcss unlike
ipq8074 or ipq6018 and the space is not contiguous,
hence remap the CE registers to a new space to access them.

Register read/write is modified to check if the register to be written
falls in the CE register space and corresponding register is written.
Also adjust the interrupt register address to ce irq enable/disable.

Tested-on: IPQ5018 hw1.0 AHB WLAN.HK.2.6.0.1-00861-QCAHKSWPL_SILICONZ-1

Signed-off-by: Sriram R <quic_srirrama@quicinc.com>
Co-developed-by: Karthikeyan Kathirvel <quic_kathirve@quicinc.com>
Signed-off-by: Karthikeyan Kathirvel <quic_kathirve@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20221122132152.17771-5-quic_kathirve@quicinc.com
drivers/net/wireless/ath/ath11k/ahb.c
drivers/net/wireless/ath/ath11k/ce.h
drivers/net/wireless/ath/ath11k/core.c
drivers/net/wireless/ath/ath11k/core.h
drivers/net/wireless/ath/ath11k/hal.c
drivers/net/wireless/ath/ath11k/hal.h
drivers/net/wireless/ath/ath11k/hw.c
drivers/net/wireless/ath/ath11k/hw.h
drivers/net/wireless/ath/ath11k/pci.c

index d34a4d6325b2b4700dcba866e9d7ded1e8d13d7a..cb9dd00d01951d18603333ee1544680930a3c50b 100644 (file)
@@ -267,30 +267,42 @@ static void ath11k_ahb_clearbit32(struct ath11k_base *ab, u8 bit, u32 offset)
 static void ath11k_ahb_ce_irq_enable(struct ath11k_base *ab, u16 ce_id)
 {
        const struct ce_attr *ce_attr;
+       const struct ce_ie_addr *ce_ie_addr = ab->hw_params.ce_ie_addr;
+       u32 ie1_reg_addr, ie2_reg_addr, ie3_reg_addr;
+
+       ie1_reg_addr = ce_ie_addr->ie1_reg_addr + ATH11K_CE_OFFSET(ab);
+       ie2_reg_addr = ce_ie_addr->ie2_reg_addr + ATH11K_CE_OFFSET(ab);
+       ie3_reg_addr = ce_ie_addr->ie3_reg_addr + ATH11K_CE_OFFSET(ab);
 
        ce_attr = &ab->hw_params.host_ce_config[ce_id];
        if (ce_attr->src_nentries)
-               ath11k_ahb_setbit32(ab, ce_id, CE_HOST_IE_ADDRESS);
+               ath11k_ahb_setbit32(ab, ce_id, ie1_reg_addr);
 
        if (ce_attr->dest_nentries) {
-               ath11k_ahb_setbit32(ab, ce_id, CE_HOST_IE_2_ADDRESS);
+               ath11k_ahb_setbit32(ab, ce_id, ie2_reg_addr);
                ath11k_ahb_setbit32(ab, ce_id + CE_HOST_IE_3_SHIFT,
-                                   CE_HOST_IE_3_ADDRESS);
+                                   ie3_reg_addr);
        }
 }
 
 static void ath11k_ahb_ce_irq_disable(struct ath11k_base *ab, u16 ce_id)
 {
        const struct ce_attr *ce_attr;
+       const struct ce_ie_addr *ce_ie_addr = ab->hw_params.ce_ie_addr;
+       u32 ie1_reg_addr, ie2_reg_addr, ie3_reg_addr;
+
+       ie1_reg_addr = ce_ie_addr->ie1_reg_addr + ATH11K_CE_OFFSET(ab);
+       ie2_reg_addr = ce_ie_addr->ie2_reg_addr + ATH11K_CE_OFFSET(ab);
+       ie3_reg_addr = ce_ie_addr->ie3_reg_addr + ATH11K_CE_OFFSET(ab);
 
        ce_attr = &ab->hw_params.host_ce_config[ce_id];
        if (ce_attr->src_nentries)
-               ath11k_ahb_clearbit32(ab, ce_id, CE_HOST_IE_ADDRESS);
+               ath11k_ahb_clearbit32(ab, ce_id, ie1_reg_addr);
 
        if (ce_attr->dest_nentries) {
-               ath11k_ahb_clearbit32(ab, ce_id, CE_HOST_IE_2_ADDRESS);
+               ath11k_ahb_clearbit32(ab, ce_id, ie2_reg_addr);
                ath11k_ahb_clearbit32(ab, ce_id + CE_HOST_IE_3_SHIFT,
-                                     CE_HOST_IE_3_ADDRESS);
+                                     ie3_reg_addr);
        }
 }
 
@@ -1142,10 +1154,26 @@ static int ath11k_ahb_probe(struct platform_device *pdev)
                goto err_core_free;
        }
 
+       ab->mem_ce = ab->mem;
+
        ret = ath11k_core_pre_init(ab);
        if (ret)
                goto err_core_free;
 
+       if (ab->hw_params.ce_remap) {
+               const struct ce_remap *ce_remap = ab->hw_params.ce_remap;
+               /* ce register space is moved out of wcss unlike ipq8074 or ipq6018
+                * and the space is not contiguous, hence remapping the CE registers
+                * to a new space for accessing them.
+                */
+               ab->mem_ce = ioremap(ce_remap->base, ce_remap->size);
+               if (IS_ERR(ab->mem_ce)) {
+                       dev_err(&pdev->dev, "ce ioremap error\n");
+                       ret = -ENOMEM;
+                       goto err_core_free;
+               }
+       }
+
        ret = ath11k_ahb_setup_resources(ab);
        if (ret)
                goto err_core_free;
@@ -1236,6 +1264,10 @@ static void ath11k_ahb_free_resources(struct ath11k_base *ab)
        ath11k_ahb_release_smp2p_handle(ab);
        ath11k_ahb_fw_resource_deinit(ab);
        ath11k_ce_free_pipes(ab);
+
+       if (ab->hw_params.ce_remap)
+               iounmap(ab->mem_ce);
+
        ath11k_core_free(ab);
        platform_set_drvdata(pdev, NULL);
 }
index 9644ff909502e9e4476da86f4052bb5129611191..1fc6360e7f01b5a0b1b69071968ebb35d3c8a2d6 100644 (file)
@@ -49,6 +49,11 @@ void ath11k_ce_byte_swap(void *mem, u32 len);
 #define CE_HOST_IE_2_ADDRESS   0x00A18040
 #define CE_HOST_IE_3_ADDRESS   CE_HOST_IE_ADDRESS
 
+/* CE IE registers are different for IPQ5018 */
+#define CE_HOST_IPQ5018_IE_ADDRESS             0x0841804C
+#define CE_HOST_IPQ5018_IE_2_ADDRESS           0x08418050
+#define CE_HOST_IPQ5018_IE_3_ADDRESS           CE_HOST_IPQ5018_IE_ADDRESS
+
 #define CE_HOST_IE_3_SHIFT     0xC
 
 #define CE_RING_IDX_INCR(nentries_mask, idx) (((idx) + 1) & (nentries_mask))
@@ -84,6 +89,17 @@ struct ce_pipe_config {
        __le32 reserved;
 };
 
+struct ce_ie_addr {
+       u32 ie1_reg_addr;
+       u32 ie2_reg_addr;
+       u32 ie3_reg_addr;
+};
+
+struct ce_remap {
+       u32 base;
+       u32 size;
+};
+
 struct ce_attr {
        /* CE_ATTR_* values */
        unsigned int flags;
index 01ad67717fa7b0a9867df47ce5a54f989b42353e..a648f5d3072e64707023dd3776d246e41aef1368 100644 (file)
@@ -54,6 +54,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
                .target_ce_count = 11,
                .svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq8074,
                .svc_to_ce_map_len = 21,
+               .ce_ie_addr = &ath11k_ce_ie_addr_ipq8074,
                .single_pdev_only = false,
                .rxdma1_enable = true,
                .num_rxmda_per_pdev = 1,
@@ -137,6 +138,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
                .target_ce_count = 11,
                .svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq6018,
                .svc_to_ce_map_len = 19,
+               .ce_ie_addr = &ath11k_ce_ie_addr_ipq8074,
                .single_pdev_only = false,
                .rxdma1_enable = true,
                .num_rxmda_per_pdev = 1,
@@ -218,6 +220,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
                .target_ce_count = 9,
                .svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390,
                .svc_to_ce_map_len = 14,
+               .ce_ie_addr = &ath11k_ce_ie_addr_ipq8074,
                .single_pdev_only = true,
                .rxdma1_enable = false,
                .num_rxmda_per_pdev = 2,
@@ -301,6 +304,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
                .target_ce_count = 9,
                .svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qcn9074,
                .svc_to_ce_map_len = 18,
+               .ce_ie_addr = &ath11k_ce_ie_addr_ipq8074,
                .rxdma1_enable = true,
                .num_rxmda_per_pdev = 1,
                .rx_mac_buf_ring = false,
@@ -381,6 +385,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
                .target_ce_count = 9,
                .svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390,
                .svc_to_ce_map_len = 14,
+               .ce_ie_addr = &ath11k_ce_ie_addr_ipq8074,
                .single_pdev_only = true,
                .rxdma1_enable = false,
                .num_rxmda_per_pdev = 2,
@@ -546,6 +551,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
                .target_ce_count = 9,
                .svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390,
                .svc_to_ce_map_len = 14,
+               .ce_ie_addr = &ath11k_ce_ie_addr_ipq8074,
                .single_pdev_only = true,
                .rxdma1_enable = false,
                .num_rxmda_per_pdev = 1,
@@ -634,6 +640,8 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
                .target_ce_count = TARGET_CE_CNT_5018,
                .svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq5018,
                .svc_to_ce_map_len = SVC_CE_MAP_LEN_5018,
+               .ce_ie_addr = &ath11k_ce_ie_addr_ipq5018,
+               .ce_remap = &ath11k_ce_remap_ipq5018,
                .rxdma1_enable = true,
                .num_rxmda_per_pdev = RXDMA_PER_PDEV_5018,
                .rx_mac_buf_ring = false,
index e7da28d6f3734397edfea2a1a020a4f69198ab90..a8acb8b7b8d53c65846f183af37d90524ce5ba1c 100644 (file)
@@ -851,6 +851,7 @@ struct ath11k_base {
        struct ath11k_dp dp;
 
        void __iomem *mem;
+       void __iomem *mem_ce;
        unsigned long mem_len;
 
        struct {
index 2fd224480d4532d7d37211b07b576f2c1ad0234a..22422237500cfd25ea444ef8cbdd38a77f00313d 100644 (file)
@@ -1220,16 +1220,20 @@ static int ath11k_hal_srng_create_config(struct ath11k_base *ab)
        s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_STATUS_RING_HP;
 
        s = &hal->srng_config[HAL_CE_SRC];
-       s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) + HAL_CE_DST_RING_BASE_LSB;
-       s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) + HAL_CE_DST_RING_HP;
+       s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) + HAL_CE_DST_RING_BASE_LSB +
+               ATH11K_CE_OFFSET(ab);
+       s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab) + HAL_CE_DST_RING_HP +
+               ATH11K_CE_OFFSET(ab);
        s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG(ab) -
                HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab);
        s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_SRC_REG(ab) -
                HAL_SEQ_WCSS_UMAC_CE0_SRC_REG(ab);
 
        s = &hal->srng_config[HAL_CE_DST];
-       s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_RING_BASE_LSB;
-       s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_RING_HP;
+       s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_RING_BASE_LSB +
+               ATH11K_CE_OFFSET(ab);
+       s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_RING_HP +
+               ATH11K_CE_OFFSET(ab);
        s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
                HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab);
        s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
@@ -1237,8 +1241,9 @@ static int ath11k_hal_srng_create_config(struct ath11k_base *ab)
 
        s = &hal->srng_config[HAL_CE_DST_STATUS];
        s->reg_start[0] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) +
-               HAL_CE_DST_STATUS_RING_BASE_LSB;
-       s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_STATUS_RING_HP;
+               HAL_CE_DST_STATUS_RING_BASE_LSB + ATH11K_CE_OFFSET(ab);
+       s->reg_start[1] = HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab) + HAL_CE_DST_STATUS_RING_HP +
+               ATH11K_CE_OFFSET(ab);
        s->reg_size[0] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
                HAL_SEQ_WCSS_UMAC_CE0_DST_REG(ab);
        s->reg_size[1] = HAL_SEQ_WCSS_UMAC_CE1_DST_REG(ab) -
index 6a1f78ee6eb66ccdbfaaa262d92891c915649f3b..1942d41d6de541a4e5e6404fa93addd2f9120c77 100644 (file)
@@ -321,6 +321,10 @@ struct ath11k_base;
 #define HAL_WBM2SW_RELEASE_RING_BASE_MSB_RING_SIZE     0x000fffff
 #define HAL_RXDMA_RING_MAX_SIZE                                0x0000ffff
 
+/* IPQ5018 ce registers */
+#define HAL_IPQ5018_CE_WFSS_REG_BASE           0x08400000
+#define HAL_IPQ5018_CE_SIZE                    0x200000
+
 /* Add any other errors here and return them in
  * ath11k_hal_rx_desc_get_err().
  */
@@ -519,6 +523,7 @@ enum hal_srng_dir {
 #define HAL_SRNG_FLAGS_MSI_INTR                        0x00020000
 #define HAL_SRNG_FLAGS_CACHED                   0x20000000
 #define HAL_SRNG_FLAGS_LMAC_RING               0x80000000
+#define HAL_SRNG_FLAGS_REMAP_CE_RING        0x10000000
 
 #define HAL_SRNG_TLV_HDR_TAG           GENMASK(9, 1)
 #define HAL_SRNG_TLV_HDR_LEN           GENMASK(25, 10)
index ce8d73c025ba453c4a0ba42b0498129013ed66d5..6b009dfc554d0918af97c74254e71a4b8a8434e6 100644 (file)
@@ -2163,6 +2163,23 @@ const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_ipq5018[] = {
        { /* terminator entry */ }
 };
 
+const struct ce_ie_addr ath11k_ce_ie_addr_ipq8074 = {
+       .ie1_reg_addr = CE_HOST_IE_ADDRESS,
+       .ie2_reg_addr = CE_HOST_IE_2_ADDRESS,
+       .ie3_reg_addr = CE_HOST_IE_3_ADDRESS,
+};
+
+const struct ce_ie_addr ath11k_ce_ie_addr_ipq5018 = {
+       .ie1_reg_addr = CE_HOST_IPQ5018_IE_ADDRESS - HAL_IPQ5018_CE_WFSS_REG_BASE,
+       .ie2_reg_addr = CE_HOST_IPQ5018_IE_2_ADDRESS - HAL_IPQ5018_CE_WFSS_REG_BASE,
+       .ie3_reg_addr = CE_HOST_IPQ5018_IE_3_ADDRESS - HAL_IPQ5018_CE_WFSS_REG_BASE,
+};
+
+const struct ce_remap ath11k_ce_remap_ipq5018 = {
+       .base = HAL_IPQ5018_CE_WFSS_REG_BASE,
+       .size = HAL_IPQ5018_CE_SIZE,
+};
+
 const struct ath11k_hw_regs ipq8074_regs = {
        /* SW2TCL(x) R0 ring configuration address */
        .hal_tcl1_ring_base_lsb = 0x00000510,
index 0c5ef8a526d8519ed48f6504109d53b577152192..e2ed5d0477430859016d78f7a756f53709009461 100644 (file)
@@ -80,6 +80,8 @@
 #define ATH11K_M3_FILE                 "m3.bin"
 #define ATH11K_REGDB_FILE_NAME         "regdb.bin"
 
+#define ATH11K_CE_OFFSET(ab)   (ab->mem_ce - ab->mem)
+
 enum ath11k_hw_rate_cck {
        ATH11K_HW_RATE_CCK_LP_11M = 0,
        ATH11K_HW_RATE_CCK_LP_5_5M,
@@ -158,6 +160,8 @@ struct ath11k_hw_params {
        u32 target_ce_count;
        const struct service_to_pipe *svc_to_ce_map;
        u32 svc_to_ce_map_len;
+       const struct ce_ie_addr *ce_ie_addr;
+       const struct ce_remap *ce_remap;
 
        bool single_pdev_only;
 
@@ -277,6 +281,11 @@ extern const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_qca6390;
 extern const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_qcn9074;
 extern const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_wcn6750;
 
+extern const struct ce_ie_addr ath11k_ce_ie_addr_ipq8074;
+extern const struct ce_ie_addr ath11k_ce_ie_addr_ipq5018;
+
+extern const struct ce_remap ath11k_ce_remap_ipq5018;
+
 extern const struct ath11k_hw_hal_params ath11k_hw_hal_params_ipq8074;
 extern const struct ath11k_hw_hal_params ath11k_hw_hal_params_qca6390;
 extern const struct ath11k_hw_hal_params ath11k_hw_hal_params_wcn6750;
index 99cf3357c66e16bbd91a0fb8e56c3f156a993383..776362d151cbb6e1a9be03c05c1bd36f7f3e81de 100644 (file)
@@ -543,6 +543,8 @@ static int ath11k_pci_claim(struct ath11k_pci *ab_pci, struct pci_dev *pdev)
                goto clear_master;
        }
 
+       ab->mem_ce = ab->mem;
+
        ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot pci_mem 0x%pK\n", ab->mem);
        return 0;