1 /*
2 * Copyright (c) 2022 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5 */
6
7 /**
8 * @brief Implements PCIe bus ops to initialize and read/write on a PCIe bus
9 */
10 #include "bal_structs.h"
11 #include "pcie.h"
12 #include "common/pal.h"
13
14 #define NRF_WIFI_PCIE_DEV_NAME "nrfwifi0"
15
nrf_wifi_bus_pcie_irq_handler(void * data)16 int nrf_wifi_bus_pcie_irq_handler(void *data)
17 {
18 struct nrf_wifi_bus_pcie_dev_ctx *dev_ctx = NULL;
19 struct nrf_wifi_bus_pcie_priv *pcie_priv = NULL;
20 int ret = 0;
21
22 dev_ctx = (struct nrf_wifi_bus_pcie_dev_ctx *)data;
23 pcie_priv = dev_ctx->pcie_priv;
24
25 ret = pcie_priv->intr_callbk_fn(dev_ctx->bal_dev_ctx);
26
27 return ret;
28 }
29
nrf_wifi_bus_pcie_dev_add(void * bus_priv,void * bal_dev_ctx)30 void *nrf_wifi_bus_pcie_dev_add(void *bus_priv,
31 void *bal_dev_ctx)
32 {
33 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
34 struct nrf_wifi_bus_pcie_priv *pcie_priv = NULL;
35 struct nrf_wifi_bus_pcie_dev_ctx *pcie_dev_ctx = NULL;
36 struct nrf_wifi_osal_host_map host_map;
37
38 pcie_priv = bus_priv;
39
40 pcie_dev_ctx = nrf_wifi_osal_mem_zalloc(
41 sizeof(*pcie_dev_ctx));
42
43 if (!pcie_dev_ctx)
44 {
45 nrf_wifi_osal_log_err(
46 "%s: Unable to allocate pcie_dev_ctx\n", __func__);
47 goto out;
48 }
49
50 pcie_dev_ctx->pcie_priv = pcie_priv;
51 pcie_dev_ctx->bal_dev_ctx = bal_dev_ctx;
52
53 pcie_dev_ctx->os_pcie_dev_ctx = nrf_wifi_osal_bus_pcie_dev_add(
54 pcie_priv->os_pcie_priv,
55 pcie_dev_ctx);
56
57 if (!pcie_dev_ctx->os_pcie_dev_ctx)
58 {
59 nrf_wifi_osal_log_err(
60 "%s: nrf_wifi_osal_bus_pcie_dev_add failed\n", __func__);
61
62 nrf_wifi_osal_mem_free(
63 pcie_dev_ctx);
64
65 pcie_dev_ctx = NULL;
66
67 goto out;
68 }
69
70 nrf_wifi_osal_bus_pcie_dev_host_map_get(
71 pcie_dev_ctx->os_pcie_dev_ctx,
72 &host_map);
73
74 pcie_dev_ctx->iomem_addr_base = nrf_wifi_osal_iomem_mmap(
75 host_map.addr,
76 host_map.size);
77
78 #ifdef INLINE_BB_MODE
79 pcie_dev_ctx->addr_pktram_base = pcie_priv->cfg_params.addr_pktram_base;
80 #endif /* INLINE_BB_MODE */
81 #ifdef OFFLINE_MODE
82 pcie_dev_ctx->addr_pktram_base = ((unsigned long)pcie_dev_ctx->iomem_addr_base +
83 pcie_priv->cfg_params.addr_pktram_base);
84 #endif /* OFFLINE_MODE */
85 #ifdef INLINE_RX
86 pcie_dev_ctx->addr_hostram_base_inline_rx = pcie_priv->cfg_params.addr_hostram_base_inline_rx;
87 #endif
88
89 status = nrf_wifi_osal_bus_pcie_dev_intr_reg(
90 pcie_dev_ctx->os_pcie_dev_ctx,
91 pcie_dev_ctx,
92 &nrf_wifi_bus_pcie_irq_handler);
93
94 if (status != NRF_WIFI_STATUS_SUCCESS)
95 {
96 nrf_wifi_osal_log_err(
97 "%s: Unable to register PCIe interrupt to the OS\n",
98 __func__);
99
100 nrf_wifi_osal_iomem_unmap(
101 pcie_dev_ctx->iomem_addr_base);
102
103 nrf_wifi_osal_bus_pcie_dev_rem(
104 pcie_dev_ctx->os_pcie_dev_ctx);
105
106 nrf_wifi_osal_mem_free(
107 pcie_dev_ctx);
108
109 pcie_dev_ctx = NULL;
110
111 goto out;
112 }
113
114 out:
115 return pcie_dev_ctx;
116 }
117
nrf_wifi_bus_pcie_dev_rem(void * bus_dev_ctx)118 void nrf_wifi_bus_pcie_dev_rem(void *bus_dev_ctx)
119 {
120 struct nrf_wifi_bus_pcie_dev_ctx *pcie_dev_ctx = NULL;
121
122 pcie_dev_ctx = bus_dev_ctx;
123
124 nrf_wifi_osal_iomem_unmap(
125 pcie_dev_ctx->iomem_addr_base);
126
127 nrf_wifi_osal_bus_pcie_dev_intr_unreg(
128 pcie_dev_ctx->os_pcie_dev_ctx);
129
130 nrf_wifi_osal_bus_pcie_dev_rem(
131 pcie_dev_ctx->os_pcie_dev_ctx);
132
133 nrf_wifi_osal_mem_free(
134 pcie_dev_ctx);
135 }
136
nrf_wifi_bus_pcie_dev_init(void * bus_dev_ctx)137 enum nrf_wifi_status nrf_wifi_bus_pcie_dev_init(void *bus_dev_ctx)
138 {
139 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
140 struct nrf_wifi_bus_pcie_dev_ctx *pcie_dev_ctx = NULL;
141
142 pcie_dev_ctx = bus_dev_ctx;
143
144 status = nrf_wifi_osal_bus_pcie_dev_init(
145 pcie_dev_ctx->os_pcie_dev_ctx);
146
147 if (status != NRF_WIFI_STATUS_SUCCESS)
148 {
149 nrf_wifi_osal_log_err(
150 "%s: nrf_wifi_osal_pcie_dev_init failed\n", __func__);
151
152 goto out;
153 }
154 out:
155 return status;
156 }
157
nrf_wifi_bus_pcie_dev_deinit(void * bus_dev_ctx)158 void nrf_wifi_bus_pcie_dev_deinit(void *bus_dev_ctx)
159 {
160 struct nrf_wifi_bus_pcie_dev_ctx *pcie_dev_ctx = NULL;
161
162 pcie_dev_ctx = bus_dev_ctx;
163
164 nrf_wifi_osal_bus_pcie_dev_deinit(
165 pcie_dev_ctx->os_pcie_dev_ctx);
166 }
167
nrf_wifi_bus_pcie_init(void * params,int (* intr_callbk_fn)(void * bal_dev_ctx))168 void *nrf_wifi_bus_pcie_init(void *params,
169 int (*intr_callbk_fn)(void *bal_dev_ctx))
170 {
171 struct nrf_wifi_bus_pcie_priv *pcie_priv = NULL;
172
173 pcie_priv = nrf_wifi_osal_mem_zalloc(
174 sizeof(*pcie_priv));
175
176 if (!pcie_priv)
177 {
178 nrf_wifi_osal_log_err(
179 "%s: Unable to allocate memory for pcie_priv\n",
180 __func__);
181 goto out;
182 }
183
184 nrf_wifi_osal_mem_cpy(
185 &pcie_priv->cfg_params,
186 params,
187 sizeof(pcie_priv->cfg_params));
188
189 pcie_priv->intr_callbk_fn = intr_callbk_fn;
190
191 pcie_priv->os_pcie_priv = nrf_wifi_osal_bus_pcie_init(
192 NRF_WIFI_PCIE_DRV_NAME,
193 NRF_WIFI_PCI_VENDOR_ID,
194 NRF_WIFI_PCI_SUB_VENDOR_ID,
195 NRF_WIFI_PCI_DEVICE_ID,
196 NRF_WIFI_PCI_SUB_DEVICE_ID);
197
198 if (!pcie_priv->os_pcie_priv)
199 {
200 nrf_wifi_osal_log_err(
201 "%s: Unable to register PCIe driver\n",
202 __func__);
203
204 nrf_wifi_osal_mem_free(
205 pcie_priv);
206
207 pcie_priv = NULL;
208
209 goto out;
210 }
211 out:
212 return pcie_priv;
213 }
214
nrf_wifi_bus_pcie_deinit(void * bus_priv)215 void nrf_wifi_bus_pcie_deinit(void *bus_priv)
216 {
217 struct nrf_wifi_bus_pcie_priv *pcie_priv = NULL;
218
219 pcie_priv = bus_priv;
220
221 nrf_wifi_osal_bus_pcie_deinit(
222 pcie_priv->os_pcie_priv);
223
224 nrf_wifi_osal_mem_free(
225 pcie_priv);
226 }
227
nrf_wifi_bus_pcie_read_word(void * dev_ctx,unsigned long addr_offset)228 unsigned int nrf_wifi_bus_pcie_read_word(void *dev_ctx,
229 unsigned long addr_offset)
230 {
231 struct nrf_wifi_bus_pcie_dev_ctx *pcie_dev_ctx = NULL;
232 void *mmap_addr = NULL;
233 unsigned int val = 0;
234
235 pcie_dev_ctx = (struct nrf_wifi_bus_pcie_dev_ctx *)dev_ctx;
236
237 mmap_addr = pcie_dev_ctx->iomem_addr_base + addr_offset;
238
239 val = nrf_wifi_osal_iomem_read_reg32(
240 mmap_addr);
241
242 return val;
243 }
244
nrf_wifi_bus_pcie_write_word(void * dev_ctx,unsigned long addr_offset,unsigned int val)245 void nrf_wifi_bus_pcie_write_word(void *dev_ctx,
246 unsigned long addr_offset,
247 unsigned int val)
248 {
249 struct nrf_wifi_bus_pcie_dev_ctx *pcie_dev_ctx = NULL;
250 void *mmap_addr = NULL;
251
252 pcie_dev_ctx = (struct nrf_wifi_bus_pcie_dev_ctx *)dev_ctx;
253
254 mmap_addr = pcie_dev_ctx->iomem_addr_base + addr_offset;
255
256 nrf_wifi_osal_iomem_write_reg32(
257 mmap_addr,
258 val);
259 }
260
nrf_wifi_bus_pcie_read_block(void * dev_ctx,void * dest_addr,unsigned long src_addr_offset,size_t len)261 void nrf_wifi_bus_pcie_read_block(void *dev_ctx,
262 void *dest_addr,
263 unsigned long src_addr_offset,
264 size_t len)
265 {
266 struct nrf_wifi_bus_pcie_dev_ctx *pcie_dev_ctx = NULL;
267 void *mmap_addr = NULL;
268
269 pcie_dev_ctx = (struct nrf_wifi_bus_pcie_dev_ctx *)dev_ctx;
270
271 mmap_addr = pcie_dev_ctx->iomem_addr_base + src_addr_offset;
272
273 nrf_wifi_osal_iomem_cpy_from(
274 dest_addr,
275 mmap_addr,
276 len);
277 }
278
nrf_wifi_bus_pcie_write_block(void * dev_ctx,unsigned long dest_addr_offset,const void * src_addr,size_t len)279 void nrf_wifi_bus_pcie_write_block(void *dev_ctx,
280 unsigned long dest_addr_offset,
281 const void *src_addr,
282 size_t len)
283 {
284 struct nrf_wifi_bus_pcie_dev_ctx *pcie_dev_ctx = NULL;
285 void *mmap_addr = NULL;
286
287 pcie_dev_ctx = (struct nrf_wifi_bus_pcie_dev_ctx *)dev_ctx;
288
289 mmap_addr = pcie_dev_ctx->iomem_addr_base + dest_addr_offset;
290
291 nrf_wifi_osal_iomem_cpy_to(
292 mmap_addr,
293 src_addr,
294 len);
295 }
296 #ifdef SOC_WEZEN
297 #ifdef INLINE_RX
nrf_wifi_bus_pcie_dma_map_inline_rx(void * dev_ctx,unsigned long virt_addr,size_t len,enum nrf_wifi_osal_dma_dir dma_dir)298 unsigned long nrf_wifi_bus_pcie_dma_map_inline_rx(void *dev_ctx,
299 unsigned long virt_addr,
300 size_t len,
301 enum nrf_wifi_osal_dma_dir dma_dir)
302 {
303 struct nrf_wifi_bus_pcie_dev_ctx *pcie_dev_ctx = NULL;
304 unsigned long phy_addr = 0;
305
306 pcie_dev_ctx = (struct nrf_wifi_bus_pcie_dev_ctx *)dev_ctx;
307 phy_addr = SOC_HOST_DATA_RAM_BASE + (virt_addr - pcie_dev_ctx->addr_hostram_base_inline_rx);
308 return phy_addr;
309 }
nrf_wifi_bus_pcie_dma_unmap_inline_rx(void * dev_ctx,unsigned long phy_addr,size_t len,enum nrf_wifi_osal_dma_dir dma_dir)310 unsigned long nrf_wifi_bus_pcie_dma_unmap_inline_rx(void *dev_ctx,
311 unsigned long phy_addr,
312 size_t len,
313 enum nrf_wifi_osal_dma_dir dma_dir)
314 {
315 struct nrf_wifi_bus_pcie_dev_ctx *pcie_dev_ctx = NULL;
316 unsigned long virt_addr = 0;
317 pcie_dev_ctx = (struct nrf_wifi_bus_pcie_dev_ctx *)dev_ctx;
318 virt_addr = pcie_dev_ctx->addr_hostram_base_inline_rx + (phy_addr - SOC_HOST_DATA_RAM_BASE);
319 return virt_addr;
320 }
321 #endif
322 #endif
323
nrf_wifi_bus_pcie_dma_map(void * dev_ctx,unsigned long virt_addr,size_t len,enum nrf_wifi_osal_dma_dir dma_dir)324 unsigned long nrf_wifi_bus_pcie_dma_map(void *dev_ctx,
325 unsigned long virt_addr,
326 size_t len,
327 enum nrf_wifi_osal_dma_dir dma_dir)
328 {
329 struct nrf_wifi_bus_pcie_dev_ctx *pcie_dev_ctx = NULL;
330 unsigned long phy_addr = 0;
331
332 pcie_dev_ctx = (struct nrf_wifi_bus_pcie_dev_ctx *)dev_ctx;
333
334 #ifdef INLINE_MODE
335 phy_addr = (unsigned long)nrf_wifi_osal_bus_pcie_dev_dma_map(
336 pcie_dev_ctx->os_pcie_dev_ctx,
337 (void *)virt_addr,
338 len,
339 dma_dir);
340 #endif /* INLINE_MODE */
341 #ifdef INLINE_BB_MODE
342 phy_addr = SOC_HOST_PKTRAM_BASE + (virt_addr - pcie_dev_ctx->addr_pktram_base);
343 #endif /* INLINE_BB_MODE */
344 #ifdef OFFLINE_MODE
345 phy_addr = (unsigned long)pcie_dev_ctx->iomem_addr_base + (virt_addr - pcie_dev_ctx->addr_pktram_base);
346 #endif /* OFFLINE_MODE */
347
348 return phy_addr;
349 }
350
nrf_wifi_bus_pcie_dma_unmap(void * dev_ctx,unsigned long phy_addr,size_t len,enum nrf_wifi_osal_dma_dir dma_dir)351 unsigned long nrf_wifi_bus_pcie_dma_unmap(void *dev_ctx,
352 unsigned long phy_addr,
353 size_t len,
354 enum nrf_wifi_osal_dma_dir dma_dir)
355 {
356 struct nrf_wifi_bus_pcie_dev_ctx *pcie_dev_ctx = NULL;
357 unsigned long virt_addr = 0;
358 #ifdef OFFLINE_MODE
359 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
360 #endif /* OFFLINE_MODE */
361
362 pcie_dev_ctx = (struct nrf_wifi_bus_pcie_dev_ctx *)dev_ctx;
363
364 #ifdef INLINE_MODE
365 nrf_wifi_osal_bus_pcie_dev_dma_unmap(
366 pcie_dev_ctx->os_pcie_dev_ctx,
367 (void *)phy_addr,
368 len,
369 dma_dir);
370 #endif /* INLINE_MODE */
371 #ifdef INLINE_BB_MODE
372 virt_addr = pcie_dev_ctx->addr_pktram_base + (phy_addr - SOC_HOST_PKTRAM_BASE);
373 #endif /* INLINE_BB_MODE */
374 #ifdef OFFLINE_MODE
375 #ifdef SOC_WEZEN
376 status = pal_rpu_addr_offset_get(
377 RPU_ADDR_DATA_RAM_START + phy_addr,
378 &virt_addr,
379 RPU_ADDR_DATA_RAM_START);
380 #else
381 status = pal_rpu_addr_offset_get(
382 RPU_ADDR_PKTRAM_START + phy_addr,
383 &virt_addr,
384 RPU_ADDR_PKTRAM_START);
385 #endif
386 if (status != NRF_WIFI_STATUS_SUCCESS)
387 nrf_wifi_osal_log_err(
388 "%s: pal_rpu_addr_offset_get failed\n", __func__);
389 #endif /* OFFLINE_MODE */
390
391 return virt_addr;
392 }
393
394 #ifdef NRF_WIFI_LOW_POWER
nrf_wifi_bus_pcie_rpu_ps_sleep(void * bus_dev_ctx)395 void nrf_wifi_bus_pcie_rpu_ps_sleep(void *bus_dev_ctx)
396 {
397 unsigned long reg_addr = 0;
398 unsigned int reg_val = 0;
399
400 reg_addr = pal_rpu_ps_ctrl_reg_addr_get();
401
402 reg_val = nrf_wifi_bus_pcie_read_word(bus_dev_ctx,
403 reg_addr);
404
405 reg_val &= (~(1 << RPU_REG_BIT_PS_CTRL));
406
407 nrf_wifi_bus_pcie_write_word(bus_dev_ctx,
408 reg_addr,
409 reg_val);
410 }
411
nrf_wifi_bus_pcie_rpu_ps_wake(void * bus_dev_ctx)412 void nrf_wifi_bus_pcie_rpu_ps_wake(void *bus_dev_ctx)
413 {
414 unsigned long reg_addr = 0;
415 unsigned int reg_val = 0;
416
417 reg_addr = pal_rpu_ps_ctrl_reg_addr_get();
418
419 reg_val = (1 << RPU_REG_BIT_PS_CTRL);
420
421 nrf_wifi_bal_write_word(bus_dev_ctx,
422 reg_addr,
423 reg_val);
424 }
425
nrf_wifi_bus_pcie_rpu_ps_status(void * bus_dev_ctx)426 int nrf_wifi_bus_pcie_rpu_ps_status(void *bus_dev_ctx)
427 {
428 unsigned long reg_addr = 0;
429
430 reg_addr = pal_rpu_ps_ctrl_reg_addr_get();
431
432 return nrf_wifi_bus_pcie_read_word(bus_dev_ctx,
433 reg_addr);
434 }
435 #endif /* NRF_WIFI_LOW_POWER */
436
437 struct nrf_wifi_bal_ops nrf_wifi_bus_pcie_ops = {
438 .init = &nrf_wifi_bus_pcie_init,
439 .deinit = &nrf_wifi_bus_pcie_deinit,
440 .dev_add = &nrf_wifi_bus_pcie_dev_add,
441 .dev_rem = &nrf_wifi_bus_pcie_dev_rem,
442 .dev_init = &nrf_wifi_bus_pcie_dev_init,
443 .dev_deinit = &nrf_wifi_bus_pcie_dev_deinit,
444 .read_word = &nrf_wifi_bus_pcie_read_word,
445 .write_word = &nrf_wifi_bus_pcie_write_word,
446 .read_block = &nrf_wifi_bus_pcie_read_block,
447 .write_block = &nrf_wifi_bus_pcie_write_block,
448 .dma_map = &nrf_wifi_bus_pcie_dma_map,
449 .dma_unmap = &nrf_wifi_bus_pcie_dma_unmap,
450 #ifdef SOC_WEZEN
451 #ifdef INLINE_RX
452 .dma_map_inline_rx = &nrf_wifi_bus_pcie_dma_map_inline_rx,
453 .dma_unmap_inline_rx = &nrf_wifi_bus_pcie_dma_unmap_inline_rx,
454 #endif
455 #endif
456 #ifdef NRF_WIFI_LOW_POWER
457 .rpu_ps_sleep = &nrf_wifi_bus_pcie_rpu_ps_sleep,
458 .rpu_ps_wake = &nrf_wifi_bus_pcie_rpu_ps_wake,
459 .rpu_ps_status = &nrf_wifi_bus_pcie_rpu_ps_status,
460 #endif /* NRF_WIFI_LOW_POWER */
461 };
462
get_bus_ops(void)463 struct nrf_wifi_bal_ops *get_bus_ops(void)
464 {
465 return &nrf_wifi_bus_pcie_ops;
466 }
467