Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e540b89d authored by priyankar's avatar priyankar
Browse files

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: default avatarpriyankar <prigup@codeaurora.org>
parent 83d4e2a3
Loading
Loading
Loading
Loading
+172 −83
Original line number Diff line number Diff line
@@ -32,27 +32,75 @@
#endif
#include <linux/fs.h>

#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;

	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;
	int ldo_index;

	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);
			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_debug("%s:GET_SWCTRL_GPIO(%d) value(%d)\n",
				pr_info("bt-sw-ctrl-gpio(%d) value(%d)\n",
					bt_power_pdata->bt_gpio_sw_ctrl,
					__func__, value);
			ret = value;
					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__);
+13 −7
Original line number Diff line number Diff line
@@ -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 {
@@ -67,13 +73,13 @@ int btpower_get_chipset_version(void);
#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_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 */