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