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