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