diff options
Diffstat (limited to 'drivers/staging/greybus/core.c')
-rw-r--r-- | drivers/staging/greybus/core.c | 349 |
1 files changed, 0 insertions, 349 deletions
diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c deleted file mode 100644 index e546c6431877..000000000000 --- a/drivers/staging/greybus/core.c +++ /dev/null @@ -1,349 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Greybus "Core" - * - * Copyright 2014-2015 Google Inc. - * Copyright 2014-2015 Linaro Ltd. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define CREATE_TRACE_POINTS -#include <linux/greybus.h> -#include "greybus_trace.h" - -#define GB_BUNDLE_AUTOSUSPEND_MS 3000 - -/* Allow greybus to be disabled at boot if needed */ -static bool nogreybus; -#ifdef MODULE -module_param(nogreybus, bool, 0444); -#else -core_param(nogreybus, nogreybus, bool, 0444); -#endif -int greybus_disabled(void) -{ - return nogreybus; -} -EXPORT_SYMBOL_GPL(greybus_disabled); - -static bool greybus_match_one_id(struct gb_bundle *bundle, - const struct greybus_bundle_id *id) -{ - if ((id->match_flags & GREYBUS_ID_MATCH_VENDOR) && - (id->vendor != bundle->intf->vendor_id)) - return false; - - if ((id->match_flags & GREYBUS_ID_MATCH_PRODUCT) && - (id->product != bundle->intf->product_id)) - return false; - - if ((id->match_flags & GREYBUS_ID_MATCH_CLASS) && - (id->class != bundle->class)) - return false; - - return true; -} - -static const struct greybus_bundle_id * -greybus_match_id(struct gb_bundle *bundle, const struct greybus_bundle_id *id) -{ - if (!id) - return NULL; - - for (; id->vendor || id->product || id->class || id->driver_info; - id++) { - if (greybus_match_one_id(bundle, id)) - return id; - } - - return NULL; -} - -static int greybus_match_device(struct device *dev, struct device_driver *drv) -{ - struct greybus_driver *driver = to_greybus_driver(drv); - struct gb_bundle *bundle; - const struct greybus_bundle_id *id; - - if (!is_gb_bundle(dev)) - return 0; - - bundle = to_gb_bundle(dev); - - id = greybus_match_id(bundle, driver->id_table); - if (id) - return 1; - /* FIXME - Dynamic ids? */ - return 0; -} - -static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env) -{ - struct gb_host_device *hd; - struct gb_module *module = NULL; - struct gb_interface *intf = NULL; - struct gb_control *control = NULL; - struct gb_bundle *bundle = NULL; - struct gb_svc *svc = NULL; - - if (is_gb_host_device(dev)) { - hd = to_gb_host_device(dev); - } else if (is_gb_module(dev)) { - module = to_gb_module(dev); - hd = module->hd; - } else if (is_gb_interface(dev)) { - intf = to_gb_interface(dev); - module = intf->module; - hd = intf->hd; - } else if (is_gb_control(dev)) { - control = to_gb_control(dev); - intf = control->intf; - module = intf->module; - hd = intf->hd; - } else if (is_gb_bundle(dev)) { - bundle = to_gb_bundle(dev); - intf = bundle->intf; - module = intf->module; - hd = intf->hd; - } else if (is_gb_svc(dev)) { - svc = to_gb_svc(dev); - hd = svc->hd; - } else { - dev_WARN(dev, "uevent for unknown greybus device \"type\"!\n"); - return -EINVAL; - } - - if (add_uevent_var(env, "BUS=%u", hd->bus_id)) - return -ENOMEM; - - if (module) { - if (add_uevent_var(env, "MODULE=%u", module->module_id)) - return -ENOMEM; - } - - if (intf) { - if (add_uevent_var(env, "INTERFACE=%u", intf->interface_id)) - return -ENOMEM; - if (add_uevent_var(env, "GREYBUS_ID=%08x/%08x", - intf->vendor_id, intf->product_id)) - return -ENOMEM; - } - - if (bundle) { - // FIXME - // add a uevent that can "load" a bundle type - // This is what we need to bind a driver to so use the info - // in gmod here as well - - if (add_uevent_var(env, "BUNDLE=%u", bundle->id)) - return -ENOMEM; - if (add_uevent_var(env, "BUNDLE_CLASS=%02x", bundle->class)) - return -ENOMEM; - } - - return 0; -} - -static void greybus_shutdown(struct device *dev) -{ - if (is_gb_host_device(dev)) { - struct gb_host_device *hd; - - hd = to_gb_host_device(dev); - gb_hd_shutdown(hd); - } -} - -struct bus_type greybus_bus_type = { - .name = "greybus", - .match = greybus_match_device, - .uevent = greybus_uevent, - .shutdown = greybus_shutdown, -}; - -static int greybus_probe(struct device *dev) -{ - struct greybus_driver *driver = to_greybus_driver(dev->driver); - struct gb_bundle *bundle = to_gb_bundle(dev); - const struct greybus_bundle_id *id; - int retval; - - /* match id */ - id = greybus_match_id(bundle, driver->id_table); - if (!id) - return -ENODEV; - - retval = pm_runtime_get_sync(&bundle->intf->dev); - if (retval < 0) { - pm_runtime_put_noidle(&bundle->intf->dev); - return retval; - } - - retval = gb_control_bundle_activate(bundle->intf->control, bundle->id); - if (retval) { - pm_runtime_put(&bundle->intf->dev); - return retval; - } - - /* - * Unbound bundle devices are always deactivated. During probe, the - * Runtime PM is set to enabled and active and the usage count is - * incremented. If the driver supports runtime PM, it should call - * pm_runtime_put() in its probe routine and pm_runtime_get_sync() - * in remove routine. - */ - pm_runtime_set_autosuspend_delay(dev, GB_BUNDLE_AUTOSUSPEND_MS); - pm_runtime_use_autosuspend(dev); - pm_runtime_get_noresume(dev); - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - - retval = driver->probe(bundle, id); - if (retval) { - /* - * Catch buggy drivers that fail to destroy their connections. - */ - WARN_ON(!list_empty(&bundle->connections)); - - gb_control_bundle_deactivate(bundle->intf->control, bundle->id); - - pm_runtime_disable(dev); - pm_runtime_set_suspended(dev); - pm_runtime_put_noidle(dev); - pm_runtime_dont_use_autosuspend(dev); - pm_runtime_put(&bundle->intf->dev); - - return retval; - } - - pm_runtime_put(&bundle->intf->dev); - - return 0; -} - -static int greybus_remove(struct device *dev) -{ - struct greybus_driver *driver = to_greybus_driver(dev->driver); - struct gb_bundle *bundle = to_gb_bundle(dev); - struct gb_connection *connection; - int retval; - - retval = pm_runtime_get_sync(dev); - if (retval < 0) - dev_err(dev, "failed to resume bundle: %d\n", retval); - - /* - * Disable (non-offloaded) connections early in case the interface is - * already gone to avoid unceccessary operation timeouts during - * driver disconnect. Otherwise, only disable incoming requests. - */ - list_for_each_entry(connection, &bundle->connections, bundle_links) { - if (gb_connection_is_offloaded(connection)) - continue; - - if (bundle->intf->disconnected) - gb_connection_disable_forced(connection); - else - gb_connection_disable_rx(connection); - } - - driver->disconnect(bundle); - - /* Catch buggy drivers that fail to destroy their connections. */ - WARN_ON(!list_empty(&bundle->connections)); - - if (!bundle->intf->disconnected) - gb_control_bundle_deactivate(bundle->intf->control, bundle->id); - - pm_runtime_put_noidle(dev); - pm_runtime_disable(dev); - pm_runtime_set_suspended(dev); - pm_runtime_dont_use_autosuspend(dev); - pm_runtime_put_noidle(dev); - - return 0; -} - -int greybus_register_driver(struct greybus_driver *driver, struct module *owner, - const char *mod_name) -{ - int retval; - - if (greybus_disabled()) - return -ENODEV; - - driver->driver.bus = &greybus_bus_type; - driver->driver.name = driver->name; - driver->driver.probe = greybus_probe; - driver->driver.remove = greybus_remove; - driver->driver.owner = owner; - driver->driver.mod_name = mod_name; - - retval = driver_register(&driver->driver); - if (retval) - return retval; - - pr_info("registered new driver %s\n", driver->name); - return 0; -} -EXPORT_SYMBOL_GPL(greybus_register_driver); - -void greybus_deregister_driver(struct greybus_driver *driver) -{ - driver_unregister(&driver->driver); -} -EXPORT_SYMBOL_GPL(greybus_deregister_driver); - -static int __init gb_init(void) -{ - int retval; - - if (greybus_disabled()) - return -ENODEV; - - BUILD_BUG_ON(CPORT_ID_MAX >= (long)CPORT_ID_BAD); - - gb_debugfs_init(); - - retval = bus_register(&greybus_bus_type); - if (retval) { - pr_err("bus_register failed (%d)\n", retval); - goto error_bus; - } - - retval = gb_hd_init(); - if (retval) { - pr_err("gb_hd_init failed (%d)\n", retval); - goto error_hd; - } - - retval = gb_operation_init(); - if (retval) { - pr_err("gb_operation_init failed (%d)\n", retval); - goto error_operation; - } - return 0; /* Success */ - -error_operation: - gb_hd_exit(); -error_hd: - bus_unregister(&greybus_bus_type); -error_bus: - gb_debugfs_cleanup(); - - return retval; -} -module_init(gb_init); - -static void __exit gb_exit(void) -{ - gb_operation_exit(); - gb_hd_exit(); - bus_unregister(&greybus_bus_type); - gb_debugfs_cleanup(); - tracepoint_synchronize_unregister(); -} -module_exit(gb_exit); -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@linuxfoundation.org>"); |