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 int *busnr
= (int *)data
;
100 struct acpi_resource_address64 address
;
102 if (resource
->id
!= ACPI_RSTYPE_ADDRESS16
&&
103 resource
->id
!= ACPI_RSTYPE_ADDRESS32
&&
104 resource
->id
!= ACPI_RSTYPE_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
.min_address_range
;
115 static int get_root_bridge_busnr(acpi_handle handle
)
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
,
124 (unsigned long *)&bbn
);
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 acpi_os_free(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 acpi_os_free(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
);
207 /* Get device's handler per its address under its parent */
208 struct acpi_find_child
{
210 acpi_integer address
;
214 do_acpi_find_child(acpi_handle handle
, u32 lvl
, void *context
, void **rv
)
217 struct acpi_device_info
*info
;
218 struct acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
219 struct acpi_find_child
*find
= (struct acpi_find_child
*)context
;
221 status
= acpi_get_object_info(handle
, &buffer
);
222 if (ACPI_SUCCESS(status
)) {
223 info
= buffer
.pointer
;
224 if (info
->address
== find
->address
)
225 find
->handle
= handle
;
226 acpi_os_free(buffer
.pointer
);
231 acpi_handle
acpi_get_child(acpi_handle parent
, acpi_integer address
)
233 struct acpi_find_child find
= { NULL
, address
};
237 acpi_walk_namespace(ACPI_TYPE_DEVICE
, parent
,
238 1, do_acpi_find_child
, &find
, NULL
);
242 EXPORT_SYMBOL(acpi_get_child
);
244 /* Link ACPI devices with physical devices */
245 static void acpi_glue_data_handler(acpi_handle handle
,
246 u32 function
, void *context
)
248 /* we provide an empty handler */
251 /* Note: a success call will increase reference count by one */
252 struct device
*acpi_get_physical_device(acpi_handle handle
)
257 status
= acpi_get_data(handle
, acpi_glue_data_handler
, (void **)&dev
);
258 if (ACPI_SUCCESS(status
))
259 return get_device(dev
);
263 EXPORT_SYMBOL(acpi_get_physical_device
);
265 static int acpi_bind_one(struct device
*dev
, acpi_handle handle
)
269 if (dev
->firmware_data
) {
270 printk(KERN_WARNING PREFIX
271 "Drivers changed 'firmware_data' for %s\n", dev
->bus_id
);
275 status
= acpi_attach_data(handle
, acpi_glue_data_handler
, dev
);
276 if (ACPI_FAILURE(status
)) {
280 dev
->firmware_data
= handle
;
285 static int acpi_unbind_one(struct device
*dev
)
287 if (!dev
->firmware_data
)
289 if (dev
== acpi_get_physical_device(dev
->firmware_data
)) {
290 /* acpi_get_physical_device increase refcnt by one */
292 acpi_detach_data(dev
->firmware_data
, acpi_glue_data_handler
);
293 dev
->firmware_data
= NULL
;
294 /* acpi_bind_one increase refcnt by one */
297 printk(KERN_ERR PREFIX
298 "Oops, 'firmware_data' corrupt for %s\n", dev
->bus_id
);
303 static int acpi_platform_notify(struct device
*dev
)
305 struct acpi_bus_type
*type
;
309 if (!dev
->bus
|| !dev
->parent
) {
310 /* bridge devices genernally haven't bus or parent */
311 ret
= acpi_find_bridge_device(dev
, &handle
);
314 type
= acpi_get_bus_type(dev
->bus
);
316 DBG("No ACPI bus support for %s\n", dev
->bus_id
);
320 if ((ret
= type
->find_device(dev
, &handle
)) != 0)
321 DBG("Can't get handler for %s\n", dev
->bus_id
);
324 acpi_bind_one(dev
, handle
);
328 struct acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
330 acpi_get_name(dev
->firmware_data
, ACPI_FULL_PATHNAME
, &buffer
);
331 DBG("Device %s -> %s\n", dev
->bus_id
, (char *)buffer
.pointer
);
332 acpi_os_free(buffer
.pointer
);
334 DBG("Device %s -> No ACPI support\n", dev
->bus_id
);
340 static int acpi_platform_notify_remove(struct device
*dev
)
342 acpi_unbind_one(dev
);
346 static int __init
init_acpi_device_notify(void)
350 if (platform_notify
|| platform_notify_remove
) {
351 printk(KERN_ERR PREFIX
"Can't use platform_notify\n");
354 platform_notify
= acpi_platform_notify
;
355 platform_notify_remove
= acpi_platform_notify_remove
;
359 arch_initcall(init_acpi_device_notify
);