xref: /wlan-driver/qcacld-3.0/core/pld/src/pld_sdio.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
4*5113495bSYour Name  *
5*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for
6*5113495bSYour Name  * any purpose with or without fee is hereby granted, provided that the
7*5113495bSYour Name  * above copyright notice and this permission notice appear in all
8*5113495bSYour Name  * copies.
9*5113495bSYour Name  *
10*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11*5113495bSYour Name  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12*5113495bSYour Name  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13*5113495bSYour Name  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14*5113495bSYour Name  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15*5113495bSYour Name  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16*5113495bSYour Name  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*5113495bSYour Name  * PERFORMANCE OF THIS SOFTWARE.
18*5113495bSYour Name  */
19*5113495bSYour Name 
20*5113495bSYour Name #include <linux/platform_device.h>
21*5113495bSYour Name #include <linux/err.h>
22*5113495bSYour Name #include <linux/mmc/sdio_func.h>
23*5113495bSYour Name #include <linux/list.h>
24*5113495bSYour Name #include <linux/slab.h>
25*5113495bSYour Name 
26*5113495bSYour Name #ifdef CONFIG_PLD_SDIO_CNSS
27*5113495bSYour Name #include <net/cnss.h>
28*5113495bSYour Name #endif
29*5113495bSYour Name #ifdef CONFIG_PLD_SDIO_CNSS2
30*5113495bSYour Name #include <net/cnss2.h>
31*5113495bSYour Name #endif
32*5113495bSYour Name 
33*5113495bSYour Name #include "pld_common.h"
34*5113495bSYour Name #include "pld_internal.h"
35*5113495bSYour Name #include "pld_sdio.h"
36*5113495bSYour Name #include "osif_psoc_sync.h"
37*5113495bSYour Name 
38*5113495bSYour Name #ifdef CONFIG_SDIO
39*5113495bSYour Name /* SDIO manufacturer ID and Codes */
40*5113495bSYour Name #define MANUFACTURER_ID_AR6320_BASE        0x500
41*5113495bSYour Name #define MANUFACTURER_ID_QCA9377_BASE       0x700
42*5113495bSYour Name #define MANUFACTURER_ID_QCA9379_BASE       0x800
43*5113495bSYour Name #define MANUFACTURER_CODE                  0x271
44*5113495bSYour Name 
45*5113495bSYour Name #ifndef CONFIG_CNSS
46*5113495bSYour Name static const struct pld_fw_files fw_files_qca6174_fw_1_1 = {
47*5113495bSYour Name 	PREFIX "qwlan11.bin", PREFIX  "bdwlan11.bin", PREFIX "otp11.bin",
48*5113495bSYour Name 	PREFIX  "utf11.bin", PREFIX "utfbd11.bin", PREFIX "qsetup11.bin",
49*5113495bSYour Name 	PREFIX "epping11.bin", ""};
50*5113495bSYour Name static const struct pld_fw_files fw_files_qca6174_fw_2_0 = {
51*5113495bSYour Name 	PREFIX "qwlan20.bin", PREFIX "bdwlan20.bin", PREFIX "otp20.bin",
52*5113495bSYour Name 	PREFIX "utf20.bin", PREFIX "utfbd20.bin", PREFIX "qsetup20.bin",
53*5113495bSYour Name 	PREFIX "epping20.bin", ""};
54*5113495bSYour Name static const struct pld_fw_files fw_files_qca6174_fw_1_3 = {
55*5113495bSYour Name 	PREFIX "qwlan13.bin", PREFIX "bdwlan13.bin", PREFIX "otp13.bin",
56*5113495bSYour Name 	PREFIX "utf13.bin", PREFIX "utfbd13.bin", PREFIX "qsetup13.bin",
57*5113495bSYour Name 	PREFIX "epping13.bin", ""};
58*5113495bSYour Name static const struct pld_fw_files fw_files_qca6174_fw_3_0 = {
59*5113495bSYour Name 	PREFIX "qwlan30.bin", PREFIX "bdwlan30.bin", PREFIX "otp30.bin",
60*5113495bSYour Name 	PREFIX "utf30.bin", PREFIX "utfbd30.bin", PREFIX "qsetup30.bin",
61*5113495bSYour Name 	PREFIX "epping30.bin", PREFIX "qwlan30i.bin"};
62*5113495bSYour Name static const struct pld_fw_files fw_files_default = {
63*5113495bSYour Name 	PREFIX "qwlan.bin", PREFIX "bdwlan.bin", PREFIX "otp.bin",
64*5113495bSYour Name 	PREFIX "utf.bin", PREFIX "utfbd.bin", PREFIX "qsetup.bin",
65*5113495bSYour Name 	PREFIX "epping.bin", ""};
66*5113495bSYour Name #endif
67*5113495bSYour Name 
68*5113495bSYour Name /**
69*5113495bSYour Name  * pld_sdio_probe() - Probe function for SDIO platform driver
70*5113495bSYour Name  * @sdio_func: pointer to sdio device function
71*5113495bSYour Name  * @id: SDIO device ID table
72*5113495bSYour Name  *
73*5113495bSYour Name  * The probe function will be called when SDIO device provided
74*5113495bSYour Name  * in the ID table is detected.
75*5113495bSYour Name  *
76*5113495bSYour Name  * Return: int
77*5113495bSYour Name  */
pld_sdio_probe(struct sdio_func * sdio_func,const struct sdio_device_id * id)78*5113495bSYour Name static int pld_sdio_probe(struct sdio_func *sdio_func,
79*5113495bSYour Name 			  const struct sdio_device_id *id)
80*5113495bSYour Name {
81*5113495bSYour Name 	struct pld_context *pld_context;
82*5113495bSYour Name 	struct device *dev;
83*5113495bSYour Name 	int ret;
84*5113495bSYour Name 
85*5113495bSYour Name 	pld_context = pld_get_global_context();
86*5113495bSYour Name 	if (!pld_context || !sdio_func) {
87*5113495bSYour Name 		ret = -ENODEV;
88*5113495bSYour Name 		goto out;
89*5113495bSYour Name 	}
90*5113495bSYour Name 
91*5113495bSYour Name 	dev = &sdio_func->dev;
92*5113495bSYour Name 	ret = pld_add_dev(pld_context, dev, NULL, PLD_BUS_TYPE_SDIO);
93*5113495bSYour Name 	if (ret)
94*5113495bSYour Name 		goto out;
95*5113495bSYour Name 
96*5113495bSYour Name 	return pld_context->ops->probe(dev, PLD_BUS_TYPE_SDIO,
97*5113495bSYour Name 		       sdio_func, (void *)id);
98*5113495bSYour Name 
99*5113495bSYour Name out:
100*5113495bSYour Name 	return ret;
101*5113495bSYour Name }
102*5113495bSYour Name 
103*5113495bSYour Name 
104*5113495bSYour Name /**
105*5113495bSYour Name  * pld_sdio_remove() - Remove function for SDIO device
106*5113495bSYour Name  * @sdio_func: pointer to sdio device function
107*5113495bSYour Name  *
108*5113495bSYour Name  * The remove function will be called when SDIO device is disconnected
109*5113495bSYour Name  *
110*5113495bSYour Name  * Return: void
111*5113495bSYour Name  */
pld_sdio_remove(struct sdio_func * sdio_func)112*5113495bSYour Name static void pld_sdio_remove(struct sdio_func *sdio_func)
113*5113495bSYour Name {
114*5113495bSYour Name 	struct pld_context *pld_context;
115*5113495bSYour Name 	struct device *dev = &sdio_func->dev;
116*5113495bSYour Name 	int errno;
117*5113495bSYour Name 	struct osif_psoc_sync *psoc_sync;
118*5113495bSYour Name 
119*5113495bSYour Name 	errno = osif_psoc_sync_trans_start_wait(dev, &psoc_sync);
120*5113495bSYour Name 	if (errno)
121*5113495bSYour Name 		return;
122*5113495bSYour Name 
123*5113495bSYour Name 	osif_psoc_sync_unregister(dev);
124*5113495bSYour Name 	osif_psoc_sync_wait_for_ops(psoc_sync);
125*5113495bSYour Name 
126*5113495bSYour Name 	pld_context = pld_get_global_context();
127*5113495bSYour Name 
128*5113495bSYour Name 	if (!pld_context)
129*5113495bSYour Name 		goto out;
130*5113495bSYour Name 
131*5113495bSYour Name 	pld_context->ops->remove(dev, PLD_BUS_TYPE_SDIO);
132*5113495bSYour Name 	pld_del_dev(pld_context, dev);
133*5113495bSYour Name 
134*5113495bSYour Name out:
135*5113495bSYour Name 	osif_psoc_sync_trans_stop(psoc_sync);
136*5113495bSYour Name 	osif_psoc_sync_destroy(psoc_sync);
137*5113495bSYour Name }
138*5113495bSYour Name 
139*5113495bSYour Name #ifdef CONFIG_PLD_SDIO_CNSS
140*5113495bSYour Name /**
141*5113495bSYour Name  * pld_sdio_reinit() - SSR re-initialize function for SDIO device
142*5113495bSYour Name  * @sdio_func: pointer to sdio device function
143*5113495bSYour Name  * @id: SDIO device ID
144*5113495bSYour Name  *
145*5113495bSYour Name  * During subsystem restart(SSR), this function will be called to
146*5113495bSYour Name  * re-initialize SDIO device.
147*5113495bSYour Name  *
148*5113495bSYour Name  * Return: int
149*5113495bSYour Name  */
pld_sdio_reinit(struct sdio_func * sdio_func,const struct sdio_device_id * id)150*5113495bSYour Name static int pld_sdio_reinit(struct sdio_func *sdio_func,
151*5113495bSYour Name 			  const struct sdio_device_id *id)
152*5113495bSYour Name {
153*5113495bSYour Name 	struct pld_context *pld_context;
154*5113495bSYour Name 	struct device *dev = &sdio_func->dev;
155*5113495bSYour Name 
156*5113495bSYour Name 	pld_context = pld_get_global_context();
157*5113495bSYour Name 	if (pld_context->ops->reinit)
158*5113495bSYour Name 		return pld_context->ops->reinit(dev, PLD_BUS_TYPE_SDIO,
159*5113495bSYour Name 		       sdio_func, (void *)id);
160*5113495bSYour Name 
161*5113495bSYour Name 	return -ENODEV;
162*5113495bSYour Name }
163*5113495bSYour Name 
164*5113495bSYour Name /**
165*5113495bSYour Name  * pld_sdio_shutdown() - SSR shutdown function for SDIO device
166*5113495bSYour Name  * @sdio_func: pointer to sdio device function
167*5113495bSYour Name  *
168*5113495bSYour Name  * During SSR, this function will be called to shutdown SDIO device.
169*5113495bSYour Name  *
170*5113495bSYour Name  * Return: void
171*5113495bSYour Name  */
pld_sdio_shutdown(struct sdio_func * sdio_func)172*5113495bSYour Name static void pld_sdio_shutdown(struct sdio_func *sdio_func)
173*5113495bSYour Name {
174*5113495bSYour Name 	struct pld_context *pld_context;
175*5113495bSYour Name 	struct device *dev = &sdio_func->dev;
176*5113495bSYour Name 
177*5113495bSYour Name 	pld_context = pld_get_global_context();
178*5113495bSYour Name 	if (pld_context->ops->shutdown)
179*5113495bSYour Name 		pld_context->ops->shutdown(dev, PLD_BUS_TYPE_SDIO);
180*5113495bSYour Name }
181*5113495bSYour Name 
182*5113495bSYour Name /**
183*5113495bSYour Name  * pld_sdio_crash_shutdown() - Crash shutdown function for SDIO device
184*5113495bSYour Name  * @sdio_func: pointer to sdio device function
185*5113495bSYour Name  *
186*5113495bSYour Name  * This function will be called when a crash is detected, it will shutdown
187*5113495bSYour Name  * the SDIO device.
188*5113495bSYour Name  *
189*5113495bSYour Name  * Return: void
190*5113495bSYour Name  */
pld_sdio_crash_shutdown(struct sdio_func * sdio_func)191*5113495bSYour Name static void pld_sdio_crash_shutdown(struct sdio_func *sdio_func)
192*5113495bSYour Name {
193*5113495bSYour Name 	struct pld_context *pld_context;
194*5113495bSYour Name 	struct device *dev = &sdio_func->dev;
195*5113495bSYour Name 
196*5113495bSYour Name 	pld_context = pld_get_global_context();
197*5113495bSYour Name 	if (pld_context->ops->crash_shutdown)
198*5113495bSYour Name 		pld_context->ops->crash_shutdown(dev, PLD_BUS_TYPE_SDIO);
199*5113495bSYour Name }
200*5113495bSYour Name 
201*5113495bSYour Name #endif
202*5113495bSYour Name 
203*5113495bSYour Name #ifdef CONFIG_PM
204*5113495bSYour Name /**
205*5113495bSYour Name  * pld_sdio_suspend() - Suspend callback function for power management
206*5113495bSYour Name  * @dev: SDIO device
207*5113495bSYour Name  *
208*5113495bSYour Name  * This function is to suspend the SDIO device when power management is
209*5113495bSYour Name  * enabled.
210*5113495bSYour Name  *
211*5113495bSYour Name  * Return: void
212*5113495bSYour Name  */
pld_sdio_suspend(struct device * dev)213*5113495bSYour Name static int pld_sdio_suspend(struct device *dev)
214*5113495bSYour Name {
215*5113495bSYour Name 	struct pld_context *pld_context;
216*5113495bSYour Name 	pm_message_t state = { .event = PM_EVENT_SUSPEND };
217*5113495bSYour Name 
218*5113495bSYour Name 	pld_context = pld_get_global_context();
219*5113495bSYour Name 	return pld_context->ops->suspend(dev,
220*5113495bSYour Name 					 PLD_BUS_TYPE_SDIO, state);
221*5113495bSYour Name }
222*5113495bSYour Name 
223*5113495bSYour Name /**
224*5113495bSYour Name  * pld_sdio_resume() - Resume callback function for power management
225*5113495bSYour Name  * @dev: SDIO device
226*5113495bSYour Name  *
227*5113495bSYour Name  * This function is to resume the SDIO device when power management is
228*5113495bSYour Name  * enabled.
229*5113495bSYour Name  *
230*5113495bSYour Name  * Return: void
231*5113495bSYour Name  */
pld_sdio_resume(struct device * dev)232*5113495bSYour Name static int pld_sdio_resume(struct device *dev)
233*5113495bSYour Name {
234*5113495bSYour Name 	struct pld_context *pld_context;
235*5113495bSYour Name 
236*5113495bSYour Name 	pld_context = pld_get_global_context();
237*5113495bSYour Name 	return pld_context->ops->resume(dev, PLD_BUS_TYPE_SDIO);
238*5113495bSYour Name }
239*5113495bSYour Name #endif
240*5113495bSYour Name 
241*5113495bSYour Name static struct sdio_device_id pld_sdio_id_table[] = {
242*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x0))},
243*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x1))},
244*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x2))},
245*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x3))},
246*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x4))},
247*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x5))},
248*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x6))},
249*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x7))},
250*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x8))},
251*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0x9))},
252*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0xA))},
253*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0xB))},
254*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0xC))},
255*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0xD))},
256*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0xE))},
257*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6320_BASE | 0xF))},
258*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x0))},
259*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x1))},
260*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x2))},
261*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x3))},
262*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x4))},
263*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x5))},
264*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x6))},
265*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x7))},
266*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x8))},
267*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0x9))},
268*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xA))},
269*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xB))},
270*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xC))},
271*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xD))},
272*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xE))},
273*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xF))},
274*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x0))},
275*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x1))},
276*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x2))},
277*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x3))},
278*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x4))},
279*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x5))},
280*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x6))},
281*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x7))},
282*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x8))},
283*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x9))},
284*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0xA))},
285*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0xB))},
286*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0xC))},
287*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0xD))},
288*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0xE))},
289*5113495bSYour Name 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0xF))},
290*5113495bSYour Name 	{},
291*5113495bSYour Name };
292*5113495bSYour Name 
293*5113495bSYour Name #ifdef CONFIG_PLD_SDIO_CNSS2
294*5113495bSYour Name /**
295*5113495bSYour Name  * pld_sdio_reinit() - SSR re-initialize function for SDIO device
296*5113495bSYour Name  * @sdio_func: pointer to sdio device function
297*5113495bSYour Name  * @id: SDIO device ID
298*5113495bSYour Name  *
299*5113495bSYour Name  * During subsystem restart(SSR), this function will be called to
300*5113495bSYour Name  * re-initialize SDIO device.
301*5113495bSYour Name  *
302*5113495bSYour Name  * Return: int
303*5113495bSYour Name  */
pld_sdio_reinit(struct sdio_func * sdio_func,const struct sdio_device_id * id)304*5113495bSYour Name static int pld_sdio_reinit(struct sdio_func *sdio_func,
305*5113495bSYour Name 			   const struct sdio_device_id *id)
306*5113495bSYour Name {
307*5113495bSYour Name 	/* TODO */
308*5113495bSYour Name 	return -ENODEV;
309*5113495bSYour Name }
310*5113495bSYour Name 
311*5113495bSYour Name /**
312*5113495bSYour Name  * pld_sdio_shutdown() - SSR shutdown function for SDIO device
313*5113495bSYour Name  * @sdio_func: pointer to sdio device function
314*5113495bSYour Name  *
315*5113495bSYour Name  * During SSR, this function will be called to shutdown SDIO device.
316*5113495bSYour Name  *
317*5113495bSYour Name  * Return: void
318*5113495bSYour Name  */
pld_sdio_shutdown(struct sdio_func * sdio_func)319*5113495bSYour Name static void pld_sdio_shutdown(struct sdio_func *sdio_func)
320*5113495bSYour Name {
321*5113495bSYour Name 	/* TODO */
322*5113495bSYour Name }
323*5113495bSYour Name 
324*5113495bSYour Name /**
325*5113495bSYour Name  * pld_sdio_crash_shutdown() - Crash shutdown function for SDIO device
326*5113495bSYour Name  * @sdio_func: pointer to sdio device function
327*5113495bSYour Name  *
328*5113495bSYour Name  * This function will be called when a crash is detected, it will shutdown
329*5113495bSYour Name  * the SDIO device.
330*5113495bSYour Name  *
331*5113495bSYour Name  * Return: void
332*5113495bSYour Name  */
pld_sdio_crash_shutdown(struct sdio_func * sdio_func)333*5113495bSYour Name static void pld_sdio_crash_shutdown(struct sdio_func *sdio_func)
334*5113495bSYour Name {
335*5113495bSYour Name 	/* TODO */
336*5113495bSYour Name }
337*5113495bSYour Name 
pld_sdio_uevent(struct sdio_func * sdio_func,uint32_t status)338*5113495bSYour Name static void pld_sdio_uevent(struct sdio_func *sdio_func, uint32_t status)
339*5113495bSYour Name {
340*5113495bSYour Name 	struct pld_context *pld_context;
341*5113495bSYour Name 	struct device *dev = &sdio_func->dev;
342*5113495bSYour Name 	struct pld_uevent_data data = {0};
343*5113495bSYour Name 
344*5113495bSYour Name 	pld_context = pld_get_global_context();
345*5113495bSYour Name 
346*5113495bSYour Name 	if (!pld_context)
347*5113495bSYour Name 		return;
348*5113495bSYour Name 
349*5113495bSYour Name 	switch (status) {
350*5113495bSYour Name 	case CNSS_RECOVERY:
351*5113495bSYour Name 		data.uevent = PLD_FW_RECOVERY_START;
352*5113495bSYour Name 		break;
353*5113495bSYour Name 	case CNSS_FW_DOWN:
354*5113495bSYour Name 		data.uevent = PLD_FW_DOWN;
355*5113495bSYour Name 		break;
356*5113495bSYour Name 	default:
357*5113495bSYour Name 		goto out;
358*5113495bSYour Name 	}
359*5113495bSYour Name 
360*5113495bSYour Name 	if (pld_context->ops->uevent)
361*5113495bSYour Name 		pld_context->ops->uevent(dev, &data);
362*5113495bSYour Name out:
363*5113495bSYour Name 	return;
364*5113495bSYour Name }
365*5113495bSYour Name 
366*5113495bSYour Name struct cnss_sdio_wlan_driver pld_sdio_ops = {
367*5113495bSYour Name 	.name       = "pld_sdio",
368*5113495bSYour Name 	.id_table   = pld_sdio_id_table,
369*5113495bSYour Name 	.probe      = pld_sdio_probe,
370*5113495bSYour Name 	.remove     = pld_sdio_remove,
371*5113495bSYour Name 	.reinit     = pld_sdio_reinit,
372*5113495bSYour Name 	.shutdown   = pld_sdio_shutdown,
373*5113495bSYour Name 	.crash_shutdown = pld_sdio_crash_shutdown,
374*5113495bSYour Name 	.update_status  = pld_sdio_uevent,
375*5113495bSYour Name #ifdef CONFIG_PM
376*5113495bSYour Name 	.suspend    = pld_sdio_suspend,
377*5113495bSYour Name 	.resume     = pld_sdio_resume,
378*5113495bSYour Name #endif
379*5113495bSYour Name };
380*5113495bSYour Name 
pld_sdio_register_driver(void)381*5113495bSYour Name int pld_sdio_register_driver(void)
382*5113495bSYour Name {
383*5113495bSYour Name 	return cnss_sdio_wlan_register_driver(&pld_sdio_ops);
384*5113495bSYour Name }
385*5113495bSYour Name 
pld_sdio_unregister_driver(void)386*5113495bSYour Name void pld_sdio_unregister_driver(void)
387*5113495bSYour Name {
388*5113495bSYour Name 	cnss_sdio_wlan_unregister_driver(&pld_sdio_ops);
389*5113495bSYour Name }
390*5113495bSYour Name 
pld_sdio_wlan_enable(struct device * dev,struct pld_wlan_enable_cfg * config,enum pld_driver_mode mode,const char * host_version)391*5113495bSYour Name int pld_sdio_wlan_enable(struct device *dev, struct pld_wlan_enable_cfg *config,
392*5113495bSYour Name 			 enum pld_driver_mode mode, const char *host_version)
393*5113495bSYour Name {
394*5113495bSYour Name 	struct cnss_wlan_enable_cfg cfg;
395*5113495bSYour Name 	enum cnss_driver_mode cnss_mode;
396*5113495bSYour Name 
397*5113495bSYour Name 	switch (mode) {
398*5113495bSYour Name 	case PLD_FTM:
399*5113495bSYour Name 		cnss_mode = CNSS_FTM;
400*5113495bSYour Name 		break;
401*5113495bSYour Name 	case PLD_EPPING:
402*5113495bSYour Name 		cnss_mode = CNSS_EPPING;
403*5113495bSYour Name 		break;
404*5113495bSYour Name 	default:
405*5113495bSYour Name 		cnss_mode = CNSS_MISSION;
406*5113495bSYour Name 		break;
407*5113495bSYour Name 	}
408*5113495bSYour Name 	return cnss_wlan_enable(dev, &cfg, cnss_mode, host_version);
409*5113495bSYour Name }
410*5113495bSYour Name 
411*5113495bSYour Name #else
412*5113495bSYour Name 
413*5113495bSYour Name #ifdef CONFIG_PM
414*5113495bSYour Name static const struct dev_pm_ops pld_device_pm_ops = {
415*5113495bSYour Name 	.suspend = pld_sdio_suspend,
416*5113495bSYour Name 	.resume = pld_sdio_resume,
417*5113495bSYour Name };
418*5113495bSYour Name #endif
419*5113495bSYour Name 
420*5113495bSYour Name struct sdio_driver pld_sdio_ops = {
421*5113495bSYour Name 	.name       = "pld_sdio",
422*5113495bSYour Name 	.id_table   = pld_sdio_id_table,
423*5113495bSYour Name 	.probe      = pld_sdio_probe,
424*5113495bSYour Name 	.remove     = pld_sdio_remove,
425*5113495bSYour Name #if defined(CONFIG_PM)
426*5113495bSYour Name 	.drv = {
427*5113495bSYour Name 		.pm = &pld_device_pm_ops,
428*5113495bSYour Name 	}
429*5113495bSYour Name #endif
430*5113495bSYour Name };
431*5113495bSYour Name 
pld_sdio_register_driver(void)432*5113495bSYour Name int pld_sdio_register_driver(void)
433*5113495bSYour Name {
434*5113495bSYour Name 	return sdio_register_driver(&pld_sdio_ops);
435*5113495bSYour Name }
436*5113495bSYour Name 
pld_sdio_unregister_driver(void)437*5113495bSYour Name void pld_sdio_unregister_driver(void)
438*5113495bSYour Name {
439*5113495bSYour Name 	sdio_unregister_driver(&pld_sdio_ops);
440*5113495bSYour Name }
441*5113495bSYour Name #endif
442*5113495bSYour Name 
443*5113495bSYour Name #ifdef CONFIG_PLD_SDIO_CNSS
444*5113495bSYour Name #ifdef CONFIG_TUFELLO_DUAL_FW_SUPPORT
pld_sdio_is_tufello_dual_fw_supported(void)445*5113495bSYour Name static inline int pld_sdio_is_tufello_dual_fw_supported(void)
446*5113495bSYour Name {
447*5113495bSYour Name 	return 1;
448*5113495bSYour Name }
449*5113495bSYour Name #else
pld_sdio_is_tufello_dual_fw_supported(void)450*5113495bSYour Name static inline int pld_sdio_is_tufello_dual_fw_supported(void)
451*5113495bSYour Name {
452*5113495bSYour Name 	return 0;
453*5113495bSYour Name #endif
454*5113495bSYour Name }
455*5113495bSYour Name 
pld_sdio_get_fw_files_for_target(struct pld_fw_files * pfw_files,u32 target_type,u32 target_version)456*5113495bSYour Name int pld_sdio_get_fw_files_for_target(struct pld_fw_files *pfw_files,
457*5113495bSYour Name 				     u32 target_type, u32 target_version)
458*5113495bSYour Name {
459*5113495bSYour Name 	int ret = 0;
460*5113495bSYour Name 	struct cnss_fw_files cnss_fw_files;
461*5113495bSYour Name 
462*5113495bSYour Name 	if (!pfw_files)
463*5113495bSYour Name 		return -ENODEV;
464*5113495bSYour Name 
465*5113495bSYour Name 	memset(pfw_files, 0, sizeof(*pfw_files));
466*5113495bSYour Name 
467*5113495bSYour Name 	if (target_version == PLD_QCA9377_REV1_1_VERSION) {
468*5113495bSYour Name 		cnss_get_qca9377_fw_files(&cnss_fw_files, PLD_MAX_FILE_NAME,
469*5113495bSYour Name 			pld_sdio_is_tufello_dual_fw_supported());
470*5113495bSYour Name 	} else {
471*5113495bSYour Name 		ret = cnss_get_fw_files_for_target(&cnss_fw_files,
472*5113495bSYour Name 					   target_type, target_version);
473*5113495bSYour Name 	}
474*5113495bSYour Name 	if (0 != ret)
475*5113495bSYour Name 		return ret;
476*5113495bSYour Name 
477*5113495bSYour Name 	snprintf(pfw_files->image_file, PLD_MAX_FILE_NAME, PREFIX "%s",
478*5113495bSYour Name 		cnss_fw_files.image_file);
479*5113495bSYour Name 	snprintf(pfw_files->board_data, PLD_MAX_FILE_NAME, PREFIX "%s",
480*5113495bSYour Name 		cnss_fw_files.board_data);
481*5113495bSYour Name 	snprintf(pfw_files->otp_data, PLD_MAX_FILE_NAME, PREFIX "%s",
482*5113495bSYour Name 		cnss_fw_files.otp_data);
483*5113495bSYour Name 	snprintf(pfw_files->utf_file, PLD_MAX_FILE_NAME, PREFIX "%s",
484*5113495bSYour Name 		cnss_fw_files.utf_file);
485*5113495bSYour Name 	snprintf(pfw_files->utf_board_data, PLD_MAX_FILE_NAME, PREFIX "%s",
486*5113495bSYour Name 		cnss_fw_files.utf_board_data);
487*5113495bSYour Name 	snprintf(pfw_files->epping_file, PLD_MAX_FILE_NAME, PREFIX "%s",
488*5113495bSYour Name 		cnss_fw_files.epping_file);
489*5113495bSYour Name 	snprintf(pfw_files->evicted_data, PLD_MAX_FILE_NAME, PREFIX "%s",
490*5113495bSYour Name 		cnss_fw_files.evicted_data);
491*5113495bSYour Name 
492*5113495bSYour Name 	return ret;
493*5113495bSYour Name }
494*5113495bSYour Name #else
495*5113495bSYour Name #ifdef CONFIG_TUFELLO_DUAL_FW_SUPPORT
get_qca9377_fw_files(struct pld_fw_files * pfw_files,u32 size)496*5113495bSYour Name static inline void get_qca9377_fw_files(struct pld_fw_files *pfw_files,
497*5113495bSYour Name 					u32 size)
498*5113495bSYour Name {
499*5113495bSYour Name 		memcpy(pfw_files, &fw_files_default, sizeof(*pfw_files));
500*5113495bSYour Name }
501*5113495bSYour Name #else
get_qca9377_fw_files(struct pld_fw_files * pfw_files,u32 size)502*5113495bSYour Name static inline void get_qca9377_fw_files(struct pld_fw_files *pfw_files,
503*5113495bSYour Name 					u32 size)
504*5113495bSYour Name {
505*5113495bSYour Name 		memcpy(pfw_files, &fw_files_qca6174_fw_3_0, sizeof(*pfw_files));
506*5113495bSYour Name }
507*5113495bSYour Name #endif
508*5113495bSYour Name 
pld_sdio_get_fw_files_for_target(struct pld_fw_files * pfw_files,u32 target_type,u32 target_version)509*5113495bSYour Name int pld_sdio_get_fw_files_for_target(struct pld_fw_files *pfw_files,
510*5113495bSYour Name 				     u32 target_type, u32 target_version)
511*5113495bSYour Name {
512*5113495bSYour Name 	if (!pfw_files)
513*5113495bSYour Name 		return -ENODEV;
514*5113495bSYour Name 
515*5113495bSYour Name 	switch (target_version) {
516*5113495bSYour Name 	case PLD_AR6320_REV1_VERSION:
517*5113495bSYour Name 	case PLD_AR6320_REV1_1_VERSION:
518*5113495bSYour Name 		memcpy(pfw_files, &fw_files_qca6174_fw_1_1, sizeof(*pfw_files));
519*5113495bSYour Name 		break;
520*5113495bSYour Name 	case PLD_AR6320_REV1_3_VERSION:
521*5113495bSYour Name 		memcpy(pfw_files, &fw_files_qca6174_fw_1_3, sizeof(*pfw_files));
522*5113495bSYour Name 		break;
523*5113495bSYour Name 	case PLD_AR6320_REV2_1_VERSION:
524*5113495bSYour Name 		memcpy(pfw_files, &fw_files_qca6174_fw_2_0, sizeof(*pfw_files));
525*5113495bSYour Name 		break;
526*5113495bSYour Name 	case PLD_AR6320_REV3_VERSION:
527*5113495bSYour Name 	case PLD_AR6320_REV3_2_VERSION:
528*5113495bSYour Name 		memcpy(pfw_files, &fw_files_qca6174_fw_3_0, sizeof(*pfw_files));
529*5113495bSYour Name 		break;
530*5113495bSYour Name 	case PLD_QCA9377_REV1_1_VERSION:
531*5113495bSYour Name 	case PLD_QCA9379_REV1_VERSION:
532*5113495bSYour Name 		get_qca9377_fw_files(pfw_files, sizeof(*pfw_files));
533*5113495bSYour Name 		break;
534*5113495bSYour Name 	default:
535*5113495bSYour Name 		memcpy(pfw_files, &fw_files_default, sizeof(*pfw_files));
536*5113495bSYour Name 		pr_err("%s version mismatch 0x%X ",
537*5113495bSYour Name 				__func__, target_version);
538*5113495bSYour Name 		break;
539*5113495bSYour Name 	}
540*5113495bSYour Name 
541*5113495bSYour Name 	return 0;
542*5113495bSYour Name }
543*5113495bSYour Name #endif
544*5113495bSYour Name #endif
545