4 * Copyright 2014 Google Inc.
6 * Released under the GPLv2 only.
9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11 #include <linux/types.h>
12 #include <linux/module.h>
13 #include <linux/moduleparam.h>
14 #include <linux/kernel.h>
15 #include <linux/slab.h>
16 #include <linux/device.h>
20 /* Allow greybus to be disabled at boot if needed */
21 static bool nogreybus;
23 module_param(nogreybus, bool, 0444);
25 core_param(nogreybus, nogreybus, bool, 0444);
27 int greybus_disabled(void)
31 EXPORT_SYMBOL_GPL(greybus_disabled);
33 static int greybus_module_match(struct device *dev, struct device_driver *drv)
35 struct greybus_driver *driver = to_greybus_driver(drv);
36 struct gb_interface_block *gb_ib = to_gb_interface_block(dev);
37 const struct greybus_module_id *id;
39 id = gb_ib_match_id(gb_ib, driver->id_table);
42 /* FIXME - Dynamic ids? */
46 static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env)
48 struct gb_interface_block *gb_ib = NULL;
49 struct gb_interface *interface = NULL;
50 struct gb_connection *connection = NULL;
52 if (is_gb_interface_block(dev)) {
53 gb_ib = to_gb_interface_block(dev);
54 } else if (is_gb_interface(dev)) {
55 interface = to_gb_interface(dev);
56 gb_ib = interface->gb_ib;
57 } else if (is_gb_connection(dev)) {
58 connection = to_gb_connection(dev);
59 interface = connection->interface;
60 gb_ib = interface->gb_ib;
62 dev_WARN(dev, "uevent for unknown greybus device \"type\"!\n");
68 // add a uevent that can "load" a connection type
74 // add a uevent that can "load" a interface type
75 // This is what we need to bind a driver to so use the info
76 // in gmod here as well
81 // "just" a module, be vague here, nothing binds to a module except
82 // the greybus core, so there's not much, if anything, we need to
87 struct bus_type greybus_bus_type = {
89 .match = greybus_module_match,
90 .uevent = greybus_uevent,
93 static int greybus_probe(struct device *dev)
95 struct greybus_driver *driver = to_greybus_driver(dev->driver);
96 struct gb_interface_block *gb_ib = to_gb_interface_block(dev);
97 const struct greybus_module_id *id;
101 id = gb_ib_match_id(gb_ib, driver->id_table);
105 retval = driver->probe(gb_ib, id);
112 static int greybus_remove(struct device *dev)
114 struct greybus_driver *driver = to_greybus_driver(dev->driver);
115 struct gb_interface_block *gb_ib = to_gb_interface_block(dev);
117 driver->disconnect(gb_ib);
121 int greybus_register_driver(struct greybus_driver *driver, struct module *owner,
122 const char *mod_name)
126 if (greybus_disabled())
129 driver->driver.name = driver->name;
130 driver->driver.probe = greybus_probe;
131 driver->driver.remove = greybus_remove;
132 driver->driver.owner = owner;
133 driver->driver.mod_name = mod_name;
135 retval = driver_register(&driver->driver);
139 pr_info("registered new driver %s\n", driver->name);
142 EXPORT_SYMBOL_GPL(greybus_register_driver);
144 void greybus_deregister(struct greybus_driver *driver)
146 driver_unregister(&driver->driver);
148 EXPORT_SYMBOL_GPL(greybus_deregister);
151 static DEFINE_MUTEX(hd_mutex);
153 static void free_hd(struct kref *kref)
155 struct greybus_host_device *hd;
157 hd = container_of(kref, struct greybus_host_device, kref);
160 mutex_unlock(&hd_mutex);
163 struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver,
164 struct device *parent)
166 struct greybus_host_device *hd;
169 * Validate that the driver implements all of the callbacks
170 * so that we don't have to every time we make them.
172 if ((!driver->buffer_send) || (!driver->buffer_cancel) ||
173 (!driver->submit_svc)) {
174 pr_err("Must implement all greybus_host_driver callbacks!\n");
178 hd = kzalloc(sizeof(*hd) + driver->hd_priv_size, GFP_KERNEL);
182 kref_init(&hd->kref);
185 INIT_LIST_HEAD(&hd->modules);
186 INIT_LIST_HEAD(&hd->connections);
187 ida_init(&hd->cport_id_map);
191 EXPORT_SYMBOL_GPL(greybus_create_hd);
193 void greybus_remove_hd(struct greybus_host_device *hd)
195 /* Tear down all modules that happen to be associated with this host
197 gb_remove_modules(hd);
198 kref_put_mutex(&hd->kref, free_hd, &hd_mutex);
200 EXPORT_SYMBOL_GPL(greybus_remove_hd);
202 static int __init gb_init(void)
206 BUILD_BUG_ON(HOST_DEV_CPORT_ID_MAX >= (long)CPORT_ID_BAD);
208 retval = gb_debugfs_init();
210 pr_err("debugfs failed\n");
214 retval = bus_register(&greybus_bus_type);
216 pr_err("bus_register failed\n");
220 retval = gb_ap_init();
222 pr_err("gb_ap_init failed\n");
226 retval = gb_operation_init();
228 pr_err("gb_operation_init failed\n");
229 goto error_operation;
232 if (!gb_protocol_init()) {
233 /* This only fails for duplicate protocol registration */
235 pr_err("gb_protocol_init failed\n");
239 return 0; /* Success */
246 bus_unregister(&greybus_bus_type);
248 gb_debugfs_cleanup();
253 static void __exit gb_exit(void)
258 bus_unregister(&greybus_bus_type);
259 gb_debugfs_cleanup();
262 module_init(gb_init);
263 module_exit(gb_exit);
265 MODULE_LICENSE("GPL");
266 MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@linuxfoundation.org>");