[go: nahoru, domu]

1da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett/*
2da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett * USB-ACPI glue code
3da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett *
4da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett * Copyright 2012 Red Hat <mjg@redhat.com>
5da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett *
6da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett * This program is free software; you can redistribute it and/or modify it
7da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett * under the terms of the GNU General Public License as published by the Free
8da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett * Software Foundation, version 2.
9da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett *
10da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett */
11da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett#include <linux/module.h>
12da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett#include <linux/usb.h>
13da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett#include <linux/device.h>
14da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett#include <linux/errno.h>
15da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett#include <linux/kernel.h>
16da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett#include <linux/acpi.h>
17da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett#include <linux/pci.h>
18bafcaf6d84b5d1bf92dabd1ffe7753ed36b7552eLan Tianyu#include <linux/usb/hcd.h>
19da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett
20d99f6b41308779244662109a9c2bad09a82e8ac6Dan Williams#include "hub.h"
21da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett
22f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu/**
23f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu * usb_acpi_power_manageable - check whether usb port has
24f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu * acpi power resource.
25f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu * @hdev: USB device belonging to the usb hub
26f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu * @index: port index based zero
27f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu *
28f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu * Return true if the port has acpi power resource and false if no.
29f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu */
30f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyubool usb_acpi_power_manageable(struct usb_device *hdev, int index)
31f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu{
32f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu	acpi_handle port_handle;
33f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu	int port1 = index + 1;
34f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu
35f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu	port_handle = usb_get_hub_port_acpi_handle(hdev,
36f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu		port1);
37f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu	if (port_handle)
38f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu		return acpi_bus_power_manageable(port_handle);
39f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu	else
40f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu		return false;
41f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu}
42f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan TianyuEXPORT_SYMBOL_GPL(usb_acpi_power_manageable);
43f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu
44f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu/**
45f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu * usb_acpi_set_power_state - control usb port's power via acpi power
46f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu * resource
47f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu * @hdev: USB device belonging to the usb hub
48f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu * @index: port index based zero
49f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu * @enable: power state expected to be set
50f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu *
51f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu * Notice to use usb_acpi_power_manageable() to check whether the usb port
52f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu * has acpi power resource before invoking this function.
53f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu *
54f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu * Returns 0 on success, else negative errno.
55f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu */
56f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyuint usb_acpi_set_power_state(struct usb_device *hdev, int index, bool enable)
57f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu{
58d99f6b41308779244662109a9c2bad09a82e8ac6Dan Williams	struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
59d99f6b41308779244662109a9c2bad09a82e8ac6Dan Williams	struct usb_port *port_dev;
60f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu	acpi_handle port_handle;
61f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu	unsigned char state;
62f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu	int port1 = index + 1;
63f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu	int error = -EINVAL;
64f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu
65d99f6b41308779244662109a9c2bad09a82e8ac6Dan Williams	if (!hub)
66d99f6b41308779244662109a9c2bad09a82e8ac6Dan Williams		return -ENODEV;
67d99f6b41308779244662109a9c2bad09a82e8ac6Dan Williams	port_dev = hub->ports[port1 - 1];
68d99f6b41308779244662109a9c2bad09a82e8ac6Dan Williams
69d99f6b41308779244662109a9c2bad09a82e8ac6Dan Williams	port_handle = (acpi_handle) usb_get_hub_port_acpi_handle(hdev, port1);
70f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu	if (!port_handle)
71f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu		return error;
72f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu
73f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu	if (enable)
74f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu		state = ACPI_STATE_D0;
75f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu	else
76f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu		state = ACPI_STATE_D3_COLD;
77f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu
78f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu	error = acpi_bus_set_power(port_handle, state);
79f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu	if (!error)
80d99f6b41308779244662109a9c2bad09a82e8ac6Dan Williams		dev_dbg(&port_dev->dev, "acpi: power was set to %d\n", enable);
81f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu	else
82d99f6b41308779244662109a9c2bad09a82e8ac6Dan Williams		dev_dbg(&port_dev->dev, "acpi: power failed to be set\n");
83f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu
84f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu	return error;
85f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu}
86f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan TianyuEXPORT_SYMBOL_GPL(usb_acpi_set_power_state);
87f7ac7787ad361e31a7972e2854ed8dc2eedfac3bLan Tianyu
883bfd659baec822f54e4acb0734669e671d853a35Dan Williamsstatic enum usb_port_connect_type usb_acpi_get_connect_type(acpi_handle handle,
893bfd659baec822f54e4acb0734669e671d853a35Dan Williams		struct acpi_pld_info *pld)
9054d3f8c63d6940966217b807972778fb17c3fa82Matthew Garrett{
91d99f6b41308779244662109a9c2bad09a82e8ac6Dan Williams	enum usb_port_connect_type connect_type = USB_PORT_CONNECT_TYPE_UNKNOWN;
9254d3f8c63d6940966217b807972778fb17c3fa82Matthew Garrett	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
93d99f6b41308779244662109a9c2bad09a82e8ac6Dan Williams	union acpi_object *upc;
94d99f6b41308779244662109a9c2bad09a82e8ac6Dan Williams	acpi_status status;
95d99f6b41308779244662109a9c2bad09a82e8ac6Dan Williams
9605f916894a692f0cc0973aef21521133623b21c0Lan Tianyu	/*
97025d44309f92bd5e3d1b2c7fab66836ab25b541bRahul Bedarkar	 * According to ACPI Spec 9.13. PLD indicates whether usb port is
9805f916894a692f0cc0973aef21521133623b21c0Lan Tianyu	 * user visible and _UPC indicates whether it is connectable. If
9905f916894a692f0cc0973aef21521133623b21c0Lan Tianyu	 * the port was visible and connectable, it could be freely connected
10005f916894a692f0cc0973aef21521133623b21c0Lan Tianyu	 * and disconnected with USB devices. If no visible and connectable,
10105f916894a692f0cc0973aef21521133623b21c0Lan Tianyu	 * a usb device is directly hard-wired to the port. If no visible and
10205f916894a692f0cc0973aef21521133623b21c0Lan Tianyu	 * no connectable, the port would be not used.
10305f916894a692f0cc0973aef21521133623b21c0Lan Tianyu	 */
10405f916894a692f0cc0973aef21521133623b21c0Lan Tianyu	status = acpi_evaluate_object(handle, "_UPC", NULL, &buffer);
10554d3f8c63d6940966217b807972778fb17c3fa82Matthew Garrett	upc = buffer.pointer;
10654d3f8c63d6940966217b807972778fb17c3fa82Matthew Garrett	if (!upc || (upc->type != ACPI_TYPE_PACKAGE)
10754d3f8c63d6940966217b807972778fb17c3fa82Matthew Garrett		|| upc->package.count != 4) {
10854d3f8c63d6940966217b807972778fb17c3fa82Matthew Garrett		goto out;
10954d3f8c63d6940966217b807972778fb17c3fa82Matthew Garrett	}
11054d3f8c63d6940966217b807972778fb17c3fa82Matthew Garrett
11154d3f8c63d6940966217b807972778fb17c3fa82Matthew Garrett	if (upc->package.elements[0].integer.value)
112d8dc91b753b881c60c766c06aeec87675a07df4aLinus Torvalds		if (pld->user_visible)
113d99f6b41308779244662109a9c2bad09a82e8ac6Dan Williams			connect_type = USB_PORT_CONNECT_TYPE_HOT_PLUG;
11405f916894a692f0cc0973aef21521133623b21c0Lan Tianyu		else
115d99f6b41308779244662109a9c2bad09a82e8ac6Dan Williams			connect_type = USB_PORT_CONNECT_TYPE_HARD_WIRED;
116d8dc91b753b881c60c766c06aeec87675a07df4aLinus Torvalds	else if (!pld->user_visible)
117d99f6b41308779244662109a9c2bad09a82e8ac6Dan Williams		connect_type = USB_PORT_NOT_USED;
11854d3f8c63d6940966217b807972778fb17c3fa82Matthew Garrettout:
11954d3f8c63d6940966217b807972778fb17c3fa82Matthew Garrett	kfree(upc);
1203bfd659baec822f54e4acb0734669e671d853a35Dan Williams	return connect_type;
12154d3f8c63d6940966217b807972778fb17c3fa82Matthew Garrett}
12254d3f8c63d6940966217b807972778fb17c3fa82Matthew Garrett
1233bfd659baec822f54e4acb0734669e671d853a35Dan Williams
1243bfd659baec822f54e4acb0734669e671d853a35Dan Williams/*
1253bfd659baec822f54e4acb0734669e671d853a35Dan Williams * Private to usb-acpi, all the core needs to know is that
1263bfd659baec822f54e4acb0734669e671d853a35Dan Williams * port_dev->location is non-zero when it has been set by the firmware.
1273bfd659baec822f54e4acb0734669e671d853a35Dan Williams */
1283bfd659baec822f54e4acb0734669e671d853a35Dan Williams#define USB_ACPI_LOCATION_VALID (1 << 31)
1293bfd659baec822f54e4acb0734669e671d853a35Dan Williams
130e3f02c5228c4b600abf6ca243301176f25553bd5Rafael J. Wysockistatic struct acpi_device *usb_acpi_find_companion(struct device *dev)
131da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett{
132da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett	struct usb_device *udev;
133a4204ff0bd576fc114357eed70e7c4e776ddf396Dan Williams	struct acpi_device *adev;
134da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett	acpi_handle *parent_handle;
135da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett
136d557542421da643358201664903e67fd01dfca1aLan Tianyu	/*
137d557542421da643358201664903e67fd01dfca1aLan Tianyu	 * In the ACPI DSDT table, only usb root hub and usb ports are
138d557542421da643358201664903e67fd01dfca1aLan Tianyu	 * acpi device nodes. The hierarchy like following.
139d557542421da643358201664903e67fd01dfca1aLan Tianyu	 * Device (EHC1)
140d557542421da643358201664903e67fd01dfca1aLan Tianyu	 *	Device (HUBN)
141d557542421da643358201664903e67fd01dfca1aLan Tianyu	 *		Device (PR01)
142d557542421da643358201664903e67fd01dfca1aLan Tianyu	 *			Device (PR11)
143d557542421da643358201664903e67fd01dfca1aLan Tianyu	 *			Device (PR12)
144d557542421da643358201664903e67fd01dfca1aLan Tianyu	 *			Device (PR13)
145d557542421da643358201664903e67fd01dfca1aLan Tianyu	 *			...
146d557542421da643358201664903e67fd01dfca1aLan Tianyu	 * So all binding process is divided into two parts. binding
147d557542421da643358201664903e67fd01dfca1aLan Tianyu	 * root hub and usb ports.
148d557542421da643358201664903e67fd01dfca1aLan Tianyu	 */
149d557542421da643358201664903e67fd01dfca1aLan Tianyu	if (is_usb_device(dev)) {
150d557542421da643358201664903e67fd01dfca1aLan Tianyu		udev = to_usb_device(dev);
151a4204ff0bd576fc114357eed70e7c4e776ddf396Dan Williams		if (udev->parent)
152e3f02c5228c4b600abf6ca243301176f25553bd5Rafael J. Wysocki			return NULL;
15305f916894a692f0cc0973aef21521133623b21c0Lan Tianyu
154a4204ff0bd576fc114357eed70e7c4e776ddf396Dan Williams		/* root hub is only child (_ADR=0) under its parent, the HC */
155a4204ff0bd576fc114357eed70e7c4e776ddf396Dan Williams		adev = ACPI_COMPANION(dev->parent);
156a4204ff0bd576fc114357eed70e7c4e776ddf396Dan Williams		return acpi_find_child_device(adev, 0, false);
157d557542421da643358201664903e67fd01dfca1aLan Tianyu	} else if (is_usb_port(dev)) {
158d99f6b41308779244662109a9c2bad09a82e8ac6Dan Williams		struct usb_port *port_dev = to_usb_port(dev);
159a4204ff0bd576fc114357eed70e7c4e776ddf396Dan Williams		int port1 = port_dev->portnum;
1603bfd659baec822f54e4acb0734669e671d853a35Dan Williams		struct acpi_pld_info *pld;
1613bfd659baec822f54e4acb0734669e671d853a35Dan Williams		acpi_handle *handle;
1623bfd659baec822f54e4acb0734669e671d853a35Dan Williams		acpi_status status;
163e3f02c5228c4b600abf6ca243301176f25553bd5Rafael J. Wysocki
164d557542421da643358201664903e67fd01dfca1aLan Tianyu		/* Get the struct usb_device point of port's hub */
165d557542421da643358201664903e67fd01dfca1aLan Tianyu		udev = to_usb_device(dev->parent->parent);
166d557542421da643358201664903e67fd01dfca1aLan Tianyu
167d557542421da643358201664903e67fd01dfca1aLan Tianyu		/*
168d557542421da643358201664903e67fd01dfca1aLan Tianyu		 * The root hub ports' parent is the root hub. The non-root-hub
169d557542421da643358201664903e67fd01dfca1aLan Tianyu		 * ports' parent is the parent hub port which the hub is
170d557542421da643358201664903e67fd01dfca1aLan Tianyu		 * connected to.
171d557542421da643358201664903e67fd01dfca1aLan Tianyu		 */
172d557542421da643358201664903e67fd01dfca1aLan Tianyu		if (!udev->parent) {
173bafcaf6d84b5d1bf92dabd1ffe7753ed36b7552eLan Tianyu			struct usb_hcd *hcd = bus_to_hcd(udev->bus);
174d99f6b41308779244662109a9c2bad09a82e8ac6Dan Williams			int raw;
175bafcaf6d84b5d1bf92dabd1ffe7753ed36b7552eLan Tianyu
176d99f6b41308779244662109a9c2bad09a82e8ac6Dan Williams			raw = usb_hcd_find_raw_port_number(hcd, port1);
177e3f02c5228c4b600abf6ca243301176f25553bd5Rafael J. Wysocki			adev = acpi_find_child_device(ACPI_COMPANION(&udev->dev),
178d99f6b41308779244662109a9c2bad09a82e8ac6Dan Williams					raw, false);
179e3f02c5228c4b600abf6ca243301176f25553bd5Rafael J. Wysocki			if (!adev)
180e3f02c5228c4b600abf6ca243301176f25553bd5Rafael J. Wysocki				return NULL;
181d557542421da643358201664903e67fd01dfca1aLan Tianyu		} else {
182d557542421da643358201664903e67fd01dfca1aLan Tianyu			parent_handle =
183d557542421da643358201664903e67fd01dfca1aLan Tianyu				usb_get_hub_port_acpi_handle(udev->parent,
184d557542421da643358201664903e67fd01dfca1aLan Tianyu				udev->portnum);
185d557542421da643358201664903e67fd01dfca1aLan Tianyu			if (!parent_handle)
186e3f02c5228c4b600abf6ca243301176f25553bd5Rafael J. Wysocki				return NULL;
187d557542421da643358201664903e67fd01dfca1aLan Tianyu
188e3f02c5228c4b600abf6ca243301176f25553bd5Rafael J. Wysocki			acpi_bus_get_device(parent_handle, &adev);
189d99f6b41308779244662109a9c2bad09a82e8ac6Dan Williams			adev = acpi_find_child_device(adev, port1, false);
190e3f02c5228c4b600abf6ca243301176f25553bd5Rafael J. Wysocki			if (!adev)
191e3f02c5228c4b600abf6ca243301176f25553bd5Rafael J. Wysocki				return NULL;
192d557542421da643358201664903e67fd01dfca1aLan Tianyu		}
1933bfd659baec822f54e4acb0734669e671d853a35Dan Williams		handle = adev->handle;
1943bfd659baec822f54e4acb0734669e671d853a35Dan Williams		status = acpi_get_physical_device_location(handle, &pld);
1953bfd659baec822f54e4acb0734669e671d853a35Dan Williams		if (ACPI_FAILURE(status) || !pld)
1963bfd659baec822f54e4acb0734669e671d853a35Dan Williams			return adev;
1973bfd659baec822f54e4acb0734669e671d853a35Dan Williams
1983bfd659baec822f54e4acb0734669e671d853a35Dan Williams		port_dev->location = USB_ACPI_LOCATION_VALID
1993bfd659baec822f54e4acb0734669e671d853a35Dan Williams			| pld->group_token << 8 | pld->group_position;
2003bfd659baec822f54e4acb0734669e671d853a35Dan Williams		port_dev->connect_type = usb_acpi_get_connect_type(handle, pld);
2013bfd659baec822f54e4acb0734669e671d853a35Dan Williams		ACPI_FREE(pld);
2023bfd659baec822f54e4acb0734669e671d853a35Dan Williams
203e3f02c5228c4b600abf6ca243301176f25553bd5Rafael J. Wysocki		return adev;
204e3f02c5228c4b600abf6ca243301176f25553bd5Rafael J. Wysocki	}
205da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett
206e3f02c5228c4b600abf6ca243301176f25553bd5Rafael J. Wysocki	return NULL;
207da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett}
208da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett
20953540098b23c3884b4a0b4f220b9d977bc496af3Rafael J. Wysockistatic bool usb_acpi_bus_match(struct device *dev)
21053540098b23c3884b4a0b4f220b9d977bc496af3Rafael J. Wysocki{
21153540098b23c3884b4a0b4f220b9d977bc496af3Rafael J. Wysocki	return is_usb_device(dev) || is_usb_port(dev);
21253540098b23c3884b4a0b4f220b9d977bc496af3Rafael J. Wysocki}
21353540098b23c3884b4a0b4f220b9d977bc496af3Rafael J. Wysocki
214da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrettstatic struct acpi_bus_type usb_acpi_bus = {
21553540098b23c3884b4a0b4f220b9d977bc496af3Rafael J. Wysocki	.name = "USB",
21653540098b23c3884b4a0b4f220b9d977bc496af3Rafael J. Wysocki	.match = usb_acpi_bus_match,
217e3f02c5228c4b600abf6ca243301176f25553bd5Rafael J. Wysocki	.find_companion = usb_acpi_find_companion,
218da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett};
219da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett
220da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrettint usb_acpi_register(void)
221da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett{
222da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett	return register_acpi_bus_type(&usb_acpi_bus);
223da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett}
224da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett
225da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrettvoid usb_acpi_unregister(void)
226da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett{
227da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett	unregister_acpi_bus_type(&usb_acpi_bus);
228da0af6e78ef311d97754aa03e10eade82cc99e16Matthew Garrett}
229