1 /* 2 * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 #ifndef _HAL_GENERIC_API_H_ 20 #define _HAL_GENERIC_API_H_ 21 22 #include <hal_rx.h> 23 24 #define SRNG_ENABLE_BIT 0x40 25 #define SRNG_IDLE_STATE_BIT 0x80 26 27 /** 28 * hal_get_radiotap_he_gi_ltf() - Convert HE ltf and GI value 29 * from stats enum to radiotap enum 30 * @he_gi: HE GI value used in stats 31 * @he_ltf: HE LTF value used in stats 32 * 33 * Return: void 34 */ 35 static inline void hal_get_radiotap_he_gi_ltf(uint16_t *he_gi, uint16_t *he_ltf) 36 { 37 switch (*he_gi) { 38 case HE_GI_0_8: 39 *he_gi = HE_GI_RADIOTAP_0_8; 40 break; 41 case HE_GI_1_6: 42 *he_gi = HE_GI_RADIOTAP_1_6; 43 break; 44 case HE_GI_3_2: 45 *he_gi = HE_GI_RADIOTAP_3_2; 46 break; 47 default: 48 *he_gi = HE_GI_RADIOTAP_RESERVED; 49 } 50 51 switch (*he_ltf) { 52 case HE_LTF_1_X: 53 *he_ltf = HE_LTF_RADIOTAP_1_X; 54 break; 55 case HE_LTF_2_X: 56 *he_ltf = HE_LTF_RADIOTAP_2_X; 57 break; 58 case HE_LTF_4_X: 59 *he_ltf = HE_LTF_RADIOTAP_4_X; 60 break; 61 default: 62 *he_ltf = HE_LTF_RADIOTAP_UNKNOWN; 63 } 64 } 65 66 /* channel number to freq conversion */ 67 #define CHANNEL_NUM_14 14 68 #define CHANNEL_NUM_15 15 69 #define CHANNEL_NUM_27 27 70 #define CHANNEL_NUM_35 35 71 #define CHANNEL_NUM_182 182 72 #define CHANNEL_NUM_197 197 73 #define CHANNEL_FREQ_2484 2484 74 #define CHANNEL_FREQ_2407 2407 75 #define CHANNEL_FREQ_2512 2512 76 #define CHANNEL_FREQ_5000 5000 77 #define CHANNEL_FREQ_5950 5950 78 #define CHANNEL_FREQ_4000 4000 79 #define CHANNEL_FREQ_5150 5150 80 #define CHANNEL_FREQ_5920 5920 81 #define CHANNEL_FREQ_5935 5935 82 #define FREQ_MULTIPLIER_CONST_5MHZ 5 83 #define FREQ_MULTIPLIER_CONST_20MHZ 20 84 /** 85 * hal_rx_radiotap_num_to_freq() - Get frequency from chan number 86 * @chan_num: Input channel number 87 * @center_freq: Input Channel Center frequency 88 * 89 * Return - Channel frequency in Mhz 90 */ 91 static inline uint16_t 92 hal_rx_radiotap_num_to_freq(uint16_t chan_num, qdf_freq_t center_freq) 93 { 94 if (center_freq > CHANNEL_FREQ_5920 && center_freq < CHANNEL_FREQ_5950) 95 return CHANNEL_FREQ_5935; 96 97 if (center_freq < CHANNEL_FREQ_5950) { 98 if (chan_num == CHANNEL_NUM_14) 99 return CHANNEL_FREQ_2484; 100 if (chan_num < CHANNEL_NUM_14) 101 return CHANNEL_FREQ_2407 + 102 (chan_num * FREQ_MULTIPLIER_CONST_5MHZ); 103 104 if (chan_num < CHANNEL_NUM_27) 105 return CHANNEL_FREQ_2512 + 106 ((chan_num - CHANNEL_NUM_15) * 107 FREQ_MULTIPLIER_CONST_20MHZ); 108 109 if (chan_num > CHANNEL_NUM_182 && 110 chan_num < CHANNEL_NUM_197) 111 return ((chan_num * FREQ_MULTIPLIER_CONST_5MHZ) + 112 CHANNEL_FREQ_4000); 113 114 return CHANNEL_FREQ_5000 + 115 (chan_num * FREQ_MULTIPLIER_CONST_5MHZ); 116 } else { 117 return CHANNEL_FREQ_5950 + 118 (chan_num * FREQ_MULTIPLIER_CONST_5MHZ); 119 } 120 } 121 122 /** 123 * hal_get_hw_hptp_generic() - Get HW head and tail pointer value for any ring 124 * @hal_soc: Opaque HAL SOC handle 125 * @hal_ring_hdl: Source ring pointer 126 * @headp: Head Pointer 127 * @tailp: Tail Pointer 128 * @ring: Ring type 129 * 130 * Return: Update tail pointer and head pointer in arguments. 131 */ 132 static inline 133 void hal_get_hw_hptp_generic(struct hal_soc *hal_soc, 134 hal_ring_handle_t hal_ring_hdl, 135 uint32_t *headp, uint32_t *tailp, 136 uint8_t ring) 137 { 138 struct hal_srng *srng = (struct hal_srng *)hal_ring_hdl; 139 struct hal_hw_srng_config *ring_config; 140 enum hal_ring_type ring_type = (enum hal_ring_type)ring; 141 142 if (!hal_soc || !srng) { 143 QDF_TRACE(QDF_MODULE_ID_HAL, QDF_TRACE_LEVEL_ERROR, 144 "%s: Context is Null", __func__); 145 return; 146 } 147 148 ring_config = HAL_SRNG_CONFIG(hal_soc, ring_type); 149 if (!ring_config->lmac_ring) { 150 if (srng->ring_dir == HAL_SRNG_SRC_RING) { 151 *headp = SRNG_SRC_REG_READ(srng, HP); 152 *tailp = SRNG_SRC_REG_READ(srng, TP); 153 } else { 154 *headp = SRNG_DST_REG_READ(srng, HP); 155 *tailp = SRNG_DST_REG_READ(srng, TP); 156 } 157 } 158 } 159 160 #if defined(WBM_IDLE_LSB_WRITE_CONFIRM_WAR) 161 /** 162 * hal_wbm_idle_lsb_write_confirm() - Check and update WBM_IDLE_LINK ring LSB 163 * @srng: srng handle 164 * 165 * Return: None 166 */ 167 static void hal_wbm_idle_lsb_write_confirm(struct hal_srng *srng) 168 { 169 if (srng->ring_id == HAL_SRNG_WBM_IDLE_LINK) { 170 while (SRNG_SRC_REG_READ(srng, BASE_LSB) != 171 ((unsigned int)srng->ring_base_paddr & 0xffffffff)) 172 SRNG_SRC_REG_WRITE(srng, BASE_LSB, 173 srng->ring_base_paddr & 174 0xffffffff); 175 } 176 } 177 #else 178 static void hal_wbm_idle_lsb_write_confirm(struct hal_srng *srng) 179 { 180 } 181 #endif 182 183 #ifdef DP_UMAC_HW_RESET_SUPPORT 184 /** 185 * hal_srng_src_hw_write_cons_prefetch_timer() - Write cons prefetch timer reg 186 * @srng: srng handle 187 * @value: value to set 188 * 189 * Return: None 190 */ 191 static inline 192 void hal_srng_src_hw_write_cons_prefetch_timer(struct hal_srng *srng, 193 uint32_t value) 194 { 195 SRNG_SRC_REG_WRITE(srng, CONSUMER_PREFETCH_TIMER, value); 196 } 197 198 /** 199 * hal_srng_hw_disable_generic() - Private function to disable SRNG 200 * source ring HW 201 * @hal: HAL SOC handle 202 * @srng: SRNG ring pointer 203 */ 204 static inline 205 void hal_srng_hw_disable_generic(struct hal_soc *hal, struct hal_srng *srng) 206 { 207 uint32_t reg_val = 0; 208 209 if (srng->ring_dir == HAL_SRNG_DST_RING) { 210 reg_val = SRNG_DST_REG_READ(srng, MISC) & ~(SRNG_ENABLE_BIT); 211 SRNG_DST_REG_WRITE(srng, MISC, reg_val); 212 } else { 213 reg_val = SRNG_SRC_REG_READ(srng, MISC) & ~(SRNG_ENABLE_BIT); 214 SRNG_SRC_REG_WRITE(srng, MISC, reg_val); 215 srng->prefetch_timer = 216 SRNG_SRC_REG_READ(srng, CONSUMER_PREFETCH_TIMER); 217 hal_srng_src_hw_write_cons_prefetch_timer(srng, 0); 218 } 219 } 220 #else 221 static inline 222 void hal_srng_hw_disable_generic(struct hal_soc *hal, struct hal_srng *srng) 223 { 224 } 225 226 static inline 227 void hal_srng_src_hw_write_cons_prefetch_timer(struct hal_srng *srng, 228 uint32_t value) 229 { 230 } 231 #endif 232 /** 233 * hal_srng_src_hw_init_generic() - Private function to initialize SRNG 234 * source ring HW 235 * @hal: HAL SOC handle 236 * @srng: SRNG ring pointer 237 * @idle_check: Check if ring is idle 238 * @idx: ring index 239 */ 240 static inline 241 void hal_srng_src_hw_init_generic(struct hal_soc *hal, 242 struct hal_srng *srng, bool idle_check, 243 uint32_t idx) 244 { 245 uint32_t reg_val = 0; 246 uint64_t tp_addr = 0; 247 248 if (idle_check) { 249 reg_val = SRNG_SRC_REG_READ(srng, MISC); 250 if (!(reg_val & SRNG_IDLE_STATE_BIT)) { 251 hal_err("ring_id %d not in idle state", srng->ring_id); 252 qdf_assert_always(0); 253 } 254 255 hal_srng_src_hw_write_cons_prefetch_timer(srng, 256 srng->prefetch_timer); 257 } 258 259 hal_debug("hw_init srng %d", srng->ring_id); 260 261 reg_val = SRNG_SRC_REG_READ(srng, MISC) & ~(SRNG_ENABLE_BIT); 262 SRNG_SRC_REG_WRITE(srng, MISC, reg_val); 263 264 reg_val = 0; 265 266 if (srng->flags & HAL_SRNG_MSI_INTR) { 267 SRNG_SRC_REG_WRITE(srng, MSI1_BASE_LSB, 268 srng->msi_addr & 0xffffffff); 269 reg_val = SRNG_SM(SRNG_SRC_FLD(MSI1_BASE_MSB, ADDR), 270 (uint64_t)(srng->msi_addr) >> 32) | 271 SRNG_SM(SRNG_SRC_FLD(MSI1_BASE_MSB, 272 MSI1_ENABLE), 1); 273 SRNG_SRC_REG_WRITE(srng, MSI1_BASE_MSB, reg_val); 274 SRNG_SRC_REG_WRITE(srng, MSI1_DATA, 275 qdf_cpu_to_le32(srng->msi_data)); 276 } 277 278 SRNG_SRC_REG_WRITE(srng, BASE_LSB, srng->ring_base_paddr & 0xffffffff); 279 hal_wbm_idle_lsb_write_confirm(srng); 280 281 reg_val = SRNG_SM(SRNG_SRC_FLD(BASE_MSB, RING_BASE_ADDR_MSB), 282 ((uint64_t)(srng->ring_base_paddr) >> 32)) | 283 SRNG_SM(SRNG_SRC_FLD(BASE_MSB, RING_SIZE), 284 srng->entry_size * srng->num_entries); 285 SRNG_SRC_REG_WRITE(srng, BASE_MSB, reg_val); 286 287 reg_val = SRNG_SM(SRNG_SRC_FLD(ID, ENTRY_SIZE), srng->entry_size); 288 SRNG_SRC_REG_WRITE(srng, ID, reg_val); 289 290 /** 291 * Interrupt setup: 292 * Default interrupt mode is 'pulse'. Need to setup SW_INTERRUPT_MODE 293 * if level mode is required 294 */ 295 reg_val = 0; 296 297 /* 298 * WAR - Hawkeye v1 has a hardware bug which requires timer value to be 299 * programmed in terms of 1us resolution instead of 8us resolution as 300 * given in MLD. 301 */ 302 if (srng->intr_timer_thres_us) { 303 reg_val |= SRNG_SM(SRNG_SRC_FLD(CONSUMER_INT_SETUP_IX0, 304 INTERRUPT_TIMER_THRESHOLD), 305 srng->intr_timer_thres_us); 306 /* For HK v2 this should be (srng->intr_timer_thres_us >> 3) */ 307 } 308 309 if (srng->intr_batch_cntr_thres_entries) { 310 reg_val |= SRNG_SM(SRNG_SRC_FLD(CONSUMER_INT_SETUP_IX0, 311 BATCH_COUNTER_THRESHOLD), 312 srng->intr_batch_cntr_thres_entries * 313 srng->entry_size); 314 } 315 SRNG_SRC_REG_WRITE(srng, CONSUMER_INT_SETUP_IX0, reg_val); 316 317 reg_val = 0; 318 if (srng->flags & HAL_SRNG_LOW_THRES_INTR_ENABLE) { 319 reg_val |= SRNG_SM(SRNG_SRC_FLD(CONSUMER_INT_SETUP_IX1, 320 LOW_THRESHOLD), srng->u.src_ring.low_threshold); 321 } 322 323 SRNG_SRC_REG_WRITE(srng, CONSUMER_INT_SETUP_IX1, reg_val); 324 325 /* As per HW team, TP_ADDR and HP_ADDR for Idle link ring should 326 * remain 0 to avoid some WBM stability issues. Remote head/tail 327 * pointers are not required since this ring is completely managed 328 * by WBM HW 329 */ 330 reg_val = 0; 331 if (srng->ring_id != HAL_SRNG_WBM_IDLE_LINK) { 332 tp_addr = (uint64_t)(hal->shadow_rdptr_mem_paddr + 333 ((unsigned long)(srng->u.src_ring.tp_addr) - 334 (unsigned long)(hal->shadow_rdptr_mem_vaddr))); 335 SRNG_SRC_REG_WRITE(srng, TP_ADDR_LSB, tp_addr & 0xffffffff); 336 SRNG_SRC_REG_WRITE(srng, TP_ADDR_MSB, tp_addr >> 32); 337 } else { 338 reg_val |= SRNG_SM(SRNG_SRC_FLD(MISC, RING_ID_DISABLE), 1); 339 } 340 341 /* Initilaize head and tail pointers to indicate ring is empty */ 342 SRNG_SRC_REG_WRITE(srng, HP, idx * srng->entry_size); 343 SRNG_SRC_REG_WRITE(srng, TP, idx * srng->entry_size); 344 *srng->u.src_ring.tp_addr = idx * srng->entry_size; 345 srng->u.src_ring.hp = idx * srng->entry_size; 346 347 reg_val |= ((srng->flags & HAL_SRNG_DATA_TLV_SWAP) ? 348 SRNG_SM(SRNG_SRC_FLD(MISC, DATA_TLV_SWAP_BIT), 1) : 0) | 349 ((srng->flags & HAL_SRNG_RING_PTR_SWAP) ? 350 SRNG_SM(SRNG_SRC_FLD(MISC, HOST_FW_SWAP_BIT), 1) : 0) | 351 ((srng->flags & HAL_SRNG_MSI_SWAP) ? 352 SRNG_SM(SRNG_SRC_FLD(MISC, MSI_SWAP_BIT), 1) : 0); 353 354 /* Loop count is not used for SRC rings */ 355 reg_val |= SRNG_SM(SRNG_SRC_FLD(MISC, LOOPCNT_DISABLE), 1); 356 357 /* 358 * reg_val |= SRNG_SM(SRNG_SRC_FLD(MISC, SRNG_ENABLE), 1); 359 * todo: update fw_api and replace with above line 360 * (when SRNG_ENABLE field for the MISC register is available in fw_api) 361 * (WCSS_UMAC_CE_0_SRC_WFSS_CE_CHANNEL_SRC_R0_SRC_RING_MISC) 362 */ 363 reg_val |= SRNG_ENABLE_BIT; 364 365 SRNG_SRC_REG_WRITE(srng, MISC, reg_val); 366 } 367 368 #ifdef WLAN_FEATURE_NEAR_FULL_IRQ 369 /** 370 * hal_srng_dst_msi2_setup() - Configure MSI2 register for a SRNG 371 * @srng: SRNG handle 372 * 373 * Return: None 374 */ 375 static inline void hal_srng_dst_msi2_setup(struct hal_srng *srng) 376 { 377 uint32_t reg_val = 0; 378 379 if (srng->u.dst_ring.nf_irq_support) { 380 SRNG_DST_REG_WRITE(srng, MSI2_BASE_LSB, 381 srng->msi2_addr & 0xffffffff); 382 reg_val = SRNG_SM(SRNG_DST_FLD(MSI2_BASE_MSB, ADDR), 383 (uint64_t)(srng->msi2_addr) >> 32) | 384 SRNG_SM(SRNG_DST_FLD(MSI2_BASE_MSB, 385 MSI2_ENABLE), 1); 386 SRNG_DST_REG_WRITE(srng, MSI2_BASE_MSB, reg_val); 387 SRNG_DST_REG_WRITE(srng, MSI2_DATA, 388 qdf_cpu_to_le32(srng->msi2_data)); 389 } 390 } 391 392 /** 393 * hal_srng_dst_near_full_int_setup() - Configure near-full params for SRNG 394 * @srng: SRNG handle 395 * 396 * Return: None 397 */ 398 static inline void hal_srng_dst_near_full_int_setup(struct hal_srng *srng) 399 { 400 uint32_t reg_val = 0; 401 402 if (srng->u.dst_ring.nf_irq_support) { 403 if (srng->intr_timer_thres_us) { 404 reg_val |= SRNG_SM(SRNG_DST_FLD(PRODUCER_INT2_SETUP, 405 INTERRUPT2_TIMER_THRESHOLD), 406 srng->intr_timer_thres_us >> 3); 407 } 408 409 reg_val |= SRNG_SM(SRNG_DST_FLD(PRODUCER_INT2_SETUP, 410 HIGH_THRESHOLD), 411 srng->u.dst_ring.high_thresh * 412 srng->entry_size); 413 } 414 415 SRNG_DST_REG_WRITE(srng, PRODUCER_INT2_SETUP, reg_val); 416 } 417 #else 418 static inline void hal_srng_dst_msi2_setup(struct hal_srng *srng) 419 { 420 } 421 422 static inline void hal_srng_dst_near_full_int_setup(struct hal_srng *srng) 423 { 424 } 425 #endif 426 427 /** 428 * hal_srng_dst_hw_init_generic() - Private function to initialize SRNG 429 * destination ring HW 430 * @hal: HAL SOC handle 431 * @srng: SRNG ring pointer 432 * @idle_check: Check if ring is idle 433 * @idx: Ring index 434 */ 435 static inline 436 void hal_srng_dst_hw_init_generic(struct hal_soc *hal, 437 struct hal_srng *srng, bool idle_check, 438 uint32_t idx) 439 { 440 uint32_t reg_val = 0; 441 uint64_t hp_addr = 0; 442 443 if (idle_check) { 444 reg_val = SRNG_DST_REG_READ(srng, MISC); 445 if (!(reg_val & SRNG_IDLE_STATE_BIT)) { 446 hal_err("ring_id %d not in idle state", srng->ring_id); 447 qdf_assert_always(0); 448 } 449 } 450 451 hal_debug("hw_init srng %d", srng->ring_id); 452 453 reg_val = SRNG_DST_REG_READ(srng, MISC) & ~(SRNG_ENABLE_BIT); 454 455 SRNG_DST_REG_WRITE(srng, MISC, reg_val); 456 457 reg_val = 0; 458 459 if (srng->flags & HAL_SRNG_MSI_INTR) { 460 SRNG_DST_REG_WRITE(srng, MSI1_BASE_LSB, 461 srng->msi_addr & 0xffffffff); 462 reg_val = SRNG_SM(SRNG_DST_FLD(MSI1_BASE_MSB, ADDR), 463 (uint64_t)(srng->msi_addr) >> 32) | 464 SRNG_SM(SRNG_DST_FLD(MSI1_BASE_MSB, 465 MSI1_ENABLE), 1); 466 SRNG_DST_REG_WRITE(srng, MSI1_BASE_MSB, reg_val); 467 SRNG_DST_REG_WRITE(srng, MSI1_DATA, 468 qdf_cpu_to_le32(srng->msi_data)); 469 470 hal_srng_dst_msi2_setup(srng); 471 } 472 473 SRNG_DST_REG_WRITE(srng, BASE_LSB, srng->ring_base_paddr & 0xffffffff); 474 reg_val = SRNG_SM(SRNG_DST_FLD(BASE_MSB, RING_BASE_ADDR_MSB), 475 ((uint64_t)(srng->ring_base_paddr) >> 32)) | 476 SRNG_SM(SRNG_DST_FLD(BASE_MSB, RING_SIZE), 477 srng->entry_size * srng->num_entries); 478 SRNG_DST_REG_WRITE(srng, BASE_MSB, reg_val); 479 480 reg_val = SRNG_SM(SRNG_DST_FLD(ID, RING_ID), srng->ring_id) | 481 SRNG_SM(SRNG_DST_FLD(ID, ENTRY_SIZE), srng->entry_size); 482 SRNG_DST_REG_WRITE(srng, ID, reg_val); 483 484 485 /** 486 * Interrupt setup: 487 * Default interrupt mode is 'pulse'. Need to setup SW_INTERRUPT_MODE 488 * if level mode is required 489 */ 490 reg_val = 0; 491 if (srng->intr_timer_thres_us) { 492 reg_val |= SRNG_SM(SRNG_DST_FLD(PRODUCER_INT_SETUP, 493 INTERRUPT_TIMER_THRESHOLD), 494 srng->intr_timer_thres_us >> 3); 495 } 496 497 if (srng->intr_batch_cntr_thres_entries) { 498 reg_val |= SRNG_SM(SRNG_DST_FLD(PRODUCER_INT_SETUP, 499 BATCH_COUNTER_THRESHOLD), 500 srng->intr_batch_cntr_thres_entries * 501 srng->entry_size); 502 } 503 504 SRNG_DST_REG_WRITE(srng, PRODUCER_INT_SETUP, reg_val); 505 506 /** 507 * Near-Full Interrupt setup: 508 * Default interrupt mode is 'pulse'. Need to setup SW_INTERRUPT_MODE 509 * if level mode is required 510 */ 511 hal_srng_dst_near_full_int_setup(srng); 512 513 hp_addr = (uint64_t)(hal->shadow_rdptr_mem_paddr + 514 ((unsigned long)(srng->u.dst_ring.hp_addr) - 515 (unsigned long)(hal->shadow_rdptr_mem_vaddr))); 516 SRNG_DST_REG_WRITE(srng, HP_ADDR_LSB, hp_addr & 0xffffffff); 517 SRNG_DST_REG_WRITE(srng, HP_ADDR_MSB, hp_addr >> 32); 518 519 /* Initilaize head and tail pointers to indicate ring is empty */ 520 SRNG_DST_REG_WRITE(srng, HP, idx * srng->entry_size); 521 SRNG_DST_REG_WRITE(srng, TP, idx * srng->entry_size); 522 *srng->u.dst_ring.hp_addr = idx * srng->entry_size; 523 srng->u.dst_ring.tp = idx * srng->entry_size; 524 525 reg_val = ((srng->flags & HAL_SRNG_DATA_TLV_SWAP) ? 526 SRNG_SM(SRNG_DST_FLD(MISC, DATA_TLV_SWAP_BIT), 1) : 0) | 527 ((srng->flags & HAL_SRNG_RING_PTR_SWAP) ? 528 SRNG_SM(SRNG_DST_FLD(MISC, HOST_FW_SWAP_BIT), 1) : 0) | 529 ((srng->flags & HAL_SRNG_MSI_SWAP) ? 530 SRNG_SM(SRNG_DST_FLD(MISC, MSI_SWAP_BIT), 1) : 0); 531 532 /* 533 * reg_val |= SRNG_SM(SRNG_SRC_FLD(MISC, SRNG_ENABLE), 1); 534 * todo: update fw_api and replace with above line 535 * (when SRNG_ENABLE field for the MISC register is available in fw_api) 536 * (WCSS_UMAC_CE_0_SRC_WFSS_CE_CHANNEL_SRC_R0_SRC_RING_MISC) 537 */ 538 reg_val |= 0x40; 539 540 SRNG_DST_REG_WRITE(srng, MISC, reg_val); 541 542 } 543 544 /** 545 * hal_srng_hw_reg_offset_init_generic() - Initialize the HW srng reg offset 546 * @hal_soc: HAL Soc handle 547 * 548 * Return: None 549 */ 550 static inline void hal_srng_hw_reg_offset_init_generic(struct hal_soc *hal_soc) 551 { 552 int32_t *hw_reg_offset = hal_soc->hal_hw_reg_offset; 553 554 /* dst */ 555 hw_reg_offset[DST_HP] = REG_OFFSET(DST, HP); 556 hw_reg_offset[DST_TP] = REG_OFFSET(DST, TP); 557 hw_reg_offset[DST_ID] = REG_OFFSET(DST, ID); 558 hw_reg_offset[DST_MISC] = REG_OFFSET(DST, MISC); 559 hw_reg_offset[DST_HP_ADDR_LSB] = REG_OFFSET(DST, HP_ADDR_LSB); 560 hw_reg_offset[DST_HP_ADDR_MSB] = REG_OFFSET(DST, HP_ADDR_MSB); 561 hw_reg_offset[DST_MSI1_BASE_LSB] = REG_OFFSET(DST, MSI1_BASE_LSB); 562 hw_reg_offset[DST_MSI1_BASE_MSB] = REG_OFFSET(DST, MSI1_BASE_MSB); 563 hw_reg_offset[DST_MSI1_DATA] = REG_OFFSET(DST, MSI1_DATA); 564 hw_reg_offset[DST_BASE_LSB] = REG_OFFSET(DST, BASE_LSB); 565 hw_reg_offset[DST_BASE_MSB] = REG_OFFSET(DST, BASE_MSB); 566 hw_reg_offset[DST_PRODUCER_INT_SETUP] = 567 REG_OFFSET(DST, PRODUCER_INT_SETUP); 568 569 /* src */ 570 hw_reg_offset[SRC_HP] = REG_OFFSET(SRC, HP); 571 hw_reg_offset[SRC_TP] = REG_OFFSET(SRC, TP); 572 hw_reg_offset[SRC_ID] = REG_OFFSET(SRC, ID); 573 hw_reg_offset[SRC_MISC] = REG_OFFSET(SRC, MISC); 574 hw_reg_offset[SRC_TP_ADDR_LSB] = REG_OFFSET(SRC, TP_ADDR_LSB); 575 hw_reg_offset[SRC_TP_ADDR_MSB] = REG_OFFSET(SRC, TP_ADDR_MSB); 576 hw_reg_offset[SRC_MSI1_BASE_LSB] = REG_OFFSET(SRC, MSI1_BASE_LSB); 577 hw_reg_offset[SRC_MSI1_BASE_MSB] = REG_OFFSET(SRC, MSI1_BASE_MSB); 578 hw_reg_offset[SRC_MSI1_DATA] = REG_OFFSET(SRC, MSI1_DATA); 579 hw_reg_offset[SRC_BASE_LSB] = REG_OFFSET(SRC, BASE_LSB); 580 hw_reg_offset[SRC_BASE_MSB] = REG_OFFSET(SRC, BASE_MSB); 581 hw_reg_offset[SRC_CONSUMER_INT_SETUP_IX0] = 582 REG_OFFSET(SRC, CONSUMER_INT_SETUP_IX0); 583 hw_reg_offset[SRC_CONSUMER_INT_SETUP_IX1] = 584 REG_OFFSET(SRC, CONSUMER_INT_SETUP_IX1); 585 #ifdef DP_UMAC_HW_RESET_SUPPORT 586 hw_reg_offset[SRC_CONSUMER_PREFETCH_TIMER] = 587 REG_OFFSET(SRC, CONSUMER_PREFETCH_TIMER); 588 #endif 589 } 590 591 #ifdef FEATURE_DIRECT_LINK 592 /** 593 * hal_srng_set_msi_config() - Set the MSI config and enable the SRNG 594 * @ring_hdl: srng handle 595 * @params: ring parameters 596 * 597 * Return: QDF status 598 */ 599 static inline 600 QDF_STATUS hal_srng_set_msi_config(hal_ring_handle_t ring_hdl, 601 void *params) 602 { 603 struct hal_srng *srng = (struct hal_srng *)ring_hdl; 604 struct hal_srng_params *ring_params = (struct hal_srng_params *)params; 605 uint32_t reg_val; 606 607 srng->intr_timer_thres_us = ring_params->intr_timer_thres_us; 608 srng->intr_batch_cntr_thres_entries = 609 ring_params->intr_batch_cntr_thres_entries; 610 srng->msi_addr = ring_params->msi_addr; 611 srng->msi_data = ring_params->msi_data; 612 613 if (srng->ring_dir == HAL_SRNG_SRC_RING) { 614 reg_val = 0; 615 616 SRNG_SRC_REG_WRITE(srng, MSI1_BASE_LSB, 617 srng->msi_addr & 0xffffffff); 618 reg_val = SRNG_SM(SRNG_SRC_FLD(MSI1_BASE_MSB, ADDR), 619 (uint64_t)(srng->msi_addr) >> 32) | 620 SRNG_SM(SRNG_SRC_FLD(MSI1_BASE_MSB, 621 MSI1_ENABLE), 1); 622 SRNG_SRC_REG_WRITE(srng, MSI1_BASE_MSB, reg_val); 623 SRNG_SRC_REG_WRITE(srng, MSI1_DATA, 624 qdf_cpu_to_le32(srng->msi_data)); 625 626 reg_val = 0; 627 628 if (srng->intr_timer_thres_us) { 629 reg_val |= SRNG_SM(SRNG_SRC_FLD(CONSUMER_INT_SETUP_IX0, 630 INTERRUPT_TIMER_THRESHOLD), 631 srng->intr_timer_thres_us); 632 } 633 634 if (srng->intr_batch_cntr_thres_entries) { 635 reg_val |= SRNG_SM(SRNG_SRC_FLD(CONSUMER_INT_SETUP_IX0, 636 BATCH_COUNTER_THRESHOLD), 637 srng->intr_batch_cntr_thres_entries * 638 srng->entry_size); 639 } 640 SRNG_SRC_REG_WRITE(srng, CONSUMER_INT_SETUP_IX0, reg_val); 641 } else { 642 reg_val = 0; 643 644 SRNG_DST_REG_WRITE(srng, MSI1_BASE_LSB, 645 srng->msi_addr & 0xffffffff); 646 reg_val = SRNG_SM(SRNG_DST_FLD(MSI1_BASE_MSB, ADDR), 647 (uint64_t)(srng->msi_addr) >> 32) | 648 SRNG_SM(SRNG_DST_FLD(MSI1_BASE_MSB, 649 MSI1_ENABLE), 1); 650 SRNG_DST_REG_WRITE(srng, MSI1_BASE_MSB, reg_val); 651 SRNG_DST_REG_WRITE(srng, MSI1_DATA, 652 qdf_cpu_to_le32(srng->msi_data)); 653 654 reg_val = 0; 655 656 if (srng->intr_timer_thres_us) { 657 reg_val |= SRNG_SM(SRNG_DST_FLD(PRODUCER_INT_SETUP, 658 INTERRUPT_TIMER_THRESHOLD), 659 srng->intr_timer_thres_us >> 3); 660 } 661 662 if (srng->intr_batch_cntr_thres_entries) { 663 reg_val |= SRNG_SM(SRNG_DST_FLD(PRODUCER_INT_SETUP, 664 BATCH_COUNTER_THRESHOLD), 665 srng->intr_batch_cntr_thres_entries * 666 srng->entry_size); 667 } 668 669 SRNG_DST_REG_WRITE(srng, PRODUCER_INT_SETUP, reg_val); 670 } 671 672 return QDF_STATUS_SUCCESS; 673 } 674 #else 675 static inline 676 QDF_STATUS hal_srng_set_msi_config(hal_ring_handle_t ring_hdl, 677 void *params) 678 { 679 return QDF_STATUS_E_NOSUPPORT; 680 } 681 #endif 682 #endif /* HAL_GENERIC_API_H_ */ 683