-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Staging: IndustryPack bus for the Linux Kernel
Add IndustryPack bus support for the Linux Kernel. This is a virtual bus that allows to perform all the operations between carrier and mezzanine boards. Signed-off-by: Samuel Iglesias Gonsalvez <siglesias@igalia.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- Loading branch information
Samuel Iglesias Gonsalvez
authored and
Greg Kroah-Hartman
committed
May 9, 2012
1 parent
de8fe02
commit d346587
Showing
7 changed files
with
395 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# | ||
# IPACK configuration. | ||
# | ||
|
||
menuconfig IPACK_BUS | ||
tristate "IndustryPack bus support" | ||
---help--- | ||
If you say Y here you get support for the IndustryPack Framework. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# | ||
# Makefile for the IPACK bridge device drivers. | ||
# | ||
obj-$(CONFIG_IPACK_BUS) += ipack.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
TODO | ||
==== | ||
Introduction | ||
============ | ||
|
||
These drivers add support for IndustryPack devices: carrier and mezzanine | ||
boards. | ||
|
||
The ipack driver is just an abstraction of the bus providing the common | ||
operations between the two kind of boards. | ||
|
||
TODO | ||
==== | ||
|
||
Ipack | ||
----- | ||
|
||
* The structures and API exported can be improved a lot. For example, the | ||
way to unregistering mezzanine devices, doing the mezzanine driver a call to | ||
remove_device() to notify the carrier driver, or the opposite with the call to | ||
the ipack_driver_ops' remove() function could be improved. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
/* | ||
* Industry-pack bus support functions. | ||
* | ||
* (C) 2011 Samuel Iglesias Gonsalvez <siglesia@cern.ch>, CERN | ||
* (C) 2012 Samuel Iglesias Gonsalvez <siglesias@igalia.com>, Igalia | ||
* | ||
* This program is free software; you can redistribute it and/or modify it | ||
* under the terms of the GNU General Public License as published by the Free | ||
* Software Foundation; either version 2 of the License, or (at your option) | ||
* any later version. | ||
*/ | ||
|
||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
|
||
#include <linux/module.h> | ||
#include <linux/mutex.h> | ||
#include "ipack.h" | ||
|
||
#define to_ipack_dev(device) container_of(device, struct ipack_device, dev) | ||
#define to_ipack_driver(drv) container_of(drv, struct ipack_driver, driver) | ||
|
||
/* used when allocating bus numbers */ | ||
#define IPACK_MAXBUS 64 | ||
|
||
static DEFINE_MUTEX(ipack_mutex); | ||
|
||
struct ipack_busmap { | ||
unsigned long busmap[IPACK_MAXBUS / (8*sizeof(unsigned long))]; | ||
}; | ||
static struct ipack_busmap busmap; | ||
|
||
static int ipack_bus_match(struct device *device, struct device_driver *driver) | ||
{ | ||
int ret; | ||
struct ipack_device *dev = to_ipack_dev(device); | ||
struct ipack_driver *drv = to_ipack_driver(driver); | ||
|
||
if (!drv->ops->match) | ||
return -EINVAL; | ||
|
||
ret = drv->ops->match(dev); | ||
if (ret) | ||
dev->driver = drv; | ||
|
||
return 0; | ||
} | ||
|
||
static int ipack_bus_probe(struct device *device) | ||
{ | ||
struct ipack_device *dev = to_ipack_dev(device); | ||
|
||
if (!dev->driver->ops->probe) | ||
return -EINVAL; | ||
|
||
return dev->driver->ops->probe(dev); | ||
} | ||
|
||
static int ipack_bus_remove(struct device *device) | ||
{ | ||
struct ipack_device *dev = to_ipack_dev(device); | ||
|
||
if (!dev->driver->ops->remove) | ||
return -EINVAL; | ||
|
||
dev->driver->ops->remove(dev); | ||
return 0; | ||
} | ||
|
||
static struct bus_type ipack_bus_type = { | ||
.name = "ipack", | ||
.probe = ipack_bus_probe, | ||
.match = ipack_bus_match, | ||
.remove = ipack_bus_remove, | ||
}; | ||
|
||
static int ipack_assign_bus_number(void) | ||
{ | ||
int busnum; | ||
|
||
mutex_lock(&ipack_mutex); | ||
busnum = find_next_zero_bit(busmap.busmap, IPACK_MAXBUS, 1); | ||
|
||
if (busnum >= IPACK_MAXBUS) { | ||
pr_err("too many buses\n"); | ||
busnum = -1; | ||
goto error_find_busnum; | ||
} | ||
|
||
set_bit(busnum, busmap.busmap); | ||
|
||
error_find_busnum: | ||
mutex_unlock(&ipack_mutex); | ||
return busnum; | ||
} | ||
|
||
int ipack_bus_register(struct ipack_bus_device *bus) | ||
{ | ||
int bus_nr; | ||
|
||
bus_nr = ipack_assign_bus_number(); | ||
if (bus_nr < 0) | ||
return -1; | ||
|
||
bus->bus_nr = bus_nr; | ||
return 0; | ||
} | ||
EXPORT_SYMBOL_GPL(ipack_bus_register); | ||
|
||
int ipack_bus_unregister(struct ipack_bus_device *bus) | ||
{ | ||
mutex_lock(&ipack_mutex); | ||
clear_bit(bus->bus_nr, busmap.busmap); | ||
mutex_unlock(&ipack_mutex); | ||
return 0; | ||
} | ||
EXPORT_SYMBOL_GPL(ipack_bus_unregister); | ||
|
||
int ipack_driver_register(struct ipack_driver *edrv) | ||
{ | ||
edrv->driver.bus = &ipack_bus_type; | ||
return driver_register(&edrv->driver); | ||
} | ||
EXPORT_SYMBOL_GPL(ipack_driver_register); | ||
|
||
void ipack_driver_unregister(struct ipack_driver *edrv) | ||
{ | ||
driver_unregister(&edrv->driver); | ||
} | ||
EXPORT_SYMBOL_GPL(ipack_driver_unregister); | ||
|
||
static void ipack_device_release(struct device *dev) | ||
{ | ||
} | ||
|
||
int ipack_device_register(struct ipack_device *dev) | ||
{ | ||
int ret; | ||
|
||
dev->dev.bus = &ipack_bus_type; | ||
dev->dev.release = ipack_device_release; | ||
dev_set_name(&dev->dev, | ||
"%s.%u.%u", dev->board_name, dev->bus_nr, dev->slot); | ||
|
||
ret = device_register(&dev->dev); | ||
if (ret < 0) { | ||
pr_err("error registering the device.\n"); | ||
dev->driver->ops->remove(dev); | ||
} | ||
|
||
return ret; | ||
} | ||
EXPORT_SYMBOL_GPL(ipack_device_register); | ||
|
||
void ipack_device_unregister(struct ipack_device *dev) | ||
{ | ||
device_unregister(&dev->dev); | ||
} | ||
EXPORT_SYMBOL_GPL(ipack_device_unregister); | ||
|
||
static int __init ipack_init(void) | ||
{ | ||
return bus_register(&ipack_bus_type); | ||
} | ||
|
||
static void __exit ipack_exit(void) | ||
{ | ||
bus_unregister(&ipack_bus_type); | ||
} | ||
|
||
module_init(ipack_init); | ||
module_exit(ipack_exit); | ||
|
||
MODULE_AUTHOR("Samuel Iglesias Gonsalvez <siglesias@igalia.com>"); | ||
MODULE_LICENSE("GPL"); | ||
MODULE_DESCRIPTION("Industry-pack bus core"); |
Oops, something went wrong.