Kaynağa Gözat

BT: Add support for kalama target

Adds voltage regulators info needed for powering on BT chipset.

Change-Id: I5f281c88b3f94a9899396ad38b81f2970e91a054
Signed-off-by: satish kumar sugasi <[email protected]>
satish kumar sugasi 3 yıl önce
ebeveyn
işleme
cc92023f48
4 değiştirilmiş dosya ile 164 ekleme ve 31 silme
  1. 114 31
      pwr/btpower.c
  2. 38 0
      slimbus/btfm_slim.c
  3. 6 0
      slimbus/btfm_slim_codec.c
  4. 6 0
      slimbus/btfm_slim_slave.h

+ 114 - 31
pwr/btpower.c

@@ -25,10 +25,7 @@
 #include <linux/of_device.h>
 #include <soc/qcom/cmd-db.h>
 #include "btpower.h"
-
-#if defined CONFIG_BT_SLIM_QCA6390 || \
-	defined CONFIG_BT_SLIM_QCA6490 || \
-	defined CONFIG_BTFM_SLIM_WCN3990
+#if (defined CONFIG_BT_SLIM)
 #include "btfm_slim.h"
 #endif
 #include <linux/fs.h>
@@ -92,11 +89,32 @@ enum power_src_pos {
 	BT_VDD_IO_LDO_CURRENT,
 	BT_VDD_LDO_CURRENT,
 	BT_VDD_RFA_0p8_CURRENT,
-	BT_VDD_RFACMN_CURRENT
+	BT_VDD_RFACMN_CURRENT,
+	BT_VDD_IPA_2p2,
+	BT_VDD_IPA_2p2_CURRENT,
+	/* The below bucks are voted for HW WAR on some platform which supports
+	 * WNC39xx.
+	 */
+	BT_VDD_SMPS,
+	BT_VDD_SMPS_CURRENT,
+	/* New entries need to be added before PWR_SRC_SIZE.
+	 * Its hold the max size of power sources states.
+	 */
+	BT_POWER_SRC_SIZE,
 };
 
-// Regulator structure for QCA6390 and QCA6490 BT SoC series
-static struct bt_power_vreg_data bt_vregs_info_qca6x9x[] = {
+// Regulator structure for QCA6174/QCA9377/QCA9379 BT SoC series
+static struct bt_power_vreg_data bt_vregs_info_qca61x4_937x[] = {
+	{NULL, "qcom,bt-vdd-aon", 928000, 928000, 0, false, false,
+		{BT_VDD_AON_LDO, BT_VDD_AON_LDO_CURRENT}},
+	{NULL, "qcom,bt-vdd-io", 1710000, 3460000, 0, false, false,
+		{BT_VDD_IO_LDO, BT_VDD_IO_LDO_CURRENT}},
+	{NULL, "qcom,bt-vdd-core", 3135000, 3465000, 0, false, false,
+		{BT_VDD_CORE_LDO, BT_VDD_CORE_LDO_CURRENT}},
+};
+
+// Regulator structure for QCA6390,QCA6490 and WCN6750 BT SoC series
+static struct bt_power_vreg_data bt_vregs_info_qca6xx0[] = {
 	{NULL, "qcom,bt-vdd-io",      1800000, 1800000, 0, false, true,
 		{BT_VDD_IO_LDO, BT_VDD_IO_LDO_CURRENT}},
 	{NULL, "qcom,bt-vdd-aon",     966000,  966000,  0, false, true,
@@ -114,12 +132,36 @@ static struct bt_power_vreg_data bt_vregs_info_qca6x9x[] = {
 		{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}},
+	{NULL, "qcom,bt-vdd-ipa-2p2",  2200000, 2210000, 0, false, true,
+		{BT_VDD_IPA_2p2, BT_VDD_IPA_2p2_CURRENT}},
+};
+
+
+// Regulator structure for kiwi BT SoC series
+static struct bt_power_vreg_data bt_vregs_info_kiwi[] = {
+	{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,  950000,  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",     1350000, 1350000, 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}},
 };
 
 // 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-smps", 984000,  984000, 0, false, false,
+			{BT_VDD_SMPS, BT_VDD_SMPS_CURRENT}},
 		{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,
@@ -129,26 +171,47 @@ static struct bt_power bt_vreg_info_wcn399x = {
 		{NULL, "qcom,bt-vdd-xtal", 1700000, 1900000, 0, false, false,
 			{BT_VDD_XTAL_LDO, BT_VDD_XTAL_LDO_CURRENT}},
 	},
-	.num_vregs = 4,
+	.num_vregs = 5,
+};
+
+static struct bt_power bt_vreg_info_qca6174 = {
+	.compatible = "qcom,qca6174",
+	.vregs = bt_vregs_info_qca61x4_937x,
+	.num_vregs = ARRAY_SIZE(bt_vregs_info_qca61x4_937x),
+
+
+static struct bt_power bt_vreg_info_kiwi = {
+	.compatible = "qcom,kiwi",
+	.vregs = bt_vregs_info_kiwi,
+	.num_vregs = ARRAY_SIZE(bt_vregs_info_kiwi),
 };
 
 static struct bt_power bt_vreg_info_qca6390 = {
 	.compatible = "qcom,qca6390",
-	.vregs = bt_vregs_info_qca6x9x,
-	.num_vregs = ARRAY_SIZE(bt_vregs_info_qca6x9x),
+	.vregs = bt_vregs_info_qca6xx0,
+	.num_vregs = ARRAY_SIZE(bt_vregs_info_qca6xx0),
 };
 
 static struct bt_power bt_vreg_info_qca6490 = {
 	.compatible = "qcom,qca6490",
-	.vregs = bt_vregs_info_qca6x9x,
-	.num_vregs = ARRAY_SIZE(bt_vregs_info_qca6x9x),
+	.vregs = bt_vregs_info_qca6xx0,
+	.num_vregs = ARRAY_SIZE(bt_vregs_info_qca6xx0),
+};
+
+
+static struct bt_power bt_vreg_info_wcn6750 = {
+	.compatible = "qcom,wcn6750-bt",
+	.vregs = bt_vregs_info_qca6xx0,
+	.num_vregs = ARRAY_SIZE(bt_vregs_info_qca6xx0),
 };
 
 static const struct of_device_id bt_power_match_table[] = {
-	{	.compatible = "qcom,qca6174" },
+	{	.compatible = "qcom,qca6174", .data = &bt_vreg_info_qca6174},
 	{	.compatible = "qcom,wcn3990", .data = &bt_vreg_info_wcn399x},
 	{	.compatible = "qcom,qca6390", .data = &bt_vreg_info_qca6390},
 	{	.compatible = "qcom,qca6490", .data = &bt_vreg_info_qca6490},
+	{	.compatible = "qcom,kiwi",    .data = &bt_vreg_info_kiwi},
+	{	.compatible = "qcom,wcn6750-bt", .data = &bt_vreg_info_wcn6750},
 	{},
 };
 
@@ -194,7 +257,7 @@ static int bt_vreg_enable(struct bt_power_vreg_data *vreg)
 
 		rc = regulator_enable(vreg->reg);
 		if (rc < 0) {
-			pr_err("regulator_enable(%s) failed. rc=%d\n",
+			pr_err("%s: regulator_enable(%s) failed. rc=%d\n",
 					__func__, vreg->name, rc);
 			goto out;
 		}
@@ -374,6 +437,9 @@ static int bt_configure_gpios(int on)
 			return rc;
 		}
 
+		pr_info("BTON:Turn Bt OFF asserting BT_EN to low\n");
+		pr_info("bt-reset-gpio(%d) value(%d)\n", bt_reset_gpio,
+			gpio_get_value(bt_reset_gpio));
 		rc = gpio_direction_output(bt_reset_gpio, 0);
 		if (rc) {
 			pr_err("%s: Unable to set direction\n", __func__);
@@ -382,25 +448,26 @@ static int bt_configure_gpios(int on)
 		bt_power_src_status[BT_RESET_GPIO] =
 			gpio_get_value(bt_reset_gpio);
 		msleep(50);
-		pr_info("BTON:Turn Bt Off bt-reset-gpio(%d) value(%d)\n",
-			bt_reset_gpio, gpio_get_value(bt_reset_gpio));
+		pr_info("BTON:Turn Bt OFF post asserting BT_EN to low\n");
+		pr_info("bt-reset-gpio(%d) value(%d)\n", bt_reset_gpio,
+			gpio_get_value(bt_reset_gpio));
+
 		if (bt_sw_ctrl_gpio >= 0) {
-			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",
+			pr_info("BTON:Turn Bt OFF bt-sw-ctrl-gpio(%d) value(%d)\n",
 				bt_sw_ctrl_gpio,
 				bt_power_src_status[BT_SW_CTRL_GPIO]);
 		}
 		if (wl_reset_gpio >= 0)
-			pr_info("BTON:Turn Bt On wl-reset-gpio(%d) value(%d)\n",
+			pr_info("BTON:Turn Bt ON wl-reset-gpio(%d) value(%d)\n",
 				wl_reset_gpio, gpio_get_value(wl_reset_gpio));
 
 		if ((wl_reset_gpio < 0) ||
 			((wl_reset_gpio >= 0) && gpio_get_value(wl_reset_gpio))) {
 
 			btpower_set_xo_clk_gpio_state(true);
-			pr_info("%s: BTON: Asserting BT_EN\n", __func__);
+			pr_info("BTON: WLAN ON Asserting BT_EN to high\n");
 			rc = gpio_direction_output(bt_reset_gpio, 1);
 			if (rc) {
 				pr_err("%s: Unable to set direction\n", __func__);
@@ -412,20 +479,39 @@ static int bt_configure_gpios(int on)
 		}
 		if ((wl_reset_gpio >= 0) && (gpio_get_value(wl_reset_gpio) == 0)) {
 			if (gpio_get_value(bt_reset_gpio)) {
-				pr_info("%s: Wlan Off and BT On too close\n", __func__);
-				pr_info("%s: reset BT_EN, enable it after delay\n", __func__);
+				pr_info("BTON: WLAN OFF and BT ON are too close\n");
+				pr_info("reset BT_EN, enable it after delay\n");
 				rc = gpio_direction_output(bt_reset_gpio, 0);
 				if (rc) {
-					pr_err("%s: Unable to set direction\n", __func__);
+					pr_err("%s: Unable to set direction\n",
+						 __func__);
 					return rc;
 				}
 				bt_power_src_status[BT_RESET_GPIO] =
 					gpio_get_value(bt_reset_gpio);
 			}
-			pr_info("%s:add 100ms delay for AON output to fully discharge\n",
-				 __func__);
+			pr_info("BTON: WLAN OFF waiting for 100ms delay\n");
+			pr_info("for AON output to fully discharge\n");
 			msleep(100);
+			pr_info("BTON: WLAN OFF Asserting BT_EN to high\n");
+			btpower_set_xo_clk_gpio_state(true);
+			rc = gpio_direction_output(bt_reset_gpio, 1);
+			if (rc) {
+				pr_err("%s: Unable to set direction\n", __func__);
+				return rc;
+			}
+			bt_power_src_status[BT_RESET_GPIO] =
+				gpio_get_value(bt_reset_gpio);
+			btpower_set_xo_clk_gpio_state(false);
+		}
+		/* Below block of code executes if WL_EN is pulled high when
+		 * BT_EN is about to pull high. so above two if conditions are
+		 * not executed.
+		 */
+		if (!gpio_get_value(bt_reset_gpio)) {
 			btpower_set_xo_clk_gpio_state(true);
+			pr_info("BTON: WLAN ON and BT ON are too close\n");
+			pr_info("Asserting BT_EN to high\n");
 			rc = gpio_direction_output(bt_reset_gpio, 1);
 			if (rc) {
 				pr_err("%s: Unable to set direction\n", __func__);
@@ -462,10 +548,9 @@ 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_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",
+			pr_info("BTON: Turn BT ON bt-sw-ctrl-gpio(%d) value(%d)\n",
 				bt_sw_ctrl_gpio,
 				bt_power_src_status[BT_SW_CTRL_GPIO]);
 		}
@@ -957,7 +1042,7 @@ static void  set_pwr_srcs_status(struct bt_power_vreg_data *handle)
 			(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,
+			pr_err("%s(%p) value(%d)\n", handle->name,
 				handle, bt_power_src_status[ldo_index]);
 		} else {
 			pr_err("%s:%s is_enabled: %d\n",
@@ -997,9 +1082,7 @@ static long bt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
 	switch (cmd) {
 	case BT_CMD_SLIM_TEST:
-#if (defined CONFIG_BT_SLIM_QCA6390 || \
-	defined CONFIG_BT_SLIM_QCA6490 || \
-	defined CONFIG_BTFM_SLIM_WCN3990)
+#if (defined CONFIG_BT_SLIM)
 		if (!bt_power_pdata->slim_dev) {
 			pr_err("%s: slim_dev is null\n", __func__);
 			return -EINVAL;

+ 38 - 0
slimbus/btfm_slim.c

@@ -27,6 +27,7 @@
 
 #ifdef CONFIG_SLIMBUS
 static bool btfm_is_port_opening_delayed = true;
+static int btfm_num_ports_open;
 #endif
 
 int btfm_slim_write(struct btfmslim *btfmslim,
@@ -183,7 +184,11 @@ int btfm_slim_enable_ch(struct btfmslim *btfmslim, struct btfmslim_ch *ch,
 		BTFMSLIM_ERR("slim_stream_enable failed = %d", ret);
 		goto error;
 	}
+
+	if (ret == 0)
+		btfm_num_ports_open++;
 error:
+	BTFMSLIM_INFO("btfm_num_ports_open: %d", btfm_num_ports_open);
 	kfree(chan->dai.sconfig.chs);
 	return ret;
 }
@@ -224,6 +229,10 @@ int btfm_slim_disable_ch(struct btfmslim *btfmslim, struct btfmslim_ch *ch,
 	}
 	ch->dai.sconfig.port_mask = 0;
 	kfree(ch->dai.sconfig.chs);
+
+	if (btfm_num_ports_open > 0)
+		btfm_num_ports_open--;
+	BTFMSLIM_INFO("btfm_num_ports_open: %d", btfm_num_ports_open);
 	return ret;
 }
 
@@ -354,6 +363,27 @@ int btfm_slim_hw_init(struct btfmslim *btfmslim)
 		slim_ifd->e_addr.dev_index = 0x0;
 		slim_ifd->e_addr.instance = 0x0;
 		slim_ifd->laddr = 0x0;
+	} else if (chipset_ver == QCA_HAMILTON_SOC_ID_0100 ||
+		chipset_ver ==  QCA_HAMILTON_SOC_ID_0101 ||
+		chipset_ver ==  QCA_HAMILTON_SOC_ID_0200) {
+		BTFMSLIM_INFO("chipset is Hamliton, overwriting EA");
+		slim->is_laddr_valid = false;
+		slim->e_addr.manf_id = SLIM_MANF_ID_QCOM;
+		slim->e_addr.prod_code = 0x220;
+		slim->e_addr.dev_index = 0x01;
+		slim->e_addr.instance = 0x0;
+		/* we are doing this to indicate that this is not a child node
+		 * (doesn't have call back functions). Needed only for querying
+		 * logical address.
+		 */
+		slim_ifd->dev.driver = NULL;
+		slim_ifd->ctrl = btfmslim->slim_pgd->ctrl; //slimbus controller structure.
+		slim_ifd->is_laddr_valid = false;
+		slim_ifd->e_addr.manf_id = SLIM_MANF_ID_QCOM;
+		slim_ifd->e_addr.prod_code = 0x220;
+		slim_ifd->e_addr.dev_index = 0x0;
+		slim_ifd->e_addr.instance = 0x0;
+		slim_ifd->laddr = 0x0;
 	}
 		BTFMSLIM_INFO(
 			"PGD Enum Addr: manu id:%.02x prod code:%.02x dev idx:%.02x instance:%.02x",
@@ -365,6 +395,14 @@ int btfm_slim_hw_init(struct btfmslim *btfmslim)
 			slim_ifd->e_addr.manf_id, slim_ifd->e_addr.prod_code,
 			slim_ifd->e_addr.dev_index, slim_ifd->e_addr.instance);
 
+	if (btfm_num_ports_open == 0 && (chipset_ver == QCA_HSP_SOC_ID_0200 ||
+		chipset_ver == QCA_HSP_SOC_ID_0210 ||
+		chipset_ver == QCA_HSP_SOC_ID_1201 ||
+		chipset_ver == QCA_HSP_SOC_ID_1211)) {
+		BTFMSLIM_INFO("SB reset needed before getting LA, sleeping");
+		msleep(DELAY_FOR_PORT_OPEN_MS);
+	}
+
 	/* Assign Logical Address for PGD (Ported Generic Device)
 	 * enumeration address
 	 */

+ 6 - 0
slimbus/btfm_slim_codec.c

@@ -14,6 +14,7 @@
 #include <linux/slimbus.h>
 #include <linux/ratelimit.h>
 #include <linux/slab.h>
+#include <linux/errno.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
@@ -223,6 +224,11 @@ static int btfm_slim_dai_prepare(struct snd_pcm_substream *substream,
 	/* save the enable channel status */
 	if (ret == 0)
 		bt_soc_enable_status = 1;
+
+	if (ret == -EISCONN) {
+		BTFMSLIM_ERR("channel opened without closing, returning success");
+		ret = 0;
+	}
 	return ret;
 }
 

+ 6 - 0
slimbus/btfm_slim_slave.h

@@ -122,6 +122,12 @@ enum {
 	QCA_MOSELLE_SOC_ID_0110 = 0x40140110,
 };
 
+enum {
+	QCA_HAMILTON_SOC_ID_0100 = 0x40170100,
+	QCA_HAMILTON_SOC_ID_0101 = 0x40170101,
+	QCA_HAMILTON_SOC_ID_0200 = 0x40170200,
+};
+
 /* Function Prototype */
 
 /*