0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/kernel.h>
0009 #include <linux/module.h>
0010 #include <linux/slab.h>
0011 #include <linux/types.h>
0012 #include <linux/idr.h>
0013 #include <linux/mcb.h>
0014
0015 static DEFINE_IDA(mcb_ida);
0016
0017 static const struct mcb_device_id *mcb_match_id(const struct mcb_device_id *ids,
0018 struct mcb_device *dev)
0019 {
0020 if (ids) {
0021 while (ids->device) {
0022 if (ids->device == dev->id)
0023 return ids;
0024 ids++;
0025 }
0026 }
0027
0028 return NULL;
0029 }
0030
0031 static int mcb_match(struct device *dev, struct device_driver *drv)
0032 {
0033 struct mcb_driver *mdrv = to_mcb_driver(drv);
0034 struct mcb_device *mdev = to_mcb_device(dev);
0035 const struct mcb_device_id *found_id;
0036
0037 found_id = mcb_match_id(mdrv->id_table, mdev);
0038 if (found_id)
0039 return 1;
0040
0041 return 0;
0042 }
0043
0044 static int mcb_uevent(struct device *dev, struct kobj_uevent_env *env)
0045 {
0046 struct mcb_device *mdev = to_mcb_device(dev);
0047 int ret;
0048
0049 ret = add_uevent_var(env, "MODALIAS=mcb:16z%03d", mdev->id);
0050 if (ret)
0051 return -ENOMEM;
0052
0053 return 0;
0054 }
0055
0056 static int mcb_probe(struct device *dev)
0057 {
0058 struct mcb_driver *mdrv = to_mcb_driver(dev->driver);
0059 struct mcb_device *mdev = to_mcb_device(dev);
0060 const struct mcb_device_id *found_id;
0061 struct module *carrier_mod;
0062 int ret;
0063
0064 found_id = mcb_match_id(mdrv->id_table, mdev);
0065 if (!found_id)
0066 return -ENODEV;
0067
0068 carrier_mod = mdev->dev.parent->driver->owner;
0069 if (!try_module_get(carrier_mod))
0070 return -EINVAL;
0071
0072 get_device(dev);
0073 ret = mdrv->probe(mdev, found_id);
0074 if (ret)
0075 module_put(carrier_mod);
0076
0077 return ret;
0078 }
0079
0080 static void mcb_remove(struct device *dev)
0081 {
0082 struct mcb_driver *mdrv = to_mcb_driver(dev->driver);
0083 struct mcb_device *mdev = to_mcb_device(dev);
0084 struct module *carrier_mod;
0085
0086 mdrv->remove(mdev);
0087
0088 carrier_mod = mdev->dev.parent->driver->owner;
0089 module_put(carrier_mod);
0090
0091 put_device(&mdev->dev);
0092 }
0093
0094 static void mcb_shutdown(struct device *dev)
0095 {
0096 struct mcb_driver *mdrv = to_mcb_driver(dev->driver);
0097 struct mcb_device *mdev = to_mcb_device(dev);
0098
0099 if (mdrv && mdrv->shutdown)
0100 mdrv->shutdown(mdev);
0101 }
0102
0103 static ssize_t revision_show(struct device *dev, struct device_attribute *attr,
0104 char *buf)
0105 {
0106 struct mcb_bus *bus = to_mcb_bus(dev);
0107
0108 return scnprintf(buf, PAGE_SIZE, "%d\n", bus->revision);
0109 }
0110 static DEVICE_ATTR_RO(revision);
0111
0112 static ssize_t model_show(struct device *dev, struct device_attribute *attr,
0113 char *buf)
0114 {
0115 struct mcb_bus *bus = to_mcb_bus(dev);
0116
0117 return scnprintf(buf, PAGE_SIZE, "%c\n", bus->model);
0118 }
0119 static DEVICE_ATTR_RO(model);
0120
0121 static ssize_t minor_show(struct device *dev, struct device_attribute *attr,
0122 char *buf)
0123 {
0124 struct mcb_bus *bus = to_mcb_bus(dev);
0125
0126 return scnprintf(buf, PAGE_SIZE, "%d\n", bus->minor);
0127 }
0128 static DEVICE_ATTR_RO(minor);
0129
0130 static ssize_t name_show(struct device *dev, struct device_attribute *attr,
0131 char *buf)
0132 {
0133 struct mcb_bus *bus = to_mcb_bus(dev);
0134
0135 return scnprintf(buf, PAGE_SIZE, "%s\n", bus->name);
0136 }
0137 static DEVICE_ATTR_RO(name);
0138
0139 static struct attribute *mcb_bus_attrs[] = {
0140 &dev_attr_revision.attr,
0141 &dev_attr_model.attr,
0142 &dev_attr_minor.attr,
0143 &dev_attr_name.attr,
0144 NULL,
0145 };
0146
0147 static const struct attribute_group mcb_carrier_group = {
0148 .attrs = mcb_bus_attrs,
0149 };
0150
0151 static const struct attribute_group *mcb_carrier_groups[] = {
0152 &mcb_carrier_group,
0153 NULL,
0154 };
0155
0156
0157 static struct bus_type mcb_bus_type = {
0158 .name = "mcb",
0159 .match = mcb_match,
0160 .uevent = mcb_uevent,
0161 .probe = mcb_probe,
0162 .remove = mcb_remove,
0163 .shutdown = mcb_shutdown,
0164 };
0165
0166 static struct device_type mcb_carrier_device_type = {
0167 .name = "mcb-carrier",
0168 .groups = mcb_carrier_groups,
0169 };
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180 int __mcb_register_driver(struct mcb_driver *drv, struct module *owner,
0181 const char *mod_name)
0182 {
0183 if (!drv->probe || !drv->remove)
0184 return -EINVAL;
0185
0186 drv->driver.owner = owner;
0187 drv->driver.bus = &mcb_bus_type;
0188 drv->driver.mod_name = mod_name;
0189
0190 return driver_register(&drv->driver);
0191 }
0192 EXPORT_SYMBOL_NS_GPL(__mcb_register_driver, MCB);
0193
0194
0195
0196
0197
0198
0199
0200 void mcb_unregister_driver(struct mcb_driver *drv)
0201 {
0202 driver_unregister(&drv->driver);
0203 }
0204 EXPORT_SYMBOL_NS_GPL(mcb_unregister_driver, MCB);
0205
0206 static void mcb_release_dev(struct device *dev)
0207 {
0208 struct mcb_device *mdev = to_mcb_device(dev);
0209
0210 mcb_bus_put(mdev->bus);
0211 kfree(mdev);
0212 }
0213
0214
0215
0216
0217
0218
0219
0220
0221 int mcb_device_register(struct mcb_bus *bus, struct mcb_device *dev)
0222 {
0223 int ret;
0224 int device_id;
0225
0226 device_initialize(&dev->dev);
0227 mcb_bus_get(bus);
0228 dev->dev.bus = &mcb_bus_type;
0229 dev->dev.parent = bus->dev.parent;
0230 dev->dev.release = mcb_release_dev;
0231 dev->dma_dev = bus->carrier;
0232
0233 device_id = dev->id;
0234 dev_set_name(&dev->dev, "mcb%d-16z%03d-%d:%d:%d",
0235 bus->bus_nr, device_id, dev->inst, dev->group, dev->var);
0236
0237 ret = device_add(&dev->dev);
0238 if (ret < 0) {
0239 pr_err("Failed registering device 16z%03d on bus mcb%d (%d)\n",
0240 device_id, bus->bus_nr, ret);
0241 goto out;
0242 }
0243
0244 return 0;
0245
0246 out:
0247
0248 return ret;
0249 }
0250 EXPORT_SYMBOL_NS_GPL(mcb_device_register, MCB);
0251
0252 static void mcb_free_bus(struct device *dev)
0253 {
0254 struct mcb_bus *bus = to_mcb_bus(dev);
0255
0256 put_device(bus->carrier);
0257 ida_free(&mcb_ida, bus->bus_nr);
0258 kfree(bus);
0259 }
0260
0261
0262
0263
0264
0265
0266 struct mcb_bus *mcb_alloc_bus(struct device *carrier)
0267 {
0268 struct mcb_bus *bus;
0269 int bus_nr;
0270 int rc;
0271
0272 bus = kzalloc(sizeof(struct mcb_bus), GFP_KERNEL);
0273 if (!bus)
0274 return ERR_PTR(-ENOMEM);
0275
0276 bus_nr = ida_alloc(&mcb_ida, GFP_KERNEL);
0277 if (bus_nr < 0) {
0278 kfree(bus);
0279 return ERR_PTR(bus_nr);
0280 }
0281
0282 bus->bus_nr = bus_nr;
0283 bus->carrier = get_device(carrier);
0284
0285 device_initialize(&bus->dev);
0286 bus->dev.parent = carrier;
0287 bus->dev.bus = &mcb_bus_type;
0288 bus->dev.type = &mcb_carrier_device_type;
0289 bus->dev.release = &mcb_free_bus;
0290
0291 dev_set_name(&bus->dev, "mcb:%d", bus_nr);
0292 rc = device_add(&bus->dev);
0293 if (rc)
0294 goto err_put;
0295
0296 return bus;
0297
0298 err_put:
0299 put_device(&bus->dev);
0300 return ERR_PTR(rc);
0301 }
0302 EXPORT_SYMBOL_NS_GPL(mcb_alloc_bus, MCB);
0303
0304 static int __mcb_devices_unregister(struct device *dev, void *data)
0305 {
0306 device_unregister(dev);
0307 return 0;
0308 }
0309
0310 static void mcb_devices_unregister(struct mcb_bus *bus)
0311 {
0312 bus_for_each_dev(&mcb_bus_type, NULL, NULL, __mcb_devices_unregister);
0313 }
0314
0315
0316
0317
0318
0319
0320 void mcb_release_bus(struct mcb_bus *bus)
0321 {
0322 mcb_devices_unregister(bus);
0323 }
0324 EXPORT_SYMBOL_NS_GPL(mcb_release_bus, MCB);
0325
0326
0327
0328
0329
0330
0331
0332 struct mcb_bus *mcb_bus_get(struct mcb_bus *bus)
0333 {
0334 if (bus)
0335 get_device(&bus->dev);
0336
0337 return bus;
0338 }
0339 EXPORT_SYMBOL_NS_GPL(mcb_bus_get, MCB);
0340
0341
0342
0343
0344
0345
0346
0347 void mcb_bus_put(struct mcb_bus *bus)
0348 {
0349 if (bus)
0350 put_device(&bus->dev);
0351 }
0352 EXPORT_SYMBOL_NS_GPL(mcb_bus_put, MCB);
0353
0354
0355
0356
0357
0358
0359
0360 struct mcb_device *mcb_alloc_dev(struct mcb_bus *bus)
0361 {
0362 struct mcb_device *dev;
0363
0364 dev = kzalloc(sizeof(struct mcb_device), GFP_KERNEL);
0365 if (!dev)
0366 return NULL;
0367
0368 dev->bus = bus;
0369
0370 return dev;
0371 }
0372 EXPORT_SYMBOL_NS_GPL(mcb_alloc_dev, MCB);
0373
0374
0375
0376
0377
0378
0379
0380 void mcb_free_dev(struct mcb_device *dev)
0381 {
0382 kfree(dev);
0383 }
0384 EXPORT_SYMBOL_NS_GPL(mcb_free_dev, MCB);
0385
0386 static int __mcb_bus_add_devices(struct device *dev, void *data)
0387 {
0388 struct mcb_device *mdev = to_mcb_device(dev);
0389 int retval;
0390
0391 if (mdev->is_added)
0392 return 0;
0393
0394 retval = device_attach(dev);
0395 if (retval < 0)
0396 dev_err(dev, "Error adding device (%d)\n", retval);
0397
0398 mdev->is_added = true;
0399
0400 return 0;
0401 }
0402
0403
0404
0405
0406
0407
0408
0409 void mcb_bus_add_devices(const struct mcb_bus *bus)
0410 {
0411 bus_for_each_dev(&mcb_bus_type, NULL, NULL, __mcb_bus_add_devices);
0412 }
0413 EXPORT_SYMBOL_NS_GPL(mcb_bus_add_devices, MCB);
0414
0415
0416
0417
0418
0419
0420 struct resource *mcb_get_resource(struct mcb_device *dev, unsigned int type)
0421 {
0422 if (type == IORESOURCE_MEM)
0423 return &dev->mem;
0424 else if (type == IORESOURCE_IRQ)
0425 return &dev->irq;
0426 else
0427 return NULL;
0428 }
0429 EXPORT_SYMBOL_NS_GPL(mcb_get_resource, MCB);
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439 struct resource *mcb_request_mem(struct mcb_device *dev, const char *name)
0440 {
0441 struct resource *mem;
0442 u32 size;
0443
0444 if (!name)
0445 name = dev->dev.driver->name;
0446
0447 size = resource_size(&dev->mem);
0448
0449 mem = request_mem_region(dev->mem.start, size, name);
0450 if (!mem)
0451 return ERR_PTR(-EBUSY);
0452
0453 return mem;
0454 }
0455 EXPORT_SYMBOL_NS_GPL(mcb_request_mem, MCB);
0456
0457
0458
0459
0460
0461
0462
0463 void mcb_release_mem(struct resource *mem)
0464 {
0465 u32 size;
0466
0467 size = resource_size(mem);
0468 release_mem_region(mem->start, size);
0469 }
0470 EXPORT_SYMBOL_NS_GPL(mcb_release_mem, MCB);
0471
0472 static int __mcb_get_irq(struct mcb_device *dev)
0473 {
0474 struct resource *irq;
0475
0476 irq = mcb_get_resource(dev, IORESOURCE_IRQ);
0477
0478 return irq->start;
0479 }
0480
0481
0482
0483
0484
0485
0486
0487 int mcb_get_irq(struct mcb_device *dev)
0488 {
0489 struct mcb_bus *bus = dev->bus;
0490
0491 if (bus->get_irq)
0492 return bus->get_irq(dev);
0493
0494 return __mcb_get_irq(dev);
0495 }
0496 EXPORT_SYMBOL_NS_GPL(mcb_get_irq, MCB);
0497
0498 static int mcb_init(void)
0499 {
0500 return bus_register(&mcb_bus_type);
0501 }
0502
0503 static void mcb_exit(void)
0504 {
0505 ida_destroy(&mcb_ida);
0506 bus_unregister(&mcb_bus_type);
0507 }
0508
0509
0510
0511
0512
0513 fs_initcall(mcb_init);
0514 module_exit(mcb_exit);
0515
0516 MODULE_DESCRIPTION("MEN Chameleon Bus Driver");
0517 MODULE_AUTHOR("Johannes Thumshirn <johannes.thumshirn@men.de>");
0518 MODULE_LICENSE("GPL v2");