mbox series

[v3,0/7] Add support for Qualcomm QCA639x chips family

Message ID 20210621223141.1638189-1-dmitry.baryshkov@linaro.org
Headers show
Series Add support for Qualcomm QCA639x chips family | expand

Message

Dmitry Baryshkov June 21, 2021, 10:31 p.m. UTC
Qualcomm QCA639x is a family of WiFi + Bluetooth chips, with BT part
being controlled through the UART and WiFi being present on PCIe
bus. Both blocks use common power management unit wich should be turned
on before either of devices can be probed. Add common 'qcom-qca6390'
driver providing regulator to be used by both BT and PCIe parts.

Changes since v2:
 - Rebase on top of linux-next to get wcn6750 changes.
 - Switch from misc device providing power domains into regulator code.
 - Use vddpe-3v3-supply as expected by pcie-qcom driver.
 - Use enable_gpio functionality in hci_qca driver.

Changes since v1:
 - Stopped using wildcard in the dts binding, stick to qcom,qca6390.
 - Stopped using pcie0_phy for qca639x power domain.
 - Describe root PCIe bridge in the dts and bind power domain to the
   bridge.
 - Add pci quirk to power up power domains connected to this bridge.

----------------------------------------------------------------
Dmitry Baryshkov (7):
      dt-bindings: regulator: qcom,qca6390: add binding for QCA6390 device
      regulator: qca6390: add support for QCA639x powerup sequence
      Bluetooth: hci_qca: provide default device data
      Bluetooth: hci_qca: merge qca_power into qca_serdev
      Bluetooth: hci_qca: merge wcn & non-wcn code paths
      Bluetooth: hci_qca: add power sequencer support to qca6390
      arm64: dts: qcom: qrb5165-rb5: add QCA6391 WiFi+BT SoC

 .../bindings/regulator/qcom,qca6390.yaml           |  70 +++++++
 arch/arm64/boot/dts/qcom/qrb5165-rb5.dts           |  56 +++++
 drivers/bluetooth/hci_qca.c                        | 225 ++++++++++-----------
 drivers/regulator/Kconfig                          |  13 ++
 drivers/regulator/Makefile                         |   1 +
 drivers/regulator/qcom-qca639x.c                   | 157 ++++++++++++++
 6 files changed, 401 insertions(+), 121 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/regulator/qcom,qca6390.yaml
 create mode 100644 drivers/regulator/qcom-qca639x.c

Comments

Bjorn Andersson July 14, 2021, 5:25 p.m. UTC | #1
On Mon 21 Jun 17:31 CDT 2021, Dmitry Baryshkov wrote:

> There is no need to allocate separate structure for handling regulators
> used by QCA chips, we gain nothing from it. Move all used data fields
> directly to struct qca_serdev.
> 

Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>

Regards,
Bjorn

> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> ---
>  drivers/bluetooth/hci_qca.c | 58 ++++++++++++++-----------------------
>  1 file changed, 22 insertions(+), 36 deletions(-)
> 
> diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
> index 3704dbadba1d..9cc8a9153d76 100644
> --- a/drivers/bluetooth/hci_qca.c
> +++ b/drivers/bluetooth/hci_qca.c
> @@ -208,20 +208,15 @@ 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 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;
>  	u32 init_speed;
>  	u32 oper_speed;
>  	const char *firmware_name;
> @@ -1602,7 +1597,7 @@ static int qca_regulator_init(struct hci_uart *hu)
>  	 * off the voltage regulator.
>  	 */
>  	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)
> @@ -1945,20 +1940,19 @@ static int qca_power_off(struct hci_dev *hdev)
>  
>  static int qca_regulator_enable(struct qca_serdev *qcadev)
>  {
> -	struct qca_power *power = qcadev->bt_power;
>  	int ret;
>  
>  	/* 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)
> @@ -1969,38 +1963,37 @@ 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,
> -				const struct qca_vreg *vregs, size_t num_vregs)
> +static int qca_init_regulators(struct device *dev, struct qca_serdev *qca,
> +			       const struct qca_vreg *vregs, size_t num_vregs)
>  {
>  	struct regulator_bulk_data *bulk;
>  	int ret;
>  	int i;
>  
> -	bulk = devm_kcalloc(qca->dev, num_vregs, sizeof(*bulk), GFP_KERNEL);
> +	if (!num_vregs)
> +		return 0;
> +
> +	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;
>  
> @@ -2044,21 +2037,15 @@ static int qca_serdev_probe(struct serdev_device *serdev)
>  	if ((qca_is_wcn399x(data->soc_type) ||
>  	     qca_is_wcn6750(data->soc_type))) {
>  		qcadev->btsoc_type = data->soc_type;
> -		qcadev->bt_power = devm_kzalloc(&serdev->dev,
> -						sizeof(struct qca_power),
> -						GFP_KERNEL);
> -		if (!qcadev->bt_power)
> -			return -ENOMEM;
> -
> -		qcadev->bt_power->dev = &serdev->dev;
> -		err = qca_init_regulators(qcadev->bt_power, data->vregs,
> +
> +		err = qca_init_regulators(&serdev->dev, 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);
> @@ -2139,11 +2126,10 @@ 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;
>  
>  	if ((qca_is_wcn399x(qcadev->btsoc_type) ||
>  	     qca_is_wcn6750(qcadev->btsoc_type)) &&
> -	     power->vregs_on)
> +	     qcadev->vregs_on)
>  		qca_power_shutdown(&qcadev->serdev_hu);
>  	else if (qcadev->susclk)
>  		clk_disable_unprepare(qcadev->susclk);
> -- 
> 2.30.2
>
Bjorn Andersson July 14, 2021, 5:27 p.m. UTC | #2
On Mon 21 Jun 17:31 CDT 2021, Dmitry Baryshkov wrote:

> In order to simplify probe function provide default device data. This

> removes the rest of if (data) checks.

> 


Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>


Regards,
Bjorn

> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>

> ---

>  drivers/bluetooth/hci_qca.c | 24 ++++++++++++++----------

>  1 file changed, 14 insertions(+), 10 deletions(-)

> 

> diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c

> index 53deea2eb7b4..3704dbadba1d 100644

> --- a/drivers/bluetooth/hci_qca.c

> +++ b/drivers/bluetooth/hci_qca.c

> @@ -1874,6 +1874,11 @@ static const struct qca_device_data qca_soc_data_wcn6750 = {

>  	.capabilities = QCA_CAP_WIDEBAND_SPEECH | QCA_CAP_VALID_LE_STATES,

>  };

>  

> +static const struct qca_device_data qca_soc_data_default = {

> +	.soc_type = QCA_ROME,

> +	.num_vregs = 0,

> +};

> +

>  static void qca_power_shutdown(struct hci_uart *hu)

>  {

>  	struct qca_serdev *qcadev;

> @@ -2019,12 +2024,15 @@ static int qca_serdev_probe(struct serdev_device *serdev)

>  	int err;

>  	bool power_ctrl_enabled = true;

>  

> +	data = device_get_match_data(&serdev->dev);

> +	if (!data)

> +		return -EINVAL;

> +

>  	qcadev = devm_kzalloc(&serdev->dev, sizeof(*qcadev), GFP_KERNEL);

>  	if (!qcadev)

>  		return -ENOMEM;

>  

>  	qcadev->serdev_hu.serdev = serdev;

> -	data = device_get_match_data(&serdev->dev);

>  	serdev_device_set_drvdata(serdev, qcadev);

>  	device_property_read_string(&serdev->dev, "firmware-name",

>  					 &qcadev->firmware_name);

> @@ -2033,9 +2041,8 @@ static int qca_serdev_probe(struct serdev_device *serdev)

>  	if (!qcadev->oper_speed)

>  		BT_DBG("UART will pick default operating speed");

>  

> -	if (data &&

> -	    (qca_is_wcn399x(data->soc_type) ||

> -	    qca_is_wcn6750(data->soc_type))) {

> +	if ((qca_is_wcn399x(data->soc_type) ||

> +	     qca_is_wcn6750(data->soc_type))) {

>  		qcadev->btsoc_type = data->soc_type;

>  		qcadev->bt_power = devm_kzalloc(&serdev->dev,

>  						sizeof(struct qca_power),

> @@ -2077,10 +2084,7 @@ static int qca_serdev_probe(struct serdev_device *serdev)

>  			return err;

>  		}

>  	} else {

> -		if (data)

> -			qcadev->btsoc_type = data->soc_type;

> -		else

> -			qcadev->btsoc_type = QCA_ROME;

> +		qcadev->btsoc_type = data->soc_type;

>  

>  		qcadev->bt_en = devm_gpiod_get_optional(&serdev->dev, "enable",

>  					       GPIOD_OUT_LOW);

> @@ -2309,9 +2313,9 @@ static SIMPLE_DEV_PM_OPS(qca_pm_ops, qca_suspend, qca_resume);

>  

>  #ifdef CONFIG_OF

>  static const struct of_device_id qca_bluetooth_of_match[] = {

> -	{ .compatible = "qcom,qca6174-bt" },

> +	{ .compatible = "qcom,qca6174-bt", .data = &qca_soc_data_default},

>  	{ .compatible = "qcom,qca6390-bt", .data = &qca_soc_data_qca6390},

> -	{ .compatible = "qcom,qca9377-bt" },

> +	{ .compatible = "qcom,qca9377-bt", .data = &qca_soc_data_default},

>  	{ .compatible = "qcom,wcn3990-bt", .data = &qca_soc_data_wcn3990},

>  	{ .compatible = "qcom,wcn3991-bt", .data = &qca_soc_data_wcn3991},

>  	{ .compatible = "qcom,wcn3998-bt", .data = &qca_soc_data_wcn3998},

> -- 

> 2.30.2

>