[PATCH v6 09/11] Bluetooth: hci_qca: Flatten struct qca_power into struct qca_serdev
From: Loic Poulain
Date: Fri Sep 04 2026 - 12:18:42 EST
struct qca_power currently only groups a handful of fields
(vreg_bulk, num_vregs, vregs_on, pwrseq) that are exclusively used
from struct qca_serdev, via its embedded bt_power member. The extra
indirection level does not provide any isolation or reuse benefit,
and just adds qcadev->bt_power.<field> noise throughout the driver.
Drop struct qca_power and move its fields directly into
struct qca_serdev, updating qca_init_regulators() to take a
struct qca_serdev pointer instead. No functional change intended.
Suggested-by: Dmitry Baryshkov <dmitry.baryshkov@xxxxxxxxxxxxxxxx>
Signed-off-by: Loic Poulain <loic.poulain@xxxxxxxxxxxxxxxx>
---
drivers/bluetooth/hci_qca.c | 91 +++++++++++++++++++--------------------------
1 file changed, 39 insertions(+), 52 deletions(-)
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index db0a968dfb00fa6f1abb86a3f6d1be89dfe80c6a..cfefa8b72e2527639299811d1b4f2fac697ee704 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -211,21 +211,16 @@ struct qca_device_data {
/*
* Platform data for the QCA Bluetooth power driver.
*/
-struct qca_power {
- struct device *dev;
- struct regulator_bulk_data *vreg_bulk;
- int num_vregs;
- bool vregs_on;
- struct pwrseq_desc *pwrseq;
-};
-
struct qca_serdev {
struct hci_uart serdev_hu;
struct gpio_desc *bt_en;
struct gpio_desc *sw_ctrl;
struct clk *susclk;
enum qca_btsoc_type btsoc_type;
- struct qca_power bt_power;
+ struct regulator_bulk_data *vreg_bulk;
+ int num_vregs;
+ bool vregs_on;
+ struct pwrseq_desc *pwrseq;
u32 init_speed;
u32 oper_speed;
bool bdaddr_property_broken;
@@ -1779,7 +1774,7 @@ static int qca_regulator_init(struct hci_uart *hu)
*/
qcadev = serdev_device_get_drvdata(hu->serdev);
- if (!qcadev->bt_power.vregs_on) {
+ if (!qcadev->vregs_on) {
serdev_device_close(hu->serdev);
ret = qca_regulator_enable(qcadev);
if (ret)
@@ -1876,8 +1871,8 @@ static int qca_power_on(struct hci_dev *hdev)
msleep(150);
}
- if (qcadev->bt_power.pwrseq)
- pwrseq_power_on(qcadev->bt_power.pwrseq);
+ if (qcadev->pwrseq)
+ pwrseq_enable(qcadev->pwrseq);
}
clear_bit(QCA_BT_OFF, &qca->flags);
@@ -2230,7 +2225,6 @@ static void qca_power_off(struct hci_uart *hu)
unsigned long flags;
enum qca_btsoc_type soc_type = qca_soc_type(hu);
bool sw_ctrl_state;
- struct qca_power *power;
/* From this point we go into power off state. But serial port is
* still open, stop queueing the IBS data and flush all the buffered
@@ -2248,7 +2242,6 @@ static void qca_power_off(struct hci_uart *hu)
return;
qcadev = serdev_device_get_drvdata(hu->serdev);
- power = &qcadev->bt_power;
switch (soc_type) {
case QCA_WCN3988:
@@ -2262,8 +2255,8 @@ static void qca_power_off(struct hci_uart *hu)
break;
}
- if (power->pwrseq) {
- pwrseq_disable(power->pwrseq);
+ if (qcadev->pwrseq) {
+ pwrseq_disable(qcadev->pwrseq);
set_bit(QCA_BT_OFF, &qca->flags);
return;
}
@@ -2319,23 +2312,22 @@ static int qca_hci_shutdown(struct hci_dev *hdev)
static int qca_regulator_enable(struct qca_serdev *qcadev)
{
- struct qca_power *power = &qcadev->bt_power;
int ret;
- if (power->pwrseq)
- return pwrseq_enable(power->pwrseq);
+ if (qcadev->pwrseq)
+ return pwrseq_enable(qcadev->pwrseq);
/* Already enabled */
- if (power->vregs_on)
+ if (qcadev->vregs_on)
return 0;
- BT_DBG("enabling %d regulators)", power->num_vregs);
+ BT_DBG("enabling %d regulators)", qcadev->num_vregs);
- ret = regulator_bulk_enable(power->num_vregs, power->vreg_bulk);
+ ret = regulator_bulk_enable(qcadev->num_vregs, qcadev->vreg_bulk);
if (ret)
return ret;
- power->vregs_on = true;
+ qcadev->vregs_on = true;
ret = clk_prepare_enable(qcadev->susclk);
if (ret)
@@ -2346,38 +2338,35 @@ static int qca_regulator_enable(struct qca_serdev *qcadev)
static void qca_regulator_disable(struct qca_serdev *qcadev)
{
- struct qca_power *power;
-
if (!qcadev)
return;
- power = &qcadev->bt_power;
-
/* Already disabled? */
- if (!power->vregs_on)
+ if (!qcadev->vregs_on)
return;
- regulator_bulk_disable(power->num_vregs, power->vreg_bulk);
- power->vregs_on = false;
+ regulator_bulk_disable(qcadev->num_vregs, qcadev->vreg_bulk);
+ qcadev->vregs_on = false;
clk_disable_unprepare(qcadev->susclk);
}
-static int qca_init_regulators(struct qca_power *qca,
+static int qca_init_regulators(struct qca_serdev *qcadev,
const struct qca_vreg *vregs, size_t num_vregs)
{
+ struct device *dev = &qcadev->serdev_hu.serdev->dev;
struct regulator_bulk_data *bulk;
int ret;
int i;
- bulk = devm_kcalloc(qca->dev, num_vregs, sizeof(*bulk), GFP_KERNEL);
+ bulk = devm_kcalloc(dev, num_vregs, sizeof(*bulk), GFP_KERNEL);
if (!bulk)
return -ENOMEM;
for (i = 0; i < num_vregs; i++)
bulk[i].supply = vregs[i].name;
- ret = devm_regulator_bulk_get(qca->dev, num_vregs, bulk);
+ ret = devm_regulator_bulk_get(dev, num_vregs, bulk);
if (ret < 0)
return ret;
@@ -2387,8 +2376,8 @@ static int qca_init_regulators(struct qca_power *qca,
return ret;
}
- qca->vreg_bulk = bulk;
- qca->num_vregs = num_vregs;
+ qcadev->vreg_bulk = bulk;
+ qcadev->num_vregs = num_vregs;
return 0;
}
@@ -2416,7 +2405,7 @@ static int qca_serdev_get_m2_pwrseq(struct qca_serdev *qcadev)
if (IS_ERR(pwrseq))
return PTR_ERR(pwrseq);
- qcadev->bt_power.pwrseq = pwrseq;
+ qcadev->pwrseq = pwrseq;
return devm_add_action_or_reset(&serdev->dev, qca_serdev_put_pwrseq, pwrseq);
}
@@ -2465,7 +2454,7 @@ static int qca_serdev_probe(struct serdev_device *serdev)
case QCA_WCN6855:
case QCA_WCN7850:
/* M.2 connector modules are powered by the pwrseq acquired above. */
- if (qcadev->bt_power.pwrseq)
+ if (qcadev->pwrseq)
break;
if (!device_property_present(&serdev->dev, "enable-gpios")) {
@@ -2475,7 +2464,7 @@ static int qca_serdev_probe(struct serdev_device *serdev)
* let's use the power sequencer. Otherwise, let's
* drive everything ourselves.
*/
- qcadev->bt_power.pwrseq = devm_pwrseq_get(&serdev->dev,
+ qcadev->pwrseq = devm_pwrseq_get(&serdev->dev,
"bluetooth");
/*
@@ -2484,21 +2473,20 @@ static int qca_serdev_probe(struct serdev_device *serdev)
* through the power sequence. In such cases, fall through
* to follow the legacy flow.
*/
- if (IS_ERR(qcadev->bt_power.pwrseq))
- qcadev->bt_power.pwrseq = NULL;
+ if (IS_ERR(qcadev->pwrseq))
+ qcadev->pwrseq = NULL;
else
break;
}
- qcadev->bt_power.dev = &serdev->dev;
- err = qca_init_regulators(&qcadev->bt_power, data->vregs,
+ err = qca_init_regulators(qcadev, data->vregs,
data->num_vregs);
if (err) {
BT_ERR("Failed to init regulators:%d", err);
return err;
}
- qcadev->bt_power.vregs_on = false;
+ qcadev->vregs_on = false;
qcadev->bt_en = devm_gpiod_get_optional(&serdev->dev, "enable",
GPIOD_OUT_LOW);
@@ -2532,10 +2520,10 @@ static int qca_serdev_probe(struct serdev_device *serdev)
case QCA_QCA6390:
if (dev_of_node(&serdev->dev)) {
- qcadev->bt_power.pwrseq = devm_pwrseq_get(&serdev->dev,
+ qcadev->pwrseq = devm_pwrseq_get(&serdev->dev,
"bluetooth");
- if (IS_ERR(qcadev->bt_power.pwrseq))
- return PTR_ERR(qcadev->bt_power.pwrseq);
+ if (IS_ERR(qcadev->pwrseq))
+ return PTR_ERR(qcadev->pwrseq);
break;
}
fallthrough;
@@ -2559,16 +2547,16 @@ static int qca_serdev_probe(struct serdev_device *serdev)
}
}
- if (qcadev->bt_power.pwrseq) {
- bt_en_available = pwrseq_is_controllable(qcadev->bt_power.pwrseq);
+ if (qcadev->pwrseq) {
+ bt_en_available = pwrseq_is_controllable(qcadev->pwrseq);
if (!bt_en_available) {
/* The host cannot gate the BT power individually.
* Treat it as always-on and drop the pwrseq handle.
* The descriptor itself is still released by devres,
* so dropping the handle here is not a leak.
*/
- pwrseq_enable(qcadev->bt_power.pwrseq);
- qcadev->bt_power.pwrseq = NULL;
+ pwrseq_enable(qcadev->pwrseq);
+ qcadev->pwrseq = NULL;
}
}
@@ -2606,7 +2594,6 @@ static int qca_serdev_probe(struct serdev_device *serdev)
static void qca_serdev_remove(struct serdev_device *serdev)
{
struct qca_serdev *qcadev = serdev_device_get_drvdata(serdev);
- struct qca_power *power = &qcadev->bt_power;
switch (qcadev->btsoc_type) {
case QCA_WCN3988:
@@ -2616,7 +2603,7 @@ static void qca_serdev_remove(struct serdev_device *serdev)
case QCA_WCN6750:
case QCA_WCN6855:
case QCA_WCN7850:
- if (power->vregs_on)
+ if (qcadev->vregs_on)
qca_power_off(&qcadev->serdev_hu);
break;
default:
--
2.34.1