diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2017-02-19 09:46:35 -0800 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-02-19 09:46:35 -0800 |
commit | 3436baed8436f303571ed5dc0027fb9b799915bd (patch) | |
tree | d95095cf58cd939f6d54c826acf0140ef2062067 /drivers | |
parent | 6f0b536eb7c5a7c7e8ae42418ec8e234a61920f1 (diff) | |
parent | bdd8861bc054bec8512cc325becff160d326de34 (diff) |
Merge "ath10k: Add support for shadow register for WNC3990"
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/ath/ath10k/ce.c | 111 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/ce.h | 61 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/core.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/core.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/hw.c | 54 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/hw.h | 57 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/snoc.c | 24 |
7 files changed, 303 insertions, 8 deletions
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index e5213de8a686..7e5e25e96762 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2005-2011 Atheros Communications Inc. - * Copyright (c) 2011-2013 Qualcomm Atheros, Inc. + * Copyright (c) 2011-2013, 2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -90,6 +90,20 @@ static inline u32 ath10k_ce_src_ring_read_index_get(struct ath10k *ar, return ar->bus_read32(ar, ce_ctrl_addr + CURRENT_SRRI_ADDRESS); } +static inline void ath10k_ce_shadow_src_ring_write_index_set(struct ath10k *ar, + u32 ce_ctrl_addr, + unsigned int n) +{ + ar->bus_write32(ar, shadow_sr_wr_ind_addr(ar, ce_ctrl_addr), n); +} + +static inline void ath10k_ce_shadow_dest_ring_write_index_set(struct ath10k *ar, + u32 ce_ctrl_addr, + unsigned int n) +{ + ar->bus_write32(ar, shadow_dst_wr_ind_addr(ar, ce_ctrl_addr), n); +} + static inline void ath10k_ce_src_ring_base_addr_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int addr) @@ -259,6 +273,72 @@ static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar, ar->bus_write32(ar, ce_ctrl_addr + HOST_IS_ADDRESS, mask); } +u32 shadow_sr_wr_ind_addr(struct ath10k *ar, u32 ctrl_addr) +{ + u32 addr = 0; + u32 ce = COPY_ENGINE_ID(ctrl_addr); + + switch (ce) { + case 0: + addr = SHADOW_VALUE0; + break; + case 3: + addr = SHADOW_VALUE3; + break; + case 4: + addr = SHADOW_VALUE4; + break; + case 5: + addr = SHADOW_VALUE5; + break; + case 7: + addr = SHADOW_VALUE7; + break; + default: + ath10k_err(ar, "invalid CE ctrl_addr (CE=%d)", ce); + WARN_ON(1); + } + return addr; +} + +u32 shadow_dst_wr_ind_addr(struct ath10k *ar, u32 ctrl_addr) +{ + u32 addr = 0; + u32 ce = COPY_ENGINE_ID(ctrl_addr); + + switch (ce) { + case 1: + addr = SHADOW_VALUE13; + break; + case 2: + addr = SHADOW_VALUE14; + break; + case 5: + addr = SHADOW_VALUE17; + break; + case 7: + addr = SHADOW_VALUE19; + break; + case 8: + addr = SHADOW_VALUE20; + break; + case 9: + addr = SHADOW_VALUE21; + break; + case 10: + addr = SHADOW_VALUE22; + break; + case 11: + addr = SHADOW_VALUE23; + break; + default: + ath10k_err(ar, "invalid CE ctrl_addr (CE=%d)", ce); + WARN_ON(1); + } + + return addr; +} + /* * Guts of ath10k_ce_send, used by both ath10k_ce_send and * ath10k_ce_sendlist_send. @@ -325,8 +405,14 @@ int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state, write_index = CE_RING_IDX_INCR(nentries_mask, write_index); /* WORKAROUND */ - if (!(flags & CE_SEND_FLAG_GATHER)) - ath10k_ce_src_ring_write_index_set(ar, ctrl_addr, write_index); + if (!(flags & CE_SEND_FLAG_GATHER)) { + if (QCA_REV_WCN3990(ar)) + ath10k_ce_shadow_src_ring_write_index_set(ar, ctrl_addr, + write_index); + else + ath10k_ce_src_ring_write_index_set(ar, ctrl_addr, + write_index); + } src_ring->write_index = write_index; exit: @@ -957,6 +1043,24 @@ ath10k_ce_alloc_src_ring(struct ath10k *ar, unsigned int ce_id, src_ring->base_addr_ce_space_unaligned, CE_DESC_RING_ALIGN); + src_ring->shadow_base_unaligned = kzalloc( + nentries * sizeof(struct ce_desc), + GFP_KERNEL); + + if (!src_ring->shadow_base_unaligned) { + dma_free_coherent(ar->dev, + (nentries * sizeof(struct ce_desc) + + CE_DESC_RING_ALIGN), + src_ring->base_addr_owner_space_unaligned, + base_addr); + kfree(src_ring); + return ERR_PTR(-ENOMEM); + } + + src_ring->shadow_base = (struct ce_desc *)PTR_ALIGN( + src_ring->shadow_base_unaligned, + CE_DESC_RING_ALIGN); + return src_ring; } @@ -1135,6 +1239,7 @@ void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id) ((struct ath10k_ce_pipe *)ar->ce_states + ce_id); if (ce_state->src_ring) { + kfree(ce_state->src_ring->shadow_base_unaligned); dma_free_coherent(ar->dev, (ce_state->src_ring->nentries * sizeof(struct ce_desc) + diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index 1b49db14d387..160a13e681df 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -120,6 +120,9 @@ struct ath10k_ce_ring { /* CE address space */ u32 base_addr_ce_space; + char *shadow_base_unaligned; + struct ce_desc *shadow_base; + /* keep last */ void *per_transfer_context[0]; }; @@ -143,6 +146,61 @@ struct ath10k_ce_pipe { /* Copy Engine settable attributes */ struct ce_attr; +#define SHADOW_VALUE0 (ar->shadow_reg_value->shadow_reg_value_0) +#define SHADOW_VALUE1 (ar->shadow_reg_value->shadow_reg_value_1) +#define SHADOW_VALUE2 (ar->shadow_reg_value->shadow_reg_value_2) +#define SHADOW_VALUE3 (ar->shadow_reg_value->shadow_reg_value_3) +#define SHADOW_VALUE4 (ar->shadow_reg_value->shadow_reg_value_4) +#define SHADOW_VALUE5 (ar->shadow_reg_value->shadow_reg_value_5) +#define SHADOW_VALUE6 (ar->shadow_reg_value->shadow_reg_value_6) +#define SHADOW_VALUE7 (ar->shadow_reg_value->shadow_reg_value_7) +#define SHADOW_VALUE8 (ar->shadow_reg_value->shadow_reg_value_8) +#define SHADOW_VALUE9 (ar->shadow_reg_value->shadow_reg_value_9) +#define SHADOW_VALUE10 (ar->shadow_reg_value->shadow_reg_value_10) +#define SHADOW_VALUE11 (ar->shadow_reg_value->shadow_reg_value_11) +#define SHADOW_VALUE12 (ar->shadow_reg_value->shadow_reg_value_12) +#define SHADOW_VALUE13 (ar->shadow_reg_value->shadow_reg_value_13) +#define SHADOW_VALUE14 (ar->shadow_reg_value->shadow_reg_value_14) +#define SHADOW_VALUE15 (ar->shadow_reg_value->shadow_reg_value_15) +#define SHADOW_VALUE16 (ar->shadow_reg_value->shadow_reg_value_16) +#define SHADOW_VALUE17 (ar->shadow_reg_value->shadow_reg_value_17) +#define SHADOW_VALUE18 (ar->shadow_reg_value->shadow_reg_value_18) +#define SHADOW_VALUE19 (ar->shadow_reg_value->shadow_reg_value_19) +#define SHADOW_VALUE20 (ar->shadow_reg_value->shadow_reg_value_20) +#define SHADOW_VALUE21 (ar->shadow_reg_value->shadow_reg_value_21) +#define SHADOW_VALUE22 (ar->shadow_reg_value->shadow_reg_value_22) +#define SHADOW_VALUE23 (ar->shadow_reg_value->shadow_reg_value_23) +#define SHADOW_ADDRESS0 (ar->shadow_reg_address->shadow_reg_address_0) +#define SHADOW_ADDRESS1 (ar->shadow_reg_address->shadow_reg_address_1) +#define SHADOW_ADDRESS2 (ar->shadow_reg_address->shadow_reg_address_2) +#define SHADOW_ADDRESS3 (ar->shadow_reg_address->shadow_reg_address_3) +#define SHADOW_ADDRESS4 (ar->shadow_reg_address->shadow_reg_address_4) +#define SHADOW_ADDRESS5 (ar->shadow_reg_address->shadow_reg_address_5) +#define SHADOW_ADDRESS6 (ar->shadow_reg_address->shadow_reg_address_6) +#define SHADOW_ADDRESS7 (ar->shadow_reg_address->shadow_reg_address_7) +#define SHADOW_ADDRESS8 (ar->shadow_reg_address->shadow_reg_address_8) +#define SHADOW_ADDRESS9 (ar->shadow_reg_address->shadow_reg_address_9) +#define SHADOW_ADDRESS10 (ar->shadow_reg_address->shadow_reg_address_10) +#define SHADOW_ADDRESS11 (ar->shadow_reg_address->shadow_reg_address_11) +#define SHADOW_ADDRESS12 (ar->shadow_reg_address->shadow_reg_address_12) +#define SHADOW_ADDRESS13 (ar->shadow_reg_address->shadow_reg_address_13) +#define SHADOW_ADDRESS14 (ar->shadow_reg_address->shadow_reg_address_14) +#define SHADOW_ADDRESS15 (ar->shadow_reg_address->shadow_reg_address_15) +#define SHADOW_ADDRESS16 (ar->shadow_reg_address->shadow_reg_address_16) +#define SHADOW_ADDRESS17 (ar->shadow_reg_address->shadow_reg_address_17) +#define SHADOW_ADDRESS18 (ar->shadow_reg_address->shadow_reg_address_18) +#define SHADOW_ADDRESS19 (ar->shadow_reg_address->shadow_reg_address_19) +#define SHADOW_ADDRESS20 (ar->shadow_reg_address->shadow_reg_address_20) +#define SHADOW_ADDRESS21 (ar->shadow_reg_address->shadow_reg_address_21) +#define SHADOW_ADDRESS22 (ar->shadow_reg_address->shadow_reg_address_22) +#define SHADOW_ADDRESS23 (ar->shadow_reg_address->shadow_reg_address_23) + +#define SHADOW_ADDRESS(i) (SHADOW_ADDRESS0 + \ + i * (SHADOW_ADDRESS1 - SHADOW_ADDRESS0)) + +u32 shadow_sr_wr_ind_addr(struct ath10k *ar, u32 ctrl_addr); +u32 shadow_dst_wr_ind_addr(struct ath10k *ar, u32 ctrl_addr); + /*==================Send====================*/ /* ath10k_ce_send flags */ @@ -591,6 +649,9 @@ struct ce_attr { & (uint64_t)(0xF00000000)) >> 32)) #endif +#define COPY_ENGINE_ID(COPY_ENGINE_BASE_ADDRESS) ((COPY_ENGINE_BASE_ADDRESS \ + - CE0_BASE_ADDRESS) / (CE1_BASE_ADDRESS - CE0_BASE_ADDRESS)) + static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id) { return CE0_BASE_ADDRESS + (CE1_BASE_ADDRESS - CE0_BASE_ADDRESS) * ce_id; diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 0803a963da3c..052ebd7dd26b 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -2350,6 +2350,8 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, /* WCN3990 chip set is non bmi based */ ar->is_bmi = false; ar->fw_flags = &wcn3990_fw_flags; + ar->shadow_reg_value = &wcn3990_shadow_reg_value; + ar->shadow_reg_address = &wcn3990_shadow_reg_address; break; default: ath10k_err(ar, "unsupported core hardware revision %d\n", diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index f2f0338696e0..bb2c5fb9a125 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -741,6 +741,8 @@ struct ath10k { const struct ath10k_hw_regs *regs; const struct ath10k_hw_values *hw_values; + struct ath10k_shadow_reg_value *shadow_reg_value; + struct ath10k_shadow_reg_address *shadow_reg_address; struct ath10k_bmi bmi; struct ath10k_wmi wmi; struct ath10k_htc htc; diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c index 0cd1068b0beb..1a8f3a388ce2 100644 --- a/drivers/net/wireless/ath/ath10k/hw.c +++ b/drivers/net/wireless/ath/ath10k/hw.c @@ -220,6 +220,60 @@ struct fw_flag wcn3990_fw_flags = { .flags = 0x82E, }; +struct ath10k_shadow_reg_value wcn3990_shadow_reg_value = { + .shadow_reg_value_0 = 0x00032000, + .shadow_reg_value_1 = 0x00032004, + .shadow_reg_value_2 = 0x00032008, + .shadow_reg_value_3 = 0x0003200C, + .shadow_reg_value_4 = 0x00032010, + .shadow_reg_value_5 = 0x00032014, + .shadow_reg_value_6 = 0x00032018, + .shadow_reg_value_7 = 0x0003201C, + .shadow_reg_value_8 = 0x00032020, + .shadow_reg_value_9 = 0x00032024, + .shadow_reg_value_10 = 0x00032028, + .shadow_reg_value_11 = 0x0003202C, + .shadow_reg_value_12 = 0x00032030, + .shadow_reg_value_13 = 0x00032034, + .shadow_reg_value_14 = 0x00032038, + .shadow_reg_value_15 = 0x0003203C, + .shadow_reg_value_16 = 0x00032040, + .shadow_reg_value_17 = 0x00032044, + .shadow_reg_value_18 = 0x00032048, + .shadow_reg_value_19 = 0x0003204C, + .shadow_reg_value_20 = 0x00032050, + .shadow_reg_value_21 = 0x00032054, + .shadow_reg_value_22 = 0x00032058, + .shadow_reg_value_23 = 0x0003205C +}; + +struct ath10k_shadow_reg_address wcn3990_shadow_reg_address = { + .shadow_reg_address_0 = 0x00030020, + .shadow_reg_address_1 = 0x00030024, + .shadow_reg_address_2 = 0x00030028, + .shadow_reg_address_3 = 0x0003002C, + .shadow_reg_address_4 = 0x00030030, + .shadow_reg_address_5 = 0x00030034, + .shadow_reg_address_6 = 0x00030038, + .shadow_reg_address_7 = 0x0003003C, + .shadow_reg_address_8 = 0x00030040, + .shadow_reg_address_9 = 0x00030044, + .shadow_reg_address_10 = 0x00030048, + .shadow_reg_address_11 = 0x0003004C, + .shadow_reg_address_12 = 0x00030050, + .shadow_reg_address_13 = 0x00030054, + .shadow_reg_address_14 = 0x00030058, + .shadow_reg_address_15 = 0x0003005C, + .shadow_reg_address_16 = 0x00030060, + .shadow_reg_address_17 = 0x00030064, + .shadow_reg_address_18 = 0x00030068, + .shadow_reg_address_19 = 0x0003006C, + .shadow_reg_address_20 = 0x00030070, + .shadow_reg_address_21 = 0x00030074, + .shadow_reg_address_22 = 0x00030078, + .shadow_reg_address_23 = 0x0003007C +}; + void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev) { diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index b59bde40714c..ce87f8112928 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -835,4 +835,61 @@ ath10k_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw, #define RTC_STATE_V_GET(x) (((x) & RTC_STATE_V_MASK) >> RTC_STATE_V_LSB) +struct ath10k_shadow_reg_value { + u32 shadow_reg_value_0; + u32 shadow_reg_value_1; + u32 shadow_reg_value_2; + u32 shadow_reg_value_3; + u32 shadow_reg_value_4; + u32 shadow_reg_value_5; + u32 shadow_reg_value_6; + u32 shadow_reg_value_7; + u32 shadow_reg_value_8; + u32 shadow_reg_value_9; + u32 shadow_reg_value_10; + u32 shadow_reg_value_11; + u32 shadow_reg_value_12; + u32 shadow_reg_value_13; + u32 shadow_reg_value_14; + u32 shadow_reg_value_15; + u32 shadow_reg_value_16; + u32 shadow_reg_value_17; + u32 shadow_reg_value_18; + u32 shadow_reg_value_19; + u32 shadow_reg_value_20; + u32 shadow_reg_value_21; + u32 shadow_reg_value_22; + u32 shadow_reg_value_23; +}; + +struct ath10k_shadow_reg_address { + u32 shadow_reg_address_0; + u32 shadow_reg_address_1; + u32 shadow_reg_address_2; + u32 shadow_reg_address_3; + u32 shadow_reg_address_4; + u32 shadow_reg_address_5; + u32 shadow_reg_address_6; + u32 shadow_reg_address_7; + u32 shadow_reg_address_8; + u32 shadow_reg_address_9; + u32 shadow_reg_address_10; + u32 shadow_reg_address_11; + u32 shadow_reg_address_12; + u32 shadow_reg_address_13; + u32 shadow_reg_address_14; + u32 shadow_reg_address_15; + u32 shadow_reg_address_16; + u32 shadow_reg_address_17; + u32 shadow_reg_address_18; + u32 shadow_reg_address_19; + u32 shadow_reg_address_20; + u32 shadow_reg_address_21; + u32 shadow_reg_address_22; + u32 shadow_reg_address_23; +}; + +extern struct ath10k_shadow_reg_value wcn3990_shadow_reg_value; +extern struct ath10k_shadow_reg_address wcn3990_shadow_reg_address; + #endif /* _HW_H_ */ diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c index be8ec97574f0..6c8797d5e5fc 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.c +++ b/drivers/net/wireless/ath/ath10k/snoc.c @@ -395,10 +395,23 @@ static struct service_to_pipe target_service_to_ce_map_wlan[] = { }, }; -#define ADRASTEA_SRC_WR_INDEX_OFFSET 0x3C -#define ADRASTEA_DST_WR_INDEX_OFFSET 0x40 - -static struct ath10k_shadow_reg_cfg target_shadow_reg_cfg_map[] = { }; +#define WCN3990_SRC_WR_INDEX_OFFSET 0x3C +#define WCN3990_DST_WR_INDEX_OFFSET 0x40 + +static struct ath10k_shadow_reg_cfg target_shadow_reg_cfg_map[] = { + { 0, WCN3990_SRC_WR_INDEX_OFFSET}, + { 3, WCN3990_SRC_WR_INDEX_OFFSET}, + { 4, WCN3990_SRC_WR_INDEX_OFFSET}, + { 5, WCN3990_SRC_WR_INDEX_OFFSET}, + { 7, WCN3990_SRC_WR_INDEX_OFFSET}, + { 1, WCN3990_DST_WR_INDEX_OFFSET}, + { 2, WCN3990_DST_WR_INDEX_OFFSET}, + { 7, WCN3990_DST_WR_INDEX_OFFSET}, + { 8, WCN3990_DST_WR_INDEX_OFFSET}, + { 9, WCN3990_DST_WR_INDEX_OFFSET}, + { 10, WCN3990_DST_WR_INDEX_OFFSET}, + { 11, WCN3990_DST_WR_INDEX_OFFSET}, +}; void ath10k_snoc_write32(void *ar, u32 offset, u32 value) { @@ -1048,7 +1061,8 @@ static int ath10k_snoc_wlan_enable(struct ath10k *ar) sizeof(struct ce_svc_pipe_cfg); cfg.ce_svc_cfg = (struct ce_svc_pipe_cfg *) &target_service_to_ce_map_wlan; - cfg.num_shadow_reg_cfg = sizeof(target_shadow_reg_cfg_map); + cfg.num_shadow_reg_cfg = sizeof(target_shadow_reg_cfg_map) / + sizeof(struct icnss_shadow_reg_cfg); cfg.shadow_reg_cfg = (struct icnss_shadow_reg_cfg *) &target_shadow_reg_cfg_map; |