xref: /openbmc/linux/drivers/pnp/driver.c (revision a8fe58ce)
1 /*
2  * driver.c - device id matching, driver model, etc.
3  *
4  * Copyright 2002 Adam Belay <ambx1@neo.rr.com>
5  */
6 
7 #include <linux/string.h>
8 #include <linux/list.h>
9 #include <linux/module.h>
10 #include <linux/ctype.h>
11 #include <linux/slab.h>
12 #include <linux/pnp.h>
13 #include "base.h"
14 
15 static int compare_func(const char *ida, const char *idb)
16 {
17 	int i;
18 
19 	/* we only need to compare the last 4 chars */
20 	for (i = 3; i < 7; i++) {
21 		if (ida[i] != 'X' &&
22 		    idb[i] != 'X' && toupper(ida[i]) != toupper(idb[i]))
23 			return 0;
24 	}
25 	return 1;
26 }
27 
28 int compare_pnp_id(struct pnp_id *pos, const char *id)
29 {
30 	if (!pos || !id || (strlen(id) != 7))
31 		return 0;
32 	if (memcmp(id, "ANYDEVS", 7) == 0)
33 		return 1;
34 	while (pos) {
35 		if (memcmp(pos->id, id, 3) == 0)
36 			if (compare_func(pos->id, id) == 1)
37 				return 1;
38 		pos = pos->next;
39 	}
40 	return 0;
41 }
42 
43 static const struct pnp_device_id *match_device(struct pnp_driver *drv,
44 						struct pnp_dev *dev)
45 {
46 	const struct pnp_device_id *drv_id = drv->id_table;
47 
48 	if (!drv_id)
49 		return NULL;
50 
51 	while (*drv_id->id) {
52 		if (compare_pnp_id(dev->id, drv_id->id))
53 			return drv_id;
54 		drv_id++;
55 	}
56 	return NULL;
57 }
58 
59 int pnp_device_attach(struct pnp_dev *pnp_dev)
60 {
61 	mutex_lock(&pnp_lock);
62 	if (pnp_dev->status != PNP_READY) {
63 		mutex_unlock(&pnp_lock);
64 		return -EBUSY;
65 	}
66 	pnp_dev->status = PNP_ATTACHED;
67 	mutex_unlock(&pnp_lock);
68 	return 0;
69 }
70 
71 void pnp_device_detach(struct pnp_dev *pnp_dev)
72 {
73 	mutex_lock(&pnp_lock);
74 	if (pnp_dev->status == PNP_ATTACHED)
75 		pnp_dev->status = PNP_READY;
76 	mutex_unlock(&pnp_lock);
77 }
78 
79 static int pnp_device_probe(struct device *dev)
80 {
81 	int error;
82 	struct pnp_driver *pnp_drv;
83 	struct pnp_dev *pnp_dev;
84 	const struct pnp_device_id *dev_id = NULL;
85 	pnp_dev = to_pnp_dev(dev);
86 	pnp_drv = to_pnp_driver(dev->driver);
87 
88 	error = pnp_device_attach(pnp_dev);
89 	if (error < 0)
90 		return error;
91 
92 	if (pnp_dev->active == 0) {
93 		if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)) {
94 			error = pnp_activate_dev(pnp_dev);
95 			if (error < 0)
96 				return error;
97 		}
98 	} else if ((pnp_drv->flags & PNP_DRIVER_RES_DISABLE)
99 		   == PNP_DRIVER_RES_DISABLE) {
100 		error = pnp_disable_dev(pnp_dev);
101 		if (error < 0)
102 			return error;
103 	}
104 	error = 0;
105 	if (pnp_drv->probe) {
106 		dev_id = match_device(pnp_drv, pnp_dev);
107 		if (dev_id != NULL)
108 			error = pnp_drv->probe(pnp_dev, dev_id);
109 	}
110 	if (error >= 0) {
111 		pnp_dev->driver = pnp_drv;
112 		error = 0;
113 	} else
114 		goto fail;
115 
116 	return error;
117 
118 fail:
119 	pnp_device_detach(pnp_dev);
120 	return error;
121 }
122 
123 static int pnp_device_remove(struct device *dev)
124 {
125 	struct pnp_dev *pnp_dev = to_pnp_dev(dev);
126 	struct pnp_driver *drv = pnp_dev->driver;
127 
128 	if (drv) {
129 		if (drv->remove)
130 			drv->remove(pnp_dev);
131 		pnp_dev->driver = NULL;
132 	}
133 
134 	if (pnp_dev->active &&
135 	    (!drv || !(drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)))
136 		pnp_disable_dev(pnp_dev);
137 
138 	pnp_device_detach(pnp_dev);
139 	return 0;
140 }
141 
142 static void pnp_device_shutdown(struct device *dev)
143 {
144 	struct pnp_dev *pnp_dev = to_pnp_dev(dev);
145 	struct pnp_driver *drv = pnp_dev->driver;
146 
147 	if (drv && drv->shutdown)
148 		drv->shutdown(pnp_dev);
149 }
150 
151 static int pnp_bus_match(struct device *dev, struct device_driver *drv)
152 {
153 	struct pnp_dev *pnp_dev = to_pnp_dev(dev);
154 	struct pnp_driver *pnp_drv = to_pnp_driver(drv);
155 
156 	if (match_device(pnp_drv, pnp_dev) == NULL)
157 		return 0;
158 	return 1;
159 }
160 
161 static int __pnp_bus_suspend(struct device *dev, pm_message_t state)
162 {
163 	struct pnp_dev *pnp_dev = to_pnp_dev(dev);
164 	struct pnp_driver *pnp_drv = pnp_dev->driver;
165 	int error;
166 
167 	if (!pnp_drv)
168 		return 0;
169 
170 	if (pnp_drv->driver.pm && pnp_drv->driver.pm->suspend) {
171 		error = pnp_drv->driver.pm->suspend(dev);
172 		suspend_report_result(pnp_drv->driver.pm->suspend, error);
173 		if (error)
174 			return error;
175 	}
176 
177 	if (pnp_drv->suspend) {
178 		error = pnp_drv->suspend(pnp_dev, state);
179 		if (error)
180 			return error;
181 	}
182 
183 	if (pnp_can_disable(pnp_dev)) {
184 		error = pnp_stop_dev(pnp_dev);
185 		if (error)
186 			return error;
187 	}
188 
189 	if (pnp_can_suspend(pnp_dev))
190 		pnp_dev->protocol->suspend(pnp_dev, state);
191 	return 0;
192 }
193 
194 static int pnp_bus_suspend(struct device *dev)
195 {
196 	return __pnp_bus_suspend(dev, PMSG_SUSPEND);
197 }
198 
199 static int pnp_bus_freeze(struct device *dev)
200 {
201 	return __pnp_bus_suspend(dev, PMSG_FREEZE);
202 }
203 
204 static int pnp_bus_poweroff(struct device *dev)
205 {
206 	return __pnp_bus_suspend(dev, PMSG_HIBERNATE);
207 }
208 
209 static int pnp_bus_resume(struct device *dev)
210 {
211 	struct pnp_dev *pnp_dev = to_pnp_dev(dev);
212 	struct pnp_driver *pnp_drv = pnp_dev->driver;
213 	int error;
214 
215 	if (!pnp_drv)
216 		return 0;
217 
218 	if (pnp_dev->protocol->resume) {
219 		error = pnp_dev->protocol->resume(pnp_dev);
220 		if (error)
221 			return error;
222 	}
223 
224 	if (pnp_can_write(pnp_dev)) {
225 		error = pnp_start_dev(pnp_dev);
226 		if (error)
227 			return error;
228 	}
229 
230 	if (pnp_drv->driver.pm && pnp_drv->driver.pm->resume) {
231 		error = pnp_drv->driver.pm->resume(dev);
232 		if (error)
233 			return error;
234 	}
235 
236 	if (pnp_drv->resume) {
237 		error = pnp_drv->resume(pnp_dev);
238 		if (error)
239 			return error;
240 	}
241 
242 	return 0;
243 }
244 
245 static const struct dev_pm_ops pnp_bus_dev_pm_ops = {
246 	/* Suspend callbacks */
247 	.suspend = pnp_bus_suspend,
248 	.resume = pnp_bus_resume,
249 	/* Hibernate callbacks */
250 	.freeze = pnp_bus_freeze,
251 	.thaw = pnp_bus_resume,
252 	.poweroff = pnp_bus_poweroff,
253 	.restore = pnp_bus_resume,
254 };
255 
256 struct bus_type pnp_bus_type = {
257 	.name    = "pnp",
258 	.match   = pnp_bus_match,
259 	.probe   = pnp_device_probe,
260 	.remove  = pnp_device_remove,
261 	.shutdown = pnp_device_shutdown,
262 	.pm	 = &pnp_bus_dev_pm_ops,
263 	.dev_groups = pnp_dev_groups,
264 };
265 
266 int pnp_register_driver(struct pnp_driver *drv)
267 {
268 	drv->driver.name = drv->name;
269 	drv->driver.bus = &pnp_bus_type;
270 
271 	return driver_register(&drv->driver);
272 }
273 
274 void pnp_unregister_driver(struct pnp_driver *drv)
275 {
276 	driver_unregister(&drv->driver);
277 }
278 
279 /**
280  * pnp_add_id - adds an EISA id to the specified device
281  * @dev: pointer to the desired device
282  * @id: pointer to an EISA id string
283  */
284 struct pnp_id *pnp_add_id(struct pnp_dev *dev, const char *id)
285 {
286 	struct pnp_id *dev_id, *ptr;
287 
288 	dev_id = kzalloc(sizeof(struct pnp_id), GFP_KERNEL);
289 	if (!dev_id)
290 		return NULL;
291 
292 	dev_id->id[0] = id[0];
293 	dev_id->id[1] = id[1];
294 	dev_id->id[2] = id[2];
295 	dev_id->id[3] = tolower(id[3]);
296 	dev_id->id[4] = tolower(id[4]);
297 	dev_id->id[5] = tolower(id[5]);
298 	dev_id->id[6] = tolower(id[6]);
299 	dev_id->id[7] = '\0';
300 
301 	dev_id->next = NULL;
302 	ptr = dev->id;
303 	while (ptr && ptr->next)
304 		ptr = ptr->next;
305 	if (ptr)
306 		ptr->next = dev_id;
307 	else
308 		dev->id = dev_id;
309 
310 	return dev_id;
311 }
312 
313 EXPORT_SYMBOL(pnp_register_driver);
314 EXPORT_SYMBOL(pnp_unregister_driver);
315 EXPORT_SYMBOL(pnp_device_attach);
316 EXPORT_SYMBOL(pnp_device_detach);
317