From 49bdeeb29b3ee1bb00103c219ad19f1d1fa06cf8 Mon Sep 17 00:00:00 2001 From: Balakrishna Godavarthi Date: Tue, 26 Oct 2021 19:27:11 +0530 Subject: [PATCH] Bluetooth: Fix BT_EN not made high in specific usecase Usecase: 1) WLAN ON triggered first and then immediately BT ON triggered. 2) As WLAN ON triggered first, before pulling WL_EN to high it will wait for 100ms as BT_EN is low. 3) WLAN timed out first and pulls WL_EN to high and in mean time BT_EN is checking WL_EN status to pull BT_EN to high. Expected behavior: BT_EN must pull high before sending version command. Observed behavior: BT_EN is not pulled high as WL_EN state changes from low to high. While BT_EN checking the WL_EN state. Fix: Check BT_EN status and pull it to high if it not set to high Change-Id: I13e209ac4e1523d377f252aa5c0d243abeb86af4 Signed-off-by: Balakrishna Godavarthi --- drivers/bluetooth/btpower.c | 51 +++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/drivers/bluetooth/btpower.c b/drivers/bluetooth/btpower.c index f477ed56ca34..0ae44e0ff50c 100644 --- a/drivers/bluetooth/btpower.c +++ b/drivers/bluetooth/btpower.c @@ -422,6 +422,9 @@ static int bt_configure_gpios(int on) return rc; } + pr_info("BTON:Turn Bt OFF asserting BT_EN to low\n"); + pr_info("bt-reset-gpio(%d) value(%d)\n", bt_reset_gpio, + gpio_get_value(bt_reset_gpio)); rc = gpio_direction_output(bt_reset_gpio, 0); if (rc) { pr_err("%s: Unable to set direction\n", __func__); @@ -430,25 +433,27 @@ static int bt_configure_gpios(int on) PWR_SRC_STATUS_SET(BT_RESET_GPIO, gpio_get_value(bt_reset_gpio)); msleep(50); - pr_info("BTON:Turn Bt Off bt-reset-gpio(%d) value(%d)\n", - bt_reset_gpio, gpio_get_value(bt_reset_gpio)); + pr_info("BTON:Turn Bt OFF post asserting BT_EN to low\n"); + pr_info("bt-reset-gpio(%d) value(%d)\n", bt_reset_gpio, + gpio_get_value(bt_reset_gpio)); + if (bt_sw_ctrl_gpio >= 0) { - pr_info("BTON:Turn Bt Off\n"); PWR_SRC_STATUS_SET(BT_SW_CTRL_GPIO, gpio_get_value(bt_sw_ctrl_gpio)); - pr_info("bt-sw-ctrl-gpio(%d) value(%d)\n", + pr_info("BTON:Turn Bt OFF bt-sw-ctrl-gpio(%d) value(%d)\n", bt_sw_ctrl_gpio, bt_power_src_status[BT_SW_CTRL_GPIO]); } + if (wl_reset_gpio >= 0) - pr_info("BTON:Turn Bt On wl-reset-gpio(%d) value(%d)\n", + pr_info("BTON:Turn Bt ON wl-reset-gpio(%d) value(%d)\n", wl_reset_gpio, gpio_get_value(wl_reset_gpio)); if ((wl_reset_gpio < 0) || ((wl_reset_gpio >= 0) && gpio_get_value(wl_reset_gpio))) { btpower_set_xo_reset_gpio_state(true); - pr_info("%s: BTON: Asserting BT_EN\n", __func__); + pr_info("BTON: WLAN ON Asserting BT_EN to high\n"); rc = gpio_direction_output(bt_reset_gpio, 1); if (rc) { pr_err("%s: Unable to set direction\n", __func__); @@ -458,21 +463,24 @@ static int bt_configure_gpios(int on) gpio_get_value(bt_reset_gpio)); btpower_set_xo_reset_gpio_state(false); } + if ((wl_reset_gpio >= 0) && (gpio_get_value(wl_reset_gpio) == 0)) { if (gpio_get_value(bt_reset_gpio)) { - pr_info("%s: Wlan Off and BT On too close\n", __func__); - pr_info("%s: reset BT_EN, enable it after delay\n", __func__); + pr_info("BTON: WLAN OFF and BT ON are too close\n"); + pr_info("reset BT_EN, enable it after delay\n"); rc = gpio_direction_output(bt_reset_gpio, 0); if (rc) { - pr_err("%s: Unable to set direction\n", __func__); + pr_err("%s: Unable to set direction\n", + __func__); return rc; } PWR_SRC_STATUS_SET(BT_RESET_GPIO, gpio_get_value(bt_reset_gpio)); } - pr_info("%s:add 100ms delay for AON output to fully discharge\n", - __func__); + pr_info("BTON: WLAN OFF waiting for 100ms delay\n"); + pr_info("for AON output to fully discharge\n"); msleep(100); + pr_info("BTON: WLAN OFF Asserting BT_EN to high\n"); btpower_set_xo_reset_gpio_state(true); rc = gpio_direction_output(bt_reset_gpio, 1); if (rc) { @@ -484,6 +492,24 @@ static int bt_configure_gpios(int on) btpower_set_xo_reset_gpio_state(false); } + /* Below block of code executes if WL_EN is pulled high when + * BT_EN is about to pull high. so above two if conditions are + * not executed. + */ + if (!gpio_get_value(bt_reset_gpio)) { + btpower_set_xo_reset_gpio_state(true); + pr_info("BTON: WLAN ON and BT ON are too close\n"); + pr_info("Asserting BT_EN to high\n"); + rc = gpio_direction_output(bt_reset_gpio, 1); + if (rc) { + pr_err("%s: Unable to set direction\n", __func__); + return rc; + } + PWR_SRC_STATUS_SET(BT_RESET_GPIO, + gpio_get_value(bt_reset_gpio)); + btpower_set_xo_reset_gpio_state(false); + } + msleep(50); /* Check if SW_CTRL is asserted */ if (bt_sw_ctrl_gpio >= 0) { @@ -515,10 +541,9 @@ static int bt_configure_gpios(int on) pr_info("BTON:Turn Bt On bt-reset-gpio(%d) value(%d)\n", bt_reset_gpio, gpio_get_value(bt_reset_gpio)); if (bt_sw_ctrl_gpio >= 0) { - pr_info("BTON:Turn Bt On\n"); PWR_SRC_STATUS_SET(BT_SW_CTRL_GPIO, gpio_get_value(bt_sw_ctrl_gpio)); - pr_info("bt-sw-ctrl-gpio(%d) value(%d)\n", + pr_info("BTON: Turn BT ON bt-sw-ctrl-gpio(%d) value(%d)\n", bt_sw_ctrl_gpio, bt_power_src_status[BT_SW_CTRL_GPIO]); }