]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/rtl8723bs/os_dep/sdio_intf.c
staging: Add rtl8723bs sdio wifi driver
[karo-tx-linux.git] / drivers / staging / rtl8723bs / os_dep / sdio_intf.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  ******************************************************************************/
15 #define _HCI_INTF_C_
16
17 #include <drv_types.h>
18 #include <rtw_debug.h>
19 #include <linux/jiffies.h>
20
21 #ifndef dev_to_sdio_func
22 #define dev_to_sdio_func(d)     container_of(d, struct sdio_func, dev)
23 #endif
24
25 static const struct sdio_device_id sdio_ids[] =
26 {
27         { SDIO_DEVICE(0x024c, 0x0523), },
28         { SDIO_DEVICE(0x024c, 0x0623), },
29         { SDIO_DEVICE(0x024c, 0x0626), },
30         { SDIO_DEVICE(0x024c, 0xb723), },
31         { /* end: all zeroes */                         },
32 };
33 static const struct acpi_device_id acpi_ids[] = {
34         {"OBDA8723", 0x0000},
35         {}
36 };
37
38 MODULE_DEVICE_TABLE(sdio, sdio_ids);
39 MODULE_DEVICE_TABLE(acpi, acpi_ids);
40
41 static int rtw_drv_init(struct sdio_func *func, const struct sdio_device_id *id);
42 static void rtw_dev_remove(struct sdio_func *func);
43 static int rtw_sdio_resume(struct device *dev);
44 static int rtw_sdio_suspend(struct device *dev);
45
46 static const struct dev_pm_ops rtw_sdio_pm_ops = {
47         .suspend        = rtw_sdio_suspend,
48         .resume = rtw_sdio_resume,
49 };
50
51 struct sdio_drv_priv {
52         struct sdio_driver r871xs_drv;
53         int drv_registered;
54 };
55
56 static struct sdio_drv_priv sdio_drvpriv = {
57         .r871xs_drv.probe = rtw_drv_init,
58         .r871xs_drv.remove = rtw_dev_remove,
59         .r871xs_drv.name = "rtl8723bs",
60         .r871xs_drv.id_table = sdio_ids,
61         .r871xs_drv.drv = {
62                 .pm = &rtw_sdio_pm_ops,
63         }
64 };
65
66 static void sd_sync_int_hdl(struct sdio_func *func)
67 {
68         struct dvobj_priv *psdpriv;
69
70
71         psdpriv = sdio_get_drvdata(func);
72
73         if (!psdpriv->if1) {
74                 DBG_871X("%s if1 == NULL\n", __func__);
75                 return;
76         }
77
78         rtw_sdio_set_irq_thd(psdpriv, current);
79         sd_int_hdl(psdpriv->if1);
80         rtw_sdio_set_irq_thd(psdpriv, NULL);
81 }
82
83 static int sdio_alloc_irq(struct dvobj_priv *dvobj)
84 {
85         PSDIO_DATA psdio_data;
86         struct sdio_func *func;
87         int err;
88
89         psdio_data = &dvobj->intf_data;
90         func = psdio_data->func;
91
92         sdio_claim_host(func);
93
94         err = sdio_claim_irq(func, &sd_sync_int_hdl);
95         if (err)
96         {
97                 dvobj->drv_dbg.dbg_sdio_alloc_irq_error_cnt++;
98                 printk(KERN_CRIT "%s: sdio_claim_irq FAIL(%d)!\n", __func__, err);
99         }
100         else
101         {
102                 dvobj->drv_dbg.dbg_sdio_alloc_irq_cnt++;
103                 dvobj->irq_alloc = 1;
104         }
105
106         sdio_release_host(func);
107
108         return err?_FAIL:_SUCCESS;
109 }
110
111 static void sdio_free_irq(struct dvobj_priv *dvobj)
112 {
113     PSDIO_DATA psdio_data;
114     struct sdio_func *func;
115     int err;
116
117     if (dvobj->irq_alloc) {
118         psdio_data = &dvobj->intf_data;
119         func = psdio_data->func;
120
121         if (func) {
122             sdio_claim_host(func);
123             err = sdio_release_irq(func);
124             if (err)
125             {
126                                 dvobj->drv_dbg.dbg_sdio_free_irq_error_cnt++;
127                                 DBG_871X_LEVEL(_drv_err_,"%s: sdio_release_irq FAIL(%d)!\n", __func__, err);
128             }
129             else
130                 dvobj->drv_dbg.dbg_sdio_free_irq_cnt++;
131             sdio_release_host(func);
132         }
133         dvobj->irq_alloc = 0;
134     }
135 }
136
137 #ifdef CONFIG_GPIO_WAKEUP
138 extern unsigned int oob_irq;
139 static irqreturn_t gpio_hostwakeup_irq_thread(int irq, void *data)
140 {
141         struct adapter *padapter = (struct adapter *)data;
142         DBG_871X_LEVEL(_drv_always_, "gpio_hostwakeup_irq_thread\n");
143         /* Disable interrupt before calling handler */
144         /* disable_irq_nosync(oob_irq); */
145         rtw_lock_suspend_timeout(HZ/2);
146         return IRQ_HANDLED;
147 }
148
149 static u8 gpio_hostwakeup_alloc_irq(struct adapter *padapter)
150 {
151         int err;
152         if (oob_irq == 0) {
153                 DBG_871X("oob_irq ZERO!\n");
154                 return _FAIL;
155         }
156         /* dont set it IRQF_TRIGGER_LOW, or wowlan */
157         /* power is high after suspend */
158         /* and failing can prevent can not sleep issue if */
159         /* wifi gpio12 pin is not linked with CPU */
160         err = request_threaded_irq(oob_irq, gpio_hostwakeup_irq_thread, NULL,
161                 /* IRQF_TRIGGER_LOW | IRQF_ONESHOT, */
162                 IRQF_TRIGGER_FALLING,
163                 "rtw_wifi_gpio_wakeup", padapter);
164         if (err < 0) {
165                 DBG_871X("Oops: can't allocate gpio irq %d err:%d\n", oob_irq, err);
166                 return false;
167         } else {
168                 DBG_871X("allocate gpio irq %d ok\n", oob_irq);
169         }
170
171         enable_irq_wake(oob_irq);
172         return _SUCCESS;
173 }
174
175 static void gpio_hostwakeup_free_irq(struct adapter *padapter)
176 {
177         if (oob_irq == 0)
178                 return;
179
180         disable_irq_wake(oob_irq);
181         free_irq(oob_irq, padapter);
182 }
183 #endif
184
185 static u32 sdio_init(struct dvobj_priv *dvobj)
186 {
187         PSDIO_DATA psdio_data;
188         struct sdio_func *func;
189         int err;
190
191         psdio_data = &dvobj->intf_data;
192         func = psdio_data->func;
193
194         /* 3 1. init SDIO bus */
195         sdio_claim_host(func);
196
197         err = sdio_enable_func(func);
198         if (err) {
199                 dvobj->drv_dbg.dbg_sdio_init_error_cnt++;
200                 DBG_8192C(KERN_CRIT "%s: sdio_enable_func FAIL(%d)!\n", __func__, err);
201                 goto release;
202         }
203
204         err = sdio_set_block_size(func, 512);
205         if (err) {
206                 dvobj->drv_dbg.dbg_sdio_init_error_cnt++;
207                 DBG_8192C(KERN_CRIT "%s: sdio_set_block_size FAIL(%d)!\n", __func__, err);
208                 goto release;
209         }
210         psdio_data->block_transfer_len = 512;
211         psdio_data->tx_block_mode = 1;
212         psdio_data->rx_block_mode = 1;
213
214 release:
215         sdio_release_host(func);
216
217         if (err)
218                 return _FAIL;
219         return _SUCCESS;
220 }
221
222 static void sdio_deinit(struct dvobj_priv *dvobj)
223 {
224         struct sdio_func *func;
225         int err;
226
227
228         RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("+sdio_deinit\n"));
229
230         func = dvobj->intf_data.func;
231
232         if (func) {
233                 sdio_claim_host(func);
234                 err = sdio_disable_func(func);
235                 if (err)
236                 {
237                         dvobj->drv_dbg.dbg_sdio_deinit_error_cnt++;
238                         DBG_8192C(KERN_ERR "%s: sdio_disable_func(%d)\n", __func__, err);
239                 }
240
241                 if (dvobj->irq_alloc) {
242                         err = sdio_release_irq(func);
243                         if (err)
244                         {
245                                 dvobj->drv_dbg.dbg_sdio_free_irq_error_cnt++;
246                                 DBG_8192C(KERN_ERR "%s: sdio_release_irq(%d)\n", __func__, err);
247                         }
248                         else
249                                 dvobj->drv_dbg.dbg_sdio_free_irq_cnt++;
250                 }
251
252                 sdio_release_host(func);
253         }
254 }
255 static struct dvobj_priv *sdio_dvobj_init(struct sdio_func *func)
256 {
257         int status = _FAIL;
258         struct dvobj_priv *dvobj = NULL;
259         PSDIO_DATA psdio;
260
261         if ((dvobj = devobj_init()) == NULL) {
262                 goto exit;
263         }
264
265         sdio_set_drvdata(func, dvobj);
266
267         psdio = &dvobj->intf_data;
268         psdio->func = func;
269
270         if (sdio_init(dvobj) != _SUCCESS) {
271                 RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("%s: initialize SDIO Failed!\n", __func__));
272                 goto free_dvobj;
273         }
274         rtw_reset_continual_io_error(dvobj);
275         status = _SUCCESS;
276
277 free_dvobj:
278         if (status != _SUCCESS && dvobj) {
279                 sdio_set_drvdata(func, NULL);
280
281                 devobj_deinit(dvobj);
282
283                 dvobj = NULL;
284         }
285 exit:
286         return dvobj;
287 }
288
289 static void sdio_dvobj_deinit(struct sdio_func *func)
290 {
291         struct dvobj_priv *dvobj = sdio_get_drvdata(func);
292
293         sdio_set_drvdata(func, NULL);
294         if (dvobj) {
295                 sdio_deinit(dvobj);
296                 devobj_deinit(dvobj);
297         }
298         return;
299 }
300
301 void rtw_set_hal_ops(struct adapter *padapter)
302 {
303         /* alloc memory for HAL DATA */
304         rtw_hal_data_init(padapter);
305
306         rtl8723bs_set_hal_ops(padapter);
307 }
308
309 static void sd_intf_start(struct adapter *padapter)
310 {
311         if (padapter == NULL) {
312                 DBG_8192C(KERN_ERR "%s: padapter is NULL!\n", __func__);
313                 return;
314         }
315
316         /*  hal dep */
317         rtw_hal_enable_interrupt(padapter);
318 }
319
320 static void sd_intf_stop(struct adapter *padapter)
321 {
322         if (padapter == NULL) {
323                 DBG_8192C(KERN_ERR "%s: padapter is NULL!\n", __func__);
324                 return;
325         }
326
327         /*  hal dep */
328         rtw_hal_disable_interrupt(padapter);
329 }
330
331
332 static struct adapter *rtw_sdio_if1_init(struct dvobj_priv *dvobj, const struct sdio_device_id  *pdid)
333 {
334         int status = _FAIL;
335         struct net_device *pnetdev;
336         struct adapter *padapter = NULL;
337         PSDIO_DATA psdio = &dvobj->intf_data;
338
339         if ((padapter = (struct adapter *)vzalloc(sizeof(*padapter))) == NULL) {
340                 goto exit;
341         }
342
343         padapter->dvobj = dvobj;
344         dvobj->if1 = padapter;
345
346         padapter->bDriverStopped =true;
347
348         dvobj->padapters = padapter;
349         padapter->iface_id = 0;
350
351         /* 3 1. init network device data */
352         pnetdev = rtw_init_netdev(padapter);
353         if (!pnetdev)
354                 goto free_adapter;
355
356         SET_NETDEV_DEV(pnetdev, dvobj_to_dev(dvobj));
357
358         padapter = rtw_netdev_priv(pnetdev);
359
360         rtw_wdev_alloc(padapter, dvobj_to_dev(dvobj));
361
362         /* 3 3. init driver special setting, interface, OS and hardware relative */
363
364         /* 4 3.1 set hardware operation functions */
365         rtw_set_hal_ops(padapter);
366
367
368         /* 3 5. initialize Chip version */
369         padapter->intf_start = &sd_intf_start;
370         padapter->intf_stop = &sd_intf_stop;
371
372         padapter->intf_init = &sdio_init;
373         padapter->intf_deinit = &sdio_deinit;
374         padapter->intf_alloc_irq = &sdio_alloc_irq;
375         padapter->intf_free_irq = &sdio_free_irq;
376
377         if (rtw_init_io_priv(padapter, sdio_set_intf_ops) == _FAIL)
378         {
379                 RT_TRACE(_module_hci_intfs_c_, _drv_err_,
380                         ("rtw_drv_init: Can't init io_priv\n"));
381                 goto free_hal_data;
382         }
383
384         rtw_hal_read_chip_version(padapter);
385
386         rtw_hal_chip_configure(padapter);
387
388         rtw_btcoex_Initialize(padapter);
389
390         /* 3 6. read efuse/eeprom data */
391         rtw_hal_read_chip_info(padapter);
392
393         /* 3 7. init driver common data */
394         if (rtw_init_drv_sw(padapter) == _FAIL) {
395                 RT_TRACE(_module_hci_intfs_c_, _drv_err_,
396                          ("rtw_drv_init: Initialize driver software resource Failed!\n"));
397                 goto free_hal_data;
398         }
399
400         /* 3 8. get WLan MAC address */
401         /*  set mac addr */
402         rtw_macaddr_cfg(&psdio->func->dev, padapter->eeprompriv.mac_addr);
403
404         rtw_hal_disable_interrupt(padapter);
405
406         DBG_871X("bDriverStopped:%d, bSurpriseRemoved:%d, bup:%d, hw_init_completed:%d\n"
407                 , padapter->bDriverStopped
408                 , padapter->bSurpriseRemoved
409                 , padapter->bup
410                 , padapter->hw_init_completed
411         );
412
413         status = _SUCCESS;
414
415 free_hal_data:
416         if (status != _SUCCESS && padapter->HalData)
417                 kfree(padapter->HalData);
418
419         if (status != _SUCCESS) {
420                 rtw_wdev_unregister(padapter->rtw_wdev);
421                 rtw_wdev_free(padapter->rtw_wdev);
422         }
423
424 free_adapter:
425         if (status != _SUCCESS) {
426                 if (pnetdev)
427                         rtw_free_netdev(pnetdev);
428                 else
429                         vfree((u8 *)padapter);
430                 padapter = NULL;
431         }
432 exit:
433         return padapter;
434 }
435
436 static void rtw_sdio_if1_deinit(struct adapter *if1)
437 {
438         struct net_device *pnetdev = if1->pnetdev;
439         struct mlme_priv *pmlmepriv = &if1->mlmepriv;
440
441         if (check_fwstate(pmlmepriv, _FW_LINKED))
442                 rtw_disassoc_cmd(if1, 0, false);
443
444         free_mlme_ap_info(if1);
445
446 #ifdef CONFIG_GPIO_WAKEUP
447         gpio_hostwakeup_free_irq(if1);
448 #endif
449
450         rtw_cancel_all_timer(if1);
451
452 #ifdef CONFIG_WOWLAN
453         adapter_to_pwrctl(if1)->wowlan_mode =false;
454         DBG_871X_LEVEL(_drv_always_, "%s wowlan_mode:%d\n", __func__, adapter_to_pwrctl(if1)->wowlan_mode);
455 #endif /* CONFIG_WOWLAN */
456
457         rtw_dev_unload(if1);
458         DBG_871X("+r871xu_dev_remove, hw_init_completed =%d\n", if1->hw_init_completed);
459
460         if (if1->rtw_wdev) {
461                 rtw_wdev_free(if1->rtw_wdev);
462         }
463
464         rtw_free_drv_sw(if1);
465
466         if (pnetdev)
467                 rtw_free_netdev(pnetdev);
468 }
469
470 /*
471  * drv_init() - a device potentially for us
472  *
473  * notes: drv_init() is called when the bus driver has located a card for us to support.
474  *        We accept the new device by returning 0.
475  */
476 static int rtw_drv_init(
477         struct sdio_func *func,
478         const struct sdio_device_id *id)
479 {
480         int status = _FAIL;
481         struct adapter *if1 = NULL, *if2 = NULL;
482         struct dvobj_priv *dvobj;
483
484         if ((dvobj = sdio_dvobj_init(func)) == NULL) {
485                 RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("initialize device object priv Failed!\n"));
486                 goto exit;
487         }
488
489         if ((if1 = rtw_sdio_if1_init(dvobj, id)) == NULL) {
490                 DBG_871X("rtw_init_primarystruct adapter Failed!\n");
491                 goto free_dvobj;
492         }
493
494         /* dev_alloc_name && register_netdev */
495         if ((status = rtw_drv_register_netdev(if1)) != _SUCCESS) {
496                 goto free_if2;
497         }
498
499         if (sdio_alloc_irq(dvobj) != _SUCCESS)
500                 goto free_if2;
501
502 #ifdef  CONFIG_GPIO_WAKEUP
503         gpio_hostwakeup_alloc_irq(if1);
504 #endif
505
506         RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-871x_drv - drv_init, success!\n"));
507
508         rtw_ndev_notifier_register();
509         status = _SUCCESS;
510
511 free_if2:
512         if (status != _SUCCESS && if2) {
513         }
514         if (status != _SUCCESS && if1) {
515                 rtw_sdio_if1_deinit(if1);
516         }
517 free_dvobj:
518         if (status != _SUCCESS)
519                 sdio_dvobj_deinit(func);
520 exit:
521         return status == _SUCCESS?0:-ENODEV;
522 }
523
524 static void rtw_dev_remove(struct sdio_func *func)
525 {
526         struct dvobj_priv *dvobj = sdio_get_drvdata(func);
527         struct adapter *padapter = dvobj->if1;
528
529         RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("+rtw_dev_remove\n"));
530
531         dvobj->processing_dev_remove = true;
532
533         rtw_unregister_netdevs(dvobj);
534
535         if (padapter->bSurpriseRemoved == false) {
536                 int err;
537
538                 /* test surprise remove */
539                 sdio_claim_host(func);
540                 sdio_readb(func, 0, &err);
541                 sdio_release_host(func);
542                 if (err == -ENOMEDIUM) {
543                         padapter->bSurpriseRemoved = true;
544                         DBG_871X(KERN_NOTICE "%s: device had been removed!\n", __func__);
545                 }
546         }
547
548         rtw_ps_deny(padapter, PS_DENY_DRV_REMOVE);
549
550         rtw_pm_set_ips(padapter, IPS_NONE);
551         rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
552
553         LeaveAllPowerSaveMode(padapter);
554
555         rtw_btcoex_HaltNotify(padapter);
556
557         rtw_sdio_if1_deinit(padapter);
558
559         sdio_dvobj_deinit(func);
560
561         RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("-rtw_dev_remove\n"));
562 }
563
564 extern int pm_netdev_open(struct net_device *pnetdev, u8 bnormal);
565 extern int pm_netdev_close(struct net_device *pnetdev, u8 bnormal);
566
567 static int rtw_sdio_suspend(struct device *dev)
568 {
569         struct sdio_func *func =dev_to_sdio_func(dev);
570         struct dvobj_priv *psdpriv = sdio_get_drvdata(func);
571         struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(psdpriv);
572         struct adapter *padapter = psdpriv->if1;
573         struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
574
575         if (padapter->bDriverStopped == true)
576         {
577                 DBG_871X("%s bDriverStopped = %d\n", __func__, padapter->bDriverStopped);
578                 return 0;
579         }
580
581         if (pwrpriv->bInSuspend == true)
582         {
583                 DBG_871X("%s bInSuspend = %d\n", __func__, pwrpriv->bInSuspend);
584                 pdbgpriv->dbg_suspend_error_cnt++;
585                 return 0;
586         }
587
588         return rtw_suspend_common(padapter);
589 }
590
591 static int rtw_resume_process(struct adapter *padapter)
592 {
593         struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
594         struct dvobj_priv *psdpriv = padapter->dvobj;
595         struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
596
597         if (pwrpriv->bInSuspend == false)
598         {
599                 pdbgpriv->dbg_resume_error_cnt++;
600                 DBG_871X("%s bInSuspend = %d\n", __func__, pwrpriv->bInSuspend);
601                 return -1;
602         }
603
604         return rtw_resume_common(padapter);
605 }
606
607 static int rtw_sdio_resume(struct device *dev)
608 {
609         struct sdio_func *func =dev_to_sdio_func(dev);
610         struct dvobj_priv *psdpriv = sdio_get_drvdata(func);
611         struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(psdpriv);
612         struct adapter *padapter = psdpriv->if1;
613         struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
614         int ret = 0;
615         struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
616
617         DBG_871X("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
618
619         pdbgpriv->dbg_resume_cnt++;
620
621         if (pwrpriv->bInternalAutoSuspend)
622         {
623                 ret = rtw_resume_process(padapter);
624         }
625         else
626         {
627                 if (pwrpriv->wowlan_mode || pwrpriv->wowlan_ap_mode)
628                 {
629                         ret = rtw_resume_process(padapter);
630                 }
631                 else
632                 {
633                         ret = rtw_resume_process(padapter);
634                 }
635         }
636         pmlmeext->last_scan_time = jiffies;
637         DBG_871X("<========  %s return %d\n", __func__, ret);
638         return ret;
639
640 }
641
642 static int __init rtw_drv_entry(void)
643 {
644         int ret = 0;
645
646         DBG_871X_LEVEL(_drv_always_, "module init start\n");
647         dump_drv_version(RTW_DBGDUMP);
648 #ifdef BTCOEXVERSION
649         DBG_871X_LEVEL(_drv_always_, "rtl8723bs BT-Coex version = %s\n", BTCOEXVERSION);
650 #endif /*  BTCOEXVERSION */
651
652         sdio_drvpriv.drv_registered = true;
653         rtw_drv_proc_init();
654
655         ret = sdio_register_driver(&sdio_drvpriv.r871xs_drv);
656         if (ret != 0)
657         {
658                 sdio_drvpriv.drv_registered = false;
659                 rtw_drv_proc_deinit();
660                 rtw_ndev_notifier_unregister();
661                 DBG_871X("%s: register driver failed!!(%d)\n", __func__, ret);
662                 goto exit;
663         }
664
665         goto exit;
666
667 exit:
668         DBG_871X_LEVEL(_drv_always_, "module init ret =%d\n", ret);
669         return ret;
670 }
671
672 static void __exit rtw_drv_halt(void)
673 {
674         DBG_871X_LEVEL(_drv_always_, "module exit start\n");
675
676         sdio_drvpriv.drv_registered = false;
677
678         sdio_unregister_driver(&sdio_drvpriv.r871xs_drv);
679
680         rtw_drv_proc_deinit();
681         rtw_ndev_notifier_unregister();
682
683         DBG_871X_LEVEL(_drv_always_, "module exit success\n");
684
685         rtw_mstat_dump(RTW_DBGDUMP);
686 }
687
688
689 module_init(rtw_drv_entry);
690 module_exit(rtw_drv_halt);