xref: /linux/drivers/pci/pwrctrl/core.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/export.h>
8 #include <linux/kernel.h>
9 #include <linux/pci.h>
10 #include <linux/pci-pwrctrl.h>
11 #include <linux/property.h>
12 #include <linux/slab.h>
13 
14 static int pci_pwrctl_notify(struct notifier_block *nb, unsigned long action,
15 			     void *data)
16 {
17 	struct pci_pwrctl *pwrctl = container_of(nb, struct pci_pwrctl, nb);
18 	struct device *dev = data;
19 
20 	if (dev_fwnode(dev) != dev_fwnode(pwrctl->dev))
21 		return NOTIFY_DONE;
22 
23 	switch (action) {
24 	case BUS_NOTIFY_ADD_DEVICE:
25 		/*
26 		 * We will have two struct device objects bound to two different
27 		 * drivers on different buses but consuming the same DT node. We
28 		 * must not bind the pins twice in this case but only once for
29 		 * the first device to be added.
30 		 *
31 		 * If we got here then the PCI device is the second after the
32 		 * power control platform device. Mark its OF node as reused.
33 		 */
34 		dev->of_node_reused = true;
35 		break;
36 	}
37 
38 	return NOTIFY_DONE;
39 }
40 
41 static void rescan_work_func(struct work_struct *work)
42 {
43 	struct pci_pwrctl *pwrctl = container_of(work, struct pci_pwrctl, work);
44 
45 	pci_lock_rescan_remove();
46 	pci_rescan_bus(to_pci_dev(pwrctl->dev->parent)->bus);
47 	pci_unlock_rescan_remove();
48 }
49 
50 /**
51  * pci_pwrctl_init() - Initialize the PCI power control context struct
52  *
53  * @pwrctl: PCI power control data
54  * @dev: Parent device
55  */
56 void pci_pwrctl_init(struct pci_pwrctl *pwrctl, struct device *dev)
57 {
58 	pwrctl->dev = dev;
59 	INIT_WORK(&pwrctl->work, rescan_work_func);
60 }
61 EXPORT_SYMBOL_GPL(pci_pwrctl_init);
62 
63 /**
64  * pci_pwrctl_device_set_ready() - Notify the pwrctl subsystem that the PCI
65  * device is powered-up and ready to be detected.
66  *
67  * @pwrctl: PCI power control data.
68  *
69  * Returns:
70  * 0 on success, negative error number on error.
71  *
72  * Note:
73  * This function returning 0 doesn't mean the device was detected. It means,
74  * that the bus rescan was successfully started. The device will get bound to
75  * its PCI driver asynchronously.
76  */
77 int pci_pwrctl_device_set_ready(struct pci_pwrctl *pwrctl)
78 {
79 	int ret;
80 
81 	if (!pwrctl->dev)
82 		return -ENODEV;
83 
84 	pwrctl->nb.notifier_call = pci_pwrctl_notify;
85 	ret = bus_register_notifier(&pci_bus_type, &pwrctl->nb);
86 	if (ret)
87 		return ret;
88 
89 	schedule_work(&pwrctl->work);
90 
91 	return 0;
92 }
93 EXPORT_SYMBOL_GPL(pci_pwrctl_device_set_ready);
94 
95 /**
96  * pci_pwrctl_device_unset_ready() - Notify the pwrctl subsystem that the PCI
97  * device is about to be powered-down.
98  *
99  * @pwrctl: PCI power control data.
100  */
101 void pci_pwrctl_device_unset_ready(struct pci_pwrctl *pwrctl)
102 {
103 	/*
104 	 * We don't have to delete the link here. Typically, this function
105 	 * is only called when the power control device is being detached. If
106 	 * it is being detached then the child PCI device must have already
107 	 * been unbound too or the device core wouldn't let us unbind.
108 	 */
109 	bus_unregister_notifier(&pci_bus_type, &pwrctl->nb);
110 }
111 EXPORT_SYMBOL_GPL(pci_pwrctl_device_unset_ready);
112 
113 static void devm_pci_pwrctl_device_unset_ready(void *data)
114 {
115 	struct pci_pwrctl *pwrctl = data;
116 
117 	pci_pwrctl_device_unset_ready(pwrctl);
118 }
119 
120 /**
121  * devm_pci_pwrctl_device_set_ready - Managed variant of
122  * pci_pwrctl_device_set_ready().
123  *
124  * @dev: Device managing this pwrctl provider.
125  * @pwrctl: PCI power control data.
126  *
127  * Returns:
128  * 0 on success, negative error number on error.
129  */
130 int devm_pci_pwrctl_device_set_ready(struct device *dev,
131 				     struct pci_pwrctl *pwrctl)
132 {
133 	int ret;
134 
135 	ret = pci_pwrctl_device_set_ready(pwrctl);
136 	if (ret)
137 		return ret;
138 
139 	return devm_add_action_or_reset(dev,
140 					devm_pci_pwrctl_device_unset_ready,
141 					pwrctl);
142 }
143 EXPORT_SYMBOL_GPL(devm_pci_pwrctl_device_set_ready);
144 
145 MODULE_AUTHOR("Bartosz Golaszewski <bartosz.golaszewski@linaro.org>");
146 MODULE_DESCRIPTION("PCI Device Power Control core driver");
147 MODULE_LICENSE("GPL");
148