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

Commit 83d4e2a3 authored by Mahesh Kumar Sharma's avatar Mahesh Kumar Sharma Committed by Gerrit - the friendly Code Review server
Browse files

Bluetooth: Update TCS content table based on PA config



When BT is turned ON on a platform using external power
amplifier(xPA), default voting ON of S3E buck results in
PMIC crash.
Solution is to disable S3E by default in AOP and enable it
dynamically based on the power amplifier confifuration
read from NVM. Handle IOCTL call for setting power
amplifier configuration from BT power driver.

Change-Id: Ibe7ef17481e33456c4692d0820ff44d9f43995de
Signed-off-by: default avatarMahesh Kumar Sharma <smahesh@codeaurora.org>
parent c0410e7e
Loading
Loading
Loading
Loading
+83 −1
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include <linux/uaccess.h>
#include <linux/btpower.h>
#include <linux/of_device.h>
#include <soc/qcom/cmd-db.h>

#if defined CONFIG_BT_SLIM_QCA6390 || \
	defined CONFIG_BT_SLIM_QCA6490 || \
@@ -77,6 +78,10 @@ static const struct of_device_id bt_power_match_table[] = {
};

static int bt_power_vreg_set(enum bt_power_modes mode);
static int btpower_get_tcs_table_info(struct platform_device *plat_dev,
			struct bluetooth_power_platform_data *bt_power_pdata);
static int btpower_enable_ipa_vreg(struct platform_device *plat_dev,
			struct bluetooth_power_platform_data *bt_power_pdata);

static struct bluetooth_power_platform_data *bt_power_pdata;
static struct platform_device *btpdev;
@@ -708,6 +713,8 @@ static int bt_power_probe(struct platform_device *pdev)
		goto free_pdata;

	btpdev = pdev;
	if (btpower_get_tcs_table_info(pdev, bt_power_pdata) < 0)
		pr_err("%s: Failed to get TCS table info\n", __func__);

	return 0;

@@ -787,7 +794,6 @@ 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:
#if (defined CONFIG_BT_SLIM_QCA6390 || \
@@ -872,6 +878,10 @@ static long bt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
	case BT_CMD_GETVAL_VDD_RFA2_LDO:
		ret = get_resource_value("vdd-rfa2");
		break;
	case BT_CMD_SET_IPA_TCS_INFO:
		pr_err("%s: BT_CMD_SET_IPA_TCS_INFO\n", __func__);
		btpower_enable_ipa_vreg(btpdev, bt_power_pdata);
		break;
	default:
		return -ENOIOCTLCMD;
	}
@@ -935,6 +945,78 @@ static int __init bluetooth_power_init(void)
	return ret;
}

static int btpower_get_tcs_table_info(struct platform_device *dev,
			struct bluetooth_power_platform_data *bt_power_pdata)
{
	struct platform_device *plat_dev = dev;
	struct btpower_tcs_table_info *tcs_table_info =
			&bt_power_pdata->tcs_table_info;
	struct resource *res;
	resource_size_t addr_len;
	void __iomem *tcs_cmd_base_addr;
	int ret = -1;

	res = platform_get_resource_byname(plat_dev, IORESOURCE_MEM, "tcs_cmd");
	if (!res) {
		pr_err("No TCS CMD entry found in DTSI\n");
		goto out;
	}

	tcs_table_info->tcs_cmd_base_addr = res->start;
	addr_len = resource_size(res);
	pr_info("TCS CMD base address is %pa with length %pa\n",
		    &tcs_table_info->tcs_cmd_base_addr, &addr_len);

	tcs_cmd_base_addr = devm_ioremap_resource(&plat_dev->dev, res);
	if (IS_ERR(tcs_cmd_base_addr)) {
		ret = PTR_ERR(tcs_cmd_base_addr);
		pr_err("Failed to map TCS CMD address, err = %d\n",
			    ret);
		goto out;
	}

	tcs_table_info->tcs_cmd_base_addr_io = tcs_cmd_base_addr;

	return 0;

out:
	return ret;
}

static int btpower_enable_ipa_vreg(struct platform_device *dev,
			struct bluetooth_power_platform_data *bt_power_pdata)
{
	struct platform_device *plat_dev = dev;
	struct btpower_tcs_table_info *tcs_table_info =
					&bt_power_pdata->tcs_table_info;
	u32 offset, addr_val, data_val;
	void __iomem *tcs_cmd;
	int ret = 0;

	if (!tcs_table_info->tcs_cmd_base_addr_io) {
		pr_err("TCS command not configured\n");
		return -EINVAL;
	}

	ret = of_property_read_u32(plat_dev->dev.of_node,
					"qcom,tcs_offset_ipa",
					&offset);
	if (ret) {
		pr_err("iPA failed to configure\n");
		return -EINVAL;
	}
	tcs_cmd = tcs_table_info->tcs_cmd_base_addr_io + offset;
	addr_val = readl_relaxed(tcs_cmd);
	tcs_cmd += TCS_CMD_IO_ADDR_OFFSET;

	writel_relaxed(1, tcs_cmd);

	data_val = readl_relaxed(tcs_cmd);
	pr_info("Configure S3E TCS Addr : %x with Data: %d\n"
		, addr_val, data_val);
	return 0;
}

static void __exit bluetooth_power_exit(void)
{
	platform_driver_unregister(&bt_power_driver);
+8 −0
Original line number Diff line number Diff line
@@ -40,6 +40,10 @@ struct bt_power_clk_data {
	bool is_enabled;  /* is this clock enabled? */
};

struct btpower_tcs_table_info {
	resource_size_t tcs_cmd_base_addr;
	void __iomem *tcs_cmd_base_addr_io;
};
/*
 * Platform data for the bluetooth power driver.
 */
@@ -53,6 +57,7 @@ struct bluetooth_power_platform_data {
	int (*bt_power_setup)(int id); /* Bluetooth power setup function */
	char compatible[32]; /*Bluetooth SoC name */
	int num_vregs;
	struct btpower_tcs_table_info tcs_table_info;
};

int btpower_register_slimdev(struct device *dev);
@@ -68,4 +73,7 @@ int btpower_get_chipset_version(void);
#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_SET_IPA_TCS_INFO  0xbfc0
#define TCS_CMD_IO_ADDR_OFFSET 0x4

#endif /* __LINUX_BLUETOOTH_POWER_H */