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