diff --git a/net/rfkill/rfkill-rk.c b/net/rfkill/rfkill-rk.c deleted file mode 100755 index cb5c717cd494..000000000000 --- a/net/rfkill/rfkill-rk.c +++ /dev/null @@ -1,752 +0,0 @@ -/* - * Copyright (C) 2012 ROCKCHIP, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ -/* Rock-chips rfkill driver for bluetooth - * - * BT 源码由原来的arch/arm/mach-rkxx/board-xxx-rfkill.c移至此处 - * GPIO的配置在 arch/arm/mach-rkxx/board-rkxx-sdk.c 的rfkill_rk_platdata结构体中 - * - * 请根据实际情况配置好蓝牙的各个GPIO引脚,引脚配置说明如下: - .xxxx_gpio = { - .io = -1, // GPIO值, -1 表示无此功能 - .enable = -1, // 使能, GPIO_HIGH - 高使能, GPIO_LOW - 低使能 - .iomux = { - .name = NULL, // IOMUX名称,NULL 表示它是单功能,不需要mux - .fgpio = -1, // 配置为GPIO时,应设置的值 - .fmux = -1, // 配置为复用功能时,应设置的值 - }, - }, -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if 0 -#define DBG(x...) printk(KERN_INFO "[BT_RFKILL]: "x) -#else -#define DBG(x...) -#endif - -#define LOG(x...) printk(KERN_INFO "[BT_RFKILL]: "x) - -#define BT_WAKEUP_TIMEOUT 10000 -#define BT_IRQ_WAKELOCK_TIMEOUT 10*1000 - -#define BT_BLOCKED true -#define BT_UNBLOCK false -#define BT_SLEEP true -#define BT_WAKEUP false - -enum { - IOMUX_FNORMAL=0, - IOMUX_FGPIO, - IOMUX_FMUX, -}; - -#ifdef CONFIG_ARCH_RK29 - #define rk_mux_api_set(name,mode) rk29_mux_api_set(name,mode) -#elif defined (CONFIG_ARCH_RK30) - #define rk_mux_api_set(name,mode) rk30_mux_api_set(name,mode) -#else - #define rk_mux_api_set(name,mode) rk30_mux_api_set(name,mode) -#endif - -// RK29+BCM4329, 其wifi与bt的power控制脚是接在一起的 -// 在给bt下电时,需要先判断wifi状态 -#if defined(CONFIG_BCM4329) -#define WIFI_BT_POWER_TOGGLE 1 -extern int rk29sdk_bt_power_state; -extern int rk29sdk_wifi_power_state; -#else -#define WIFI_BT_POWER_TOGGLE 0 -#endif - -struct rfkill_rk_data { - // 指向board中定义的platform data - struct rfkill_rk_platform_data *pdata; - - // 指向rfkill设备,它由rfkill_alloc创建 - struct rfkill *rfkill_dev; - - // 在IRQ中断函数中使用,确保在BT唤醒AP后,不会立即 - // 调用suspend进入睡眠 - struct wake_lock bt_irq_wl; - - // 在唤醒BT后,通过该delay work延时一段时间后进入睡眠 - // 如果delay work还未执行就又来一次 BT wake,则会先cancel - // 已有的 delay work,并重新计时。 - struct delayed_work bt_sleep_delay_work; -}; - -static struct rfkill_rk_data *g_rfkill = NULL; - -static const char bt_name[] = -#if defined (CONFIG_BCM4330) - #if defined (CONFIG_BT_MODULE_NH660) - "nh660" - #else - "bcm4330" - #endif -#elif defined (CONFIG_RK903) - #if defined(CONFIG_RKWIFI_26M) - "rk903_26M" - #else - "rk903" - #endif -#elif defined(CONFIG_BCM4329) - "bcm4329" -#elif defined(CONFIG_MV8787) - "mv8787" -#elif defined(CONFIG_AP6210) - #if defined(CONFIG_RKWIFI_26M) - "ap6210" - #else - "ap6210_24M" - #endif -#elif defined(CONFIG_AP6330) - "ap6330" -#elif defined(CONFIG_AP6476) - "ap6476" -#elif defined(CONFIG_AP6493) - "ap6493" -#elif defined(CONFIG_AP6441) - "ap6441" -#else - "bt_default" -#endif -; - -/* - * rfkill_rk_wake_host_irq - BT_WAKE_HOST 中断回调函数 - * 申请一个wakelock,以确保此次唤醒不会马上结束 - */ -static irqreturn_t rfkill_rk_wake_host_irq(int irq, void *dev) -{ - struct rfkill_rk_data *rfkill = dev; - LOG("BT_WAKE_HOST IRQ fired\n"); - - DBG("BT IRQ wakeup, request %dms wakelock\n", BT_IRQ_WAKELOCK_TIMEOUT); - - wake_lock_timeout(&rfkill->bt_irq_wl, - msecs_to_jiffies(BT_IRQ_WAKELOCK_TIMEOUT)); - - return IRQ_HANDLED; -} - -/* - * rfkill_rk_setup_gpio - 设置GPIO - * gpio - 要设置的GPIO - * mux - iomux 什么功能 - * prefix,name - 组成该IO的名称 - * 返回值 - * 返回值与 gpio_request 相同 - */ -static int rfkill_rk_setup_gpio(struct rfkill_rk_gpio* gpio, int mux, const char* prefix, const char* name) -{ - if (gpio_is_valid(gpio->io)) { - int ret=0; - sprintf(gpio->name, "%s_%s", prefix, name); - ret = gpio_request(gpio->io, gpio->name); - if (ret) { - LOG("Failed to get %s gpio.\n", gpio->name); - return -1; - } - if (gpio->iomux.name) - { - if (mux==IOMUX_FGPIO) - rk_mux_api_set(gpio->iomux.name, gpio->iomux.fgpio); - else if (mux==IOMUX_FMUX) - rk_mux_api_set(gpio->iomux.name, gpio->iomux.fmux); - else - ;// do nothing - } - } - - return 0; -} - -// 设置 BT_WAKE_HOST IRQ -static int rfkill_rk_setup_wake_irq(struct rfkill_rk_data* rfkill) -{ - int ret=0; - struct rfkill_rk_irq* irq = &(rfkill->pdata->wake_host_irq); - -#ifndef CONFIG_BK3515A_COMBO - ret = rfkill_rk_setup_gpio(&irq->gpio, IOMUX_FGPIO, rfkill->pdata->name, "wake_host"); - if (ret) goto fail1; -#endif - - if (gpio_is_valid(irq->gpio.io)) - { -#ifndef CONFIG_BK3515A_COMBO - ret = gpio_pull_updown(irq->gpio.io, (irq->gpio.enable==GPIO_LOW)?GPIOPullUp:GPIOPullDown); - if (ret) goto fail2; -#endif - LOG("Request irq for bt wakeup host\n"); - irq->irq = gpio_to_irq(irq->gpio.io); - sprintf(irq->name, "%s_irq", irq->gpio.name); - ret = request_irq(irq->irq, - rfkill_rk_wake_host_irq, - (irq->gpio.enable==GPIO_LOW)?IRQF_TRIGGER_FALLING:IRQF_TRIGGER_RISING, - irq->name, - rfkill); - if (ret) goto fail2; - LOG("** disable irq\n"); - disable_irq(irq->irq); - ret = enable_irq_wake(irq->irq); - if (ret) goto fail3; - } - - return ret; - -fail3: - free_irq(irq->gpio.io, rfkill); -fail2: - gpio_free(irq->gpio.io); -fail1: - return ret; -} - -static inline void rfkill_rk_sleep_bt_internal(struct rfkill_rk_data *rfkill, bool sleep) -{ - struct rfkill_rk_gpio *wake = &rfkill->pdata->wake_gpio; - - DBG("*** bt sleep: %d ***\n", sleep); -#ifndef CONFIG_BK3515A_COMBO - gpio_direction_output(wake->io, sleep?!wake->enable:wake->enable); -#else - if(!sleep) - { - DBG("HOST_UART0_TX pull down 10us\n"); - if (rfkill_rk_setup_gpio(wake, IOMUX_FGPIO, rfkill->pdata->name, "wake") != 0) { - return; - } - - gpio_direction_output(wake->io, wake->enable); - udelay(10); - gpio_direction_output(wake->io, !wake->enable); - - rk_mux_api_set(wake->iomux.name, wake->iomux.fmux); - gpio_free(wake->io); - } -#endif -} - -static void rfkill_rk_delay_sleep_bt(struct work_struct *work) -{ - struct rfkill_rk_data *rfkill = NULL; - DBG("Enter %s\n",__FUNCTION__); - - rfkill = container_of(work, struct rfkill_rk_data, bt_sleep_delay_work.work); - - rfkill_rk_sleep_bt_internal(rfkill, BT_SLEEP); -} - -/* - * rfkill_rk_sleep_bt - Sleep or Wakeup BT - * 1 在给BT上电时候,调用该函数唤醒BT - * 2 在suspend驱动时候,调用该函数睡眠BT - * 3 在HCI驱动中,当有命令发送给BT时,调用该函数唤醒BT - * - * 对蓝牙的指令发送是发生在蓝牙上电之后,因此1与3不会同时调用该函数 - * 蓝牙指令发送由用户层发起,2与3不会同时调用该函数 - */ -void rfkill_rk_sleep_bt(bool sleep) -{ - struct rfkill_rk_data *rfkill = g_rfkill; - struct rfkill_rk_gpio *wake; - bool ret; - DBG("Enter %s\n",__FUNCTION__); - - if (rfkill==NULL) - { - LOG("*** RFKILL is empty???\n"); - return; - } - - wake = &rfkill->pdata->wake_gpio; - if (!gpio_is_valid(wake->io)) - { - DBG("*** Not support bt wakeup and sleep\n"); - return; - } - - // 取消delay work,如果work处于pendding,则立即取消 - // 如果work处于running,则等待直到该work结束 - ret = cancel_delayed_work_sync(&rfkill->bt_sleep_delay_work); - - rfkill_rk_sleep_bt_internal(rfkill, sleep); - -#ifdef CONFIG_BT_AUTOSLEEP - if (sleep==BT_WAKEUP) - { - // 重新设置delay work - schedule_delayed_work(&rfkill->bt_sleep_delay_work, - msecs_to_jiffies(BT_WAKEUP_TIMEOUT)); - } -#endif -} -EXPORT_SYMBOL(rfkill_rk_sleep_bt); - -static int rfkill_rk_set_power(void *data, bool blocked) -{ - struct rfkill_rk_data *rfkill = data; - struct rfkill_rk_gpio *poweron = &rfkill->pdata->poweron_gpio; - struct rfkill_rk_gpio *reset = &rfkill->pdata->reset_gpio; - struct rfkill_rk_gpio* rts = &rfkill->pdata->rts_gpio; - - DBG("Enter %s\n", __func__); - - DBG("Set blocked:%d\n", blocked); - - if (false == blocked) { - rfkill_rk_sleep_bt(BT_WAKEUP); // ensure bt is wakeup - - if (gpio_is_valid(poweron->io)) - { - gpio_direction_output(poweron->io, poweron->enable); - msleep(20); - } - if (gpio_is_valid(reset->io)) - { - gpio_direction_output(reset->io, reset->enable); - msleep(20); - gpio_direction_output(reset->io, !reset->enable); - msleep(20); - } - -#if defined(CONFIG_AP6210) - if (gpio_is_valid(rts->io)) - { - if (rts->iomux.name) - { - rk_mux_api_set(rts->iomux.name, rts->iomux.fgpio); - } - LOG("ENABLE UART_RTS\n"); - gpio_direction_output(rts->io, rts->enable); - - msleep(100); - - LOG("DISABLE UART_RTS\n"); - gpio_direction_output(rts->io, !rts->enable); - if (rts->iomux.name) - { - rk_mux_api_set(rts->iomux.name, rts->iomux.fmux); - } - } -#endif - - LOG("bt turn on power\n"); - } else { -#if WIFI_BT_POWER_TOGGLE - if (!rk29sdk_wifi_power_state) { -#endif - if (gpio_is_valid(poweron->io)) - { - gpio_direction_output(poweron->io, !poweron->enable); - msleep(20); - } - - LOG("bt shut off power\n"); -#if WIFI_BT_POWER_TOGGLE - }else { - LOG("bt shouldn't shut off power, wifi is using it!\n"); - } -#endif - if (gpio_is_valid(reset->io)) - { - gpio_direction_output(reset->io, reset->enable);/* bt reset active*/ - msleep(20); - } - } - -#if WIFI_BT_POWER_TOGGLE - rk29sdk_bt_power_state = !blocked; -#endif - return 0; -} - -static int rfkill_rk_pm_prepare(struct device *dev) -{ - struct rfkill_rk_data *rfkill = g_rfkill; - struct rfkill_rk_gpio* rts; - struct rfkill_rk_irq* wake_host_irq; - DBG("Enter %s\n",__FUNCTION__); - - if (!rfkill) - return 0; - - rts = &rfkill->pdata->rts_gpio; - wake_host_irq = &rfkill->pdata->wake_host_irq; - - //To prevent uart to receive bt data when suspended - if (gpio_is_valid(rts->io)) - { - DBG("Disable UART_RTS\n"); - if (rts->iomux.name) - { - rk_mux_api_set(rts->iomux.name, rts->iomux.fgpio); - } - gpio_direction_output(rts->io, !rts->enable); - } - -#ifdef CONFIG_BT_AUTOSLEEP - // BT进入睡眠状态,不接收主控数据 - rfkill_rk_sleep_bt(BT_SLEEP); -#endif - - /* 至此,蓝牙不再送数据到UART,也不再接收主控的UART数据 - * 接着调用enable_irq使能 bt_wake_host irq,当远端设备有数据 - * 到来时,将通过该IRQ唤醒主控 - */ - - // enable bt wakeup host - if (gpio_is_valid(wake_host_irq->gpio.io)) - { -#ifdef CONFIG_BK3515A_COMBO - int ret = 0; - ret = rfkill_rk_setup_gpio(&wake_host_irq->gpio, IOMUX_FGPIO, rfkill->pdata->name, "wake_host"); - if (ret) - LOG("irq rfkill_rk_setup_gpio failed\n"); - - ret = gpio_pull_updown(wake_host_irq->gpio.io, (wake_host_irq->gpio.enable==GPIO_LOW)?GPIOPullUp:GPIOPullDown); - if (ret) - LOG("irq gpio_pull_updown failed\n"); -#endif - DBG("enable irq for bt wakeup host\n"); - enable_irq(wake_host_irq->irq); - } - -#ifdef CONFIG_RFKILL_RESET - rfkill_set_states(rfkill->rfkill_dev, BT_BLOCKED, false); - rfkill_rk_set_power(rfkill, BT_BLOCKED); -#endif - - return 0; -} - -static void rfkill_rk_pm_complete(struct device *dev) -{ - struct rfkill_rk_data *rfkill = g_rfkill; - struct rfkill_rk_irq* wake_host_irq; - struct rfkill_rk_gpio* rts; - DBG("Enter %s\n",__FUNCTION__); - - if (!rfkill) - return; - - wake_host_irq = &rfkill->pdata->wake_host_irq; - rts = &rfkill->pdata->rts_gpio; - - if (gpio_is_valid(wake_host_irq->gpio.io)) - { - // 禁用掉 BT_WAKE_HOST IRQ,确保在系统唤醒后不会因BT的操作 - // 而多次触发该中断 - LOG("** disable irq\n"); - disable_irq(wake_host_irq->irq); -#ifdef CONFIG_BK3515A_COMBO - rk_mux_api_set(wake_host_irq->gpio.iomux.name, wake_host_irq->gpio.iomux.fmux); - gpio_free(wake_host_irq->gpio.io); -#endif - } - - /* 使用UART_RTS,此时蓝牙如果有数据就会送到UART - * 上层分析送来的数据并做出相应的动作,比如: 送来的是 - * 配对请求,则上层将会亮屏并弹出配对界面 - */ - if (gpio_is_valid(rts->io)) - { - DBG("Enable UART_RTS\n"); - gpio_direction_output(rts->io, rts->enable); - if (rts->iomux.name) - { - rk_mux_api_set(rts->iomux.name, rts->iomux.fmux); - } - } -} - -static const struct rfkill_ops rfkill_rk_ops = { - .set_block = rfkill_rk_set_power, -}; - -#define PROC_DIR "bluetooth/sleep" - -static struct proc_dir_entry *bluetooth_dir, *sleep_dir; - -static int bluesleep_read_proc_lpm(char *page, char **start, off_t offset, - int count, int *eof, void *data) -{ - *eof = 1; - return sprintf(page, "unsupported to read\n"); -} - -static int bluesleep_write_proc_lpm(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - return count; -} - -static int bluesleep_read_proc_btwrite(char *page, char **start, off_t offset, - int count, int *eof, void *data) -{ - *eof = 1; - return sprintf(page, "unsupported to read\n"); -} - -static int bluesleep_write_proc_btwrite(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - char b; - - if (count < 1) - return -EINVAL; - - if (copy_from_user(&b, buffer, 1)) - return -EFAULT; - - DBG("btwrite %c\n", b); - /* HCI_DEV_WRITE */ - if (b != '0') { - rfkill_rk_sleep_bt(BT_WAKEUP); - } - - return count; -} - -static int rfkill_rk_probe(struct platform_device *pdev) -{ - struct rfkill_rk_data *rfkill; - struct rfkill_rk_platform_data *pdata = pdev->dev.platform_data; - int ret = 0; - struct proc_dir_entry *ent; - - DBG("Enter %s\n", __func__); - - if (!pdata) { - LOG("%s: No platform data specified\n", __func__); - return -EINVAL; - } - - pdata->name = (char*)bt_name; - - rfkill = kzalloc(sizeof(*rfkill), GFP_KERNEL); - if (!rfkill) - return -ENOMEM; - - rfkill->pdata = pdata; - g_rfkill = rfkill; - - bluetooth_dir = proc_mkdir("bluetooth", NULL); - if (bluetooth_dir == NULL) { - LOG("Unable to create /proc/bluetooth directory"); - return -ENOMEM; - } - - sleep_dir = proc_mkdir("sleep", bluetooth_dir); - if (sleep_dir == NULL) { - LOG("Unable to create /proc/%s directory", PROC_DIR); - return -ENOMEM; - } - - /* read/write proc entries */ - ent = create_proc_entry("lpm", 0, sleep_dir); - if (ent == NULL) { - LOG("Unable to create /proc/%s/lpm entry", PROC_DIR); - ret = -ENOMEM; - goto fail_alloc; - } - ent->read_proc = bluesleep_read_proc_lpm; - ent->write_proc = bluesleep_write_proc_lpm; - - /* read/write proc entries */ - ent = create_proc_entry("btwrite", 0, sleep_dir); - if (ent == NULL) { - LOG("Unable to create /proc/%s/btwrite entry", PROC_DIR); - ret = -ENOMEM; - goto fail_alloc; - } - ent->read_proc = bluesleep_read_proc_btwrite; - ent->write_proc = bluesleep_write_proc_btwrite; - - // 申请GPIO以及IRQ - DBG("init gpio\n"); - // 对于RK29 BCM4329,它的poweron io与wifi共用,在boad文件中已经request - // 此处不用去申请 -#if !WIFI_BT_POWER_TOGGLE - ret = rfkill_rk_setup_gpio(&pdata->poweron_gpio, IOMUX_FGPIO, pdata->name, "poweron"); - if (ret) goto fail_alloc; -#endif - - ret = rfkill_rk_setup_gpio(&pdata->reset_gpio, IOMUX_FGPIO, pdata->name, "reset"); - if (ret) goto fail_poweron; - -#ifndef CONFIG_BK3515A_COMBO - ret = rfkill_rk_setup_gpio(&pdata->wake_gpio, IOMUX_FGPIO, pdata->name, "wake"); - if (ret) goto fail_reset; -#endif - - ret = rfkill_rk_setup_wake_irq(rfkill); - if (ret) goto fail_wake; - - ret = rfkill_rk_setup_gpio(&pdata->rts_gpio, IOMUX_FMUX, rfkill->pdata->name, "rts"); - if (ret) goto fail_wake_host_irq; - - // 创建并注册RFKILL设备 - DBG("setup rfkill\n"); - rfkill->rfkill_dev = rfkill_alloc(pdata->name, &pdev->dev, pdata->type, - &rfkill_rk_ops, rfkill); - if (!rfkill->rfkill_dev) - goto fail_rts; - - // cmy: 设置rfkill初始状态为blocked,在注册时不会调用 set_blocked函数 - rfkill_set_states(rfkill->rfkill_dev, BT_BLOCKED, false); - ret = rfkill_register(rfkill->rfkill_dev); - if (ret < 0) - goto fail_rfkill; - - wake_lock_init(&(rfkill->bt_irq_wl), WAKE_LOCK_SUSPEND, "rfkill_rk_irq_wl"); - INIT_DELAYED_WORK(&rfkill->bt_sleep_delay_work, rfkill_rk_delay_sleep_bt); - - // cmy: 设置蓝牙电源的状态为 blocked - rfkill_rk_set_power(rfkill, BT_BLOCKED); - - platform_set_drvdata(pdev, rfkill); - - LOG("%s device registered.\n", pdata->name); - - return 0; - -fail_rfkill: - rfkill_destroy(rfkill->rfkill_dev); -fail_rts: - if (gpio_is_valid(pdata->rts_gpio.io)) - gpio_free(pdata->rts_gpio.io); -fail_wake_host_irq: - if (gpio_is_valid(pdata->wake_host_irq.gpio.io)){ - free_irq(pdata->wake_host_irq.irq, rfkill); -#ifndef CONFIG_BK3515A_COMBO - gpio_free(pdata->wake_host_irq.gpio.io); -#endif - } -fail_wake: -#ifndef CONFIG_BK3515A_COMBO - if (gpio_is_valid(pdata->wake_gpio.io)) - gpio_free(pdata->wake_gpio.io); -#endif -fail_reset: - if (gpio_is_valid(pdata->reset_gpio.io)) - gpio_free(pdata->reset_gpio.io); -fail_poweron: -#if !WIFI_BT_POWER_TOGGLE - if (gpio_is_valid(pdata->poweron_gpio.io)) - gpio_free(pdata->poweron_gpio.io); -#endif -fail_alloc: - kfree(rfkill); - g_rfkill = NULL; - - remove_proc_entry("btwrite", sleep_dir); - remove_proc_entry("lpm", sleep_dir); - - return ret; -} - -static int rfkill_rk_remove(struct platform_device *pdev) -{ - struct rfkill_rk_data *rfkill = platform_get_drvdata(pdev); - - LOG("Enter %s\n", __func__); - - rfkill_unregister(rfkill->rfkill_dev); - rfkill_destroy(rfkill->rfkill_dev); - - wake_lock_destroy(&rfkill->bt_irq_wl); - - cancel_delayed_work_sync(&rfkill->bt_sleep_delay_work); - - // free gpio - if (gpio_is_valid(rfkill->pdata->rts_gpio.io)) - gpio_free(rfkill->pdata->rts_gpio.io); - - if (gpio_is_valid(rfkill->pdata->wake_host_irq.gpio.io)){ - free_irq(rfkill->pdata->wake_host_irq.irq, rfkill); -#ifndef CONFIG_BK3515A_COMBO - gpio_free(rfkill->pdata->wake_host_irq.gpio.io); -#endif - } - -#ifndef CONFIG_BK3515A_COMBO - if (gpio_is_valid(rfkill->pdata->wake_gpio.io)) - gpio_free(rfkill->pdata->wake_gpio.io); -#endif - - if (gpio_is_valid(rfkill->pdata->reset_gpio.io)) - gpio_free(rfkill->pdata->reset_gpio.io); - - if (gpio_is_valid(rfkill->pdata->poweron_gpio.io)) - gpio_free(rfkill->pdata->poweron_gpio.io); - - kfree(rfkill); - g_rfkill = NULL; - - return 0; -} - -static const struct dev_pm_ops rfkill_rk_pm_ops = { - .prepare = rfkill_rk_pm_prepare, - .complete = rfkill_rk_pm_complete, -}; - -static struct platform_driver rfkill_rk_driver = { - .probe = rfkill_rk_probe, - .remove = __devexit_p(rfkill_rk_remove), - .driver = { - .name = "rfkill_rk", - .owner = THIS_MODULE, - .pm = &rfkill_rk_pm_ops, - }, -}; - -static int __init rfkill_rk_init(void) -{ - LOG("Enter %s\n", __func__); - return platform_driver_register(&rfkill_rk_driver); -} - -static void __exit rfkill_rk_exit(void) -{ - LOG("Enter %s\n", __func__); - platform_driver_unregister(&rfkill_rk_driver); -} - -module_init(rfkill_rk_init); -module_exit(rfkill_rk_exit); - -MODULE_DESCRIPTION("rock-chips rfkill for Bluetooth v0.2"); -MODULE_AUTHOR("cmy@rock-chips.com, cz@rock-chips.com"); -MODULE_LICENSE("GPL"); -