4 * Copyright 2012 Red Hat <mjg@redhat.com>
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation, version 2.
11 #include <linux/module.h>
12 #include <linux/usb.h>
13 #include <linux/device.h>
14 #include <linux/errno.h>
15 #include <linux/kernel.h>
16 #include <linux/acpi.h>
17 #include <linux/pci.h>
18 #include <linux/usb/hcd.h>
23 * usb_acpi_power_manageable - check whether usb port has
24 * acpi power resource.
25 * @hdev: USB device belonging to the usb hub
26 * @index: port index based zero
28 * Return true if the port has acpi power resource and false if no.
30 bool usb_acpi_power_manageable(struct usb_device
*hdev
, int index
)
32 acpi_handle port_handle
;
33 int port1
= index
+ 1;
35 port_handle
= usb_get_hub_port_acpi_handle(hdev
,
38 return acpi_bus_power_manageable(port_handle
);
42 EXPORT_SYMBOL_GPL(usb_acpi_power_manageable
);
45 * usb_acpi_set_power_state - control usb port's power via acpi power
47 * @hdev: USB device belonging to the usb hub
48 * @index: port index based zero
49 * @enable: power state expected to be set
51 * Notice to use usb_acpi_power_manageable() to check whether the usb port
52 * has acpi power resource before invoking this function.
54 * Returns 0 on success, else negative errno.
56 int usb_acpi_set_power_state(struct usb_device
*hdev
, int index
, bool enable
)
58 struct usb_hub
*hub
= usb_hub_to_struct_hub(hdev
);
59 struct usb_port
*port_dev
;
60 acpi_handle port_handle
;
62 int port1
= index
+ 1;
67 port_dev
= hub
->ports
[port1
- 1];
69 port_handle
= (acpi_handle
) usb_get_hub_port_acpi_handle(hdev
, port1
);
74 state
= ACPI_STATE_D0
;
76 state
= ACPI_STATE_D3_COLD
;
78 error
= acpi_bus_set_power(port_handle
, state
);
80 dev_dbg(&port_dev
->dev
, "acpi: power was set to %d\n", enable
);
82 dev_dbg(&port_dev
->dev
, "acpi: power failed to be set\n");
86 EXPORT_SYMBOL_GPL(usb_acpi_set_power_state
);
88 static enum usb_port_connect_type
usb_acpi_get_connect_type(acpi_handle handle
,
89 struct acpi_pld_info
*pld
)
91 enum usb_port_connect_type connect_type
= USB_PORT_CONNECT_TYPE_UNKNOWN
;
92 struct acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
93 union acpi_object
*upc
;
97 * According to ACPI Spec 9.13. PLD indicates whether usb port is
98 * user visible and _UPC indicates whether it is connectable. If
99 * the port was visible and connectable, it could be freely connected
100 * and disconnected with USB devices. If no visible and connectable,
101 * a usb device is directly hard-wired to the port. If no visible and
102 * no connectable, the port would be not used.
104 status
= acpi_evaluate_object(handle
, "_UPC", NULL
, &buffer
);
105 upc
= buffer
.pointer
;
106 if (!upc
|| (upc
->type
!= ACPI_TYPE_PACKAGE
)
107 || upc
->package
.count
!= 4) {
111 if (upc
->package
.elements
[0].integer
.value
)
112 if (pld
->user_visible
)
113 connect_type
= USB_PORT_CONNECT_TYPE_HOT_PLUG
;
115 connect_type
= USB_PORT_CONNECT_TYPE_HARD_WIRED
;
116 else if (!pld
->user_visible
)
117 connect_type
= USB_PORT_NOT_USED
;
125 * Private to usb-acpi, all the core needs to know is that
126 * port_dev->location is non-zero when it has been set by the firmware.
128 #define USB_ACPI_LOCATION_VALID (1 << 31)
130 static struct acpi_device
*usb_acpi_find_companion(struct device
*dev
)
132 struct usb_device
*udev
;
133 struct acpi_device
*adev
;
134 acpi_handle
*parent_handle
;
137 * In the ACPI DSDT table, only usb root hub and usb ports are
138 * acpi device nodes. The hierarchy like following.
146 * So all binding process is divided into two parts. binding
147 * root hub and usb ports.
149 if (is_usb_device(dev
)) {
150 udev
= to_usb_device(dev
);
154 /* root hub is only child (_ADR=0) under its parent, the HC */
155 adev
= ACPI_COMPANION(dev
->parent
);
156 return acpi_find_child_device(adev
, 0, false);
157 } else if (is_usb_port(dev
)) {
158 struct usb_port
*port_dev
= to_usb_port(dev
);
159 int port1
= port_dev
->portnum
;
160 struct acpi_pld_info
*pld
;
164 /* Get the struct usb_device point of port's hub */
165 udev
= to_usb_device(dev
->parent
->parent
);
168 * The root hub ports' parent is the root hub. The non-root-hub
169 * ports' parent is the parent hub port which the hub is
173 struct usb_hcd
*hcd
= bus_to_hcd(udev
->bus
);
176 raw
= usb_hcd_find_raw_port_number(hcd
, port1
);
177 adev
= acpi_find_child_device(ACPI_COMPANION(&udev
->dev
),
183 usb_get_hub_port_acpi_handle(udev
->parent
,
188 acpi_bus_get_device(parent_handle
, &adev
);
189 adev
= acpi_find_child_device(adev
, port1
, false);
193 handle
= adev
->handle
;
194 status
= acpi_get_physical_device_location(handle
, &pld
);
195 if (ACPI_FAILURE(status
) || !pld
)
198 port_dev
->location
= USB_ACPI_LOCATION_VALID
199 | pld
->group_token
<< 8 | pld
->group_position
;
200 port_dev
->connect_type
= usb_acpi_get_connect_type(handle
, pld
);
209 static bool usb_acpi_bus_match(struct device
*dev
)
211 return is_usb_device(dev
) || is_usb_port(dev
);
214 static struct acpi_bus_type usb_acpi_bus
= {
216 .match
= usb_acpi_bus_match
,
217 .find_companion
= usb_acpi_find_companion
,
220 int usb_acpi_register(void)
222 return register_acpi_bus_type(&usb_acpi_bus
);
225 void usb_acpi_unregister(void)
227 unregister_acpi_bus_type(&usb_acpi_bus
);