lkml.org 
[lkml]   [2024]   [Feb]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v5 18/18] PCI/pwrctl: add a PCI power control driver for power sequenced devices
    Date
    From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>

    Add a PCI power control driver that's capable of correctly powering up
    devices using the power sequencing subsystem. The first user of this
    driver is the ath11k module on QCA6390.

    Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
    ---
    drivers/pci/pwrctl/Kconfig | 9 +++
    drivers/pci/pwrctl/Makefile | 1 +
    drivers/pci/pwrctl/pci-pwrctl-pwrseq.c | 84 ++++++++++++++++++++++++++
    3 files changed, 94 insertions(+)
    create mode 100644 drivers/pci/pwrctl/pci-pwrctl-pwrseq.c

    diff --git a/drivers/pci/pwrctl/Kconfig b/drivers/pci/pwrctl/Kconfig
    index b91170ebfb49..3880a88aa73b 100644
    --- a/drivers/pci/pwrctl/Kconfig
    +++ b/drivers/pci/pwrctl/Kconfig
    @@ -5,6 +5,15 @@ menu "PCI Power control drivers"
    config PCI_PWRCTL
    tristate

    +config PCI_PWRCTL_PWRSEQ
    + tristate "PCI Power Control driver using the Power Sequencing subsystem"
    + select POWER_SEQUENCING
    + select PCI_PWRCTL
    + default m if (ATH11K_PCI && ARCH_QCOM)
    + help
    + Enable support for the PCI power control driver for device
    + drivers using the Power Sequencing subsystem.
    +
    config PCI_PWRCTL_WCN7850
    tristate "PCI Power Control driver for WCN7850"
    select PCI_PWRCTL
    diff --git a/drivers/pci/pwrctl/Makefile b/drivers/pci/pwrctl/Makefile
    index de20c3af1b78..47ab9db1fb42 100644
    --- a/drivers/pci/pwrctl/Makefile
    +++ b/drivers/pci/pwrctl/Makefile
    @@ -3,4 +3,5 @@
    obj-$(CONFIG_PCI_PWRCTL) += pci-pwrctl-core.o
    pci-pwrctl-core-y := core.o

    +obj-$(CONFIG_PCI_PWRCTL_PWRSEQ) += pci-pwrctl-pwrseq.o
    obj-$(CONFIG_PCI_PWRCTL_WCN7850) += pci-pwrctl-wcn7850.o
    diff --git a/drivers/pci/pwrctl/pci-pwrctl-pwrseq.c b/drivers/pci/pwrctl/pci-pwrctl-pwrseq.c
    new file mode 100644
    index 000000000000..43820a727b3f
    --- /dev/null
    +++ b/drivers/pci/pwrctl/pci-pwrctl-pwrseq.c
    @@ -0,0 +1,84 @@
    +// SPDX-License-Identifier: GPL-2.0-only
    +/*
    + * Copyright (C) 2024 Linaro Ltd.
    + */
    +
    +#include <linux/device.h>
    +#include <linux/mod_devicetable.h>
    +#include <linux/module.h>
    +#include <linux/of.h>
    +#include <linux/pci-pwrctl.h>
    +#include <linux/platform_device.h>
    +#include <linux/pwrseq/consumer.h>
    +#include <linux/slab.h>
    +#include <linux/types.h>
    +
    +struct pci_pwrctl_pwrseq_data {
    + struct pci_pwrctl ctx;
    + struct pwrseq_desc *pwrseq;
    +};
    +
    +static void devm_pci_pwrctl_pwrseq_power_off(void *data)
    +{
    + struct pwrseq_desc *pwrseq = data;
    +
    + pwrseq_power_off(pwrseq);
    +}
    +
    +static int pci_pwrctl_pwrseq_probe(struct platform_device *pdev)
    +{
    + struct pci_pwrctl_pwrseq_data *data;
    + struct device *dev = &pdev->dev;
    + int ret;
    +
    + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
    + if (!data)
    + return -ENOMEM;
    +
    + data->pwrseq = devm_pwrseq_get(dev, of_device_get_match_data(dev));
    + if (IS_ERR(data->pwrseq))
    + return dev_err_probe(dev, PTR_ERR(data->pwrseq),
    + "Failed to get the power sequencer\n");
    +
    + ret = pwrseq_power_on(data->pwrseq);
    + if (ret)
    + return dev_err_probe(dev, ret,
    + "Failed to power-on the device\n");
    +
    + ret = devm_add_action_or_reset(dev, devm_pci_pwrctl_pwrseq_power_off,
    + data->pwrseq);
    + if (ret)
    + return ret;
    +
    + data->ctx.dev = dev;
    +
    + ret = devm_pci_pwrctl_device_set_ready(dev, &data->ctx);
    + if (ret)
    + return dev_err_probe(dev, ret,
    + "Failed to register the pwrctl wrapper\n");
    +
    + return 0;
    +}
    +
    +static const struct of_device_id pci_pwrctl_pwrseq_of_match[] = {
    + {
    + /* ATH11K in QCA6390 package. */
    + .compatible = "pci17cb,1101",
    + .data = "wlan",
    + },
    + { }
    +};
    +MODULE_DEVICE_TABLE(of, pci_pwrctl_pwrseq_of_match);
    +
    +static struct platform_driver pci_pwrctl_pwrseq_driver = {
    + .driver = {
    + .name = "pci-pwrctl-pwrseq",
    + .of_match_table = pci_pwrctl_pwrseq_of_match,
    + },
    + .probe = pci_pwrctl_pwrseq_probe,
    +};
    +module_platform_driver(pci_pwrctl_pwrseq_driver);
    +
    +MODULE_AUTHOR("Bartosz Golaszewski <bartosz.golaszewski@linaro.org>");
    +MODULE_DESCRIPTION("Generic PCI Power Control module for power sequenced devices");
    +MODULE_LICENSE("GPL");
    --
    2.40.1

    \
     
     \ /
      Last update: 2024-05-27 15:07    [W:7.933 / U:0.756 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site