4 * Copyright (C) 2013 MEN Mikroelektronik GmbH (www.men.de)
5 * Author: Johannes Thumshirn <johannes.thumshirn@men.de>
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; version 2 of the License.
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/slab.h>
14 #include <linux/types.h>
15 #include <linux/idr.h>
16 #include <linux/mcb.h>
18 static DEFINE_IDA(mcb_ida
);
20 static const struct mcb_device_id
*mcb_match_id(const struct mcb_device_id
*ids
,
21 struct mcb_device
*dev
)
25 if (ids
->device
== dev
->id
)
34 static int mcb_match(struct device
*dev
, struct device_driver
*drv
)
36 struct mcb_driver
*mdrv
= to_mcb_driver(drv
);
37 struct mcb_device
*mdev
= to_mcb_device(dev
);
38 const struct mcb_device_id
*found_id
;
40 found_id
= mcb_match_id(mdrv
->id_table
, mdev
);
47 static int mcb_uevent(struct device
*dev
, struct kobj_uevent_env
*env
)
49 struct mcb_device
*mdev
= to_mcb_device(dev
);
52 ret
= add_uevent_var(env
, "MODALIAS=mcb:16z%03d", mdev
->id
);
59 static int mcb_probe(struct device
*dev
)
61 struct mcb_driver
*mdrv
= to_mcb_driver(dev
->driver
);
62 struct mcb_device
*mdev
= to_mcb_device(dev
);
63 const struct mcb_device_id
*found_id
;
64 struct module
*carrier_mod
;
67 found_id
= mcb_match_id(mdrv
->id_table
, mdev
);
71 carrier_mod
= mdev
->dev
.parent
->driver
->owner
;
72 if (!try_module_get(carrier_mod
))
76 ret
= mdrv
->probe(mdev
, found_id
);
78 module_put(carrier_mod
);
83 static int mcb_remove(struct device
*dev
)
85 struct mcb_driver
*mdrv
= to_mcb_driver(dev
->driver
);
86 struct mcb_device
*mdev
= to_mcb_device(dev
);
87 struct module
*carrier_mod
;
91 carrier_mod
= mdev
->dev
.parent
->driver
->owner
;
92 module_put(carrier_mod
);
94 put_device(&mdev
->dev
);
99 static void mcb_shutdown(struct device
*dev
)
101 struct mcb_driver
*mdrv
= to_mcb_driver(dev
->driver
);
102 struct mcb_device
*mdev
= to_mcb_device(dev
);
104 if (mdrv
&& mdrv
->shutdown
)
105 mdrv
->shutdown(mdev
);
108 static ssize_t
revision_show(struct device
*dev
, struct device_attribute
*attr
,
111 struct mcb_bus
*bus
= to_mcb_bus(dev
);
113 return scnprintf(buf
, PAGE_SIZE
, "%d\n", bus
->revision
);
115 static DEVICE_ATTR_RO(revision
);
117 static ssize_t
model_show(struct device
*dev
, struct device_attribute
*attr
,
120 struct mcb_bus
*bus
= to_mcb_bus(dev
);
122 return scnprintf(buf
, PAGE_SIZE
, "%c\n", bus
->model
);
124 static DEVICE_ATTR_RO(model
);
126 static ssize_t
minor_show(struct device
*dev
, struct device_attribute
*attr
,
129 struct mcb_bus
*bus
= to_mcb_bus(dev
);
131 return scnprintf(buf
, PAGE_SIZE
, "%d\n", bus
->minor
);
133 static DEVICE_ATTR_RO(minor
);
135 static ssize_t
name_show(struct device
*dev
, struct device_attribute
*attr
,
138 struct mcb_bus
*bus
= to_mcb_bus(dev
);
140 return scnprintf(buf
, PAGE_SIZE
, "%s\n", bus
->name
);
142 static DEVICE_ATTR_RO(name
);
144 static struct attribute
*mcb_bus_attrs
[] = {
145 &dev_attr_revision
.attr
,
146 &dev_attr_model
.attr
,
147 &dev_attr_minor
.attr
,
152 static const struct attribute_group mcb_carrier_group
= {
153 .attrs
= mcb_bus_attrs
,
156 static const struct attribute_group
*mcb_carrier_groups
[] = {
162 static struct bus_type mcb_bus_type
= {
165 .uevent
= mcb_uevent
,
167 .remove
= mcb_remove
,
168 .shutdown
= mcb_shutdown
,
171 static struct device_type mcb_carrier_device_type
= {
172 .name
= "mcb-carrier",
173 .groups
= mcb_carrier_groups
,
177 * __mcb_register_driver() - Register a @mcb_driver at the system
178 * @drv: The @mcb_driver
179 * @owner: The @mcb_driver's module
180 * @mod_name: The name of the @mcb_driver's module
182 * Register a @mcb_driver at the system. Perform some sanity checks, if
183 * the .probe and .remove methods are provided by the driver.
185 int __mcb_register_driver(struct mcb_driver
*drv
, struct module
*owner
,
186 const char *mod_name
)
188 if (!drv
->probe
|| !drv
->remove
)
191 drv
->driver
.owner
= owner
;
192 drv
->driver
.bus
= &mcb_bus_type
;
193 drv
->driver
.mod_name
= mod_name
;
195 return driver_register(&drv
->driver
);
197 EXPORT_SYMBOL_GPL(__mcb_register_driver
);
200 * mcb_unregister_driver() - Unregister a @mcb_driver from the system
201 * @drv: The @mcb_driver
203 * Unregister a @mcb_driver from the system.
205 void mcb_unregister_driver(struct mcb_driver
*drv
)
207 driver_unregister(&drv
->driver
);
209 EXPORT_SYMBOL_GPL(mcb_unregister_driver
);
211 static void mcb_release_dev(struct device
*dev
)
213 struct mcb_device
*mdev
= to_mcb_device(dev
);
215 mcb_bus_put(mdev
->bus
);
220 * mcb_device_register() - Register a mcb_device
221 * @bus: The @mcb_bus of the device
222 * @dev: The @mcb_device
224 * Register a specific @mcb_device at a @mcb_bus and the system itself.
226 int mcb_device_register(struct mcb_bus
*bus
, struct mcb_device
*dev
)
231 device_initialize(&dev
->dev
);
233 dev
->dev
.bus
= &mcb_bus_type
;
234 dev
->dev
.parent
= bus
->dev
.parent
;
235 dev
->dev
.release
= mcb_release_dev
;
236 dev
->dma_dev
= bus
->carrier
;
239 dev_set_name(&dev
->dev
, "mcb%d-16z%03d-%d:%d:%d",
240 bus
->bus_nr
, device_id
, dev
->inst
, dev
->group
, dev
->var
);
242 ret
= device_add(&dev
->dev
);
244 pr_err("Failed registering device 16z%03d on bus mcb%d (%d)\n",
245 device_id
, bus
->bus_nr
, ret
);
255 EXPORT_SYMBOL_GPL(mcb_device_register
);
257 static void mcb_free_bus(struct device
*dev
)
259 struct mcb_bus
*bus
= to_mcb_bus(dev
);
261 put_device(bus
->carrier
);
262 ida_simple_remove(&mcb_ida
, bus
->bus_nr
);
267 * mcb_alloc_bus() - Allocate a new @mcb_bus
269 * Allocate a new @mcb_bus.
271 struct mcb_bus
*mcb_alloc_bus(struct device
*carrier
)
277 bus
= kzalloc(sizeof(struct mcb_bus
), GFP_KERNEL
);
279 return ERR_PTR(-ENOMEM
);
281 bus_nr
= ida_simple_get(&mcb_ida
, 0, 0, GFP_KERNEL
);
287 bus
->bus_nr
= bus_nr
;
288 bus
->carrier
= get_device(carrier
);
290 device_initialize(&bus
->dev
);
291 bus
->dev
.parent
= carrier
;
292 bus
->dev
.bus
= &mcb_bus_type
;
293 bus
->dev
.type
= &mcb_carrier_device_type
;
294 bus
->dev
.release
= &mcb_free_bus
;
296 dev_set_name(&bus
->dev
, "mcb:%d", bus_nr
);
297 rc
= device_add(&bus
->dev
);
307 EXPORT_SYMBOL_GPL(mcb_alloc_bus
);
309 static int __mcb_devices_unregister(struct device
*dev
, void *data
)
311 device_unregister(dev
);
315 static void mcb_devices_unregister(struct mcb_bus
*bus
)
317 bus_for_each_dev(&mcb_bus_type
, NULL
, NULL
, __mcb_devices_unregister
);
320 * mcb_release_bus() - Free a @mcb_bus
321 * @bus: The @mcb_bus to release
323 * Release an allocated @mcb_bus from the system.
325 void mcb_release_bus(struct mcb_bus
*bus
)
327 mcb_devices_unregister(bus
);
329 EXPORT_SYMBOL_GPL(mcb_release_bus
);
332 * mcb_bus_put() - Increment refcnt
335 * Get a @mcb_bus' ref
337 struct mcb_bus
*mcb_bus_get(struct mcb_bus
*bus
)
340 get_device(&bus
->dev
);
344 EXPORT_SYMBOL_GPL(mcb_bus_get
);
347 * mcb_bus_put() - Decrement refcnt
350 * Release a @mcb_bus' ref
352 void mcb_bus_put(struct mcb_bus
*bus
)
355 put_device(&bus
->dev
);
357 EXPORT_SYMBOL_GPL(mcb_bus_put
);
360 * mcb_alloc_dev() - Allocate a device
361 * @bus: The @mcb_bus the device is part of
363 * Allocate a @mcb_device and add bus.
365 struct mcb_device
*mcb_alloc_dev(struct mcb_bus
*bus
)
367 struct mcb_device
*dev
;
369 dev
= kzalloc(sizeof(struct mcb_device
), GFP_KERNEL
);
377 EXPORT_SYMBOL_GPL(mcb_alloc_dev
);
380 * mcb_free_dev() - Free @mcb_device
381 * @dev: The device to free
385 void mcb_free_dev(struct mcb_device
*dev
)
389 EXPORT_SYMBOL_GPL(mcb_free_dev
);
391 static int __mcb_bus_add_devices(struct device
*dev
, void *data
)
393 struct mcb_device
*mdev
= to_mcb_device(dev
);
399 retval
= device_attach(dev
);
401 dev_err(dev
, "Error adding device (%d)\n", retval
);
403 mdev
->is_added
= true;
409 * mcb_bus_add_devices() - Add devices in the bus' internal device list
410 * @bus: The @mcb_bus we add the devices
412 * Add devices in the bus' internal device list to the system.
414 void mcb_bus_add_devices(const struct mcb_bus
*bus
)
416 bus_for_each_dev(&mcb_bus_type
, NULL
, NULL
, __mcb_bus_add_devices
);
418 EXPORT_SYMBOL_GPL(mcb_bus_add_devices
);
421 * mcb_get_resource() - get a resource for a mcb device
422 * @dev: the mcb device
423 * @type: the type of resource
425 struct resource
*mcb_get_resource(struct mcb_device
*dev
, unsigned int type
)
427 if (type
== IORESOURCE_MEM
)
429 else if (type
== IORESOURCE_IRQ
)
434 EXPORT_SYMBOL_GPL(mcb_get_resource
);
437 * mcb_request_mem() - Request memory
438 * @dev: The @mcb_device the memory is for
439 * @name: The name for the memory reference.
441 * Request memory for a @mcb_device. If @name is NULL the driver name will
444 struct resource
*mcb_request_mem(struct mcb_device
*dev
, const char *name
)
446 struct resource
*mem
;
450 name
= dev
->dev
.driver
->name
;
452 size
= resource_size(&dev
->mem
);
454 mem
= request_mem_region(dev
->mem
.start
, size
, name
);
456 return ERR_PTR(-EBUSY
);
460 EXPORT_SYMBOL_GPL(mcb_request_mem
);
463 * mcb_release_mem() - Release memory requested by device
464 * @dev: The @mcb_device that requested the memory
466 * Release memory that was prior requested via @mcb_request_mem().
468 void mcb_release_mem(struct resource
*mem
)
472 size
= resource_size(mem
);
473 release_mem_region(mem
->start
, size
);
475 EXPORT_SYMBOL_GPL(mcb_release_mem
);
477 static int __mcb_get_irq(struct mcb_device
*dev
)
479 struct resource
*irq
;
481 irq
= mcb_get_resource(dev
, IORESOURCE_IRQ
);
487 * mcb_get_irq() - Get device's IRQ number
488 * @dev: The @mcb_device the IRQ is for
490 * Get the IRQ number of a given @mcb_device.
492 int mcb_get_irq(struct mcb_device
*dev
)
494 struct mcb_bus
*bus
= dev
->bus
;
497 return bus
->get_irq(dev
);
499 return __mcb_get_irq(dev
);
501 EXPORT_SYMBOL_GPL(mcb_get_irq
);
503 static int mcb_init(void)
505 return bus_register(&mcb_bus_type
);
508 static void mcb_exit(void)
510 ida_destroy(&mcb_ida
);
511 bus_unregister(&mcb_bus_type
);
514 /* mcb must be initialized after PCI but before the chameleon drivers.
515 * That means we must use some initcall between subsys_initcall and
518 fs_initcall(mcb_init
);
519 module_exit(mcb_exit
);
521 MODULE_DESCRIPTION("MEN Chameleon Bus Driver");
522 MODULE_AUTHOR("Johannes Thumshirn <johannes.thumshirn@men.de>");
523 MODULE_LICENSE("GPL v2");