Bluetooth: Implement a minimum off-time for AON discharge issue

Sometimes it is seen that AON LDO output takes minimum
off-time (worst case 100ms) to fully discharge. If BT is
turned on in this timeframe when AON is not fully discharged
yet ,BT would fail to turn ON.
This fix ensures to:
Toggle BT_EN high when WL_EN is already high.
Handle corner case if WL_EN goes low in step 1.
Add 100ms to toggle BT_EN high when WL_EN is low.

Change-Id: I7b035d3c91e4b73564a866f40ebdff25f1a315b4
Signed-off-by: priyankar <prigup@codeaurora.org>
This commit is contained in:
priyankar 2020-10-12 16:54:17 +05:30 committed by Gerrit - the friendly Code Review server
parent ba87aa9b05
commit efab7ef9d1
2 changed files with 89 additions and 13 deletions

View file

@ -288,6 +288,67 @@ static int bt_clk_disable(struct bt_power_clk_data *clk)
return rc;
}
static int bt_enable_bt_reset_gpios_safely(void)
{
int rc = 0;
int bt_reset_gpio = bt_power_pdata->bt_gpio_sys_rst;
int wl_reset_gpio = bt_power_pdata->wl_gpio_sys_rst;
if (wl_reset_gpio >= 0) {
BT_PWR_INFO("%s: BTON:Turn Bt On", __func__);
BT_PWR_INFO("%s: wl-reset-gpio(%d) value(%d)",
__func__, wl_reset_gpio,
gpio_get_value(wl_reset_gpio));
}
if ((wl_reset_gpio < 0) ||
((wl_reset_gpio >= 0) &&
gpio_get_value(wl_reset_gpio))) {
BT_PWR_INFO("%s: BTON: Asserting BT_EN",
__func__);
rc = gpio_direction_output(bt_reset_gpio, 1);
if (rc) {
BT_PWR_ERR("%s: Unable to set direction",
__func__);
return rc;
}
bt_power_src_status[BT_RESET_GPIO] =
gpio_get_value(bt_reset_gpio);
}
if ((wl_reset_gpio >= 0) &&
(gpio_get_value(wl_reset_gpio) == 0)) {
if (gpio_get_value(bt_reset_gpio)) {
BT_PWR_INFO("%s: Wlan Off and BT On too close",
__func__);
BT_PWR_INFO("%s: Reset BT_EN", __func__);
BT_PWR_INFO("%s: Enable it after delay",
__func__);
rc = gpio_direction_output(bt_reset_gpio, 0);
if (rc) {
BT_PWR_ERR("%s:Unable to set direction",
__func__);
return rc;
}
bt_power_src_status[BT_RESET_GPIO] =
gpio_get_value(bt_reset_gpio);
}
BT_PWR_INFO("%s: 100ms delay added", __func__);
BT_PWR_INFO("%s: for AON output to fully discharge",
__func__);
msleep(100);
rc = gpio_direction_output(bt_reset_gpio, 1);
if (rc) {
BT_PWR_ERR("%s: Unable to set direction",
__func__);
return rc;
}
bt_power_src_status[BT_RESET_GPIO] =
gpio_get_value(bt_reset_gpio);
}
return rc;
}
static int bt_configure_gpios(int on)
{
int rc = 0;
@ -312,7 +373,7 @@ static int bt_configure_gpios(int on)
bt_power_src_status[BT_RESET_GPIO] =
gpio_get_value(bt_reset_gpio);
msleep(50);
BT_PWR_INFO("BTON:Turn Bt Off bt-reset-gpio(%d) value(%d)\n",
BT_PWR_INFO("BTON:Turn Bt Off bt-reset-gpio(%d) value(%d)",
bt_reset_gpio, gpio_get_value(bt_reset_gpio));
if (bt_sw_ctrl_gpio >= 0) {
BT_PWR_INFO("BTON:Turn Bt Off");
@ -323,14 +384,12 @@ static int bt_configure_gpios(int on)
bt_power_src_status[BT_SW_CTRL_GPIO]);
}
rc = gpio_direction_output(bt_reset_gpio, 1);
rc = bt_enable_bt_reset_gpios_safely();
if (rc) {
BT_PWR_ERR("Unable to set direction\n");
return rc;
BT_PWR_ERR("%s:bt_enable_bt_reset_gpios_safely failed",
__func__);
}
bt_power_src_status[BT_RESET_GPIO] =
gpio_get_value(bt_reset_gpio);
msleep(50);
/* Check if SW_CTRL is asserted */
if (bt_sw_ctrl_gpio >= 0) {
@ -384,6 +443,18 @@ static int bt_configure_gpios(int on)
return rc;
}
static void bt_free_gpios(void)
{
if (bt_power_pdata->bt_gpio_sys_rst > 0)
gpio_free(bt_power_pdata->bt_gpio_sys_rst);
if (bt_power_pdata->wl_gpio_sys_rst > 0)
gpio_free(bt_power_pdata->wl_gpio_sys_rst);
if (bt_power_pdata->bt_gpio_sw_ctrl > 0)
gpio_free(bt_power_pdata->bt_gpio_sw_ctrl);
if (bt_power_pdata->bt_gpio_debug > 0)
gpio_free(bt_power_pdata->bt_gpio_debug);
}
static int bluetooth_power(int on)
{
int rc = 0;
@ -547,12 +618,9 @@ static int bluetooth_power(int on)
if (bt_power_pdata->bt_gpio_sys_rst > 0)
bt_configure_gpios(on);
gpio_fail:
if (bt_power_pdata->bt_gpio_sys_rst > 0)
gpio_free(bt_power_pdata->bt_gpio_sys_rst);
if (bt_power_pdata->bt_gpio_sw_ctrl > 0)
gpio_free(bt_power_pdata->bt_gpio_sw_ctrl);
if (bt_power_pdata->bt_gpio_debug > 0)
gpio_free(bt_power_pdata->bt_gpio_debug);
//Free Gpios
bt_free_gpios();
if (bt_power_pdata->bt_chip_clk)
bt_clk_disable(bt_power_pdata->bt_chip_clk);
clk_fail:
@ -821,6 +889,12 @@ static int bt_power_populate_dt_pinfo(struct platform_device *pdev)
if (bt_power_pdata->bt_gpio_sys_rst < 0)
BT_PWR_INFO("bt-reset-gpio not provided in devicetree");
bt_power_pdata->wl_gpio_sys_rst =
of_get_named_gpio(pdev->dev.of_node,
"qca,wl-reset-gpio", 0);
if (bt_power_pdata->wl_gpio_sys_rst < 0)
BT_PWR_INFO("wl-reset-gpio not provided in devicetree");
bt_power_pdata->bt_gpio_sw_ctrl =
of_get_named_gpio(pdev->dev.of_node,
"qca,bt-sw-ctrl-gpio", 0);

View file

@ -52,6 +52,8 @@ struct bluetooth_power_platform_data {
int bt_gpio_sys_rst;
/* Bluetooth sw_ctrl gpio */
int bt_gpio_sw_ctrl;
/* Wlan reset gpio */
int wl_gpio_sys_rst;
/* Bluetooth debug gpio */
int bt_gpio_debug;
struct device *slim_dev;