Skip to content

Commit 6140d18

Browse files
author
Bartosz Golaszewski
committed
PCI/pwrctl: Add a PCI power control driver for power sequenced devices
Add a PCI power control driver that's capable of correctly powering up devices using the power sequencing subsystem. The first users of this driver are the ath11k module on QCA6390 and ath12k on WCN7850. These packages require a certain delay between enabling the Bluetooth and WLAN modules and the power sequencing subsystem takes care of it behind the scenes. Tested-by: Amit Pundir <[email protected]> Tested-by: Neil Armstrong <[email protected]> # on SM8550-QRD, SM8650-QRD & SM8650-HDK Tested-by: Caleb Connolly <[email protected]> # OnePlus 8T Acked-by: Bjorn Helgaas <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Bartosz Golaszewski <[email protected]>
1 parent 4565d26 commit 6140d18

File tree

3 files changed

+100
-0
lines changed

3 files changed

+100
-0
lines changed

drivers/pci/pwrctl/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,13 @@ menu "PCI Power control drivers"
55
config PCI_PWRCTL
66
tristate
77

8+
config PCI_PWRCTL_PWRSEQ
9+
tristate "PCI Power Control driver using the Power Sequencing subsystem"
10+
select POWER_SEQUENCING
11+
select PCI_PWRCTL
12+
default m if ((ATH11K_PCI || ATH12K) && ARCH_QCOM)
13+
help
14+
Enable support for the PCI power control driver for device
15+
drivers using the Power Sequencing subsystem.
16+
817
endmenu

drivers/pci/pwrctl/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@
22

33
obj-$(CONFIG_PCI_PWRCTL) += pci-pwrctl-core.o
44
pci-pwrctl-core-y := core.o
5+
6+
obj-$(CONFIG_PCI_PWRCTL_PWRSEQ) += pci-pwrctl-pwrseq.o
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/*
3+
* Copyright (C) 2024 Linaro Ltd.
4+
*/
5+
6+
#include <linux/device.h>
7+
#include <linux/mod_devicetable.h>
8+
#include <linux/module.h>
9+
#include <linux/of.h>
10+
#include <linux/pci-pwrctl.h>
11+
#include <linux/platform_device.h>
12+
#include <linux/pwrseq/consumer.h>
13+
#include <linux/slab.h>
14+
#include <linux/types.h>
15+
16+
struct pci_pwrctl_pwrseq_data {
17+
struct pci_pwrctl ctx;
18+
struct pwrseq_desc *pwrseq;
19+
};
20+
21+
static void devm_pci_pwrctl_pwrseq_power_off(void *data)
22+
{
23+
struct pwrseq_desc *pwrseq = data;
24+
25+
pwrseq_power_off(pwrseq);
26+
}
27+
28+
static int pci_pwrctl_pwrseq_probe(struct platform_device *pdev)
29+
{
30+
struct pci_pwrctl_pwrseq_data *data;
31+
struct device *dev = &pdev->dev;
32+
int ret;
33+
34+
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
35+
if (!data)
36+
return -ENOMEM;
37+
38+
data->pwrseq = devm_pwrseq_get(dev, of_device_get_match_data(dev));
39+
if (IS_ERR(data->pwrseq))
40+
return dev_err_probe(dev, PTR_ERR(data->pwrseq),
41+
"Failed to get the power sequencer\n");
42+
43+
ret = pwrseq_power_on(data->pwrseq);
44+
if (ret)
45+
return dev_err_probe(dev, ret,
46+
"Failed to power-on the device\n");
47+
48+
ret = devm_add_action_or_reset(dev, devm_pci_pwrctl_pwrseq_power_off,
49+
data->pwrseq);
50+
if (ret)
51+
return ret;
52+
53+
data->ctx.dev = dev;
54+
55+
ret = devm_pci_pwrctl_device_set_ready(dev, &data->ctx);
56+
if (ret)
57+
return dev_err_probe(dev, ret,
58+
"Failed to register the pwrctl wrapper\n");
59+
60+
return 0;
61+
}
62+
63+
static const struct of_device_id pci_pwrctl_pwrseq_of_match[] = {
64+
{
65+
/* ATH11K in QCA6390 package. */
66+
.compatible = "pci17cb,1101",
67+
.data = "wlan",
68+
},
69+
{
70+
/* ATH12K in WCN7850 package. */
71+
.compatible = "pci17cb,1107",
72+
.data = "wlan",
73+
},
74+
{ }
75+
};
76+
MODULE_DEVICE_TABLE(of, pci_pwrctl_pwrseq_of_match);
77+
78+
static struct platform_driver pci_pwrctl_pwrseq_driver = {
79+
.driver = {
80+
.name = "pci-pwrctl-pwrseq",
81+
.of_match_table = pci_pwrctl_pwrseq_of_match,
82+
},
83+
.probe = pci_pwrctl_pwrseq_probe,
84+
};
85+
module_platform_driver(pci_pwrctl_pwrseq_driver);
86+
87+
MODULE_AUTHOR("Bartosz Golaszewski <[email protected]>");
88+
MODULE_DESCRIPTION("Generic PCI Power Control module for power sequenced devices");
89+
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)