Add support for returning power sources status

This patch contains changes for returning power sources status
to BT HAL.

Change-Id: I042bbb92f4e4d7fd26edb35641e854be3fbb9389
Signed-off-by: priyankar <prigup@codeaurora.org>
This commit is contained in:
priyankar 2020-07-16 12:32:29 +05:30 committed by Gerrit - the friendly Code Review server
parent 6d9424d872
commit 1a4104b63a
2 changed files with 232 additions and 89 deletions

View file

@ -21,6 +21,7 @@
#include <linux/slab.h>
#include <linux/regulator/consumer.h>
#include <linux/clk.h>
#include <linux/uaccess.h>
#if defined(CONFIG_CNSS)
#include <net/cnss.h>
@ -36,6 +37,9 @@
#define BT_PWR_INFO(fmt, arg...) pr_info("%s: " fmt "\n", __func__, ## arg)
#define BT_PWR_ERR(fmt, arg...) pr_err("%s: " fmt "\n", __func__, ## arg)
#define PWR_SRC_NOT_AVAILABLE -2
#define DEFAULT_INVALID_VALUE -1
#define PWR_SRC_INIT_STATE_IDX 0
static const struct of_device_id bt_power_match_table[] = {
{ .compatible = "qca,ar3002" },
@ -46,6 +50,39 @@ static const struct of_device_id bt_power_match_table[] = {
{}
};
enum power_src_pos {
BT_RESET_GPIO = PWR_SRC_INIT_STATE_IDX,
BT_SW_CTRL_GPIO,
BT_VDD_AON_LDO,
BT_VDD_DIG_LDO,
BT_VDD_RFA1_LDO,
BT_VDD_RFA2_LDO,
BT_VDD_ASD_LDO,
BT_VDD_XTAL_LDO,
BT_VDD_PA_LDO,
BT_VDD_CORE_LDO,
BT_VDD_IO_LDO,
BT_VDD_LDO,
BT_VDD_RFA_0p8,
BT_VDD_RFACMN,
// these indexes GPIOs/regs value are fetched during crash.
BT_RESET_GPIO_CURRENT,
BT_SW_CTRL_GPIO_CURRENT,
BT_VDD_AON_LDO_CURRENT,
BT_VDD_DIG_LDO_CURRENT,
BT_VDD_RFA1_LDO_CURRENT,
BT_VDD_RFA2_LDO_CURRENT,
BT_VDD_ASD_LDO_CURRENT,
BT_VDD_XTAL_LDO_CURRENT,
BT_VDD_PA_LDO_CURRENT,
BT_VDD_CORE_LDO_CURRENT,
BT_VDD_IO_LDO_CURRENT,
BT_VDD_LDO_CURRENT,
BT_VDD_RFA_0p8_CURRENT,
BT_VDD_RFACMN_CURRENT
};
static int bt_power_src_status[BT_POWER_SRC_SIZE];
static struct bluetooth_power_platform_data *bt_power_pdata;
static struct platform_device *btpdev;
static bool previous;
@ -266,27 +303,34 @@ static int bt_configure_gpios(int on)
bt_reset_gpio, rc);
return rc;
}
rc = gpio_direction_output(bt_reset_gpio, 0);
if (rc) {
BT_PWR_ERR("Unable to set direction\n");
return rc;
}
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_reset_gpio, gpio_get_value(bt_reset_gpio));
if (bt_sw_ctrl_gpio >= 0) {
BT_PWR_INFO("BTON:Turn Bt Off");
bt_power_src_status[BT_SW_CTRL_GPIO] =
gpio_get_value(bt_sw_ctrl_gpio);
BT_PWR_INFO("bt-sw-ctrl-gpio(%d) value(%d)",
bt_sw_ctrl_gpio,
gpio_get_value(bt_sw_ctrl_gpio));
bt_power_src_status[BT_SW_CTRL_GPIO]);
}
rc = gpio_direction_output(bt_reset_gpio, 1);
if (rc) {
BT_PWR_ERR("Unable to set direction\n");
return rc;
}
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) {
@ -315,9 +359,11 @@ static int bt_configure_gpios(int on)
bt_reset_gpio, gpio_get_value(bt_reset_gpio));
if (bt_sw_ctrl_gpio >= 0) {
BT_PWR_INFO("BTON:Turn Bt On");
bt_power_src_status[BT_SW_CTRL_GPIO] =
gpio_get_value(bt_sw_ctrl_gpio);
BT_PWR_INFO("bt-sw-ctrl-gpio(%d) value(%d)",
bt_sw_ctrl_gpio,
gpio_get_value(bt_sw_ctrl_gpio));
bt_power_src_status[BT_SW_CTRL_GPIO]);
}
} else {
gpio_set_value(bt_reset_gpio, 0);
@ -341,80 +387,132 @@ static int bt_configure_gpios(int on)
static int bluetooth_power(int on)
{
int rc = 0;
struct regulator *reg = NULL;
BT_PWR_DBG("on: %d", on);
if (on == 1) {
// Power On
if (bt_power_pdata->bt_vdd_io) {
bt_power_src_status[BT_VDD_IO_LDO] =
DEFAULT_INVALID_VALUE;
rc = bt_configure_vreg(bt_power_pdata->bt_vdd_io);
if (rc < 0) {
BT_PWR_ERR("bt_power vddio config failed");
goto out;
}
reg = bt_power_pdata->bt_vdd_io->reg;
bt_power_src_status[BT_VDD_IO_LDO] =
regulator_get_voltage(reg);
}
if (bt_power_pdata->bt_vdd_xtal) {
bt_power_src_status[BT_VDD_XTAL_LDO] =
DEFAULT_INVALID_VALUE;
rc = bt_configure_vreg(bt_power_pdata->bt_vdd_xtal);
if (rc < 0) {
BT_PWR_ERR("bt_power vddxtal config failed");
goto vdd_xtal_fail;
}
reg = bt_power_pdata->bt_vdd_xtal->reg;
bt_power_src_status[BT_VDD_XTAL_LDO] =
regulator_get_voltage(reg);
}
if (bt_power_pdata->bt_vdd_core) {
bt_power_src_status[BT_VDD_CORE_LDO] =
DEFAULT_INVALID_VALUE;
rc = bt_configure_vreg(bt_power_pdata->bt_vdd_core);
if (rc < 0) {
BT_PWR_ERR("bt_power vddcore config failed");
goto vdd_core_fail;
}
reg = bt_power_pdata->bt_vdd_core->reg;
bt_power_src_status[BT_VDD_CORE_LDO] =
regulator_get_voltage(reg);
}
if (bt_power_pdata->bt_vdd_pa) {
bt_power_src_status[BT_VDD_PA_LDO] =
DEFAULT_INVALID_VALUE;
rc = bt_configure_vreg(bt_power_pdata->bt_vdd_pa);
if (rc < 0) {
BT_PWR_ERR("bt_power vddpa config failed");
goto vdd_pa_fail;
}
reg = bt_power_pdata->bt_vdd_pa->reg;
bt_power_src_status[BT_VDD_PA_LDO] =
regulator_get_voltage(reg);
}
if (bt_power_pdata->bt_vdd_ldo) {
bt_power_src_status[BT_VDD_LDO] =
DEFAULT_INVALID_VALUE;
rc = bt_configure_vreg(bt_power_pdata->bt_vdd_ldo);
if (rc < 0) {
BT_PWR_ERR("bt_power vddldo config failed");
goto vdd_ldo_fail;
}
reg = bt_power_pdata->bt_vdd_ldo->reg;
bt_power_src_status[BT_VDD_LDO] =
regulator_get_voltage(reg);
}
if (bt_power_pdata->bt_vdd_aon) {
bt_power_src_status[BT_VDD_AON_LDO] =
DEFAULT_INVALID_VALUE;
rc = bt_configure_vreg(bt_power_pdata->bt_vdd_aon);
if (rc < 0) {
BT_PWR_ERR("bt_power vddaon config failed");
goto vdd_aon_fail;
}
reg = bt_power_pdata->bt_vdd_aon->reg;
bt_power_src_status[BT_VDD_AON_LDO] =
regulator_get_voltage(reg);
}
if (bt_power_pdata->bt_vdd_dig) {
bt_power_src_status[BT_VDD_DIG_LDO] =
DEFAULT_INVALID_VALUE;
rc = bt_configure_vreg(bt_power_pdata->bt_vdd_dig);
if (rc < 0) {
BT_PWR_ERR("bt_power vdddig config failed");
goto vdd_dig_fail;
}
reg = bt_power_pdata->bt_vdd_dig->reg;
bt_power_src_status[BT_VDD_DIG_LDO] =
regulator_get_voltage(reg);
}
if (bt_power_pdata->bt_vdd_rfa1) {
bt_power_src_status[BT_VDD_RFA1_LDO] =
DEFAULT_INVALID_VALUE;
rc = bt_configure_vreg(bt_power_pdata->bt_vdd_rfa1);
if (rc < 0) {
BT_PWR_ERR("bt_power vddrfa1 config failed");
goto vdd_rfa1_fail;
}
reg = bt_power_pdata->bt_vdd_rfa1->reg;
bt_power_src_status[BT_VDD_RFA1_LDO] =
regulator_get_voltage(reg);
}
if (bt_power_pdata->bt_vdd_rfa2) {
bt_power_src_status[BT_VDD_RFA2_LDO] =
DEFAULT_INVALID_VALUE;
rc = bt_configure_vreg(bt_power_pdata->bt_vdd_rfa2);
if (rc < 0) {
BT_PWR_ERR("bt_power vddrfa2 config failed");
goto vdd_rfa2_fail;
}
reg = bt_power_pdata->bt_vdd_rfa2->reg;
bt_power_src_status[BT_VDD_RFA2_LDO] =
regulator_get_voltage(reg);
}
if (bt_power_pdata->bt_vdd_asd) {
bt_power_src_status[BT_VDD_ASD_LDO] =
DEFAULT_INVALID_VALUE;
rc = bt_configure_vreg(bt_power_pdata->bt_vdd_asd);
if (rc < 0) {
BT_PWR_ERR("bt_power vddasd config failed");
goto vdd_asd_fail;
}
reg = bt_power_pdata->bt_vdd_asd->reg;
bt_power_src_status[BT_VDD_ASD_LDO] =
regulator_get_voltage(reg);
}
if (bt_power_pdata->bt_chip_pwd) {
rc = bt_configure_vreg(bt_power_pdata->bt_chip_pwd);
@ -434,6 +532,10 @@ static int bluetooth_power(int on)
}
}
if (bt_power_pdata->bt_gpio_sys_rst > 0) {
bt_power_src_status[BT_RESET_GPIO] =
DEFAULT_INVALID_VALUE;
bt_power_src_status[BT_SW_CTRL_GPIO] =
DEFAULT_INVALID_VALUE;
rc = bt_configure_gpios(on);
if (rc < 0) {
BT_PWR_ERR("bt_power gpio config failed");
@ -730,59 +832,94 @@ static int bt_power_populate_dt_pinfo(struct platform_device *pdev)
rc = bt_dt_parse_vreg_info(&pdev->dev,
&bt_power_pdata->bt_vdd_core,
"qca,bt-vdd-core");
if (rc < 0)
goto err;
rc = bt_dt_parse_vreg_info(&pdev->dev,
&bt_power_pdata->bt_vdd_io,
"qca,bt-vdd-io");
if (rc < 0)
goto err;
rc = bt_dt_parse_vreg_info(&pdev->dev,
&bt_power_pdata->bt_vdd_xtal,
"qca,bt-vdd-xtal");
if (rc < 0)
goto err;
rc = bt_dt_parse_vreg_info(&pdev->dev,
&bt_power_pdata->bt_vdd_pa,
"qca,bt-vdd-pa");
if (rc < 0)
goto err;
rc = bt_dt_parse_vreg_info(&pdev->dev,
&bt_power_pdata->bt_vdd_ldo,
"qca,bt-vdd-ldo");
if (rc < 0)
goto err;
rc = bt_dt_parse_vreg_info(&pdev->dev,
&bt_power_pdata->bt_chip_pwd,
"qca,bt-chip-pwd");
if (rc < 0)
goto err;
rc = bt_dt_parse_vreg_info(&pdev->dev,
&bt_power_pdata->bt_vdd_aon,
"qca,bt-vdd-aon");
if (rc < 0)
goto err;
rc = bt_dt_parse_vreg_info(&pdev->dev,
&bt_power_pdata->bt_vdd_dig,
"qca,bt-vdd-dig");
if (rc < 0)
goto err;
rc = bt_dt_parse_vreg_info(&pdev->dev,
&bt_power_pdata->bt_vdd_rfa1,
"qca,bt-vdd-rfa1");
if (rc < 0)
goto err;
rc = bt_dt_parse_vreg_info(&pdev->dev,
&bt_power_pdata->bt_vdd_rfa2,
"qca,bt-vdd-rfa2");
if (rc < 0)
goto err;
rc = bt_dt_parse_vreg_info(&pdev->dev,
&bt_power_pdata->bt_vdd_asd,
"qca,bt-vdd-asd");
if (rc < 0)
goto err;
rc = bt_dt_parse_clk_info(&pdev->dev,
&bt_power_pdata->bt_chip_clk);
if (rc < 0)
goto err;
}
bt_power_pdata->bt_power_setup = bluetooth_power;
return 0;
err:
BT_PWR_ERR("%s: Failed with err code: %d",
__func__, rc);
return rc;
}
static int bt_power_probe(struct platform_device *pdev)
{
int ret = 0;
int itr;
/* Fill whole array with -2 i.e NOT_AVAILABLE state by default
* for any GPIO or Reg handle.
*/
for (itr = PWR_SRC_INIT_STATE_IDX;
itr < BT_POWER_SRC_SIZE; ++itr)
bt_power_src_status[itr] = PWR_SRC_NOT_AVAILABLE;
dev_dbg(&pdev->dev, "%s\n", __func__);
@ -873,11 +1010,41 @@ int bt_disable_asd(void)
return rc;
}
static void set_pwr_srcs_status(int ldo_index,
struct bt_power_vreg_data *handle)
{
if (handle) {
bt_power_src_status[ldo_index] = DEFAULT_INVALID_VALUE;
if (handle->is_enabled && regulator_is_enabled(handle->reg)) {
bt_power_src_status[ldo_index] =
(int)regulator_get_voltage(handle->reg);
BT_PWR_ERR("%s(%d) value(%d)", handle->name,
handle, bt_power_src_status[ldo_index]);
} else {
BT_PWR_ERR("%s: %s is_enabled %d", __func__,
handle->name, handle->is_enabled);
}
}
}
static void set_gpios_srcs_status(char *gpio_name,
int gpio_index, int handle)
{
if (handle >= 0) {
bt_power_src_status[gpio_index] = DEFAULT_INVALID_VALUE;
bt_power_src_status[gpio_index] = gpio_get_value(handle);
BT_PWR_ERR("%s(%d) value(%d)", gpio_name,
handle, bt_power_src_status[gpio_index]);
} else {
BT_PWR_ERR("%s: %s not configured",
__func__, gpio_name);
}
}
static long bt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
int ret = 0, pwr_cntrl = 0;
int chipset_version = 0;
long value = -1;
switch (cmd) {
case BT_CMD_SLIM_TEST:
@ -919,88 +1086,62 @@ static long bt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
soc_id = 0;
}
break;
case BT_CMD_GETVAL_RESET_GPIO:
if (bt_power_pdata->bt_gpio_sys_rst > 0) {
value = (long)gpio_get_value(
bt_power_pdata->bt_gpio_sys_rst);
BT_PWR_ERR("GET_RESET_GPIO(%d) value(%d)",
bt_power_pdata->bt_gpio_sys_rst, value);
ret = value;
} else {
BT_PWR_ERR("RESET_GPIO not configured");
ret = -EINVAL;
}
break;
case BT_CMD_GETVAL_SW_CTRL_GPIO:
if (bt_power_pdata->bt_gpio_sw_ctrl > 0) {
value = (long)gpio_get_value(
case BT_CMD_CHECK_SW_CTRL:
BT_PWR_INFO("BT_CMD_CHECK_SW_CTRL");
/* Check if SW_CTRL is asserted */
if (bt_power_pdata->bt_gpio_sw_ctrl > 0) {
bt_power_src_status[BT_SW_CTRL_GPIO] =
DEFAULT_INVALID_VALUE;
ret = gpio_direction_input(
bt_power_pdata->bt_gpio_sw_ctrl);
BT_PWR_ERR("GET_SWCTRL_GPIO(%d) value(%d)",
bt_power_pdata->bt_gpio_sw_ctrl, value);
ret = value;
if (ret) {
BT_PWR_ERR("%s:gpio_direction_input api",
__func__);
BT_PWR_ERR("%s:failed for SW_CTRL:%d",
__func__, ret);
} else {
bt_power_src_status[BT_SW_CTRL_GPIO] =
gpio_get_value(
bt_power_pdata->bt_gpio_sw_ctrl);
BT_PWR_INFO("bt-sw-ctrl-gpio(%d) value(%d)",
bt_power_pdata->bt_gpio_sw_ctrl,
bt_power_src_status[BT_SW_CTRL_GPIO]);
}
} else {
BT_PWR_ERR("SW_CTRL_GPIO not configured");
ret = -EINVAL;
BT_PWR_ERR("bt_gpio_sw_ctrl not configured");
return -EINVAL;
}
break;
case BT_CMD_GETVAL_VDD_AON_LDO:
if ((bt_power_pdata->bt_vdd_aon) &&
(bt_power_pdata->bt_vdd_aon->is_enabled) &&
(regulator_is_enabled(
bt_power_pdata->bt_vdd_aon->reg))) {
value = (int)regulator_get_voltage(
bt_power_pdata->bt_vdd_aon->reg);
BT_PWR_ERR("GET_VDD_AON_LDO(%d) value(%d)",
bt_power_pdata->bt_vdd_aon, value);
ret = value;
} else {
BT_PWR_ERR("VDD-AON_LDO not configure/enabled");
ret = -EINVAL;
}
break;
case BT_CMD_GETVAL_VDD_DIG_LDO:
if ((bt_power_pdata->bt_vdd_dig) &&
(bt_power_pdata->bt_vdd_dig->is_enabled) &&
(regulator_is_enabled(
bt_power_pdata->bt_vdd_dig->reg))) {
value = (int)regulator_get_voltage(
bt_power_pdata->bt_vdd_dig->reg);
BT_PWR_ERR("GET_VDD_DIG_LDO(%d) value(%d)",
bt_power_pdata->bt_vdd_dig, value);
ret = value;
} else {
BT_PWR_ERR("VDD-DIG-LDO not configured/enabled");
ret = -EINVAL;
}
break;
case BT_CMD_GETVAL_VDD_RFA1_LDO:
if ((bt_power_pdata->bt_vdd_rfa1) &&
(bt_power_pdata->bt_vdd_rfa1->is_enabled) &&
(regulator_is_enabled(
bt_power_pdata->bt_vdd_rfa1->reg))) {
value = (int)regulator_get_voltage(
bt_power_pdata->bt_vdd_rfa1->reg);
BT_PWR_ERR("GET_VDD_RFA1_LDO(%d) value(%d)",
bt_power_pdata->bt_vdd_rfa1, value);
ret = value;
} else {
BT_PWR_ERR("VDD-RFA1-LDO not configure/enabled");
ret = -EINVAL;
}
break;
case BT_CMD_GETVAL_VDD_RFA2_LDO:
if ((bt_power_pdata->bt_vdd_rfa2) &&
(bt_power_pdata->bt_vdd_rfa2->is_enabled) &&
(regulator_is_enabled(
bt_power_pdata->bt_vdd_rfa2->reg))) {
value = (int)regulator_get_voltage(
bt_power_pdata->bt_vdd_rfa2->reg);
BT_PWR_ERR("GET_VDD_RFA2_LDO(%d) value(%d)",
bt_power_pdata->bt_vdd_rfa2, value);
ret = value;
} else {
BT_PWR_ERR("VDD-RFA2-LDO not configure/enabled");
ret = -EINVAL;
case BT_CMD_GETVAL_POWER_SRCS:
BT_PWR_ERR("BT_CMD_GETVAL_POWER_SRCS");
set_gpios_srcs_status("BT_RESET_GPIO", BT_RESET_GPIO_CURRENT,
bt_power_pdata->bt_gpio_sys_rst);
set_gpios_srcs_status("SW_CTRL_GPIO", BT_SW_CTRL_GPIO_CURRENT,
bt_power_pdata->bt_gpio_sw_ctrl);
set_pwr_srcs_status(BT_VDD_AON_LDO_CURRENT,
bt_power_pdata->bt_vdd_aon);
set_pwr_srcs_status(BT_VDD_DIG_LDO_CURRENT,
bt_power_pdata->bt_vdd_dig);
set_pwr_srcs_status(BT_VDD_RFA1_LDO_CURRENT,
bt_power_pdata->bt_vdd_rfa1);
set_pwr_srcs_status(BT_VDD_RFA2_LDO_CURRENT,
bt_power_pdata->bt_vdd_rfa2);
set_pwr_srcs_status(BT_VDD_ASD_LDO_CURRENT,
bt_power_pdata->bt_vdd_asd);
set_pwr_srcs_status(BT_VDD_IO_LDO_CURRENT,
bt_power_pdata->bt_vdd_io);
set_pwr_srcs_status(BT_VDD_XTAL_LDO_CURRENT,
bt_power_pdata->bt_vdd_xtal);
set_pwr_srcs_status(BT_VDD_CORE_LDO_CURRENT,
bt_power_pdata->bt_vdd_core);
set_pwr_srcs_status(BT_VDD_PA_LDO_CURRENT,
bt_power_pdata->bt_vdd_pa);
set_pwr_srcs_status(BT_VDD_LDO_CURRENT,
bt_power_pdata->bt_vdd_ldo);
if (copy_to_user((void __user *)arg,
bt_power_src_status, sizeof(bt_power_src_status))) {
BT_PWR_ERR("%s: copy to user failed\n", __func__);
ret = -EFAULT;
}
break;
default:

View file

@ -93,10 +93,12 @@ int get_chipset_version(void);
#define BT_CMD_SLIM_TEST 0xbfac
#define BT_CMD_PWR_CTRL 0xbfad
#define BT_CMD_CHIPSET_VERS 0xbfae
#define BT_CMD_GETVAL_RESET_GPIO 0xbfb5
#define BT_CMD_GETVAL_SW_CTRL_GPIO 0xbfb0
#define BT_CMD_GETVAL_VDD_AON_LDO 0xbfb1
#define BT_CMD_GETVAL_VDD_DIG_LDO 0xbfb2
#define BT_CMD_GETVAL_VDD_RFA1_LDO 0xbfb3
#define BT_CMD_GETVAL_VDD_RFA2_LDO 0xbfb4
/* 0xbfaf --> reserved for kernel 5.4 */
#define BT_CMD_CHECK_SW_CTRL 0xbfb0
#define BT_CMD_GETVAL_POWER_SRCS 0xbfb1
/* total number of power src */
#define BT_POWER_SRC_SIZE 28
#endif /* __LINUX_BLUETOOTH_POWER_H */