xref: /linux/drivers/staging/rtl8723bs/os_dep/sdio_intf.c (revision 3a39d672e7f48b8d6b91a09afa4b55352773b4b5)
1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
5  *
6  ******************************************************************************/
7 #include <drv_types.h>
8 #include <hal_btcoex.h>
9 #include <linux/jiffies.h>
10 
11 #ifndef dev_to_sdio_func
12 #define dev_to_sdio_func(d)     container_of(d, struct sdio_func, dev)
13 #endif
14 
15 static const struct sdio_device_id sdio_ids[] = {
16 	{ SDIO_DEVICE(0x024c, 0x0523), },
17 	{ SDIO_DEVICE(0x024c, 0x0525), },
18 	{ SDIO_DEVICE(0x024c, 0x0623), },
19 	{ SDIO_DEVICE(0x024c, 0x0626), },
20 	{ SDIO_DEVICE(0x024c, 0x0627), },
21 	{ SDIO_DEVICE(0x024c, 0xb723), },
22 	{ /* end: all zeroes */				},
23 };
24 MODULE_DEVICE_TABLE(sdio, sdio_ids);
25 
26 static int rtw_drv_init(struct sdio_func *func, const struct sdio_device_id *id);
27 static void rtw_dev_remove(struct sdio_func *func);
28 static int rtw_sdio_resume(struct device *dev);
29 static int rtw_sdio_suspend(struct device *dev);
30 
31 static const struct dev_pm_ops rtw_sdio_pm_ops = {
32 	.suspend	= rtw_sdio_suspend,
33 	.resume	= rtw_sdio_resume,
34 };
35 
36 static struct sdio_driver rtl8723bs_sdio_driver = {
37 	.probe = rtw_drv_init,
38 	.remove = rtw_dev_remove,
39 	.name = "rtl8723bs",
40 	.id_table = sdio_ids,
41 	.drv = {
42 		.pm = &rtw_sdio_pm_ops,
43 	}
44 };
45 
sd_sync_int_hdl(struct sdio_func * func)46 static void sd_sync_int_hdl(struct sdio_func *func)
47 {
48 	struct dvobj_priv *psdpriv;
49 
50 
51 	psdpriv = sdio_get_drvdata(func);
52 
53 	if (!psdpriv->if1)
54 		return;
55 
56 	rtw_sdio_set_irq_thd(psdpriv, current);
57 	sd_int_hdl(psdpriv->if1);
58 	rtw_sdio_set_irq_thd(psdpriv, NULL);
59 }
60 
sdio_alloc_irq(struct dvobj_priv * dvobj)61 static int sdio_alloc_irq(struct dvobj_priv *dvobj)
62 {
63 	struct sdio_data *psdio_data;
64 	struct sdio_func *func;
65 	int err;
66 
67 	psdio_data = &dvobj->intf_data;
68 	func = psdio_data->func;
69 
70 	sdio_claim_host(func);
71 
72 	err = sdio_claim_irq(func, &sd_sync_int_hdl);
73 	if (err) {
74 		dvobj->drv_dbg.dbg_sdio_alloc_irq_error_cnt++;
75 		printk(KERN_CRIT "%s: sdio_claim_irq FAIL(%d)!\n", __func__, err);
76 	} else {
77 		dvobj->drv_dbg.dbg_sdio_alloc_irq_cnt++;
78 		dvobj->irq_alloc = 1;
79 	}
80 
81 	sdio_release_host(func);
82 
83 	return err?_FAIL:_SUCCESS;
84 }
85 
sdio_free_irq(struct dvobj_priv * dvobj)86 static void sdio_free_irq(struct dvobj_priv *dvobj)
87 {
88 	struct sdio_data *psdio_data;
89 	struct sdio_func *func;
90 	int err;
91 
92 	if (dvobj->irq_alloc) {
93 		psdio_data = &dvobj->intf_data;
94 		func = psdio_data->func;
95 
96 		if (func) {
97 			sdio_claim_host(func);
98 			err = sdio_release_irq(func);
99 			if (err) {
100 				dvobj->drv_dbg.dbg_sdio_free_irq_error_cnt++;
101 				netdev_err(dvobj->if1->pnetdev,
102 					   "%s: sdio_release_irq FAIL(%d)!\n",
103 					   __func__, err);
104 			} else
105 				dvobj->drv_dbg.dbg_sdio_free_irq_cnt++;
106 			sdio_release_host(func);
107 		}
108 		dvobj->irq_alloc = 0;
109 	}
110 }
111 
sdio_init(struct dvobj_priv * dvobj)112 static u32 sdio_init(struct dvobj_priv *dvobj)
113 {
114 	struct sdio_data *psdio_data;
115 	struct sdio_func *func;
116 	int err;
117 
118 	psdio_data = &dvobj->intf_data;
119 	func = psdio_data->func;
120 
121 	/* 3 1. init SDIO bus */
122 	sdio_claim_host(func);
123 
124 	err = sdio_enable_func(func);
125 	if (err) {
126 		dvobj->drv_dbg.dbg_sdio_init_error_cnt++;
127 		goto release;
128 	}
129 
130 	err = sdio_set_block_size(func, 512);
131 	if (err) {
132 		dvobj->drv_dbg.dbg_sdio_init_error_cnt++;
133 		goto release;
134 	}
135 	psdio_data->block_transfer_len = 512;
136 	psdio_data->tx_block_mode = 1;
137 	psdio_data->rx_block_mode = 1;
138 
139 release:
140 	sdio_release_host(func);
141 
142 	if (err)
143 		return _FAIL;
144 	return _SUCCESS;
145 }
146 
sdio_deinit(struct dvobj_priv * dvobj)147 static void sdio_deinit(struct dvobj_priv *dvobj)
148 {
149 	struct sdio_func *func;
150 	int err;
151 
152 	func = dvobj->intf_data.func;
153 
154 	if (func) {
155 		sdio_claim_host(func);
156 		err = sdio_disable_func(func);
157 		if (err)
158 			dvobj->drv_dbg.dbg_sdio_deinit_error_cnt++;
159 
160 		if (dvobj->irq_alloc) {
161 			err = sdio_release_irq(func);
162 			if (err)
163 				dvobj->drv_dbg.dbg_sdio_free_irq_error_cnt++;
164 			else
165 				dvobj->drv_dbg.dbg_sdio_free_irq_cnt++;
166 		}
167 
168 		sdio_release_host(func);
169 	}
170 }
sdio_dvobj_init(struct sdio_func * func)171 static struct dvobj_priv *sdio_dvobj_init(struct sdio_func *func)
172 {
173 	int status = _FAIL;
174 	struct dvobj_priv *dvobj = NULL;
175 	struct sdio_data *psdio;
176 
177 	dvobj = devobj_init();
178 	if (!dvobj)
179 		goto exit;
180 
181 	sdio_set_drvdata(func, dvobj);
182 
183 	psdio = &dvobj->intf_data;
184 	psdio->func = func;
185 
186 	if (sdio_init(dvobj) != _SUCCESS)
187 		goto free_dvobj;
188 
189 	rtw_reset_continual_io_error(dvobj);
190 	status = _SUCCESS;
191 
192 free_dvobj:
193 	if (status != _SUCCESS && dvobj) {
194 		sdio_set_drvdata(func, NULL);
195 
196 		devobj_deinit(dvobj);
197 
198 		dvobj = NULL;
199 	}
200 exit:
201 	return dvobj;
202 }
203 
sdio_dvobj_deinit(struct sdio_func * func)204 static void sdio_dvobj_deinit(struct sdio_func *func)
205 {
206 	struct dvobj_priv *dvobj = sdio_get_drvdata(func);
207 
208 	sdio_set_drvdata(func, NULL);
209 	if (dvobj) {
210 		sdio_deinit(dvobj);
211 		devobj_deinit(dvobj);
212 	}
213 }
214 
rtw_set_hal_ops(struct adapter * padapter)215 void rtw_set_hal_ops(struct adapter *padapter)
216 {
217 	/* alloc memory for HAL DATA */
218 	rtw_hal_data_init(padapter);
219 
220 	rtl8723bs_set_hal_ops(padapter);
221 }
222 
sd_intf_start(struct adapter * padapter)223 static void sd_intf_start(struct adapter *padapter)
224 {
225 	if (!padapter)
226 		return;
227 
228 	/*  hal dep */
229 	rtw_hal_enable_interrupt(padapter);
230 }
231 
sd_intf_stop(struct adapter * padapter)232 static void sd_intf_stop(struct adapter *padapter)
233 {
234 	if (!padapter)
235 		return;
236 
237 	/*  hal dep */
238 	rtw_hal_disable_interrupt(padapter);
239 }
240 
241 
rtw_sdio_if1_init(struct dvobj_priv * dvobj,const struct sdio_device_id * pdid)242 static struct adapter *rtw_sdio_if1_init(struct dvobj_priv *dvobj, const struct sdio_device_id  *pdid)
243 {
244 	int status = _FAIL;
245 	struct net_device *pnetdev;
246 	struct adapter *padapter = NULL;
247 	struct sdio_data *psdio = &dvobj->intf_data;
248 
249 	padapter = vzalloc(sizeof(*padapter));
250 	if (!padapter)
251 		goto exit;
252 
253 	padapter->dvobj = dvobj;
254 	dvobj->if1 = padapter;
255 
256 	padapter->bDriverStopped = true;
257 
258 	dvobj->padapters = padapter;
259 	padapter->iface_id = 0;
260 
261 	/* 3 1. init network device data */
262 	pnetdev = rtw_init_netdev(padapter);
263 	if (!pnetdev)
264 		goto free_adapter;
265 
266 	SET_NETDEV_DEV(pnetdev, dvobj_to_dev(dvobj));
267 
268 	padapter = rtw_netdev_priv(pnetdev);
269 
270 	/* 3 3. init driver special setting, interface, OS and hardware relative */
271 
272 	/* 4 3.1 set hardware operation functions */
273 	rtw_set_hal_ops(padapter);
274 
275 
276 	/* 3 5. initialize Chip version */
277 	padapter->intf_start = &sd_intf_start;
278 	padapter->intf_stop = &sd_intf_stop;
279 
280 	padapter->intf_init = &sdio_init;
281 	padapter->intf_deinit = &sdio_deinit;
282 	padapter->intf_alloc_irq = &sdio_alloc_irq;
283 	padapter->intf_free_irq = &sdio_free_irq;
284 
285 	if (rtw_init_io_priv(padapter, sdio_set_intf_ops) == _FAIL)
286 		goto free_hal_data;
287 
288 	rtw_hal_read_chip_version(padapter);
289 
290 	rtw_hal_chip_configure(padapter);
291 
292 	hal_btcoex_Initialize((void *) padapter);
293 
294 	/* 3 6. read efuse/eeprom data */
295 	rtw_hal_read_chip_info(padapter);
296 
297 	/* 3 7. init driver common data */
298 	if (rtw_init_drv_sw(padapter) == _FAIL)
299 		goto free_hal_data;
300 
301 	rtw_wdev_alloc(padapter, dvobj_to_dev(dvobj));
302 
303 	/* 3 8. get WLan MAC address */
304 	/*  set mac addr */
305 	rtw_macaddr_cfg(&psdio->func->dev, padapter->eeprompriv.mac_addr);
306 
307 	rtw_hal_disable_interrupt(padapter);
308 
309 	status = _SUCCESS;
310 
311 free_hal_data:
312 	if (status != _SUCCESS && padapter->HalData)
313 		kfree(padapter->HalData);
314 
315 	if (status != _SUCCESS) {
316 		rtw_wdev_unregister(padapter->rtw_wdev);
317 		rtw_wdev_free(padapter->rtw_wdev);
318 	}
319 
320 free_adapter:
321 	if (status != _SUCCESS) {
322 		if (pnetdev)
323 			rtw_free_netdev(pnetdev);
324 		else
325 			vfree((u8 *)padapter);
326 		padapter = NULL;
327 	}
328 exit:
329 	return padapter;
330 }
331 
rtw_sdio_if1_deinit(struct adapter * if1)332 static void rtw_sdio_if1_deinit(struct adapter *if1)
333 {
334 	struct net_device *pnetdev = if1->pnetdev;
335 	struct mlme_priv *pmlmepriv = &if1->mlmepriv;
336 
337 	if (check_fwstate(pmlmepriv, _FW_LINKED))
338 		rtw_disassoc_cmd(if1, 0, false);
339 
340 	free_mlme_ap_info(if1);
341 
342 	rtw_cancel_all_timer(if1);
343 
344 	rtw_dev_unload(if1);
345 
346 	if (if1->rtw_wdev)
347 		rtw_wdev_free(if1->rtw_wdev);
348 
349 	rtw_free_drv_sw(if1);
350 
351 	if (pnetdev)
352 		rtw_free_netdev(pnetdev);
353 }
354 
355 /*
356  * drv_init() - a device potentially for us
357  *
358  * notes: drv_init() is called when the bus driver has located a card for us to support.
359  *        We accept the new device by returning 0.
360  */
rtw_drv_init(struct sdio_func * func,const struct sdio_device_id * id)361 static int rtw_drv_init(
362 	struct sdio_func *func,
363 	const struct sdio_device_id *id)
364 {
365 	int status = _FAIL;
366 	struct adapter *if1 = NULL;
367 	struct dvobj_priv *dvobj;
368 
369 	dvobj = sdio_dvobj_init(func);
370 	if (!dvobj)
371 		goto exit;
372 
373 	if1 = rtw_sdio_if1_init(dvobj, id);
374 	if (!if1)
375 		goto free_dvobj;
376 
377 	/* dev_alloc_name && register_netdev */
378 	status = rtw_drv_register_netdev(if1);
379 	if (status != _SUCCESS)
380 		goto free_if1;
381 
382 	if (sdio_alloc_irq(dvobj) != _SUCCESS)
383 		goto free_if1;
384 
385 	rtw_ndev_notifier_register();
386 	status = _SUCCESS;
387 
388 free_if1:
389 	if (status != _SUCCESS && if1)
390 		rtw_sdio_if1_deinit(if1);
391 
392 free_dvobj:
393 	if (status != _SUCCESS)
394 		sdio_dvobj_deinit(func);
395 exit:
396 	return status == _SUCCESS ? 0 : -ENODEV;
397 }
398 
rtw_dev_remove(struct sdio_func * func)399 static void rtw_dev_remove(struct sdio_func *func)
400 {
401 	struct dvobj_priv *dvobj = sdio_get_drvdata(func);
402 	struct adapter *padapter = dvobj->if1;
403 
404 	dvobj->processing_dev_remove = true;
405 
406 	rtw_unregister_netdevs(dvobj);
407 
408 	if (!padapter->bSurpriseRemoved) {
409 		int err;
410 
411 		/* test surprise remove */
412 		sdio_claim_host(func);
413 		sdio_readb(func, 0, &err);
414 		sdio_release_host(func);
415 		if (err == -ENOMEDIUM)
416 			padapter->bSurpriseRemoved = true;
417 	}
418 
419 	rtw_ps_deny(padapter, PS_DENY_DRV_REMOVE);
420 
421 	rtw_pm_set_ips(padapter, IPS_NONE);
422 	rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
423 
424 	LeaveAllPowerSaveMode(padapter);
425 
426 	rtw_btcoex_HaltNotify(padapter);
427 
428 	rtw_sdio_if1_deinit(padapter);
429 
430 	sdio_dvobj_deinit(func);
431 }
432 
rtw_sdio_suspend(struct device * dev)433 static int rtw_sdio_suspend(struct device *dev)
434 {
435 	struct sdio_func *func = dev_to_sdio_func(dev);
436 	struct dvobj_priv *psdpriv = sdio_get_drvdata(func);
437 	struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(psdpriv);
438 	struct adapter *padapter = psdpriv->if1;
439 	struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
440 
441 	if (padapter->bDriverStopped)
442 		return 0;
443 
444 	if (pwrpriv->bInSuspend) {
445 		pdbgpriv->dbg_suspend_error_cnt++;
446 		return 0;
447 	}
448 
449 	rtw_suspend_common(padapter);
450 
451 	return 0;
452 }
453 
rtw_resume_process(struct adapter * padapter)454 static int rtw_resume_process(struct adapter *padapter)
455 {
456 	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
457 	struct dvobj_priv *psdpriv = padapter->dvobj;
458 	struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
459 
460 	if (!pwrpriv->bInSuspend) {
461 		pdbgpriv->dbg_resume_error_cnt++;
462 		return -1;
463 	}
464 
465 	return rtw_resume_common(padapter);
466 }
467 
rtw_sdio_resume(struct device * dev)468 static int rtw_sdio_resume(struct device *dev)
469 {
470 	struct sdio_func *func = dev_to_sdio_func(dev);
471 	struct dvobj_priv *psdpriv = sdio_get_drvdata(func);
472 	struct adapter *padapter = psdpriv->if1;
473 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
474 	int ret = 0;
475 	struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
476 
477 	pdbgpriv->dbg_resume_cnt++;
478 
479 	ret = rtw_resume_process(padapter);
480 
481 	pmlmeext->last_scan_time = jiffies;
482 	return ret;
483 }
484 
rtw_drv_entry(void)485 static int __init rtw_drv_entry(void)
486 {
487 	int ret;
488 
489 	ret = sdio_register_driver(&rtl8723bs_sdio_driver);
490 	if (ret != 0)
491 		rtw_ndev_notifier_unregister();
492 
493 	return ret;
494 }
495 
rtw_drv_halt(void)496 static void __exit rtw_drv_halt(void)
497 {
498 	sdio_unregister_driver(&rtl8723bs_sdio_driver);
499 
500 	rtw_ndev_notifier_unregister();
501 }
502 
503 
504 module_init(rtw_drv_entry);
505 module_exit(rtw_drv_halt);
506