From e3e9c77659855158ecadd03106b3fcd7d444fc0f Mon Sep 17 00:00:00 2001 From: Patrick Mochel Date: Mon, 26 Aug 2002 06:12:10 -0700 Subject: Add class_data field to struct device, for the class drivers to use. --- include/linux/device.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/device.h b/include/linux/device.h index 4dcadb058a00..748dd2268549 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -65,7 +65,7 @@ struct bus_type { struct driver_dir_entry device_dir; struct driver_dir_entry driver_dir; - int (*match) (struct device * dev, struct device_driver * drv); + int (*match)(struct device * dev, struct device_driver * drv); }; @@ -281,6 +281,8 @@ struct device { void *driver_data; /* data private to the driver */ u32 class_num; /* class-enumerated value */ + void * class_data; /* class-specific data */ + void *platform_data; /* Platform specific data (e.g. ACPI, BIOS data relevant to device) */ -- cgit v1.2.3 From 30b92fdde37f40bbba4000b36ac83a30ff8996c9 Mon Sep 17 00:00:00 2001 From: Patrick Mochel Date: Mon, 26 Aug 2002 06:14:03 -0700 Subject: Add add() callback to struct bus_type. This is so other entities in the kernel can inform the bus about devices that it either doesn't know about yet (like when using the firmware to enumerate the system) or that it wouldn't otherwise find (for the same reason, or because they're weird legacy devices that won't be probed for). --- include/linux/device.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/device.h b/include/linux/device.h index 748dd2268549..fc3e10867139 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -66,6 +66,7 @@ struct bus_type { struct driver_dir_entry driver_dir; int (*match)(struct device * dev, struct device_driver * drv); + struct device * (*add) (struct device * parent, char * bus_id); }; -- cgit v1.2.3 From 538588a7f9cacde4dec762d31edc996787663ae9 Mon Sep 17 00:00:00 2001 From: Patrick Mochel Date: Mon, 26 Aug 2002 09:16:59 -0700 Subject: Add struct bus_type platform_bus and document its intentions. The platform bus is a pseudo-bus meant to group legacy devices. Not only does it give legacy devices a common parent and bus type, it provides the necessary infrastructure to allow for firmware-based enumeration of the system's devices (using the platform's add() callback). --- Documentation/driver-model/platform.txt | 99 +++++++++++++++++++++++++++++++++ drivers/base/Makefile | 2 +- drivers/base/platform.c | 27 +++++++++ include/linux/device.h | 3 + 4 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 Documentation/driver-model/platform.txt create mode 100644 drivers/base/platform.c (limited to 'include/linux') diff --git a/Documentation/driver-model/platform.txt b/Documentation/driver-model/platform.txt new file mode 100644 index 000000000000..5ead0296f2a8 --- /dev/null +++ b/Documentation/driver-model/platform.txt @@ -0,0 +1,99 @@ +Platform Devices and Drivers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Platform devices +~~~~~~~~~~~~~~~~ +Platform devices are devices that typically appear as autonomous +entities in the system. This includes legacy port-based devices and +host bridges to peripheral buses. + + +Platform drivers +~~~~~~~~~~~~~~~~ +Drivers for platform devices have typically very simple and +unstructured. Either the device was present at a particular I/O port +and the driver was loaded, or there was not. There was no possibility +of hotplugging or alternative discovery besides probing at a specific +I/O address and expecting a specific response. + + +Other Architectures, Modern Firmware, and new Platforms +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +These devices are not always at the legacy I/O ports. This is true on +other architectures and on some modern architectures. In most cases, +the drivers are modified to discover the devices at other well-known +ports for the given platform. However, the firmware in these systems +does usually know where exactly these devices reside, and in some +cases, it's the only way of discovering them. + + +The Platform Bus +~~~~~~~~~~~~~~~~ +A platform bus has been created to deal with these issues. First and +foremost, it groups all the legacy devices under a common bus, and +gives them a common parent if they don't already have one. + +But, besides the organizational benefits, the platform bus can also +accomodate firmware-based enumeration. + + +Device Discovery +~~~~~~~~~~~~~~~~ +The platform bus has no concept of probing for devices. Devices +discovery is left up to either the legacy drivers or the +firmware. These entities are expected to notify the platform of +devices that it discovers via the bus's add() callback: + + platform_bus.add(parent,bus_id). + + +Bus IDs +~~~~~~~ +Bus IDs are the canonical name for the device. There is no globally +standard addressing mechanism for legacy devices. In the IA-32 world, +we have Pnp IDs to use, as well as the legacy I/O ports. However, +neither tell what the device really is or have any meaning on other +platforms. + +Since both PnP IDs and the legacy I/O ports (and other standard I/O +ports for specific devices) have a 1:1 mapping, we map the +platform-specific name or identifier to a generic name (at least +within the scope of the kernel). + +For example, a serial driver might find a device at I/O 0x3f8. The +ACPI firmware might also discover a device with PnP ID (_HID) +PNP0501. Both correspond to the same device should be mapped to the +canonical name 'serial'. + +The bus_id field should be a concatenation of the canonical name and +the instance of that type of device. For example, the device at I/O +port 0x3f8 should have a bus_id of "serial0". This places the +responsibility of enumerating devices of a particular type up to the +discovery mechanism. But, they are the entity that should know best +(as opposed to the platform bus driver). + + +Drivers +~~~~~~~ +Drivers for platform devices should have a name that is the same as +the canonical name of the devices they support. This allows the +platform bus driver to do simple matching with the basic data +structures to determine if a driver supports a certain device. + +For example, a legacy serial driver should have a name of 'serial' and +register itself with the platform bus. + + +Driver Binding +~~~~~~~~~~~~~~ +Legacy drivers assume they are bound to the device once they start up +and probe an I/O port. Divorcing them from this will be a difficult +process. However, that shouldn't prevent us from impelementing +firmware-based enumeration. + +The firmware should notify the platform bus about devices before the +legacy drivers have had a chance to load. Once the drivers are loaded, +they driver model core will attempt to bind the driver to any +previously-discovered devices. Once that has happened, it will be free +to discover any other devices it pleases. + diff --git a/drivers/base/Makefile b/drivers/base/Makefile index 03f418c4b046..411b2bf44cfa 100644 --- a/drivers/base/Makefile +++ b/drivers/base/Makefile @@ -1,7 +1,7 @@ # Makefile for the Linux device tree obj-y := core.o sys.o interface.o power.o bus.o \ - driver.o class.o intf.o + driver.o class.o intf.o platform.o obj-y += fs/ diff --git a/drivers/base/platform.c b/drivers/base/platform.c new file mode 100644 index 000000000000..f637a25937cb --- /dev/null +++ b/drivers/base/platform.c @@ -0,0 +1,27 @@ +/* + * platform.c - platform 'psuedo' bus for legacy devices + * + * Please see Documentation/driver-model/platform.txt for more + * information. + */ + +#include +#include +#include + +static int platform_match(struct device * dev, struct device_driver * drv) +{ + return 0; +} + +struct bus_type platform_bus = { + .name = "platform", + .match = platform_match, +}; + +static int __init platform_bus_init(void) +{ + return bus_register(&platform_bus); +} + +postcore_initcall(platform_bus_init); diff --git a/include/linux/device.h b/include/linux/device.h index fc3e10867139..af11d2b8c8a5 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -369,6 +369,9 @@ extern void put_device(struct device * dev); extern int register_sys_device(struct device * dev); extern void unregister_sys_device(struct device * dev); +/* drivers/base/platform.c */ +extern struct bus_type platform_bus; + /* drivers/base/power.c */ extern int device_suspend(u32 state, u32 level); extern void device_resume(u32 level); -- cgit v1.2.3