xref: /linux/drivers/staging/rtl8723bs/os_dep/sdio_intf.c (revision 1641684528815bb7e85737d5d2bceb551c55d5a8)
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 		netdev_crit(dvobj->if1->pnetdev, "%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 
sd_intf_start(struct adapter * padapter)221 static void sd_intf_start(struct adapter *padapter)
222 {
223 	if (!padapter)
224 		return;
225 
226 	/*  hal dep */
227 	rtw_hal_enable_interrupt(padapter);
228 }
229 
sd_intf_stop(struct adapter * padapter)230 static void sd_intf_stop(struct adapter *padapter)
231 {
232 	if (!padapter)
233 		return;
234 
235 	/*  hal dep */
236 	rtw_hal_disable_interrupt(padapter);
237 }
238 
239 
rtw_sdio_if1_init(struct dvobj_priv * dvobj,const struct sdio_device_id * pdid)240 static struct adapter *rtw_sdio_if1_init(struct dvobj_priv *dvobj, const struct sdio_device_id  *pdid)
241 {
242 	int status = _FAIL;
243 	struct net_device *pnetdev;
244 	struct adapter *padapter = NULL;
245 	struct sdio_data *psdio = &dvobj->intf_data;
246 
247 	padapter = vzalloc(sizeof(*padapter));
248 	if (!padapter)
249 		goto exit;
250 
251 	padapter->dvobj = dvobj;
252 	dvobj->if1 = padapter;
253 
254 	padapter->bDriverStopped = true;
255 
256 	dvobj->padapters = padapter;
257 	padapter->iface_id = 0;
258 
259 	/* 3 1. init network device data */
260 	pnetdev = rtw_init_netdev(padapter);
261 	if (!pnetdev)
262 		goto free_adapter;
263 
264 	SET_NETDEV_DEV(pnetdev, dvobj_to_dev(dvobj));
265 
266 	padapter = rtw_netdev_priv(pnetdev);
267 
268 	/* 3 3. init driver special setting, interface, OS and hardware relative */
269 
270 	/* 4 3.1 set hardware operation functions */
271 	rtw_set_hal_ops(padapter);
272 
273 
274 	/* 3 5. initialize Chip version */
275 	padapter->intf_start = &sd_intf_start;
276 	padapter->intf_stop = &sd_intf_stop;
277 
278 	padapter->intf_init = &sdio_init;
279 	padapter->intf_deinit = &sdio_deinit;
280 	padapter->intf_alloc_irq = &sdio_alloc_irq;
281 	padapter->intf_free_irq = &sdio_free_irq;
282 
283 	if (rtw_init_io_priv(padapter, sdio_set_intf_ops) == _FAIL)
284 		goto free_hal_data;
285 
286 	rtw_hal_read_chip_version(padapter);
287 
288 	rtw_hal_chip_configure(padapter);
289 
290 	hal_btcoex_Initialize((void *)padapter);
291 
292 	/* 3 6. read efuse/eeprom data */
293 	rtw_hal_read_chip_info(padapter);
294 
295 	/* 3 7. init driver common data */
296 	if (rtw_init_drv_sw(padapter) == _FAIL)
297 		goto free_hal_data;
298 
299 	rtw_wdev_alloc(padapter, dvobj_to_dev(dvobj));
300 
301 	/* 3 8. get WLan MAC address */
302 	/*  set mac addr */
303 	rtw_macaddr_cfg(&psdio->func->dev, padapter->eeprompriv.mac_addr);
304 
305 	rtw_hal_disable_interrupt(padapter);
306 
307 	status = _SUCCESS;
308 
309 free_hal_data:
310 	if (status != _SUCCESS && padapter->HalData)
311 		kfree(padapter->HalData);
312 
313 	if (status != _SUCCESS) {
314 		rtw_wdev_unregister(padapter->rtw_wdev);
315 		rtw_wdev_free(padapter->rtw_wdev);
316 	}
317 
318 free_adapter:
319 	if (status != _SUCCESS) {
320 		if (pnetdev)
321 			rtw_free_netdev(pnetdev);
322 		else
323 			vfree((u8 *)padapter);
324 		padapter = NULL;
325 	}
326 exit:
327 	return padapter;
328 }
329 
rtw_sdio_if1_deinit(struct adapter * if1)330 static void rtw_sdio_if1_deinit(struct adapter *if1)
331 {
332 	struct net_device *pnetdev = if1->pnetdev;
333 	struct mlme_priv *pmlmepriv = &if1->mlmepriv;
334 
335 	if (check_fwstate(pmlmepriv, _FW_LINKED))
336 		rtw_disassoc_cmd(if1, 0, false);
337 
338 	free_mlme_ap_info(if1);
339 
340 	rtw_cancel_all_timer(if1);
341 
342 	rtw_dev_unload(if1);
343 
344 	if (if1->rtw_wdev)
345 		rtw_wdev_free(if1->rtw_wdev);
346 
347 	rtw_free_drv_sw(if1);
348 
349 	if (pnetdev)
350 		rtw_free_netdev(pnetdev);
351 }
352 
353 /*
354  * drv_init() - a device potentially for us
355  *
356  * notes: drv_init() is called when the bus driver has located a card for us to support.
357  *        We accept the new device by returning 0.
358  */
rtw_drv_init(struct sdio_func * func,const struct sdio_device_id * id)359 static int rtw_drv_init(
360 	struct sdio_func *func,
361 	const struct sdio_device_id *id)
362 {
363 	int status = _FAIL;
364 	struct adapter *if1 = NULL;
365 	struct dvobj_priv *dvobj;
366 
367 	dvobj = sdio_dvobj_init(func);
368 	if (!dvobj)
369 		goto exit;
370 
371 	if1 = rtw_sdio_if1_init(dvobj, id);
372 	if (!if1)
373 		goto free_dvobj;
374 
375 	/* dev_alloc_name && register_netdev */
376 	status = rtw_drv_register_netdev(if1);
377 	if (status != _SUCCESS)
378 		goto free_if1;
379 
380 	if (sdio_alloc_irq(dvobj) != _SUCCESS)
381 		goto free_if1;
382 
383 	status = _SUCCESS;
384 
385 free_if1:
386 	if (status != _SUCCESS && if1)
387 		rtw_sdio_if1_deinit(if1);
388 
389 free_dvobj:
390 	if (status != _SUCCESS)
391 		sdio_dvobj_deinit(func);
392 exit:
393 	return status == _SUCCESS ? 0 : -ENODEV;
394 }
395 
rtw_dev_remove(struct sdio_func * func)396 static void rtw_dev_remove(struct sdio_func *func)
397 {
398 	struct dvobj_priv *dvobj = sdio_get_drvdata(func);
399 	struct adapter *padapter = dvobj->if1;
400 
401 	dvobj->processing_dev_remove = true;
402 
403 	rtw_unregister_netdevs(dvobj);
404 
405 	if (!padapter->bSurpriseRemoved) {
406 		int err;
407 
408 		/* test surprise remove */
409 		sdio_claim_host(func);
410 		sdio_readb(func, 0, &err);
411 		sdio_release_host(func);
412 		if (err == -ENOMEDIUM)
413 			padapter->bSurpriseRemoved = true;
414 	}
415 
416 	rtw_ps_deny(padapter, PS_DENY_DRV_REMOVE);
417 
418 	rtw_pm_set_ips(padapter, IPS_NONE);
419 	rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
420 
421 	LeaveAllPowerSaveMode(padapter);
422 
423 	rtw_btcoex_HaltNotify(padapter);
424 
425 	rtw_sdio_if1_deinit(padapter);
426 
427 	sdio_dvobj_deinit(func);
428 }
429 
rtw_sdio_suspend(struct device * dev)430 static int rtw_sdio_suspend(struct device *dev)
431 {
432 	struct sdio_func *func = dev_to_sdio_func(dev);
433 	struct dvobj_priv *psdpriv = sdio_get_drvdata(func);
434 	struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(psdpriv);
435 	struct adapter *padapter = psdpriv->if1;
436 	struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
437 
438 	if (padapter->bDriverStopped)
439 		return 0;
440 
441 	if (pwrpriv->bInSuspend) {
442 		pdbgpriv->dbg_suspend_error_cnt++;
443 		return 0;
444 	}
445 
446 	rtw_suspend_common(padapter);
447 
448 	return 0;
449 }
450 
rtw_resume_process(struct adapter * padapter)451 static int rtw_resume_process(struct adapter *padapter)
452 {
453 	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
454 	struct dvobj_priv *psdpriv = padapter->dvobj;
455 	struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
456 
457 	if (!pwrpriv->bInSuspend) {
458 		pdbgpriv->dbg_resume_error_cnt++;
459 		return -1;
460 	}
461 
462 	return rtw_resume_common(padapter);
463 }
464 
rtw_sdio_resume(struct device * dev)465 static int rtw_sdio_resume(struct device *dev)
466 {
467 	struct sdio_func *func = dev_to_sdio_func(dev);
468 	struct dvobj_priv *psdpriv = sdio_get_drvdata(func);
469 	struct adapter *padapter = psdpriv->if1;
470 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
471 	int ret = 0;
472 	struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
473 
474 	pdbgpriv->dbg_resume_cnt++;
475 
476 	ret = rtw_resume_process(padapter);
477 
478 	pmlmeext->last_scan_time = jiffies;
479 	return ret;
480 }
481 
rtw_drv_entry(void)482 static int __init rtw_drv_entry(void)
483 {
484 	return sdio_register_driver(&rtl8723bs_sdio_driver);
485 }
486 module_init(rtw_drv_entry);
487 
rtw_drv_halt(void)488 static void __exit rtw_drv_halt(void)
489 {
490 	sdio_unregister_driver(&rtl8723bs_sdio_driver);
491 }
492 module_exit(rtw_drv_halt);
493