1131377Stjr// SPDX-License-Identifier: GPL-2.0 2311285Sdelphij/* 3131377Stjr * Greybus "Core" 417651Speter * 517651Speter * Copyright 2014-2015 Google Inc. 6131377Stjr * Copyright 2014-2015 Linaro Ltd. 7131377Stjr */ 8131377Stjr 9131377Stjr#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 10131377Stjr 11131377Stjr#define CREATE_TRACE_POINTS 12131377Stjr#include <linux/greybus.h> 13131377Stjr#include "greybus_trace.h" 14131377Stjr 15131377Stjr#define GB_BUNDLE_AUTOSUSPEND_MS 3000 16131377Stjr 17131377Stjr/* Allow greybus to be disabled at boot if needed */ 18131377Stjrstatic bool nogreybus; 19131377Stjr#ifdef MODULE 20131377Stjrmodule_param(nogreybus, bool, 0444); 21131377Stjr#else 22131377Stjrcore_param(nogreybus, nogreybus, bool, 0444); 23131377Stjr#endif 24131377Stjrint greybus_disabled(void) 25131377Stjr{ 26131377Stjr return nogreybus; 27131377Stjr} 28131377StjrEXPORT_SYMBOL_GPL(greybus_disabled); 29131377Stjr 30131377Stjrstatic int is_gb_host_device(const struct device *dev) 31131377Stjr{ 32131377Stjr return dev->type == &greybus_hd_type; 33131377Stjr} 34131377Stjr 35131377Stjrstatic int is_gb_module(const struct device *dev) 36131377Stjr{ 37131377Stjr return dev->type == &greybus_module_type; 38131377Stjr} 39131377Stjr 40131377Stjrstatic int is_gb_interface(const struct device *dev) 41131377Stjr{ 42131377Stjr return dev->type == &greybus_interface_type; 43131377Stjr} 44131377Stjr 45131377Stjrstatic int is_gb_control(const struct device *dev) 46131377Stjr{ 47131377Stjr return dev->type == &greybus_control_type; 48205194Sdelphij} 49131377Stjr 50131377Stjrstatic int is_gb_bundle(const struct device *dev) 51131377Stjr{ 52131377Stjr return dev->type == &greybus_bundle_type; 53131377Stjr} 54131377Stjr 55131377Stjrstatic int is_gb_svc(const struct device *dev) 56131377Stjr{ 57131377Stjr return dev->type == &greybus_svc_type; 58131377Stjr} 59131377Stjr 60131377Stjrstatic bool greybus_match_one_id(struct gb_bundle *bundle, 61131377Stjr const struct greybus_bundle_id *id) 62131377Stjr{ 63131377Stjr if ((id->match_flags & GREYBUS_ID_MATCH_VENDOR) && 64131377Stjr (id->vendor != bundle->intf->vendor_id)) 65131377Stjr return false; 66131377Stjr 67131377Stjr if ((id->match_flags & GREYBUS_ID_MATCH_PRODUCT) && 68131377Stjr (id->product != bundle->intf->product_id)) 69131377Stjr return false; 70131377Stjr 71131377Stjr if ((id->match_flags & GREYBUS_ID_MATCH_CLASS) && 72131377Stjr (id->class != bundle->class)) 73131377Stjr return false; 74131377Stjr 75131377Stjr return true; 76131377Stjr} 77131377Stjr 78131377Stjrstatic const struct greybus_bundle_id * 79131377Stjrgreybus_match_id(struct gb_bundle *bundle, const struct greybus_bundle_id *id) 80131377Stjr{ 81131377Stjr if (!id) 82131377Stjr return NULL; 8317651Speter 84131377Stjr for (; id->vendor || id->product || id->class || id->driver_info; 85131377Stjr id++) { 86131377Stjr if (greybus_match_one_id(bundle, id)) 8717651Speter return id; 88131377Stjr } 89131377Stjr 90131377Stjr return NULL; 91131377Stjr} 92131377Stjr 9317651Speterstatic int greybus_match_device(struct device *dev, struct device_driver *drv) 94131377Stjr{ 95311285Sdelphij struct greybus_driver *driver = to_greybus_driver(drv); 96131377Stjr struct gb_bundle *bundle; 97250224Sdelphij const struct greybus_bundle_id *id; 98250224Sdelphij 99131377Stjr if (!is_gb_bundle(dev)) 100131377Stjr return 0; 101131377Stjr 102250224Sdelphij bundle = to_gb_bundle(dev); 103131377Stjr 10417651Speter id = greybus_match_id(bundle, driver->id_table); 105311285Sdelphij if (id) 106311285Sdelphij return 1; 107311285Sdelphij /* FIXME - Dynamic ids? */ 108311285Sdelphij return 0; 109311285Sdelphij} 110311285Sdelphij 111311285Sdelphijstatic int greybus_uevent(const struct device *dev, struct kobj_uevent_env *env) 112311285Sdelphij{ 113311285Sdelphij const struct gb_host_device *hd; 114311285Sdelphij const struct gb_module *module = NULL; 115311285Sdelphij const struct gb_interface *intf = NULL; 116311285Sdelphij const struct gb_control *control = NULL; 117311285Sdelphij const struct gb_bundle *bundle = NULL; 118311285Sdelphij const struct gb_svc *svc = NULL; 119230837Sdelphij 120131377Stjr if (is_gb_host_device(dev)) { 121131377Stjr hd = to_gb_host_device(dev); 122131377Stjr } else if (is_gb_module(dev)) { 12333904Ssteve module = to_gb_module(dev); 124311285Sdelphij hd = module->hd; 125131377Stjr } else if (is_gb_interface(dev)) { 126131377Stjr intf = to_gb_interface(dev); 127131377Stjr module = intf->module; 128230837Sdelphij hd = intf->hd; 129230837Sdelphij } else if (is_gb_control(dev)) { 130131377Stjr control = to_gb_control(dev); 131131377Stjr intf = control->intf; 132131377Stjr module = intf->module; 133157043Sdes hd = intf->hd; 134157043Sdes } else if (is_gb_bundle(dev)) { 135131377Stjr bundle = to_gb_bundle(dev); 136131377Stjr intf = bundle->intf; 137131377Stjr module = intf->module; 138205194Sdelphij hd = intf->hd; 139205194Sdelphij } else if (is_gb_svc(dev)) { 140131377Stjr svc = to_gb_svc(dev); 141131377Stjr hd = svc->hd; 142131377Stjr } else { 14333904Ssteve dev_WARN(dev, "uevent for unknown greybus device \"type\"!\n"); 144230837Sdelphij return -EINVAL; 145230837Sdelphij } 146230837Sdelphij 147230837Sdelphij if (add_uevent_var(env, "BUS=%u", hd->bus_id)) 148230837Sdelphij return -ENOMEM; 149311285Sdelphij 150230837Sdelphij if (module) { 151230837Sdelphij if (add_uevent_var(env, "MODULE=%u", module->module_id)) 152230837Sdelphij return -ENOMEM; 153230837Sdelphij } 154230837Sdelphij 155230837Sdelphij if (intf) { 156230837Sdelphij if (add_uevent_var(env, "INTERFACE=%u", intf->interface_id)) 157205194Sdelphij return -ENOMEM; 158157043Sdes if (add_uevent_var(env, "GREYBUS_ID=%08x/%08x", 159205194Sdelphij intf->vendor_id, intf->product_id)) 160157043Sdes return -ENOMEM; 161205194Sdelphij } 162157043Sdes 163157043Sdes if (bundle) { 164205194Sdelphij // FIXME 165311285Sdelphij // add a uevent that can "load" a bundle type 166157043Sdes // This is what we need to bind a driver to so use the info 167205194Sdelphij // in gmod here as well 168205194Sdelphij 169205194Sdelphij if (add_uevent_var(env, "BUNDLE=%u", bundle->id)) 170205194Sdelphij return -ENOMEM; 171205194Sdelphij if (add_uevent_var(env, "BUNDLE_CLASS=%02x", bundle->class)) 172205194Sdelphij return -ENOMEM; 173205194Sdelphij } 174311285Sdelphij 175205194Sdelphij return 0; 176205194Sdelphij} 177205194Sdelphij 178205194Sdelphijstatic void greybus_shutdown(struct device *dev) 179205194Sdelphij{ 180205194Sdelphij if (is_gb_host_device(dev)) { 181205194Sdelphij struct gb_host_device *hd; 182205194Sdelphij 183205194Sdelphij hd = to_gb_host_device(dev); 184205194Sdelphij gb_hd_shutdown(hd); 185205194Sdelphij } 186205194Sdelphij} 187205194Sdelphij 188205194Sdelphijconst struct bus_type greybus_bus_type = { 189205194Sdelphij .name = "greybus", 190205194Sdelphij .match = greybus_match_device, 191205194Sdelphij .uevent = greybus_uevent, 192205194Sdelphij .shutdown = greybus_shutdown, 193157043Sdes}; 194157043Sdes 195131377Stjrstatic int greybus_probe(struct device *dev) 196131377Stjr{ 197131377Stjr struct greybus_driver *driver = to_greybus_driver(dev->driver); 198131377Stjr struct gb_bundle *bundle = to_gb_bundle(dev); 199131377Stjr const struct greybus_bundle_id *id; 200131377Stjr int retval; 201205194Sdelphij 202131377Stjr /* match id */ 20317651Speter id = greybus_match_id(bundle, driver->id_table); 204131377Stjr if (!id) 205131377Stjr return -ENODEV; 206131377Stjr 207131377Stjr retval = pm_runtime_get_sync(&bundle->intf->dev); 208131377Stjr if (retval < 0) { 209131377Stjr pm_runtime_put_noidle(&bundle->intf->dev); 210230837Sdelphij return retval; 211230837Sdelphij } 212230837Sdelphij 213131377Stjr retval = gb_control_bundle_activate(bundle->intf->control, bundle->id); 214131377Stjr if (retval) { 215230837Sdelphij pm_runtime_put(&bundle->intf->dev); 216131377Stjr return retval; 217230837Sdelphij } 218230837Sdelphij 219230837Sdelphij /* 220230837Sdelphij * Unbound bundle devices are always deactivated. During probe, the 221230837Sdelphij * Runtime PM is set to enabled and active and the usage count is 222230837Sdelphij * incremented. If the driver supports runtime PM, it should call 223131377Stjr * pm_runtime_put() in its probe routine and pm_runtime_get_sync() 224131377Stjr * in remove routine. 225131377Stjr */ 226131377Stjr pm_runtime_set_autosuspend_delay(dev, GB_BUNDLE_AUTOSUSPEND_MS); 227157043Sdes pm_runtime_use_autosuspend(dev); 228311285Sdelphij pm_runtime_get_noresume(dev); 229205194Sdelphij pm_runtime_set_active(dev); 230311285Sdelphij pm_runtime_enable(dev); 231205194Sdelphij 232205194Sdelphij retval = driver->probe(bundle, id); 233131377Stjr if (retval) { 234131377Stjr /* 235131377Stjr * Catch buggy drivers that fail to destroy their connections. 236205194Sdelphij */ 237131377Stjr WARN_ON(!list_empty(&bundle->connections)); 23817651Speter 239131377Stjr gb_control_bundle_deactivate(bundle->intf->control, bundle->id); 240131377Stjr 241131377Stjr pm_runtime_disable(dev); 242131377Stjr pm_runtime_set_suspended(dev); 24317651Speter pm_runtime_put_noidle(dev); 244131377Stjr pm_runtime_dont_use_autosuspend(dev); 24517651Speter pm_runtime_put(&bundle->intf->dev); 24617651Speter 247205194Sdelphij return retval; 248205194Sdelphij } 249205194Sdelphij 250205194Sdelphij pm_runtime_put(&bundle->intf->dev); 251205194Sdelphij 252205194Sdelphij return 0; 253205194Sdelphij} 254311285Sdelphij 255205194Sdelphijstatic int greybus_remove(struct device *dev) 256205194Sdelphij{ 257205194Sdelphij struct greybus_driver *driver = to_greybus_driver(dev->driver); 258205194Sdelphij struct gb_bundle *bundle = to_gb_bundle(dev); 259205194Sdelphij struct gb_connection *connection; 260205194Sdelphij int retval; 261311285Sdelphij 262205194Sdelphij retval = pm_runtime_get_sync(dev); 263311285Sdelphij if (retval < 0) 264311285Sdelphij dev_err(dev, "failed to resume bundle: %d\n", retval); 265205194Sdelphij 266205194Sdelphij /* 267205194Sdelphij * Disable (non-offloaded) connections early in case the interface is 268131377Stjr * already gone to avoid unceccessary operation timeouts during 269131377Stjr * driver disconnect. Otherwise, only disable incoming requests. 270131377Stjr */ 271131377Stjr list_for_each_entry(connection, &bundle->connections, bundle_links) { 272131377Stjr if (gb_connection_is_offloaded(connection)) 273131377Stjr continue; 274131377Stjr 275131377Stjr if (bundle->intf->disconnected) 276131377Stjr gb_connection_disable_forced(connection); 277131377Stjr else 278131377Stjr gb_connection_disable_rx(connection); 279131377Stjr } 280131377Stjr 281131377Stjr driver->disconnect(bundle); 282131377Stjr 283131377Stjr /* Catch buggy drivers that fail to destroy their connections. */ 284131377Stjr WARN_ON(!list_empty(&bundle->connections)); 28517651Speter 286131377Stjr if (!bundle->intf->disconnected) 287131377Stjr gb_control_bundle_deactivate(bundle->intf->control, bundle->id); 288131377Stjr 289131377Stjr pm_runtime_put_noidle(dev); 290131377Stjr pm_runtime_disable(dev); 291131377Stjr pm_runtime_set_suspended(dev); 292131377Stjr pm_runtime_dont_use_autosuspend(dev); 293131377Stjr pm_runtime_put_noidle(dev); 294131377Stjr 295131377Stjr return 0; 296131377Stjr} 297131377Stjr 298131377Stjrint greybus_register_driver(struct greybus_driver *driver, struct module *owner, 299131377Stjr const char *mod_name) 300131377Stjr{ 301131377Stjr int retval; 302131377Stjr 303131377Stjr if (greybus_disabled()) 304131377Stjr return -ENODEV; 305131377Stjr 306131377Stjr driver->driver.bus = &greybus_bus_type; 307131377Stjr driver->driver.name = driver->name; 308131377Stjr driver->driver.probe = greybus_probe; 309131377Stjr driver->driver.remove = greybus_remove; 310131377Stjr driver->driver.owner = owner; 311131377Stjr driver->driver.mod_name = mod_name; 312131377Stjr 313131377Stjr retval = driver_register(&driver->driver); 314131377Stjr if (retval) 315131377Stjr return retval; 316131377Stjr 317131377Stjr pr_info("registered new driver %s\n", driver->name); 318131377Stjr return 0; 31917651Speter} 32017651SpeterEXPORT_SYMBOL_GPL(greybus_register_driver); 321131377Stjr 322131377Stjrvoid greybus_deregister_driver(struct greybus_driver *driver) 32317651Speter{ 324131377Stjr driver_unregister(&driver->driver); 325131377Stjr} 326131377StjrEXPORT_SYMBOL_GPL(greybus_deregister_driver); 327131377Stjr 328131377Stjrstatic int __init gb_init(void) 32917651Speter{ 330131377Stjr int retval; 33117651Speter 332131377Stjr if (greybus_disabled()) 333131377Stjr return -ENODEV; 334131377Stjr 335131377Stjr BUILD_BUG_ON(CPORT_ID_MAX >= (long)CPORT_ID_BAD); 336131377Stjr 33717651Speter gb_debugfs_init(); 338131377Stjr 33917651Speter retval = bus_register(&greybus_bus_type); 340131377Stjr if (retval) { 341131377Stjr pr_err("bus_register failed (%d)\n", retval); 342131377Stjr goto error_bus; 343131377Stjr } 344131377Stjr 345131377Stjr retval = gb_hd_init(); 34617651Speter if (retval) { 347131377Stjr pr_err("gb_hd_init failed (%d)\n", retval); 348131377Stjr goto error_hd; 349131377Stjr } 350131377Stjr 351131377Stjr retval = gb_operation_init(); 352131377Stjr if (retval) { 353131377Stjr pr_err("gb_operation_init failed (%d)\n", retval); 354131377Stjr goto error_operation; 355131377Stjr } 356131377Stjr return 0; /* Success */ 357131377Stjr 358131377Stjrerror_operation: 359131377Stjr gb_hd_exit(); 360131377Stjrerror_hd: 361131377Stjr bus_unregister(&greybus_bus_type); 362230837Sdelphijerror_bus: 363230837Sdelphij gb_debugfs_cleanup(); 364131377Stjr 365131377Stjr return retval; 366131377Stjr} 367131377Stjrmodule_init(gb_init); 368131377Stjr 369131377Stjrstatic void __exit gb_exit(void) 370131377Stjr{ 371131377Stjr gb_operation_exit(); 372131377Stjr gb_hd_exit(); 373131377Stjr bus_unregister(&greybus_bus_type); 374131377Stjr gb_debugfs_cleanup(); 375131377Stjr tracepoint_synchronize_unregister(); 376131377Stjr} 377131377Stjrmodule_exit(gb_exit); 378131377StjrMODULE_LICENSE("GPL v2"); 37917651SpeterMODULE_AUTHOR("Greg Kroah-Hartman <gregkh@linuxfoundation.org>"); 380131377Stjr