1 /*
2  * Copyright (c) 2024 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 /**
8  * @brief File containing QSPI Bus Layer specific function definitions of the
9  * Wi-Fi driver.
10  */
11 
12 #include "bal_structs.h"
13 #include "qspi.h"
14 #include "common/pal.h"
15 
16 
nrf_wifi_bus_qspi_irq_handler(void * data)17 static int nrf_wifi_bus_qspi_irq_handler(void *data)
18 {
19 	struct nrf_wifi_bus_qspi_dev_ctx *dev_ctx = NULL;
20 	struct nrf_wifi_bus_qspi_priv *qspi_priv = NULL;
21 	int ret = 0;
22 
23 	dev_ctx = (struct nrf_wifi_bus_qspi_dev_ctx *)data;
24 	qspi_priv = dev_ctx->qspi_priv;
25 
26 	ret = qspi_priv->intr_callbk_fn(dev_ctx->bal_dev_ctx);
27 
28 	return ret;
29 }
30 
31 
nrf_wifi_bus_qspi_dev_add(void * bus_priv,void * bal_dev_ctx)32 static void *nrf_wifi_bus_qspi_dev_add(void *bus_priv,
33 				       void *bal_dev_ctx)
34 {
35 	struct nrf_wifi_bus_qspi_priv *qspi_priv = NULL;
36 	struct nrf_wifi_bus_qspi_dev_ctx *qspi_dev_ctx = NULL;
37 	struct nrf_wifi_osal_host_map host_map;
38 
39 	qspi_priv = bus_priv;
40 
41 	qspi_dev_ctx = nrf_wifi_osal_mem_zalloc(sizeof(*qspi_dev_ctx));
42 
43 	if (!qspi_dev_ctx) {
44 		nrf_wifi_osal_log_err("%s: Unable to allocate qspi_dev_ctx", __func__);
45 		goto out;
46 	}
47 
48 	qspi_dev_ctx->qspi_priv = qspi_priv;
49 	qspi_dev_ctx->bal_dev_ctx = bal_dev_ctx;
50 
51 	qspi_dev_ctx->os_qspi_dev_ctx = nrf_wifi_osal_bus_qspi_dev_add(qspi_priv->os_qspi_priv,
52 								       qspi_dev_ctx);
53 
54 	if (!qspi_dev_ctx->os_qspi_dev_ctx) {
55 		nrf_wifi_osal_log_err("%s: nrf_wifi_osal_bus_qspi_dev_add failed", __func__);
56 
57 		nrf_wifi_osal_mem_free(qspi_dev_ctx);
58 
59 		qspi_dev_ctx = NULL;
60 
61 		goto out;
62 	}
63 
64 	nrf_wifi_osal_bus_qspi_dev_host_map_get(qspi_dev_ctx->os_qspi_dev_ctx,
65 						&host_map);
66 
67 	qspi_dev_ctx->host_addr_base = host_map.addr;
68 
69 	qspi_dev_ctx->addr_pktram_base = qspi_dev_ctx->host_addr_base +
70 		qspi_priv->cfg_params.addr_pktram_base;
71 
72 out:
73 	return qspi_dev_ctx;
74 }
75 
76 
nrf_wifi_bus_qspi_dev_rem(void * bus_dev_ctx)77 static void nrf_wifi_bus_qspi_dev_rem(void *bus_dev_ctx)
78 {
79 	struct nrf_wifi_bus_qspi_dev_ctx *qspi_dev_ctx = NULL;
80 
81 	qspi_dev_ctx = bus_dev_ctx;
82 
83 	nrf_wifi_osal_bus_qspi_dev_rem(qspi_dev_ctx->os_qspi_dev_ctx);
84 
85 	nrf_wifi_osal_mem_free(qspi_dev_ctx);
86 }
87 
88 
nrf_wifi_bus_qspi_dev_init(void * bus_dev_ctx)89 static enum nrf_wifi_status nrf_wifi_bus_qspi_dev_init(void *bus_dev_ctx)
90 {
91 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
92 	struct nrf_wifi_bus_qspi_dev_ctx *qspi_dev_ctx = NULL;
93 
94 	qspi_dev_ctx = bus_dev_ctx;
95 
96 
97 	status = nrf_wifi_osal_bus_qspi_dev_intr_reg(qspi_dev_ctx->os_qspi_dev_ctx,
98 						     qspi_dev_ctx,
99 						     &nrf_wifi_bus_qspi_irq_handler);
100 
101 	if (status != NRF_WIFI_STATUS_SUCCESS) {
102 		nrf_wifi_osal_log_err("%s: Unable to register interrupt to the OS",
103 				      __func__);
104 		qspi_dev_ctx = NULL;
105 
106 		goto out;
107 	}
108 
109 	status = nrf_wifi_osal_bus_qspi_dev_init(qspi_dev_ctx->os_qspi_dev_ctx);
110 
111 	if (status != NRF_WIFI_STATUS_SUCCESS) {
112 		nrf_wifi_osal_log_err("%s: nrf_wifi_osal_qspi_dev_init failed", __func__);
113 
114 		nrf_wifi_osal_bus_qspi_dev_intr_unreg(qspi_dev_ctx->os_qspi_dev_ctx);
115 		goto out;
116 	}
117 out:
118 	return status;
119 }
120 
121 
nrf_wifi_bus_qspi_dev_deinit(void * bus_dev_ctx)122 static void nrf_wifi_bus_qspi_dev_deinit(void *bus_dev_ctx)
123 {
124 	struct nrf_wifi_bus_qspi_dev_ctx *qspi_dev_ctx = NULL;
125 
126 	qspi_dev_ctx = bus_dev_ctx;
127 
128 	nrf_wifi_osal_bus_qspi_dev_intr_unreg(qspi_dev_ctx->os_qspi_dev_ctx);
129 
130 	nrf_wifi_osal_bus_qspi_dev_deinit(qspi_dev_ctx->os_qspi_dev_ctx);
131 }
132 
133 
nrf_wifi_bus_qspi_init(void * params,enum nrf_wifi_status (* intr_callbk_fn)(void * bal_dev_ctx))134 static void *nrf_wifi_bus_qspi_init(void *params,
135 				    enum nrf_wifi_status (*intr_callbk_fn)(void *bal_dev_ctx))
136 {
137 	struct nrf_wifi_bus_qspi_priv *qspi_priv = NULL;
138 
139 	qspi_priv = nrf_wifi_osal_mem_zalloc(sizeof(*qspi_priv));
140 
141 	if (!qspi_priv) {
142 		nrf_wifi_osal_log_err("%s: Unable to allocate memory for qspi_priv",
143 				      __func__);
144 		goto out;
145 	}
146 
147 	nrf_wifi_osal_mem_cpy(&qspi_priv->cfg_params,
148 			      params,
149 			      sizeof(qspi_priv->cfg_params));
150 
151 	qspi_priv->intr_callbk_fn = intr_callbk_fn;
152 
153 	qspi_priv->os_qspi_priv = nrf_wifi_osal_bus_qspi_init();
154 
155 	if (!qspi_priv->os_qspi_priv) {
156 		nrf_wifi_osal_log_err("%s: Unable to register QSPI driver",
157 				      __func__);
158 
159 		nrf_wifi_osal_mem_free(qspi_priv);
160 
161 		qspi_priv = NULL;
162 
163 		goto out;
164 	}
165 out:
166 	return qspi_priv;
167 }
168 
169 
nrf_wifi_bus_qspi_deinit(void * bus_priv)170 static void nrf_wifi_bus_qspi_deinit(void *bus_priv)
171 {
172 	struct nrf_wifi_bus_qspi_priv *qspi_priv = NULL;
173 
174 	qspi_priv = bus_priv;
175 
176 	nrf_wifi_osal_bus_qspi_deinit(qspi_priv->os_qspi_priv);
177 
178 	nrf_wifi_osal_mem_free(qspi_priv);
179 }
180 
181 
nrf_wifi_bus_qspi_read_word(void * dev_ctx,unsigned long addr_offset)182 static unsigned int nrf_wifi_bus_qspi_read_word(void *dev_ctx,
183 						unsigned long addr_offset)
184 {
185 	struct nrf_wifi_bus_qspi_dev_ctx *qspi_dev_ctx = NULL;
186 	unsigned int val = 0;
187 
188 	qspi_dev_ctx = (struct nrf_wifi_bus_qspi_dev_ctx *)dev_ctx;
189 
190 	val = nrf_wifi_osal_qspi_read_reg32(qspi_dev_ctx->os_qspi_dev_ctx,
191 					    qspi_dev_ctx->host_addr_base + addr_offset);
192 
193 	return val;
194 }
195 
196 
nrf_wifi_bus_qspi_write_word(void * dev_ctx,unsigned long addr_offset,unsigned int val)197 static void nrf_wifi_bus_qspi_write_word(void *dev_ctx,
198 					 unsigned long addr_offset,
199 					 unsigned int val)
200 {
201 	struct nrf_wifi_bus_qspi_dev_ctx *qspi_dev_ctx = NULL;
202 
203 	qspi_dev_ctx = (struct nrf_wifi_bus_qspi_dev_ctx *)dev_ctx;
204 
205 	nrf_wifi_osal_qspi_write_reg32(qspi_dev_ctx->os_qspi_dev_ctx,
206 				       qspi_dev_ctx->host_addr_base + addr_offset,
207 				       val);
208 }
209 
210 
nrf_wifi_bus_qspi_read_block(void * dev_ctx,void * dest_addr,unsigned long src_addr_offset,size_t len)211 static void nrf_wifi_bus_qspi_read_block(void *dev_ctx,
212 					 void *dest_addr,
213 					 unsigned long src_addr_offset,
214 					 size_t len)
215 {
216 	struct nrf_wifi_bus_qspi_dev_ctx *qspi_dev_ctx = NULL;
217 
218 	qspi_dev_ctx = (struct nrf_wifi_bus_qspi_dev_ctx *)dev_ctx;
219 
220 	nrf_wifi_osal_qspi_cpy_from(qspi_dev_ctx->os_qspi_dev_ctx,
221 				    dest_addr,
222 				    qspi_dev_ctx->host_addr_base + src_addr_offset,
223 				    len);
224 }
225 
226 
nrf_wifi_bus_qspi_write_block(void * dev_ctx,unsigned long dest_addr_offset,const void * src_addr,size_t len)227 static void nrf_wifi_bus_qspi_write_block(void *dev_ctx,
228 					  unsigned long dest_addr_offset,
229 					  const void *src_addr,
230 					  size_t len)
231 {
232 	struct nrf_wifi_bus_qspi_dev_ctx *qspi_dev_ctx = NULL;
233 
234 	qspi_dev_ctx = (struct nrf_wifi_bus_qspi_dev_ctx *)dev_ctx;
235 
236 	nrf_wifi_osal_qspi_cpy_to(qspi_dev_ctx->os_qspi_dev_ctx,
237 				  qspi_dev_ctx->host_addr_base + dest_addr_offset,
238 				  src_addr,
239 				  len);
240 }
241 
242 
nrf_wifi_bus_qspi_dma_map(void * dev_ctx,unsigned long virt_addr,size_t len,enum nrf_wifi_osal_dma_dir dma_dir)243 static unsigned long nrf_wifi_bus_qspi_dma_map(void *dev_ctx,
244 					       unsigned long virt_addr,
245 					       size_t len,
246 					       enum nrf_wifi_osal_dma_dir dma_dir)
247 {
248 	struct nrf_wifi_bus_qspi_dev_ctx *qspi_dev_ctx = NULL;
249 	unsigned long phy_addr = 0;
250 
251 	qspi_dev_ctx = (struct nrf_wifi_bus_qspi_dev_ctx *)dev_ctx;
252 
253 	phy_addr = qspi_dev_ctx->host_addr_base + (virt_addr - qspi_dev_ctx->addr_pktram_base);
254 
255 	return phy_addr;
256 }
257 
258 
nrf_wifi_bus_qspi_dma_unmap(void * dev_ctx,unsigned long phy_addr,size_t len,enum nrf_wifi_osal_dma_dir dma_dir)259 static unsigned long nrf_wifi_bus_qspi_dma_unmap(void *dev_ctx,
260 						 unsigned long phy_addr,
261 						 size_t len,
262 						 enum nrf_wifi_osal_dma_dir dma_dir)
263 {
264 	struct nrf_wifi_bus_qspi_dev_ctx *qspi_dev_ctx = NULL;
265 	unsigned long virt_addr = 0;
266 
267 	qspi_dev_ctx = (struct nrf_wifi_bus_qspi_dev_ctx *)dev_ctx;
268 
269 	virt_addr = qspi_dev_ctx->addr_pktram_base + (phy_addr - qspi_dev_ctx->host_addr_base);
270 
271 	return virt_addr;
272 }
273 
274 
275 #ifdef NRF_WIFI_LOW_POWER
nrf_wifi_bus_qspi_ps_sleep(void * dev_ctx)276 static void nrf_wifi_bus_qspi_ps_sleep(void *dev_ctx)
277 {
278 	struct nrf_wifi_bus_qspi_dev_ctx *qspi_dev_ctx = NULL;
279 
280 	qspi_dev_ctx = (struct nrf_wifi_bus_qspi_dev_ctx *)dev_ctx;
281 
282 	nrf_wifi_osal_bus_qspi_ps_sleep(qspi_dev_ctx->os_qspi_dev_ctx);
283 }
284 
285 
nrf_wifi_bus_qspi_ps_wake(void * dev_ctx)286 static void nrf_wifi_bus_qspi_ps_wake(void *dev_ctx)
287 {
288 	struct nrf_wifi_bus_qspi_dev_ctx *qspi_dev_ctx = NULL;
289 
290 	qspi_dev_ctx = (struct nrf_wifi_bus_qspi_dev_ctx *)dev_ctx;
291 
292 	nrf_wifi_osal_bus_qspi_ps_wake(qspi_dev_ctx->os_qspi_dev_ctx);
293 }
294 
295 
nrf_wifi_bus_qspi_ps_status(void * dev_ctx)296 static int nrf_wifi_bus_qspi_ps_status(void *dev_ctx)
297 {
298 	struct nrf_wifi_bus_qspi_dev_ctx *qspi_dev_ctx = NULL;
299 
300 	qspi_dev_ctx = (struct nrf_wifi_bus_qspi_dev_ctx *)dev_ctx;
301 
302 	return nrf_wifi_osal_bus_qspi_ps_status(qspi_dev_ctx->os_qspi_dev_ctx);
303 }
304 #endif /* NRF_WIFI_LOW_POWER */
305 
306 
307 static struct nrf_wifi_bal_ops nrf_wifi_bus_qspi_ops = {
308 	.init = &nrf_wifi_bus_qspi_init,
309 	.deinit = &nrf_wifi_bus_qspi_deinit,
310 	.dev_add = &nrf_wifi_bus_qspi_dev_add,
311 	.dev_rem = &nrf_wifi_bus_qspi_dev_rem,
312 	.dev_init = &nrf_wifi_bus_qspi_dev_init,
313 	.dev_deinit = &nrf_wifi_bus_qspi_dev_deinit,
314 	.read_word = &nrf_wifi_bus_qspi_read_word,
315 	.write_word = &nrf_wifi_bus_qspi_write_word,
316 	.read_block = &nrf_wifi_bus_qspi_read_block,
317 	.write_block = &nrf_wifi_bus_qspi_write_block,
318 	.dma_map = &nrf_wifi_bus_qspi_dma_map,
319 	.dma_unmap = &nrf_wifi_bus_qspi_dma_unmap,
320 #ifdef NRF_WIFI_LOW_POWER
321 	.rpu_ps_sleep = &nrf_wifi_bus_qspi_ps_sleep,
322 	.rpu_ps_wake = &nrf_wifi_bus_qspi_ps_wake,
323 	.rpu_ps_status = &nrf_wifi_bus_qspi_ps_status,
324 #endif /* NRF_WIFI_LOW_POWER */
325 };
326 
327 
get_bus_ops(void)328 struct nrf_wifi_bal_ops *get_bus_ops(void)
329 {
330 	return &nrf_wifi_bus_qspi_ops;
331 }
332