|
@@ -25,10 +25,7 @@
|
|
#include <linux/of_device.h>
|
|
#include <linux/of_device.h>
|
|
#include <soc/qcom/cmd-db.h>
|
|
#include <soc/qcom/cmd-db.h>
|
|
#include "btpower.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"
|
|
#include "btfm_slim.h"
|
|
#endif
|
|
#endif
|
|
#include <linux/fs.h>
|
|
#include <linux/fs.h>
|
|
@@ -92,11 +89,32 @@ enum power_src_pos {
|
|
BT_VDD_IO_LDO_CURRENT,
|
|
BT_VDD_IO_LDO_CURRENT,
|
|
BT_VDD_LDO_CURRENT,
|
|
BT_VDD_LDO_CURRENT,
|
|
BT_VDD_RFA_0p8_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,
|
|
{NULL, "qcom,bt-vdd-io", 1800000, 1800000, 0, false, true,
|
|
{BT_VDD_IO_LDO, BT_VDD_IO_LDO_CURRENT}},
|
|
{BT_VDD_IO_LDO, BT_VDD_IO_LDO_CURRENT}},
|
|
{NULL, "qcom,bt-vdd-aon", 966000, 966000, 0, false, true,
|
|
{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}},
|
|
{BT_VDD_RFA2_LDO, BT_VDD_RFA2_LDO_CURRENT}},
|
|
{NULL, "qcom,bt-vdd-asd", 2800000, 2800000, 0, false, true,
|
|
{NULL, "qcom,bt-vdd-asd", 2800000, 2800000, 0, false, true,
|
|
{BT_VDD_ASD_LDO, BT_VDD_ASD_LDO_CURRENT}},
|
|
{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
|
|
// Regulator structure for WCN399x BT SoC series
|
|
static struct bt_power bt_vreg_info_wcn399x = {
|
|
static struct bt_power bt_vreg_info_wcn399x = {
|
|
.compatible = "qcom,wcn3990",
|
|
.compatible = "qcom,wcn3990",
|
|
.vregs = (struct bt_power_vreg_data []) {
|
|
.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,
|
|
{NULL, "qcom,bt-vdd-io", 1700000, 1900000, 0, false, false,
|
|
{BT_VDD_IO_LDO, BT_VDD_IO_LDO_CURRENT}},
|
|
{BT_VDD_IO_LDO, BT_VDD_IO_LDO_CURRENT}},
|
|
{NULL, "qcom,bt-vdd-core", 1304000, 1304000, 0, false, false,
|
|
{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,
|
|
{NULL, "qcom,bt-vdd-xtal", 1700000, 1900000, 0, false, false,
|
|
{BT_VDD_XTAL_LDO, BT_VDD_XTAL_LDO_CURRENT}},
|
|
{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 = {
|
|
static struct bt_power bt_vreg_info_qca6390 = {
|
|
.compatible = "qcom,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 = {
|
|
static struct bt_power bt_vreg_info_qca6490 = {
|
|
.compatible = "qcom,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[] = {
|
|
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,wcn3990", .data = &bt_vreg_info_wcn399x},
|
|
{ .compatible = "qcom,qca6390", .data = &bt_vreg_info_qca6390},
|
|
{ .compatible = "qcom,qca6390", .data = &bt_vreg_info_qca6390},
|
|
{ .compatible = "qcom,qca6490", .data = &bt_vreg_info_qca6490},
|
|
{ .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);
|
|
rc = regulator_enable(vreg->reg);
|
|
if (rc < 0) {
|
|
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);
|
|
__func__, vreg->name, rc);
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
@@ -374,6 +437,9 @@ static int bt_configure_gpios(int on)
|
|
return rc;
|
|
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);
|
|
rc = gpio_direction_output(bt_reset_gpio, 0);
|
|
if (rc) {
|
|
if (rc) {
|
|
pr_err("%s: Unable to set direction\n", __func__);
|
|
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] =
|
|
bt_power_src_status[BT_RESET_GPIO] =
|
|
gpio_get_value(bt_reset_gpio);
|
|
gpio_get_value(bt_reset_gpio);
|
|
msleep(50);
|
|
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) {
|
|
if (bt_sw_ctrl_gpio >= 0) {
|
|
- pr_info("BTON:Turn Bt Off\n");
|
|
|
|
bt_power_src_status[BT_SW_CTRL_GPIO] =
|
|
bt_power_src_status[BT_SW_CTRL_GPIO] =
|
|
gpio_get_value(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_sw_ctrl_gpio,
|
|
bt_power_src_status[BT_SW_CTRL_GPIO]);
|
|
bt_power_src_status[BT_SW_CTRL_GPIO]);
|
|
}
|
|
}
|
|
if (wl_reset_gpio >= 0)
|
|
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));
|
|
wl_reset_gpio, gpio_get_value(wl_reset_gpio));
|
|
|
|
|
|
if ((wl_reset_gpio < 0) ||
|
|
if ((wl_reset_gpio < 0) ||
|
|
((wl_reset_gpio >= 0) && gpio_get_value(wl_reset_gpio))) {
|
|
((wl_reset_gpio >= 0) && gpio_get_value(wl_reset_gpio))) {
|
|
|
|
|
|
btpower_set_xo_clk_gpio_state(true);
|
|
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);
|
|
rc = gpio_direction_output(bt_reset_gpio, 1);
|
|
if (rc) {
|
|
if (rc) {
|
|
pr_err("%s: Unable to set direction\n", __func__);
|
|
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 ((wl_reset_gpio >= 0) && (gpio_get_value(wl_reset_gpio) == 0)) {
|
|
if (gpio_get_value(bt_reset_gpio)) {
|
|
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);
|
|
rc = gpio_direction_output(bt_reset_gpio, 0);
|
|
if (rc) {
|
|
if (rc) {
|
|
- pr_err("%s: Unable to set direction\n", __func__);
|
|
|
|
|
|
+ pr_err("%s: Unable to set direction\n",
|
|
|
|
+ __func__);
|
|
return rc;
|
|
return rc;
|
|
}
|
|
}
|
|
bt_power_src_status[BT_RESET_GPIO] =
|
|
bt_power_src_status[BT_RESET_GPIO] =
|
|
gpio_get_value(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);
|
|
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);
|
|
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);
|
|
rc = gpio_direction_output(bt_reset_gpio, 1);
|
|
if (rc) {
|
|
if (rc) {
|
|
pr_err("%s: Unable to set direction\n", __func__);
|
|
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",
|
|
pr_info("BTON:Turn Bt On bt-reset-gpio(%d) value(%d)\n",
|
|
bt_reset_gpio, gpio_get_value(bt_reset_gpio));
|
|
bt_reset_gpio, gpio_get_value(bt_reset_gpio));
|
|
if (bt_sw_ctrl_gpio >= 0) {
|
|
if (bt_sw_ctrl_gpio >= 0) {
|
|
- pr_info("BTON:Turn Bt On\n");
|
|
|
|
bt_power_src_status[BT_SW_CTRL_GPIO] =
|
|
bt_power_src_status[BT_SW_CTRL_GPIO] =
|
|
gpio_get_value(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_sw_ctrl_gpio,
|
|
bt_power_src_status[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))) {
|
|
(regulator_is_enabled(handle->reg))) {
|
|
bt_power_src_status[ldo_index] =
|
|
bt_power_src_status[ldo_index] =
|
|
(int)regulator_get_voltage(handle->reg);
|
|
(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]);
|
|
handle, bt_power_src_status[ldo_index]);
|
|
} else {
|
|
} else {
|
|
pr_err("%s:%s is_enabled: %d\n",
|
|
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) {
|
|
switch (cmd) {
|
|
case BT_CMD_SLIM_TEST:
|
|
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) {
|
|
if (!bt_power_pdata->slim_dev) {
|
|
pr_err("%s: slim_dev is null\n", __func__);
|
|
pr_err("%s: slim_dev is null\n", __func__);
|
|
return -EINVAL;
|
|
return -EINVAL;
|