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 #ifdef DP_UMAC_HW_RESET_SUPPORT 161 /** 162 * hal_srng_src_hw_write_cons_prefetch_timer() - Write cons prefetch timer reg 163 * @srng: srng handle 164 * @value: value to set 165 * 166 * Return: None 167 */ 168 static inline 169 void hal_srng_src_hw_write_cons_prefetch_timer(struct hal_srng *srng, 170 uint32_t value) 171 { 172 SRNG_SRC_REG_WRITE(srng, CONSUMER_PREFETCH_TIMER, value); 173 } 174 175 /** 176 * hal_srng_hw_disable_generic() - Private function to disable SRNG 177 * source ring HW 178 * @hal: HAL SOC handle 179 * @srng: SRNG ring pointer 180 */ 181 static inline 182 void hal_srng_hw_disable_generic(struct hal_soc *hal, struct hal_srng *srng) 183 { 184 uint32_t reg_val = 0; 185 186 if (srng->ring_dir == HAL_SRNG_DST_RING) { 187 reg_val = SRNG_DST_REG_READ(srng, MISC) & ~(SRNG_ENABLE_BIT); 188 SRNG_DST_REG_WRITE(srng, MISC, reg_val); 189 } else { 190 reg_val = SRNG_SRC_REG_READ(srng, MISC) & ~(SRNG_ENABLE_BIT); 191 SRNG_SRC_REG_WRITE(srng, MISC, reg_val); 192 srng->prefetch_timer = 193 SRNG_SRC_REG_READ(srng, CONSUMER_PREFETCH_TIMER); 194 hal_srng_src_hw_write_cons_prefetch_timer(srng, 0); 195 } 196 } 197 #else 198 static inline 199 void hal_srng_hw_disable_generic(struct hal_soc *hal, struct hal_srng *srng) 200 { 201 } 202 203 static inline 204 void hal_srng_src_hw_write_cons_prefetch_timer(struct hal_srng *srng, 205 uint32_t value) 206 { 207 } 208 #endif 209 210 #ifndef WLAN_SOFTUMAC_SUPPORT 211 #if defined(WBM_IDLE_LSB_WRITE_CONFIRM_WAR) 212 /** 213 * hal_wbm_idle_lsb_write_confirm() - Check and update WBM_IDLE_LINK ring LSB 214 * @srng: srng handle 215 * 216 * Return: None 217 */ 218 static void hal_wbm_idle_lsb_write_confirm(struct hal_srng *srng) 219 { 220 if (srng->ring_id == HAL_SRNG_WBM_IDLE_LINK) { 221 while (SRNG_SRC_REG_READ(srng, BASE_LSB) != 222 ((unsigned int)srng->ring_base_paddr & 0xffffffff)) 223 SRNG_SRC_REG_WRITE(srng, BASE_LSB, 224 srng->ring_base_paddr & 225 0xffffffff); 226 } 227 } 228 #else 229 static void hal_wbm_idle_lsb_write_confirm(struct hal_srng *srng) 230 { 231 } 232 #endif 233 234 /** 235 * hal_srng_src_hw_init_generic() - Private function to initialize SRNG 236 * source ring HW 237 * @hal: HAL SOC handle 238 * @srng: SRNG ring pointer 239 * @idle_check: Check if ring is idle 240 * @idx: ring index 241 */ 242 static inline 243 void hal_srng_src_hw_init_generic(struct hal_soc *hal, 244 struct hal_srng *srng, bool idle_check, 245 uint32_t idx) 246 { 247 uint32_t reg_val = 0; 248 uint64_t tp_addr = 0; 249 250 if (idle_check) { 251 reg_val = SRNG_SRC_REG_READ(srng, MISC); 252 if (!(reg_val & SRNG_IDLE_STATE_BIT)) { 253 hal_err("ring_id %d not in idle state", srng->ring_id); 254 qdf_assert_always(0); 255 } 256 257 hal_srng_src_hw_write_cons_prefetch_timer(srng, 258 srng->prefetch_timer); 259 } 260 261 hal_debug("hw_init srng %d", srng->ring_id); 262 263 reg_val = SRNG_SRC_REG_READ(srng, MISC) & ~(SRNG_ENABLE_BIT); 264 SRNG_SRC_REG_WRITE(srng, MISC, reg_val); 265 266 reg_val = 0; 267 268 if (srng->flags & HAL_SRNG_MSI_INTR) { 269 SRNG_SRC_REG_WRITE(srng, MSI1_BASE_LSB, 270 srng->msi_addr & 0xffffffff); 271 reg_val = SRNG_SM(SRNG_SRC_FLD(MSI1_BASE_MSB, ADDR), 272 (uint64_t)(srng->msi_addr) >> 32) | 273 SRNG_SM(SRNG_SRC_FLD(MSI1_BASE_MSB, 274 MSI1_ENABLE), 1); 275 SRNG_SRC_REG_WRITE(srng, MSI1_BASE_MSB, reg_val); 276 SRNG_SRC_REG_WRITE(srng, MSI1_DATA, 277 qdf_cpu_to_le32(srng->msi_data)); 278 } 279 280 SRNG_SRC_REG_WRITE(srng, BASE_LSB, srng->ring_base_paddr & 0xffffffff); 281 hal_wbm_idle_lsb_write_confirm(srng); 282 283 reg_val = SRNG_SM(SRNG_SRC_FLD(BASE_MSB, RING_BASE_ADDR_MSB), 284 ((uint64_t)(srng->ring_base_paddr) >> 32)) | 285 SRNG_SM(SRNG_SRC_FLD(BASE_MSB, RING_SIZE), 286 srng->entry_size * srng->num_entries); 287 SRNG_SRC_REG_WRITE(srng, BASE_MSB, reg_val); 288 289 reg_val = SRNG_SM(SRNG_SRC_FLD(ID, ENTRY_SIZE), srng->entry_size); 290 SRNG_SRC_REG_WRITE(srng, ID, reg_val); 291 292 /** 293 * Interrupt setup: 294 * Default interrupt mode is 'pulse'. Need to setup SW_INTERRUPT_MODE 295 * if level mode is required 296 */ 297 reg_val = 0; 298 299 /* 300 * WAR - Hawkeye v1 has a hardware bug which requires timer value to be 301 * programmed in terms of 1us resolution instead of 8us resolution as 302 * given in MLD. 303 */ 304 if (srng->intr_timer_thres_us) { 305 reg_val |= SRNG_SM(SRNG_SRC_FLD(CONSUMER_INT_SETUP_IX0, 306 INTERRUPT_TIMER_THRESHOLD), 307 srng->intr_timer_thres_us); 308 /* For HK v2 this should be (srng->intr_timer_thres_us >> 3) */ 309 } 310 311 if (srng->intr_batch_cntr_thres_entries) { 312 reg_val |= SRNG_SM(SRNG_SRC_FLD(CONSUMER_INT_SETUP_IX0, 313 BATCH_COUNTER_THRESHOLD), 314 srng->intr_batch_cntr_thres_entries * 315 srng->entry_size); 316 } 317 SRNG_SRC_REG_WRITE(srng, CONSUMER_INT_SETUP_IX0, reg_val); 318 319 reg_val = 0; 320 if (srng->flags & HAL_SRNG_LOW_THRES_INTR_ENABLE) { 321 reg_val |= SRNG_SM(SRNG_SRC_FLD(CONSUMER_INT_SETUP_IX1, 322 LOW_THRESHOLD), srng->u.src_ring.low_threshold); 323 } 324 325 SRNG_SRC_REG_WRITE(srng, CONSUMER_INT_SETUP_IX1, reg_val); 326 327 /* As per HW team, TP_ADDR and HP_ADDR for Idle link ring should 328 * remain 0 to avoid some WBM stability issues. Remote head/tail 329 * pointers are not required since this ring is completely managed 330 * by WBM HW 331 */ 332 reg_val = 0; 333 if (srng->ring_id != HAL_SRNG_WBM_IDLE_LINK) { 334 tp_addr = (uint64_t)(hal->shadow_rdptr_mem_paddr + 335 ((unsigned long)(srng->u.src_ring.tp_addr) - 336 (unsigned long)(hal->shadow_rdptr_mem_vaddr))); 337 SRNG_SRC_REG_WRITE(srng, TP_ADDR_LSB, tp_addr & 0xffffffff); 338 SRNG_SRC_REG_WRITE(srng, TP_ADDR_MSB, tp_addr >> 32); 339 } else { 340 reg_val |= SRNG_SM(SRNG_SRC_FLD(MISC, RING_ID_DISABLE), 1); 341 } 342 343 /* Initilaize head and tail pointers to indicate ring is empty */ 344 SRNG_SRC_REG_WRITE(srng, HP, idx * srng->entry_size); 345 SRNG_SRC_REG_WRITE(srng, TP, idx * srng->entry_size); 346 *srng->u.src_ring.tp_addr = idx * srng->entry_size; 347 srng->u.src_ring.hp = idx * srng->entry_size; 348 349 reg_val |= ((srng->flags & HAL_SRNG_DATA_TLV_SWAP) ? 350 SRNG_SM(SRNG_SRC_FLD(MISC, DATA_TLV_SWAP_BIT), 1) : 0) | 351 ((srng->flags & HAL_SRNG_RING_PTR_SWAP) ? 352 SRNG_SM(SRNG_SRC_FLD(MISC, HOST_FW_SWAP_BIT), 1) : 0) | 353 ((srng->flags & HAL_SRNG_MSI_SWAP) ? 354 SRNG_SM(SRNG_SRC_FLD(MISC, MSI_SWAP_BIT), 1) : 0); 355 356 /* Loop count is not used for SRC rings */ 357 reg_val |= SRNG_SM(SRNG_SRC_FLD(MISC, LOOPCNT_DISABLE), 1); 358 359 /* 360 * reg_val |= SRNG_SM(SRNG_SRC_FLD(MISC, SRNG_ENABLE), 1); 361 * todo: update fw_api and replace with above line 362 * (when SRNG_ENABLE field for the MISC register is available in fw_api) 363 * (WCSS_UMAC_CE_0_SRC_WFSS_CE_CHANNEL_SRC_R0_SRC_RING_MISC) 364 */ 365 reg_val |= SRNG_ENABLE_BIT; 366 367 SRNG_SRC_REG_WRITE(srng, MISC, reg_val); 368 } 369 370 #ifdef WLAN_FEATURE_NEAR_FULL_IRQ 371 /** 372 * hal_srng_dst_msi2_setup() - Configure MSI2 register for a SRNG 373 * @srng: SRNG handle 374 * 375 * Return: None 376 */ 377 static inline void hal_srng_dst_msi2_setup(struct hal_srng *srng) 378 { 379 uint32_t reg_val = 0; 380 381 if (srng->u.dst_ring.nf_irq_support) { 382 SRNG_DST_REG_WRITE(srng, MSI2_BASE_LSB, 383 srng->msi2_addr & 0xffffffff); 384 reg_val = SRNG_SM(SRNG_DST_FLD(MSI2_BASE_MSB, ADDR), 385 (uint64_t)(srng->msi2_addr) >> 32) | 386 SRNG_SM(SRNG_DST_FLD(MSI2_BASE_MSB, 387 MSI2_ENABLE), 1); 388 SRNG_DST_REG_WRITE(srng, MSI2_BASE_MSB, reg_val); 389 SRNG_DST_REG_WRITE(srng, MSI2_DATA, 390 qdf_cpu_to_le32(srng->msi2_data)); 391 } 392 } 393 394 /** 395 * hal_srng_dst_near_full_int_setup() - Configure near-full params for SRNG 396 * @srng: SRNG handle 397 * 398 * Return: None 399 */ 400 static inline void hal_srng_dst_near_full_int_setup(struct hal_srng *srng) 401 { 402 uint32_t reg_val = 0; 403 404 if (srng->u.dst_ring.nf_irq_support) { 405 if (srng->intr_timer_thres_us) { 406 reg_val |= SRNG_SM(SRNG_DST_FLD(PRODUCER_INT2_SETUP, 407 INTERRUPT2_TIMER_THRESHOLD), 408 srng->intr_timer_thres_us >> 3); 409 } 410 411 reg_val |= SRNG_SM(SRNG_DST_FLD(PRODUCER_INT2_SETUP, 412 HIGH_THRESHOLD), 413 srng->u.dst_ring.high_thresh * 414 srng->entry_size); 415 } 416 417 SRNG_DST_REG_WRITE(srng, PRODUCER_INT2_SETUP, reg_val); 418 } 419 #else 420 static inline void hal_srng_dst_msi2_setup(struct hal_srng *srng) 421 { 422 } 423 424 static inline void hal_srng_dst_near_full_int_setup(struct hal_srng *srng) 425 { 426 } 427 #endif 428 429 /** 430 * hal_srng_dst_hw_init_generic() - Private function to initialize SRNG 431 * destination ring HW 432 * @hal: HAL SOC handle 433 * @srng: SRNG ring pointer 434 * @idle_check: Check if ring is idle 435 * @idx: Ring index 436 */ 437 static inline 438 void hal_srng_dst_hw_init_generic(struct hal_soc *hal, 439 struct hal_srng *srng, bool idle_check, 440 uint32_t idx) 441 { 442 uint32_t reg_val = 0; 443 uint64_t hp_addr = 0; 444 445 if (idle_check) { 446 reg_val = SRNG_DST_REG_READ(srng, MISC); 447 if (!(reg_val & SRNG_IDLE_STATE_BIT)) { 448 hal_err("ring_id %d not in idle state", srng->ring_id); 449 qdf_assert_always(0); 450 } 451 } 452 453 hal_debug("hw_init srng %d", srng->ring_id); 454 455 reg_val = SRNG_DST_REG_READ(srng, MISC) & ~(SRNG_ENABLE_BIT); 456 457 SRNG_DST_REG_WRITE(srng, MISC, reg_val); 458 459 reg_val = 0; 460 461 if (srng->flags & HAL_SRNG_MSI_INTR) { 462 SRNG_DST_REG_WRITE(srng, MSI1_BASE_LSB, 463 srng->msi_addr & 0xffffffff); 464 reg_val = SRNG_SM(SRNG_DST_FLD(MSI1_BASE_MSB, ADDR), 465 (uint64_t)(srng->msi_addr) >> 32) | 466 SRNG_SM(SRNG_DST_FLD(MSI1_BASE_MSB, 467 MSI1_ENABLE), 1); 468 SRNG_DST_REG_WRITE(srng, MSI1_BASE_MSB, reg_val); 469 SRNG_DST_REG_WRITE(srng, MSI1_DATA, 470 qdf_cpu_to_le32(srng->msi_data)); 471 472 hal_srng_dst_msi2_setup(srng); 473 } 474 475 SRNG_DST_REG_WRITE(srng, BASE_LSB, srng->ring_base_paddr & 0xffffffff); 476 reg_val = SRNG_SM(SRNG_DST_FLD(BASE_MSB, RING_BASE_ADDR_MSB), 477 ((uint64_t)(srng->ring_base_paddr) >> 32)) | 478 SRNG_SM(SRNG_DST_FLD(BASE_MSB, RING_SIZE), 479 srng->entry_size * srng->num_entries); 480 SRNG_DST_REG_WRITE(srng, BASE_MSB, reg_val); 481 482 reg_val = SRNG_SM(SRNG_DST_FLD(ID, RING_ID), srng->ring_id) | 483 SRNG_SM(SRNG_DST_FLD(ID, ENTRY_SIZE), srng->entry_size); 484 SRNG_DST_REG_WRITE(srng, ID, reg_val); 485 486 487 /** 488 * Interrupt setup: 489 * Default interrupt mode is 'pulse'. Need to setup SW_INTERRUPT_MODE 490 * if level mode is required 491 */ 492 reg_val = 0; 493 if (srng->intr_timer_thres_us) { 494 reg_val |= SRNG_SM(SRNG_DST_FLD(PRODUCER_INT_SETUP, 495 INTERRUPT_TIMER_THRESHOLD), 496 srng->intr_timer_thres_us >> 3); 497 } 498 499 if (srng->intr_batch_cntr_thres_entries) { 500 reg_val |= SRNG_SM(SRNG_DST_FLD(PRODUCER_INT_SETUP, 501 BATCH_COUNTER_THRESHOLD), 502 srng->intr_batch_cntr_thres_entries * 503 srng->entry_size); 504 } 505 506 SRNG_DST_REG_WRITE(srng, PRODUCER_INT_SETUP, reg_val); 507 508 /** 509 * Near-Full Interrupt setup: 510 * Default interrupt mode is 'pulse'. Need to setup SW_INTERRUPT_MODE 511 * if level mode is required 512 */ 513 hal_srng_dst_near_full_int_setup(srng); 514 515 hp_addr = (uint64_t)(hal->shadow_rdptr_mem_paddr + 516 ((unsigned long)(srng->u.dst_ring.hp_addr) - 517 (unsigned long)(hal->shadow_rdptr_mem_vaddr))); 518 SRNG_DST_REG_WRITE(srng, HP_ADDR_LSB, hp_addr & 0xffffffff); 519 SRNG_DST_REG_WRITE(srng, HP_ADDR_MSB, hp_addr >> 32); 520 521 /* Initilaize head and tail pointers to indicate ring is empty */ 522 SRNG_DST_REG_WRITE(srng, HP, idx * srng->entry_size); 523 SRNG_DST_REG_WRITE(srng, TP, idx * srng->entry_size); 524 *srng->u.dst_ring.hp_addr = idx * srng->entry_size; 525 srng->u.dst_ring.tp = idx * srng->entry_size; 526 527 reg_val = ((srng->flags & HAL_SRNG_DATA_TLV_SWAP) ? 528 SRNG_SM(SRNG_DST_FLD(MISC, DATA_TLV_SWAP_BIT), 1) : 0) | 529 ((srng->flags & HAL_SRNG_RING_PTR_SWAP) ? 530 SRNG_SM(SRNG_DST_FLD(MISC, HOST_FW_SWAP_BIT), 1) : 0) | 531 ((srng->flags & HAL_SRNG_MSI_SWAP) ? 532 SRNG_SM(SRNG_DST_FLD(MISC, MSI_SWAP_BIT), 1) : 0); 533 534 /* 535 * reg_val |= SRNG_SM(SRNG_SRC_FLD(MISC, SRNG_ENABLE), 1); 536 * todo: update fw_api and replace with above line 537 * (when SRNG_ENABLE field for the MISC register is available in fw_api) 538 * (WCSS_UMAC_CE_0_SRC_WFSS_CE_CHANNEL_SRC_R0_SRC_RING_MISC) 539 */ 540 reg_val |= 0x40; 541 542 SRNG_DST_REG_WRITE(srng, MISC, reg_val); 543 544 } 545 546 /** 547 * hal_srng_hw_reg_offset_init_generic() - Initialize the HW srng reg offset 548 * @hal_soc: HAL Soc handle 549 * 550 * Return: None 551 */ 552 static inline void hal_srng_hw_reg_offset_init_generic(struct hal_soc *hal_soc) 553 { 554 int32_t *hw_reg_offset = hal_soc->hal_hw_reg_offset; 555 556 /* dst */ 557 hw_reg_offset[DST_HP] = REG_OFFSET(DST, HP); 558 hw_reg_offset[DST_TP] = REG_OFFSET(DST, TP); 559 hw_reg_offset[DST_ID] = REG_OFFSET(DST, ID); 560 hw_reg_offset[DST_MISC] = REG_OFFSET(DST, MISC); 561 hw_reg_offset[DST_HP_ADDR_LSB] = REG_OFFSET(DST, HP_ADDR_LSB); 562 hw_reg_offset[DST_HP_ADDR_MSB] = REG_OFFSET(DST, HP_ADDR_MSB); 563 hw_reg_offset[DST_MSI1_BASE_LSB] = REG_OFFSET(DST, MSI1_BASE_LSB); 564 hw_reg_offset[DST_MSI1_BASE_MSB] = REG_OFFSET(DST, MSI1_BASE_MSB); 565 hw_reg_offset[DST_MSI1_DATA] = REG_OFFSET(DST, MSI1_DATA); 566 hw_reg_offset[DST_BASE_LSB] = REG_OFFSET(DST, BASE_LSB); 567 hw_reg_offset[DST_BASE_MSB] = REG_OFFSET(DST, BASE_MSB); 568 hw_reg_offset[DST_PRODUCER_INT_SETUP] = 569 REG_OFFSET(DST, PRODUCER_INT_SETUP); 570 571 /* src */ 572 hw_reg_offset[SRC_HP] = REG_OFFSET(SRC, HP); 573 hw_reg_offset[SRC_TP] = REG_OFFSET(SRC, TP); 574 hw_reg_offset[SRC_ID] = REG_OFFSET(SRC, ID); 575 hw_reg_offset[SRC_MISC] = REG_OFFSET(SRC, MISC); 576 hw_reg_offset[SRC_TP_ADDR_LSB] = REG_OFFSET(SRC, TP_ADDR_LSB); 577 hw_reg_offset[SRC_TP_ADDR_MSB] = REG_OFFSET(SRC, TP_ADDR_MSB); 578 hw_reg_offset[SRC_MSI1_BASE_LSB] = REG_OFFSET(SRC, MSI1_BASE_LSB); 579 hw_reg_offset[SRC_MSI1_BASE_MSB] = REG_OFFSET(SRC, MSI1_BASE_MSB); 580 hw_reg_offset[SRC_MSI1_DATA] = REG_OFFSET(SRC, MSI1_DATA); 581 hw_reg_offset[SRC_BASE_LSB] = REG_OFFSET(SRC, BASE_LSB); 582 hw_reg_offset[SRC_BASE_MSB] = REG_OFFSET(SRC, BASE_MSB); 583 hw_reg_offset[SRC_CONSUMER_INT_SETUP_IX0] = 584 REG_OFFSET(SRC, CONSUMER_INT_SETUP_IX0); 585 hw_reg_offset[SRC_CONSUMER_INT_SETUP_IX1] = 586 REG_OFFSET(SRC, CONSUMER_INT_SETUP_IX1); 587 #ifdef DP_UMAC_HW_RESET_SUPPORT 588 hw_reg_offset[SRC_CONSUMER_PREFETCH_TIMER] = 589 REG_OFFSET(SRC, CONSUMER_PREFETCH_TIMER); 590 #endif 591 } 592 #else 593 static inline 594 void hal_srng_src_hw_init_generic(struct hal_soc *hal, 595 struct hal_srng *srng, bool idle_check, 596 uint32_t idx) {} 597 598 static inline 599 void hal_srng_dst_hw_init_generic(struct hal_soc *hal, 600 struct hal_srng *srng, bool idle_check, 601 uint32_t idx) {} 602 #endif 603 604 #ifdef FEATURE_DIRECT_LINK 605 /** 606 * hal_srng_set_msi_config() - Set the MSI config and enable the SRNG 607 * @ring_hdl: srng handle 608 * @params: ring parameters 609 * 610 * Return: QDF status 611 */ 612 static inline 613 QDF_STATUS hal_srng_set_msi_config(hal_ring_handle_t ring_hdl, 614 void *params) 615 { 616 struct hal_srng *srng = (struct hal_srng *)ring_hdl; 617 struct hal_srng_params *ring_params = (struct hal_srng_params *)params; 618 uint32_t reg_val; 619 620 srng->intr_timer_thres_us = ring_params->intr_timer_thres_us; 621 srng->intr_batch_cntr_thres_entries = 622 ring_params->intr_batch_cntr_thres_entries; 623 srng->msi_addr = ring_params->msi_addr; 624 srng->msi_data = ring_params->msi_data; 625 626 if (srng->ring_dir == HAL_SRNG_SRC_RING) { 627 reg_val = 0; 628 629 SRNG_SRC_REG_WRITE(srng, MSI1_BASE_LSB, 630 srng->msi_addr & 0xffffffff); 631 reg_val = SRNG_SM(SRNG_SRC_FLD(MSI1_BASE_MSB, ADDR), 632 (uint64_t)(srng->msi_addr) >> 32) | 633 SRNG_SM(SRNG_SRC_FLD(MSI1_BASE_MSB, 634 MSI1_ENABLE), 1); 635 SRNG_SRC_REG_WRITE(srng, MSI1_BASE_MSB, reg_val); 636 SRNG_SRC_REG_WRITE(srng, MSI1_DATA, 637 qdf_cpu_to_le32(srng->msi_data)); 638 639 reg_val = 0; 640 641 if (srng->intr_timer_thres_us) { 642 reg_val |= SRNG_SM(SRNG_SRC_FLD(CONSUMER_INT_SETUP_IX0, 643 INTERRUPT_TIMER_THRESHOLD), 644 srng->intr_timer_thres_us); 645 } 646 647 if (srng->intr_batch_cntr_thres_entries) { 648 reg_val |= SRNG_SM(SRNG_SRC_FLD(CONSUMER_INT_SETUP_IX0, 649 BATCH_COUNTER_THRESHOLD), 650 srng->intr_batch_cntr_thres_entries * 651 srng->entry_size); 652 } 653 SRNG_SRC_REG_WRITE(srng, CONSUMER_INT_SETUP_IX0, reg_val); 654 } else { 655 reg_val = 0; 656 657 SRNG_DST_REG_WRITE(srng, MSI1_BASE_LSB, 658 srng->msi_addr & 0xffffffff); 659 reg_val = SRNG_SM(SRNG_DST_FLD(MSI1_BASE_MSB, ADDR), 660 (uint64_t)(srng->msi_addr) >> 32) | 661 SRNG_SM(SRNG_DST_FLD(MSI1_BASE_MSB, 662 MSI1_ENABLE), 1); 663 SRNG_DST_REG_WRITE(srng, MSI1_BASE_MSB, reg_val); 664 SRNG_DST_REG_WRITE(srng, MSI1_DATA, 665 qdf_cpu_to_le32(srng->msi_data)); 666 667 reg_val = 0; 668 669 if (srng->intr_timer_thres_us) { 670 reg_val |= SRNG_SM(SRNG_DST_FLD(PRODUCER_INT_SETUP, 671 INTERRUPT_TIMER_THRESHOLD), 672 srng->intr_timer_thres_us >> 3); 673 } 674 675 if (srng->intr_batch_cntr_thres_entries) { 676 reg_val |= SRNG_SM(SRNG_DST_FLD(PRODUCER_INT_SETUP, 677 BATCH_COUNTER_THRESHOLD), 678 srng->intr_batch_cntr_thres_entries * 679 srng->entry_size); 680 } 681 682 SRNG_DST_REG_WRITE(srng, PRODUCER_INT_SETUP, reg_val); 683 } 684 685 return QDF_STATUS_SUCCESS; 686 } 687 #else 688 static inline 689 QDF_STATUS hal_srng_set_msi_config(hal_ring_handle_t ring_hdl, 690 void *params) 691 { 692 return QDF_STATUS_E_NOSUPPORT; 693 } 694 #endif 695 #endif /* HAL_GENERIC_API_H_ */ 696