diff --git a/net/rfkill/rfkill-bt.c b/net/rfkill/rfkill-bt.c index 719a23d41bac..bb9e41b57ef5 100644 --- a/net/rfkill/rfkill-bt.c +++ b/net/rfkill/rfkill-bt.c @@ -274,8 +274,7 @@ int rfkill_get_bt_power_state(int *power, bool *toggle) return 0; } - -static int rfkill_rk_set_power(void *data, bool blocked) +static int proc_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; @@ -381,6 +380,113 @@ static int rfkill_rk_set_power(void *data, bool blocked) 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); + } else { + LOG("%s: bt shouldn't control the vbat\n", __func__); + } + } + } + + return 0; +} + static int rfkill_rk_pm_prepare(struct device *dev) { struct rfkill_rk_data *rfkill = g_rfkill; @@ -491,9 +597,9 @@ static ssize_t bluesleep_write_proc_btwrite(struct file *file, DBG("btwrite %c\n", b); /* HCI_DEV_WRITE */ if (b != '0') - rfkill_rk_sleep_bt(BT_WAKEUP); + proc_rk_set_power(g_rfkill, 0); else - rfkill_rk_sleep_bt(BT_SLEEP); + proc_rk_set_power(g_rfkill, 1); return count; }