xref: /wlan-dirver/qca-wifi-host-cmn/hal/wifi3.0/hal_generic_api.h (revision ed7ed761f307f964abd13da4df8dcb908086bd83)
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