From e3e12f52b214121840b44c91de5b3e5af5d3eb84 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Mon, 06 Nov 2023 03:04:41 +0000 Subject: [PATCH] rk3568 rt init --- kernel/net/rfkill/rfkill-bt.c | 248 ++++++++++++++++++++++++++----------------------- 1 files changed, 132 insertions(+), 116 deletions(-) diff --git a/kernel/net/rfkill/rfkill-bt.c b/kernel/net/rfkill/rfkill-bt.c index 378fdc9..a2d31bc 100644 --- a/kernel/net/rfkill/rfkill-bt.c +++ b/kernel/net/rfkill/rfkill-bt.c @@ -25,6 +25,7 @@ #include <linux/rfkill-bt.h> #include <linux/rfkill-wlan.h> #include <linux/wakelock.h> +#include <linux/input.h> #include <linux/interrupt.h> #include <asm/irq.h> #include <linux/suspend.h> @@ -69,9 +70,11 @@ struct wake_lock bt_irq_wl; struct delayed_work bt_sleep_delay_work; int irq_req; + bool enable_power_key; }; static struct rfkill_rk_data *g_rfkill = NULL; +static struct input_dev *power_key_dev; static const char bt_name[] = #if defined(CONFIG_BCM4330) @@ -113,6 +116,20 @@ #endif ; +static int rfkill_rk_power_key_up(void) +{ + if (!power_key_dev) + return -ENODEV; + + input_report_key(power_key_dev, KEY_POWER, 1); + input_sync(power_key_dev); + msleep(20); + input_report_key(power_key_dev, KEY_POWER, 0); + input_sync(power_key_dev); + + return 0; +} + static irqreturn_t rfkill_rk_wake_host_irq(int irq, void *dev) { struct rfkill_rk_data *rfkill = dev; @@ -123,6 +140,16 @@ wake_lock_timeout(&rfkill->bt_irq_wl, msecs_to_jiffies(BT_IRQ_WAKELOCK_TIMEOUT)); + + if (rfkill->enable_power_key) + return IRQ_WAKE_THREAD; + + return IRQ_HANDLED; +} + +static irqreturn_t rfkill_rk_wake_host_irq_thread(int irq, void *dev) +{ + rfkill_rk_power_key_up(); return IRQ_HANDLED; } @@ -165,11 +192,12 @@ 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_ACTIVE_LOW) ? - IRQF_TRIGGER_FALLING : - IRQF_TRIGGER_RISING, - irq->name, rfkill); + ret = request_threaded_irq(irq->irq, rfkill_rk_wake_host_irq, + rfkill_rk_wake_host_irq_thread, + IRQF_ONESHOT | ((irq->gpio.enable == GPIO_ACTIVE_LOW) ? + IRQF_TRIGGER_FALLING : + IRQF_TRIGGER_RISING), + irq->name, rfkill); if (ret) goto fail2; rfkill->irq_req = 1; @@ -271,7 +299,8 @@ return 0; } -static int proc_rk_set_power(void *data, bool blocked) + +static int rfkill_rk_set_power(void *data, bool blocked) { struct rfkill_rk_data *rfkill = data; struct rfkill_rk_gpio *wake_host = &rfkill->pdata->wake_host_irq.gpio; @@ -363,113 +392,6 @@ LOG("%s: cannot get wifi power state!\n", __func__); return -EPERM; } - if (!wifi_power) { - LOG("%s: bt will set vbat to low\n", __func__); - rfkill_set_wifi_bt_power(0); - } else { - LOG("%s: bt shouldn't control the vbat\n", __func__); - } - } - } - - return 0; -} - - -static int rfkill_rk_set_power(void *data, bool blocked) -{ - struct rfkill_rk_data *rfkill = data; - struct rfkill_rk_gpio *wake_host = &rfkill->pdata->wake_host_irq.gpio; - 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; - struct pinctrl *pinctrl = rfkill->pdata->pinctrl; - int wifi_power = 0; - bool toggle = false; - - DBG("Enter %s\n", __func__); - - DBG("Set blocked:%d\n", blocked); - - toggle = rfkill->pdata->power_toggle; - - if (toggle) { - if (rfkill_get_wifi_power_state(&wifi_power)) { - LOG("%s: cannot get wifi power state!\n", __func__); - return -1; - } - } - - DBG("%s: toggle = %s\n", __func__, toggle ? "true" : "false"); - - if (!blocked) { - if (toggle) { - rfkill_set_wifi_bt_power(1); - msleep(100); - } - - rfkill_rk_sleep_bt(BT_WAKEUP); // ensure bt is wakeup - - if (gpio_is_valid(wake_host->io)) { - LOG("%s: set bt wake_host high!\n", __func__); - gpio_direction_output(wake_host->io, 1); - msleep(20); - } - - if (gpio_is_valid(poweron->io)) { - if (gpio_get_value(poweron->io) == !poweron->enable) { - gpio_direction_output(poweron->io, - !poweron->enable); - msleep(20); - gpio_direction_output(poweron->io, - poweron->enable); - msleep(20); - if (gpio_is_valid(wake_host->io)) - gpio_direction_input(wake_host->io); - } - } - - if (gpio_is_valid(reset->io)) { - if (gpio_get_value(reset->io) == !reset->enable) { - gpio_direction_output(reset->io, - !reset->enable); - msleep(20); - gpio_direction_output(reset->io, reset->enable); - } - } - - if (pinctrl && gpio_is_valid(rts->io)) { - pinctrl_select_state(pinctrl, rts->gpio_state); - 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); - pinctrl_select_state(pinctrl, rts->default_state); - } - - bt_power_state = 1; - LOG("bt turn on power\n"); - rfkill_rk_setup_wake_irq(rfkill, 1); - } else { - if (gpio_is_valid(poweron->io)) { - if (gpio_get_value(poweron->io) == poweron->enable) { - gpio_direction_output(poweron->io, - poweron->enable); - msleep(20); - } - } - - bt_power_state = 0; - LOG("bt shut off power\n"); - if (gpio_is_valid(reset->io)) { - if (gpio_get_value(reset->io) == reset->enable) { - gpio_direction_output(reset->io, - reset->enable); - msleep(20); - } - } - if (toggle) { if (!wifi_power) { LOG("%s: bt will set vbat to low\n", __func__); rfkill_set_wifi_bt_power(0); @@ -592,11 +514,56 @@ return -EFAULT; DBG("btwrite %c\n", b); - /* HCI_DEV_WRITE */ if (b != '0') - proc_rk_set_power(g_rfkill, 0); + rfkill_rk_sleep_bt(BT_WAKEUP); else - proc_rk_set_power(g_rfkill, 1); + rfkill_rk_sleep_bt(BT_SLEEP); + + return count; +} + +static ssize_t bluesleep_read_proc_powerupkey(struct file *file, + char __user *buffer, size_t count, + loff_t *data) +{ + struct rfkill_rk_data *rfkill = g_rfkill; + char src[2]; + + if (*data >= 1) + return 0; + + if (!rfkill) + return -EFAULT; + + src[0] = rfkill->enable_power_key ? '1' : '0'; + src[1] = '\n'; + if (copy_to_user(buffer, src, 2)) + return -EFAULT; + *data = 1; + + return 2; +} + +static ssize_t bluesleep_write_proc_powerupkey(struct file *file, + const char __user *buffer, + size_t count, loff_t *data) +{ + char b; + struct rfkill_rk_data *rfkill = g_rfkill; + + if (!rfkill) + return -EFAULT; + + if (count < 1) + return -EINVAL; + + if (copy_from_user(&b, buffer, 1)) + return -EFAULT; + + if (b != '0') + rfkill->enable_power_key = true; + else + rfkill->enable_power_key = false; return count; } @@ -700,6 +667,39 @@ .write = bluesleep_write_proc_btwrite, }; +static const struct file_operations bluesleep_powerupkey = { + .owner = THIS_MODULE, + .read = bluesleep_read_proc_powerupkey, + .write = bluesleep_write_proc_powerupkey, +}; + +static int rfkill_rk_register_power_key(void) +{ + int ret = 0; + + /* register input device */ + power_key_dev = input_allocate_device(); + if (!power_key_dev) { + LOG("ir_dev: not enough memory for input device\n"); + return -ENOMEM; + } + + power_key_dev->name = "bt-powerkey"; + power_key_dev->id.bustype = BUS_HOST; + + power_key_dev->evbit[0] = BIT_MASK(EV_KEY); + set_bit(KEY_POWER, power_key_dev->keybit); + + ret = input_register_device(power_key_dev); + if (ret) { + input_free_device(power_key_dev); + LOG("ir_rx_init: register input device exception, exit\n"); + return -EBUSY; + } + + return ret; +} + static int rfkill_rk_probe(struct platform_device *pdev) { struct rfkill_rk_data *rfkill; @@ -766,6 +766,14 @@ goto fail_alloc; } + /* read/write proc entries */ + ent = proc_create("powerupkey", 0, sleep_dir, &bluesleep_powerupkey); + if (!ent) { + LOG("Unable to create /proc/%s/powerupkey entry", PROC_DIR); + ret = -ENOMEM; + goto fail_alloc; + } + DBG("init gpio\n"); ret = rfkill_rk_setup_gpio(pdev, &pdata->poweron_gpio, pdata->name, @@ -824,12 +832,16 @@ LOG("%s device registered.\n", pdata->name); + if (rfkill_rk_register_power_key() != 0) + goto fail_rfkill; + return 0; fail_rfkill: rfkill_destroy(rfkill->rfkill_dev); fail_alloc: + remove_proc_entry("powerupkey", sleep_dir); remove_proc_entry("btwrite", sleep_dir); remove_proc_entry("lpm", sleep_dir); fail_setup_wake_irq: @@ -848,7 +860,11 @@ rfkill_unregister(rfkill->rfkill_dev); rfkill_destroy(rfkill->rfkill_dev); + remove_proc_entry("powerupkey", sleep_dir); + remove_proc_entry("btwrite", sleep_dir); + remove_proc_entry("lpm", sleep_dir); + input_unregister_device(power_key_dev); cancel_delayed_work_sync(&rfkill->bt_sleep_delay_work); // free gpio -- Gitblit v1.6.2