2 * Link physical devices with ACPI devices support
4 * Copyright (c) 2005 David Shaohua Li <shaohua.li@intel.com>
5 * Copyright (c) 2005 Intel Corp.
7 * This file is released under the GPLv2.
9 #include <linux/init.h>
10 #include <linux/list.h>
11 #include <linux/device.h>
12 #include <linux/rwsem.h>
13 #include <linux/acpi.h>
15 #define ACPI_GLUE_DEBUG 0
17 #define DBG(x...) printk(PREFIX x)
21 static LIST_HEAD(bus_type_list
);
22 static DECLARE_RWSEM(bus_type_sem
);
24 int register_acpi_bus_type(struct acpi_bus_type
*type
)
28 if (type
&& type
->bus
&& type
->find_device
) {
29 down_write(&bus_type_sem
);
30 list_add_tail(&type
->list
, &bus_type_list
);
31 up_write(&bus_type_sem
);
32 printk(KERN_INFO PREFIX
"bus type %s registered\n",
39 EXPORT_SYMBOL(register_acpi_bus_type
);
41 int unregister_acpi_bus_type(struct acpi_bus_type
*type
)
46 down_write(&bus_type_sem
);
47 list_del_init(&type
->list
);
48 up_write(&bus_type_sem
);
49 printk(KERN_INFO PREFIX
"ACPI bus type %s unregistered\n",
56 EXPORT_SYMBOL(unregister_acpi_bus_type
);
58 static struct acpi_bus_type
*acpi_get_bus_type(struct bus_type
*type
)
60 struct acpi_bus_type
*tmp
, *ret
= NULL
;
62 down_read(&bus_type_sem
);
63 list_for_each_entry(tmp
, &bus_type_list
, list
) {
64 if (tmp
->bus
== type
) {
69 up_read(&bus_type_sem
);
73 static int acpi_find_bridge_device(struct device
*dev
, acpi_handle
* handle
)
75 struct acpi_bus_type
*tmp
;
78 down_read(&bus_type_sem
);
79 list_for_each_entry(tmp
, &bus_type_list
, list
) {
80 if (tmp
->find_bridge
&& !tmp
->find_bridge(dev
, handle
)) {
85 up_read(&bus_type_sem
);
89 /* Get PCI root bridge's handle from its segment and bus number */
90 struct acpi_find_pci_root
{
97 do_root_bridge_busnr_callback(struct acpi_resource
*resource
, void *data
)
99 unsigned long *busnr
= (unsigned long *)data
;
100 struct acpi_resource_address64 address
;
102 if (resource
->type
!= ACPI_RESOURCE_TYPE_ADDRESS16
&&
103 resource
->type
!= ACPI_RESOURCE_TYPE_ADDRESS32
&&
104 resource
->type
!= ACPI_RESOURCE_TYPE_ADDRESS64
)
107 acpi_resource_to_address64(resource
, &address
);
108 if ((address
.address_length
> 0) &&
109 (address
.resource_type
== ACPI_BUS_NUMBER_RANGE
))
110 *busnr
= address
.minimum
;
115 static int get_root_bridge_busnr(acpi_handle handle
)
118 unsigned long bus
, bbn
;
119 struct acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
121 acpi_get_name(handle
, ACPI_FULL_PATHNAME
, &buffer
);
123 status
= acpi_evaluate_integer(handle
, METHOD_NAME__BBN
, NULL
,
125 if (status
== AE_NOT_FOUND
) {
127 printk(KERN_INFO PREFIX
128 "Assume root bridge [%s] bus is 0\n",
129 (char *)buffer
.pointer
);
133 if (ACPI_FAILURE(status
)) {
140 /* _BBN in some systems return 0 for all root bridges */
142 status
= acpi_walk_resources(handle
, METHOD_NAME__CRS
,
143 do_root_bridge_busnr_callback
, &bus
);
144 /* If _CRS failed, we just use _BBN */
145 if (ACPI_FAILURE(status
) || (bus
== -1))
149 printk(KERN_INFO PREFIX
150 "_BBN and _CRS returns different value for %s. Select _CRS\n",
151 (char *)buffer
.pointer
);
155 kfree(buffer
.pointer
);
160 find_pci_rootbridge(acpi_handle handle
, u32 lvl
, void *context
, void **rv
)
162 struct acpi_find_pci_root
*find
= (struct acpi_find_pci_root
*)context
;
163 unsigned long seg
, bus
;
166 struct acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
168 acpi_get_name(handle
, ACPI_FULL_PATHNAME
, &buffer
);
170 status
= acpi_evaluate_integer(handle
, METHOD_NAME__SEG
, NULL
, &seg
);
171 if (status
== AE_NOT_FOUND
) {
176 if (ACPI_FAILURE(status
)) {
177 status
= AE_CTRL_DEPTH
;
181 tmp
= get_root_bridge_busnr(handle
);
183 printk(KERN_ERR PREFIX
184 "Find root bridge failed for %s\n",
185 (char *)buffer
.pointer
);
186 status
= AE_CTRL_DEPTH
;
191 if (seg
== find
->seg
&& bus
== find
->bus
)
192 find
->handle
= handle
;
195 kfree(buffer
.pointer
);
199 acpi_handle
acpi_get_pci_rootbridge_handle(unsigned int seg
, unsigned int bus
)
201 struct acpi_find_pci_root find
= { seg
, bus
, NULL
};
203 acpi_get_devices(PCI_ROOT_HID_STRING
, find_pci_rootbridge
, &find
, NULL
);
206 EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle
);
208 /* Get device's handler per its address under its parent */
209 struct acpi_find_child
{
211 acpi_integer address
;
215 do_acpi_find_child(acpi_handle handle
, u32 lvl
, void *context
, void **rv
)
218 struct acpi_device_info
*info
;
219 struct acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
220 struct acpi_find_child
*find
= (struct acpi_find_child
*)context
;
222 status
= acpi_get_object_info(handle
, &buffer
);
223 if (ACPI_SUCCESS(status
)) {
224 info
= buffer
.pointer
;
225 if (info
->address
== find
->address
)
226 find
->handle
= handle
;
227 kfree(buffer
.pointer
);
232 acpi_handle
acpi_get_child(acpi_handle parent
, acpi_integer address
)
234 struct acpi_find_child find
= { NULL
, address
};
238 acpi_walk_namespace(ACPI_TYPE_DEVICE
, parent
,
239 1, do_acpi_find_child
, &find
, NULL
);
243 EXPORT_SYMBOL(acpi_get_child
);
245 /* Link ACPI devices with physical devices */
246 static void acpi_glue_data_handler(acpi_handle handle
,
247 u32 function
, void *context
)
249 /* we provide an empty handler */
252 /* Note: a success call will increase reference count by one */
253 struct device
*acpi_get_physical_device(acpi_handle handle
)
258 status
= acpi_get_data(handle
, acpi_glue_data_handler
, (void **)&dev
);
259 if (ACPI_SUCCESS(status
))
260 return get_device(dev
);
264 EXPORT_SYMBOL(acpi_get_physical_device
);
266 static int acpi_bind_one(struct device
*dev
, acpi_handle handle
)
270 if (dev
->firmware_data
) {
271 printk(KERN_WARNING PREFIX
272 "Drivers changed 'firmware_data' for %s\n", dev
->bus_id
);
276 status
= acpi_attach_data(handle
, acpi_glue_data_handler
, dev
);
277 if (ACPI_FAILURE(status
)) {
281 dev
->firmware_data
= handle
;
286 static int acpi_unbind_one(struct device
*dev
)
288 if (!dev
->firmware_data
)
290 if (dev
== acpi_get_physical_device(dev
->firmware_data
)) {
291 /* acpi_get_physical_device increase refcnt by one */
293 acpi_detach_data(dev
->firmware_data
, acpi_glue_data_handler
);
294 dev
->firmware_data
= NULL
;
295 /* acpi_bind_one increase refcnt by one */
298 printk(KERN_ERR PREFIX
299 "Oops, 'firmware_data' corrupt for %s\n", dev
->bus_id
);
304 static int acpi_platform_notify(struct device
*dev
)
306 struct acpi_bus_type
*type
;
310 if (!dev
->bus
|| !dev
->parent
) {
311 /* bridge devices genernally haven't bus or parent */
312 ret
= acpi_find_bridge_device(dev
, &handle
);
315 type
= acpi_get_bus_type(dev
->bus
);
317 DBG("No ACPI bus support for %s\n", dev
->bus_id
);
321 if ((ret
= type
->find_device(dev
, &handle
)) != 0)
322 DBG("Can't get handler for %s\n", dev
->bus_id
);
325 acpi_bind_one(dev
, handle
);
329 struct acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
331 acpi_get_name(dev
->firmware_data
, ACPI_FULL_PATHNAME
, &buffer
);
332 DBG("Device %s -> %s\n", dev
->bus_id
, (char *)buffer
.pointer
);
333 kfree(buffer
.pointer
);
335 DBG("Device %s -> No ACPI support\n", dev
->bus_id
);
341 static int acpi_platform_notify_remove(struct device
*dev
)
343 acpi_unbind_one(dev
);
347 static int __init
init_acpi_device_notify(void)
351 if (platform_notify
|| platform_notify_remove
) {
352 printk(KERN_ERR PREFIX
"Can't use platform_notify\n");
355 platform_notify
= acpi_platform_notify
;
356 platform_notify_remove
= acpi_platform_notify_remove
;
360 arch_initcall(init_acpi_device_notify
);