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