root/drivers/staging/greybus/gbphy.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. protocol_id_show
  2. gbphy_dev_release
  3. gb_gbphy_idle
  4. gbphy_dev_uevent
  5. gbphy_dev_match_id
  6. gbphy_dev_match
  7. gbphy_dev_probe
  8. gbphy_dev_remove
  9. gb_gbphy_register_driver
  10. gb_gbphy_deregister_driver
  11. gb_gbphy_create_dev
  12. gb_gbphy_disconnect
  13. gb_gbphy_probe
  14. gbphy_init
  15. gbphy_exit

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Greybus Bridged-Phy Bus driver
   4  *
   5  * Copyright 2014 Google Inc.
   6  * Copyright 2014 Linaro Ltd.
   7  */
   8 
   9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  10 
  11 #include <linux/types.h>
  12 #include <linux/module.h>
  13 #include <linux/kernel.h>
  14 #include <linux/slab.h>
  15 #include <linux/device.h>
  16 #include <linux/greybus.h>
  17 
  18 #include "gbphy.h"
  19 
  20 #define GB_GBPHY_AUTOSUSPEND_MS 3000
  21 
  22 struct gbphy_host {
  23         struct gb_bundle *bundle;
  24         struct list_head devices;
  25 };
  26 
  27 static DEFINE_IDA(gbphy_id);
  28 
  29 static ssize_t protocol_id_show(struct device *dev,
  30                                  struct device_attribute *attr, char *buf)
  31 {
  32         struct gbphy_device *gbphy_dev = to_gbphy_dev(dev);
  33 
  34         return sprintf(buf, "0x%02x\n", gbphy_dev->cport_desc->protocol_id);
  35 }
  36 static DEVICE_ATTR_RO(protocol_id);
  37 
  38 static struct attribute *gbphy_dev_attrs[] = {
  39         &dev_attr_protocol_id.attr,
  40         NULL,
  41 };
  42 
  43 ATTRIBUTE_GROUPS(gbphy_dev);
  44 
  45 static void gbphy_dev_release(struct device *dev)
  46 {
  47         struct gbphy_device *gbphy_dev = to_gbphy_dev(dev);
  48 
  49         ida_simple_remove(&gbphy_id, gbphy_dev->id);
  50         kfree(gbphy_dev);
  51 }
  52 
  53 #ifdef CONFIG_PM
  54 static int gb_gbphy_idle(struct device *dev)
  55 {
  56         pm_runtime_mark_last_busy(dev);
  57         pm_request_autosuspend(dev);
  58         return 0;
  59 }
  60 #endif
  61 
  62 static const struct dev_pm_ops gb_gbphy_pm_ops = {
  63         SET_RUNTIME_PM_OPS(pm_generic_runtime_suspend,
  64                            pm_generic_runtime_resume,
  65                            gb_gbphy_idle)
  66 };
  67 
  68 static const struct device_type greybus_gbphy_dev_type = {
  69         .name    =      "gbphy_device",
  70         .release =      gbphy_dev_release,
  71         .pm     =       &gb_gbphy_pm_ops,
  72 };
  73 
  74 static int gbphy_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
  75 {
  76         struct gbphy_device *gbphy_dev = to_gbphy_dev(dev);
  77         struct greybus_descriptor_cport *cport_desc = gbphy_dev->cport_desc;
  78         struct gb_bundle *bundle = gbphy_dev->bundle;
  79         struct gb_interface *intf = bundle->intf;
  80         struct gb_module *module = intf->module;
  81         struct gb_host_device *hd = intf->hd;
  82 
  83         if (add_uevent_var(env, "BUS=%u", hd->bus_id))
  84                 return -ENOMEM;
  85         if (add_uevent_var(env, "MODULE=%u", module->module_id))
  86                 return -ENOMEM;
  87         if (add_uevent_var(env, "INTERFACE=%u", intf->interface_id))
  88                 return -ENOMEM;
  89         if (add_uevent_var(env, "GREYBUS_ID=%08x/%08x",
  90                            intf->vendor_id, intf->product_id))
  91                 return -ENOMEM;
  92         if (add_uevent_var(env, "BUNDLE=%u", gbphy_dev->bundle->id))
  93                 return -ENOMEM;
  94         if (add_uevent_var(env, "BUNDLE_CLASS=%02x", bundle->class))
  95                 return -ENOMEM;
  96         if (add_uevent_var(env, "GBPHY=%u", gbphy_dev->id))
  97                 return -ENOMEM;
  98         if (add_uevent_var(env, "PROTOCOL_ID=%02x", cport_desc->protocol_id))
  99                 return -ENOMEM;
 100 
 101         return 0;
 102 }
 103 
 104 static const struct gbphy_device_id *
 105 gbphy_dev_match_id(struct gbphy_device *gbphy_dev,
 106                    struct gbphy_driver *gbphy_drv)
 107 {
 108         const struct gbphy_device_id *id = gbphy_drv->id_table;
 109 
 110         if (!id)
 111                 return NULL;
 112 
 113         for (; id->protocol_id; id++)
 114                 if (id->protocol_id == gbphy_dev->cport_desc->protocol_id)
 115                         return id;
 116 
 117         return NULL;
 118 }
 119 
 120 static int gbphy_dev_match(struct device *dev, struct device_driver *drv)
 121 {
 122         struct gbphy_driver *gbphy_drv = to_gbphy_driver(drv);
 123         struct gbphy_device *gbphy_dev = to_gbphy_dev(dev);
 124         const struct gbphy_device_id *id;
 125 
 126         id = gbphy_dev_match_id(gbphy_dev, gbphy_drv);
 127         if (id)
 128                 return 1;
 129 
 130         return 0;
 131 }
 132 
 133 static int gbphy_dev_probe(struct device *dev)
 134 {
 135         struct gbphy_driver *gbphy_drv = to_gbphy_driver(dev->driver);
 136         struct gbphy_device *gbphy_dev = to_gbphy_dev(dev);
 137         const struct gbphy_device_id *id;
 138         int ret;
 139 
 140         id = gbphy_dev_match_id(gbphy_dev, gbphy_drv);
 141         if (!id)
 142                 return -ENODEV;
 143 
 144         /* for old kernels we need get_sync to resume parent devices */
 145         ret = gb_pm_runtime_get_sync(gbphy_dev->bundle);
 146         if (ret < 0)
 147                 return ret;
 148 
 149         pm_runtime_set_autosuspend_delay(dev, GB_GBPHY_AUTOSUSPEND_MS);
 150         pm_runtime_use_autosuspend(dev);
 151         pm_runtime_get_noresume(dev);
 152         pm_runtime_set_active(dev);
 153         pm_runtime_enable(dev);
 154 
 155         /*
 156          * Drivers should call put on the gbphy dev before returning
 157          * from probe if they support runtime pm.
 158          */
 159         ret = gbphy_drv->probe(gbphy_dev, id);
 160         if (ret) {
 161                 pm_runtime_disable(dev);
 162                 pm_runtime_set_suspended(dev);
 163                 pm_runtime_put_noidle(dev);
 164                 pm_runtime_dont_use_autosuspend(dev);
 165         }
 166 
 167         gb_pm_runtime_put_autosuspend(gbphy_dev->bundle);
 168 
 169         return ret;
 170 }
 171 
 172 static int gbphy_dev_remove(struct device *dev)
 173 {
 174         struct gbphy_driver *gbphy_drv = to_gbphy_driver(dev->driver);
 175         struct gbphy_device *gbphy_dev = to_gbphy_dev(dev);
 176 
 177         gbphy_drv->remove(gbphy_dev);
 178 
 179         pm_runtime_disable(dev);
 180         pm_runtime_set_suspended(dev);
 181         pm_runtime_put_noidle(dev);
 182         pm_runtime_dont_use_autosuspend(dev);
 183 
 184         return 0;
 185 }
 186 
 187 static struct bus_type gbphy_bus_type = {
 188         .name =         "gbphy",
 189         .match =        gbphy_dev_match,
 190         .probe =        gbphy_dev_probe,
 191         .remove =       gbphy_dev_remove,
 192         .uevent =       gbphy_dev_uevent,
 193 };
 194 
 195 int gb_gbphy_register_driver(struct gbphy_driver *driver,
 196                              struct module *owner, const char *mod_name)
 197 {
 198         int retval;
 199 
 200         if (greybus_disabled())
 201                 return -ENODEV;
 202 
 203         driver->driver.bus = &gbphy_bus_type;
 204         driver->driver.name = driver->name;
 205         driver->driver.owner = owner;
 206         driver->driver.mod_name = mod_name;
 207 
 208         retval = driver_register(&driver->driver);
 209         if (retval)
 210                 return retval;
 211 
 212         pr_info("registered new driver %s\n", driver->name);
 213         return 0;
 214 }
 215 EXPORT_SYMBOL_GPL(gb_gbphy_register_driver);
 216 
 217 void gb_gbphy_deregister_driver(struct gbphy_driver *driver)
 218 {
 219         driver_unregister(&driver->driver);
 220 }
 221 EXPORT_SYMBOL_GPL(gb_gbphy_deregister_driver);
 222 
 223 static struct gbphy_device *gb_gbphy_create_dev(struct gb_bundle *bundle,
 224                                 struct greybus_descriptor_cport *cport_desc)
 225 {
 226         struct gbphy_device *gbphy_dev;
 227         int retval;
 228         int id;
 229 
 230         id = ida_simple_get(&gbphy_id, 1, 0, GFP_KERNEL);
 231         if (id < 0)
 232                 return ERR_PTR(id);
 233 
 234         gbphy_dev = kzalloc(sizeof(*gbphy_dev), GFP_KERNEL);
 235         if (!gbphy_dev) {
 236                 ida_simple_remove(&gbphy_id, id);
 237                 return ERR_PTR(-ENOMEM);
 238         }
 239 
 240         gbphy_dev->id = id;
 241         gbphy_dev->bundle = bundle;
 242         gbphy_dev->cport_desc = cport_desc;
 243         gbphy_dev->dev.parent = &bundle->dev;
 244         gbphy_dev->dev.bus = &gbphy_bus_type;
 245         gbphy_dev->dev.type = &greybus_gbphy_dev_type;
 246         gbphy_dev->dev.groups = gbphy_dev_groups;
 247         gbphy_dev->dev.dma_mask = bundle->dev.dma_mask;
 248         dev_set_name(&gbphy_dev->dev, "gbphy%d", id);
 249 
 250         retval = device_register(&gbphy_dev->dev);
 251         if (retval) {
 252                 put_device(&gbphy_dev->dev);
 253                 return ERR_PTR(retval);
 254         }
 255 
 256         return gbphy_dev;
 257 }
 258 
 259 static void gb_gbphy_disconnect(struct gb_bundle *bundle)
 260 {
 261         struct gbphy_host *gbphy_host = greybus_get_drvdata(bundle);
 262         struct gbphy_device *gbphy_dev, *temp;
 263         int ret;
 264 
 265         ret = gb_pm_runtime_get_sync(bundle);
 266         if (ret < 0)
 267                 gb_pm_runtime_get_noresume(bundle);
 268 
 269         list_for_each_entry_safe(gbphy_dev, temp, &gbphy_host->devices, list) {
 270                 list_del(&gbphy_dev->list);
 271                 device_unregister(&gbphy_dev->dev);
 272         }
 273 
 274         kfree(gbphy_host);
 275 }
 276 
 277 static int gb_gbphy_probe(struct gb_bundle *bundle,
 278                           const struct greybus_bundle_id *id)
 279 {
 280         struct gbphy_host *gbphy_host;
 281         struct gbphy_device *gbphy_dev;
 282         int i;
 283 
 284         if (bundle->num_cports == 0)
 285                 return -ENODEV;
 286 
 287         gbphy_host = kzalloc(sizeof(*gbphy_host), GFP_KERNEL);
 288         if (!gbphy_host)
 289                 return -ENOMEM;
 290 
 291         gbphy_host->bundle = bundle;
 292         INIT_LIST_HEAD(&gbphy_host->devices);
 293         greybus_set_drvdata(bundle, gbphy_host);
 294 
 295         /*
 296          * Create a bunch of children devices, one per cport, and bind the
 297          * bridged phy drivers to them.
 298          */
 299         for (i = 0; i < bundle->num_cports; ++i) {
 300                 gbphy_dev = gb_gbphy_create_dev(bundle, &bundle->cport_desc[i]);
 301                 if (IS_ERR(gbphy_dev)) {
 302                         gb_gbphy_disconnect(bundle);
 303                         return PTR_ERR(gbphy_dev);
 304                 }
 305                 list_add(&gbphy_dev->list, &gbphy_host->devices);
 306         }
 307 
 308         gb_pm_runtime_put_autosuspend(bundle);
 309 
 310         return 0;
 311 }
 312 
 313 static const struct greybus_bundle_id gb_gbphy_id_table[] = {
 314         { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_BRIDGED_PHY) },
 315         { },
 316 };
 317 MODULE_DEVICE_TABLE(greybus, gb_gbphy_id_table);
 318 
 319 static struct greybus_driver gb_gbphy_driver = {
 320         .name           = "gbphy",
 321         .probe          = gb_gbphy_probe,
 322         .disconnect     = gb_gbphy_disconnect,
 323         .id_table       = gb_gbphy_id_table,
 324 };
 325 
 326 static int __init gbphy_init(void)
 327 {
 328         int retval;
 329 
 330         retval = bus_register(&gbphy_bus_type);
 331         if (retval) {
 332                 pr_err("gbphy bus register failed (%d)\n", retval);
 333                 return retval;
 334         }
 335 
 336         retval = greybus_register(&gb_gbphy_driver);
 337         if (retval) {
 338                 pr_err("error registering greybus driver\n");
 339                 goto error_gbphy;
 340         }
 341 
 342         return 0;
 343 
 344 error_gbphy:
 345         bus_unregister(&gbphy_bus_type);
 346         ida_destroy(&gbphy_id);
 347         return retval;
 348 }
 349 module_init(gbphy_init);
 350 
 351 static void __exit gbphy_exit(void)
 352 {
 353         greybus_deregister(&gb_gbphy_driver);
 354         bus_unregister(&gbphy_bus_type);
 355         ida_destroy(&gbphy_id);
 356 }
 357 module_exit(gbphy_exit);
 358 
 359 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */