Merge remote-tracking branch 'stable/linux-3.0.y' 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_RKWIFI)
107     #if defined(CONFIG_RKWIFI_26M)
108         "rk903_26M"
109     #else
110         "rk903"
111     #endif
112 #elif defined(CONFIG_BCM4329)
113         "bcm4329"
114 #elif defined(CONFIG_MV8787)
115         "mv8787"
116 #else
117         "bt_default"
118 #endif
119 ;
120
121 /*
122  *  rfkill_rk_wake_host_irq - BT_WAKE_HOST Öжϻص÷º¯Êý
123  *      ÉêÇëÒ»¸öwakelock£¬ÒÔÈ·±£´Ë´Î»½ÐѲ»»áÂíÉϽáÊø
124  */
125 static irqreturn_t rfkill_rk_wake_host_irq(int irq, void *dev)
126 {
127     struct rfkill_rk_data *rfkill = dev;
128     LOG("BT_WAKE_HOST IRQ fired\n");
129     
130     DBG("BT IRQ wakeup, request %dms wakelock\n", BT_IRQ_WAKELOCK_TIMEOUT);
131
132     wake_lock_timeout(&rfkill->bt_irq_wl, 
133                     msecs_to_jiffies(BT_IRQ_WAKELOCK_TIMEOUT));
134     
135         return IRQ_HANDLED;
136 }
137
138 /*
139  * rfkill_rk_setup_gpio - ÉèÖÃGPIO
140  *      gpio    - ÒªÉèÖõÄGPIO
141  *      mux     - iomux Ê²Ã´¹¦ÄÜ
142  *      prefix,name - ×é³É¸ÃIOµÄÃû³Æ
143  * ·µ»ØÖµ
144  *      ·µ»ØÖµÓë gpio_request Ïàͬ
145  */
146 static int rfkill_rk_setup_gpio(struct rfkill_rk_gpio* gpio, int mux, const char* prefix, const char* name)
147 {
148         if (gpio_is_valid(gpio->io)) {
149         int ret=0;
150         sprintf(gpio->name, "%s_%s", prefix, name);
151                 ret = gpio_request(gpio->io, gpio->name);
152                 if (ret) {
153                         LOG("Failed to get %s gpio.\n", gpio->name);
154                         return -1;
155                 }
156         if (gpio->iomux.name)
157         {
158             if (mux==1)
159                 rk_mux_api_set(gpio->iomux.name, gpio->iomux.fgpio);
160             else if (mux==2)
161                 rk_mux_api_set(gpio->iomux.name, gpio->iomux.fmux);
162             else
163                 ;// do nothing
164         }
165         }
166
167     return 0;
168 }
169
170 // ÉèÖàBT_WAKE_HOST IRQ
171 static int rfkill_rk_setup_wake_irq(struct rfkill_rk_data* rfkill)
172 {
173     int ret=0;
174     struct rfkill_rk_irq* irq = &(rfkill->pdata->wake_host_irq);
175     
176     ret = rfkill_rk_setup_gpio(&irq->gpio, IOMUX_FGPIO, rfkill->pdata->name, "wake_host");
177     if (ret) goto fail1;
178
179     if (gpio_is_valid(irq->gpio.io))
180     {
181         ret = gpio_pull_updown(irq->gpio.io, (irq->gpio.enable==GPIO_LOW)?GPIOPullUp:GPIOPullDown);
182         if (ret) goto fail2;
183         LOG("Request irq for bt wakeup host\n");
184         irq->irq = gpio_to_irq(irq->gpio.io);
185         sprintf(irq->name, "%s_irq", irq->gpio.name);
186         ret = request_irq(irq->irq,
187                     rfkill_rk_wake_host_irq,
188                     (irq->gpio.enable==GPIO_LOW)?IRQF_TRIGGER_FALLING:IRQF_TRIGGER_RISING,
189                     irq->name,
190                     rfkill);
191         if (ret) goto fail2;
192         LOG("** disable irq\n");
193         disable_irq(irq->irq);
194         ret = enable_irq_wake(irq->irq);
195         if (ret) goto fail3;
196     }
197
198     return ret;
199
200 fail3:
201     free_irq(irq->gpio.io, rfkill);
202 fail2:
203     gpio_free(irq->gpio.io);
204 fail1:
205     return ret;
206 }
207
208 static inline void rfkill_rk_sleep_bt_internal(struct rfkill_rk_data *rfkill, bool sleep)
209 {
210     struct rfkill_rk_gpio *wake = &rfkill->pdata->wake_gpio;
211     
212     DBG("*** bt sleep: %d ***\n", sleep);
213     gpio_direction_output(wake->io, sleep?!wake->enable:wake->enable);
214 }
215
216 static void rfkill_rk_delay_sleep_bt(struct work_struct *work)
217 {
218     struct rfkill_rk_data *rfkill = NULL;
219     DBG("Enter %s\n",__FUNCTION__);
220
221     rfkill = container_of(work, struct rfkill_rk_data, bt_sleep_delay_work.work);
222
223     rfkill_rk_sleep_bt_internal(rfkill, BT_SLEEP);
224 }
225
226 /*
227  *  rfkill_rk_sleep_bt - Sleep or Wakeup BT
228  *      1 ÔÚ¸øBTÉϵçʱºò£¬µ÷Óøú¯Êý»½ÐÑBT
229  *      2 ÔÚsuspendÇý¶¯Ê±ºò£¬µ÷Óøú¯Êý˯ÃßBT
230  *      3 ÔÚHCIÇý¶¯ÖУ¬µ±ÓÐÃüÁî·¢Ë͸øBTʱ£¬µ÷Óøú¯Êý»½ÐÑBT
231  *
232  *  ¶ÔÀ¶ÑÀµÄÖ¸Áî·¢ËÍÊÇ·¢ÉúÔÚÀ¶ÑÀÉϵçÖ®ºó£¬Òò´Ë1Óë3²»»áͬʱµ÷Óøú¯Êý
233  *  À¶ÑÀÖ¸Áî·¢ËÍÓÉÓû§²ã·¢Æð£¬2Óë3²»»áͬʱµ÷Óøú¯Êý
234  */
235 void rfkill_rk_sleep_bt(bool sleep)
236 {
237     struct rfkill_rk_data *rfkill = g_rfkill;
238     struct rfkill_rk_gpio *wake;
239     bool ret;
240     DBG("Enter %s\n",__FUNCTION__);
241     
242     if (rfkill==NULL)
243     {
244         LOG("*** RFKILL is empty???\n");
245         return;
246     }
247
248     wake = &rfkill->pdata->wake_gpio;
249     if (!gpio_is_valid(wake->io))
250     {
251         DBG("*** Not support bt wakeup and sleep\n");
252         return;
253     }
254
255     // È¡Ïûdelay work£¬Èç¹ûwork´¦ÓÚpendding£¬ÔòÁ¢¼´È¡Ïû
256     // Èç¹ûwork´¦ÓÚrunning£¬ÔòµÈ´ýÖ±µ½¸Ãwork½áÊø
257     ret = cancel_delayed_work_sync(&rfkill->bt_sleep_delay_work);
258
259     rfkill_rk_sleep_bt_internal(rfkill, sleep);
260
261 #ifdef CONFIG_BT_AUTOSLEEP
262     if (sleep==BT_WAKEUP)
263     {
264         // ÖØÐÂÉèÖÃdelay work
265         schedule_delayed_work(&rfkill->bt_sleep_delay_work, 
266                             msecs_to_jiffies(BT_WAKEUP_TIMEOUT));
267     }
268 #endif
269 }
270 EXPORT_SYMBOL(rfkill_rk_sleep_bt);
271
272 static int rfkill_rk_set_power(void *data, bool blocked)
273 {
274         struct rfkill_rk_data *rfkill = data;
275     struct rfkill_rk_gpio *poweron = &rfkill->pdata->poweron_gpio;
276     struct rfkill_rk_gpio *reset = &rfkill->pdata->reset_gpio;
277
278     DBG("Enter %s\n", __func__);
279
280     DBG("Set blocked:%d\n", blocked);
281
282         if (false == blocked) { 
283         rfkill_rk_sleep_bt(BT_WAKEUP); // ensure bt is wakeup
284         
285                 if (gpio_is_valid(poweron->io))
286         {
287                         gpio_direction_output(poweron->io, poweron->enable);
288             msleep(20);
289         }
290                 if (gpio_is_valid(reset->io))
291         {
292                         gpio_direction_output(reset->io, reset->enable);
293             msleep(20);
294                         gpio_direction_output(reset->io, !reset->enable);
295             msleep(20);
296         }
297
298         LOG("bt turn on power\n");
299         } else {
300 #if WIFI_BT_POWER_TOGGLE
301                 if (!rk29sdk_wifi_power_state) {
302 #endif
303             if (gpio_is_valid(poweron->io))
304             {      
305                 gpio_direction_output(poweron->io, !poweron->enable);
306                 msleep(20);
307             }
308
309                 LOG("bt shut off power\n");
310 #if WIFI_BT_POWER_TOGGLE
311                 }else {
312                         LOG("bt shouldn't shut off power, wifi is using it!\n");
313                 }
314 #endif
315                 if (gpio_is_valid(reset->io))
316         {      
317                         gpio_direction_output(reset->io, reset->enable);/* bt reset active*/
318             msleep(20);
319         }
320         }
321
322 #if WIFI_BT_POWER_TOGGLE
323         rk29sdk_bt_power_state = !blocked;
324 #endif
325         return 0;
326 }
327
328 static int rfkill_rk_pm_prepare(struct device *dev)
329 {
330     struct rfkill_rk_data *rfkill = g_rfkill;
331     struct rfkill_rk_gpio* rts;
332     struct rfkill_rk_irq*  wake_host_irq;
333     DBG("Enter %s\n",__FUNCTION__);
334
335     if (!rfkill)
336         return 0;
337
338     rts = &rfkill->pdata->rts_gpio;
339     wake_host_irq = &rfkill->pdata->wake_host_irq;
340
341     //To prevent uart to receive bt data when suspended
342     if (gpio_is_valid(rts->io))
343     {
344         DBG("Disable UART_RTS\n");
345         if (rts->iomux.name)
346         {
347             rk_mux_api_set(rts->iomux.name, rts->iomux.fgpio);
348         }
349         gpio_direction_output(rts->io, !rts->enable);
350     }
351
352 #ifdef CONFIG_BT_AUTOSLEEP
353     // BT½øÈë˯Ãß״̬£¬²»½ÓÊÕÖ÷¿ØÊý¾Ý
354     rfkill_rk_sleep_bt(BT_SLEEP);
355 #endif
356
357     /* ÖÁ´Ë£¬À¶ÑÀ²»ÔÙËÍÊý¾Ýµ½UART£¬Ò²²»ÔÙ½ÓÊÕÖ÷¿ØµÄUARTÊý¾Ý
358      * ½Ó×ŵ÷ÓÃenable_irqʹÄÜ bt_wake_host irq£¬µ±Ô¶¶ËÉ豸ÓÐÊý¾Ý
359      * µ½À´Ê±£¬½«Í¨¹ý¸ÃIRQ»½ÐÑÖ÷¿Ø
360      */
361
362     // enable bt wakeup host
363     if (gpio_is_valid(wake_host_irq->gpio.io))
364     {
365         DBG("enable irq for bt wakeup host\n");
366         enable_irq(wake_host_irq->irq);
367     }
368
369 #ifdef CONFIG_RFKILL_RESET
370     rfkill_set_states(rfkill->rfkill_dev, BT_BLOCKED, false);
371     rfkill_rk_set_power(rfkill, BT_BLOCKED);
372 #endif
373
374     return 0;
375 }
376
377 static void rfkill_rk_pm_complete(struct device *dev)
378 {
379     struct rfkill_rk_data *rfkill = g_rfkill;
380     struct rfkill_rk_irq*  wake_host_irq;
381     struct rfkill_rk_gpio* rts;
382     DBG("Enter %s\n",__FUNCTION__);
383
384     if (!rfkill)
385         return;
386
387     wake_host_irq = &rfkill->pdata->wake_host_irq;
388     rts = &rfkill->pdata->rts_gpio;
389
390     if (gpio_is_valid(wake_host_irq->gpio.io))
391     {
392         // ½ûÓõô BT_WAKE_HOST IRQ£¬È·±£ÔÚϵͳ»½ÐѺ󲻻áÒòBTµÄ²Ù×÷
393         // ¶ø¶à´Î´¥·¢¸ÃÖжÏ
394         LOG("** disable irq\n");
395         disable_irq(wake_host_irq->irq);
396     }
397
398     /* Ê¹ÓÃUART_RTS£¬´ËʱÀ¶ÑÀÈç¹ûÓÐÊý¾Ý¾Í»áË͵½UART
399      * Éϲã·ÖÎöËÍÀ´µÄÊý¾Ý²¢×ö³öÏàÓ¦µÄ¶¯×÷£¬±ÈÈç: ËÍÀ´µÄÊÇ
400      * Åä¶ÔÇëÇó£¬ÔòÉϲ㽫»áÁÁÆÁ²¢µ¯³öÅä¶Ô½çÃæ
401      */
402     if (gpio_is_valid(rts->io))
403     {
404         DBG("Enable UART_RTS\n");
405         gpio_direction_output(rts->io, rts->enable);
406         if (rts->iomux.name)
407         {
408             rk_mux_api_set(rts->iomux.name, rts->iomux.fmux);
409         }
410     }
411 }
412
413 static const struct rfkill_ops rfkill_rk_ops = {
414     .set_block = rfkill_rk_set_power,
415 };
416
417 static int rfkill_rk_probe(struct platform_device *pdev)
418 {
419         struct rfkill_rk_data *rfkill;
420         struct rfkill_rk_platform_data *pdata = pdev->dev.platform_data;
421         int ret = 0;
422
423     DBG("Enter %s\n", __func__);
424
425         if (!pdata) {
426                 LOG("%s: No platform data specified\n", __func__);
427                 return -EINVAL;
428         }
429
430     pdata->name = (char*)bt_name;
431
432         rfkill = kzalloc(sizeof(*rfkill), GFP_KERNEL);
433         if (!rfkill)
434                 return -ENOMEM;
435
436         rfkill->pdata = pdata;
437     g_rfkill = rfkill;
438
439     // ÉêÇëGPIOÒÔ¼°IRQ
440     DBG("init gpio\n");
441     // ¶ÔÓÚRK29 BCM4329£¬ËüµÄpoweron ioÓëwifi¹²Óã¬ÔÚboadÎļþÖÐÒѾ­request
442     // ´Ë´¦²»ÓÃÈ¥ÉêÇë
443 #if !WIFI_BT_POWER_TOGGLE
444     ret = rfkill_rk_setup_gpio(&pdata->poweron_gpio, IOMUX_FGPIO, pdata->name, "poweron");
445     if (ret) goto fail_alloc;
446 #endif
447
448     ret = rfkill_rk_setup_gpio(&pdata->reset_gpio, IOMUX_FGPIO, pdata->name, "reset");
449     if (ret) goto fail_poweron;
450
451     ret = rfkill_rk_setup_gpio(&pdata->wake_gpio, IOMUX_FGPIO, pdata->name, "wake");
452     if (ret) goto fail_reset;
453
454     ret = rfkill_rk_setup_wake_irq(rfkill);
455     if (ret) goto fail_wake;
456
457     ret = rfkill_rk_setup_gpio(&(pdata->rts_gpio), IOMUX_FNORMAL, rfkill->pdata->name, "rts");
458     if (ret) goto fail_wake_host_irq;
459
460     // ´´½¨²¢×¢²áRFKILLÉ豸
461     DBG("setup rfkill\n");
462         rfkill->rfkill_dev = rfkill_alloc(pdata->name, &pdev->dev, pdata->type,
463                                 &rfkill_rk_ops, rfkill);
464         if (!rfkill->rfkill_dev)
465                 goto fail_rts;
466
467     // cmy: ÉèÖÃrfkill³õʼ״̬Ϊblocked£¬ÔÚ×¢²áʱ²»»áµ÷Óàset_blockedº¯Êý
468     rfkill_set_states(rfkill->rfkill_dev, BT_BLOCKED, false);
469         ret = rfkill_register(rfkill->rfkill_dev);
470         if (ret < 0)
471                 goto fail_rfkill;
472
473     wake_lock_init(&(rfkill->bt_irq_wl), WAKE_LOCK_SUSPEND, "rfkill_rk_irq_wl");
474     INIT_DELAYED_WORK(&rfkill->bt_sleep_delay_work, rfkill_rk_delay_sleep_bt);
475
476     // cmy: ÉèÖÃÀ¶ÑÀµçÔ´µÄ״̬Ϊ blocked
477     rfkill_rk_set_power(rfkill, BT_BLOCKED);
478
479         platform_set_drvdata(pdev, rfkill);
480
481     LOG("%s device registered.\n", pdata->name);
482
483         return 0;
484
485 fail_rfkill:
486         rfkill_destroy(rfkill->rfkill_dev);
487 fail_rts:
488     if (gpio_is_valid(pdata->rts_gpio.io))
489         gpio_free(pdata->rts_gpio.io);
490 fail_wake_host_irq:
491     if (gpio_is_valid(pdata->wake_host_irq.gpio.io)){
492         free_irq(pdata->wake_host_irq.irq, rfkill);
493         gpio_free(pdata->wake_host_irq.gpio.io);
494     }
495 fail_wake:
496     if (gpio_is_valid(pdata->wake_gpio.io))
497         gpio_free(pdata->wake_gpio.io);
498 fail_reset:
499         if (gpio_is_valid(pdata->reset_gpio.io))
500                 gpio_free(pdata->reset_gpio.io);
501 fail_poweron:
502 #if !WIFI_BT_POWER_TOGGLE
503     if (gpio_is_valid(pdata->poweron_gpio.io))
504         gpio_free(pdata->poweron_gpio.io);
505 #endif
506 fail_alloc:
507         kfree(rfkill);
508     g_rfkill = NULL;
509
510         return ret;
511 }
512
513 static int rfkill_rk_remove(struct platform_device *pdev)
514 {
515         struct rfkill_rk_data *rfkill = platform_get_drvdata(pdev);
516
517     LOG("Enter %s\n", __func__);
518
519         rfkill_unregister(rfkill->rfkill_dev);
520         rfkill_destroy(rfkill->rfkill_dev);
521
522     wake_lock_destroy(&rfkill->bt_irq_wl);
523     
524     cancel_delayed_work_sync(&rfkill->bt_sleep_delay_work);
525
526     // free gpio
527     if (gpio_is_valid(rfkill->pdata->rts_gpio.io))
528         gpio_free(rfkill->pdata->rts_gpio.io);
529     
530     if (gpio_is_valid(rfkill->pdata->wake_host_irq.gpio.io)){
531         free_irq(rfkill->pdata->wake_host_irq.irq, rfkill);
532         gpio_free(rfkill->pdata->wake_host_irq.gpio.io);
533     }
534     
535     if (gpio_is_valid(rfkill->pdata->wake_gpio.io))
536         gpio_free(rfkill->pdata->wake_gpio.io);
537     
538     if (gpio_is_valid(rfkill->pdata->reset_gpio.io))
539         gpio_free(rfkill->pdata->reset_gpio.io);
540     
541     if (gpio_is_valid(rfkill->pdata->poweron_gpio.io))
542         gpio_free(rfkill->pdata->poweron_gpio.io);
543
544     kfree(rfkill);
545     g_rfkill = NULL;
546
547         return 0;
548 }
549
550 static const struct dev_pm_ops rfkill_rk_pm_ops = {
551         .prepare = rfkill_rk_pm_prepare,
552         .complete = rfkill_rk_pm_complete,
553 };
554
555 static struct platform_driver rfkill_rk_driver = {
556         .probe = rfkill_rk_probe,
557         .remove = __devexit_p(rfkill_rk_remove),
558         .driver = {
559                 .name = "rfkill_rk",
560                 .owner = THIS_MODULE,
561                 .pm = &rfkill_rk_pm_ops,
562         },
563 };
564
565 static int __init rfkill_rk_init(void)
566 {
567     LOG("Enter %s\n", __func__);
568         return platform_driver_register(&rfkill_rk_driver);
569 }
570
571 static void __exit rfkill_rk_exit(void)
572 {
573     LOG("Enter %s\n", __func__);
574         platform_driver_unregister(&rfkill_rk_driver);
575 }
576
577 module_init(rfkill_rk_init);
578 module_exit(rfkill_rk_exit);
579
580 MODULE_DESCRIPTION("rock-chips rfkill for Bluetooth v0.2");
581 MODULE_AUTHOR("cmy@rock-chips.com, cz@rock-chips.com");
582 MODULE_LICENSE("GPL");
583