Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | /* SPDX-License-Identifier: BSD-3-Clause-Clear */ /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. */ #ifndef ATH11K_CE_H #define ATH11K_CE_H #define CE_COUNT_MAX 12 /* Byte swap data words */ #define CE_ATTR_BYTE_SWAP_DATA 2 /* no interrupt on copy completion */ #define CE_ATTR_DIS_INTR 8 /* Host software's Copy Engine configuration. */ #ifdef __BIG_ENDIAN #define CE_ATTR_FLAGS CE_ATTR_BYTE_SWAP_DATA #else #define CE_ATTR_FLAGS 0 #endif /* Threshold to poll for tx completion in case of Interrupt disabled CE's */ #define ATH11K_CE_USAGE_THRESHOLD 32 void ath11k_ce_byte_swap(void *mem, u32 len); /* * Directions for interconnect pipe configuration. * These definitions may be used during configuration and are shared * between Host and Target. * * Pipe Directions are relative to the Host, so PIPEDIR_IN means * "coming IN over air through Target to Host" as with a WiFi Rx operation. * Conversely, PIPEDIR_OUT means "going OUT from Host through Target over air" * as with a WiFi Tx operation. This is somewhat awkward for the "middle-man" * Target since things that are "PIPEDIR_OUT" are coming IN to the Target * over the interconnect. */ #define PIPEDIR_NONE 0 #define PIPEDIR_IN 1 /* Target-->Host, WiFi Rx direction */ #define PIPEDIR_OUT 2 /* Host->Target, WiFi Tx direction */ #define PIPEDIR_INOUT 3 /* bidirectional */ #define PIPEDIR_INOUT_H2H 4 /* bidirectional, host to host */ /* CE address/mask */ #define CE_HOST_IE_ADDRESS 0x00A1803C #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)) #define ATH11K_CE_RX_POST_RETRY_JIFFIES 50 struct ath11k_base; /* * Establish a mapping between a service/direction and a pipe. * Configuration information for a Copy Engine pipe and services. * Passed from Host to Target through QMI message and must be in * little endian format. */ struct service_to_pipe { __le32 service_id; __le32 pipedir; __le32 pipenum; }; /* * Configuration information for a Copy Engine pipe. * Passed from Host to Target through QMI message during startup (one per CE). * * NOTE: Structure is shared between Host software and Target firmware! */ struct ce_pipe_config { __le32 pipenum; __le32 pipedir; __le32 nentries; __le32 nbytes_max; __le32 flags; __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; /* #entries in source ring - Must be a power of 2 */ unsigned int src_nentries; /* * Max source send size for this CE. * This is also the minimum size of a destination buffer. */ unsigned int src_sz_max; /* #entries in destination ring - Must be a power of 2 */ unsigned int dest_nentries; void (*recv_cb)(struct ath11k_base *, struct sk_buff *); void (*send_cb)(struct ath11k_base *, struct sk_buff *); }; #define CE_DESC_RING_ALIGN 8 struct ath11k_ce_ring { /* Number of entries in this ring; must be power of 2 */ unsigned int nentries; unsigned int nentries_mask; /* For dest ring, this is the next index to be processed * by software after it was/is received into. * * For src ring, this is the last descriptor that was sent * and completion processed by software. * * Regardless of src or dest ring, this is an invariant * (modulo ring size): * write index >= read index >= sw_index */ unsigned int sw_index; /* cached copy */ unsigned int write_index; /* Start of DMA-coherent area reserved for descriptors */ /* Host address space */ void *base_addr_owner_space_unaligned; /* CE address space */ u32 base_addr_ce_space_unaligned; /* Actual start of descriptors. * Aligned to descriptor-size boundary. * Points into reserved DMA-coherent area, above. */ /* Host address space */ void *base_addr_owner_space; /* CE address space */ u32 base_addr_ce_space; /* HAL ring id */ u32 hal_ring_id; /* keep last */ struct sk_buff *skb[]; }; struct ath11k_ce_pipe { struct ath11k_base *ab; u16 pipe_num; unsigned int attr_flags; unsigned int buf_sz; unsigned int rx_buf_needed; void (*send_cb)(struct ath11k_base *, struct sk_buff *); void (*recv_cb)(struct ath11k_base *, struct sk_buff *); struct tasklet_struct intr_tq; struct ath11k_ce_ring *src_ring; struct ath11k_ce_ring *dest_ring; struct ath11k_ce_ring *status_ring; u64 timestamp; }; struct ath11k_ce { struct ath11k_ce_pipe ce_pipe[CE_COUNT_MAX]; /* Protects rings of all ce pipes */ spinlock_t ce_lock; struct ath11k_hp_update_timer hp_timer[CE_COUNT_MAX]; }; extern const struct ce_attr ath11k_host_ce_config_ipq8074[]; extern const struct ce_attr ath11k_host_ce_config_qca6390[]; extern const struct ce_attr ath11k_host_ce_config_qcn9074[]; void ath11k_ce_cleanup_pipes(struct ath11k_base *ab); void ath11k_ce_rx_replenish_retry(struct timer_list *t); void ath11k_ce_per_engine_service(struct ath11k_base *ab, u16 ce_id); int ath11k_ce_send(struct ath11k_base *ab, struct sk_buff *skb, u8 pipe_id, u16 transfer_id); void ath11k_ce_rx_post_buf(struct ath11k_base *ab); int ath11k_ce_init_pipes(struct ath11k_base *ab); int ath11k_ce_alloc_pipes(struct ath11k_base *ab); void ath11k_ce_free_pipes(struct ath11k_base *ab); int ath11k_ce_get_attr_flags(struct ath11k_base *ab, int ce_id); void ath11k_ce_poll_send_completed(struct ath11k_base *ab, u8 pipe_id); void ath11k_ce_get_shadow_config(struct ath11k_base *ab, u32 **shadow_cfg, u32 *shadow_cfg_len); void ath11k_ce_stop_shadow_timers(struct ath11k_base *ab); #endif |