359 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Greybus Bridged-Phy Bus driver4 *5 * Copyright 2014 Google Inc.6 * Copyright 2014 Linaro Ltd.7 */8 9#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt10 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 300021 22struct gbphy_host {23 struct gb_bundle *bundle;24 struct list_head devices;25};26 27static DEFINE_IDA(gbphy_id);28 29static 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}36static DEVICE_ATTR_RO(protocol_id);37 38static struct attribute *gbphy_dev_attrs[] = {39 &dev_attr_protocol_id.attr,40 NULL,41};42 43ATTRIBUTE_GROUPS(gbphy_dev);44 45static void gbphy_dev_release(struct device *dev)46{47 struct gbphy_device *gbphy_dev = to_gbphy_dev(dev);48 49 ida_free(&gbphy_id, gbphy_dev->id);50 kfree(gbphy_dev);51}52 53#ifdef CONFIG_PM54static 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#endif61 62static 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 68static 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 74static int gbphy_dev_uevent(const struct device *dev, struct kobj_uevent_env *env)75{76 const struct gbphy_device *gbphy_dev = to_gbphy_dev(dev);77 const struct greybus_descriptor_cport *cport_desc = gbphy_dev->cport_desc;78 const struct gb_bundle *bundle = gbphy_dev->bundle;79 const struct gb_interface *intf = bundle->intf;80 const struct gb_module *module = intf->module;81 const 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 104static const struct gbphy_device_id *105gbphy_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 120static int gbphy_dev_match(struct device *dev, const 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 133static 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 returning157 * 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 172static void 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 185static const struct bus_type gbphy_bus_type = {186 .name = "gbphy",187 .match = gbphy_dev_match,188 .probe = gbphy_dev_probe,189 .remove = gbphy_dev_remove,190 .uevent = gbphy_dev_uevent,191};192 193int gb_gbphy_register_driver(struct gbphy_driver *driver,194 struct module *owner, const char *mod_name)195{196 int retval;197 198 if (greybus_disabled())199 return -ENODEV;200 201 driver->driver.bus = &gbphy_bus_type;202 driver->driver.name = driver->name;203 driver->driver.owner = owner;204 driver->driver.mod_name = mod_name;205 206 retval = driver_register(&driver->driver);207 if (retval)208 return retval;209 210 pr_info("registered new driver %s\n", driver->name);211 return 0;212}213EXPORT_SYMBOL_GPL(gb_gbphy_register_driver);214 215void gb_gbphy_deregister_driver(struct gbphy_driver *driver)216{217 driver_unregister(&driver->driver);218}219EXPORT_SYMBOL_GPL(gb_gbphy_deregister_driver);220 221static struct gbphy_device *gb_gbphy_create_dev(struct gb_bundle *bundle,222 struct greybus_descriptor_cport *cport_desc)223{224 struct gbphy_device *gbphy_dev;225 int retval;226 int id;227 228 id = ida_alloc_min(&gbphy_id, 1, GFP_KERNEL);229 if (id < 0)230 return ERR_PTR(id);231 232 gbphy_dev = kzalloc(sizeof(*gbphy_dev), GFP_KERNEL);233 if (!gbphy_dev) {234 ida_free(&gbphy_id, id);235 return ERR_PTR(-ENOMEM);236 }237 238 gbphy_dev->id = id;239 gbphy_dev->bundle = bundle;240 gbphy_dev->cport_desc = cport_desc;241 gbphy_dev->dev.parent = &bundle->dev;242 gbphy_dev->dev.bus = &gbphy_bus_type;243 gbphy_dev->dev.type = &greybus_gbphy_dev_type;244 gbphy_dev->dev.groups = gbphy_dev_groups;245 gbphy_dev->dev.dma_mask = bundle->dev.dma_mask;246 dev_set_name(&gbphy_dev->dev, "gbphy%d", id);247 248 retval = device_register(&gbphy_dev->dev);249 if (retval) {250 put_device(&gbphy_dev->dev);251 return ERR_PTR(retval);252 }253 254 return gbphy_dev;255}256 257static void gb_gbphy_disconnect(struct gb_bundle *bundle)258{259 struct gbphy_host *gbphy_host = greybus_get_drvdata(bundle);260 struct gbphy_device *gbphy_dev, *temp;261 int ret;262 263 ret = gb_pm_runtime_get_sync(bundle);264 if (ret < 0)265 gb_pm_runtime_get_noresume(bundle);266 267 list_for_each_entry_safe(gbphy_dev, temp, &gbphy_host->devices, list) {268 list_del(&gbphy_dev->list);269 device_unregister(&gbphy_dev->dev);270 }271 272 kfree(gbphy_host);273}274 275static int gb_gbphy_probe(struct gb_bundle *bundle,276 const struct greybus_bundle_id *id)277{278 struct gbphy_host *gbphy_host;279 struct gbphy_device *gbphy_dev;280 int i;281 282 if (bundle->num_cports == 0)283 return -ENODEV;284 285 gbphy_host = kzalloc(sizeof(*gbphy_host), GFP_KERNEL);286 if (!gbphy_host)287 return -ENOMEM;288 289 gbphy_host->bundle = bundle;290 INIT_LIST_HEAD(&gbphy_host->devices);291 greybus_set_drvdata(bundle, gbphy_host);292 293 /*294 * Create a bunch of children devices, one per cport, and bind the295 * bridged phy drivers to them.296 */297 for (i = 0; i < bundle->num_cports; ++i) {298 gbphy_dev = gb_gbphy_create_dev(bundle, &bundle->cport_desc[i]);299 if (IS_ERR(gbphy_dev)) {300 gb_gbphy_disconnect(bundle);301 return PTR_ERR(gbphy_dev);302 }303 list_add(&gbphy_dev->list, &gbphy_host->devices);304 }305 306 gb_pm_runtime_put_autosuspend(bundle);307 308 return 0;309}310 311static const struct greybus_bundle_id gb_gbphy_id_table[] = {312 { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_BRIDGED_PHY) },313 { },314};315MODULE_DEVICE_TABLE(greybus, gb_gbphy_id_table);316 317static struct greybus_driver gb_gbphy_driver = {318 .name = "gbphy",319 .probe = gb_gbphy_probe,320 .disconnect = gb_gbphy_disconnect,321 .id_table = gb_gbphy_id_table,322};323 324static int __init gbphy_init(void)325{326 int retval;327 328 retval = bus_register(&gbphy_bus_type);329 if (retval) {330 pr_err("gbphy bus register failed (%d)\n", retval);331 return retval;332 }333 334 retval = greybus_register(&gb_gbphy_driver);335 if (retval) {336 pr_err("error registering greybus driver\n");337 goto error_gbphy;338 }339 340 return 0;341 342error_gbphy:343 bus_unregister(&gbphy_bus_type);344 ida_destroy(&gbphy_id);345 return retval;346}347module_init(gbphy_init);348 349static void __exit gbphy_exit(void)350{351 greybus_deregister(&gb_gbphy_driver);352 bus_unregister(&gbphy_bus_type);353 ida_destroy(&gbphy_id);354}355module_exit(gbphy_exit);356 357MODULE_DESCRIPTION("Greybus Bridged-Phy Bus driver");358MODULE_LICENSE("GPL v2");359