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(dev->driver);
36 struct gb_module *gmod = to_gb_module(dev);
37 const struct greybus_module_id *id;
39 id = gb_module_match_id(gmod, driver->id_table);
42 /* FIXME - Dyanmic ids? */
46 static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env)
48 /* struct gb_module *gmod = to_gb_module(dev); */
50 /* FIXME - add some uevents here... */
52 /* FIXME - be sure to check the type to know how to handle modules and
53 * interfaces differently */
58 struct bus_type greybus_bus_type = {
60 .match = greybus_module_match,
61 .uevent = greybus_uevent,
64 static int greybus_probe(struct device *dev)
66 struct greybus_driver *driver = to_greybus_driver(dev->driver);
67 struct gb_module *gmod = to_gb_module(dev);
68 const struct greybus_module_id *id;
72 id = gb_module_match_id(gmod, driver->id_table);
76 retval = driver->probe(gmod, id);
83 static int greybus_remove(struct device *dev)
85 struct greybus_driver *driver = to_greybus_driver(dev->driver);
86 struct gb_module *gmod = to_gb_module(dev);
88 driver->disconnect(gmod);
92 int greybus_register_driver(struct greybus_driver *driver, struct module *owner,
97 if (greybus_disabled())
100 driver->driver.name = driver->name;
101 driver->driver.probe = greybus_probe;
102 driver->driver.remove = greybus_remove;
103 driver->driver.owner = owner;
104 driver->driver.mod_name = mod_name;
106 retval = driver_register(&driver->driver);
110 pr_info("registered new driver %s\n", driver->name);
113 EXPORT_SYMBOL_GPL(greybus_register_driver);
115 void greybus_deregister(struct greybus_driver *driver)
117 driver_unregister(&driver->driver);
119 EXPORT_SYMBOL_GPL(greybus_deregister);
122 static const struct greybus_module_id fake_greybus_module_id = {
123 GREYBUS_DEVICE(0x42, 0x42)
130 * Pass in a buffer that _should_ contain a Greybus module manifest
131 * and register a greybus device structure with the kernel core.
133 void gb_add_module(struct greybus_host_device *hd, u8 module_id,
136 struct gb_module *gmod;
138 gmod = gb_module_create(hd, module_id);
140 dev_err(hd->parent, "failed to create module\n");
145 * Parse the manifest and build up our data structures
146 * representing what's in it.
148 if (!gb_manifest_parse(gmod, data, size)) {
149 dev_err(hd->parent, "manifest error\n");
155 * We've successfully parsed the manifest. Now we need to
156 * allocate CPort Id's for connecting to the CPorts found on
157 * other modules. For each of these, establish a connection
158 * between the local and remote CPorts (including
159 * configuring the switch to allow them to communicate).
165 gb_module_destroy(gmod);
168 void gb_remove_module(struct greybus_host_device *hd, u8 module_id)
170 struct gb_module *gmod;
173 list_for_each_entry(gmod, &hd->modules, links)
174 if (gmod->module_id == module_id) {
180 gb_module_destroy(gmod);
182 dev_err(hd->parent, "module id %d remove error\n", module_id);
185 static void gb_remove_modules(struct greybus_host_device *hd)
187 struct gb_module *gmod, *temp;
189 list_for_each_entry_safe(gmod, temp, &hd->modules, links) {
190 gb_module_destroy(gmod);
194 static DEFINE_MUTEX(hd_mutex);
196 static void free_hd(struct kref *kref)
198 struct greybus_host_device *hd;
200 hd = container_of(kref, struct greybus_host_device, kref);
203 mutex_unlock(&hd_mutex);
206 struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver,
207 struct device *parent)
209 struct greybus_host_device *hd;
212 * Validate that the driver implements all of the callbacks
213 * so that we don't have to every time we make them.
215 if ((!driver->alloc_gbuf_data) ||
216 (!driver->free_gbuf_data) ||
217 (!driver->submit_svc) ||
218 (!driver->submit_gbuf) ||
219 (!driver->kill_gbuf)) {
220 pr_err("Must implement all greybus_host_driver callbacks!\n");
224 hd = kzalloc(sizeof(*hd) + driver->hd_priv_size, GFP_KERNEL);
228 kref_init(&hd->kref);
231 INIT_LIST_HEAD(&hd->modules);
232 hd->connections = RB_ROOT;
233 ida_init(&hd->cport_id_map);
234 spin_lock_init(&hd->cport_id_map_lock);
238 EXPORT_SYMBOL_GPL(greybus_create_hd);
240 void greybus_remove_hd(struct greybus_host_device *hd)
242 /* Tear down all modules that happen to be associated with this host
244 gb_remove_modules(hd);
245 kref_put_mutex(&hd->kref, free_hd, &hd_mutex);
247 EXPORT_SYMBOL_GPL(greybus_remove_hd);
249 static int __init gb_init(void)
253 BUILD_BUG_ON(HOST_DEV_CPORT_ID_MAX >= (long)CPORT_ID_BAD);
255 retval = gb_debugfs_init();
257 pr_err("debugfs failed\n");
261 retval = bus_register(&greybus_bus_type);
263 pr_err("bus_register failed\n");
267 retval = gb_ap_init();
269 pr_err("gb_ap_init failed\n");
273 retval = gb_gbuf_init();
275 pr_err("gb_gbuf_init failed\n");
279 retval = gb_operation_init();
281 pr_err("gb_operation_init failed\n");
282 goto error_operation;
285 retval = gb_tty_init();
287 pr_err("gb_tty_init failed\n");
303 bus_unregister(&greybus_bus_type);
306 gb_debugfs_cleanup();
311 static void __exit gb_exit(void)
317 bus_unregister(&greybus_bus_type);
318 gb_debugfs_cleanup();
321 module_init(gb_init);
322 module_exit(gb_exit);
324 MODULE_LICENSE("GPL");
325 MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@linuxfoundation.org>");