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", type
->bus
->name
);
38 EXPORT_SYMBOL(register_acpi_bus_type
);
40 int unregister_acpi_bus_type(struct acpi_bus_type
*type
)
45 down_write(&bus_type_sem
);
46 list_del_init(&type
->list
);
47 up_write(&bus_type_sem
);
48 printk(KERN_INFO PREFIX
"ACPI bus type %s unregistered\n", type
->bus
->name
);
54 EXPORT_SYMBOL(unregister_acpi_bus_type
);
56 static struct acpi_bus_type
*acpi_get_bus_type(struct bus_type
*type
)
58 struct acpi_bus_type
*tmp
, *ret
= NULL
;
60 down_read(&bus_type_sem
);
61 list_for_each_entry(tmp
, &bus_type_list
, list
) {
62 if (tmp
->bus
== type
) {
67 up_read(&bus_type_sem
);
71 static int acpi_find_bridge_device(struct device
*dev
, acpi_handle
* handle
)
73 struct acpi_bus_type
*tmp
;
76 down_read(&bus_type_sem
);
77 list_for_each_entry(tmp
, &bus_type_list
, list
) {
78 if (tmp
->find_bridge
&& !tmp
->find_bridge(dev
, handle
)) {
83 up_read(&bus_type_sem
);
87 /* Get PCI root bridge's handle from its segment and bus number */
88 struct acpi_find_pci_root
{
95 do_root_bridge_busnr_callback(struct acpi_resource
*resource
, void *data
)
97 int *busnr
= (int *)data
;
98 struct acpi_resource_address64 address
;
100 if (resource
->id
!= ACPI_RSTYPE_ADDRESS16
&&
101 resource
->id
!= ACPI_RSTYPE_ADDRESS32
&&
102 resource
->id
!= ACPI_RSTYPE_ADDRESS64
)
105 acpi_resource_to_address64(resource
, &address
);
106 if ((address
.address_length
> 0) &&
107 (address
.resource_type
== ACPI_BUS_NUMBER_RANGE
))
108 *busnr
= address
.min_address_range
;
113 static int get_root_bridge_busnr(acpi_handle handle
)
117 struct acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
119 acpi_get_name(handle
, ACPI_FULL_PATHNAME
, &buffer
);
121 status
= acpi_evaluate_integer(handle
, METHOD_NAME__BBN
, NULL
,
122 (unsigned long *)&bbn
);
123 if (status
== AE_NOT_FOUND
) {
125 printk(KERN_INFO PREFIX
126 "Assume root bridge [%s] bus is 0\n",
127 (char *)buffer
.pointer
);
131 if (ACPI_FAILURE(status
)) {
138 /* _BBN in some systems return 0 for all root bridges */
140 status
= acpi_walk_resources(handle
, METHOD_NAME__CRS
,
141 do_root_bridge_busnr_callback
, &bus
);
142 /* If _CRS failed, we just use _BBN */
143 if (ACPI_FAILURE(status
) || (bus
== -1))
147 printk(KERN_INFO PREFIX
148 "_BBN and _CRS returns different value for %s. Select _CRS\n",
149 (char *)buffer
.pointer
);
153 acpi_os_free(buffer
.pointer
);
158 find_pci_rootbridge(acpi_handle handle
, u32 lvl
, void *context
, void **rv
)
160 struct acpi_find_pci_root
*find
= (struct acpi_find_pci_root
*)context
;
161 unsigned long seg
, bus
;
164 struct acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
166 acpi_get_name(handle
, ACPI_FULL_PATHNAME
, &buffer
);
168 status
= acpi_evaluate_integer(handle
, METHOD_NAME__SEG
, NULL
, &seg
);
169 if (status
== AE_NOT_FOUND
) {
171 printk(KERN_INFO PREFIX
172 "Assume root bridge [%s] segment is 0\n",
173 (char *)buffer
.pointer
);
177 if (ACPI_FAILURE(status
)) {
178 status
= AE_CTRL_DEPTH
;
182 tmp
= get_root_bridge_busnr(handle
);
184 printk(KERN_ERR PREFIX
185 "Find root bridge failed for %s\n",
186 (char *)buffer
.pointer
);
187 status
= AE_CTRL_DEPTH
;
192 if (seg
== find
->seg
&& bus
== find
->bus
)
193 find
->handle
= handle
;
196 acpi_os_free(buffer
.pointer
);
200 acpi_handle
acpi_get_pci_rootbridge_handle(unsigned int seg
, unsigned int bus
)
202 struct acpi_find_pci_root find
= { seg
, bus
, NULL
};
204 acpi_get_devices(PCI_ROOT_HID_STRING
, find_pci_rootbridge
, &find
, NULL
);
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 acpi_os_free(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 acpi_os_free(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
);