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, bool, 0444);
27 int greybus_disabled(void)
31 EXPORT_SYMBOL_GPL(greybus_disabled);
33 static spinlock_t cport_id_map_lock;
35 static int greybus_module_match(struct device *dev, struct device_driver *drv)
37 struct greybus_driver *driver = to_greybus_driver(dev->driver);
38 struct gb_module *gmod = to_gb_module(dev);
39 const struct greybus_module_id *id;
41 id = gb_module_match_id(gmod, driver->id_table);
44 /* FIXME - Dyanmic ids? */
48 static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env)
50 /* struct gb_module *gmod = to_gb_module(dev); */
52 /* FIXME - add some uevents here... */
56 static struct bus_type greybus_bus_type = {
58 .match = greybus_module_match,
59 .uevent = greybus_uevent,
62 static int greybus_probe(struct device *dev)
64 struct greybus_driver *driver = to_greybus_driver(dev->driver);
65 struct gb_module *gmod = to_gb_module(dev);
66 const struct greybus_module_id *id;
70 id = gb_module_match_id(gmod, driver->id_table);
74 retval = driver->probe(gmod, id);
81 static int greybus_remove(struct device *dev)
83 struct greybus_driver *driver = to_greybus_driver(dev->driver);
84 struct gb_module *gmod = to_gb_module(dev);
86 driver->disconnect(gmod);
90 int greybus_register_driver(struct greybus_driver *driver, struct module *owner,
95 if (greybus_disabled())
98 driver->driver.name = driver->name;
99 driver->driver.probe = greybus_probe;
100 driver->driver.remove = greybus_remove;
101 driver->driver.owner = owner;
102 driver->driver.mod_name = mod_name;
104 retval = driver_register(&driver->driver);
108 pr_info("registered new driver %s\n", driver->name);
111 EXPORT_SYMBOL_GPL(greybus_register_driver);
113 void greybus_deregister(struct greybus_driver *driver)
115 driver_unregister(&driver->driver);
117 EXPORT_SYMBOL_GPL(greybus_deregister);
120 static void greybus_module_release(struct device *dev)
122 struct gb_module *gmod = to_gb_module(dev);
125 for (i = 0; i < gmod->num_strings; ++i)
126 kfree(gmod->string[i]);
131 static struct device_type greybus_module_type = {
132 .name = "greybus_module",
133 .release = greybus_module_release,
137 * This needs to be driven by the list of functions that the
138 * manifest says are present.
140 static int gb_init_subdevs(struct gb_module *gmod,
141 const struct greybus_module_id *id)
145 /* Allocate all of the different "sub device types" for this device */
148 * Decide what exactly we should get supplied for the i2c
149 * probe, and then work that back to what should be present
152 retval = gb_i2c_probe(gmod, id);
156 retval = gb_gpio_probe(gmod, id);
160 retval = gb_sdio_probe(gmod, id);
164 retval = gb_tty_probe(gmod, id);
168 retval = gb_battery_probe(gmod, id);
174 gb_tty_disconnect(gmod);
177 gb_sdio_disconnect(gmod);
180 gb_gpio_disconnect(gmod);
183 gb_i2c_disconnect(gmod);
189 static const struct greybus_module_id fake_greybus_module_id = {
190 GREYBUS_DEVICE(0x42, 0x42)
197 * Pass in a buffer that _should_ contain a Greybus module manifest
198 * and register a greybus device structure with the kernel core.
200 void gb_add_module(struct greybus_host_device *hd, u8 module_id,
203 struct gb_module *gmod;
207 * Parse the manifest and build up our data structures
208 * representing what's in it.
210 gmod = gb_manifest_parse(data, size);
212 dev_err(hd->parent, "manifest error\n");
218 * We've successfully parsed the manifest. Now we need to
219 * allocate CPort Id's for connecting to the CPorts found on
220 * other modules. For each of these, establish a connection
221 * between the local and remote CPorts (including
222 * configuring the switch to allow them to communicate).
225 gmod->dev.parent = hd->parent;
226 gmod->dev.driver = NULL;
227 gmod->dev.bus = &greybus_bus_type;
228 gmod->dev.type = &greybus_module_type;
229 gmod->dev.groups = greybus_module_groups;
230 gmod->dev.dma_mask = hd->parent->dma_mask;
231 device_initialize(&gmod->dev);
232 dev_set_name(&gmod->dev, "%d", module_id);
234 retval = gb_init_subdevs(gmod, &fake_greybus_module_id);
238 // FIXME device_add(&gmod->dev);
243 put_device(&gmod->dev);
244 greybus_module_release(&gmod->dev);
247 void gb_remove_module(struct greybus_host_device *hd, u8 module_id)
249 // FIXME should be the remove_device call...
252 void greybus_remove_device(struct gb_module *gmod)
254 /* tear down all of the "sub device types" for this device */
255 gb_i2c_disconnect(gmod);
256 gb_gpio_disconnect(gmod);
257 gb_sdio_disconnect(gmod);
258 gb_tty_disconnect(gmod);
259 gb_battery_disconnect(gmod);
261 // FIXME - device_remove(&gmod->dev);
264 static DEFINE_MUTEX(hd_mutex);
267 * Allocate an available CPort Id for use on the given host device.
268 * Returns the CPort Id, or CPORT_ID_BAD of none remain.
270 * The lowest-available id is returned, so the first call is
271 * guaranteed to allocate CPort Id 0.
273 u16 greybus_hd_cport_id_alloc(struct greybus_host_device *hd)
275 unsigned long cport_id;
277 /* If none left, return BAD */
278 if (hd->cport_id_count == HOST_DEV_CPORT_ID_MAX)
281 spin_lock_irq(&cport_id_map_lock);
282 cport_id = find_next_zero_bit(hd->cport_id_map, hd->cport_id_count,
283 hd->cport_id_next_free);
284 if (cport_id < hd->cport_id_count) {
285 hd->cport_id_next_free = cport_id + 1; /* Success */
286 hd->cport_id_count++;
288 /* Lost a race for the last one */
289 if (hd->cport_id_count != HOST_DEV_CPORT_ID_MAX) {
290 pr_err("bad cport_id_count in alloc");
291 hd->cport_id_count = HOST_DEV_CPORT_ID_MAX;
293 cport_id = CPORT_ID_BAD;
295 spin_unlock_irq(&cport_id_map_lock);
301 * Free a previously-allocated CPort Id on the given host device.
303 void greybus_hd_cport_id_free(struct greybus_host_device *hd, u16 cport_id)
305 if (cport_id >= HOST_DEV_CPORT_ID_MAX) {
306 pr_err("bad cport_id %hu\n", cport_id);
309 if (!hd->cport_id_count) {
310 pr_err("too many cport_id frees\n");
314 spin_lock_irq(&cport_id_map_lock);
315 if (test_and_clear_bit(cport_id, hd->cport_id_map)) {
316 if (hd->cport_id_count) {
317 hd->cport_id_count--;
318 if (cport_id < hd->cport_id_next_free)
319 hd->cport_id_next_free = cport_id;
321 pr_err("bad cport_id_count in free");
324 pr_err("duplicate cport_id %hu free\n", cport_id);
326 spin_unlock_irq(&cport_id_map_lock);
329 static void free_hd(struct kref *kref)
331 struct greybus_host_device *hd;
333 hd = container_of(kref, struct greybus_host_device, kref);
338 struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver,
339 struct device *parent)
341 struct greybus_host_device *hd;
343 hd = kzalloc(sizeof(*hd) + driver->hd_priv_size, GFP_KERNEL);
347 kref_init(&hd->kref);
350 INIT_LIST_HEAD(&hd->modules);
352 /* Pre-allocate CPort 0 for control stuff. XXX */
353 if (greybus_hd_cport_id_alloc(hd) != 0) {
354 pr_err("couldn't allocate cport 0\n");
361 EXPORT_SYMBOL_GPL(greybus_create_hd);
363 void greybus_remove_hd(struct greybus_host_device *hd)
365 kref_put_mutex(&hd->kref, free_hd, &hd_mutex);
367 EXPORT_SYMBOL_GPL(greybus_remove_hd);
370 static int __init gb_init(void)
374 BUILD_BUG_ON(HOST_DEV_CPORT_ID_MAX >= (long)CPORT_ID_BAD);
375 spin_lock_init(&cport_id_map_lock);
377 retval = gb_debugfs_init();
379 pr_err("debugfs failed\n");
383 retval = bus_register(&greybus_bus_type);
385 pr_err("bus_register failed\n");
389 retval = gb_ap_init();
391 pr_err("gb_ap_init failed\n");
395 retval = gb_gbuf_init();
397 pr_err("gb_gbuf_init failed\n");
401 retval = gb_tty_init();
403 pr_err("gb_tty_init failed\n");
416 bus_unregister(&greybus_bus_type);
419 gb_debugfs_cleanup();
424 static void __exit gb_exit(void)
429 bus_unregister(&greybus_bus_type);
430 gb_debugfs_cleanup();
433 module_init(gb_init);
434 module_exit(gb_exit);
436 MODULE_LICENSE("GPL");
437 MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@linuxfoundation.org>");