diff --git a/hal/wifi3.0/hal_api.h b/hal/wifi3.0/hal_api.h index 84393d6cc8..97862e7c6b 100644 --- a/hal/wifi3.0/hal_api.h +++ b/hal/wifi3.0/hal_api.h @@ -727,6 +727,12 @@ struct hal_mem_info { void *dev_base_addr; /* dev base physical addr */ void *dev_base_paddr; + /* dev base ce virutal addr - applicable only for qca5018 */ + /* In qca5018 CE register are outside wcss block */ + /* using a separate address space to access CE registers */ + void *dev_base_addr_ce; + /* dev base ce physical addr */ + void *dev_base_paddr_ce; /* Remote virtual pointer memory for HW/FW updates */ void *shadow_rdptr_mem_vaddr; /* Remote physical pointer memory for HW/FW updates */ diff --git a/hal/wifi3.0/hal_internal.h b/hal/wifi3.0/hal_internal.h index 98f58c2416..ad678a3b3c 100644 --- a/hal/wifi3.0/hal_internal.h +++ b/hal/wifi3.0/hal_internal.h @@ -665,6 +665,8 @@ struct hal_soc { /* Device base address */ void *dev_base_addr; + /* Device base address for ce - qca5018 target */ + void *dev_base_addr_ce; /* HAL internal state for all SRNG rings. * TODO: See if this is required diff --git a/hal/wifi3.0/hal_srng.c b/hal/wifi3.0/hal_srng.c index 8b25986063..969bd601b8 100644 --- a/hal/wifi3.0/hal_srng.c +++ b/hal/wifi3.0/hal_srng.c @@ -337,6 +337,8 @@ static void hal_target_based_configure(struct hal_soc *hal) #endif #ifdef QCA_WIFI_QCA5018 case TARGET_TYPE_QCA5018: + hal->use_register_windowing = true; + hal->static_window_map = true; hal_qca5018_attach(hal); break; #endif @@ -739,7 +741,8 @@ void *hal_attach(struct hif_opaque_softc *hif_handle, qdf_device_t qdf_dev) goto fail0; } hal->hif_handle = hif_handle; - hal->dev_base_addr = hif_get_dev_ba(hif_handle); + hal->dev_base_addr = hif_get_dev_ba(hif_handle); /* UMAC */ + hal->dev_base_addr_ce = hif_get_dev_ba_ce(hif_handle); /* CE */ hal->qdf_dev = qdf_dev; hal->shadow_rdptr_mem_vaddr = (uint32_t *)qdf_mem_alloc_consistent( qdf_dev, qdf_dev->dev, sizeof(*(hal->shadow_rdptr_mem_vaddr)) * diff --git a/hal/wifi3.0/qca5018/hal_5018.c b/hal/wifi3.0/qca5018/hal_5018.c index 7436b535f0..4e30e7934d 100644 --- a/hal/wifi3.0/qca5018/hal_5018.c +++ b/hal/wifi3.0/qca5018/hal_5018.c @@ -111,6 +111,8 @@ (UMAC_WINDOW_ADDRESS_5018 << 12) | \ WINDOW_ENABLE_BIT) +#define HOST_CE_MASK_VALUE 0xFF000000 + #include #include #include @@ -1336,26 +1338,23 @@ static inline qdf_iomem_t hal_get_window_address_5018(struct hal_soc *hal_soc, qdf_iomem_t new_offset; /* - * If offset lies within DP register range, use 3rd window to write - * into DP region. - */ - if ((offset ^ SEQ_WCSS_UMAC_OFFSET) < WINDOW_RANGE_MASK) { - new_offset = (hal_soc->dev_base_addr + (3 * WINDOW_START) + - (offset & WINDOW_RANGE_MASK)); - /* - * If offset lies within CE register range, use 2nd window to write + * Check if offset lies within CE register range(0x08400000) + * or UMAC/DP register range (0x00A00000). + * If offset lies within CE register range, map it * into CE region. */ - } else if ((offset ^ WFSS_CE_REG_BASE) < WINDOW_RANGE_MASK) { - new_offset = (hal_soc->dev_base_addr + (2 * WINDOW_START) + - (offset & WINDOW_RANGE_MASK)); + if (offset & HOST_CE_MASK_VALUE) { + offset = offset - WFSS_CE_REG_BASE; + new_offset = (hal_soc->dev_base_addr_ce + offset); + + return new_offset; } else { - QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, - "%s: ERROR: Accessing Wrong register\n", __func__); - qdf_assert_always(0); - return 0; + /* + * If offset lies within DP register range, + * return the address as such + */ + return addr; } - return new_offset; } static inline void hal_write_window_register(struct hal_soc *hal_soc) @@ -1955,6 +1954,4 @@ void hal_qca5018_attach(struct hal_soc *hal_soc) hal_soc->hw_srng_table = hw_srng_table_5018; hal_soc->hal_hw_reg_offset = hal_hw_reg_offset_qca5018; hal_soc->ops = &qca5018_hal_hw_txrx_ops; - if (hal_soc->static_window_map) - hal_write_window_register(hal_soc); } diff --git a/hif/inc/hif.h b/hif/inc/hif.h index 38ed6838d4..99b8c1ef81 100644 --- a/hif/inc/hif.h +++ b/hif/inc/hif.h @@ -1309,6 +1309,7 @@ void hif_allow_link_low_power_states(struct hif_opaque_softc *hif) #endif void *hif_get_dev_ba(struct hif_opaque_softc *hif_handle); +void *hif_get_dev_ba_ce(struct hif_opaque_softc *hif_handle); /** * hif_set_initial_wakeup_cb() - set the initial wakeup event handler function diff --git a/hif/inc/reg_struct.h b/hif/inc/reg_struct.h index 422b00146e..25a9de233f 100644 --- a/hif/inc/reg_struct.h +++ b/hif/inc/reg_struct.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2020 The Linux Foundation. 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 @@ -660,6 +660,7 @@ struct ce_reg_def { uint32_t d_HOST_IE_REG1_CE_LSB; uint32_t d_HOST_IE_REG2_CE_LSB; uint32_t d_HOST_IE_REG3_CE_LSB; + uint32_t d_HOST_CE_ADDRESS; }; #endif diff --git a/hif/inc/target_reg_init.h b/hif/inc/target_reg_init.h index 607a5cc1e3..34b8aef24e 100644 --- a/hif/inc/target_reg_init.h +++ b/hif/inc/target_reg_init.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020 The Linux Foundation. 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 @@ -375,6 +375,9 @@ struct targetdef_s *MY_TARGET_DEF = &my_target_def; #if !defined(HOST_IE_REG3_CE_LSB) #define HOST_IE_REG3_CE_LSB 0 #endif +#if !defined(HOST_CE_ADDRESS) +#define HOST_CE_ADDRESS ATH_UNSUPPORTED_REG_OFFSET +#endif static struct ce_reg_def my_ce_reg_def = { /* copy_engine.c */ @@ -460,7 +463,8 @@ static struct ce_reg_def my_ce_reg_def = { .d_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES = A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES, .d_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_STATUS - = A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_STATUS + = A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_STATUS, + .d_HOST_CE_ADDRESS = HOST_CE_ADDRESS }; struct ce_reg_def *MY_CEREG_DEF = &my_ce_reg_def; diff --git a/hif/src/ce/ce_reg.h b/hif/src/ce/ce_reg.h index cb12694f38..d67817a614 100644 --- a/hif/src/ce/ce_reg.h +++ b/hif/src/ce/ce_reg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2020 The Linux Foundation. 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 @@ -210,6 +210,7 @@ #define HOST_IE_ADDRESS_3 (scn->target_ce_def->d_HOST_IE_ADDRESS_3) #define HOST_IE_REG3_CE_LSB (scn->target_ce_def->d_HOST_IE_REG3_CE_LSB) #define HOST_IS_ADDRESS (scn->target_ce_def->d_HOST_IS_ADDRESS) +#define HOST_CE_ADDRESS (scn->target_ce_def->d_HOST_CE_ADDRESS) #define SRC_WATERMARK_LOW_SET(x) \ (((x) << SRC_WATERMARK_LOW_LSB) & SRC_WATERMARK_LOW_MASK) diff --git a/hif/src/hif_main.c b/hif/src/hif_main.c index 421e136cbd..10aeb4db20 100644 --- a/hif/src/hif_main.c +++ b/hif/src/hif_main.c @@ -414,6 +414,21 @@ void *hif_get_dev_ba(struct hif_opaque_softc *hif_handle) } qdf_export_symbol(hif_get_dev_ba); +/** + * hif_get_dev_ba_ce(): API to get device ce base address. + * @scn: scn + * + * Return: dev mem base address for CE + */ +void *hif_get_dev_ba_ce(struct hif_opaque_softc *hif_handle) +{ + struct hif_softc *scn = (struct hif_softc *)hif_handle; + + return scn->mem_ce; +} + +qdf_export_symbol(hif_get_dev_ba_ce); + #ifdef WLAN_CE_INTERRUPT_THRESHOLD_CONFIG /** * hif_get_cfg_from_psoc() - Retrieve ini cfg from psoc diff --git a/hif/src/hif_main.h b/hif/src/hif_main.h index a7de9beb4e..c582df212b 100644 --- a/hif/src/hif_main.h +++ b/hif/src/hif_main.h @@ -173,6 +173,7 @@ struct hif_softc { struct hif_config_info hif_config; struct hif_target_info target_info; void __iomem *mem; + void __iomem *mem_ce; enum qdf_bus_type bus_type; struct hif_bus_ops bus_ops; void *ce_id_to_state[CE_COUNT_MAX]; diff --git a/hif/src/pcie/if_pci.h b/hif/src/pcie/if_pci.h index 76edc18d72..ea18b717dc 100644 --- a/hif/src/pcie/if_pci.h +++ b/hif/src/pcie/if_pci.h @@ -151,6 +151,7 @@ struct hif_pci_stats { struct hif_pci_softc { struct HIF_CE_state ce_sc; void __iomem *mem; /* PCI address. */ + void __iomem *mem_ce; /* PCI address for CE. */ size_t mem_len; struct device *dev; /* For efficiency, should be first in struct */ diff --git a/hif/src/qca5018def.c b/hif/src/qca5018def.c index 069ee044fa..ba8eba31af 100644 --- a/hif/src/qca5018def.c +++ b/hif/src/qca5018def.c @@ -157,17 +157,19 @@ #define HOST_IE_ADDRESS \ HWIO_WFSS_CE_COMMON_R0_CE_HOST_IE_0_ADDR(\ - WFSS_CE_COMMON_REG_REG_BASE) + WFSS_CE_COMMON_REG_REG_BASE_OFFS) #define HOST_IE_REG1_CE_LSB HWIO_WFSS_CE_COMMON_R0_CE_HOST_IE_0_SRC_RING_IE_SHFT #define HOST_IE_ADDRESS_2 \ HWIO_WFSS_CE_COMMON_R0_CE_HOST_IE_1_ADDR(\ - WFSS_CE_COMMON_REG_REG_BASE) + WFSS_CE_COMMON_REG_REG_BASE_OFFS) #define HOST_IE_REG2_CE_LSB HWIO_WFSS_CE_COMMON_R0_CE_HOST_IE_1_STS_RING_IE_SHFT #define HOST_IE_ADDRESS_3 \ HWIO_WFSS_CE_COMMON_R0_CE_HOST_IE_0_ADDR(\ - WFSS_CE_COMMON_REG_REG_BASE) + WFSS_CE_COMMON_REG_REG_BASE_OFFS) #define HOST_IE_REG3_CE_LSB HWIO_WFSS_CE_COMMON_R0_CE_HOST_IE_0_DST_RING_IE_SHFT +#define HOST_CE_ADDRESS WFSS_CE_REG_BASE + #define HOST_IE_COPY_COMPLETE_MASK MISSING #define SR_BA_ADDRESS MISSING #define SR_BA_ADDRESS_HIGH MISSING diff --git a/hif/src/snoc/if_ahb.c b/hif/src/snoc/if_ahb.c index a1c3b1c02b..c3ed8aaec8 100644 --- a/hif/src/snoc/if_ahb.c +++ b/hif/src/snoc/if_ahb.c @@ -495,6 +495,11 @@ void hif_ahb_disable_bus(struct hif_softc *scn) hif_ahb_device_reset(scn); } + if (tgt_info->target_type == TARGET_TYPE_QCA5018) { + iounmap(sc->mem_ce); + sc->mem_ce = NULL; + scn->mem_ce = NULL; + } mem = (void __iomem *)sc->mem; if (mem) { pfrm_devm_iounmap(&pdev->dev, mem); @@ -605,11 +610,25 @@ QDF_STATUS hif_ahb_enable_bus(struct hif_softc *ol_sc, tgt_info->target_type = target_type; hif_register_tbl_attach(ol_sc, hif_type); hif_target_register_tbl_attach(ol_sc, target_type); + /* + * In QCA5018 CE region moved to SOC outside WCSS block. + * Allocate separate I/O remap to access CE registers. + */ + if (tgt_info->target_type == TARGET_TYPE_QCA5018) { + struct hif_softc *scn = HIF_GET_SOFTC(sc); + + sc->mem_ce = ioremap_nocache(HOST_CE_ADDRESS, HOST_CE_SIZE); + if (IS_ERR(sc->mem_ce)) { + HIF_INFO("CE: ioremap failed\n"); + return PTR_ERR(sc->mem_ce); + } + ol_sc->mem_ce = sc->mem_ce; + } if ((tgt_info->target_type != TARGET_TYPE_QCA8074) && - (tgt_info->target_type != TARGET_TYPE_QCA8074V2) && - (tgt_info->target_type != TARGET_TYPE_QCA5018) && - (tgt_info->target_type != TARGET_TYPE_QCA6018)) { + (tgt_info->target_type != TARGET_TYPE_QCA8074V2) && + (tgt_info->target_type != TARGET_TYPE_QCA5018) && + (tgt_info->target_type != TARGET_TYPE_QCA6018)) { if (hif_ahb_enable_radio(sc, pdev, id) != 0) { HIF_INFO("error in enabling soc\n"); return -EIO; @@ -718,22 +737,23 @@ void hif_ahb_irq_enable(struct hif_softc *scn, int ce_id) struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); struct CE_pipe_config *target_ce_conf = &hif_state->target_ce_config[ce_id]; struct hif_target_info *tgt_info = &scn->target_info; + void *mem = scn->mem_ce ? scn->mem_ce : scn->mem; if (scn->per_ce_irq) { if (target_ce_conf->pipedir & PIPEDIR_OUT) { reg_offset = HOST_IE_ADDRESS; qdf_spin_lock_irqsave(&hif_state->irq_reg_lock); - regval = hif_read32_mb(scn, scn->mem + reg_offset); + regval = hif_read32_mb(scn, mem + reg_offset); regval |= HOST_IE_REG1_CE_BIT(ce_id); - hif_write32_mb(scn, scn->mem + reg_offset, regval); + hif_write32_mb(scn, mem + reg_offset, regval); qdf_spin_unlock_irqrestore(&hif_state->irq_reg_lock); } if (target_ce_conf->pipedir & PIPEDIR_IN) { reg_offset = HOST_IE_ADDRESS_2; qdf_spin_lock_irqsave(&hif_state->irq_reg_lock); - regval = hif_read32_mb(scn, scn->mem + reg_offset); + regval = hif_read32_mb(scn, mem + reg_offset); regval |= HOST_IE_REG2_CE_BIT(ce_id); - hif_write32_mb(scn, scn->mem + reg_offset, regval); + hif_write32_mb(scn, mem + reg_offset, regval); if (tgt_info->target_type == TARGET_TYPE_QCA8074 || tgt_info->target_type == TARGET_TYPE_QCA8074V2 || tgt_info->target_type == TARGET_TYPE_QCA5018 || @@ -741,11 +761,11 @@ void hif_ahb_irq_enable(struct hif_softc *scn, int ce_id) /* Enable destination ring interrupts for * 8074, 8074V2, 6018 and 50xx */ - regval = hif_read32_mb(scn, scn->mem + + regval = hif_read32_mb(scn, mem + HOST_IE_ADDRESS_3); regval |= HOST_IE_REG3_CE_BIT(ce_id); - hif_write32_mb(scn, scn->mem + + hif_write32_mb(scn, mem + HOST_IE_ADDRESS_3, regval); } qdf_spin_unlock_irqrestore(&hif_state->irq_reg_lock); @@ -769,22 +789,23 @@ void hif_ahb_irq_disable(struct hif_softc *scn, int ce_id) struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); struct CE_pipe_config *target_ce_conf = &hif_state->target_ce_config[ce_id]; struct hif_target_info *tgt_info = &scn->target_info; + void *mem = scn->mem_ce ? scn->mem_ce : scn->mem; if (scn->per_ce_irq) { if (target_ce_conf->pipedir & PIPEDIR_OUT) { reg_offset = HOST_IE_ADDRESS; qdf_spin_lock_irqsave(&hif_state->irq_reg_lock); - regval = hif_read32_mb(scn, scn->mem + reg_offset); + regval = hif_read32_mb(scn, mem + reg_offset); regval &= ~HOST_IE_REG1_CE_BIT(ce_id); - hif_write32_mb(scn, scn->mem + reg_offset, regval); + hif_write32_mb(scn, mem + reg_offset, regval); qdf_spin_unlock_irqrestore(&hif_state->irq_reg_lock); } if (target_ce_conf->pipedir & PIPEDIR_IN) { reg_offset = HOST_IE_ADDRESS_2; qdf_spin_lock_irqsave(&hif_state->irq_reg_lock); - regval = hif_read32_mb(scn, scn->mem + reg_offset); + regval = hif_read32_mb(scn, mem + reg_offset); regval &= ~HOST_IE_REG2_CE_BIT(ce_id); - hif_write32_mb(scn, scn->mem + reg_offset, regval); + hif_write32_mb(scn, mem + reg_offset, regval); if (tgt_info->target_type == TARGET_TYPE_QCA8074 || tgt_info->target_type == TARGET_TYPE_QCA8074V2 || tgt_info->target_type == TARGET_TYPE_QCA5018 || @@ -792,11 +813,11 @@ void hif_ahb_irq_disable(struct hif_softc *scn, int ce_id) /* Disable destination ring interrupts for * 8074, 8074V2, 6018 and 50xx */ - regval = hif_read32_mb(scn, scn->mem + + regval = hif_read32_mb(scn, mem + HOST_IE_ADDRESS_3); regval &= ~HOST_IE_REG3_CE_BIT(ce_id); - hif_write32_mb(scn, scn->mem + + hif_write32_mb(scn, mem + HOST_IE_ADDRESS_3, regval); } qdf_spin_unlock_irqrestore(&hif_state->irq_reg_lock); diff --git a/hif/src/snoc/if_ahb.h b/hif/src/snoc/if_ahb.h index 6ab4568856..12b9710d02 100644 --- a/hif/src/snoc/if_ahb.h +++ b/hif/src/snoc/if_ahb.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2020 The Linux Foundation. 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 @@ -45,6 +45,7 @@ #define TCSR_WCSS0_HALTACK 0x52010 #define TCSR_WCSS1_HALTACK 0x52014 #define ATH_AHB_RESET_WAIT_MAX 10 /* Ms */ +#define HOST_CE_SIZE 0x200000 irqreturn_t hif_ahb_interrupt_handler(int irq, void *context);