Bluetooth: qca: use the power sequencer for QCA6390

Use the pwrseq subsystem's consumer API to run the power-up sequence for
the Bluetooth module of the QCA6390 package.

Tested-by: Amit Pundir <amit.pundir@linaro.org>
Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD, SM8650-QRD & SM8650-HDK
Tested-by: Caleb Connolly <caleb.connolly@linaro.org> # OnePlus 8T
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
Bartosz Golaszewski 2024-06-12 10:01:50 +02:00 committed by Luiz Augusto von Dentz
parent 66ef82c66e
commit 9a15ce6857

View File

@ -28,6 +28,7 @@
#include <linux/of.h>
#include <linux/acpi.h>
#include <linux/platform_device.h>
#include <linux/pwrseq/consumer.h>
#include <linux/regulator/consumer.h>
#include <linux/serdev.h>
#include <linux/mutex.h>
@ -214,6 +215,7 @@ struct qca_power {
struct regulator_bulk_data *vreg_bulk;
int num_vregs;
bool vregs_on;
struct pwrseq_desc *pwrseq;
};
struct qca_serdev {
@ -1684,6 +1686,27 @@ static bool qca_wakeup(struct hci_dev *hdev)
return wakeup;
}
static int qca_port_reopen(struct hci_uart *hu)
{
int ret;
/* Now the device is in ready state to communicate with host.
* To sync host with device we need to reopen port.
* Without this, we will have RTS and CTS synchronization
* issues.
*/
serdev_device_close(hu->serdev);
ret = serdev_device_open(hu->serdev);
if (ret) {
bt_dev_err(hu->hdev, "failed to open port");
return ret;
}
hci_uart_set_flow_control(hu, false);
return 0;
}
static int qca_regulator_init(struct hci_uart *hu)
{
enum qca_btsoc_type soc_type = qca_soc_type(hu);
@ -1752,21 +1775,7 @@ static int qca_regulator_init(struct hci_uart *hu)
break;
}
/* Now the device is in ready state to communicate with host.
* To sync host with device we need to reopen port.
* Without this, we will have RTS and CTS synchronization
* issues.
*/
serdev_device_close(hu->serdev);
ret = serdev_device_open(hu->serdev);
if (ret) {
bt_dev_err(hu->hdev, "failed to open port");
return ret;
}
hci_uart_set_flow_control(hu, false);
return 0;
return qca_port_reopen(hu);
}
static int qca_power_on(struct hci_dev *hdev)
@ -1794,6 +1803,17 @@ static int qca_power_on(struct hci_dev *hdev)
ret = qca_regulator_init(hu);
break;
case QCA_QCA6390:
qcadev = serdev_device_get_drvdata(hu->serdev);
ret = pwrseq_power_on(qcadev->bt_power->pwrseq);
if (ret)
return ret;
ret = qca_port_reopen(hu);
if (ret)
return ret;
break;
default:
qcadev = serdev_device_get_drvdata(hu->serdev);
if (qcadev->bt_en) {
@ -2168,6 +2188,10 @@ static void qca_power_shutdown(struct hci_uart *hu)
}
break;
case QCA_QCA6390:
pwrseq_power_off(qcadev->bt_power->pwrseq);
break;
default:
gpiod_set_value_cansleep(qcadev->bt_en, 0);
}
@ -2309,12 +2333,25 @@ static int qca_serdev_probe(struct serdev_device *serdev)
case QCA_WCN6750:
case QCA_WCN6855:
case QCA_WCN7850:
case QCA_QCA6390:
qcadev->bt_power = devm_kzalloc(&serdev->dev,
sizeof(struct qca_power),
GFP_KERNEL);
if (!qcadev->bt_power)
return -ENOMEM;
break;
default:
break;
}
switch (qcadev->btsoc_type) {
case QCA_WCN3988:
case QCA_WCN3990:
case QCA_WCN3991:
case QCA_WCN3998:
case QCA_WCN6750:
case QCA_WCN6855:
case QCA_WCN7850:
qcadev->bt_power->dev = &serdev->dev;
err = qca_init_regulators(qcadev->bt_power, data->vregs,
data->num_vregs);
@ -2360,6 +2397,13 @@ static int qca_serdev_probe(struct serdev_device *serdev)
}
break;
case QCA_QCA6390:
qcadev->bt_power->pwrseq = devm_pwrseq_get(&serdev->dev,
"bluetooth");
if (IS_ERR(qcadev->bt_power->pwrseq))
return PTR_ERR(qcadev->bt_power->pwrseq);
fallthrough;
default:
qcadev->bt_en = devm_gpiod_get_optional(&serdev->dev, "enable",
GPIOD_OUT_LOW);