Merge remote-tracking branch 'aosp/android-3.0' into develop-3.0-jb
[firefly-linux-kernel-4.4.55.git] / net / rfkill / rfkill-rk.c
1 /*
2  * Copyright (C) 2012 ROCKCHIP, Inc.
3  *
4  * This software is licensed under the terms of the GNU General Public
5  * License version 2, as published by the Free Software Foundation, and
6  * may be copied, distributed, and modified under those terms.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  */
14 /* Rock-chips rfkill driver for bluetooth
15  *
16  * BT Ô´ÂëÓÉÔ­À´µÄarch/arm/mach-rkxx/board-xxx-rfkill.cÒÆÖÁ´Ë´¦
17  * GPIOµÄÅäÖÃÔÚ arch/arm/mach-rkxx/board-rkxx-sdk.c µÄrfkill_rk_platdata½á¹¹ÌåÖÐ
18  *
19  * Çë¸ù¾Ýʵ¼ÊÇé¿öÅäÖúÃÀ¶ÑÀµÄ¸÷¸öGPIOÒý½Å£¬Òý½ÅÅäÖÃ˵Ã÷ÈçÏÂ:
20     .xxxx_gpio   = {
21       .io         = -1,      // GPIOÖµ£¬ -1 ±íʾÎ޴˹¦ÄÜ
22       .enable     = -1,      // Ê¹ÄÜ, GPIO_HIGH - ¸ßʹÄÜ£¬ GPIO_LOW - µÍʹÄÜ
23       .iomux      = {
24           .name    = NULL,   // IOMUXÃû³Æ£¬NULL ±íʾËüÊǵ¥¹¦ÄÜ£¬²»ÐèÒªmux
25           .fgpio   = -1,     // ÅäÖÃΪGPIOʱ£¬Ó¦ÉèÖõÄÖµ
26           .fmux   = -1,      // ÅäÖÃΪ¸´Óù¦ÄÜʱ£¬Ó¦ÉèÖõÄÖµ
27       },
28     },
29 */
30
31 #include <linux/kernel.h>
32 #include <linux/platform_device.h>
33 #include <linux/module.h>
34 #include <linux/rfkill.h>
35 #include <linux/init.h>
36 #include <linux/slab.h>
37 #include <asm/gpio.h>
38 #include <mach/iomux.h>
39 #include <linux/delay.h>
40 #include <linux/rfkill-rk.h>
41 #include <linux/wakelock.h>
42 #include <linux/interrupt.h>
43 #include <asm/irq.h>
44 #include <linux/suspend.h>
45
46 #if 0
47 #define DBG(x...)   printk(KERN_INFO "[BT_RFKILL]: "x)
48 #else
49 #define DBG(x...)
50 #endif
51
52 #define LOG(x...)   printk(KERN_INFO "[BT_RFKILL]: "x)
53
54 #define BT_WAKEUP_TIMEOUT           3000
55 #define BT_IRQ_WAKELOCK_TIMEOUT     10*1000
56
57 #define BT_BLOCKED     true
58 #define BT_UNBLOCK     false
59 #define BT_SLEEP       true
60 #define BT_WAKEUP      false
61
62 enum {
63     IOMUX_FNORMAL=0,
64     IOMUX_FGPIO,
65     IOMUX_FMUX,
66 };
67
68 #ifdef CONFIG_ARCH_RK29
69     #define rk_mux_api_set(name,mode)      rk29_mux_api_set(name,mode)
70 #elif defined (CONFIG_ARCH_RK30)
71     #define rk_mux_api_set(name,mode)      rk30_mux_api_set(name,mode)
72 #else
73     #define rk_mux_api_set(name,mode)
74 #endif
75
76 // RK29+BCM4329, ÆäwifiÓëbtµÄpower¿ØÖƽÅÊǽÓÔÚÒ»ÆðµÄ
77 // ÔÚ¸øbtϵçʱ£¬ÐèÒªÏÈÅжÏwifi״̬
78 #if defined(CONFIG_BCM4329)
79 #define WIFI_BT_POWER_TOGGLE    1
80 extern int rk29sdk_bt_power_state;
81 extern int rk29sdk_wifi_power_state;
82 #else
83 #define WIFI_BT_POWER_TOGGLE    0
84 #endif
85
86 struct rfkill_rk_data {
87     // Ö¸ÏòboardÖж¨ÒåµÄplatform data
88         struct rfkill_rk_platform_data  *pdata;
89
90     // Ö¸ÏòrfkillÉ豸£¬ËüÓÉrfkill_alloc´´½¨
91         struct rfkill                           *rfkill_dev;
92
93     // ÔÚIRQÖжϺ¯ÊýÖÐʹÓã¬È·±£ÔÚBT»½ÐÑAPºó£¬²»»áÁ¢¼´
94     // µ÷ÓÃsuspend½øÈë˯Ãß
95     struct wake_lock            bt_irq_wl;
96     
97     // ÔÚ»½ÐÑBTºó£¬Í¨¹ý¸Ãdelay workÑÓʱһ¶Îʱ¼äºó½øÈë˯Ãß
98     // Èç¹ûdelay work»¹Î´Ö´ÐоÍÓÖÀ´Ò»´Î BT wake£¬Ôò»áÏÈcancel
99     // ÒÑÓеĠdelay work£¬²¢ÖØмÆʱ¡£
100     struct delayed_work         bt_sleep_delay_work;
101 };
102
103 static struct rfkill_rk_data *g_rfkill = NULL;
104
105 static const char bt_name[] = 
106 #if defined (CONFIG_BCM4330)
107     #if defined (CONFIG_BT_MODULE_NH660)
108         "nh660"
109     #else
110         "bcm4330"
111     #endif
112 #elif defined (CONFIG_RK903)
113     #if defined(CONFIG_RKWIFI_26M)
114         "rk903_26M"
115     #else
116         "rk903"
117     #endif
118 #elif defined(CONFIG_BCM4329)
119         "bcm4329"
120 #elif defined(CONFIG_MV8787)
121         "mv8787"
122 #else
123         "bt_default"
124 #endif
125 ;
126
127 /*
128  *  rfkill_rk_wake_host_irq - BT_WAKE_HOST Öжϻص÷º¯Êý
129  *      ÉêÇëÒ»¸öwakelock£¬ÒÔÈ·±£´Ë´Î»½ÐѲ»»áÂíÉϽáÊø
130  */
131 static irqreturn_t rfkill_rk_wake_host_irq(int irq, void *dev)
132 {
133     struct rfkill_rk_data *rfkill = dev;
134     LOG("BT_WAKE_HOST IRQ fired\n");
135     
136     DBG("BT IRQ wakeup, request %dms wakelock\n", BT_IRQ_WAKELOCK_TIMEOUT);
137
138     wake_lock_timeout(&rfkill->bt_irq_wl, 
139                     msecs_to_jiffies(BT_IRQ_WAKELOCK_TIMEOUT));
140     
141         return IRQ_HANDLED;
142 }
143
144 /*
145  * rfkill_rk_setup_gpio - ÉèÖÃGPIO
146  *      gpio    - ÒªÉèÖõÄGPIO
147  *      mux     - iomux Ê²Ã´¹¦ÄÜ
148  *      prefix,name - ×é³É¸ÃIOµÄÃû³Æ
149  * ·µ»ØÖµ
150  *      ·µ»ØÖµÓë gpio_request Ïàͬ
151  */
152 static int rfkill_rk_setup_gpio(struct rfkill_rk_gpio* gpio, int mux, const char* prefix, const char* name)
153 {
154         if (gpio_is_valid(gpio->io)) {
155         int ret=0;
156         sprintf(gpio->name, "%s_%s", prefix, name);
157                 ret = gpio_request(gpio->io, gpio->name);
158                 if (ret) {
159                         LOG("Failed to get %s gpio.\n", gpio->name);
160                         return -1;
161                 }
162         if (gpio->iomux.name)
163         {
164             if (mux==1)
165                 rk_mux_api_set(gpio->iomux.name, gpio->iomux.fgpio);
166             else if (mux==2)
167                 rk_mux_api_set(gpio->iomux.name, gpio->iomux.fmux);
168             else
169                 ;// do nothing
170         }
171         }
172
173     return 0;
174 }
175
176 // ÉèÖàBT_WAKE_HOST IRQ
177 static int rfkill_rk_setup_wake_irq(struct rfkill_rk_data* rfkill)
178 {
179     int ret=0;
180     struct rfkill_rk_irq* irq = &(rfkill->pdata->wake_host_irq);
181     
182     ret = rfkill_rk_setup_gpio(&irq->gpio, IOMUX_FGPIO, rfkill->pdata->name, "wake_host");
183     if (ret) goto fail1;
184
185     if (gpio_is_valid(irq->gpio.io))
186     {
187         ret = gpio_pull_updown(irq->gpio.io, (irq->gpio.enable==GPIO_LOW)?GPIOPullUp:GPIOPullDown);
188         if (ret) goto fail2;
189         LOG("Request irq for bt wakeup host\n");
190         irq->irq = gpio_to_irq(irq->gpio.io);
191         sprintf(irq->name, "%s_irq", irq->gpio.name);
192         ret = request_irq(irq->irq,
193                     rfkill_rk_wake_host_irq,
194                     (irq->gpio.enable==GPIO_LOW)?IRQF_TRIGGER_FALLING:IRQF_TRIGGER_RISING,
195                     irq->name,
196                     rfkill);
197         if (ret) goto fail2;
198         LOG("** disable irq\n");
199         disable_irq(irq->irq);
200         ret = enable_irq_wake(irq->irq);
201         if (ret) goto fail3;
202     }
203
204     return ret;
205
206 fail3:
207     free_irq(irq->gpio.io, rfkill);
208 fail2:
209     gpio_free(irq->gpio.io);
210 fail1:
211     return ret;
212 }
213
214 static inline void rfkill_rk_sleep_bt_internal(struct rfkill_rk_data *rfkill, bool sleep)
215 {
216     struct rfkill_rk_gpio *wake = &rfkill->pdata->wake_gpio;
217     
218     DBG("*** bt sleep: %d ***\n", sleep);
219     gpio_direction_output(wake->io, sleep?!wake->enable:wake->enable);
220 }
221
222 static void rfkill_rk_delay_sleep_bt(struct work_struct *work)
223 {
224     struct rfkill_rk_data *rfkill = NULL;
225     DBG("Enter %s\n",__FUNCTION__);
226
227     rfkill = container_of(work, struct rfkill_rk_data, bt_sleep_delay_work.work);
228
229     rfkill_rk_sleep_bt_internal(rfkill, BT_SLEEP);
230 }
231
232 /*
233  *  rfkill_rk_sleep_bt - Sleep or Wakeup BT
234  *      1 ÔÚ¸øBTÉϵçʱºò£¬µ÷Óøú¯Êý»½ÐÑBT
235  *      2 ÔÚsuspendÇý¶¯Ê±ºò£¬µ÷Óøú¯Êý˯ÃßBT
236  *      3 ÔÚHCIÇý¶¯ÖУ¬µ±ÓÐÃüÁî·¢Ë͸øBTʱ£¬µ÷Óøú¯Êý»½ÐÑBT
237  *
238  *  ¶ÔÀ¶ÑÀµÄÖ¸Áî·¢ËÍÊÇ·¢ÉúÔÚÀ¶ÑÀÉϵçÖ®ºó£¬Òò´Ë1Óë3²»»áͬʱµ÷Óøú¯Êý
239  *  À¶ÑÀÖ¸Áî·¢ËÍÓÉÓû§²ã·¢Æð£¬2Óë3²»»áͬʱµ÷Óøú¯Êý
240  */
241 void rfkill_rk_sleep_bt(bool sleep)
242 {
243     struct rfkill_rk_data *rfkill = g_rfkill;
244     struct rfkill_rk_gpio *wake;
245     bool ret;
246     DBG("Enter %s\n",__FUNCTION__);
247     
248     if (rfkill==NULL)
249     {
250         LOG("*** RFKILL is empty???\n");
251         return;
252     }
253
254     wake = &rfkill->pdata->wake_gpio;
255     if (!gpio_is_valid(wake->io))
256     {
257         DBG("*** Not support bt wakeup and sleep\n");
258         return;
259     }
260
261     // È¡Ïûdelay work£¬Èç¹ûwork´¦ÓÚpendding£¬ÔòÁ¢¼´È¡Ïû
262     // Èç¹ûwork´¦ÓÚrunning£¬ÔòµÈ´ýÖ±µ½¸Ãwork½áÊø
263     ret = cancel_delayed_work_sync(&rfkill->bt_sleep_delay_work);
264
265     rfkill_rk_sleep_bt_internal(rfkill, sleep);
266
267 #ifdef CONFIG_BT_AUTOSLEEP
268     if (sleep==BT_WAKEUP)
269     {
270         // ÖØÐÂÉèÖÃdelay work
271         schedule_delayed_work(&rfkill->bt_sleep_delay_work, 
272                             msecs_to_jiffies(BT_WAKEUP_TIMEOUT));
273     }
274 #endif
275 }
276 EXPORT_SYMBOL(rfkill_rk_sleep_bt);
277
278 static int rfkill_rk_set_power(void *data, bool blocked)
279 {
280         struct rfkill_rk_data *rfkill = data;
281     struct rfkill_rk_gpio *poweron = &rfkill->pdata->poweron_gpio;
282     struct rfkill_rk_gpio *reset = &rfkill->pdata->reset_gpio;
283
284     DBG("Enter %s\n", __func__);
285
286     DBG("Set blocked:%d\n", blocked);
287
288         if (false == blocked) { 
289         rfkill_rk_sleep_bt(BT_WAKEUP); // ensure bt is wakeup
290         
291                 if (gpio_is_valid(poweron->io))
292         {
293                         gpio_direction_output(poweron->io, poweron->enable);
294             msleep(20);
295         }
296                 if (gpio_is_valid(reset->io))
297         {
298                         gpio_direction_output(reset->io, reset->enable);
299             msleep(20);
300                         gpio_direction_output(reset->io, !reset->enable);
301             msleep(20);
302         }
303
304         LOG("bt turn on power\n");
305         } else {
306 #if WIFI_BT_POWER_TOGGLE
307                 if (!rk29sdk_wifi_power_state) {
308 #endif
309             if (gpio_is_valid(poweron->io))
310             {      
311                 gpio_direction_output(poweron->io, !poweron->enable);
312                 msleep(20);
313             }
314
315                 LOG("bt shut off power\n");
316 #if WIFI_BT_POWER_TOGGLE
317                 }else {
318                         LOG("bt shouldn't shut off power, wifi is using it!\n");
319                 }
320 #endif
321                 if (gpio_is_valid(reset->io))
322         {      
323                         gpio_direction_output(reset->io, reset->enable);/* bt reset active*/
324             msleep(20);
325         }
326         }
327
328 #if WIFI_BT_POWER_TOGGLE
329         rk29sdk_bt_power_state = !blocked;
330 #endif
331         return 0;
332 }
333
334 static int rfkill_rk_pm_prepare(struct device *dev)
335 {
336     struct rfkill_rk_data *rfkill = g_rfkill;
337     struct rfkill_rk_gpio* rts;
338     struct rfkill_rk_irq*  wake_host_irq;
339     DBG("Enter %s\n",__FUNCTION__);
340
341     if (!rfkill)
342         return 0;
343
344     rts = &rfkill->pdata->rts_gpio;
345     wake_host_irq = &rfkill->pdata->wake_host_irq;
346
347     //To prevent uart to receive bt data when suspended
348     if (gpio_is_valid(rts->io))
349     {
350         DBG("Disable UART_RTS\n");
351         if (rts->iomux.name)
352         {
353             rk_mux_api_set(rts->iomux.name, rts->iomux.fgpio);
354         }
355         gpio_direction_output(rts->io, !rts->enable);
356     }
357
358 #ifdef CONFIG_BT_AUTOSLEEP
359     // BT½øÈë˯Ãß״̬£¬²»½ÓÊÕÖ÷¿ØÊý¾Ý
360     rfkill_rk_sleep_bt(BT_SLEEP);
361 #endif
362
363     /* ÖÁ´Ë£¬À¶ÑÀ²»ÔÙËÍÊý¾Ýµ½UART£¬Ò²²»ÔÙ½ÓÊÕÖ÷¿ØµÄUARTÊý¾Ý
364      * ½Ó×ŵ÷ÓÃenable_irqʹÄÜ bt_wake_host irq£¬µ±Ô¶¶ËÉ豸ÓÐÊý¾Ý
365      * µ½À´Ê±£¬½«Í¨¹ý¸ÃIRQ»½ÐÑÖ÷¿Ø
366      */
367
368     // enable bt wakeup host
369     if (gpio_is_valid(wake_host_irq->gpio.io))
370     {
371         DBG("enable irq for bt wakeup host\n");
372         enable_irq(wake_host_irq->irq);
373     }
374
375 #ifdef CONFIG_RFKILL_RESET
376     rfkill_set_states(rfkill->rfkill_dev, BT_BLOCKED, false);
377     rfkill_rk_set_power(rfkill, BT_BLOCKED);
378 #endif
379
380     return 0;
381 }
382
383 static void rfkill_rk_pm_complete(struct device *dev)
384 {
385     struct rfkill_rk_data *rfkill = g_rfkill;
386     struct rfkill_rk_irq*  wake_host_irq;
387     struct rfkill_rk_gpio* rts;
388     DBG("Enter %s\n",__FUNCTION__);
389
390     if (!rfkill)
391         return;
392
393     wake_host_irq = &rfkill->pdata->wake_host_irq;
394     rts = &rfkill->pdata->rts_gpio;
395
396     if (gpio_is_valid(wake_host_irq->gpio.io))
397     {
398         // ½ûÓõô BT_WAKE_HOST IRQ£¬È·±£ÔÚϵͳ»½ÐѺ󲻻áÒòBTµÄ²Ù×÷
399         // ¶ø¶à´Î´¥·¢¸ÃÖжÏ
400         LOG("** disable irq\n");
401         disable_irq(wake_host_irq->irq);
402     }
403
404     /* Ê¹ÓÃUART_RTS£¬´ËʱÀ¶ÑÀÈç¹ûÓÐÊý¾Ý¾Í»áË͵½UART
405      * Éϲã·ÖÎöËÍÀ´µÄÊý¾Ý²¢×ö³öÏàÓ¦µÄ¶¯×÷£¬±ÈÈç: ËÍÀ´µÄÊÇ
406      * Åä¶ÔÇëÇó£¬ÔòÉϲ㽫»áÁÁÆÁ²¢µ¯³öÅä¶Ô½çÃæ
407      */
408     if (gpio_is_valid(rts->io))
409     {
410         DBG("Enable UART_RTS\n");
411         gpio_direction_output(rts->io, rts->enable);
412         if (rts->iomux.name)
413         {
414             rk_mux_api_set(rts->iomux.name, rts->iomux.fmux);
415         }
416     }
417 }
418
419 static const struct rfkill_ops rfkill_rk_ops = {
420     .set_block = rfkill_rk_set_power,
421 };
422
423 static int rfkill_rk_probe(struct platform_device *pdev)
424 {
425         struct rfkill_rk_data *rfkill;
426         struct rfkill_rk_platform_data *pdata = pdev->dev.platform_data;
427         int ret = 0;
428
429     DBG("Enter %s\n", __func__);
430
431         if (!pdata) {
432                 LOG("%s: No platform data specified\n", __func__);
433                 return -EINVAL;
434         }
435
436     pdata->name = (char*)bt_name;
437
438         rfkill = kzalloc(sizeof(*rfkill), GFP_KERNEL);
439         if (!rfkill)
440                 return -ENOMEM;
441
442         rfkill->pdata = pdata;
443     g_rfkill = rfkill;
444
445     // ÉêÇëGPIOÒÔ¼°IRQ
446     DBG("init gpio\n");
447     // ¶ÔÓÚRK29 BCM4329£¬ËüµÄpoweron ioÓëwifi¹²Óã¬ÔÚboadÎļþÖÐÒѾ­request
448     // ´Ë´¦²»ÓÃÈ¥ÉêÇë
449 #if !WIFI_BT_POWER_TOGGLE
450     ret = rfkill_rk_setup_gpio(&pdata->poweron_gpio, IOMUX_FGPIO, pdata->name, "poweron");
451     if (ret) goto fail_alloc;
452 #endif
453
454     ret = rfkill_rk_setup_gpio(&pdata->reset_gpio, IOMUX_FGPIO, pdata->name, "reset");
455     if (ret) goto fail_poweron;
456
457     ret = rfkill_rk_setup_gpio(&pdata->wake_gpio, IOMUX_FGPIO, pdata->name, "wake");
458     if (ret) goto fail_reset;
459
460     ret = rfkill_rk_setup_wake_irq(rfkill);
461     if (ret) goto fail_wake;
462
463     ret = rfkill_rk_setup_gpio(&(pdata->rts_gpio), IOMUX_FNORMAL, rfkill->pdata->name, "rts");
464     if (ret) goto fail_wake_host_irq;
465
466     // ´´½¨²¢×¢²áRFKILLÉ豸
467     DBG("setup rfkill\n");
468         rfkill->rfkill_dev = rfkill_alloc(pdata->name, &pdev->dev, pdata->type,
469                                 &rfkill_rk_ops, rfkill);
470         if (!rfkill->rfkill_dev)
471                 goto fail_rts;
472
473     // cmy: ÉèÖÃrfkill³õʼ״̬Ϊblocked£¬ÔÚ×¢²áʱ²»»áµ÷Óàset_blockedº¯Êý
474     rfkill_set_states(rfkill->rfkill_dev, BT_BLOCKED, false);
475         ret = rfkill_register(rfkill->rfkill_dev);
476         if (ret < 0)
477                 goto fail_rfkill;
478
479     wake_lock_init(&(rfkill->bt_irq_wl), WAKE_LOCK_SUSPEND, "rfkill_rk_irq_wl");
480     INIT_DELAYED_WORK(&rfkill->bt_sleep_delay_work, rfkill_rk_delay_sleep_bt);
481
482     // cmy: ÉèÖÃÀ¶ÑÀµçÔ´µÄ״̬Ϊ blocked
483     rfkill_rk_set_power(rfkill, BT_BLOCKED);
484
485         platform_set_drvdata(pdev, rfkill);
486
487     LOG("%s device registered.\n", pdata->name);
488
489         return 0;
490
491 fail_rfkill:
492         rfkill_destroy(rfkill->rfkill_dev);
493 fail_rts:
494     if (gpio_is_valid(pdata->rts_gpio.io))
495         gpio_free(pdata->rts_gpio.io);
496 fail_wake_host_irq:
497     if (gpio_is_valid(pdata->wake_host_irq.gpio.io)){
498         free_irq(pdata->wake_host_irq.irq, rfkill);
499         gpio_free(pdata->wake_host_irq.gpio.io);
500     }
501 fail_wake:
502     if (gpio_is_valid(pdata->wake_gpio.io))
503         gpio_free(pdata->wake_gpio.io);
504 fail_reset:
505         if (gpio_is_valid(pdata->reset_gpio.io))
506                 gpio_free(pdata->reset_gpio.io);
507 fail_poweron:
508 #if !WIFI_BT_POWER_TOGGLE
509     if (gpio_is_valid(pdata->poweron_gpio.io))
510         gpio_free(pdata->poweron_gpio.io);
511 #endif
512 fail_alloc:
513         kfree(rfkill);
514     g_rfkill = NULL;
515
516         return ret;
517 }
518
519 static int rfkill_rk_remove(struct platform_device *pdev)
520 {
521         struct rfkill_rk_data *rfkill = platform_get_drvdata(pdev);
522
523     LOG("Enter %s\n", __func__);
524
525         rfkill_unregister(rfkill->rfkill_dev);
526         rfkill_destroy(rfkill->rfkill_dev);
527
528     wake_lock_destroy(&rfkill->bt_irq_wl);
529     
530     cancel_delayed_work_sync(&rfkill->bt_sleep_delay_work);
531
532     // free gpio
533     if (gpio_is_valid(rfkill->pdata->rts_gpio.io))
534         gpio_free(rfkill->pdata->rts_gpio.io);
535     
536     if (gpio_is_valid(rfkill->pdata->wake_host_irq.gpio.io)){
537         free_irq(rfkill->pdata->wake_host_irq.irq, rfkill);
538         gpio_free(rfkill->pdata->wake_host_irq.gpio.io);
539     }
540     
541     if (gpio_is_valid(rfkill->pdata->wake_gpio.io))
542         gpio_free(rfkill->pdata->wake_gpio.io);
543     
544     if (gpio_is_valid(rfkill->pdata->reset_gpio.io))
545         gpio_free(rfkill->pdata->reset_gpio.io);
546     
547     if (gpio_is_valid(rfkill->pdata->poweron_gpio.io))
548         gpio_free(rfkill->pdata->poweron_gpio.io);
549
550     kfree(rfkill);
551     g_rfkill = NULL;
552
553         return 0;
554 }
555
556 static const struct dev_pm_ops rfkill_rk_pm_ops = {
557         .prepare = rfkill_rk_pm_prepare,
558         .complete = rfkill_rk_pm_complete,
559 };
560
561 static struct platform_driver rfkill_rk_driver = {
562         .probe = rfkill_rk_probe,
563         .remove = __devexit_p(rfkill_rk_remove),
564         .driver = {
565                 .name = "rfkill_rk",
566                 .owner = THIS_MODULE,
567                 .pm = &rfkill_rk_pm_ops,
568         },
569 };
570
571 static int __init rfkill_rk_init(void)
572 {
573     LOG("Enter %s\n", __func__);
574         return platform_driver_register(&rfkill_rk_driver);
575 }
576
577 static void __exit rfkill_rk_exit(void)
578 {
579     LOG("Enter %s\n", __func__);
580         platform_driver_unregister(&rfkill_rk_driver);
581 }
582
583 module_init(rfkill_rk_init);
584 module_exit(rfkill_rk_exit);
585
586 MODULE_DESCRIPTION("rock-chips rfkill for Bluetooth v0.2");
587 MODULE_AUTHOR("cmy@rock-chips.com, cz@rock-chips.com");
588 MODULE_LICENSE("GPL");
589