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