net: rfkill: remove unused rfkill-rk

Change-Id: Ib91b06390453c8878108f0dc24e36261f04e82ee
Signed-off-by: Tao Huang <huangtao@rock-chips.com>
This commit is contained in:
Tao Huang 2018-03-23 11:45:47 +08:00
parent e6f2796ef5
commit 0de0a2a416

View File

@ -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 <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/rfkill.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <asm/gpio.h>
#include <mach/iomux.h>
#include <linux/delay.h>
#include <linux/rfkill-rk.h>
#include <linux/wakelock.h>
#include <linux/interrupt.h>
#include <asm/irq.h>
#include <linux/suspend.h>
#include <linux/proc_fs.h>
#include <linux/uaccess.h>
#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
*
* 13
* 23
*/
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");