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