From e540b89dd61cf4fcc21f123bd0faeb142aaf229b Mon Sep 17 00:00:00 2001 From: priyankar Date: Wed, 29 Jul 2020 18:36:10 +0530 Subject: [PATCH] Add support for returning power sources status This patch contains changes for returning power sources status to BT HAL and also setting value of SW CTRL for CHE chip. Change-Id: I8a0349171a5bbd516b098cc5a070804a454c2b7d Signed-off-by: priyankar --- drivers/bluetooth/btpower.c | 253 ++++++++++++++++++++++++------------ include/linux/btpower.h | 20 ++- 2 files changed, 184 insertions(+), 89 deletions(-) diff --git a/drivers/bluetooth/btpower.c b/drivers/bluetooth/btpower.c index 9518e5694fa4..6992fdd542c1 100644 --- a/drivers/bluetooth/btpower.c +++ b/drivers/bluetooth/btpower.c @@ -32,27 +32,75 @@ #endif #include +#define PWR_SRC_NOT_AVAILABLE -2 +#define DEFAULT_INVALID_VALUE -1 +#define PWR_SRC_INIT_STATE_IDX 0 + +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 +}; + // Regulator structure for QCA6390 and QCA6490 BT SoC series static struct bt_power_vreg_data bt_vregs_info_qca6x9x[] = { - {NULL, "qcom,bt-vdd-io", 1800000, 1800000, 0, false, true}, - {NULL, "qcom,bt-vdd-aon", 950000, 950000, 0, false, true}, - {NULL, "qcom,bt-vdd-rfacmn", 950000, 950000, 0, false, true}, + {NULL, "qcom,bt-vdd-io", 1800000, 1800000, 0, false, true, + {BT_VDD_IO_LDO, BT_VDD_IO_LDO_CURRENT}}, + {NULL, "qcom,bt-vdd-aon", 950000, 950000, 0, false, true, + {BT_VDD_AON_LDO, BT_VDD_AON_LDO_CURRENT}}, + {NULL, "qcom,bt-vdd-rfacmn", 950000, 950000, 0, false, true, + {BT_VDD_RFACMN, BT_VDD_RFACMN_CURRENT}}, /* BT_CX_MX */ - {NULL, "qcom,bt-vdd-dig", 950000, 952000, 0, false, true}, - {NULL, "qcom,bt-vdd-rfa-0p8", 950000, 952000, 0, false, true}, - {NULL, "qcom,bt-vdd-rfa1", 1900000, 1900000, 0, false, true}, - {NULL, "qcom,bt-vdd-rfa2", 1900000, 1900000, 0, false, true}, - {NULL, "qcom,bt-vdd-asd", 2800000, 2800000, 0, false, true}, + {NULL, "qcom,bt-vdd-dig", 950000, 952000, 0, false, true, + {BT_VDD_DIG_LDO, BT_VDD_DIG_LDO_CURRENT}}, + {NULL, "qcom,bt-vdd-rfa-0p8", 950000, 952000, 0, false, true, + {BT_VDD_RFA_0p8, BT_VDD_RFA_0p8_CURRENT}}, + {NULL, "qcom,bt-vdd-rfa1", 1900000, 1900000, 0, false, true, + {BT_VDD_RFA1_LDO, BT_VDD_RFA1_LDO_CURRENT}}, + {NULL, "qcom,bt-vdd-rfa2", 1900000, 1900000, 0, false, true, + {BT_VDD_RFA2_LDO, BT_VDD_RFA2_LDO_CURRENT}}, + {NULL, "qcom,bt-vdd-asd", 2800000, 2800000, 0, false, true, + {BT_VDD_ASD_LDO, BT_VDD_ASD_LDO_CURRENT}}, }; // Regulator structure for WCN399x BT SoC series static struct bt_power bt_vreg_info_wcn399x = { .compatible = "qcom,wcn3990", .vregs = (struct bt_power_vreg_data []) { - {NULL, "qcom,bt-vdd-io", 1700000, 1900000, 0, false, false}, - {NULL, "qcom,bt-vdd-core", 1304000, 1304000, 0, false, false}, - {NULL, "qcom,bt-vdd-pa", 3000000, 3312000, 0, false, false}, - {NULL, "qcom,bt-vdd-xtal", 1700000, 1900000, 0, false, false}, + {NULL, "qcom,bt-vdd-io", 1700000, 1900000, 0, false, false, + {BT_VDD_IO_LDO, BT_VDD_IO_LDO_CURRENT}}, + {NULL, "qcom,bt-vdd-core", 1304000, 1304000, 0, false, false, + {BT_VDD_CORE_LDO, BT_VDD_CORE_LDO_CURRENT}}, + {NULL, "qcom,bt-vdd-pa", 3000000, 3312000, 0, false, false, + {BT_VDD_PA_LDO, BT_VDD_PA_LDO_CURRENT}}, + {NULL, "qcom,bt-vdd-xtal", 1700000, 1900000, 0, false, false, + {BT_VDD_XTAL_LDO, BT_VDD_XTAL_LDO_CURRENT}}, }, .num_vregs = 4, }; @@ -83,6 +131,7 @@ static int btpower_get_tcs_table_info(struct platform_device *plat_dev, static int btpower_enable_ipa_vreg(struct platform_device *plat_dev, struct bluetooth_power_platform_data *bt_power_pdata); +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; @@ -265,14 +314,18 @@ static int bt_configure_gpios(int on) pr_err("%s: Unable to set direction\n", __func__); return rc; } + bt_power_src_status[BT_RESET_GPIO] = + gpio_get_value(bt_reset_gpio); msleep(50); - pr_debug("BTON:Turn Bt Off bt-reset-gpio(%d) value(%d)\n", + pr_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) { - pr_debug("BTON:Turn Bt Off\n"); - pr_debug("bt-sw-ctrl-gpio(%d) value(%d)\n", + pr_info("BTON:Turn Bt Off\n"); + bt_power_src_status[BT_SW_CTRL_GPIO] = + gpio_get_value(bt_sw_ctrl_gpio); + pr_info("bt-sw-ctrl-gpio(%d) value(%d)\n", 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); @@ -280,6 +333,8 @@ static int bt_configure_gpios(int on) pr_err("%s: Unable to set direction\n", __func__); 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) { @@ -307,24 +362,26 @@ 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_debug("BTON:Turn Bt On\n"); - pr_debug("bt-sw-ctrl-gpio(%d) value(%d)\n", + pr_info("BTON:Turn Bt On\n"); + bt_power_src_status[BT_SW_CTRL_GPIO] = + gpio_get_value(bt_sw_ctrl_gpio); + pr_info("bt-sw-ctrl-gpio(%d) value(%d)\n", 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); msleep(100); - pr_debug("BT-OFF:bt-reset-gpio(%d) value(%d)\n", + pr_info("BT-OFF:bt-reset-gpio(%d) value(%d)\n", bt_reset_gpio, gpio_get_value(bt_reset_gpio)); if (bt_sw_ctrl_gpio >= 0) { - pr_debug("BT-OFF:bt-sw-ctrl-gpio(%d) value(%d)\n", + pr_info("BT-OFF:bt-sw-ctrl-gpio(%d) value(%d)\n", bt_sw_ctrl_gpio, gpio_get_value(bt_sw_ctrl_gpio)); } } - pr_debug("%s: bt_gpio= %d on: %d\n", __func__, bt_reset_gpio, on); + pr_info("%s: bt_gpio= %d on: %d\n", __func__, bt_reset_gpio, on); return rc; } @@ -354,6 +411,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) { pr_err("%s: bt_power gpio config failed\n", @@ -585,16 +646,25 @@ static int bt_power_vreg_get(struct platform_device *pdev) static int bt_power_vreg_set(enum bt_power_modes mode) { int num_vregs, i = 0, ret = 0; + int log_indx; struct bt_power_vreg_data *vreg_info = NULL; num_vregs = bt_power_pdata->num_vregs; if (mode == BT_POWER_ENABLE) { for (; i < num_vregs; i++) { vreg_info = &bt_power_pdata->vreg_info[i]; + log_indx = vreg_info->indx.init; if (vreg_info->reg) { + bt_power_src_status[log_indx] = + DEFAULT_INVALID_VALUE; ret = bt_vreg_enable(vreg_info); if (ret < 0) goto out; + if (vreg_info->is_enabled) { + bt_power_src_status[log_indx] = + regulator_get_voltage( + vreg_info->reg); + } } } } else if (mode == BT_POWER_DISABLE) { @@ -677,9 +747,17 @@ static int bt_power_populate_dt_pinfo(struct platform_device *pdev) static int bt_power_probe(struct platform_device *pdev) { int ret = 0; + int itr; pr_debug("%s\n", __func__); + /* 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; + bt_power_pdata = kzalloc(sizeof(*bt_power_pdata), GFP_KERNEL); if (!bt_power_pdata) @@ -754,46 +832,51 @@ int btpower_get_chipset_version(void) } EXPORT_SYMBOL(btpower_get_chipset_version); -static long get_resource_value(char *res_name) +static void set_pwr_srcs_status(struct bt_power_vreg_data *handle) { - int ret = 0; - int i = 0; - long value = -1; - struct bt_power_vreg_data *vreg; - int num_vregs = bt_power_pdata->num_vregs; + int ldo_index; - for (; i < num_vregs; i++) { - vreg = &bt_power_pdata->vreg_info[i]; - - if (!vreg->reg) - continue; - else { - if (strnstr(vreg->name, res_name, - strlen(vreg->name))) - break; - } - } - if (i < num_vregs) { - if (regulator_is_enabled(vreg->reg)) { - value = (int)regulator_get_voltage(vreg->reg); - pr_debug("%s:%s value(%d)\n", - __func__, res_name, value); - ret = value; + if (handle) { + ldo_index = handle->indx.crash; + 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); + pr_err("%s(%d) value(%d)\n", handle->name, + handle, bt_power_src_status[ldo_index]); } else { - pr_err("%s:%s not configure/enabled\n", - __func__, res_name); - ret = -EINVAL; + pr_err("%s:%s is_enabled: %d\n", + __func__, handle->name, + handle->is_enabled); } } +} - return ret; +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); + pr_err("%s(%d) value(%d)\n", gpio_name, + handle, bt_power_src_status[gpio_index]); + } else { + pr_err("%s: %s not configured\n", + __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; + int itr, num_vregs; + struct bt_power_vreg_data *vreg_info = NULL; + switch (cmd) { case BT_CMD_SLIM_TEST: #if (defined CONFIG_BT_SLIM_QCA6390 || \ @@ -840,43 +923,49 @@ static long bt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ret = -EFAULT; } 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); - pr_debug("%s:GET_RESET_GPIO(%d) value(%d)\n", - bt_power_pdata->bt_gpio_sys_rst, - __func__, value); - ret = value; - } else { - pr_err("%s: RESET_GPIO not configured\n", __func__); - ret = -EINVAL; - } - break; - case BT_CMD_GETVAL_SW_CTRL_GPIO: + case BT_CMD_CHECK_SW_CTRL: + /* Check if SW_CTRL is asserted */ + pr_info("BT_CMD_CHECK_SW_CTRL\n"); if (bt_power_pdata->bt_gpio_sw_ctrl > 0) { - value = (long)gpio_get_value( + bt_power_src_status[BT_SW_CTRL_GPIO] = + DEFAULT_INVALID_VALUE; + ret = gpio_direction_input( bt_power_pdata->bt_gpio_sw_ctrl); - pr_debug("%s:GET_SWCTRL_GPIO(%d) value(%d)\n", - bt_power_pdata->bt_gpio_sw_ctrl, - __func__, value); - ret = value; + if (ret) { + pr_err("%s:gpio_direction_input api\n", + __func__); + pr_err("%s:failed for SW_CTRL:%d\n", + __func__, ret); + } else { + bt_power_src_status[BT_SW_CTRL_GPIO] = + gpio_get_value( + bt_power_pdata->bt_gpio_sw_ctrl); + pr_info("bt-sw-ctrl-gpio(%d) value(%d)\n", + bt_power_pdata->bt_gpio_sw_ctrl, + bt_power_src_status[BT_SW_CTRL_GPIO]); + } } else { - pr_err("%s:SW_CTRL_GPIO not configured\n", __func__); - ret = -EINVAL; + pr_err("bt_gpio_sw_ctrl not configured\n"); + return -EINVAL; } break; - case BT_CMD_GETVAL_VDD_AON_LDO: - ret = get_resource_value("vdd-aon"); - break; - case BT_CMD_GETVAL_VDD_DIG_LDO: - ret = get_resource_value("vdd-dig"); - break; - case BT_CMD_GETVAL_VDD_RFA1_LDO: - ret = get_resource_value("vdd-rfa1"); - break; - case BT_CMD_GETVAL_VDD_RFA2_LDO: - ret = get_resource_value("vdd-rfa2"); + case BT_CMD_GETVAL_POWER_SRCS: + pr_err("BT_CMD_GETVAL_POWER_SRCS\n"); + 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); + + num_vregs = bt_power_pdata->num_vregs; + for (itr = 0; itr < num_vregs; itr++) { + vreg_info = &bt_power_pdata->vreg_info[itr]; + set_pwr_srcs_status(vreg_info); + } + if (copy_to_user((void __user *)arg, + bt_power_src_status, sizeof(bt_power_src_status))) { + pr_err("%s: copy to user failed\n", __func__); + ret = -EFAULT; + } break; case BT_CMD_SET_IPA_TCS_INFO: pr_err("%s: BT_CMD_SET_IPA_TCS_INFO\n", __func__); diff --git a/include/linux/btpower.h b/include/linux/btpower.h index e372e6dba75e..84deb2361738 100644 --- a/include/linux/btpower.h +++ b/include/linux/btpower.h @@ -18,6 +18,11 @@ enum bt_power_modes { BT_POWER_RETENTION }; +struct log_index { + int init; + int crash; +}; + struct bt_power_vreg_data { struct regulator *reg; /* voltage regulator handle */ const char *name; /* regulator name */ @@ -26,6 +31,7 @@ struct bt_power_vreg_data { u32 load_curr; /* current */ bool is_enabled; /* is this regulator enabled? */ bool is_retention_supp; /* does this regulator support retention mode */ + struct log_index indx; /* Index for reg. w.r.t init & crash */ }; struct bt_power { @@ -66,14 +72,14 @@ int btpower_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_GET_CHIPSET_ID 0xbfaf -#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 +#define BT_CMD_GET_CHIPSET_ID 0xbfaf +#define BT_CMD_CHECK_SW_CTRL 0xbfb0 +#define BT_CMD_GETVAL_POWER_SRCS 0xbfb1 #define BT_CMD_SET_IPA_TCS_INFO 0xbfc0 + #define TCS_CMD_IO_ADDR_OFFSET 0x4 +/* total number of power src */ +#define BT_POWER_SRC_SIZE 28 + #endif /* __LINUX_BLUETOOTH_POWER_H */