diff --git a/hif/inc/hif.h b/hif/inc/hif.h index 7277c86c82..58e4c2ad7d 100644 --- a/hif/inc/hif.h +++ b/hif/inc/hif.h @@ -72,6 +72,9 @@ typedef void *hif_handle_t; #define TARGET_TYPE_AR9888 7 #define TARGET_TYPE_AR6320 8 #define TARGET_TYPE_AR900B 9 +#define TARGET_TYPE_QCA9984 10 +#define TARGET_TYPE_IPQ4019 11 +#define TARGET_TYPE_QCA9888 12 /* For attach Peregrine 2.0 board target_reg_tbl only */ #define TARGET_TYPE_AR9888V2 13 /* For attach Rome1.0 target_reg_tbl only*/ @@ -555,6 +558,9 @@ int hif_send_single(struct hif_opaque_softc *osc, qdf_nbuf_t msdu, uint32_t int hif_send_fast(struct hif_opaque_softc *osc, qdf_nbuf_t *nbuf_arr, uint32_t num_msdus, uint32_t transfer_id); void hif_pkt_dl_len_set(void *hif_sc, unsigned int pkt_download_len); +void hif_ce_war_disable(void); +void hif_ce_war_enable(void); + #ifdef __cplusplus } #endif diff --git a/hif/src/ce/ce_assignment.h b/hif/src/ce/ce_assignment.h index 9bfce43c0b..dcb78c8f2a 100644 --- a/hif/src/ce/ce_assignment.h +++ b/hif/src/ce/ce_assignment.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -33,6 +33,12 @@ #ifndef __HIF_PCI_INTERNAL_H__ #define __HIF_PCI_INTERNAL_H__ +#ifndef CONFIG_WIN +#ifndef PEER_CACHEING_HOST_ENABLE +#define PEER_CACHEING_HOST_ENABLE 0 +#endif +#endif + #define HIF_PCI_DEBUG ATH_DEBUG_MAKE_MODULE_MASK(0) #define HIF_PCI_IPA_UC_ASSIGNED_CE 5 @@ -313,6 +319,85 @@ static struct CE_pipe_config target_ce_config_wlan_epping[] = { }; #endif +static struct CE_attr host_ce_config_wlan_ar9888[] = { + { /* CE0 */ CE_ATTR_FLAGS, 0, 16, 256, 0, NULL, }, /* host->target HTC control and raw streams */ + /* could be moved to share CE3 */ + { /* CE1 */ CE_ATTR_FLAGS, 0, 0, 512, 512, NULL, },/* target->host BMI + HTC control */ + { /* CE2 */ CE_ATTR_FLAGS, 0, 0, 2048, 128, NULL, },/* target->host WMI */ + { /* CE3 */ CE_ATTR_FLAGS, 0, 32, 2048, 0, NULL, },/* host->target WMI */ + { /* CE4 */ CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR, 0, + CE_HTT_H2T_MSG_SRC_NENTRIES, 256, 0, NULL, }, /* host->target HTT */ +#if WLAN_FEATURE_FASTPATH + { /* CE5 */ CE_ATTR_FLAGS, 0, 0, 512, 512, NULL, }, /* target->host HTT messages */ +#else /* WLAN_FEATURE_FASTPATH */ + { /* CE5 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL, }, /* unused */ +#endif /* WLAN_FEATURE_FASTPATH */ + { /* CE6 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL, }, /* Target autonomous HIF_memcpy */ + { /* CE7 */ CE_ATTR_FLAGS, 0, 2, DIAG_TRANSFER_LIMIT, 2, NULL, }, /* ce_diag, the Diagnostic Window */ + { /* CE8 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL, }, /* Target autonomous HIF_memcpy */ +}; + +static struct CE_attr host_ce_config_wlan_ar900b[] = { + { /* CE0 */ CE_ATTR_FLAGS, 0, 16, 256, 0, NULL, }, /* host->target HTC control and raw streams */ + /* could be moved to share CE3 */ + { /* CE1 */ CE_ATTR_FLAGS, 0, 0, 512, 512, NULL, },/* target->host BMI + HTC control */ + { /* CE2 */ CE_ATTR_FLAGS, 0, 0, 2048, 128, NULL, },/* target->host WMI */ + { /* CE3 */ CE_ATTR_FLAGS, 0, 32, 2048, 0, NULL, },/* host->target WMI */ + { /* CE4 */ CE_ATTR_FLAGS | CE_ATTR_DISABLE_INTR, 0, + CE_HTT_H2T_MSG_SRC_NENTRIES, 256, 0, NULL, }, /* host->target HTT */ +#if WLAN_FEATURE_FASTPATH + { /* CE5 */ CE_ATTR_FLAGS, 0, 0, 512, 512, NULL, }, /* target->host HTT messages */ +#else /* WLAN_FEATURE_FASTPATH */ + { /* CE5 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL, }, /* unused */ +#endif /* WLAN_FEATURE_FASTPATH */ + { /* CE6 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL, }, /* Target autonomous HIF_memcpy */ + { /* CE7 */ CE_ATTR_FLAGS, 0, 2, DIAG_TRANSFER_LIMIT, 2, NULL, }, /* ce_diag, the Diagnostic Window */ + { /* CE8 */ CE_ATTR_FLAGS, 0, 0, 2048, 128, NULL, },/* target->host pktlog */ + { /* CE9 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL, }, /* Target autonomous HIF_memcpy */ + { /* CE10 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL, }, /* Target autonomous HIF_memcpy */ + { /* CE11 */ CE_ATTR_FLAGS, 0, 0, 0, 0, NULL, }, /* Target autonomous HIF_memcpy */ +}; + +static struct CE_pipe_config target_ce_config_wlan_ar9888[] = { + { /* CE0 */ 0, PIPEDIR_OUT, 32, 256, CE_ATTR_FLAGS, 0, }, /* host->target HTC control and raw streams */ + { /* CE1 */ 1, PIPEDIR_IN, 32, 512, CE_ATTR_FLAGS, 0, }, /* target->host HTC control */ + { /* CE2 */ 2, PIPEDIR_IN, 64, 2048, CE_ATTR_FLAGS, 0, }, /* target->host WMI */ + { /* CE3 */ 3, PIPEDIR_OUT, 32, 2048, CE_ATTR_FLAGS, 0, }, /* host->target WMI */ + { /* CE4 */ 4, PIPEDIR_OUT, 256, 256, CE_ATTR_FLAGS, 0, }, /* host->target HTT */ + /* NB: 50% of src nentries, since tx has 2 frags */ +#if WLAN_FEATURE_FASTPATH + { /* CE5 */ 5, PIPEDIR_IN, 32, 512, CE_ATTR_FLAGS, 0, }, /* target->host HTT */ +#else + { /* CE5 */ 5, PIPEDIR_OUT, 32, 2048, CE_ATTR_FLAGS, 0, }, /* unused */ +#endif + { /* CE6 */ 6, PIPEDIR_INOUT, 32, 4096, CE_ATTR_FLAGS, 0, },/* Reserved for target autonomous HIF_memcpy */ + /* CE7 used only by Host */ +}; + +static struct CE_pipe_config target_ce_config_wlan_ar900b[] = { + { /* CE0 */ 0, PIPEDIR_OUT, 32, 256, CE_ATTR_FLAGS, 0, }, /* host->target HTC control and raw streams */ + { /* CE1 */ 1, PIPEDIR_IN, 32, 512, CE_ATTR_FLAGS, 0, }, /* target->host HTC control */ + { /* CE2 */ 2, PIPEDIR_IN, 64, 2048, CE_ATTR_FLAGS, 0, }, /* target->host WMI */ + { /* CE3 */ 3, PIPEDIR_OUT, 32, 2048, CE_ATTR_FLAGS, 0, }, /* host->target WMI */ + { /* CE4 */ 4, PIPEDIR_OUT, 256, 256, CE_ATTR_FLAGS, 0, }, /* host->target HTT */ + /* NB: 50% of src nentries, since tx has 2 frags */ +#if WLAN_FEATURE_FASTPATH + { /* CE5 */ 5, PIPEDIR_IN, 32, 512, CE_ATTR_FLAGS, 0, }, /* target->host HTT */ +#else + { /* CE5 */ 5, PIPEDIR_OUT, 32, 2048, CE_ATTR_FLAGS, 0, }, /* unused */ +#endif + { /* CE6 */ 6, PIPEDIR_INOUT, 32, 4096, CE_ATTR_FLAGS, 0, },/* Reserved for target autonomous HIF_memcpy */ + { /* CE7 */ 7, PIPEDIR_INOUT, 0, 0, 0, 0, }, /* CE7 used only by Host */ + { /* CE8 */ 8, PIPEDIR_IN, 64, 2048, CE_ATTR_FLAGS + | CE_ATTR_DISABLE_INTR, 0, }, /* target->host packtlog */ +#if PEER_CACHEING_HOST_ENABLE + { /* CE9 */ 9, PIPEDIR_INOUT, 32, 2048, CE_ATTR_FLAGS | + CE_ATTR_DISABLE_INTR, 0, }, /* target autonomous qcache memcpy */ +#endif +}; + + + static struct CE_attr *host_ce_config = host_ce_config_wlan; static struct CE_pipe_config *target_ce_config = target_ce_config_wlan; static int target_ce_config_sz = sizeof(target_ce_config_wlan); diff --git a/hif/src/ce/ce_diag.c b/hif/src/ce/ce_diag.c index ead738709e..6fee451e05 100644 --- a/hif/src/ce/ce_diag.c +++ b/hif/src/ce/ce_diag.c @@ -82,20 +82,77 @@ hif_dump_target_memory(struct hif_opaque_softc *hif_ctx, void *ramdump_base, (SOC_CORE_BASE_ADDRESS|CORE_CTRL_ADDRESS)) & 0x7ff) << 21) \ | 0x100000 | ((addr) & 0xfffff)) #endif + +#define TARG_CPU_SPACE_TO_CE_SPACE_IPQ4019(pci_addr, addr) \ + (hif_read32_mb((pci_addr)+(WIFICMN_PCIE_BAR_REG_ADDRESS)) \ + | ((addr) & 0xfffff)) + +#define TARG_CPU_SPACE_TO_CE_SPACE_AR900B(pci_addr, addr) \ + (hif_read32_mb((pci_addr)+(WIFICMN_PCIE_BAR_REG_ADDRESS)) \ + | 0x100000 | ((addr) & 0xfffff)) + +#define SRAM_BASE_ADDRESS 0xc0000 +#define SRAM_END_ADDRESS 0x100000 +#define WIFI0_IPQ4019_BAR 0xa000000 +#define WIFI1_IPQ4019_BAR 0xa800000 + /* Wait up to this many Ms for a Diagnostic Access CE operation to complete */ #define DIAG_ACCESS_CE_TIMEOUT_MS 10 +/** + * get_ce_phy_addr() - get the physical address of an soc virtual address + * @sc: hif context + * @address: soc virtual address + * @target_type: target type being used. + * + * Return: soc physical address + */ +qdf_dma_addr_t get_ce_phy_addr(struct hif_softc *sc, uint32_t address, + unsigned int target_type) +{ + qdf_dma_addr_t ce_phy_addr; + struct hif_softc *scn = sc; + unsigned int region = address & 0xfffff; + unsigned int bar = address & 0xfff00000; + unsigned int sramregion = 0; + + if ((target_type == TARGET_TYPE_IPQ4019) && + (region >= SRAM_BASE_ADDRESS && region <= SRAM_END_ADDRESS) + && (bar == WIFI0_IPQ4019_BAR || + bar == WIFI1_IPQ4019_BAR || bar == 0)) { + sramregion = 1; + } + + if ((target_type == TARGET_TYPE_IPQ4019) && sramregion == 1) { + ce_phy_addr = + TARG_CPU_SPACE_TO_CE_SPACE_IPQ4019(sc->mem, address); + } else if ((target_type == TARGET_TYPE_AR900B) || + (target_type == TARGET_TYPE_QCA9984) || + (target_type == TARGET_TYPE_IPQ4019) || + (target_type == TARGET_TYPE_QCA9888)) { + ce_phy_addr = + TARG_CPU_SPACE_TO_CE_SPACE_AR900B(sc->mem, address); + } else { + ce_phy_addr = + TARG_CPU_SPACE_TO_CE_SPACE(sc->mem, address); + } + + return ce_phy_addr; +} + /* * Diagnostic read/write access is provided for startup/config/debug usage. * Caller must guarantee proper alignment, when applicable, and single user * at any moment. */ -QDF_STATUS -hif_diag_read_mem(struct hif_opaque_softc *hif_ctx, uint32_t address, - uint8_t *data, int nbytes) +#define FW_SRAM_ADDRESS 0x000C0000 + +QDF_STATUS hif_diag_read_mem(struct hif_opaque_softc *hif_ctx, + uint32_t address, uint8_t *data, int nbytes) { struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); + struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); QDF_STATUS status = QDF_STATUS_SUCCESS; qdf_dma_addr_t buf; @@ -112,18 +169,30 @@ hif_diag_read_mem(struct hif_opaque_softc *hif_ctx, uint32_t address, qdf_dma_addr_t ce_phy_addr = address; unsigned int toeplitz_hash_result; unsigned int user_flags = 0; + unsigned int target_type = 0; + unsigned int boundary_addr = 0; transaction_id = (mux_id & MUX_ID_MASK) | (transaction_id & TRANSACTION_ID_MASK); #ifdef QCA_WIFI_3_0 user_flags &= DESC_DATA_FLAG_MASK; #endif + target_type = (hif_get_target_info_handle(hif_ctx))->target_type; /* This code cannot handle reads to non-memory space. Redirect to the * register read fn but preserve the multi word read capability of * this fn */ - if (address < DRAM_BASE_ADDRESS) { + if ((target_type == TARGET_TYPE_IPQ4019) || + (target_type == TARGET_TYPE_AR900B) || + (target_type == TARGET_TYPE_QCA9984) || + (target_type == TARGET_TYPE_IPQ4019) || + (target_type == TARGET_TYPE_QCA9888)) + boundary_addr = FW_SRAM_ADDRESS; + else + boundary_addr = DRAM_BASE_ADDRESS; + + if (address < boundary_addr) { if ((address & 0x3) || ((uintptr_t) data & 0x3)) return QDF_STATUS_E_INVAL; @@ -172,31 +241,21 @@ hif_diag_read_mem(struct hif_opaque_softc *hif_ctx, uint32_t address, goto done; } - { /* Request CE to send from Target(!) - * address to Host buffer */ - /* - * The address supplied by the caller is in the - * Target CPU virtual address space. - * - * In order to use this address with the diagnostic CE, - * convert it from - * Target CPU virtual address space - * to - * CE address space - */ - if (Q_TARGET_ACCESS_BEGIN(scn) < 0) - return QDF_STATUS_E_FAILURE; - ce_phy_addr = - TARG_CPU_SPACE_TO_CE_SPACE(scn->mem, address); - if (Q_TARGET_ACCESS_END(scn) < 0) - return QDF_STATUS_E_FAILURE; + if (Q_TARGET_ACCESS_BEGIN(scn) < 0) + return QDF_STATUS_E_FAILURE; - status = - ce_send(ce_diag, NULL, ce_phy_addr, nbytes, - transaction_id, 0, user_flags); - if (status != QDF_STATUS_SUCCESS) - goto done; - } + /* convert soc virtual address to physical address */ + ce_phy_addr = get_ce_phy_addr(scn, address, target_type); + + if (Q_TARGET_ACCESS_END(scn) < 0) + return QDF_STATUS_E_FAILURE; + + /* Request CE to send from Target(!) + * address to Host buffer */ + status = ce_send(ce_diag, NULL, ce_phy_addr, nbytes, + transaction_id, 0, user_flags); + if (status != QDF_STATUS_SUCCESS) + goto done; i = 0; while (ce_completed_send_next(ce_diag, NULL, NULL, &buf, @@ -278,6 +337,13 @@ QDF_STATUS hif_diag_read_access(struct hif_opaque_softc *hif_ctx, } } +/** + * hif_diag_write_mem() - write data into the soc memory + * @hif_ctx: hif context + * @address: soc virtual address + * @data: data to copy into the soc address + * @nbytes: number of bytes to coppy + */ QDF_STATUS hif_diag_write_mem(struct hif_opaque_softc *hif_ctx, uint32_t address, uint8_t *data, int nbytes) { @@ -298,7 +364,7 @@ QDF_STATUS hif_diag_write_mem(struct hif_opaque_softc *hif_ctx, qdf_dma_addr_t ce_phy_addr = address; unsigned int toeplitz_hash_result; unsigned int user_flags = 0; - + unsigned int target_type = 0; ce_diag = hif_state->ce_diag; transaction_id = (mux_id & MUX_ID_MASK) | (transaction_id & TRANSACTION_ID_MASK); @@ -327,19 +393,14 @@ QDF_STATUS hif_diag_write_mem(struct hif_opaque_softc *hif_ctx, qdf_mem_dma_sync_single_for_device(scn->qdf_dev, CE_data_base, orig_nbytes, DMA_TO_DEVICE); - /* - * The address supplied by the caller is in the - * Target CPU virtual address space. - * - * In order to use this address with the diagnostic CE, - * convert it from - * Target CPU virtual address space - * to - * CE address space - */ + target_type = (hif_get_target_info_handle(hif_ctx))->target_type; + if (Q_TARGET_ACCESS_BEGIN(scn) < 0) return QDF_STATUS_E_FAILURE; - ce_phy_addr = TARG_CPU_SPACE_TO_CE_SPACE(scn->mem, address); + + /* convert soc virtual address to physical address */ + ce_phy_addr = get_ce_phy_addr(scn, address, target_type); + if (Q_TARGET_ACCESS_END(scn) < 0) return QDF_STATUS_E_FAILURE; @@ -348,26 +409,22 @@ QDF_STATUS hif_diag_write_mem(struct hif_opaque_softc *hif_ctx, while (remaining_bytes) { nbytes = min(remaining_bytes, DIAG_TRANSFER_LIMIT); - { /* Set up to receive directly into Target(!) address */ - status = ce_recv_buf_enqueue(ce_diag, - NULL, ce_phy_addr); - if (status != QDF_STATUS_SUCCESS) - goto done; - } + /* Set up to receive directly into Target(!) address */ + status = ce_recv_buf_enqueue(ce_diag, NULL, ce_phy_addr); + if (status != QDF_STATUS_SUCCESS) + goto done; - { - /* - * Request CE to send caller-supplied data that - * was copied to bounce buffer to Target(!) address. - */ - status = - ce_send(ce_diag, NULL, - (qdf_dma_addr_t) CE_data, nbytes, - transaction_id, 0, user_flags); - if (status != QDF_STATUS_SUCCESS) - goto done; - } + /* + * Request CE to send caller-supplied data that + * was copied to bounce buffer to Target(!) address. + */ + status = ce_send(ce_diag, NULL, (qdf_dma_addr_t) CE_data, + nbytes, transaction_id, 0, user_flags); + if (status != QDF_STATUS_SUCCESS) + goto done; + + /* poll for transfer complete */ i = 0; while (ce_completed_send_next(ce_diag, NULL, NULL, &buf, &completed_nbytes, &id, diff --git a/hif/src/ce/ce_internal.h b/hif/src/ce/ce_internal.h index 4df0ec0e37..e9d25758db 100644 --- a/hif/src/ce/ce_internal.h +++ b/hif/src/ce/ce_internal.h @@ -152,6 +152,7 @@ struct CE_state { /* Descriptor rings must be aligned to this boundary */ #define CE_DESC_RING_ALIGN 8 +#define CLOCK_OVERRIDE 0x2 #ifdef QCA_WIFI_3_0 #define HIF_CE_DESC_ADDR_TO_DMA(desc) \ diff --git a/hif/src/ce/ce_main.c b/hif/src/ce/ce_main.c index 88ef77b5bf..95b07423f7 100644 --- a/hif/src/ce/ce_main.c +++ b/hif/src/ce/ce_main.c @@ -310,6 +310,106 @@ static struct service_to_pipe target_service_to_ce_map_wlan[] = { }, }; +static struct service_to_pipe target_service_to_ce_map_ar900b[] = { + { + WMI_DATA_VO_SVC, + PIPEDIR_OUT, /* out = UL = host -> target */ + 3, + }, + { + WMI_DATA_VO_SVC, + PIPEDIR_IN, /* in = DL = target -> host */ + 2, + }, + { + WMI_DATA_BK_SVC, + PIPEDIR_OUT, /* out = UL = host -> target */ + 3, + }, + { + WMI_DATA_BK_SVC, + PIPEDIR_IN, /* in = DL = target -> host */ + 2, + }, + { + WMI_DATA_BE_SVC, + PIPEDIR_OUT, /* out = UL = host -> target */ + 3, + }, + { + WMI_DATA_BE_SVC, + PIPEDIR_IN, /* in = DL = target -> host */ + 2, + }, + { + WMI_DATA_VI_SVC, + PIPEDIR_OUT, /* out = UL = host -> target */ + 3, + }, + { + WMI_DATA_VI_SVC, + PIPEDIR_IN, /* in = DL = target -> host */ + 2, + }, + { + WMI_CONTROL_SVC, + PIPEDIR_OUT, /* out = UL = host -> target */ + 3, + }, + { + WMI_CONTROL_SVC, + PIPEDIR_IN, /* in = DL = target -> host */ + 2, + }, + { + HTC_CTRL_RSVD_SVC, + PIPEDIR_OUT, /* out = UL = host -> target */ + 0, /* could be moved to 3 (share with WMI) */ + }, + { + HTC_CTRL_RSVD_SVC, + PIPEDIR_IN, /* in = DL = target -> host */ + 1, + }, + { + HTC_RAW_STREAMS_SVC, /* not currently used */ + PIPEDIR_OUT, /* out = UL = host -> target */ + 0, + }, + { + HTC_RAW_STREAMS_SVC, /* not currently used */ + PIPEDIR_IN, /* in = DL = target -> host */ + 1, + }, + { + HTT_DATA_MSG_SVC, + PIPEDIR_OUT, /* out = UL = host -> target */ + 4, + }, +#if WLAN_FEATURE_FASTPATH + { + HTT_DATA_MSG_SVC, + PIPEDIR_IN, /* in = DL = target -> host */ + 5, + }, +#else /* WLAN_FEATURE_FASTPATH */ + { + HTT_DATA_MSG_SVC, + PIPEDIR_IN, /* in = DL = target -> host */ + 1, + }, +#endif /* WLAN_FEATURE_FASTPATH */ + + /* (Additions here) */ + + { /* Must be last */ + 0, + 0, + 0, + }, +}; + + static struct service_to_pipe *target_service_to_ce_map = target_service_to_ce_map_wlan; static int target_service_to_ce_map_sz = sizeof(target_service_to_ce_map_wlan); @@ -355,6 +455,8 @@ bool ce_mark_datapath(struct CE_state *ce_state) size_t map_sz; int i; bool rc = false; + struct hif_opaque_softc *hif_hdl = GET_HIF_OPAQUE_HDL(ce_state->scn); + struct hif_target_info *tgt_info = hif_get_target_info_handle(hif_hdl); if (ce_state != NULL) { if (QDF_IS_EPPING_ENABLED(hif_get_conparam(ce_state->scn))) { @@ -362,9 +464,25 @@ bool ce_mark_datapath(struct CE_state *ce_state) map_sz = sizeof(target_service_to_ce_map_wlan_epping) / sizeof(struct service_to_pipe); } else { - svc_map = target_service_to_ce_map_wlan; - map_sz = sizeof(target_service_to_ce_map_wlan) / - sizeof(struct service_to_pipe); + switch (tgt_info->target_type) { + default: + svc_map = target_service_to_ce_map_wlan; + map_sz = + sizeof(target_service_to_ce_map_wlan) / + sizeof(struct service_to_pipe); + break; + case TARGET_TYPE_AR900B: + case TARGET_TYPE_QCA9984: + case TARGET_TYPE_IPQ4019: + case TARGET_TYPE_QCA9888: + case TARGET_TYPE_AR9888: + case TARGET_TYPE_AR9888V2: + svc_map = target_service_to_ce_map_ar900b; + map_sz = + sizeof(target_service_to_ce_map_ar900b) + / sizeof(struct service_to_pipe); + break; + } } for (i = 0; i < map_sz; i++) { if ((svc_map[i].pipenum == ce_state->id) && @@ -1788,6 +1906,9 @@ int hif_wlan_enable(struct hif_softc *scn) void hif_ce_prepare_config(struct hif_softc *scn) { uint32_t mode = hif_get_conparam(scn); + struct hif_opaque_softc *hif_hdl = GET_HIF_OPAQUE_HDL(scn); + struct hif_target_info *tgt_info = hif_get_target_info_handle(hif_hdl); + /* if epping is enabled we need to use the epping configuration. */ if (QDF_IS_EPPING_ENABLED(mode)) { if (CE_EPPING_USES_IRQ) @@ -1803,6 +1924,34 @@ void hif_ce_prepare_config(struct hif_softc *scn) target_shadow_reg_cfg = target_shadow_reg_cfg_epping; shadow_cfg_sz = sizeof(target_shadow_reg_cfg_epping); } + + switch (tgt_info->target_type) { + default: + break; + case TARGET_TYPE_AR900B: + case TARGET_TYPE_QCA9984: + case TARGET_TYPE_IPQ4019: + case TARGET_TYPE_QCA9888: + host_ce_config = host_ce_config_wlan_ar900b; + target_ce_config = target_ce_config_wlan_ar900b; + target_ce_config_sz = sizeof(target_ce_config_wlan_ar900b); + + target_service_to_ce_map = target_service_to_ce_map_ar900b; + target_service_to_ce_map_sz = + sizeof(target_service_to_ce_map_ar900b); + break; + + case TARGET_TYPE_AR9888: + case TARGET_TYPE_AR9888V2: + host_ce_config = host_ce_config_wlan_ar9888; + target_ce_config = target_ce_config_wlan_ar9888; + target_ce_config_sz = sizeof(target_ce_config_wlan_ar9888); + + target_service_to_ce_map = target_service_to_ce_map_ar900b; + target_service_to_ce_map_sz = + sizeof(target_service_to_ce_map_ar900b); + break; + } } /** @@ -2287,6 +2436,7 @@ int hif_map_service_to_pipe(struct hif_opaque_softc *hif_hdl, uint16_t svc_id, size_t sz_tgt_svc_map_to_use; struct hif_softc *scn = HIF_GET_SOFTC(hif_hdl); uint32_t mode = hif_get_conparam(scn); + struct hif_target_info *tgt_info = hif_get_target_info_handle(hif_hdl); bool dl_updated = false; bool ul_updated = false; @@ -2295,8 +2445,23 @@ int hif_map_service_to_pipe(struct hif_opaque_softc *hif_hdl, uint16_t svc_id, sz_tgt_svc_map_to_use = sizeof(target_service_to_ce_map_wlan_epping); } else { - tgt_svc_map_to_use = target_service_to_ce_map_wlan; - sz_tgt_svc_map_to_use = sizeof(target_service_to_ce_map_wlan); + switch (tgt_info->target_type) { + default: + tgt_svc_map_to_use = target_service_to_ce_map_wlan; + sz_tgt_svc_map_to_use = + sizeof(target_service_to_ce_map_wlan); + break; + case TARGET_TYPE_AR900B: + case TARGET_TYPE_QCA9984: + case TARGET_TYPE_IPQ4019: + case TARGET_TYPE_QCA9888: + case TARGET_TYPE_AR9888: + case TARGET_TYPE_AR9888V2: + tgt_svc_map_to_use = target_service_to_ce_map_ar900b; + sz_tgt_svc_map_to_use = + sizeof(target_service_to_ce_map_ar900b); + break; + } } *dl_is_polled = 0; /* polling for received messages not supported */ diff --git a/hif/src/ce/ce_service.c b/hif/src/ce/ce_service.c index ae4d643bad..98ac3965f2 100644 --- a/hif/src/ce/ce_service.c +++ b/hif/src/ce/ce_service.c @@ -72,6 +72,22 @@ static int war1_allow_sleep; /* io32 write workaround */ static int hif_ce_war1; +/** + * hif_ce_war_disable() - disable ce war gobally + */ +void hif_ce_war_disable(void) +{ + hif_ce_war1 = 0; +} + +/** + * hif_ce_war_enable() - enable ce war gobally + */ +void hif_ce_war_enable(void) +{ + hif_ce_war1 = 1; +} + #ifdef CONFIG_SLUB_DEBUG_ON /** @@ -257,8 +273,9 @@ void war_ce_src_ring_write_idx_set(struct hif_softc *scn, hif_write32_mb(indicator_addr, 0); local_irq_restore(irq_flags); } - } else + } else { CE_SRC_RING_WRITE_IDX_SET(scn, ctrl_addr, write_index); + } } int diff --git a/hif/src/hif_main.c b/hif/src/hif_main.c index 03c9f76a31..8510537e43 100644 --- a/hif/src/hif_main.c +++ b/hif/src/hif_main.c @@ -296,6 +296,15 @@ uint32_t hif_hia_item_address(uint32_t target_type, uint32_t item_offset) /* ADRASTEA doesn't have a host interest address */ ASSERT(0); return 0; + case TARGET_TYPE_AR900B: + return AR900B_HOST_INTEREST_ADDRESS + item_offset; + case TARGET_TYPE_QCA9984: + return QCA9984_HOST_INTEREST_ADDRESS + item_offset; + case TARGET_TYPE_QCA9888: + return QCA9888_HOST_INTEREST_ADDRESS + item_offset; + case TARGET_TYPE_IPQ4019: + return IPQ4019_HOST_INTEREST_ADDRESS + item_offset; + default: ASSERT(0); return 0; @@ -771,6 +780,30 @@ int hif_get_device_type(uint32_t device_id, } break; + case AR9887_DEVICE_ID: + *hif_type = HIF_TYPE_AR9888; + *target_type = TARGET_TYPE_AR9888; + HIF_INFO(" *********** AR9887 **************\n"); + break; + + case QCA9984_DEVICE_ID: + *hif_type = HIF_TYPE_QCA9984; + *target_type = TARGET_TYPE_QCA9984; + HIF_INFO(" *********** QCA9984 *************\n"); + break; + + case QCA9888_DEVICE_ID: + *hif_type = HIF_TYPE_QCA9888; + *target_type = TARGET_TYPE_QCA9888; + HIF_INFO(" *********** QCA9888 *************\n"); + break; + + case AR900B_DEVICE_ID: + *hif_type = HIF_TYPE_AR900B; + *target_type = TARGET_TYPE_AR900B; + HIF_INFO(" *********** AR900B *************\n"); + break; + default: HIF_ERROR("%s: Unsupported device ID!", __func__); ret = -ENODEV; diff --git a/hif/src/hif_main.h b/hif/src/hif_main.h index 7ec86768f3..4f7c297e29 100644 --- a/hif/src/hif_main.h +++ b/hif/src/hif_main.h @@ -86,6 +86,10 @@ #define AR6320_FW_3_2 (0x32) #define ADRASTEA_DEVICE_ID (0xabcd) #define ADRASTEA_DEVICE_ID_P2_E12 (0x7021) +#define AR9887_DEVICE_ID (0x0050) +#define AR900B_DEVICE_ID (0x0040) +#define QCA9984_DEVICE_ID (0x0046) +#define QCA9888_DEVICE_ID (0x0056) #define HIF_GET_PCI_SOFTC(scn) ((struct hif_pci_softc *)scn) #define HIF_GET_CE_STATE(scn) ((struct HIF_CE_state *)scn) diff --git a/hif/src/pcie/if_pci.c b/hif/src/pcie/if_pci.c index ec8d72f305..70135a7663 100644 --- a/hif/src/pcie/if_pci.c +++ b/hif/src/pcie/if_pci.c @@ -72,6 +72,11 @@ * use TargetCPU warm reset * instead of SOC_GLOBAL_RESET */ #define CPU_WARM_RESET_WAR + +#ifdef CONFIG_WIN +extern int32_t frac, intval, ar900b_20_targ_clk, qca9888_20_targ_clk; +#endif + /* * Top-level interrupt handler for all PCI interrupts from a Target. * When a block of MSI interrupts is allocated, this top-level handler @@ -1458,6 +1463,149 @@ static void hif_sleep_entry(void *arg) #define HIF_HIA_MAX_POLL_LOOP 1000000 #define HIF_HIA_POLLING_DELAY_MS 10 +#ifdef CONFIG_WIN +void hif_set_hia_extnd(struct hif_softc *scn) +{ + struct hif_opaque_softc *hif_hdl = GET_HIF_OPAQUE_HDL(scn); + struct hif_target_info *tgt_info = hif_get_target_info_handle(hif_hdl); + uint32_t target_type = tgt_info->target_type; + + HIF_TRACE("%s: E", __func__); + + if ((target_type == TARGET_TYPE_AR900B) || + target_type == TARGET_TYPE_QCA9984 || + target_type == TARGET_TYPE_QCA9888) { + /* CHIP revision is 8-11 bits of the CHIP_ID register 0xec + in RTC space */ + tgt_info->target_revision + = CHIP_ID_REVISION_GET(hif_read32_mb(scn->mem + + CHIP_ID_ADDRESS)); + qdf_print(KERN_INFO"chip_id 0x%x chip_revision 0x%x\n", + target_type, tgt_info->target_revision); + } + + { + uint32_t flag2_value = 0; + uint32_t flag2_targ_addr = + host_interest_item_address(target_type, + offsetof(struct host_interest_s, hi_skip_clock_init)); + + if ((ar900b_20_targ_clk != -1) && + (frac != -1) && (intval != -1)) { + hif_diag_read_access(hif_hdl, flag2_targ_addr, + &flag2_value); + qdf_print("\n Setting clk_override\n"); + flag2_value |= CLOCK_OVERRIDE; + + hif_diag_write_access(hif_hdl, flag2_targ_addr, + flag2_value); + qdf_print("\n CLOCK PLL val set %d\n", flag2_value); + } else { + qdf_print(KERN_INFO"\n CLOCK PLL skipped\n"); + } + } + + if (target_type == TARGET_TYPE_AR900B + || target_type == TARGET_TYPE_QCA9984 + || target_type == TARGET_TYPE_QCA9888) { + + /* for AR9980_2.0, 300 mhz clock is used, right now we assume + * this would be supplied through module parameters, + * if not supplied assumed default or same behavior as 1.0. + * Assume 1.0 clock can't be tuned, reset to defaults + */ + + qdf_print(KERN_INFO"%s: setting the target pll frac %x intval %x\n", + __func__, frac, intval); + + /* do not touch frac, and int val, let them be default -1, + * if desired, host can supply these through module params + */ + if (frac != -1 || intval != -1) { + uint32_t flag2_value = 0; + uint32_t flag2_targ_addr; + + flag2_targ_addr = + host_interest_item_address(target_type, + offsetof(struct host_interest_s, + hi_clock_info)); + hif_diag_read_access(hif_hdl, + flag2_targ_addr, &flag2_value); + qdf_print("\n ====> FRAC Val %x Address %x\n", frac, + flag2_value); + hif_diag_write_access(hif_hdl, flag2_value, frac); + qdf_print("\n INT Val %x Address %x\n", + intval, flag2_value + 4); + hif_diag_write_access(hif_hdl, + flag2_value + 4, intval); + } else { + qdf_print(KERN_INFO"%s: no frac provided, skipping pre-configuring PLL\n", + __func__); + } + + /* for 2.0 write 300 mhz into hi_desired_cpu_speed_hz */ + if ((target_type == TARGET_TYPE_AR900B) + && (tgt_info->target_revision == AR900B_REV_2) + && ar900b_20_targ_clk != -1) { + uint32_t flag2_value = 0; + uint32_t flag2_targ_addr; + + flag2_targ_addr + = host_interest_item_address(target_type, + offsetof(struct host_interest_s, + hi_desired_cpu_speed_hz)); + hif_diag_read_access(hif_hdl, flag2_targ_addr, + &flag2_value); + qdf_print("\n ====> hi_desired_cpu_speed_hz Address %x\n", + flag2_value); + hif_diag_write_access(hif_hdl, flag2_value, + ar900b_20_targ_clk/*300000000u*/); + } else if (target_type == TARGET_TYPE_QCA9888) { + uint32_t flag2_targ_addr; + + if (200000000u != qca9888_20_targ_clk) { + qca9888_20_targ_clk = 300000000u; + /* Setting the target clock speed to 300 mhz */ + } + + flag2_targ_addr + = host_interest_item_address(target_type, + offsetof(struct host_interest_s, + hi_desired_cpu_speed_hz)); + hif_diag_write_access(hif_hdl, flag2_targ_addr, + qca9888_20_targ_clk); + } else { + qdf_print(KERN_INFO"%s: targ_clk is not provided, skipping pre-configuring PLL\n", + __func__); + } + } else { + if (frac != -1 || intval != -1) { + uint32_t flag2_value = 0; + uint32_t flag2_targ_addr = + host_interest_item_address(target_type, + offsetof(struct host_interest_s, + hi_clock_info)); + hif_diag_read_access(hif_hdl, flag2_targ_addr, + &flag2_value); + qdf_print("\n ====> FRAC Val %x Address %x\n", frac, + flag2_value); + hif_diag_write_access(hif_hdl, flag2_value, frac); + qdf_print("\n INT Val %x Address %x\n", intval, + flag2_value + 4); + hif_diag_write_access(hif_hdl, flag2_value + 4, + intval); + } + } +} + +#else + +void hif_set_hia_extnd(struct hif_softc *scn) +{ +} + +#endif + /** * hif_set_hia() - fill out the host interest area * @scn: hif context @@ -1704,6 +1852,12 @@ int hif_set_hia(struct hif_softc *scn) goto done; } #endif + if ((target_type == TARGET_TYPE_AR900B) + || (target_type == TARGET_TYPE_QCA9984) + || (target_type == TARGET_TYPE_QCA9888) + || (target_type == TARGET_TYPE_QCA9888)) { + hif_set_hia_extnd(scn); + } /* Tell Target to proceed with initialization */ flag2_targ_addr = hif_hia_item_address(target_type, @@ -1743,6 +1897,8 @@ int hif_pci_bus_configure(struct hif_softc *hif_sc) { int status = 0; struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(hif_sc); + struct hif_opaque_softc *hif_hdl = GET_HIF_OPAQUE_HDL(hif_sc); + struct hif_target_info *tgt_info = hif_get_target_info_handle(hif_hdl); hif_ce_prepare_config(hif_sc); @@ -1772,10 +1928,12 @@ int hif_pci_bus_configure(struct hif_softc *hif_sc) if (CONFIG_ATH_PCIE_MAX_PERF || CONFIG_ATH_PCIE_AWAKE_WHILE_DRIVER_LOAD) { /* Force AWAKE forever/till the driver is loaded */ - if (hif_pci_target_sleep_state_adjust(hif_sc, false, true) - < 0) { - status = -EACCES; - goto disable_wlan; + if (tgt_info->target_type != TARGET_TYPE_IPQ4019) { + if (hif_pci_target_sleep_state_adjust(hif_sc, + false, true) < 0) { + status = -EACCES; + goto disable_wlan; + } } } @@ -2184,9 +2342,10 @@ static int hif_pci_configure_legacy_irq(struct hif_pci_softc *sc) hif_write32_mb(sc->mem+(SOC_CORE_BASE_ADDRESS | PCIE_INTR_ENABLE_ADDRESS), HOST_GROUP0_MASK); + hif_read32_mb(sc->mem+(SOC_CORE_BASE_ADDRESS | + PCIE_INTR_ENABLE_ADDRESS)); hif_write32_mb(sc->mem + PCIE_LOCAL_BASE_ADDRESS + - PCIE_SOC_WAKE_ADDRESS, - PCIE_SOC_WAKE_RESET); + PCIE_SOC_WAKE_ADDRESS, PCIE_SOC_WAKE_RESET); end: QDF_TRACE(QDF_MODULE_ID_HIF, QDF_TRACE_LEVEL_ERROR, "%s: X, ret = %d", __func__, ret); diff --git a/htc/htc_api.h b/htc/htc_api.h index de00e37502..a667a1de09 100644 --- a/htc/htc_api.h +++ b/htc/htc_api.h @@ -711,6 +711,8 @@ void *htc_get_targetdef(HTC_HANDLE htc_handle); int htc_runtime_suspend(HTC_HANDLE htc_ctx); int htc_runtime_resume(HTC_HANDLE htc_ctx); #endif +void htc_global_credit_flow_disable(void); +void htc_global_credit_flow_enable(void); /* Disable ASPM : Disable PCIe low power */ bool htc_can_suspend_link(HTC_HANDLE HTCHandle); diff --git a/htc/htc_services.c b/htc/htc_services.c index 57be7cf350..396eb3fb6c 100644 --- a/htc/htc_services.c +++ b/htc/htc_services.c @@ -36,6 +36,18 @@ unsigned int htc_credit_flow = 1; #define DEBUG_CREDIT 0 #endif +/* HTC credit flow global disable */ +void htc_global_credit_flow_disable(void) +{ + htc_credit_flow = 0; +} + +/* HTC credit flow global enable */ +void htc_global_credit_flow_enable(void) +{ + htc_credit_flow = 1; +} + A_STATUS htc_connect_service(HTC_HANDLE HTCHandle, HTC_SERVICE_CONNECT_REQ *pConnectReq, HTC_SERVICE_CONNECT_RESP *pConnectResp)