* struct subsys_private - structure to hold the private to the driver core portions of the bus_type/class structure.
  *
  * @subsys - the struct kset that defines this subsystem
- * @devices_kset - the list of devices associated
+ * @devices_kset - the subsystem's 'devices' directory
+ * @interfaces - list of subsystem interfaces associated
+ * @mutex - protect the devices, and interfaces lists.
  *
  * @drivers_kset - the list of drivers associated
  * @klist_devices - the klist to iterate over the @devices_kset
  * @bus - pointer back to the struct bus_type that this structure is associated
  *        with.
  *
- * @class_interfaces - list of class_interfaces associated
  * @glue_dirs - "glue" directory to put in-between the parent device to
  *              avoid namespace conflicts
- * @class_mutex - mutex to protect the children, devices, and interfaces lists.
  * @class - pointer back to the struct class that this structure is associated
  *          with.
  *
 struct subsys_private {
        struct kset subsys;
        struct kset *devices_kset;
+       struct list_head interfaces;
+       struct mutex mutex;
 
        struct kset *drivers_kset;
        struct klist klist_devices;
        unsigned int drivers_autoprobe:1;
        struct bus_type *bus;
 
-       struct list_head class_interfaces;
        struct kset glue_dirs;
-       struct mutex class_mutex;
        struct class *class;
 };
 #define to_subsys_private(obj) container_of(obj, struct subsys_private, subsys.kobj)
 static inline int hypervisor_init(void) { return 0; }
 #endif
 extern int platform_bus_init(void);
-extern int system_bus_init(void);
 extern int cpu_dev_init(void);
 
 extern int bus_add_device(struct device *dev);
 
 extern int devres_release_all(struct device *dev);
 
+/* /sys/devices directory */
 extern struct kset *devices_kset;
 
 #if defined(CONFIG_MODULES) && defined(CONFIG_SYSFS)
 
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/string.h>
+#include <linux/mutex.h>
 #include "base.h"
 #include "power/power.h"
 
+/* /sys/devices/system */
+/* FIXME: make static after drivers/base/sys.c is deleted */
+struct kset *system_kset;
+
 #define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr)
 
 /*
 }
 EXPORT_SYMBOL_GPL(bus_find_device_by_name);
 
+/**
+ * subsys_find_device_by_id - find a device with a specific enumeration number
+ * @subsys: subsystem
+ * @id: index 'id' in struct device
+ * @hint: device to check first
+ *
+ * Check the hint's next object and if it is a match return it directly,
+ * otherwise, fall back to a full list search. Either way a reference for
+ * the returned object is taken.
+ */
+struct device *subsys_find_device_by_id(struct bus_type *subsys, unsigned int id,
+                                       struct device *hint)
+{
+       struct klist_iter i;
+       struct device *dev;
+
+       if (!subsys)
+               return NULL;
+
+       if (hint) {
+               klist_iter_init_node(&subsys->p->klist_devices, &i, &hint->p->knode_bus);
+               dev = next_device(&i);
+               if (dev && dev->id == id && get_device(dev)) {
+                       klist_iter_exit(&i);
+                       return dev;
+               }
+               klist_iter_exit(&i);
+       }
+
+       klist_iter_init_node(&subsys->p->klist_devices, &i, NULL);
+       while ((dev = next_device(&i))) {
+               if (dev->id == id && get_device(dev)) {
+                       klist_iter_exit(&i);
+                       return dev;
+               }
+       }
+       klist_iter_exit(&i);
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(subsys_find_device_by_id);
+
 static struct device_driver *next_driver(struct klist_iter *i)
 {
        struct klist_node *n = klist_next(i);
 void bus_probe_device(struct device *dev)
 {
        struct bus_type *bus = dev->bus;
+       struct subsys_interface *sif;
        int ret;
 
-       if (bus && bus->p->drivers_autoprobe) {
+       if (!bus)
+               return;
+
+       if (bus->p->drivers_autoprobe) {
                ret = device_attach(dev);
                WARN_ON(ret < 0);
        }
+
+       mutex_lock(&bus->p->mutex);
+       list_for_each_entry(sif, &bus->p->interfaces, node)
+               if (sif->add_dev)
+                       sif->add_dev(dev, sif);
+       mutex_unlock(&bus->p->mutex);
 }
 
 /**
  * bus_remove_device - remove device from bus
  * @dev: device to be removed
  *
- * - Remove symlink from bus's directory.
+ * - Remove device from all interfaces.
+ * - Remove symlink from bus' directory.
  * - Delete device from bus's list.
  * - Detach from its driver.
  * - Drop reference taken in bus_add_device().
  */
 void bus_remove_device(struct device *dev)
 {
-       if (dev->bus) {
-               sysfs_remove_link(&dev->kobj, "subsystem");
-               sysfs_remove_link(&dev->bus->p->devices_kset->kobj,
-                                 dev_name(dev));
-               device_remove_attrs(dev->bus, dev);
-               if (klist_node_attached(&dev->p->knode_bus))
-                       klist_del(&dev->p->knode_bus);
-
-               pr_debug("bus: '%s': remove device %s\n",
-                        dev->bus->name, dev_name(dev));
-               device_release_driver(dev);
-               bus_put(dev->bus);
-       }
+       struct bus_type *bus = dev->bus;
+       struct subsys_interface *sif;
+
+       if (!bus)
+               return;
+
+       mutex_lock(&bus->p->mutex);
+       list_for_each_entry(sif, &bus->p->interfaces, node)
+               if (sif->remove_dev)
+                       sif->remove_dev(dev, sif);
+       mutex_unlock(&bus->p->mutex);
+
+       sysfs_remove_link(&dev->kobj, "subsystem");
+       sysfs_remove_link(&dev->bus->p->devices_kset->kobj,
+                         dev_name(dev));
+       device_remove_attrs(dev->bus, dev);
+       if (klist_node_attached(&dev->p->knode_bus))
+               klist_del(&dev->p->knode_bus);
+
+       pr_debug("bus: '%s': remove device %s\n",
+                dev->bus->name, dev_name(dev));
+       device_release_driver(dev);
+       bus_put(dev->bus);
 }
 
 static int driver_add_attrs(struct bus_type *bus, struct device_driver *drv)
 static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store);
 
 /**
- * bus_register - register a bus with the system.
+ * __bus_register - register a driver-core subsystem
  * @bus: bus.
  *
  * Once we have that, we registered the bus with the kobject
  * infrastructure, then register the children subsystems it has:
- * the devices and drivers that belong to the bus.
+ * the devices and drivers that belong to the subsystem.
  */
-int bus_register(struct bus_type *bus)
+int __bus_register(struct bus_type *bus, struct lock_class_key *key)
 {
        int retval;
        struct subsys_private *priv;
                goto bus_drivers_fail;
        }
 
+       INIT_LIST_HEAD(&priv->interfaces);
+       __mutex_init(&priv->mutex, "subsys mutex", key);
        klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);
        klist_init(&priv->klist_drivers, NULL, NULL);
 
        bus->p = NULL;
        return retval;
 }
-EXPORT_SYMBOL_GPL(bus_register);
+EXPORT_SYMBOL_GPL(__bus_register);
 
 /**
  * bus_unregister - remove a bus from the system
 void bus_unregister(struct bus_type *bus)
 {
        pr_debug("bus: '%s': unregistering\n", bus->name);
+       if (bus->dev_root)
+               device_unregister(bus->dev_root);
        bus_remove_attrs(bus);
        remove_probe_files(bus);
        kset_unregister(bus->p->drivers_kset);
 }
 EXPORT_SYMBOL_GPL(bus_sort_breadthfirst);
 
+/**
+ * subsys_dev_iter_init - initialize subsys device iterator
+ * @iter: subsys iterator to initialize
+ * @subsys: the subsys we wanna iterate over
+ * @start: the device to start iterating from, if any
+ * @type: device_type of the devices to iterate over, NULL for all
+ *
+ * Initialize subsys iterator @iter such that it iterates over devices
+ * of @subsys.  If @start is set, the list iteration will start there,
+ * otherwise if it is NULL, the iteration starts at the beginning of
+ * the list.
+ */
+void subsys_dev_iter_init(struct subsys_dev_iter *iter, struct bus_type *subsys,
+                         struct device *start, const struct device_type *type)
+{
+       struct klist_node *start_knode = NULL;
+
+       if (start)
+               start_knode = &start->p->knode_bus;
+       klist_iter_init_node(&subsys->p->klist_devices, &iter->ki, start_knode);
+       iter->type = type;
+}
+EXPORT_SYMBOL_GPL(subsys_dev_iter_init);
+
+/**
+ * subsys_dev_iter_next - iterate to the next device
+ * @iter: subsys iterator to proceed
+ *
+ * Proceed @iter to the next device and return it.  Returns NULL if
+ * iteration is complete.
+ *
+ * The returned device is referenced and won't be released till
+ * iterator is proceed to the next device or exited.  The caller is
+ * free to do whatever it wants to do with the device including
+ * calling back into subsys code.
+ */
+struct device *subsys_dev_iter_next(struct subsys_dev_iter *iter)
+{
+       struct klist_node *knode;
+       struct device *dev;
+
+       for (;;) {
+               knode = klist_next(&iter->ki);
+               if (!knode)
+                       return NULL;
+               dev = container_of(knode, struct device_private, knode_bus)->device;
+               if (!iter->type || iter->type == dev->type)
+                       return dev;
+       }
+}
+EXPORT_SYMBOL_GPL(subsys_dev_iter_next);
+
+/**
+ * subsys_dev_iter_exit - finish iteration
+ * @iter: subsys iterator to finish
+ *
+ * Finish an iteration.  Always call this function after iteration is
+ * complete whether the iteration ran till the end or not.
+ */
+void subsys_dev_iter_exit(struct subsys_dev_iter *iter)
+{
+       klist_iter_exit(&iter->ki);
+}
+EXPORT_SYMBOL_GPL(subsys_dev_iter_exit);
+
+int subsys_interface_register(struct subsys_interface *sif)
+{
+       struct bus_type *subsys;
+       struct subsys_dev_iter iter;
+       struct device *dev;
+
+       if (!sif || !sif->subsys)
+               return -ENODEV;
+
+       subsys = bus_get(sif->subsys);
+       if (!subsys)
+               return -EINVAL;
+
+       mutex_lock(&subsys->p->mutex);
+       list_add_tail(&sif->node, &subsys->p->interfaces);
+       if (sif->add_dev) {
+               subsys_dev_iter_init(&iter, subsys, NULL, NULL);
+               while ((dev = subsys_dev_iter_next(&iter)))
+                       sif->add_dev(dev, sif);
+               subsys_dev_iter_exit(&iter);
+       }
+       mutex_unlock(&subsys->p->mutex);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(subsys_interface_register);
+
+void subsys_interface_unregister(struct subsys_interface *sif)
+{
+       struct bus_type *subsys = sif->subsys;
+       struct subsys_dev_iter iter;
+       struct device *dev;
+
+       if (!sif)
+               return;
+
+       mutex_lock(&subsys->p->mutex);
+       list_del_init(&sif->node);
+       if (sif->remove_dev) {
+               subsys_dev_iter_init(&iter, subsys, NULL, NULL);
+               while ((dev = subsys_dev_iter_next(&iter)))
+                       sif->remove_dev(dev, sif);
+               subsys_dev_iter_exit(&iter);
+       }
+       mutex_unlock(&subsys->p->mutex);
+
+       bus_put(subsys);
+}
+EXPORT_SYMBOL_GPL(subsys_interface_unregister);
+
+static void system_root_device_release(struct device *dev)
+{
+       kfree(dev);
+}
+/**
+ * subsys_system_register - register a subsystem at /sys/devices/system/
+ * @subsys - system subsystem
+ * @groups - default attributes for the root device
+ *
+ * All 'system' subsystems have a /sys/devices/system/<name> root device
+ * with the name of the subsystem. The root device can carry subsystem-
+ * wide attributes. All registered devices are below this single root
+ * device and are named after the subsystem with a simple enumeration
+ * number appended. The registered devices are not explicitely named;
+ * only 'id' in the device needs to be set.
+ *
+ * Do not use this interface for anything new, it exists for compatibility
+ * with bad ideas only. New subsystems should use plain subsystems; and
+ * add the subsystem-wide attributes should be added to the subsystem
+ * directory itself and not some create fake root-device placed in
+ * /sys/devices/system/<name>.
+ */
+int subsys_system_register(struct bus_type *subsys,
+                          const struct attribute_group **groups)
+{
+       struct device *dev;
+       int err;
+
+       err = bus_register(subsys);
+       if (err < 0)
+               return err;
+
+       dev = kzalloc(sizeof(struct device), GFP_KERNEL);
+       if (!dev) {
+               err = -ENOMEM;
+               goto err_dev;
+       }
+
+       err = dev_set_name(dev, "%s", subsys->name);
+       if (err < 0)
+               goto err_name;
+
+       dev->kobj.parent = &system_kset->kobj;
+       dev->groups = groups;
+       dev->release = system_root_device_release;
+
+       err = device_register(dev);
+       if (err < 0)
+               goto err_dev_reg;
+
+       subsys->dev_root = dev;
+       return 0;
+
+err_dev_reg:
+       put_device(dev);
+       dev = NULL;
+err_name:
+       kfree(dev);
+err_dev:
+       bus_unregister(subsys);
+       return err;
+}
+EXPORT_SYMBOL_GPL(subsys_system_register);
+
 int __init buses_init(void)
 {
        bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
        if (!bus_kset)
                return -ENOMEM;
+
+       system_kset = kset_create_and_add("system", NULL, &devices_kset->kobj);
+       if (!system_kset)
+               return -ENOMEM;
+
        return 0;
 }
 
        if (!cp)
                return -ENOMEM;
        klist_init(&cp->klist_devices, klist_class_dev_get, klist_class_dev_put);
-       INIT_LIST_HEAD(&cp->class_interfaces);
+       INIT_LIST_HEAD(&cp->interfaces);
        kset_init(&cp->glue_dirs);
-       __mutex_init(&cp->class_mutex, "struct class mutex", key);
+       __mutex_init(&cp->mutex, "subsys mutex", key);
        error = kobject_set_name(&cp->subsys.kobj, "%s", cls->name);
        if (error) {
                kfree(cp);
        if (!parent)
                return -EINVAL;
 
-       mutex_lock(&parent->p->class_mutex);
-       list_add_tail(&class_intf->node, &parent->p->class_interfaces);
+       mutex_lock(&parent->p->mutex);
+       list_add_tail(&class_intf->node, &parent->p->interfaces);
        if (class_intf->add_dev) {
                class_dev_iter_init(&iter, parent, NULL, NULL);
                while ((dev = class_dev_iter_next(&iter)))
                        class_intf->add_dev(dev, class_intf);
                class_dev_iter_exit(&iter);
        }
-       mutex_unlock(&parent->p->class_mutex);
+       mutex_unlock(&parent->p->mutex);
 
        return 0;
 }
        if (!parent)
                return;
 
-       mutex_lock(&parent->p->class_mutex);
+       mutex_lock(&parent->p->mutex);
        list_del_init(&class_intf->node);
        if (class_intf->remove_dev) {
                class_dev_iter_init(&iter, parent, NULL, NULL);
                        class_intf->remove_dev(dev, class_intf);
                class_dev_iter_exit(&iter);
        }
-       mutex_unlock(&parent->p->class_mutex);
+       mutex_unlock(&parent->p->mutex);
 
        class_put(parent);
 }
 
        .store  = dev_attr_store,
 };
 
+#define to_ext_attr(x) container_of(x, struct dev_ext_attribute, attr)
+
+ssize_t device_store_ulong(struct device *dev,
+                          struct device_attribute *attr,
+                          const char *buf, size_t size)
+{
+       struct dev_ext_attribute *ea = to_ext_attr(attr);
+       char *end;
+       unsigned long new = simple_strtoul(buf, &end, 0);
+       if (end == buf)
+               return -EINVAL;
+       *(unsigned long *)(ea->var) = new;
+       /* Always return full write size even if we didn't consume all */
+       return size;
+}
+EXPORT_SYMBOL_GPL(device_store_ulong);
+
+ssize_t device_show_ulong(struct device *dev,
+                         struct device_attribute *attr,
+                         char *buf)
+{
+       struct dev_ext_attribute *ea = to_ext_attr(attr);
+       return snprintf(buf, PAGE_SIZE, "%lx\n", *(unsigned long *)(ea->var));
+}
+EXPORT_SYMBOL_GPL(device_show_ulong);
+
+ssize_t device_store_int(struct device *dev,
+                        struct device_attribute *attr,
+                        const char *buf, size_t size)
+{
+       struct dev_ext_attribute *ea = to_ext_attr(attr);
+       char *end;
+       long new = simple_strtol(buf, &end, 0);
+       if (end == buf || new > INT_MAX || new < INT_MIN)
+               return -EINVAL;
+       *(int *)(ea->var) = new;
+       /* Always return full write size even if we didn't consume all */
+       return size;
+}
+EXPORT_SYMBOL_GPL(device_store_int);
+
+ssize_t device_show_int(struct device *dev,
+                       struct device_attribute *attr,
+                       char *buf)
+{
+       struct dev_ext_attribute *ea = to_ext_attr(attr);
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", *(int *)(ea->var));
+}
+EXPORT_SYMBOL_GPL(device_show_int);
 
 /**
  *     device_release - free device structure.
 static struct device_attribute devt_attr =
        __ATTR(dev, S_IRUGO, show_dev, NULL);
 
-/* kset to create /sys/devices/  */
+/* /sys/devices/ */
 struct kset *devices_kset;
 
 /**
                return k;
        }
 
+       /* subsystems can specify a default root directory for their devices */
+       if (!parent && dev->bus && dev->bus->dev_root)
+               return &dev->bus->dev_root->kobj;
+
        if (parent)
                return &parent->kobj;
        return NULL;
        cleanup_glue_dir(dev, dev->kobj.parent);
 }
 
-static void setup_parent(struct device *dev, struct device *parent)
-{
-       struct kobject *kobj;
-       kobj = get_device_parent(dev, parent);
-       if (kobj)
-               dev->kobj.parent = kobj;
-}
-
 static int device_add_class_symlinks(struct device *dev)
 {
        int error;
 int device_add(struct device *dev)
 {
        struct device *parent = NULL;
+       struct kobject *kobj;
        struct class_interface *class_intf;
        int error = -EINVAL;
 
                dev->init_name = NULL;
        }
 
+       /* subsystems can specify simple device enumeration */
+       if (!dev_name(dev) && dev->bus && dev->bus->dev_name)
+               dev_set_name(dev, "%s%u", dev->bus->dev_name, dev->id);
+
        if (!dev_name(dev)) {
                error = -EINVAL;
                goto name_error;
        pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
 
        parent = get_device(dev->parent);
-       setup_parent(dev, parent);
+       kobj = get_device_parent(dev, parent);
+       if (kobj)
+               dev->kobj.parent = kobj;
 
        /* use parent numa_node */
        if (parent)
                               &parent->p->klist_children);
 
        if (dev->class) {
-               mutex_lock(&dev->class->p->class_mutex);
+               mutex_lock(&dev->class->p->mutex);
                /* tie the class to the device */
                klist_add_tail(&dev->knode_class,
                               &dev->class->p->klist_devices);
 
                /* notify any interfaces that the device is here */
                list_for_each_entry(class_intf,
-                                   &dev->class->p->class_interfaces, node)
+                                   &dev->class->p->interfaces, node)
                        if (class_intf->add_dev)
                                class_intf->add_dev(dev, class_intf);
-               mutex_unlock(&dev->class->p->class_mutex);
+               mutex_unlock(&dev->class->p->mutex);
        }
 done:
        put_device(dev);
        if (dev->class) {
                device_remove_class_symlinks(dev);
 
-               mutex_lock(&dev->class->p->class_mutex);
+               mutex_lock(&dev->class->p->mutex);
                /* notify any interfaces that the device is now gone */
                list_for_each_entry(class_intf,
-                                   &dev->class->p->class_interfaces, node)
+                                   &dev->class->p->interfaces, node)
                        if (class_intf->remove_dev)
                                class_intf->remove_dev(dev, class_intf);
                /* remove the device from the class list */
                klist_del(&dev->knode_class);
-               mutex_unlock(&dev->class->p->class_mutex);
+               mutex_unlock(&dev->class->p->mutex);
        }
        device_remove_file(dev, &uevent_attr);
        device_remove_attrs(dev);
 
         * core core pieces.
         */
        platform_bus_init();
-       system_bus_init();
        cpu_dev_init();
        memory_dev_init();
 }
 
 }
 EXPORT_SYMBOL_GPL(sysdev_class_remove_file);
 
-static struct kset *system_kset;
+extern struct kset *system_kset;
 
 int sysdev_class_register(struct sysdev_class *cls)
 {
 EXPORT_SYMBOL_GPL(sysdev_register);
 EXPORT_SYMBOL_GPL(sysdev_unregister);
 
-int __init system_bus_init(void)
-{
-       system_kset = kset_create_and_add("system", NULL, &devices_kset->kobj);
-       if (!system_kset)
-               return -ENOMEM;
-       return 0;
-}
-
 #define to_ext_attr(x) container_of(x, struct sysdev_ext_attribute, attr)
 
 ssize_t sysdev_store_ulong(struct sys_device *sysdev,
 
  * struct bus_type - The bus type of the device
  *
  * @name:      The name of the bus.
+ * @dev_name:  Used for subsystems to enumerate devices like ("foo%u", dev->id).
+ * @dev_root:  Default device to use as the parent.
  * @bus_attrs: Default attributes of the bus.
  * @dev_attrs: Default attributes of the devices on the bus.
  * @drv_attrs: Default attributes of the device drivers on the bus.
  */
 struct bus_type {
        const char              *name;
+       const char              *dev_name;
+       struct device           *dev_root;
        struct bus_attribute    *bus_attrs;
        struct device_attribute *dev_attrs;
        struct driver_attribute *drv_attrs;
        struct subsys_private *p;
 };
 
-extern int __must_check bus_register(struct bus_type *bus);
+/* This is a #define to keep the compiler from merging different
+ * instances of the __key variable */
+#define bus_register(subsys)                   \
+({                                             \
+       static struct lock_class_key __key;     \
+       __bus_register(subsys, &__key); \
+})
+extern int __must_check __bus_register(struct bus_type *bus,
+                                      struct lock_class_key *key);
 extern void bus_unregister(struct bus_type *bus);
 
 extern int __must_check bus_rescan_devices(struct bus_type *bus);
 
 /* iterator helpers for buses */
+struct subsys_dev_iter {
+       struct klist_iter               ki;
+       const struct device_type        *type;
+};
+void subsys_dev_iter_init(struct subsys_dev_iter *iter,
+                        struct bus_type *subsys,
+                        struct device *start,
+                        const struct device_type *type);
+struct device *subsys_dev_iter_next(struct subsys_dev_iter *iter);
+void subsys_dev_iter_exit(struct subsys_dev_iter *iter);
 
 int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data,
                     int (*fn)(struct device *dev, void *data));
 struct device *bus_find_device_by_name(struct bus_type *bus,
                                       struct device *start,
                                       const char *name);
-
+struct device *subsys_find_device_by_id(struct bus_type *bus, unsigned int id,
+                                       struct device *hint);
 int bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
                     void *data, int (*fn)(struct device_driver *, void *));
-
 void bus_sort_breadthfirst(struct bus_type *bus,
                           int (*compare)(const struct device *a,
                                          const struct device *b));
                                  struct device *start, void *data,
                                  int (*match)(struct device *dev, void *data));
 
+/**
+ * struct subsys_interface - interfaces to device functions
+ * @name        name of the device function
+ * @subsystem   subsytem of the devices to attach to
+ * @node        the list of functions registered at the subsystem
+ * @add         device hookup to device function handler
+ * @remove      device hookup to device function handler
+ *
+ * Simple interfaces attached to a subsystem. Multiple interfaces can
+ * attach to a subsystem and its devices. Unlike drivers, they do not
+ * exclusively claim or control devices. Interfaces usually represent
+ * a specific functionality of a subsystem/class of devices.
+ */
+struct subsys_interface {
+       const char *name;
+       struct bus_type *subsys;
+       struct list_head node;
+       int (*add_dev)(struct device *dev, struct subsys_interface *sif);
+       int (*remove_dev)(struct device *dev, struct subsys_interface *sif);
+};
+
+int subsys_interface_register(struct subsys_interface *sif);
+void subsys_interface_unregister(struct subsys_interface *sif);
+
+int subsys_system_register(struct bus_type *subsys,
+                          const struct attribute_group **groups);
+
 /**
  * struct class - device classes
  * @name:      Name of the class.
                         const char *buf, size_t count);
 };
 
+struct dev_ext_attribute {
+       struct device_attribute attr;
+       void *var;
+};
+
+ssize_t device_show_ulong(struct device *dev, struct device_attribute *attr,
+                         char *buf);
+ssize_t device_store_ulong(struct device *dev, struct device_attribute *attr,
+                          const char *buf, size_t count);
+ssize_t device_show_int(struct device *dev, struct device_attribute *attr,
+                       char *buf);
+ssize_t device_store_int(struct device *dev, struct device_attribute *attr,
+                        const char *buf, size_t count);
+
 #define DEVICE_ATTR(_name, _mode, _show, _store) \
-struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
+       struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
+#define DEVICE_ULONG_ATTR(_name, _mode, _var) \
+       struct dev_ext_attribute dev_attr_##_name = \
+               { __ATTR(_name, _mode, device_show_ulong, device_store_ulong), &(_var) }
+#define DEVICE_INT_ATTR(_name, _mode, _var) \
+       struct dev_ext_attribute dev_attr_##_name = \
+               { __ATTR(_name, _mode, device_show_ulong, device_store_ulong), &(_var) }
 
 extern int __must_check device_create_file(struct device *device,
                                        const struct device_attribute *entry);
        struct device_node      *of_node; /* associated device tree node */
 
        dev_t                   devt;   /* dev_t, creates the sysfs "dev" */
+       u32                     id;     /* device instance */
 
        spinlock_t              devres_lock;
        struct list_head        devres_head;