summaryrefslogtreecommitdiffstats
path: root/Documentation/driver-model
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /Documentation/driver-model
Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'Documentation/driver-model')
-rw-r--r--Documentation/driver-model/binding.txt102
-rw-r--r--Documentation/driver-model/bus.txt160
-rw-r--r--Documentation/driver-model/class.txt162
-rw-r--r--Documentation/driver-model/device.txt154
-rw-r--r--Documentation/driver-model/driver.txt287
-rw-r--r--Documentation/driver-model/interface.txt129
-rw-r--r--Documentation/driver-model/overview.txt114
-rw-r--r--Documentation/driver-model/platform.txt99
-rw-r--r--Documentation/driver-model/porting.txt445
9 files changed, 1652 insertions, 0 deletions
diff --git a/Documentation/driver-model/binding.txt b/Documentation/driver-model/binding.txt
new file mode 100644
index 000000000000..f7ec9d625bfc
--- /dev/null
+++ b/Documentation/driver-model/binding.txt
@@ -0,0 +1,102 @@
+
+Driver Binding
+
+Driver binding is the process of associating a device with a device
+driver that can control it. Bus drivers have typically handled this
+because there have been bus-specific structures to represent the
+devices and the drivers. With generic device and device driver
+structures, most of the binding can take place using common code.
+
+
+Bus
+~~~
+
+The bus type structure contains a list of all devices that are on that bus
+type in the system. When device_register is called for a device, it is
+inserted into the end of this list. The bus object also contains a
+list of all drivers of that bus type. When driver_register is called
+for a driver, it is inserted at the end of this list. These are the
+two events which trigger driver binding.
+
+
+device_register
+~~~~~~~~~~~~~~~
+
+When a new device is added, the bus's list of drivers is iterated over
+to find one that supports it. In order to determine that, the device
+ID of the device must match one of the device IDs that the driver
+supports. The format and semantics for comparing IDs is bus-specific.
+Instead of trying to derive a complex state machine and matching
+algorithm, it is up to the bus driver to provide a callback to compare
+a device against the IDs of a driver. The bus returns 1 if a match was
+found; 0 otherwise.
+
+int match(struct device * dev, struct device_driver * drv);
+
+If a match is found, the device's driver field is set to the driver
+and the driver's probe callback is called. This gives the driver a
+chance to verify that it really does support the hardware, and that
+it's in a working state.
+
+Device Class
+~~~~~~~~~~~~
+
+Upon the successful completion of probe, the device is registered with
+the class to which it belongs. Device drivers belong to one and only one
+class, and that is set in the driver's devclass field.
+devclass_add_device is called to enumerate the device within the class
+and actually register it with the class, which happens with the
+class's register_dev callback.
+
+NOTE: The device class structures and core routines to manipulate them
+are not in the mainline kernel, so the discussion is still a bit
+speculative.
+
+
+Driver
+~~~~~~
+
+When a driver is attached to a device, the device is inserted into the
+driver's list of devices.
+
+
+sysfs
+~~~~~
+
+A symlink is created in the bus's 'devices' directory that points to
+the device's directory in the physical hierarchy.
+
+A symlink is created in the driver's 'devices' directory that points
+to the device's directory in the physical hierarchy.
+
+A directory for the device is created in the class's directory. A
+symlink is created in that directory that points to the device's
+physical location in the sysfs tree.
+
+A symlink can be created (though this isn't done yet) in the device's
+physical directory to either its class directory, or the class's
+top-level directory. One can also be created to point to its driver's
+directory also.
+
+
+driver_register
+~~~~~~~~~~~~~~~
+
+The process is almost identical for when a new driver is added.
+The bus's list of devices is iterated over to find a match. Devices
+that already have a driver are skipped. All the devices are iterated
+over, to bind as many devices as possible to the driver.
+
+
+Removal
+~~~~~~~
+
+When a device is removed, the reference count for it will eventually
+go to 0. When it does, the remove callback of the driver is called. It
+is removed from the driver's list of devices and the reference count
+of the driver is decremented. All symlinks between the two are removed.
+
+When a driver is removed, the list of devices that it supports is
+iterated over, and the driver's remove callback is called for each
+one. The device is removed from that list and the symlinks removed.
+
diff --git a/Documentation/driver-model/bus.txt b/Documentation/driver-model/bus.txt
new file mode 100644
index 000000000000..dd62c7b80b3f
--- /dev/null
+++ b/Documentation/driver-model/bus.txt
@@ -0,0 +1,160 @@
+
+Bus Types
+
+Definition
+~~~~~~~~~~
+
+struct bus_type {
+ char * name;
+
+ struct subsystem subsys;
+ struct kset drivers;
+ struct kset devices;
+
+ struct bus_attribute * bus_attrs;
+ struct device_attribute * dev_attrs;
+ struct driver_attribute * drv_attrs;
+
+ int (*match)(struct device * dev, struct device_driver * drv);
+ int (*hotplug) (struct device *dev, char **envp,
+ int num_envp, char *buffer, int buffer_size);
+ int (*suspend)(struct device * dev, u32 state);
+ int (*resume)(struct device * dev);
+};
+
+int bus_register(struct bus_type * bus);
+
+
+Declaration
+~~~~~~~~~~~
+
+Each bus type in the kernel (PCI, USB, etc) should declare one static
+object of this type. They must initialize the name field, and may
+optionally initialize the match callback.
+
+struct bus_type pci_bus_type = {
+ .name = "pci",
+ .match = pci_bus_match,
+};
+
+The structure should be exported to drivers in a header file:
+
+extern struct bus_type pci_bus_type;
+
+
+Registration
+~~~~~~~~~~~~
+
+When a bus driver is initialized, it calls bus_register. This
+initializes the rest of the fields in the bus object and inserts it
+into a global list of bus types. Once the bus object is registered,
+the fields in it are usable by the bus driver.
+
+
+Callbacks
+~~~~~~~~~
+
+match(): Attaching Drivers to Devices
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The format of device ID structures and the semantics for comparing
+them are inherently bus-specific. Drivers typically declare an array
+of device IDs of devices they support that reside in a bus-specific
+driver structure.
+
+The purpose of the match callback is provide the bus an opportunity to
+determine if a particular driver supports a particular device by
+comparing the device IDs the driver supports with the device ID of a
+particular device, without sacrificing bus-specific functionality or
+type-safety.
+
+When a driver is registered with the bus, the bus's list of devices is
+iterated over, and the match callback is called for each device that
+does not have a driver associated with it.
+
+
+
+Device and Driver Lists
+~~~~~~~~~~~~~~~~~~~~~~~
+
+The lists of devices and drivers are intended to replace the local
+lists that many buses keep. They are lists of struct devices and
+struct device_drivers, respectively. Bus drivers are free to use the
+lists as they please, but conversion to the bus-specific type may be
+necessary.
+
+The LDM core provides helper functions for iterating over each list.
+
+int bus_for_each_dev(struct bus_type * bus, struct device * start, void * data,
+ int (*fn)(struct device *, void *));
+
+int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,
+ void * data, int (*fn)(struct device_driver *, void *));
+
+These helpers iterate over the respective list, and call the callback
+for each device or driver in the list. All list accesses are
+synchronized by taking the bus's lock (read currently). The reference
+count on each object in the list is incremented before the callback is
+called; it is decremented after the next object has been obtained. The
+lock is not held when calling the callback.
+
+
+sysfs
+~~~~~~~~
+There is a top-level directory named 'bus'.
+
+Each bus gets a directory in the bus directory, along with two default
+directories:
+
+ /sys/bus/pci/
+ |-- devices
+ `-- drivers
+
+Drivers registered with the bus get a directory in the bus's drivers
+directory:
+
+ /sys/bus/pci/
+ |-- devices
+ `-- drivers
+ |-- Intel ICH
+ |-- Intel ICH Joystick
+ |-- agpgart
+ `-- e100
+
+Each device that is discovered on a bus of that type gets a symlink in
+the bus's devices directory to the device's directory in the physical
+hierarchy:
+
+ /sys/bus/pci/
+ |-- devices
+ | |-- 00:00.0 -> ../../../root/pci0/00:00.0
+ | |-- 00:01.0 -> ../../../root/pci0/00:01.0
+ | `-- 00:02.0 -> ../../../root/pci0/00:02.0
+ `-- drivers
+
+
+Exporting Attributes
+~~~~~~~~~~~~~~~~~~~~
+struct bus_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct bus_type *, char * buf);
+ ssize_t (*store)(struct bus_type *, const char * buf, size_t count);
+};
+
+Bus drivers can export attributes using the BUS_ATTR macro that works
+similarly to the DEVICE_ATTR macro for devices. For example, a definition
+like this:
+
+static BUS_ATTR(debug,0644,show_debug,store_debug);
+
+is equivalent to declaring:
+
+static bus_attribute bus_attr_debug;
+
+This can then be used to add and remove the attribute from the bus's
+sysfs directory using:
+
+int bus_create_file(struct bus_type *, struct bus_attribute *);
+void bus_remove_file(struct bus_type *, struct bus_attribute *);
+
+
diff --git a/Documentation/driver-model/class.txt b/Documentation/driver-model/class.txt
new file mode 100644
index 000000000000..2d1d893a5e5d
--- /dev/null
+++ b/Documentation/driver-model/class.txt
@@ -0,0 +1,162 @@
+
+Device Classes
+
+
+Introduction
+~~~~~~~~~~~~
+A device class describes a type of device, like an audio or network
+device. The following device classes have been identified:
+
+<Insert List of Device Classes Here>
+
+
+Each device class defines a set of semantics and a programming interface
+that devices of that class adhere to. Device drivers are the
+implemention of that programming interface for a particular device on
+a particular bus.
+
+Device classes are agnostic with respect to what bus a device resides
+on.
+
+
+Programming Interface
+~~~~~~~~~~~~~~~~~~~~~
+The device class structure looks like:
+
+
+typedef int (*devclass_add)(struct device *);
+typedef void (*devclass_remove)(struct device *);
+
+struct device_class {
+ char * name;
+ rwlock_t lock;
+ u32 devnum;
+ struct list_head node;
+
+ struct list_head drivers;
+ struct list_head intf_list;
+
+ struct driver_dir_entry dir;
+ struct driver_dir_entry device_dir;
+ struct driver_dir_entry driver_dir;
+
+ devclass_add add_device;
+ devclass_remove remove_device;
+};
+
+A typical device class definition would look like:
+
+struct device_class input_devclass = {
+ .name = "input",
+ .add_device = input_add_device,
+ .remove_device = input_remove_device,
+};
+
+Each device class structure should be exported in a header file so it
+can be used by drivers, extensions and interfaces.
+
+Device classes are registered and unregistered with the core using:
+
+int devclass_register(struct device_class * cls);
+void devclass_unregister(struct device_class * cls);
+
+
+Devices
+~~~~~~~
+As devices are bound to drivers, they are added to the device class
+that the driver belongs to. Before the driver model core, this would
+typically happen during the driver's probe() callback, once the device
+has been initialized. It now happens after the probe() callback
+finishes from the core.
+
+The device is enumerated in the class. Each time a device is added to
+the class, the class's devnum field is incremented and assigned to the
+device. The field is never decremented, so if the device is removed
+from the class and re-added, it will receive a different enumerated
+value.
+
+The class is allowed to create a class-specific structure for the
+device and store it in the device's class_data pointer.
+
+There is no list of devices in the device class. Each driver has a
+list of devices that it supports. The device class has a list of
+drivers of that particular class. To access all of the devices in the
+class, iterate over the device lists of each driver in the class.
+
+
+Device Drivers
+~~~~~~~~~~~~~~
+Device drivers are added to device classes when they are registered
+with the core. A driver specifies the class it belongs to by setting
+the struct device_driver::devclass field.
+
+
+sysfs directory structure
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+There is a top-level sysfs directory named 'class'.
+
+Each class gets a directory in the class directory, along with two
+default subdirectories:
+
+ class/
+ `-- input
+ |-- devices
+ `-- drivers
+
+
+Drivers registered with the class get a symlink in the drivers/ directory
+that points to the driver's directory (under its bus directory):
+
+ class/
+ `-- input
+ |-- devices
+ `-- drivers
+ `-- usb:usb_mouse -> ../../../bus/drivers/usb_mouse/
+
+
+Each device gets a symlink in the devices/ directory that points to the
+device's directory in the physical hierarchy:
+
+ class/
+ `-- input
+ |-- devices
+ | `-- 1 -> ../../../root/pci0/00:1f.0/usb_bus/00:1f.2-1:0/
+ `-- drivers
+
+
+Exporting Attributes
+~~~~~~~~~~~~~~~~~~~~
+struct devclass_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct device_class *, char * buf, size_t count, loff_t off);
+ ssize_t (*store)(struct device_class *, const char * buf, size_t count, loff_t off);
+};
+
+Class drivers can export attributes using the DEVCLASS_ATTR macro that works
+similarly to the DEVICE_ATTR macro for devices. For example, a definition
+like this:
+
+static DEVCLASS_ATTR(debug,0644,show_debug,store_debug);
+
+is equivalent to declaring:
+
+static devclass_attribute devclass_attr_debug;
+
+The bus driver can add and remove the attribute from the class's
+sysfs directory using:
+
+int devclass_create_file(struct device_class *, struct devclass_attribute *);
+void devclass_remove_file(struct device_class *, struct devclass_attribute *);
+
+In the example above, the file will be named 'debug' in placed in the
+class's directory in sysfs.
+
+
+Interfaces
+~~~~~~~~~~
+There may exist multiple mechanisms for accessing the same device of a
+particular class type. Device interfaces describe these mechanisms.
+
+When a device is added to a device class, the core attempts to add it
+to every interface that is registered with the device class.
+
diff --git a/Documentation/driver-model/device.txt b/Documentation/driver-model/device.txt
new file mode 100644
index 000000000000..58cc5dc8fd3e
--- /dev/null
+++ b/Documentation/driver-model/device.txt
@@ -0,0 +1,154 @@
+
+The Basic Device Structure
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+struct device {
+ struct list_head g_list;
+ struct list_head node;
+ struct list_head bus_list;
+ struct list_head driver_list;
+ struct list_head intf_list;
+ struct list_head children;
+ struct device * parent;
+
+ char name[DEVICE_NAME_SIZE];
+ char bus_id[BUS_ID_SIZE];
+
+ spinlock_t lock;
+ atomic_t refcount;
+
+ struct bus_type * bus;
+ struct driver_dir_entry dir;
+
+ u32 class_num;
+
+ struct device_driver *driver;
+ void *driver_data;
+ void *platform_data;
+
+ u32 current_state;
+ unsigned char *saved_state;
+
+ void (*release)(struct device * dev);
+};
+
+Fields
+~~~~~~
+g_list: Node in the global device list.
+
+node: Node in device's parent's children list.
+
+bus_list: Node in device's bus's devices list.
+
+driver_list: Node in device's driver's devices list.
+
+intf_list: List of intf_data. There is one structure allocated for
+ each interface that the device supports.
+
+children: List of child devices.
+
+parent: *** FIXME ***
+
+name: ASCII description of device.
+ Example: " 3Com Corporation 3c905 100BaseTX [Boomerang]"
+
+bus_id: ASCII representation of device's bus position. This
+ field should be a name unique across all devices on the
+ bus type the device belongs to.
+
+ Example: PCI bus_ids are in the form of
+ <bus number>:<slot number>.<function number>
+ This name is unique across all PCI devices in the system.
+
+lock: Spinlock for the device.
+
+refcount: Reference count on the device.
+
+bus: Pointer to struct bus_type that device belongs to.
+
+dir: Device's sysfs directory.
+
+class_num: Class-enumerated value of the device.
+
+driver: Pointer to struct device_driver that controls the device.
+
+driver_data: Driver-specific data.
+
+platform_data: Platform data specific to the device.
+
+current_state: Current power state of the device.
+
+saved_state: Pointer to saved state of the device. This is usable by
+ the device driver controlling the device.
+
+release: Callback to free the device after all references have
+ gone away. This should be set by the allocator of the
+ device (i.e. the bus driver that discovered the device).
+
+
+Programming Interface
+~~~~~~~~~~~~~~~~~~~~~
+The bus driver that discovers the device uses this to register the
+device with the core:
+
+int device_register(struct device * dev);
+
+The bus should initialize the following fields:
+
+ - parent
+ - name
+ - bus_id
+ - bus
+
+A device is removed from the core when its reference count goes to
+0. The reference count can be adjusted using:
+
+struct device * get_device(struct device * dev);
+void put_device(struct device * dev);
+
+get_device() will return a pointer to the struct device passed to it
+if the reference is not already 0 (if it's in the process of being
+removed already).
+
+A driver can access the lock in the device structure using:
+
+void lock_device(struct device * dev);
+void unlock_device(struct device * dev);
+
+
+Attributes
+~~~~~~~~~~
+struct device_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct device * dev, char * buf, size_t count, loff_t off);
+ ssize_t (*store)(struct device * dev, const char * buf, size_t count, loff_t off);
+};
+
+Attributes of devices can be exported via drivers using a simple
+procfs-like interface.
+
+Please see Documentation/filesystems/sysfs.txt for more information
+on how sysfs works.
+
+Attributes are declared using a macro called DEVICE_ATTR:
+
+#define DEVICE_ATTR(name,mode,show,store)
+
+Example:
+
+DEVICE_ATTR(power,0644,show_power,store_power);
+
+This declares a structure of type struct device_attribute named
+'dev_attr_power'. This can then be added and removed to the device's
+directory using:
+
+int device_create_file(struct device *device, struct device_attribute * entry);
+void device_remove_file(struct device * dev, struct device_attribute * attr);
+
+Example:
+
+device_create_file(dev,&dev_attr_power);
+device_remove_file(dev,&dev_attr_power);
+
+The file name will be 'power' with a mode of 0644 (-rw-r--r--).
+
diff --git a/Documentation/driver-model/driver.txt b/Documentation/driver-model/driver.txt
new file mode 100644
index 000000000000..12447787d329
--- /dev/null
+++ b/Documentation/driver-model/driver.txt
@@ -0,0 +1,287 @@
+
+Device Drivers
+
+struct device_driver {
+ char * name;
+ struct bus_type * bus;
+
+ rwlock_t lock;
+ atomic_t refcount;
+
+ list_t bus_list;
+ list_t devices;
+
+ struct driver_dir_entry dir;
+
+ int (*probe) (struct device * dev);
+ int (*remove) (struct device * dev);
+
+ int (*suspend) (struct device * dev, u32 state, u32 level);
+ int (*resume) (struct device * dev, u32 level);
+
+ void (*release) (struct device_driver * drv);
+};
+
+
+
+Allocation
+~~~~~~~~~~
+
+Device drivers are statically allocated structures. Though there may
+be multiple devices in a system that a driver supports, struct
+device_driver represents the driver as a whole (not a particular
+device instance).
+
+Initialization
+~~~~~~~~~~~~~~
+
+The driver must initialize at least the name and bus fields. It should
+also initialize the devclass field (when it arrives), so it may obtain
+the proper linkage internally. It should also initialize as many of
+the callbacks as possible, though each is optional.
+
+Declaration
+~~~~~~~~~~~
+
+As stated above, struct device_driver objects are statically
+allocated. Below is an example declaration of the eepro100
+driver. This declaration is hypothetical only; it relies on the driver
+being converted completely to the new model.
+
+static struct device_driver eepro100_driver = {
+ .name = "eepro100",
+ .bus = &pci_bus_type,
+ .devclass = &ethernet_devclass, /* when it's implemented */
+
+ .probe = eepro100_probe,
+ .remove = eepro100_remove,
+ .suspend = eepro100_suspend,
+ .resume = eepro100_resume,
+};
+
+Most drivers will not be able to be converted completely to the new
+model because the bus they belong to has a bus-specific structure with
+bus-specific fields that cannot be generalized.
+
+The most common example of this are device ID structures. A driver
+typically defines an array of device IDs that it supports. The format
+of these structures and the semantics for comparing device IDs are
+completely bus-specific. Defining them as bus-specific entities would
+sacrifice type-safety, so we keep bus-specific structures around.
+
+Bus-specific drivers should include a generic struct device_driver in
+the definition of the bus-specific driver. Like this:
+
+struct pci_driver {
+ const struct pci_device_id *id_table;
+ struct device_driver driver;
+};
+
+A definition that included bus-specific fields would look like
+(using the eepro100 driver again):
+
+static struct pci_driver eepro100_driver = {
+ .id_table = eepro100_pci_tbl,
+ .driver = {
+ .name = "eepro100",
+ .bus = &pci_bus_type,
+ .devclass = &ethernet_devclass, /* when it's implemented */
+ .probe = eepro100_probe,
+ .remove = eepro100_remove,
+ .suspend = eepro100_suspend,
+ .resume = eepro100_resume,
+ },
+};
+
+Some may find the syntax of embedded struct initialization awkward or
+even a bit ugly. So far, it's the best way we've found to do what we want...
+
+Registration
+~~~~~~~~~~~~
+
+int driver_register(struct device_driver * drv);
+
+The driver registers the structure on startup. For drivers that have
+no bus-specific fields (i.e. don't have a bus-specific driver
+structure), they would use driver_register and pass a pointer to their
+struct device_driver object.
+
+Most drivers, however, will have a bus-specific structure and will
+need to register with the bus using something like pci_driver_register.
+
+It is important that drivers register their driver structure as early as
+possible. Registration with the core initializes several fields in the
+struct device_driver object, including the reference count and the
+lock. These fields are assumed to be valid at all times and may be
+used by the device model core or the bus driver.
+
+
+Transition Bus Drivers
+~~~~~~~~~~~~~~~~~~~~~~
+
+By defining wrapper functions, the transition to the new model can be
+made easier. Drivers can ignore the generic structure altogether and
+let the bus wrapper fill in the fields. For the callbacks, the bus can
+define generic callbacks that forward the call to the bus-specific
+callbacks of the drivers.
+
+This solution is intended to be only temporary. In order to get class
+information in the driver, the drivers must be modified anyway. Since
+converting drivers to the new model should reduce some infrastructural
+complexity and code size, it is recommended that they are converted as
+class information is added.
+
+Access
+~~~~~~
+
+Once the object has been registered, it may access the common fields of
+the object, like the lock and the list of devices.
+
+int driver_for_each_dev(struct device_driver * drv, void * data,
+ int (*callback)(struct device * dev, void * data));
+
+The devices field is a list of all the devices that have been bound to
+the driver. The LDM core provides a helper function to operate on all
+the devices a driver controls. This helper locks the driver on each
+node access, and does proper reference counting on each device as it
+accesses it.
+
+
+sysfs
+~~~~~
+
+When a driver is registered, a sysfs directory is created in its
+bus's directory. In this directory, the driver can export an interface
+to userspace to control operation of the driver on a global basis;
+e.g. toggling debugging output in the driver.
+
+A future feature of this directory will be a 'devices' directory. This
+directory will contain symlinks to the directories of devices it
+supports.
+
+
+
+Callbacks
+~~~~~~~~~
+
+ int (*probe) (struct device * dev);
+
+probe is called to verify the existence of a certain type of
+hardware. This is called during the driver binding process, after the
+bus has verified that the device ID of a device matches one of the
+device IDs supported by the driver.
+
+This callback only verifies that there actually is supported hardware
+present. It may allocate a driver-specific structure, but it should
+not do any initialization of the hardware itself. The device-specific
+structure may be stored in the device's driver_data field.
+
+ int (*init) (struct device * dev);
+
+init is called during the binding stage. It is called after probe has
+successfully returned and the device has been registered with its
+class. It is responsible for initializing the hardware.
+
+ int (*remove) (struct device * dev);
+
+remove is called to dissociate a driver with a device. This may be
+called if a device is physically removed from the system, if the
+driver module is being unloaded, or during a reboot sequence.
+
+It is up to the driver to determine if the device is present or
+not. It should free any resources allocated specifically for the
+device; i.e. anything in the device's driver_data field.
+
+If the device is still present, it should quiesce the device and place
+it into a supported low-power state.
+
+ int (*suspend) (struct device * dev, u32 state, u32 level);
+
+suspend is called to put the device in a low power state. There are
+several stages to successfully suspending a device, which is denoted in
+the @level parameter. Breaking the suspend transition into several
+stages affords the platform flexibility in performing device power
+management based on the requirements of the system and the
+user-defined policy.
+
+SUSPEND_NOTIFY notifies the device that a suspend transition is about
+to happen. This happens on system power state transitions to verify
+that all devices can successfully suspend.
+
+A driver may choose to fail on this call, which should cause the
+entire suspend transition to fail. A driver should fail only if it
+knows that the device will not be able to be resumed properly when the
+system wakes up again. It could also fail if it somehow determines it
+is in the middle of an operation too important to stop.
+
+SUSPEND_DISABLE tells the device to stop I/O transactions. When it
+stops transactions, or what it should do with unfinished transactions
+is a policy of the driver. After this call, the driver should not
+accept any other I/O requests.
+
+SUSPEND_SAVE_STATE tells the device to save the context of the
+hardware. This includes any bus-specific hardware state and
+device-specific hardware state. A pointer to this saved state can be
+stored in the device's saved_state field.
+
+SUSPEND_POWER_DOWN tells the driver to place the device in the low
+power state requested.
+
+Whether suspend is called with a given level is a policy of the
+platform. Some levels may be omitted; drivers must not assume the
+reception of any level. However, all levels must be called in the
+order above; i.e. notification will always come before disabling;
+disabling the device will come before suspending the device.
+
+All calls are made with interrupts enabled, except for the
+SUSPEND_POWER_DOWN level.
+
+ int (*resume) (struct device * dev, u32 level);
+
+Resume is used to bring a device back from a low power state. Like the
+suspend transition, it happens in several stages.
+
+RESUME_POWER_ON tells the driver to set the power state to the state
+before the suspend call (The device could have already been in a low
+power state before the suspend call to put in a lower power state).
+
+RESUME_RESTORE_STATE tells the driver to restore the state saved by
+the SUSPEND_SAVE_STATE suspend call.
+
+RESUME_ENABLE tells the driver to start accepting I/O transactions
+again. Depending on driver policy, the device may already have pending
+I/O requests.
+
+RESUME_POWER_ON is called with interrupts disabled. The other resume
+levels are called with interrupts enabled.
+
+As with the various suspend stages, the driver must not assume that
+any other resume calls have been or will be made. Each call should be
+self-contained and not dependent on any external state.
+
+
+Attributes
+~~~~~~~~~~
+struct driver_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct device_driver *, char * buf, size_t count, loff_t off);
+ ssize_t (*store)(struct device_driver *, const char * buf, size_t count, loff_t off);
+};
+
+Device drivers can export attributes via their sysfs directories.
+Drivers can declare attributes using a DRIVER_ATTR macro that works
+identically to the DEVICE_ATTR macro.
+
+Example:
+
+DRIVER_ATTR(debug,0644,show_debug,store_debug);
+
+This is equivalent to declaring:
+
+struct driver_attribute driver_attr_debug;
+
+This can then be used to add and remove the attribute from the
+driver's directory using:
+
+int driver_create_file(struct device_driver *, struct driver_attribute *);
+void driver_remove_file(struct device_driver *, struct driver_attribute *);
diff --git a/Documentation/driver-model/interface.txt b/Documentation/driver-model/interface.txt
new file mode 100644
index 000000000000..c66912bfe866
--- /dev/null
+++ b/Documentation/driver-model/interface.txt
@@ -0,0 +1,129 @@
+
+Device Interfaces
+
+Introduction
+~~~~~~~~~~~~
+
+Device interfaces are the logical interfaces of device classes that correlate
+directly to userspace interfaces, like device nodes.
+
+Each device class may have multiple interfaces through which you can
+access the same device. An input device may support the mouse interface,
+the 'evdev' interface, and the touchscreen interface. A SCSI disk would
+support the disk interface, the SCSI generic interface, and possibly a raw
+device interface.
+
+Device interfaces are registered with the class they belong to. As devices
+are added to the class, they are added to each interface registered with
+the class. The interface is responsible for determining whether the device
+supports the interface or not.
+
+
+Programming Interface
+~~~~~~~~~~~~~~~~~~~~~
+
+struct device_interface {
+ char * name;
+ rwlock_t lock;
+ u32 devnum;
+ struct device_class * devclass;
+
+ struct list_head node;
+ struct driver_dir_entry dir;
+
+ int (*add_device)(struct device *);
+ int (*add_device)(struct intf_data *);
+};
+
+int interface_register(struct device_interface *);
+void interface_unregister(struct device_interface *);
+
+
+An interface must specify the device class it belongs to. It is added
+to that class's list of interfaces on registration.
+
+
+Interfaces can be added to a device class at any time. Whenever it is
+added, each device in the class is passed to the interface's
+add_device callback. When an interface is removed, each device is
+removed from the interface.
+
+
+Devices
+~~~~~~~
+Once a device is added to a device class, it is added to each
+interface that is registered with the device class. The class
+is expected to place a class-specific data structure in
+struct device::class_data. The interface can use that (along with
+other fields of struct device) to determine whether or not the driver
+and/or device support that particular interface.
+
+
+Data
+~~~~
+
+struct intf_data {
+ struct list_head node;
+ struct device_interface * intf;
+ struct device * dev;
+ u32 intf_num;
+};
+
+int interface_add_data(struct interface_data *);
+
+The interface is responsible for allocating and initializing a struct
+intf_data and calling interface_add_data() to add it to the device's list
+of interfaces it belongs to. This list will be iterated over when the device
+is removed from the class (instead of all possible interfaces for a class).
+This structure should probably be embedded in whatever per-device data
+structure the interface is allocating anyway.
+
+Devices are enumerated within the interface. This happens in interface_add_data()
+and the enumerated value is stored in the struct intf_data for that device.
+
+sysfs
+~~~~~
+Each inter