xref: /linux/drivers/pci/pwrctrl/pci-pwrctrl-pwrseq.c (revision b88cbaaa6fa109c2eb455d8fe2a318de0d197ea2)
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-pwrctrl.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 	pci_pwrctl_init(&data->ctx, 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 		/* ATH11K in WCN6855 package. */
71 		.compatible = "pci17cb,1103",
72 		.data = "wlan",
73 	},
74 	{
75 		/* ATH12K in WCN7850 package. */
76 		.compatible = "pci17cb,1107",
77 		.data = "wlan",
78 	},
79 	{ }
80 };
81 MODULE_DEVICE_TABLE(of, pci_pwrctl_pwrseq_of_match);
82 
83 static struct platform_driver pci_pwrctl_pwrseq_driver = {
84 	.driver = {
85 		.name = "pci-pwrctl-pwrseq",
86 		.of_match_table = pci_pwrctl_pwrseq_of_match,
87 	},
88 	.probe = pci_pwrctl_pwrseq_probe,
89 };
90 module_platform_driver(pci_pwrctl_pwrseq_driver);
91 
92 MODULE_AUTHOR("Bartosz Golaszewski <bartosz.golaszewski@linaro.org>");
93 MODULE_DESCRIPTION("Generic PCI Power Control module for power sequenced devices");
94 MODULE_LICENSE("GPL");
95