Re: [RFC PATCH 10/15] pwrseq: add support for QCA BT+WiFi power sequencer
From: Bjorn Andersson <hidden>
Date: 2021-08-19 23:17:41
Also in:
linux-arm-msm, linux-bluetooth, linux-mmc, linux-wireless, lkml
On Mon 16 Aug 17:55 PDT 2021, Dmitry Baryshkov wrote: [..]
quoted hunk ↗ jump to hunk
diff --git a/drivers/power/pwrseq/pwrseq_qca.c b/drivers/power/pwrseq/pwrseq_qca.c new file mode 100644 index 000000000000..3421a4821126 --- /dev/null +++ b/drivers/power/pwrseq/pwrseq_qca.c@@ -0,0 +1,290 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2021, Linaro Ltd. + * + * Author: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> + * + * Power Sequencer for Qualcomm WiFi + BT SoCs + */ + +#include <linux/delay.h> +#include <linux/gpio/consumer.h> +#include <linux/platform_device.h> +#include <linux/pwrseq/driver.h> +#include <linux/regulator/consumer.h> + +/* + * Voltage regulator information required for configuring the + * QCA WiFi+Bluetooth chipset + */ +struct qca_vreg { + const char *name; + unsigned int load_uA; +}; + +struct qca_device_data { + struct qca_vreg vddio;
Any particular reason why this isn't just the first entry in vregs and operated as part of the bulk API?
quoted hunk ↗ jump to hunk
+ struct qca_vreg *vregs; + size_t num_vregs; + bool has_bt_en; + bool has_wifi_en; +}; + +struct pwrseq_qca; +struct pwrseq_qca_one { + struct pwrseq_qca *common; + struct gpio_desc *enable; +}; + +#define PWRSEQ_QCA_WIFI 0 +#define PWRSEQ_QCA_BT 1 + +#define PWRSEQ_QCA_MAX 2 + +struct pwrseq_qca { + struct regulator *vddio; + struct gpio_desc *sw_ctrl; + struct pwrseq_qca_one pwrseq_qcas[PWRSEQ_QCA_MAX]; + int num_vregs; + struct regulator_bulk_data vregs[]; +}; + +static int pwrseq_qca_power_on(struct pwrseq *pwrseq) +{ + struct pwrseq_qca_one *qca_one = pwrseq_get_data(pwrseq); + int ret; + + if (qca_one->common->vddio) {
devm_regulator_get() doesn't return NULL, so this is always true.
quoted hunk ↗ jump to hunk
+ ret = regulator_enable(qca_one->common->vddio); + if (ret) + return ret; + } + + ret = regulator_bulk_enable(qca_one->common->num_vregs, qca_one->common->vregs); + if (ret) + goto vddio_off; + + if (qca_one->enable) { + gpiod_set_value_cansleep(qca_one->enable, 0); + msleep(50); + gpiod_set_value_cansleep(qca_one->enable, 1); + msleep(150); + } + + if (qca_one->common->sw_ctrl) { + bool sw_ctrl_state = gpiod_get_value_cansleep(qca_one->common->sw_ctrl); + dev_dbg(&pwrseq->dev, "SW_CTRL is %d", sw_ctrl_state); + } + + return 0; + +vddio_off: + regulator_disable(qca_one->common->vddio); + + return ret; +}
[..]
quoted hunk ↗ jump to hunk
+static int pwrseq_qca_probe(struct platform_device *pdev) +{ + struct pwrseq_qca *pwrseq_qca; + struct pwrseq *pwrseq; + struct pwrseq_provider *provider; + struct device *dev = &pdev->dev; + struct pwrseq_onecell_data *onecell; + const struct qca_device_data *data; + int ret, i; + + data = device_get_match_data(dev); + if (!data) + return -EINVAL; + + pwrseq_qca = devm_kzalloc(dev, struct_size(pwrseq_qca, vregs, data->num_vregs), GFP_KERNEL); + if (!pwrseq_qca) + return -ENOMEM; + + onecell = devm_kzalloc(dev, struct_size(onecell, pwrseqs, PWRSEQ_QCA_MAX), GFP_KERNEL); + if (!onecell) + return -ENOMEM; + + ret = pwrseq_qca_regulators_init(dev, pwrseq_qca, data); + if (ret) + return ret; + + if (data->has_wifi_en) { + pwrseq_qca->pwrseq_qcas[PWRSEQ_QCA_WIFI].enable = devm_gpiod_get(dev, "wifi-enable", GPIOD_OUT_LOW); + if (IS_ERR(pwrseq_qca->pwrseq_qcas[PWRSEQ_QCA_WIFI].enable)) { + return dev_err_probe(dev, PTR_ERR(pwrseq_qca->pwrseq_qcas[PWRSEQ_QCA_WIFI].enable), + "failed to acquire WIFI enable GPIO\n"); + } + } + + if (data->has_bt_en) { + pwrseq_qca->pwrseq_qcas[PWRSEQ_QCA_BT].enable = devm_gpiod_get(dev, "bt-enable", GPIOD_OUT_LOW); + if (IS_ERR(pwrseq_qca->pwrseq_qcas[PWRSEQ_QCA_BT].enable)) { + return dev_err_probe(dev, PTR_ERR(pwrseq_qca->pwrseq_qcas[PWRSEQ_QCA_BT].enable), + "failed to acquire BT enable GPIO\n"); + } + } + + pwrseq_qca->sw_ctrl = devm_gpiod_get_optional(dev, "swctrl", GPIOD_IN); + if (IS_ERR(pwrseq_qca->sw_ctrl)) { + return dev_err_probe(dev, PTR_ERR(pwrseq_qca->sw_ctrl), + "failed to acquire SW_CTRL gpio\n"); + } else if (!pwrseq_qca->sw_ctrl) + dev_info(dev, "No SW_CTRL gpio\n");
Some {} around the else as well please.
Regards,
Bjorn