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 "spi.h"
14 #include "pal.h"
15 
16 
nrf_wifi_bus_spi_irq_handler(void * data)17 static int nrf_wifi_bus_spi_irq_handler(void *data)
18 {
19 	struct nrf_wifi_bus_spi_dev_ctx *dev_ctx = NULL;
20 	struct nrf_wifi_bus_spi_priv *spi_priv = NULL;
21 	int ret = 0;
22 
23 	dev_ctx = (struct nrf_wifi_bus_spi_dev_ctx *)data;
24 	spi_priv = dev_ctx->spi_priv;
25 
26 	ret = spi_priv->intr_callbk_fn(dev_ctx->bal_dev_ctx);
27 
28 	return ret;
29 }
30 
31 
nrf_wifi_bus_spi_dev_add(void * bus_priv,void * bal_dev_ctx)32 static void *nrf_wifi_bus_spi_dev_add(void *bus_priv,
33 				       void *bal_dev_ctx)
34 {
35 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
36 	struct nrf_wifi_bus_spi_priv *spi_priv = NULL;
37 	struct nrf_wifi_bus_spi_dev_ctx *spi_dev_ctx = NULL;
38 	struct nrf_wifi_osal_host_map host_map;
39 
40 	spi_priv = bus_priv;
41 
42 	spi_dev_ctx = nrf_wifi_osal_mem_zalloc(sizeof(*spi_dev_ctx));
43 
44 	if (!spi_dev_ctx) {
45 		nrf_wifi_osal_log_err("%s: Unable to allocate spi_dev_ctx", __func__);
46 		goto out;
47 	}
48 
49 	spi_dev_ctx->spi_priv = spi_priv;
50 	spi_dev_ctx->bal_dev_ctx = bal_dev_ctx;
51 
52 	spi_dev_ctx->os_spi_dev_ctx = nrf_wifi_osal_bus_spi_dev_add(spi_priv->os_spi_priv,
53 								    spi_dev_ctx);
54 
55 	if (!spi_dev_ctx->os_spi_dev_ctx) {
56 		nrf_wifi_osal_log_err("%s: nrf_wifi_osal_bus_spi_dev_add failed", __func__);
57 
58 		nrf_wifi_osal_mem_free(spi_dev_ctx);
59 
60 		spi_dev_ctx = NULL;
61 
62 		goto out;
63 	}
64 
65 	nrf_wifi_osal_bus_spi_dev_host_map_get(spi_dev_ctx->os_spi_dev_ctx,
66 					       &host_map);
67 
68 	spi_dev_ctx->host_addr_base = host_map.addr;
69 
70 	spi_dev_ctx->addr_pktram_base = spi_dev_ctx->host_addr_base +
71 		spi_priv->cfg_params.addr_pktram_base;
72 
73 out:
74 	return spi_dev_ctx;
75 }
76 
77 
nrf_wifi_bus_spi_dev_rem(void * bus_dev_ctx)78 static void nrf_wifi_bus_spi_dev_rem(void *bus_dev_ctx)
79 {
80 	struct nrf_wifi_bus_spi_dev_ctx *spi_dev_ctx = NULL;
81 
82 	spi_dev_ctx = bus_dev_ctx;
83 
84 	nrf_wifi_osal_mem_free(spi_dev_ctx);
85 }
86 
87 
nrf_wifi_bus_spi_dev_init(void * bus_dev_ctx)88 static enum nrf_wifi_status nrf_wifi_bus_spi_dev_init(void *bus_dev_ctx)
89 {
90 	enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
91 	struct nrf_wifi_bus_spi_dev_ctx *spi_dev_ctx = NULL;
92 
93 	spi_dev_ctx = bus_dev_ctx;
94 
95 
96 	status = nrf_wifi_osal_bus_spi_dev_intr_reg(spi_dev_ctx->os_spi_dev_ctx, spi_dev_ctx,
97 					&nrf_wifi_bus_spi_irq_handler);
98 
99 	if (status != NRF_WIFI_STATUS_SUCCESS) {
100 		nrf_wifi_osal_log_err(
101 				      "%s: Unable to register interrupt to the OS",
102 				      __func__);
103 		goto out;
104 	}
105 
106 	status = nrf_wifi_osal_bus_spi_dev_init(spi_dev_ctx->os_spi_dev_ctx);
107 
108 	if (status != NRF_WIFI_STATUS_SUCCESS) {
109 		nrf_wifi_osal_log_err("%s: nrf_wifi_osal_spi_dev_init failed", __func__);
110 
111 		nrf_wifi_osal_bus_spi_dev_intr_unreg(spi_dev_ctx->os_spi_dev_ctx);
112 		goto out;
113 	}
114 out:
115 	return status;
116 }
117 
118 
nrf_wifi_bus_spi_dev_deinit(void * bus_dev_ctx)119 static void nrf_wifi_bus_spi_dev_deinit(void *bus_dev_ctx)
120 {
121 	struct nrf_wifi_bus_spi_dev_ctx *spi_dev_ctx = NULL;
122 
123 	spi_dev_ctx = bus_dev_ctx;
124 
125 	nrf_wifi_osal_bus_spi_dev_intr_unreg(
126 					      spi_dev_ctx->os_spi_dev_ctx);
127 
128 	nrf_wifi_osal_bus_spi_dev_deinit(
129 					  spi_dev_ctx->os_spi_dev_ctx);
130 }
131 
132 
nrf_wifi_bus_spi_init(void * params,enum nrf_wifi_status (* intr_callbk_fn)(void * bal_dev_ctx))133 static void *nrf_wifi_bus_spi_init(void *params,
134 				   enum nrf_wifi_status (*intr_callbk_fn)(void *bal_dev_ctx))
135 {
136 	struct nrf_wifi_bus_spi_priv *spi_priv = NULL;
137 
138 	spi_priv = nrf_wifi_osal_mem_zalloc(sizeof(*spi_priv));
139 
140 	if (!spi_priv) {
141 		nrf_wifi_osal_log_err("%s: Unable to allocate memory for spi_priv",
142 				      __func__);
143 		goto out;
144 	}
145 
146 	nrf_wifi_osal_mem_cpy(&spi_priv->cfg_params,
147 			      params,
148 			      sizeof(spi_priv->cfg_params));
149 
150 	spi_priv->intr_callbk_fn = intr_callbk_fn;
151 
152 	spi_priv->os_spi_priv = nrf_wifi_osal_bus_spi_init();
153 	if (!spi_priv->os_spi_priv) {
154 		nrf_wifi_osal_log_err("%s: Unable to register QSPI driver",
155 				      __func__);
156 
157 		nrf_wifi_osal_mem_free(spi_priv);
158 
159 		spi_priv = NULL;
160 
161 		goto out;
162 	}
163 out:
164 	return spi_priv;
165 }
166 
167 
nrf_wifi_bus_spi_deinit(void * bus_priv)168 static void nrf_wifi_bus_spi_deinit(void *bus_priv)
169 {
170 	struct nrf_wifi_bus_spi_priv *spi_priv = NULL;
171 
172 	spi_priv = bus_priv;
173 
174 	nrf_wifi_osal_bus_spi_deinit(spi_priv->os_spi_priv);
175 
176 	nrf_wifi_osal_mem_free(spi_priv);
177 }
178 
179 
nrf_wifi_bus_spi_read_word(void * dev_ctx,unsigned long addr_offset)180 static unsigned int nrf_wifi_bus_spi_read_word(void *dev_ctx,
181 					       unsigned long addr_offset)
182 {
183 	struct nrf_wifi_bus_spi_dev_ctx *spi_dev_ctx = NULL;
184 	unsigned int val = 0;
185 
186 	spi_dev_ctx = (struct nrf_wifi_bus_spi_dev_ctx *)dev_ctx;
187 
188 	val = nrf_wifi_osal_spi_read_reg32(spi_dev_ctx->os_spi_dev_ctx,
189 					   spi_dev_ctx->host_addr_base + addr_offset);
190 	return val;
191 }
192 
193 
nrf_wifi_bus_spi_write_word(void * dev_ctx,unsigned long addr_offset,unsigned int val)194 static void nrf_wifi_bus_spi_write_word(void *dev_ctx,
195 					unsigned long addr_offset,
196 					unsigned int val)
197 {
198 	struct nrf_wifi_bus_spi_dev_ctx *spi_dev_ctx = NULL;
199 
200 	spi_dev_ctx = (struct nrf_wifi_bus_spi_dev_ctx *)dev_ctx;
201 
202 	nrf_wifi_osal_spi_write_reg32(spi_dev_ctx->os_spi_dev_ctx,
203 				      spi_dev_ctx->host_addr_base + addr_offset,
204 				      val);
205 }
206 
207 
nrf_wifi_bus_spi_read_block(void * dev_ctx,void * dest_addr,unsigned long src_addr_offset,size_t len)208 static void nrf_wifi_bus_spi_read_block(void *dev_ctx,
209 					void *dest_addr,
210 					unsigned long src_addr_offset,
211 					size_t len)
212 {
213 	struct nrf_wifi_bus_spi_dev_ctx *spi_dev_ctx = NULL;
214 
215 	spi_dev_ctx = (struct nrf_wifi_bus_spi_dev_ctx *)dev_ctx;
216 
217 	nrf_wifi_osal_spi_cpy_from(spi_dev_ctx->os_spi_dev_ctx,
218 				   dest_addr,
219 				   spi_dev_ctx->host_addr_base + src_addr_offset,
220 				   len);
221 }
222 
223 
nrf_wifi_bus_spi_write_block(void * dev_ctx,unsigned long dest_addr_offset,const void * src_addr,size_t len)224 static void nrf_wifi_bus_spi_write_block(void *dev_ctx,
225 					 unsigned long dest_addr_offset,
226 					 const void *src_addr,
227 					 size_t len)
228 {
229 	struct nrf_wifi_bus_spi_dev_ctx *spi_dev_ctx = NULL;
230 
231 	spi_dev_ctx = (struct nrf_wifi_bus_spi_dev_ctx *)dev_ctx;
232 
233 	nrf_wifi_osal_spi_cpy_to(spi_dev_ctx->os_spi_dev_ctx,
234 				 spi_dev_ctx->host_addr_base + dest_addr_offset,
235 				 src_addr,
236 				 len);
237 }
238 
239 
nrf_wifi_bus_spi_dma_map(void * dev_ctx,unsigned long virt_addr,size_t len,enum nrf_wifi_osal_dma_dir dma_dir)240 static unsigned long nrf_wifi_bus_spi_dma_map(void *dev_ctx,
241 					      unsigned long virt_addr,
242 					      size_t len,
243 					      enum nrf_wifi_osal_dma_dir dma_dir)
244 {
245 	struct nrf_wifi_bus_spi_dev_ctx *spi_dev_ctx = NULL;
246 	unsigned long phy_addr = 0;
247 
248 	spi_dev_ctx = (struct nrf_wifi_bus_spi_dev_ctx *)dev_ctx;
249 
250 	phy_addr = spi_dev_ctx->host_addr_base + (virt_addr - spi_dev_ctx->addr_pktram_base);
251 
252 
253 	return phy_addr;
254 }
255 
256 
nrf_wifi_bus_spi_dma_unmap(void * dev_ctx,unsigned long phy_addr,size_t len,enum nrf_wifi_osal_dma_dir dma_dir)257 static unsigned long nrf_wifi_bus_spi_dma_unmap(void *dev_ctx,
258 						unsigned long phy_addr,
259 						size_t len,
260 						enum nrf_wifi_osal_dma_dir dma_dir)
261 {
262 	struct nrf_wifi_bus_spi_dev_ctx *spi_dev_ctx = NULL;
263 	unsigned long virt_addr = 0;
264 
265 	spi_dev_ctx = (struct nrf_wifi_bus_spi_dev_ctx *)dev_ctx;
266 
267 	virt_addr = spi_dev_ctx->addr_pktram_base + (phy_addr - spi_dev_ctx->host_addr_base);
268 
269 	return virt_addr;
270 }
271 
272 
273 #ifdef NRF_WIFI_LOW_POWER
nrf_wifi_bus_spi_ps_sleep(void * dev_ctx)274 static void nrf_wifi_bus_spi_ps_sleep(void *dev_ctx)
275 {
276 	struct nrf_wifi_bus_spi_dev_ctx *spi_dev_ctx = NULL;
277 
278 	spi_dev_ctx = (struct nrf_wifi_bus_spi_dev_ctx *)dev_ctx;
279 
280 	nrf_wifi_osal_bus_qspi_ps_sleep(spi_dev_ctx->os_spi_dev_ctx);
281 }
282 
283 
nrf_wifi_bus_spi_ps_wake(void * dev_ctx)284 static void nrf_wifi_bus_spi_ps_wake(void *dev_ctx)
285 {
286 	struct nrf_wifi_bus_spi_dev_ctx *spi_dev_ctx = NULL;
287 
288 	spi_dev_ctx = (struct nrf_wifi_bus_spi_dev_ctx *)dev_ctx;
289 
290 	nrf_wifi_osal_bus_qspi_ps_wake(spi_dev_ctx->os_spi_dev_ctx);
291 }
292 
293 
nrf_wifi_bus_spi_ps_status(void * dev_ctx)294 static int nrf_wifi_bus_spi_ps_status(void *dev_ctx)
295 {
296 	struct nrf_wifi_bus_spi_dev_ctx *spi_dev_ctx = NULL;
297 
298 	spi_dev_ctx = (struct nrf_wifi_bus_spi_dev_ctx *)dev_ctx;
299 
300 	return nrf_wifi_osal_bus_qspi_ps_status(spi_dev_ctx->os_spi_dev_ctx);
301 }
302 #endif /* NRF_WIFI_LOW_POWER */
303 
304 
305 static struct nrf_wifi_bal_ops nrf_wifi_bus_spi_ops = {
306 	.init = &nrf_wifi_bus_spi_init,
307 	.deinit = &nrf_wifi_bus_spi_deinit,
308 	.dev_add = &nrf_wifi_bus_spi_dev_add,
309 	.dev_rem = &nrf_wifi_bus_spi_dev_rem,
310 	.dev_init = &nrf_wifi_bus_spi_dev_init,
311 	.dev_deinit = &nrf_wifi_bus_spi_dev_deinit,
312 	.read_word = &nrf_wifi_bus_spi_read_word,
313 	.write_word = &nrf_wifi_bus_spi_write_word,
314 	.read_block = &nrf_wifi_bus_spi_read_block,
315 	.write_block = &nrf_wifi_bus_spi_write_block,
316 	.dma_map = &nrf_wifi_bus_spi_dma_map,
317 	.dma_unmap = &nrf_wifi_bus_spi_dma_unmap,
318 #ifdef NRF_WIFI_LOW_POWER
319 	.rpu_ps_sleep = &nrf_wifi_bus_spi_ps_sleep,
320 	.rpu_ps_wake = &nrf_wifi_bus_spi_ps_wake,
321 	.rpu_ps_status = &nrf_wifi_bus_spi_ps_status,
322 #endif /* NRF_WIFI_LOW_POWER */
323 };
324 
325 
get_bus_ops(void)326 struct nrf_wifi_bal_ops *get_bus_ops(void)
327 {
328 	return &nrf_wifi_bus_spi_ops;
329 }
330