xref: /linux/drivers/pci/pwrctrl/core.c (revision c8b90d40d5bba8e6fba457b8a7c10d3c0d467e37)
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_pwrctrl_notify(struct notifier_block *nb, unsigned long action,
15 			      void *data)
16 {
17 	struct pci_pwrctrl *pwrctrl = container_of(nb, struct pci_pwrctrl, nb);
18 	struct device *dev = data;
19 
20 	if (dev_fwnode(dev) != dev_fwnode(pwrctrl->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_pwrctrl *pwrctrl = container_of(work,
44 						   struct pci_pwrctrl, work);
45 
46 	pci_lock_rescan_remove();
47 	pci_rescan_bus(to_pci_dev(pwrctrl->dev->parent)->bus);
48 	pci_unlock_rescan_remove();
49 }
50 
51 /**
52  * pci_pwrctrl_init() - Initialize the PCI power control context struct
53  *
54  * @pwrctrl: PCI power control data
55  * @dev: Parent device
56  */
57 void pci_pwrctrl_init(struct pci_pwrctrl *pwrctrl, struct device *dev)
58 {
59 	pwrctrl->dev = dev;
60 	INIT_WORK(&pwrctrl->work, rescan_work_func);
61 }
62 EXPORT_SYMBOL_GPL(pci_pwrctrl_init);
63 
64 /**
65  * pci_pwrctrl_device_set_ready() - Notify the pwrctrl subsystem that the PCI
66  * device is powered-up and ready to be detected.
67  *
68  * @pwrctrl: PCI power control data.
69  *
70  * Returns:
71  * 0 on success, negative error number on error.
72  *
73  * Note:
74  * This function returning 0 doesn't mean the device was detected. It means,
75  * that the bus rescan was successfully started. The device will get bound to
76  * its PCI driver asynchronously.
77  */
78 int pci_pwrctrl_device_set_ready(struct pci_pwrctrl *pwrctrl)
79 {
80 	int ret;
81 
82 	if (!pwrctrl->dev)
83 		return -ENODEV;
84 
85 	pwrctrl->nb.notifier_call = pci_pwrctrl_notify;
86 	ret = bus_register_notifier(&pci_bus_type, &pwrctrl->nb);
87 	if (ret)
88 		return ret;
89 
90 	schedule_work(&pwrctrl->work);
91 
92 	return 0;
93 }
94 EXPORT_SYMBOL_GPL(pci_pwrctrl_device_set_ready);
95 
96 /**
97  * pci_pwrctrl_device_unset_ready() - Notify the pwrctrl subsystem that the PCI
98  * device is about to be powered-down.
99  *
100  * @pwrctrl: PCI power control data.
101  */
102 void pci_pwrctrl_device_unset_ready(struct pci_pwrctrl *pwrctrl)
103 {
104 	/*
105 	 * We don't have to delete the link here. Typically, this function
106 	 * is only called when the power control device is being detached. If
107 	 * it is being detached then the child PCI device must have already
108 	 * been unbound too or the device core wouldn't let us unbind.
109 	 */
110 	bus_unregister_notifier(&pci_bus_type, &pwrctrl->nb);
111 }
112 EXPORT_SYMBOL_GPL(pci_pwrctrl_device_unset_ready);
113 
114 static void devm_pci_pwrctrl_device_unset_ready(void *data)
115 {
116 	struct pci_pwrctrl *pwrctrl = data;
117 
118 	pci_pwrctrl_device_unset_ready(pwrctrl);
119 }
120 
121 /**
122  * devm_pci_pwrctrl_device_set_ready - Managed variant of
123  * pci_pwrctrl_device_set_ready().
124  *
125  * @dev: Device managing this pwrctrl provider.
126  * @pwrctrl: PCI power control data.
127  *
128  * Returns:
129  * 0 on success, negative error number on error.
130  */
131 int devm_pci_pwrctrl_device_set_ready(struct device *dev,
132 				      struct pci_pwrctrl *pwrctrl)
133 {
134 	int ret;
135 
136 	ret = pci_pwrctrl_device_set_ready(pwrctrl);
137 	if (ret)
138 		return ret;
139 
140 	return devm_add_action_or_reset(dev,
141 					devm_pci_pwrctrl_device_unset_ready,
142 					pwrctrl);
143 }
144 EXPORT_SYMBOL_GPL(devm_pci_pwrctrl_device_set_ready);
145 
146 MODULE_AUTHOR("Bartosz Golaszewski <bartosz.golaszewski@linaro.org>");
147 MODULE_DESCRIPTION("PCI Device Power Control core driver");
148 MODULE_LICENSE("GPL");
149