xref: /openbmc/linux/drivers/dio/dio-driver.c (revision 275876e2)
1 /*
2  *  DIO Driver Services
3  *
4  *  Copyright (C) 2004 Jochen Friedrich
5  *
6  *  Loosely based on drivers/pci/pci-driver.c and drivers/zorro/zorro-driver.c
7  *
8  *  This file is subject to the terms and conditions of the GNU General Public
9  *  License.  See the file COPYING in the main directory of this archive
10  *  for more details.
11  */
12 
13 #include <linux/init.h>
14 #include <linux/module.h>
15 #include <linux/dio.h>
16 
17 
18 /**
19  *  dio_match_device - Tell if a DIO device structure has a matching DIO device id structure
20  *  @ids: array of DIO device id structures to search in
21  *  @d: the DIO device structure to match against
22  *
23  *  Used by a driver to check whether a DIO device present in the
24  *  system is in its list of supported devices. Returns the matching
25  *  dio_device_id structure or %NULL if there is no match.
26  */
27 
28 const struct dio_device_id *
29 dio_match_device(const struct dio_device_id *ids,
30 		   const struct dio_dev *d)
31 {
32 	while (ids->id) {
33 		if (ids->id == DIO_WILDCARD)
34 			return ids;
35 		if (DIO_NEEDSSECID(ids->id & 0xff)) {
36 			if (ids->id == d->id)
37 				return ids;
38 		} else {
39 			if ((ids->id & 0xff) == (d->id & 0xff))
40 				return ids;
41 		}
42 		ids++;
43 	}
44 	return NULL;
45 }
46 
47 static int dio_device_probe(struct device *dev)
48 {
49 	int error = 0;
50 	struct dio_driver *drv = to_dio_driver(dev->driver);
51 	struct dio_dev *d = to_dio_dev(dev);
52 
53 	if (!d->driver && drv->probe) {
54 		const struct dio_device_id *id;
55 
56 		id = dio_match_device(drv->id_table, d);
57 		if (id)
58 			error = drv->probe(d, id);
59 		if (error >= 0) {
60 			d->driver = drv;
61 			error = 0;
62 		}
63 	}
64 	return error;
65 }
66 
67 
68 /**
69  *  dio_register_driver - register a new DIO driver
70  *  @drv: the driver structure to register
71  *
72  *  Adds the driver structure to the list of registered drivers
73  *  Returns zero or a negative error value.
74  */
75 
76 int dio_register_driver(struct dio_driver *drv)
77 {
78 	/* initialize common driver fields */
79 	drv->driver.name = drv->name;
80 	drv->driver.bus = &dio_bus_type;
81 
82 	/* register with core */
83 	return driver_register(&drv->driver);
84 }
85 
86 
87 /**
88  *  dio_unregister_driver - unregister a DIO driver
89  *  @drv: the driver structure to unregister
90  *
91  *  Deletes the driver structure from the list of registered DIO drivers,
92  *  gives it a chance to clean up by calling its remove() function for
93  *  each device it was responsible for, and marks those devices as
94  *  driverless.
95  */
96 
97 void dio_unregister_driver(struct dio_driver *drv)
98 {
99 	driver_unregister(&drv->driver);
100 }
101 
102 
103 /**
104  *  dio_bus_match - Tell if a DIO device structure has a matching DIO device id structure
105  *  @dev: the DIO device structure to match against
106  *  @drv: the &device_driver that points to the array of DIO device id structures to search
107  *
108  *  Used by a driver to check whether a DIO device present in the
109  *  system is in its list of supported devices. Returns the matching
110  *  dio_device_id structure or %NULL if there is no match.
111  */
112 
113 static int dio_bus_match(struct device *dev, struct device_driver *drv)
114 {
115 	struct dio_dev *d = to_dio_dev(dev);
116 	struct dio_driver *dio_drv = to_dio_driver(drv);
117 	const struct dio_device_id *ids = dio_drv->id_table;
118 
119 	if (!ids)
120 		return 0;
121 
122 	return dio_match_device(ids, d) ? 1 : 0;
123 }
124 
125 
126 struct bus_type dio_bus_type = {
127 	.name	= "dio",
128 	.match	= dio_bus_match,
129 	.probe	= dio_device_probe,
130 };
131 
132 
133 static int __init dio_driver_init(void)
134 {
135 	return bus_register(&dio_bus_type);
136 }
137 
138 postcore_initcall(dio_driver_init);
139 
140 EXPORT_SYMBOL(dio_match_device);
141 EXPORT_SYMBOL(dio_register_driver);
142 EXPORT_SYMBOL(dio_unregister_driver);
143 EXPORT_SYMBOL(dio_bus_type);
144