1 /* 2 * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above 10 * copyright notice, this list of conditions and the following 11 * disclaimer in the documentation and/or other materials provided 12 * with the distribution. 13 * * Neither the name of The Linux Foundation nor the names of its 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include "hal_api.h" 31 #include "target_type.h" 32 #include "wcss_version.h" 33 #include "qdf_module.h" 34 35 /** 36 * Common SRNG register access macros: 37 * The SRNG registers are distributed across various UMAC and LMAC HW blocks, 38 * but the register group and format is exactly same for all rings, with some 39 * difference between producer rings (these are 'producer rings' with respect 40 * to HW and referred as 'destination rings' in SW) and consumer rings (these 41 * are 'consumer rings' with respect to HW and referred as 'source rings' in SW). 42 * The following macros provide uniform access to all SRNG rings. 43 */ 44 45 /* SRNG registers are split among two groups R0 and R2 and following 46 * definitions identify the group to which each register belongs to 47 */ 48 #define R0_INDEX 0 49 #define R2_INDEX 1 50 51 #define HWREG_INDEX(_reg_group) _reg_group ## _ ## INDEX 52 53 /* Registers in R0 group */ 54 #define BASE_LSB_GROUP R0 55 #define BASE_MSB_GROUP R0 56 #define ID_GROUP R0 57 #define STATUS_GROUP R0 58 #define MISC_GROUP R0 59 #define HP_ADDR_LSB_GROUP R0 60 #define HP_ADDR_MSB_GROUP R0 61 #define PRODUCER_INT_SETUP_GROUP R0 62 #define PRODUCER_INT_STATUS_GROUP R0 63 #define PRODUCER_FULL_COUNTER_GROUP R0 64 #define MSI1_BASE_LSB_GROUP R0 65 #define MSI1_BASE_MSB_GROUP R0 66 #define MSI1_DATA_GROUP R0 67 #define HP_TP_SW_OFFSET_GROUP R0 68 #define TP_ADDR_LSB_GROUP R0 69 #define TP_ADDR_MSB_GROUP R0 70 #define CONSUMER_INT_SETUP_IX0_GROUP R0 71 #define CONSUMER_INT_SETUP_IX1_GROUP R0 72 #define CONSUMER_INT_STATUS_GROUP R0 73 #define CONSUMER_EMPTY_COUNTER_GROUP R0 74 #define CONSUMER_PREFETCH_TIMER_GROUP R0 75 #define CONSUMER_PREFETCH_STATUS_GROUP R0 76 77 /* Registers in R2 group */ 78 #define HP_GROUP R2 79 #define TP_GROUP R2 80 81 /** 82 * Register definitions for all SRNG based rings are same, except few 83 * differences between source (HW consumer) and destination (HW producer) 84 * registers. Following macros definitions provide generic access to all 85 * SRNG based rings. 86 * For source rings, we will use the register/field definitions of SW2TCL1 87 * ring defined in the HW header file mac_tcl_reg_seq_hwioreg.h. To setup 88 * individual fields, SRNG_SM macros should be used with fields specified 89 * using SRNG_SRC_FLD(<register>, <field>), Register writes should be done 90 * using SRNG_SRC_REG_WRITE(<hal_srng>, <register>, <value>). 91 * Similarly for destination rings we will use definitions of REO2SW1 ring 92 * defined in the register reo_destination_ring.h. To setup individual 93 * fields SRNG_SM macros should be used with fields specified using 94 * SRNG_DST_FLD(<register>, <field>). Register writes should be done using 95 * SRNG_DST_REG_WRITE(<hal_srng>, <register>, <value>). 96 */ 97 98 #define SRNG_DST_REG_OFFSET(_reg, _reg_group) \ 99 HWIO_REO_ ## _reg_group ## _REO2SW1_RING_ ## _reg##_ADDR(0) 100 101 #define SRNG_SRC_REG_OFFSET(_reg, _reg_group) \ 102 HWIO_TCL_ ## _reg_group ## _SW2TCL1_RING_ ## _reg ## _ADDR(0) 103 104 #define _SRNG_DST_FLD(_reg_group, _reg_fld) \ 105 HWIO_REO_ ## _reg_group ## _REO2SW1_RING_ ## _reg_fld 106 #define _SRNG_SRC_FLD(_reg_group, _reg_fld) \ 107 HWIO_TCL_ ## _reg_group ## _SW2TCL1_RING_ ## _reg_fld 108 109 #define _SRNG_FLD(_reg_group, _reg_fld, _dir) \ 110 _SRNG_ ## _dir ## _FLD(_reg_group, _reg_fld) 111 112 #define SRNG_DST_FLD(_reg, _f) _SRNG_FLD(_reg ## _GROUP, _reg ## _ ## _f, DST) 113 #define SRNG_SRC_FLD(_reg, _f) _SRNG_FLD(_reg ## _GROUP, _reg ## _ ## _f, SRC) 114 115 #define SRNG_SRC_R0_START_OFFSET SRNG_SRC_REG_OFFSET(BASE_LSB, R0) 116 #define SRNG_DST_R0_START_OFFSET SRNG_DST_REG_OFFSET(BASE_LSB, R0) 117 118 #define SRNG_SRC_R2_START_OFFSET SRNG_SRC_REG_OFFSET(HP, R2) 119 #define SRNG_DST_R2_START_OFFSET SRNG_DST_REG_OFFSET(HP, R2) 120 121 #define SRNG_SRC_START_OFFSET(_reg_group) \ 122 SRNG_SRC_ ## _reg_group ## _START_OFFSET 123 #define SRNG_DST_START_OFFSET(_reg_group) \ 124 SRNG_DST_ ## _reg_group ## _START_OFFSET 125 126 #define SRNG_REG_ADDR(_srng, _reg, _reg_group, _dir) \ 127 ((_srng)->hwreg_base[HWREG_INDEX(_reg_group)] + \ 128 SRNG_ ## _dir ## _REG_OFFSET(_reg, _reg_group) - \ 129 SRNG_ ## _dir ## _START_OFFSET(_reg_group)) 130 131 #define SRNG_DST_ADDR(_srng, _reg) \ 132 SRNG_REG_ADDR(_srng, _reg, _reg ## _GROUP, DST) 133 134 #define SRNG_SRC_ADDR(_srng, _reg) \ 135 SRNG_REG_ADDR(_srng, _reg, _reg ## _GROUP, SRC) 136 137 #define SRNG_REG_WRITE(_srng, _reg, _value, _dir) \ 138 hal_write_address_32_mb(_srng->hal_soc, SRNG_ ## _dir ## _ADDR(_srng, _reg), (_value)) 139 140 #define SRNG_REG_READ(_srng, _reg, _dir) \ 141 hal_read_address_32_mb(_srng->hal_soc, SRNG_ ## _dir ## _ADDR(_srng, _reg)) 142 143 #define SRNG_SRC_REG_WRITE(_srng, _reg, _value) \ 144 SRNG_REG_WRITE(_srng, _reg, _value, SRC) 145 146 #define SRNG_DST_REG_WRITE(_srng, _reg, _value) \ 147 SRNG_REG_WRITE(_srng, _reg, _value, DST) 148 149 #define SRNG_SRC_REG_READ(_srng, _reg) \ 150 SRNG_REG_READ(_srng, _reg, SRC) 151 152 #define _SRNG_FM(_reg_fld) _reg_fld ## _BMSK 153 #define _SRNG_FS(_reg_fld) _reg_fld ## _SHFT 154 155 #define SRNG_SM(_reg_fld, _val) \ 156 (((_val) << _SRNG_FS(_reg_fld)) & _SRNG_FM(_reg_fld)) 157 158 #define SRNG_MS(_reg_fld, _val) \ 159 (((_val) & _SRNG_FM(_reg_fld)) >> _SRNG_FS(_reg_fld)) 160 161 #define SRNG_MAX_SIZE_DWORDS \ 162 (SRNG_MS(SRNG_SRC_FLD(BASE_MSB, RING_SIZE), 0xffffffff)) 163 164 /** 165 * HW ring configuration table to identify hardware ring attributes like 166 * register addresses, number of rings, ring entry size etc., for each type 167 * of SRNG ring. 168 * 169 * Currently there is just one HW ring table, but there could be multiple 170 * configurations in future based on HW variants from the same wifi3.0 family 171 * and hence need to be attached with hal_soc based on HW type 172 */ 173 #define HAL_SRNG_CONFIG(_hal_soc, _ring_type) (&hw_srng_table[_ring_type]) 174 static struct hal_hw_srng_config hw_srng_table[] = { 175 /* TODO: max_rings can populated by querying HW capabilities */ 176 { /* REO_DST */ 177 .start_ring_id = HAL_SRNG_REO2SW1, 178 .max_rings = 4, 179 .entry_size = sizeof(struct reo_destination_ring) >> 2, 180 .lmac_ring = FALSE, 181 .ring_dir = HAL_SRNG_DST_RING, 182 .reg_start = { 183 HWIO_REO_R0_REO2SW1_RING_BASE_LSB_ADDR( 184 SEQ_WCSS_UMAC_REO_REG_OFFSET), 185 HWIO_REO_R2_REO2SW1_RING_HP_ADDR( 186 SEQ_WCSS_UMAC_REO_REG_OFFSET) 187 }, 188 .reg_size = { 189 HWIO_REO_R0_REO2SW2_RING_BASE_LSB_ADDR(0) - 190 HWIO_REO_R0_REO2SW1_RING_BASE_LSB_ADDR(0), 191 HWIO_REO_R2_REO2SW2_RING_HP_ADDR(0) - 192 HWIO_REO_R2_REO2SW1_RING_HP_ADDR(0), 193 }, 194 }, 195 { /* REO_EXCEPTION */ 196 /* Designating REO2TCL ring as exception ring. This ring is 197 * similar to other REO2SW rings though it is named as REO2TCL. 198 * Any of theREO2SW rings can be used as exception ring. 199 */ 200 .start_ring_id = HAL_SRNG_REO2TCL, 201 .max_rings = 1, 202 .entry_size = sizeof(struct reo_destination_ring) >> 2, 203 .lmac_ring = FALSE, 204 .ring_dir = HAL_SRNG_DST_RING, 205 .reg_start = { 206 HWIO_REO_R0_REO2TCL_RING_BASE_LSB_ADDR( 207 SEQ_WCSS_UMAC_REO_REG_OFFSET), 208 HWIO_REO_R2_REO2TCL_RING_HP_ADDR( 209 SEQ_WCSS_UMAC_REO_REG_OFFSET) 210 }, 211 /* Single ring - provide ring size if multiple rings of this 212 * type are supported */ 213 .reg_size = {}, 214 }, 215 { /* REO_REINJECT */ 216 .start_ring_id = HAL_SRNG_SW2REO, 217 .max_rings = 1, 218 .entry_size = sizeof(struct reo_entrance_ring) >> 2, 219 .lmac_ring = FALSE, 220 .ring_dir = HAL_SRNG_SRC_RING, 221 .reg_start = { 222 HWIO_REO_R0_SW2REO_RING_BASE_LSB_ADDR( 223 SEQ_WCSS_UMAC_REO_REG_OFFSET), 224 HWIO_REO_R2_SW2REO_RING_HP_ADDR( 225 SEQ_WCSS_UMAC_REO_REG_OFFSET) 226 }, 227 /* Single ring - provide ring size if multiple rings of this 228 * type are supported */ 229 .reg_size = {}, 230 }, 231 { /* REO_CMD */ 232 .start_ring_id = HAL_SRNG_REO_CMD, 233 .max_rings = 1, 234 .entry_size = (sizeof(struct tlv_32_hdr) + 235 sizeof(struct reo_get_queue_stats)) >> 2, 236 .lmac_ring = FALSE, 237 .ring_dir = HAL_SRNG_SRC_RING, 238 .reg_start = { 239 HWIO_REO_R0_REO_CMD_RING_BASE_LSB_ADDR( 240 SEQ_WCSS_UMAC_REO_REG_OFFSET), 241 HWIO_REO_R2_REO_CMD_RING_HP_ADDR( 242 SEQ_WCSS_UMAC_REO_REG_OFFSET), 243 }, 244 /* Single ring - provide ring size if multiple rings of this 245 * type are supported */ 246 .reg_size = {}, 247 }, 248 { /* REO_STATUS */ 249 .start_ring_id = HAL_SRNG_REO_STATUS, 250 .max_rings = 1, 251 .entry_size = (sizeof(struct tlv_32_hdr) + 252 sizeof(struct reo_get_queue_stats_status)) >> 2, 253 .lmac_ring = FALSE, 254 .ring_dir = HAL_SRNG_DST_RING, 255 .reg_start = { 256 HWIO_REO_R0_REO_STATUS_RING_BASE_LSB_ADDR( 257 SEQ_WCSS_UMAC_REO_REG_OFFSET), 258 HWIO_REO_R2_REO_STATUS_RING_HP_ADDR( 259 SEQ_WCSS_UMAC_REO_REG_OFFSET), 260 }, 261 /* Single ring - provide ring size if multiple rings of this 262 * type are supported */ 263 .reg_size = {}, 264 }, 265 { /* TCL_DATA */ 266 .start_ring_id = HAL_SRNG_SW2TCL1, 267 .max_rings = 3, 268 .entry_size = (sizeof(struct tlv_32_hdr) + 269 sizeof(struct tcl_data_cmd)) >> 2, 270 .lmac_ring = FALSE, 271 .ring_dir = HAL_SRNG_SRC_RING, 272 .reg_start = { 273 HWIO_TCL_R0_SW2TCL1_RING_BASE_LSB_ADDR( 274 SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET), 275 HWIO_TCL_R2_SW2TCL1_RING_HP_ADDR( 276 SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET), 277 }, 278 .reg_size = { 279 HWIO_TCL_R0_SW2TCL2_RING_BASE_LSB_ADDR(0) - 280 HWIO_TCL_R0_SW2TCL1_RING_BASE_LSB_ADDR(0), 281 HWIO_TCL_R2_SW2TCL2_RING_HP_ADDR(0) - 282 HWIO_TCL_R2_SW2TCL1_RING_HP_ADDR(0), 283 }, 284 }, 285 { /* TCL_CMD */ 286 .start_ring_id = HAL_SRNG_SW2TCL_CMD, 287 .max_rings = 1, 288 .entry_size = (sizeof(struct tlv_32_hdr) + 289 sizeof(struct tcl_gse_cmd)) >> 2, 290 .lmac_ring = FALSE, 291 .ring_dir = HAL_SRNG_SRC_RING, 292 .reg_start = { 293 HWIO_TCL_R0_SW2TCL_CMD_RING_BASE_LSB_ADDR( 294 SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET), 295 HWIO_TCL_R2_SW2TCL_CMD_RING_HP_ADDR( 296 SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET), 297 }, 298 /* Single ring - provide ring size if multiple rings of this 299 * type are supported */ 300 .reg_size = {}, 301 }, 302 { /* TCL_STATUS */ 303 .start_ring_id = HAL_SRNG_TCL_STATUS, 304 .max_rings = 1, 305 .entry_size = (sizeof(struct tlv_32_hdr) + 306 sizeof(struct tcl_status_ring)) >> 2, 307 .lmac_ring = FALSE, 308 .ring_dir = HAL_SRNG_DST_RING, 309 .reg_start = { 310 HWIO_TCL_R0_TCL_STATUS1_RING_BASE_LSB_ADDR( 311 SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET), 312 HWIO_TCL_R2_TCL_STATUS1_RING_HP_ADDR( 313 SEQ_WCSS_UMAC_MAC_TCL_REG_OFFSET), 314 }, 315 /* Single ring - provide ring size if multiple rings of this 316 * type are supported */ 317 .reg_size = {}, 318 }, 319 { /* CE_SRC */ 320 .start_ring_id = HAL_SRNG_CE_0_SRC, 321 .max_rings = 12, 322 .entry_size = sizeof(struct ce_src_desc) >> 2, 323 .lmac_ring = FALSE, 324 .ring_dir = HAL_SRNG_SRC_RING, 325 .reg_start = { 326 HWIO_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_LSB_ADDR( 327 SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_SRC_REG_OFFSET), 328 HWIO_WFSS_CE_CHANNEL_DST_R2_DEST_RING_HP_ADDR( 329 SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_SRC_REG_OFFSET), 330 }, 331 .reg_size = { 332 SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_1_CHANNEL_SRC_REG_OFFSET - 333 SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_SRC_REG_OFFSET, 334 SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_1_CHANNEL_SRC_REG_OFFSET - 335 SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_SRC_REG_OFFSET, 336 }, 337 }, 338 { /* CE_DST */ 339 .start_ring_id = HAL_SRNG_CE_0_DST, 340 .max_rings = 12, 341 .entry_size = 8 >> 2, 342 /*TODO: entry_size above should actually be 343 * sizeof(struct ce_dst_desc) >> 2, but couldn't find definition 344 * of struct ce_dst_desc in HW header files 345 */ 346 .lmac_ring = FALSE, 347 .ring_dir = HAL_SRNG_SRC_RING, 348 .reg_start = { 349 HWIO_WFSS_CE_CHANNEL_DST_R0_DEST_RING_BASE_LSB_ADDR( 350 SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET), 351 HWIO_WFSS_CE_CHANNEL_DST_R2_DEST_RING_HP_ADDR( 352 SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET), 353 }, 354 .reg_size = { 355 SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_1_CHANNEL_DST_REG_OFFSET - 356 SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET, 357 SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_1_CHANNEL_DST_REG_OFFSET - 358 SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET, 359 }, 360 }, 361 { /* CE_DST_STATUS */ 362 .start_ring_id = HAL_SRNG_CE_0_DST_STATUS, 363 .max_rings = 12, 364 .entry_size = sizeof(struct ce_stat_desc) >> 2, 365 .lmac_ring = FALSE, 366 .ring_dir = HAL_SRNG_DST_RING, 367 .reg_start = { 368 HWIO_WFSS_CE_CHANNEL_DST_R0_STATUS_RING_BASE_LSB_ADDR( 369 SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET), 370 HWIO_WFSS_CE_CHANNEL_DST_R2_STATUS_RING_HP_ADDR( 371 SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET), 372 }, 373 /* TODO: check destination status ring registers */ 374 .reg_size = { 375 SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_1_CHANNEL_DST_REG_OFFSET - 376 SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET, 377 SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_1_CHANNEL_DST_REG_OFFSET - 378 SEQ_WCSS_UMAC_WFSS_CE_0_REG_WFSS_CE_0_CHANNEL_DST_REG_OFFSET, 379 }, 380 }, 381 { /* WBM_IDLE_LINK */ 382 .start_ring_id = HAL_SRNG_WBM_IDLE_LINK, 383 .max_rings = 1, 384 .entry_size = sizeof(struct wbm_link_descriptor_ring) >> 2, 385 .lmac_ring = FALSE, 386 .ring_dir = HAL_SRNG_SRC_RING, 387 .reg_start = { 388 HWIO_WBM_R0_WBM_IDLE_LINK_RING_BASE_LSB_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), 389 HWIO_WBM_R2_WBM_IDLE_LINK_RING_HP_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), 390 }, 391 /* Single ring - provide ring size if multiple rings of this 392 * type are supported */ 393 .reg_size = {}, 394 }, 395 { /* SW2WBM_RELEASE */ 396 .start_ring_id = HAL_SRNG_WBM_SW_RELEASE, 397 .max_rings = 1, 398 .entry_size = sizeof(struct wbm_release_ring) >> 2, 399 .lmac_ring = FALSE, 400 .ring_dir = HAL_SRNG_SRC_RING, 401 .reg_start = { 402 HWIO_WBM_R0_SW_RELEASE_RING_BASE_LSB_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), 403 HWIO_WBM_R2_SW_RELEASE_RING_HP_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), 404 }, 405 /* Single ring - provide ring size if multiple rings of this 406 * type are supported */ 407 .reg_size = {}, 408 }, 409 { /* WBM2SW_RELEASE */ 410 .start_ring_id = HAL_SRNG_WBM2SW0_RELEASE, 411 .max_rings = 4, 412 .entry_size = sizeof(struct wbm_release_ring) >> 2, 413 .lmac_ring = FALSE, 414 .ring_dir = HAL_SRNG_DST_RING, 415 .reg_start = { 416 HWIO_WBM_R0_WBM2SW0_RELEASE_RING_BASE_LSB_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), 417 HWIO_WBM_R2_WBM2SW0_RELEASE_RING_HP_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), 418 }, 419 .reg_size = { 420 HWIO_WBM_R0_WBM2SW1_RELEASE_RING_BASE_LSB_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET) - 421 HWIO_WBM_R0_WBM2SW0_RELEASE_RING_BASE_LSB_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), 422 HWIO_WBM_R2_WBM2SW1_RELEASE_RING_HP_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET) - 423 HWIO_WBM_R2_WBM2SW0_RELEASE_RING_HP_ADDR(SEQ_WCSS_UMAC_WBM_REG_OFFSET), 424 }, 425 }, 426 { /* RXDMA_BUF */ 427 .start_ring_id = HAL_SRNG_WMAC1_SW2RXDMA0_BUF0, 428 #ifdef IPA_OFFLOAD 429 .max_rings = 3, 430 #else 431 .max_rings = 2, 432 #endif 433 .entry_size = sizeof(struct wbm_buffer_ring) >> 2, 434 .lmac_ring = TRUE, 435 .ring_dir = HAL_SRNG_SRC_RING, 436 /* reg_start is not set because LMAC rings are not accessed 437 * from host 438 */ 439 .reg_start = {}, 440 .reg_size = {}, 441 }, 442 { /* RXDMA_DST */ 443 .start_ring_id = HAL_SRNG_WMAC1_RXDMA2SW0, 444 .max_rings = 1, 445 .entry_size = sizeof(struct reo_entrance_ring) >> 2, 446 .lmac_ring = TRUE, 447 .ring_dir = HAL_SRNG_DST_RING, 448 /* reg_start is not set because LMAC rings are not accessed 449 * from host 450 */ 451 .reg_start = {}, 452 .reg_size = {}, 453 }, 454 { /* RXDMA_MONITOR_BUF */ 455 .start_ring_id = HAL_SRNG_WMAC1_SW2RXDMA2_BUF, 456 .max_rings = 1, 457 .entry_size = sizeof(struct wbm_buffer_ring) >> 2, 458 .lmac_ring = TRUE, 459 .ring_dir = HAL_SRNG_SRC_RING, 460 /* reg_start is not set because LMAC rings are not accessed 461 * from host 462 */ 463 .reg_start = {}, 464 .reg_size = {}, 465 }, 466 { /* RXDMA_MONITOR_STATUS */ 467 .start_ring_id = HAL_SRNG_WMAC1_SW2RXDMA1_STATBUF, 468 .max_rings = 1, 469 .entry_size = sizeof(struct wbm_buffer_ring) >> 2, 470 .lmac_ring = TRUE, 471 .ring_dir = HAL_SRNG_SRC_RING, 472 /* reg_start is not set because LMAC rings are not accessed 473 * from host 474 */ 475 .reg_start = {}, 476 .reg_size = {}, 477 }, 478 { /* RXDMA_MONITOR_DST */ 479 .start_ring_id = HAL_SRNG_WMAC1_RXDMA2SW1, 480 .max_rings = 1, 481 .entry_size = sizeof(struct reo_entrance_ring) >> 2, 482 .lmac_ring = TRUE, 483 .ring_dir = HAL_SRNG_DST_RING, 484 /* reg_start is not set because LMAC rings are not accessed 485 * from host 486 */ 487 .reg_start = {}, 488 .reg_size = {}, 489 }, 490 { /* RXDMA_MONITOR_DESC */ 491 .start_ring_id = HAL_SRNG_WMAC1_SW2RXDMA1_DESC, 492 .max_rings = 1, 493 .entry_size = sizeof(struct wbm_buffer_ring) >> 2, 494 .lmac_ring = TRUE, 495 .ring_dir = HAL_SRNG_SRC_RING, 496 /* reg_start is not set because LMAC rings are not accessed 497 * from host 498 */ 499 .reg_start = {}, 500 .reg_size = {}, 501 }, 502 { /* DIR_BUF_RX_DMA_SRC */ 503 .start_ring_id = HAL_SRNG_DIR_BUF_RX_SRC_DMA_RING, 504 .max_rings = 1, 505 .entry_size = 2, 506 .lmac_ring = TRUE, 507 .ring_dir = HAL_SRNG_SRC_RING, 508 /* reg_start is not set because LMAC rings are not accessed 509 * from host 510 */ 511 .reg_start = {}, 512 .reg_size = {}, 513 }, 514 #ifdef WLAN_FEATURE_CIF_CFR 515 { /* WIFI_POS_SRC */ 516 .start_ring_id = HAL_SRNG_WIFI_POS_SRC_DMA_RING, 517 .max_rings = 1, 518 .entry_size = sizeof(wmi_oem_dma_buf_release_entry) >> 2, 519 .lmac_ring = TRUE, 520 .ring_dir = HAL_SRNG_SRC_RING, 521 /* reg_start is not set because LMAC rings are not accessed 522 * from host 523 */ 524 .reg_start = {}, 525 .reg_size = {}, 526 }, 527 #endif 528 }; 529 530 /** 531 * hal_get_srng_ring_id() - get the ring id of a descriped ring 532 * @hal: hal_soc data structure 533 * @ring_type: type enum describing the ring 534 * @ring_num: which ring of the ring type 535 * @mac_id: which mac does the ring belong to (or 0 for non-lmac rings) 536 * 537 * Return: the ring id or -EINVAL if the ring does not exist. 538 */ 539 static int hal_get_srng_ring_id(struct hal_soc *hal, int ring_type, 540 int ring_num, int mac_id) 541 { 542 struct hal_hw_srng_config *ring_config = 543 HAL_SRNG_CONFIG(hal, ring_type); 544 int ring_id; 545 546 if (ring_num >= ring_config->max_rings) { 547 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 548 "%s: ring_num exceeded maximum no. of supported rings\n", 549 __func__); 550 /* TODO: This is a programming error. Assert if this happens */ 551 return -EINVAL; 552 } 553 554 if (ring_config->lmac_ring) { 555 ring_id = ring_config->start_ring_id + ring_num + 556 (mac_id * HAL_MAX_RINGS_PER_LMAC); 557 } else { 558 ring_id = ring_config->start_ring_id + ring_num; 559 } 560 561 return ring_id; 562 } 563 564 static struct hal_srng *hal_get_srng(struct hal_soc *hal, int ring_id) 565 { 566 /* TODO: Should we allocate srng structures dynamically? */ 567 return &(hal->srng_list[ring_id]); 568 } 569 570 #define HP_OFFSET_IN_REG_START 1 571 #define OFFSET_FROM_HP_TO_TP 4 572 static void hal_update_srng_hp_tp_address(void *hal_soc, 573 int shadow_config_index, 574 int ring_type, 575 int ring_num) 576 { 577 struct hal_srng *srng; 578 struct hal_soc *hal = (struct hal_soc *)hal_soc; 579 int ring_id; 580 581 ring_id = hal_get_srng_ring_id(hal_soc, ring_type, ring_num, 0); 582 if (ring_id < 0) 583 return; 584 585 srng = hal_get_srng(hal_soc, ring_id); 586 587 if (srng->ring_dir == HAL_SRNG_DST_RING) 588 srng->u.dst_ring.tp_addr = SHADOW_REGISTER(shadow_config_index) 589 + hal->dev_base_addr; 590 else 591 srng->u.src_ring.hp_addr = SHADOW_REGISTER(shadow_config_index) 592 + hal->dev_base_addr; 593 } 594 595 QDF_STATUS hal_set_one_shadow_config(void *hal_soc, 596 int ring_type, 597 int ring_num) 598 { 599 uint32_t target_register; 600 struct hal_soc *hal = (struct hal_soc *)hal_soc; 601 struct hal_hw_srng_config *srng_config = &hw_srng_table[ring_type]; 602 int shadow_config_index = hal->num_shadow_registers_configured; 603 604 if (shadow_config_index >= MAX_SHADOW_REGISTERS) { 605 QDF_ASSERT(0); 606 return QDF_STATUS_E_RESOURCES; 607 } 608 609 hal->num_shadow_registers_configured++; 610 611 target_register = srng_config->reg_start[HP_OFFSET_IN_REG_START]; 612 target_register += (srng_config->reg_size[HP_OFFSET_IN_REG_START] 613 *ring_num); 614 615 /* if the ring is a dst ring, we need to shadow the tail pointer */ 616 if (srng_config->ring_dir == HAL_SRNG_DST_RING) 617 target_register += OFFSET_FROM_HP_TO_TP; 618 619 hal->shadow_config[shadow_config_index].addr = target_register; 620 621 /* update hp/tp addr in the hal_soc structure*/ 622 hal_update_srng_hp_tp_address(hal_soc, shadow_config_index, ring_type, 623 ring_num); 624 625 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO, 626 "%s: target_reg %x, shadow_index %x, ring_type %d, ring num %d\n", 627 __func__, target_register, shadow_config_index, 628 ring_type, ring_num); 629 630 return QDF_STATUS_SUCCESS; 631 } 632 633 QDF_STATUS hal_construct_shadow_config(void *hal_soc) 634 { 635 int ring_type, ring_num; 636 637 for (ring_type = 0; ring_type < MAX_RING_TYPES; ring_type++) { 638 struct hal_hw_srng_config *srng_config = 639 &hw_srng_table[ring_type]; 640 641 if (ring_type == CE_SRC || 642 ring_type == CE_DST || 643 ring_type == CE_DST_STATUS) 644 continue; 645 646 if (srng_config->lmac_ring) 647 continue; 648 649 for (ring_num = 0; ring_num < srng_config->max_rings; 650 ring_num++) 651 hal_set_one_shadow_config(hal_soc, ring_type, ring_num); 652 } 653 654 return QDF_STATUS_SUCCESS; 655 } 656 657 void hal_get_shadow_config(void *hal_soc, 658 struct pld_shadow_reg_v2_cfg **shadow_config, 659 int *num_shadow_registers_configured) 660 { 661 struct hal_soc *hal = (struct hal_soc *)hal_soc; 662 663 *shadow_config = hal->shadow_config; 664 *num_shadow_registers_configured = 665 hal->num_shadow_registers_configured; 666 667 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 668 "%s\n", __func__); 669 } 670 671 672 static void hal_validate_shadow_register(struct hal_soc *hal, 673 uint32_t *destination, 674 uint32_t *shadow_address) 675 { 676 unsigned int index; 677 uint32_t *shadow_0_offset = SHADOW_REGISTER(0) + hal->dev_base_addr; 678 int destination_ba_offset = 679 ((char *)destination) - (char *)hal->dev_base_addr; 680 681 index = shadow_address - shadow_0_offset; 682 683 if (index >= MAX_SHADOW_REGISTERS) { 684 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 685 "%s: index %x out of bounds\n", __func__, index); 686 goto error; 687 } else if (hal->shadow_config[index].addr != destination_ba_offset) { 688 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 689 "%s: sanity check failure, expected %x, found %x\n", 690 __func__, destination_ba_offset, 691 hal->shadow_config[index].addr); 692 goto error; 693 } 694 return; 695 error: 696 qdf_print("%s: baddr %pK, desination %pK, shadow_address %pK s0offset %pK index %x", 697 __func__, hal->dev_base_addr, destination, shadow_address, 698 shadow_0_offset, index); 699 QDF_BUG(0); 700 return; 701 } 702 703 static void hal_target_based_configure(struct hal_soc *hal) 704 { 705 struct hif_target_info *tgt_info = 706 hif_get_target_info_handle(hal->hif_handle); 707 708 switch (tgt_info->target_type) { 709 case TARGET_TYPE_QCA6290: 710 hal->use_register_windowing = true; 711 break; 712 default: 713 break; 714 } 715 } 716 717 /** 718 * hal_attach - Initialize HAL layer 719 * @hif_handle: Opaque HIF handle 720 * @qdf_dev: QDF device 721 * 722 * Return: Opaque HAL SOC handle 723 * NULL on failure (if given ring is not available) 724 * 725 * This function should be called as part of HIF initialization (for accessing 726 * copy engines). DP layer will get hal_soc handle using hif_get_hal_handle() 727 * 728 */ 729 void *hal_attach(void *hif_handle, qdf_device_t qdf_dev) 730 { 731 struct hal_soc *hal; 732 int i; 733 734 hal = qdf_mem_malloc(sizeof(*hal)); 735 736 if (!hal) { 737 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 738 "%s: hal_soc allocation failed\n", __func__); 739 goto fail0; 740 } 741 hal->hif_handle = hif_handle; 742 hal->dev_base_addr = hif_get_dev_ba(hif_handle); 743 hal->qdf_dev = qdf_dev; 744 hal->shadow_rdptr_mem_vaddr = (uint32_t *)qdf_mem_alloc_consistent( 745 qdf_dev, qdf_dev->dev, sizeof(*(hal->shadow_rdptr_mem_vaddr)) * 746 HAL_SRNG_ID_MAX, &(hal->shadow_rdptr_mem_paddr)); 747 if (!hal->shadow_rdptr_mem_paddr) { 748 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 749 "%s: hal->shadow_rdptr_mem_paddr allocation failed\n", 750 __func__); 751 goto fail1; 752 } 753 754 hal->shadow_wrptr_mem_vaddr = 755 (uint32_t *)qdf_mem_alloc_consistent(qdf_dev, qdf_dev->dev, 756 sizeof(*(hal->shadow_wrptr_mem_vaddr)) * HAL_MAX_LMAC_RINGS, 757 &(hal->shadow_wrptr_mem_paddr)); 758 if (!hal->shadow_wrptr_mem_vaddr) { 759 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 760 "%s: hal->shadow_wrptr_mem_vaddr allocation failed\n", 761 __func__); 762 goto fail2; 763 } 764 765 for (i = 0; i < HAL_SRNG_ID_MAX; i++) { 766 hal->srng_list[i].initialized = 0; 767 hal->srng_list[i].ring_id = i; 768 } 769 770 qdf_spinlock_create(&hal->register_access_lock); 771 hal->register_window = 0; 772 773 hal_target_based_configure(hal); 774 775 return (void *)hal; 776 777 fail2: 778 qdf_mem_free_consistent(qdf_dev, qdf_dev->dev, 779 sizeof(*(hal->shadow_rdptr_mem_vaddr)) * HAL_SRNG_ID_MAX, 780 hal->shadow_rdptr_mem_vaddr, hal->shadow_rdptr_mem_paddr, 0); 781 fail1: 782 qdf_mem_free(hal); 783 fail0: 784 return NULL; 785 } 786 qdf_export_symbol(hal_attach); 787 788 /** 789 * hal_mem_info - Retrieve hal memory base address 790 * 791 * @hal_soc: Opaque HAL SOC handle 792 * @mem: pointer to structure to be updated with hal mem info 793 */ 794 void hal_get_meminfo(void *hal_soc, struct hal_mem_info *mem ) 795 { 796 struct hal_soc *hal = (struct hal_soc *)hal_soc; 797 mem->dev_base_addr = (void *)hal->dev_base_addr; 798 mem->shadow_rdptr_mem_vaddr = (void *)hal->shadow_rdptr_mem_vaddr; 799 mem->shadow_wrptr_mem_vaddr = (void *)hal->shadow_wrptr_mem_vaddr; 800 mem->shadow_rdptr_mem_paddr = (void *)hal->shadow_rdptr_mem_paddr; 801 mem->shadow_wrptr_mem_paddr = (void *)hal->shadow_wrptr_mem_paddr; 802 hif_read_phy_mem_base(hal->hif_handle, (qdf_dma_addr_t *)&mem->dev_base_paddr); 803 return; 804 } 805 qdf_export_symbol(hal_get_meminfo); 806 807 /** 808 * hal_detach - Detach HAL layer 809 * @hal_soc: HAL SOC handle 810 * 811 * Return: Opaque HAL SOC handle 812 * NULL on failure (if given ring is not available) 813 * 814 * This function should be called as part of HIF initialization (for accessing 815 * copy engines). DP layer will get hal_soc handle using hif_get_hal_handle() 816 * 817 */ 818 extern void hal_detach(void *hal_soc) 819 { 820 struct hal_soc *hal = (struct hal_soc *)hal_soc; 821 822 qdf_mem_free_consistent(hal->qdf_dev, hal->qdf_dev->dev, 823 sizeof(*(hal->shadow_rdptr_mem_vaddr)) * HAL_SRNG_ID_MAX, 824 hal->shadow_rdptr_mem_vaddr, hal->shadow_rdptr_mem_paddr, 0); 825 qdf_mem_free_consistent(hal->qdf_dev, hal->qdf_dev->dev, 826 sizeof(*(hal->shadow_wrptr_mem_vaddr)) * HAL_MAX_LMAC_RINGS, 827 hal->shadow_wrptr_mem_vaddr, hal->shadow_wrptr_mem_paddr, 0); 828 qdf_mem_free(hal); 829 830 return; 831 } 832 qdf_export_symbol(hal_detach); 833 834 /** 835 * hal_srng_src_hw_init - Private function to initialize SRNG 836 * source ring HW 837 * @hal_soc: HAL SOC handle 838 * @srng: SRNG ring pointer 839 */ 840 static inline void hal_srng_src_hw_init(struct hal_soc *hal, 841 struct hal_srng *srng) 842 { 843 uint32_t reg_val = 0; 844 uint64_t tp_addr = 0; 845 846 HIF_DBG("%s: hw_init srng %d", __func__, srng->ring_id); 847 848 if (srng->flags & HAL_SRNG_MSI_INTR) { 849 SRNG_SRC_REG_WRITE(srng, MSI1_BASE_LSB, 850 srng->msi_addr & 0xffffffff); 851 reg_val = SRNG_SM(SRNG_SRC_FLD(MSI1_BASE_MSB, ADDR), 852 (uint64_t)(srng->msi_addr) >> 32) | 853 SRNG_SM(SRNG_SRC_FLD(MSI1_BASE_MSB, 854 MSI1_ENABLE), 1); 855 SRNG_SRC_REG_WRITE(srng, MSI1_BASE_MSB, reg_val); 856 SRNG_SRC_REG_WRITE(srng, MSI1_DATA, srng->msi_data); 857 } 858 859 SRNG_SRC_REG_WRITE(srng, BASE_LSB, srng->ring_base_paddr & 0xffffffff); 860 reg_val = SRNG_SM(SRNG_SRC_FLD(BASE_MSB, RING_BASE_ADDR_MSB), 861 ((uint64_t)(srng->ring_base_paddr) >> 32)) | 862 SRNG_SM(SRNG_SRC_FLD(BASE_MSB, RING_SIZE), 863 srng->entry_size * srng->num_entries); 864 SRNG_SRC_REG_WRITE(srng, BASE_MSB, reg_val); 865 866 #if defined(WCSS_VERSION) && \ 867 ((defined(CONFIG_WIN) && (WCSS_VERSION > 81)) || \ 868 (defined(CONFIG_MCL) && (WCSS_VERSION >= 72))) 869 reg_val = SRNG_SM(SRNG_SRC_FLD(ID, ENTRY_SIZE), srng->entry_size); 870 #else 871 reg_val = SRNG_SM(SRNG_SRC_FLD(ID, RING_ID), srng->ring_id) | 872 SRNG_SM(SRNG_SRC_FLD(ID, ENTRY_SIZE), srng->entry_size); 873 #endif 874 SRNG_SRC_REG_WRITE(srng, ID, reg_val); 875 876 /** 877 * Interrupt setup: 878 * Default interrupt mode is 'pulse'. Need to setup SW_INTERRUPT_MODE 879 * if level mode is required 880 */ 881 reg_val = 0; 882 883 /* 884 * WAR - Hawkeye v1 has a hardware bug which requires timer value to be 885 * programmed in terms of 1us resolution instead of 8us resolution as 886 * given in MLD. 887 */ 888 if (srng->intr_timer_thres_us) { 889 reg_val |= SRNG_SM(SRNG_SRC_FLD(CONSUMER_INT_SETUP_IX0, 890 INTERRUPT_TIMER_THRESHOLD), 891 srng->intr_timer_thres_us); 892 /* For HK v2 this should be (srng->intr_timer_thres_us >> 3) */ 893 } 894 895 if (srng->intr_batch_cntr_thres_entries) { 896 reg_val |= SRNG_SM(SRNG_SRC_FLD(CONSUMER_INT_SETUP_IX0, 897 BATCH_COUNTER_THRESHOLD), 898 srng->intr_batch_cntr_thres_entries * 899 srng->entry_size); 900 } 901 SRNG_SRC_REG_WRITE(srng, CONSUMER_INT_SETUP_IX0, reg_val); 902 903 reg_val = 0; 904 if (srng->flags & HAL_SRNG_LOW_THRES_INTR_ENABLE) { 905 reg_val |= SRNG_SM(SRNG_SRC_FLD(CONSUMER_INT_SETUP_IX1, 906 LOW_THRESHOLD), srng->u.src_ring.low_threshold); 907 } 908 909 SRNG_SRC_REG_WRITE(srng, CONSUMER_INT_SETUP_IX1, reg_val); 910 911 /* As per HW team, TP_ADDR and HP_ADDR for Idle link ring should 912 * remain 0 to avoid some WBM stability issues. Remote head/tail 913 * pointers are not required since this ring is completely managed 914 * by WBM HW */ 915 if (srng->ring_id != HAL_SRNG_WBM_IDLE_LINK) { 916 tp_addr = (uint64_t)(hal->shadow_rdptr_mem_paddr + 917 ((unsigned long)(srng->u.src_ring.tp_addr) - 918 (unsigned long)(hal->shadow_rdptr_mem_vaddr))); 919 SRNG_SRC_REG_WRITE(srng, TP_ADDR_LSB, tp_addr & 0xffffffff); 920 SRNG_SRC_REG_WRITE(srng, TP_ADDR_MSB, tp_addr >> 32); 921 } 922 923 /* Initilaize head and tail pointers to indicate ring is empty */ 924 SRNG_SRC_REG_WRITE(srng, HP, 0); 925 SRNG_SRC_REG_WRITE(srng, TP, 0); 926 *(srng->u.src_ring.tp_addr) = 0; 927 928 reg_val = ((srng->flags & HAL_SRNG_DATA_TLV_SWAP) ? 929 SRNG_SM(SRNG_SRC_FLD(MISC, DATA_TLV_SWAP_BIT), 1) : 0) | 930 ((srng->flags & HAL_SRNG_RING_PTR_SWAP) ? 931 SRNG_SM(SRNG_SRC_FLD(MISC, HOST_FW_SWAP_BIT), 1) : 0) | 932 ((srng->flags & HAL_SRNG_MSI_SWAP) ? 933 SRNG_SM(SRNG_SRC_FLD(MISC, MSI_SWAP_BIT), 1) : 0); 934 935 /* Loop count is not used for SRC rings */ 936 reg_val |= SRNG_SM(SRNG_SRC_FLD(MISC, LOOPCNT_DISABLE), 1); 937 938 /* 939 * reg_val |= SRNG_SM(SRNG_SRC_FLD(MISC, SRNG_ENABLE), 1); 940 * todo: update fw_api and replace with above line 941 * (when SRNG_ENABLE field for the MISC register is available in fw_api) 942 * (WCSS_UMAC_CE_0_SRC_WFSS_CE_CHANNEL_SRC_R0_SRC_RING_MISC) 943 */ 944 reg_val |= 0x40; 945 946 SRNG_SRC_REG_WRITE(srng, MISC, reg_val); 947 948 } 949 950 /** 951 * hal_ce_dst_setup - Initialize CE destination ring registers 952 * @hal_soc: HAL SOC handle 953 * @srng: SRNG ring pointer 954 */ 955 static inline void hal_ce_dst_setup(struct hal_soc *hal, struct hal_srng *srng, 956 int ring_num) 957 { 958 uint32_t reg_val = 0; 959 uint32_t reg_addr; 960 struct hal_hw_srng_config *ring_config = 961 HAL_SRNG_CONFIG(hal, CE_DST); 962 963 /* set DEST_MAX_LENGTH according to ce assignment */ 964 reg_addr = HWIO_WFSS_CE_CHANNEL_DST_R0_DEST_CTRL_ADDR( 965 ring_config->reg_start[R0_INDEX] + 966 (ring_num * ring_config->reg_size[R0_INDEX])); 967 968 reg_val = HAL_REG_READ(hal, reg_addr); 969 reg_val &= ~HWIO_WFSS_CE_CHANNEL_DST_R0_DEST_CTRL_DEST_MAX_LENGTH_BMSK; 970 reg_val |= srng->u.dst_ring.max_buffer_length & 971 HWIO_WFSS_CE_CHANNEL_DST_R0_DEST_CTRL_DEST_MAX_LENGTH_BMSK; 972 HAL_REG_WRITE(hal, reg_addr, reg_val); 973 } 974 975 /** 976 * hal_reo_remap_IX0 - Remap REO ring destination 977 * @hal: HAL SOC handle 978 * @remap_val: Remap value 979 */ 980 void hal_reo_remap_IX0(struct hal_soc *hal, uint32_t remap_val) 981 { 982 uint32_t reg_offset = HWIO_REO_R0_DESTINATION_RING_CTRL_IX_0_ADDR( 983 SEQ_WCSS_UMAC_REO_REG_OFFSET); 984 HAL_REG_WRITE(hal, reg_offset, remap_val); 985 } 986 987 /** 988 * hal_srng_dst_set_hp_paddr() - Set physical address to dest ring head pointer 989 * @srng: sring pointer 990 * @paddr: physical address 991 */ 992 void hal_srng_dst_set_hp_paddr(struct hal_srng *srng, 993 uint64_t paddr) 994 { 995 SRNG_DST_REG_WRITE(srng, HP_ADDR_LSB, 996 paddr & 0xffffffff); 997 SRNG_DST_REG_WRITE(srng, HP_ADDR_MSB, 998 paddr >> 32); 999 } 1000 1001 /** 1002 * hal_srng_dst_init_hp() - Initilaize destination ring head pointer 1003 * @srng: sring pointer 1004 * @vaddr: virtual address 1005 */ 1006 void hal_srng_dst_init_hp(struct hal_srng *srng, 1007 uint32_t *vaddr) 1008 { 1009 srng->u.dst_ring.hp_addr = vaddr; 1010 SRNG_DST_REG_WRITE(srng, HP, srng->u.dst_ring.cached_hp); 1011 *(srng->u.dst_ring.hp_addr) = srng->u.dst_ring.cached_hp; 1012 1013 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR, 1014 "hp_addr=%pK, cached_hp=%d, hp=%d\n", 1015 (void *)srng->u.dst_ring.hp_addr, srng->u.dst_ring.cached_hp, 1016 *(srng->u.dst_ring.hp_addr)); 1017 } 1018 1019 /** 1020 * hal_srng_dst_hw_init - Private function to initialize SRNG 1021 * destination ring HW 1022 * @hal_soc: HAL SOC handle 1023 * @srng: SRNG ring pointer 1024 */ 1025 static inline void hal_srng_dst_hw_init(struct hal_soc *hal, 1026 struct hal_srng *srng) 1027 { 1028 uint32_t reg_val = 0; 1029 uint64_t hp_addr = 0; 1030 1031 HIF_DBG("%s: hw_init srng %d", __func__, srng->ring_id); 1032 1033 if (srng->flags & HAL_SRNG_MSI_INTR) { 1034 SRNG_DST_REG_WRITE(srng, MSI1_BASE_LSB, 1035 srng->msi_addr & 0xffffffff); 1036 reg_val = SRNG_SM(SRNG_DST_FLD(MSI1_BASE_MSB, ADDR), 1037 (uint64_t)(srng->msi_addr) >> 32) | 1038 SRNG_SM(SRNG_DST_FLD(MSI1_BASE_MSB, 1039 MSI1_ENABLE), 1); 1040 SRNG_DST_REG_WRITE(srng, MSI1_BASE_MSB, reg_val); 1041 SRNG_DST_REG_WRITE(srng, MSI1_DATA, srng->msi_data); 1042 } 1043 1044 SRNG_DST_REG_WRITE(srng, BASE_LSB, srng->ring_base_paddr & 0xffffffff); 1045 reg_val = SRNG_SM(SRNG_DST_FLD(BASE_MSB, RING_BASE_ADDR_MSB), 1046 ((uint64_t)(srng->ring_base_paddr) >> 32)) | 1047 SRNG_SM(SRNG_DST_FLD(BASE_MSB, RING_SIZE), 1048 srng->entry_size * srng->num_entries); 1049 SRNG_DST_REG_WRITE(srng, BASE_MSB, reg_val); 1050 1051 reg_val = SRNG_SM(SRNG_DST_FLD(ID, RING_ID), srng->ring_id) | 1052 SRNG_SM(SRNG_DST_FLD(ID, ENTRY_SIZE), srng->entry_size); 1053 SRNG_DST_REG_WRITE(srng, ID, reg_val); 1054 1055 1056 /** 1057 * Interrupt setup: 1058 * Default interrupt mode is 'pulse'. Need to setup SW_INTERRUPT_MODE 1059 * if level mode is required 1060 */ 1061 reg_val = 0; 1062 if (srng->intr_timer_thres_us) { 1063 reg_val |= SRNG_SM(SRNG_DST_FLD(PRODUCER_INT_SETUP, 1064 INTERRUPT_TIMER_THRESHOLD), 1065 srng->intr_timer_thres_us >> 3); 1066 } 1067 1068 if (srng->intr_batch_cntr_thres_entries) { 1069 reg_val |= SRNG_SM(SRNG_DST_FLD(PRODUCER_INT_SETUP, 1070 BATCH_COUNTER_THRESHOLD), 1071 srng->intr_batch_cntr_thres_entries * 1072 srng->entry_size); 1073 } 1074 1075 SRNG_DST_REG_WRITE(srng, PRODUCER_INT_SETUP, reg_val); 1076 hp_addr = (uint64_t)(hal->shadow_rdptr_mem_paddr + 1077 ((unsigned long)(srng->u.dst_ring.hp_addr) - 1078 (unsigned long)(hal->shadow_rdptr_mem_vaddr))); 1079 SRNG_DST_REG_WRITE(srng, HP_ADDR_LSB, hp_addr & 0xffffffff); 1080 SRNG_DST_REG_WRITE(srng, HP_ADDR_MSB, hp_addr >> 32); 1081 1082 /* Initilaize head and tail pointers to indicate ring is empty */ 1083 SRNG_DST_REG_WRITE(srng, HP, 0); 1084 SRNG_DST_REG_WRITE(srng, TP, 0); 1085 *(srng->u.dst_ring.hp_addr) = 0; 1086 1087 reg_val = ((srng->flags & HAL_SRNG_DATA_TLV_SWAP) ? 1088 SRNG_SM(SRNG_DST_FLD(MISC, DATA_TLV_SWAP_BIT), 1) : 0) | 1089 ((srng->flags & HAL_SRNG_RING_PTR_SWAP) ? 1090 SRNG_SM(SRNG_DST_FLD(MISC, HOST_FW_SWAP_BIT), 1) : 0) | 1091 ((srng->flags & HAL_SRNG_MSI_SWAP) ? 1092 SRNG_SM(SRNG_DST_FLD(MISC, MSI_SWAP_BIT), 1) : 0); 1093 1094 /* 1095 * reg_val |= SRNG_SM(SRNG_SRC_FLD(MISC, SRNG_ENABLE), 1); 1096 * todo: update fw_api and replace with above line 1097 * (when SRNG_ENABLE field for the MISC register is available in fw_api) 1098 * (WCSS_UMAC_CE_0_SRC_WFSS_CE_CHANNEL_SRC_R0_SRC_RING_MISC) 1099 */ 1100 reg_val |= 0x40; 1101 1102 SRNG_DST_REG_WRITE(srng, MISC, reg_val); 1103 1104 } 1105 1106 /** 1107 * hal_srng_hw_init - Private function to initialize SRNG HW 1108 * @hal_soc: HAL SOC handle 1109 * @srng: SRNG ring pointer 1110 */ 1111 static inline void hal_srng_hw_init(struct hal_soc *hal, 1112 struct hal_srng *srng) 1113 { 1114 if (srng->ring_dir == HAL_SRNG_SRC_RING) 1115 hal_srng_src_hw_init(hal, srng); 1116 else 1117 hal_srng_dst_hw_init(hal, srng); 1118 } 1119 1120 #ifdef CONFIG_SHADOW_V2 1121 #define ignore_shadow false 1122 #define CHECK_SHADOW_REGISTERS true 1123 #else 1124 #define ignore_shadow true 1125 #define CHECK_SHADOW_REGISTERS false 1126 #endif 1127 1128 /** 1129 * hal_srng_setup - Initialize HW SRNG ring. 1130 * @hal_soc: Opaque HAL SOC handle 1131 * @ring_type: one of the types from hal_ring_type 1132 * @ring_num: Ring number if there are multiple rings of same type (staring 1133 * from 0) 1134 * @mac_id: valid MAC Id should be passed if ring type is one of lmac rings 1135 * @ring_params: SRNG ring params in hal_srng_params structure. 1136 1137 * Callers are expected to allocate contiguous ring memory of size 1138 * 'num_entries * entry_size' bytes and pass the physical and virtual base 1139 * addresses through 'ring_base_paddr' and 'ring_base_vaddr' in 1140 * hal_srng_params structure. Ring base address should be 8 byte aligned 1141 * and size of each ring entry should be queried using the API 1142 * hal_srng_get_entrysize 1143 * 1144 * Return: Opaque pointer to ring on success 1145 * NULL on failure (if given ring is not available) 1146 */ 1147 void *hal_srng_setup(void *hal_soc, int ring_type, int ring_num, 1148 int mac_id, struct hal_srng_params *ring_params) 1149 { 1150 int ring_id; 1151 struct hal_soc *hal = (struct hal_soc *)hal_soc; 1152 struct hal_srng *srng; 1153 struct hal_hw_srng_config *ring_config = 1154 HAL_SRNG_CONFIG(hal, ring_type); 1155 void *dev_base_addr; 1156 int i; 1157 1158 ring_id = hal_get_srng_ring_id(hal_soc, ring_type, ring_num, mac_id); 1159 if (ring_id < 0) 1160 return NULL; 1161 1162 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 1163 "%s: mac_id %d ring_id %d\n", 1164 __func__, mac_id, ring_id); 1165 1166 srng = hal_get_srng(hal_soc, ring_id); 1167 1168 if (srng->initialized) { 1169 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR, 1170 "%s: Ring (ring_type, ring_num) already initialized\n", 1171 __func__); 1172 return NULL; 1173 } 1174 1175 dev_base_addr = hal->dev_base_addr; 1176 srng->ring_id = ring_id; 1177 srng->ring_dir = ring_config->ring_dir; 1178 srng->ring_base_paddr = ring_params->ring_base_paddr; 1179 srng->ring_base_vaddr = ring_params->ring_base_vaddr; 1180 srng->entry_size = ring_config->entry_size; 1181 srng->num_entries = ring_params->num_entries; 1182 srng->ring_size = srng->num_entries * srng->entry_size; 1183 srng->ring_size_mask = srng->ring_size - 1; 1184 srng->msi_addr = ring_params->msi_addr; 1185 srng->msi_data = ring_params->msi_data; 1186 srng->intr_timer_thres_us = ring_params->intr_timer_thres_us; 1187 srng->intr_batch_cntr_thres_entries = 1188 ring_params->intr_batch_cntr_thres_entries; 1189 srng->hal_soc = hal_soc; 1190 1191 for (i = 0 ; i < MAX_SRNG_REG_GROUPS; i++) { 1192 srng->hwreg_base[i] = dev_base_addr + ring_config->reg_start[i] 1193 + (ring_num * ring_config->reg_size[i]); 1194 } 1195 1196 /* Zero out the entire ring memory */ 1197 qdf_mem_zero(srng->ring_base_vaddr, (srng->entry_size * 1198 srng->num_entries) << 2); 1199 1200 srng->flags = ring_params->flags; 1201 #ifdef BIG_ENDIAN_HOST 1202 /* TODO: See if we should we get these flags from caller */ 1203 srng->flags |= HAL_SRNG_DATA_TLV_SWAP; 1204 srng->flags |= HAL_SRNG_MSI_SWAP; 1205 srng->flags |= HAL_SRNG_RING_PTR_SWAP; 1206 #endif 1207 1208 if (srng->ring_dir == HAL_SRNG_SRC_RING) { 1209 srng->u.src_ring.hp = 0; 1210 srng->u.src_ring.reap_hp = srng->ring_size - 1211 srng->entry_size; 1212 srng->u.src_ring.tp_addr = 1213 &(hal->shadow_rdptr_mem_vaddr[ring_id]); 1214 srng->u.src_ring.low_threshold = 1215 ring_params->low_threshold * srng->entry_size; 1216 if (ring_config->lmac_ring) { 1217 /* For LMAC rings, head pointer updates will be done 1218 * through FW by writing to a shared memory location 1219 */ 1220 srng->u.src_ring.hp_addr = 1221 &(hal->shadow_wrptr_mem_vaddr[ring_id - 1222 HAL_SRNG_LMAC1_ID_START]); 1223 srng->flags |= HAL_SRNG_LMAC_RING; 1224 } else if (ignore_shadow || (srng->u.src_ring.hp_addr == 0)) { 1225 srng->u.src_ring.hp_addr = SRNG_SRC_ADDR(srng, HP); 1226 1227 if (CHECK_SHADOW_REGISTERS) { 1228 QDF_TRACE(QDF_MODULE_ID_TXRX, 1229 QDF_TRACE_LEVEL_ERROR, 1230 "%s: Ring (%d, %d) missing shadow config\n", 1231 __func__, ring_type, ring_num); 1232 } 1233 } else { 1234 hal_validate_shadow_register(hal, 1235 SRNG_SRC_ADDR(srng, HP), 1236 srng->u.src_ring.hp_addr); 1237 } 1238 } else { 1239 /* During initialization loop count in all the descriptors 1240 * will be set to zero, and HW will set it to 1 on completing 1241 * descriptor update in first loop, and increments it by 1 on 1242 * subsequent loops (loop count wraps around after reaching 1243 * 0xffff). The 'loop_cnt' in SW ring state is the expected 1244 * loop count in descriptors updated by HW (to be processed 1245 * by SW). 1246 */ 1247 srng->u.dst_ring.loop_cnt = 1; 1248 srng->u.dst_ring.tp = 0; 1249 srng->u.dst_ring.hp_addr = 1250 &(hal->shadow_rdptr_mem_vaddr[ring_id]); 1251 if (ring_config->lmac_ring) { 1252 /* For LMAC rings, tail pointer updates will be done 1253 * through FW by writing to a shared memory location 1254 */ 1255 srng->u.dst_ring.tp_addr = 1256 &(hal->shadow_wrptr_mem_vaddr[ring_id - 1257 HAL_SRNG_LMAC1_ID_START]); 1258 srng->flags |= HAL_SRNG_LMAC_RING; 1259 } else if (ignore_shadow || srng->u.dst_ring.tp_addr == 0) { 1260 srng->u.dst_ring.tp_addr = SRNG_DST_ADDR(srng, TP); 1261 1262 if (CHECK_SHADOW_REGISTERS) { 1263 QDF_TRACE(QDF_MODULE_ID_TXRX, 1264 QDF_TRACE_LEVEL_ERROR, 1265 "%s: Ring (%d, %d) missing shadow config\n", 1266 __func__, ring_type, ring_num); 1267 } 1268 } else { 1269 hal_validate_shadow_register(hal, 1270 SRNG_DST_ADDR(srng, TP), 1271 srng->u.dst_ring.tp_addr); 1272 } 1273 } 1274 1275 if (!(ring_config->lmac_ring)) { 1276 hal_srng_hw_init(hal, srng); 1277 1278 if (ring_type == CE_DST) { 1279 srng->u.dst_ring.max_buffer_length = ring_params->max_buffer_length; 1280 hal_ce_dst_setup(hal, srng, ring_num); 1281 } 1282 } 1283 1284 SRNG_LOCK_INIT(&srng->lock); 1285 1286 srng->initialized = true; 1287 1288 return (void *)srng; 1289 } 1290 qdf_export_symbol(hal_srng_setup); 1291 1292 /** 1293 * hal_srng_cleanup - Deinitialize HW SRNG ring. 1294 * @hal_soc: Opaque HAL SOC handle 1295 * @hal_srng: Opaque HAL SRNG pointer 1296 */ 1297 void hal_srng_cleanup(void *hal_soc, void *hal_srng) 1298 { 1299 struct hal_srng *srng = (struct hal_srng *)hal_srng; 1300 SRNG_LOCK_DESTROY(&srng->lock); 1301 srng->initialized = 0; 1302 } 1303 qdf_export_symbol(hal_srng_cleanup); 1304 1305 /** 1306 * hal_srng_get_entrysize - Returns size of ring entry in bytes 1307 * @hal_soc: Opaque HAL SOC handle 1308 * @ring_type: one of the types from hal_ring_type 1309 * 1310 */ 1311 uint32_t hal_srng_get_entrysize(void *hal_soc, int ring_type) 1312 { 1313 struct hal_hw_srng_config *ring_config = 1314 HAL_SRNG_CONFIG(hal, ring_type); 1315 return ring_config->entry_size << 2; 1316 } 1317 qdf_export_symbol(hal_srng_get_entrysize); 1318 1319 /** 1320 * hal_srng_max_entries - Returns maximum possible number of ring entries 1321 * @hal_soc: Opaque HAL SOC handle 1322 * @ring_type: one of the types from hal_ring_type 1323 * 1324 * Return: Maximum number of entries for the given ring_type 1325 */ 1326 uint32_t hal_srng_max_entries(void *hal_soc, int ring_type) 1327 { 1328 struct hal_hw_srng_config *ring_config = HAL_SRNG_CONFIG(hal, ring_type); 1329 return SRNG_MAX_SIZE_DWORDS / ring_config->entry_size; 1330 } 1331 qdf_export_symbol(hal_srng_max_entries); 1332 1333 enum hal_srng_dir hal_srng_get_dir(void *hal_soc, int ring_type) 1334 { 1335 struct hal_hw_srng_config *ring_config = 1336 HAL_SRNG_CONFIG(hal, ring_type); 1337 1338 return ring_config->ring_dir; 1339 } 1340 1341 /** 1342 * hal_srng_dump - Dump ring status 1343 * @srng: hal srng pointer 1344 */ 1345 void hal_srng_dump(struct hal_srng *srng) 1346 { 1347 if (srng->ring_dir == HAL_SRNG_SRC_RING) { 1348 qdf_print("=== SRC RING %d ===", srng->ring_id); 1349 qdf_print("hp %u, reap_hp %u, tp %u, cached tp %u", 1350 srng->u.src_ring.hp, 1351 srng->u.src_ring.reap_hp, 1352 *srng->u.src_ring.tp_addr, 1353 srng->u.src_ring.cached_tp); 1354 } else { 1355 qdf_print("=== DST RING %d ===", srng->ring_id); 1356 qdf_print("tp %u, hp %u, cached tp %u, loop_cnt %u", 1357 srng->u.dst_ring.tp, 1358 *srng->u.dst_ring.hp_addr, 1359 srng->u.dst_ring.cached_hp, 1360 srng->u.dst_ring.loop_cnt); 1361 } 1362 } 1363 1364 /** 1365 * hal_get_srng_params - Retrieve SRNG parameters for a given ring from HAL 1366 * 1367 * @hal_soc: Opaque HAL SOC handle 1368 * @hal_ring: Ring pointer (Source or Destination ring) 1369 * @ring_params: SRNG parameters will be returned through this structure 1370 */ 1371 extern void hal_get_srng_params(void *hal_soc, void *hal_ring, 1372 struct hal_srng_params *ring_params) 1373 { 1374 struct hal_srng *srng = (struct hal_srng *)hal_ring; 1375 int i =0; 1376 ring_params->ring_id = srng->ring_id; 1377 ring_params->ring_dir = srng->ring_dir; 1378 ring_params->entry_size = srng->entry_size; 1379 1380 ring_params->ring_base_paddr = srng->ring_base_paddr; 1381 ring_params->ring_base_vaddr = srng->ring_base_vaddr; 1382 ring_params->num_entries = srng->num_entries; 1383 ring_params->msi_addr = srng->msi_addr; 1384 ring_params->msi_data = srng->msi_data; 1385 ring_params->intr_timer_thres_us = srng->intr_timer_thres_us; 1386 ring_params->intr_batch_cntr_thres_entries = 1387 srng->intr_batch_cntr_thres_entries; 1388 ring_params->low_threshold = srng->u.src_ring.low_threshold; 1389 ring_params->flags = srng->flags; 1390 ring_params->ring_id = srng->ring_id; 1391 for (i = 0 ; i < MAX_SRNG_REG_GROUPS; i++) 1392 ring_params->hwreg_base[i] = srng->hwreg_base[i]; 1393 } 1394 qdf_export_symbol(hal_get_srng_params); 1395