xref: /wlan-dirver/qca-wifi-host-cmn/hal/wifi3.0/hal_generic_api.h (revision 70a19e16789e308182f63b15c75decec7bf0b342)
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  * @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 - Private function to initialize SRNG
429  * destination ring HW
430  * @hal_soc: 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  * @hal_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