98d873c6faabca992364e4cd50131708e1c0056c
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rtl8723bs / os_dep / linux / 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  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17  *
18  *
19  ******************************************************************************/
20 #define _HCI_INTF_C_
21
22 #include <drv_types.h>
23 #include <platform_ops.h>
24
25 #ifndef CONFIG_SDIO_HCI
26 #error "CONFIG_SDIO_HCI shall be on!\n"
27 #endif
28
29 #ifndef dev_to_sdio_func
30 #define dev_to_sdio_func(d)     container_of(d, struct sdio_func, dev)
31 #endif
32
33 #ifdef CONFIG_WOWLAN
34 static struct mmc_host *mmc_host = NULL;
35 #endif
36
37 static const struct sdio_device_id sdio_ids[] =
38 {
39 #ifdef CONFIG_RTL8723A
40         { SDIO_DEVICE(0x024c, 0x8723),.driver_data = RTL8723A},
41 #endif //CONFIG_RTL8723A
42 #ifdef CONFIG_RTL8723B
43         { SDIO_DEVICE(0x024c, 0xB723),.driver_data = RTL8723B},
44 #endif
45 #ifdef CONFIG_RTL8188E
46         { SDIO_DEVICE(0x024c, 0x8179),.driver_data = RTL8188E},
47 #endif //CONFIG_RTL8188E
48 #ifdef CONFIG_RTL8821A
49         { SDIO_DEVICE(0x024c, 0x8821),.driver_data = RTL8821},
50 #endif //CONFIG_RTL8188E
51
52 #if defined(RTW_ENABLE_WIFI_CONTROL_FUNC) /* temporarily add this to accept all sdio wlan id */
53         { SDIO_DEVICE_CLASS(SDIO_CLASS_WLAN) },
54 #endif
55 //      { /* end: all zeroes */                         },
56 };
57
58 static int rtw_drv_init(struct sdio_func *func, const struct sdio_device_id *id);
59 static void rtw_dev_remove(struct sdio_func *func);
60 static int rtw_sdio_resume(struct device *dev);
61 static int rtw_sdio_suspend(struct device *dev);
62
63 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) 
64 static const struct dev_pm_ops rtw_sdio_pm_ops = {
65         .suspend        = rtw_sdio_suspend,
66         .resume = rtw_sdio_resume,
67 };
68 #endif
69         
70 struct sdio_drv_priv {
71         struct sdio_driver r871xs_drv;
72         int drv_registered;
73 };
74
75 static struct sdio_drv_priv sdio_drvpriv = {
76         .r871xs_drv.probe = rtw_drv_init,
77         .r871xs_drv.remove = rtw_dev_remove,
78         .r871xs_drv.name = (char*)DRV_NAME,
79         .r871xs_drv.id_table = sdio_ids,
80         #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)) 
81         .r871xs_drv.drv = {
82                 .pm = &rtw_sdio_pm_ops,
83         }
84         #endif
85 };
86
87 static void sd_sync_int_hdl(struct sdio_func *func)
88 {
89         struct dvobj_priv *psdpriv;
90
91
92         psdpriv = sdio_get_drvdata(func);
93
94         if (!psdpriv->if1) {
95                 DBG_871X("%s if1 == NULL\n", __func__);
96                 return;
97         }
98
99         rtw_sdio_set_irq_thd(psdpriv, current);
100         sd_int_hdl(psdpriv->if1);
101         rtw_sdio_set_irq_thd(psdpriv, NULL);
102 }
103
104 int sdio_alloc_irq(struct dvobj_priv *dvobj)
105 {
106         PSDIO_DATA psdio_data;
107         struct sdio_func *func;
108         int err;
109
110         psdio_data = &dvobj->intf_data;
111         func = psdio_data->func;
112
113         sdio_claim_host(func);
114
115         err = sdio_claim_irq(func, &sd_sync_int_hdl);
116         if (err)
117         {
118                 dvobj->drv_dbg.dbg_sdio_alloc_irq_error_cnt++;
119                 printk(KERN_CRIT "%s: sdio_claim_irq FAIL(%d)!\n", __func__, err);
120         }
121         else
122         {
123                 dvobj->drv_dbg.dbg_sdio_alloc_irq_cnt++;
124                 dvobj->irq_alloc = 1;
125         }
126
127         sdio_release_host(func);
128
129         return err?_FAIL:_SUCCESS;
130 }
131
132 void sdio_free_irq(struct dvobj_priv *dvobj)
133 {
134     PSDIO_DATA psdio_data;
135     struct sdio_func *func;
136     int err;
137
138     if (dvobj->irq_alloc) {
139         psdio_data = &dvobj->intf_data;
140         func = psdio_data->func;
141
142         if (func) {
143             sdio_claim_host(func);
144             err = sdio_release_irq(func);
145             if (err)
146             {
147                                 dvobj->drv_dbg.dbg_sdio_free_irq_error_cnt++;
148                                 DBG_871X_LEVEL(_drv_err_,"%s: sdio_release_irq FAIL(%d)!\n", __func__, err);
149             }
150             else
151                 dvobj->drv_dbg.dbg_sdio_free_irq_cnt++;
152             sdio_release_host(func);
153         }
154         dvobj->irq_alloc = 0;
155     }
156 }
157
158 #ifdef CONFIG_GPIO_WAKEUP
159 extern unsigned int oob_irq;
160 static irqreturn_t gpio_hostwakeup_irq_thread(int irq, void *data)
161 {
162         PADAPTER padapter = (PADAPTER)data;
163         DBG_871X_LEVEL(_drv_always_, "gpio_hostwakeup_irq_thread\n");
164         /* Disable interrupt before calling handler */
165         //disable_irq_nosync(oob_irq);
166         rtw_lock_suspend_timeout(HZ/2);
167 #ifdef CONFIG_PLATFORM_ARM_SUN6I
168         return 0;
169 #else
170         return IRQ_HANDLED;
171 #endif
172 }
173
174 static u8 gpio_hostwakeup_alloc_irq(PADAPTER padapter)
175 {
176         int err;
177         if (oob_irq == 0) {
178                 DBG_871X("oob_irq ZERO!\n");
179                 return _FAIL;
180         }
181         /* dont set it IRQF_TRIGGER_LOW, or wowlan */
182         /* power is high after suspend */
183         /* and failing can prevent can not sleep issue if */
184         /* wifi gpio12 pin is not linked with CPU */
185         err = request_threaded_irq(oob_irq, gpio_hostwakeup_irq_thread, NULL,
186                 //IRQF_TRIGGER_LOW | IRQF_ONESHOT,
187                 IRQF_TRIGGER_FALLING,
188                 "rtw_wifi_gpio_wakeup", padapter);
189         if (err < 0) {
190                 DBG_871X("Oops: can't allocate gpio irq %d err:%d\n", oob_irq, err);
191                 return _FALSE;
192         } else {
193                 DBG_871X("allocate gpio irq %d ok\n", oob_irq);
194         }
195         
196 #ifndef CONFIG_PLATFORM_ARM_SUN8I       
197         enable_irq_wake(oob_irq);
198 #endif
199         return _SUCCESS;
200 }
201
202 static void gpio_hostwakeup_free_irq(PADAPTER padapter)
203 {
204         if (oob_irq == 0)
205                 return;
206                 
207 #ifndef CONFIG_PLATFORM_ARM_SUN8I
208         disable_irq_wake(oob_irq);
209 #endif
210         free_irq(oob_irq, padapter);
211 }
212 #endif
213
214 static u32 sdio_init(struct dvobj_priv *dvobj)
215 {
216         PSDIO_DATA psdio_data;
217         struct sdio_func *func;
218         int err;
219
220 _func_enter_;
221
222         psdio_data = &dvobj->intf_data;
223         func = psdio_data->func;
224
225         //3 1. init SDIO bus
226         sdio_claim_host(func);
227
228         err = sdio_enable_func(func);
229         if (err) {
230                 dvobj->drv_dbg.dbg_sdio_init_error_cnt++;
231                 DBG_8192C(KERN_CRIT "%s: sdio_enable_func FAIL(%d)!\n", __func__, err);
232                 goto release;
233         }
234
235         err = sdio_set_block_size(func, 512);
236         if (err) {
237                 dvobj->drv_dbg.dbg_sdio_init_error_cnt++;
238                 DBG_8192C(KERN_CRIT "%s: sdio_set_block_size FAIL(%d)!\n", __func__, err);
239                 goto release;
240         }
241         psdio_data->block_transfer_len = 512;
242         psdio_data->tx_block_mode = 1;
243         psdio_data->rx_block_mode = 1;
244
245 release:
246         sdio_release_host(func);
247
248 exit:
249 _func_exit_;
250
251         if (err) return _FAIL;
252         return _SUCCESS;
253 }
254
255 static void sdio_deinit(struct dvobj_priv *dvobj)
256 {
257         struct sdio_func *func;
258         int err;
259
260
261         RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("+sdio_deinit\n"));
262
263         func = dvobj->intf_data.func;
264
265         if (func) {
266                 sdio_claim_host(func);
267                 err = sdio_disable_func(func);
268                 if (err)
269                 {
270                         dvobj->drv_dbg.dbg_sdio_deinit_error_cnt++;
271                         DBG_8192C(KERN_ERR "%s: sdio_disable_func(%d)\n", __func__, err);
272                 }
273
274                 if (dvobj->irq_alloc) {
275                         err = sdio_release_irq(func);
276                         if (err)
277                         {
278                                 dvobj->drv_dbg.dbg_sdio_free_irq_error_cnt++;
279                                 DBG_8192C(KERN_ERR "%s: sdio_release_irq(%d)\n", __func__, err);
280                         }
281                         else
282                                 dvobj->drv_dbg.dbg_sdio_free_irq_cnt++;
283                 }
284
285                 sdio_release_host(func);
286         }
287 }
288 static struct dvobj_priv *sdio_dvobj_init(struct sdio_func *func)
289 {
290         int status = _FAIL;
291         struct dvobj_priv *dvobj = NULL;
292         PSDIO_DATA psdio;
293 _func_enter_;
294
295         if((dvobj = devobj_init()) == NULL) {
296                 goto exit;
297         }
298
299         sdio_set_drvdata(func, dvobj);
300
301         psdio = &dvobj->intf_data;
302         psdio->func = func;
303
304         if (sdio_init(dvobj) != _SUCCESS) {
305                 RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("%s: initialize SDIO Failed!\n", __FUNCTION__));
306                 goto free_dvobj;
307         }
308         rtw_reset_continual_io_error(dvobj);
309         status = _SUCCESS;
310
311 free_dvobj:
312         if (status != _SUCCESS && dvobj) {
313                 sdio_set_drvdata(func, NULL);
314                 
315                 devobj_deinit(dvobj);
316                 
317                 dvobj = NULL;
318         }
319 exit:
320 _func_exit_;
321         return dvobj;
322 }
323
324 static void sdio_dvobj_deinit(struct sdio_func *func)
325 {
326         struct dvobj_priv *dvobj = sdio_get_drvdata(func);
327 _func_enter_;
328
329         sdio_set_drvdata(func, NULL);
330         if (dvobj) {
331                 sdio_deinit(dvobj);
332                 devobj_deinit(dvobj);
333         }
334
335 _func_exit_;
336         return;
337 }
338 static void rtw_decide_chip_type_by_device_id(PADAPTER padapter, const struct sdio_device_id  *pdid)
339 {
340         padapter->chip_type = pdid->driver_data;
341
342 #if defined(CONFIG_RTL8723A)
343         if( padapter->chip_type == RTL8723A){
344                 padapter->HardwareType = HARDWARE_TYPE_RTL8723AS;
345                 DBG_871X("CHIP TYPE: RTL8723A\n");
346         }
347 #endif
348
349 #if defined(CONFIG_RTL8188E)
350         if(padapter->chip_type == RTL8188E){
351                 padapter->HardwareType = HARDWARE_TYPE_RTL8188ES;
352                 DBG_871X("CHIP TYPE: RTL8188E\n");
353         }
354 #endif
355
356 #if defined(CONFIG_RTL8723B)
357         padapter->chip_type = RTL8723B;
358         padapter->HardwareType = HARDWARE_TYPE_RTL8723BS;
359 #endif
360
361 #if defined(CONFIG_RTL8821A)
362         if (padapter->chip_type == RTL8821) {
363                 padapter->HardwareType = HARDWARE_TYPE_RTL8821S;
364                 DBG_871X("CHIP TYPE: RTL8821A\n");
365         }
366 #endif
367 }
368
369 void rtw_set_hal_ops(PADAPTER padapter)
370 {
371         //alloc memory for HAL DATA
372         rtw_hal_data_init(padapter);
373         
374 #if defined(CONFIG_RTL8723A)
375         if( padapter->chip_type == RTL8723A){
376                 rtl8723as_set_hal_ops(padapter);
377         }
378 #endif
379 #if defined(CONFIG_RTL8188E)
380         if(padapter->chip_type == RTL8188E){
381                 rtl8188es_set_hal_ops(padapter);
382         }
383 #endif
384 #if defined(CONFIG_RTL8723B)
385         if(padapter->chip_type == RTL8723B){
386                 rtl8723bs_set_hal_ops(padapter);
387         }
388 #endif
389 #if defined(CONFIG_RTL8821A)
390         if(padapter->chip_type == RTL8821){
391                 rtl8821as_set_hal_ops(padapter);
392         }
393 #endif
394 }
395
396 static void sd_intf_start(PADAPTER padapter)
397 {
398         if (padapter == NULL) {
399                 DBG_8192C(KERN_ERR "%s: padapter is NULL!\n", __func__);
400                 return;
401         }
402
403         // hal dep
404         rtw_hal_enable_interrupt(padapter);
405 }
406
407 static void sd_intf_stop(PADAPTER padapter)
408 {
409         if (padapter == NULL) {
410                 DBG_8192C(KERN_ERR "%s: padapter is NULL!\n", __func__);
411                 return;
412         }
413
414         // hal dep
415         rtw_hal_disable_interrupt(padapter);
416 }
417
418
419 #ifdef RTW_SUPPORT_PLATFORM_SHUTDOWN
420 PADAPTER g_test_adapter = NULL;
421 #endif // RTW_SUPPORT_PLATFORM_SHUTDOWN
422
423 _adapter *rtw_sdio_if1_init(struct dvobj_priv *dvobj, const struct sdio_device_id  *pdid)
424 {
425         int status = _FAIL;
426         struct net_device *pnetdev;
427         PADAPTER padapter = NULL;
428         
429         if ((padapter = (_adapter *)rtw_zvmalloc(sizeof(*padapter))) == NULL) {
430                 goto exit;
431         }
432
433 #ifdef RTW_SUPPORT_PLATFORM_SHUTDOWN
434         g_test_adapter = padapter;
435 #endif // RTW_SUPPORT_PLATFORM_SHUTDOWN
436         padapter->dvobj = dvobj;
437         dvobj->if1 = padapter;
438
439         padapter->bDriverStopped=_TRUE;
440
441         dvobj->padapters[dvobj->iface_nums++] = padapter;
442         padapter->iface_id = IFACE_ID0;
443
444 #if defined(CONFIG_CONCURRENT_MODE) || defined(CONFIG_DUALMAC_CONCURRENT)
445         //set adapter_type/iface type for primary padapter
446         padapter->isprimary = _TRUE;
447         padapter->adapter_type = PRIMARY_ADAPTER;       
448         #ifndef CONFIG_HWPORT_SWAP
449         padapter->iface_type = IFACE_PORT0;
450         #else
451         padapter->iface_type = IFACE_PORT1;
452         #endif
453 #endif
454
455         padapter->interface_type = RTW_SDIO;
456         rtw_decide_chip_type_by_device_id(padapter, pdid);
457         
458         //3 1. init network device data
459         pnetdev = rtw_init_netdev(padapter);
460         if (!pnetdev)
461                 goto free_adapter;
462         
463         SET_NETDEV_DEV(pnetdev, dvobj_to_dev(dvobj));
464
465         padapter = rtw_netdev_priv(pnetdev);
466
467 #ifdef CONFIG_IOCTL_CFG80211
468         rtw_wdev_alloc(padapter, dvobj_to_dev(dvobj));
469 #endif
470
471         //3 3. init driver special setting, interface, OS and hardware relative
472
473         //4 3.1 set hardware operation functions
474         rtw_set_hal_ops(padapter);
475
476
477         //3 5. initialize Chip version
478         padapter->intf_start = &sd_intf_start;
479         padapter->intf_stop = &sd_intf_stop;
480
481         padapter->intf_init = &sdio_init;
482         padapter->intf_deinit = &sdio_deinit;
483         padapter->intf_alloc_irq = &sdio_alloc_irq;
484         padapter->intf_free_irq = &sdio_free_irq;
485
486         if (rtw_init_io_priv(padapter, sdio_set_intf_ops) == _FAIL)
487         {
488                 RT_TRACE(_module_hci_intfs_c_, _drv_err_,
489                         ("rtw_drv_init: Can't init io_priv\n"));
490                 goto free_hal_data;
491         }
492
493         rtw_hal_read_chip_version(padapter);
494
495         rtw_hal_chip_configure(padapter);
496
497 #ifdef CONFIG_BT_COEXIST
498         rtw_btcoex_Initialize(padapter);
499 #endif // CONFIG_BT_COEXIST
500
501         //3 6. read efuse/eeprom data
502         rtw_hal_read_chip_info(padapter);
503
504         //3 7. init driver common data
505         if (rtw_init_drv_sw(padapter) == _FAIL) {
506                 RT_TRACE(_module_hci_intfs_c_, _drv_err_,
507                          ("rtw_drv_init: Initialize driver software resource Failed!\n"));
508                 goto free_hal_data;
509         }
510
511         //3 8. get WLan MAC address
512         // set mac addr
513         rtw_macaddr_cfg(padapter->eeprompriv.mac_addr);
514         rtw_init_wifidirect_addrs(padapter, padapter->eeprompriv.mac_addr, padapter->eeprompriv.mac_addr);
515
516         rtw_hal_disable_interrupt(padapter);
517
518         DBG_871X("bDriverStopped:%d, bSurpriseRemoved:%d, bup:%d, hw_init_completed:%d\n"
519                 ,padapter->bDriverStopped
520                 ,padapter->bSurpriseRemoved
521                 ,padapter->bup
522                 ,padapter->hw_init_completed
523         );
524         
525         status = _SUCCESS;
526         
527 free_hal_data:
528         if(status != _SUCCESS && padapter->HalData)
529                 rtw_mfree(padapter->HalData, sizeof(*(padapter->HalData)));
530
531 free_wdev:
532         if(status != _SUCCESS) {
533                 #ifdef CONFIG_IOCTL_CFG80211
534                 rtw_wdev_unregister(padapter->rtw_wdev);
535                 rtw_wdev_free(padapter->rtw_wdev);
536                 #endif
537         }
538
539 free_adapter:
540         if (status != _SUCCESS) {
541                 if (pnetdev)
542                         rtw_free_netdev(pnetdev);
543                 else
544                         rtw_vmfree((u8*)padapter, sizeof(*padapter));
545                 padapter = NULL;
546         }
547 exit:
548         return padapter;
549 }
550
551 static void rtw_sdio_if1_deinit(_adapter *if1)
552 {
553         struct net_device *pnetdev = if1->pnetdev;
554         struct mlme_priv *pmlmepriv= &if1->mlmepriv;
555
556         if(check_fwstate(pmlmepriv, _FW_LINKED))
557                 rtw_disassoc_cmd(if1, 0, _FALSE);
558
559 #ifdef CONFIG_AP_MODE
560         free_mlme_ap_info(if1);
561         #ifdef CONFIG_HOSTAPD_MLME
562         hostapd_mode_unload(if1);
563         #endif
564 #endif
565
566 #ifdef CONFIG_GPIO_WAKEUP
567 #ifdef CONFIG_PLATFORM_ARM_SUN6I 
568         sw_gpio_eint_set_enable(gpio_eint_wlan, 0);
569         sw_gpio_irq_free(eint_wlan_handle);
570 #else  
571         gpio_hostwakeup_free_irq(if1);
572 #endif
573 #endif
574
575         rtw_cancel_all_timer(if1);
576
577 #ifdef CONFIG_WOWLAN
578         adapter_to_pwrctl(if1)->wowlan_mode=_FALSE;
579         DBG_871X_LEVEL(_drv_always_, "%s wowlan_mode:%d\n", __func__, adapter_to_pwrctl(if1)->wowlan_mode);
580 #endif //CONFIG_WOWLAN
581
582         rtw_dev_unload(if1);
583         DBG_871X("+r871xu_dev_remove, hw_init_completed=%d\n", if1->hw_init_completed);
584         
585         rtw_handle_dualmac(if1, 0);
586
587 #ifdef CONFIG_IOCTL_CFG80211
588         if (if1->rtw_wdev) {
589                 rtw_wdev_free(if1->rtw_wdev);
590         }
591 #endif
592
593         rtw_free_drv_sw(if1);
594
595         if(pnetdev)
596                 rtw_free_netdev(pnetdev);
597
598 #ifdef CONFIG_PLATFORM_RTD2880B
599         DBG_871X("wlan link down\n");
600         rtd2885_wlan_netlink_sendMsg("linkdown", "8712");
601 #endif
602
603 #ifdef RTW_SUPPORT_PLATFORM_SHUTDOWN
604         g_test_adapter = NULL;
605 #endif // RTW_SUPPORT_PLATFORM_SHUTDOWN
606 }
607
608 /*
609  * drv_init() - a device potentially for us
610  *
611  * notes: drv_init() is called when the bus driver has located a card for us to support.
612  *        We accept the new device by returning 0.
613  */
614 static int rtw_drv_init(
615         struct sdio_func *func,
616         const struct sdio_device_id *id)
617 {
618         int status = _FAIL;
619         struct net_device *pnetdev;
620         PADAPTER if1 = NULL, if2 = NULL;
621         struct dvobj_priv *dvobj;
622
623         RT_TRACE(_module_hci_intfs_c_, _drv_info_,
624                 ("+rtw_drv_init: vendor=0x%04x device=0x%04x class=0x%02x\n",
625                 func->vendor, func->device, func->class));
626
627         if ((dvobj = sdio_dvobj_init(func)) == NULL) {
628                 RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("initialize device object priv Failed!\n"));
629                 goto exit;
630         }
631
632         if ((if1 = rtw_sdio_if1_init(dvobj, id)) == NULL) {
633                 DBG_871X("rtw_init_primary_adapter Failed!\n");
634                 goto free_dvobj;
635         }
636
637 #ifdef CONFIG_CONCURRENT_MODE
638         if ((if2 = rtw_drv_if2_init(if1, sdio_set_intf_ops)) == NULL) {
639                 goto free_if1;
640         }
641 #endif
642
643         //dev_alloc_name && register_netdev
644         if((status = rtw_drv_register_netdev(if1)) != _SUCCESS) {
645                 goto free_if2;
646         }
647
648 #ifdef CONFIG_HOSTAPD_MLME
649         hostapd_mode_init(if1);
650 #endif
651
652 #ifdef CONFIG_PLATFORM_RTD2880B
653         DBG_871X("wlan link up\n");
654         rtd2885_wlan_netlink_sendMsg("linkup", "8712");
655 #endif
656
657         if (sdio_alloc_irq(dvobj) != _SUCCESS)
658                 goto free_if2;
659
660 #ifdef  CONFIG_GPIO_WAKEUP
661 #ifdef CONFIG_PLATFORM_ARM_SUN6I
662         eint_wlan_handle = sw_gpio_irq_request(gpio_eint_wlan, TRIG_EDGE_NEGATIVE,(peint_handle)gpio_hostwakeup_irq_thread, NULL);
663         if (!eint_wlan_handle) {
664                DBG_871X( "%s: request irq failed\n",__func__);
665                return -1;
666   }
667 #else
668         gpio_hostwakeup_alloc_irq(if1);
669 #endif
670 #endif
671
672 #ifdef CONFIG_GLOBAL_UI_PID
673         if(ui_pid[1]!=0) {
674                 DBG_871X("ui_pid[1]:%d\n",ui_pid[1]);
675                 rtw_signal_process(ui_pid[1], SIGUSR2);
676         }
677 #endif
678
679         RT_TRACE(_module_hci_intfs_c_,_drv_err_,("-871x_drv - drv_init, success!\n"));
680
681         status = _SUCCESS;
682
683 free_if2:
684         if(status != _SUCCESS && if2) {
685                 #ifdef CONFIG_CONCURRENT_MODE
686                 rtw_drv_if2_stop(if2);
687                 rtw_drv_if2_free(if2);
688                 #endif
689         }
690 free_if1:
691         if (status != _SUCCESS && if1) {
692                 rtw_sdio_if1_deinit(if1);
693         }
694 free_dvobj:
695         if (status != _SUCCESS)
696                 sdio_dvobj_deinit(func);
697 exit:
698         return status == _SUCCESS?0:-ENODEV;
699 }
700
701 static void rtw_dev_remove(struct sdio_func *func)
702 {
703         struct dvobj_priv *dvobj = sdio_get_drvdata(func);
704         struct pwrctrl_priv *pwrctl = dvobj_to_pwrctl(dvobj);
705         PADAPTER padapter = dvobj->if1;
706
707 _func_enter_;
708
709         RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("+rtw_dev_remove\n"));
710
711         dvobj->processing_dev_remove = _TRUE;
712
713         rtw_unregister_netdevs(dvobj);
714
715         if (padapter->bSurpriseRemoved == _FALSE) {
716                 int err;
717
718                 /* test surprise remove */
719                 sdio_claim_host(func);
720                 sdio_readb(func, 0, &err);
721                 sdio_release_host(func);
722                 if (err == -ENOMEDIUM) {
723                         padapter->bSurpriseRemoved = _TRUE;
724                         DBG_871X(KERN_NOTICE "%s: device had been removed!\n", __func__);
725                 }
726         }
727
728 #if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_ANDROID_POWER)
729         rtw_unregister_early_suspend(pwrctl);
730 #endif
731
732         rtw_ps_deny(padapter, PS_DENY_DRV_REMOVE);
733
734         rtw_pm_set_ips(padapter, IPS_NONE);
735         rtw_pm_set_lps(padapter, PS_MODE_ACTIVE);
736
737         LeaveAllPowerSaveMode(padapter);
738
739 #ifdef CONFIG_CONCURRENT_MODE
740         rtw_drv_if2_stop(dvobj->if2);
741 #endif
742
743 #ifdef CONFIG_BT_COEXIST
744         rtw_btcoex_HaltNotify(padapter);
745 #endif
746
747         rtw_sdio_if1_deinit(padapter);
748
749 #ifdef CONFIG_CONCURRENT_MODE
750         rtw_drv_if2_free(dvobj->if2);
751 #endif
752
753         sdio_dvobj_deinit(func);
754
755         RT_TRACE(_module_hci_intfs_c_, _drv_notice_, ("-rtw_dev_remove\n"));
756
757 _func_exit_;
758 }
759 extern int pm_netdev_open(struct net_device *pnetdev,u8 bnormal);
760 extern int pm_netdev_close(struct net_device *pnetdev,u8 bnormal);
761
762 static int rtw_sdio_suspend(struct device *dev)
763 {
764         struct sdio_func *func =dev_to_sdio_func(dev);
765         struct dvobj_priv *psdpriv = sdio_get_drvdata(func);
766         struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(psdpriv);
767         _adapter *padapter = psdpriv->if1;
768         struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
769         int ret = 0;
770         u8 ch, bw, offset;
771
772         if(padapter->bDriverStopped == _TRUE)
773         {
774                 DBG_871X("%s bDriverStopped = %d\n", __FUNCTION__, padapter->bDriverStopped);
775                 goto exit;
776         }
777
778         if (pwrpriv->bInSuspend == _TRUE)
779         {
780                 DBG_871X("%s bInSuspend = %d\n", __FUNCTION__, pwrpriv->bInSuspend);
781                 pdbgpriv->dbg_suspend_error_cnt++;
782                 goto exit;
783         }
784
785         ret = rtw_suspend_common(padapter);             
786
787 exit:
788 #ifdef CONFIG_RTW_SDIO_PM_KEEP_POWER 
789 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34))
790         //Android 4.0 don't support WIFI close power
791         //or power down or clock will close after wifi resume,
792         //this is sprd's bug in Android 4.0, but sprd don't
793         //want to fix it.
794         //we have test power under 8723as, power consumption is ok
795         if (func) {
796                 mmc_pm_flag_t pm_flag = 0;
797                 pm_flag = sdio_get_host_pm_caps(func);
798                 DBG_871X("cmd: %s: suspend: PM flag = 0x%x\n", sdio_func_id(func), pm_flag);
799                 if (!(pm_flag & MMC_PM_KEEP_POWER)) {
800                         DBG_871X("%s: cannot remain alive while host is suspended\n", sdio_func_id(func));
801                         pdbgpriv->dbg_suspend_error_cnt++;
802                         return -ENOSYS;
803                 } else {
804                         DBG_871X("cmd: suspend with MMC_PM_KEEP_POWER\n");
805                         sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
806                 }
807         }
808 #endif  
809 #endif
810         return ret;
811 }
812 int rtw_resume_process(_adapter *padapter)
813 {
814         struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
815         struct dvobj_priv *psdpriv = padapter->dvobj;
816         struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
817                 
818         if (pwrpriv->bInSuspend == _FALSE)
819         {
820                 pdbgpriv->dbg_resume_error_cnt++;
821                 DBG_871X("%s bInSuspend = %d\n", __FUNCTION__, pwrpriv->bInSuspend);
822                 return -1;
823         }
824         
825         return rtw_resume_common(padapter);
826 }
827
828 static int rtw_sdio_resume(struct device *dev)
829 {
830         struct sdio_func *func =dev_to_sdio_func(dev);
831         struct dvobj_priv *psdpriv = sdio_get_drvdata(func);
832         struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(psdpriv);
833         _adapter *padapter = psdpriv->if1;
834         struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
835         int ret = 0;
836         struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
837
838         DBG_871X("==> %s (%s:%d)\n",__FUNCTION__, current->comm, current->pid);
839
840         pdbgpriv->dbg_resume_cnt++;
841
842         if(pwrpriv->bInternalAutoSuspend)
843         {
844                 ret = rtw_resume_process(padapter);
845         }
846         else
847         {
848                 if(pwrpriv->wowlan_mode || pwrpriv->wowlan_ap_mode)
849                 {
850                         rtw_resume_lock_suspend();                      
851                         ret = rtw_resume_process(padapter);
852                         rtw_resume_unlock_suspend();
853                 }
854                 else
855                 {
856 #ifdef CONFIG_RESUME_IN_WORKQUEUE
857                         rtw_resume_in_workqueue(pwrpriv);
858 #else                   
859                         if (rtw_is_earlysuspend_registered(pwrpriv))
860                         {
861                                 /* jeff: bypass resume here, do in late_resume */
862                                 rtw_set_do_late_resume(pwrpriv, _TRUE);
863                         }       
864                         else
865                         {
866                                 rtw_resume_lock_suspend();                      
867                                 ret = rtw_resume_process(padapter);
868                                 rtw_resume_unlock_suspend();
869                         }
870 #endif
871                 }
872         }
873         pmlmeext->last_scan_time = rtw_get_current_time();
874         DBG_871X("<========  %s return %d\n", __FUNCTION__, ret);
875         return ret;
876
877 }
878
879 static int rtw_drv_entry(void)
880 {
881         int ret = 0;
882
883         DBG_871X_LEVEL(_drv_always_, "module init start\n");
884         dump_drv_version(RTW_DBGDUMP);
885 #ifdef BTCOEXVERSION
886         DBG_871X_LEVEL(_drv_always_, DRV_NAME" BT-Coex version = %s\n", BTCOEXVERSION);
887 #endif // BTCOEXVERSION
888
889         ret = platform_wifi_power_on();
890         if (ret)
891         {
892                 DBG_871X("%s: power on failed!!(%d)\n", __FUNCTION__, ret);
893                 ret = -1;
894                 goto exit;
895         }
896
897         sdio_drvpriv.drv_registered = _TRUE;
898         rtw_suspend_lock_init();
899         rtw_drv_proc_init();
900         rtw_ndev_notifier_register();
901
902         ret = sdio_register_driver(&sdio_drvpriv.r871xs_drv);
903         if (ret != 0)
904         {
905                 sdio_drvpriv.drv_registered = _FALSE;
906                 rtw_suspend_lock_uninit();
907                 rtw_drv_proc_deinit();
908                 rtw_ndev_notifier_unregister();
909                 DBG_871X("%s: register driver failed!!(%d)\n", __FUNCTION__, ret);
910                 goto poweroff;
911         }
912
913         rtw_android_wifictrl_func_add();
914
915         goto exit;
916
917 poweroff:
918         platform_wifi_power_off();
919
920 exit:
921         DBG_871X_LEVEL(_drv_always_, "module init ret=%d\n", ret);
922         return ret;
923 }
924
925 static void rtw_drv_halt(void)
926 {
927         DBG_871X_LEVEL(_drv_always_, "module exit start\n");
928
929         sdio_drvpriv.drv_registered = _FALSE;
930
931         sdio_unregister_driver(&sdio_drvpriv.r871xs_drv);
932
933         rtw_android_wifictrl_func_del();
934
935         platform_wifi_power_off();
936
937         rtw_suspend_lock_uninit();
938         rtw_drv_proc_deinit();
939         rtw_ndev_notifier_unregister();
940
941         DBG_871X_LEVEL(_drv_always_, "module exit success\n");
942
943         rtw_mstat_dump(RTW_DBGDUMP);
944 }
945
946 #include "wifi_version.h"
947
948 extern int rockchip_wifi_power(int on);
949 extern int rockchip_wifi_set_carddetect(int val);
950
951 int rockchip_wifi_init_module_rtkwifi(void)
952 {
953     printk("\n");
954     printk("=======================================================\n");
955     printk("==== Launching Wi-Fi driver! (Powered by Rockchip) ====\n");
956     printk("=======================================================\n");
957     printk("Realtek 8723BS SDIO WiFi driver (Powered by Rockchip,Ver %s) init.\n", RTL8723BS_DRV_VERSION);
958
959     rockchip_wifi_power(1);
960     rockchip_wifi_set_carddetect(1);    
961     return rtw_drv_entry();
962 }
963
964 void rockchip_wifi_exit_module_rtkwifi(void)
965 {
966     printk("\n");
967     printk("=======================================================\n");
968     printk("==== Dislaunching Wi-Fi driver! (Powered by Rockchip) ====\n");
969     printk("=======================================================\n");
970     printk("Realtek 8723BS SDIO WiFi driver (Powered by Rockchip,Ver %s) init.\n", RTL8723BS_DRV_VERSION);
971
972     rtw_drv_halt();
973
974     rockchip_wifi_set_carddetect(0);
975     rockchip_wifi_power(0);
976 }
977
978 EXPORT_SYMBOL(rockchip_wifi_init_module_rtkwifi);
979 EXPORT_SYMBOL(rockchip_wifi_exit_module_rtkwifi);
980 //module_init(rtw_drv_entry);
981 //module_exit(rtw_drv_halt);
982