diff options
249 files changed, 16059 insertions, 3376 deletions
diff --git a/Documentation/ABI/testing/configfs-usb-gadget b/Documentation/ABI/testing/configfs-usb-gadget new file mode 100644 index 000000000000..01e769d6984d --- /dev/null +++ b/Documentation/ABI/testing/configfs-usb-gadget | |||
@@ -0,0 +1,81 @@ | |||
1 | What: /config/usb-gadget | ||
2 | Date: Jun 2013 | ||
3 | KenelVersion: 3.11 | ||
4 | Description: | ||
5 | This group contains sub-groups corresponding to created | ||
6 | USB gadgets. | ||
7 | |||
8 | What: /config/usb-gadget/gadget | ||
9 | Date: Jun 2013 | ||
10 | KenelVersion: 3.11 | ||
11 | Description: | ||
12 | |||
13 | The attributes of a gadget: | ||
14 | |||
15 | UDC - bind a gadget to UDC/unbind a gadget; | ||
16 | write UDC's name found in /sys/class/udc/* | ||
17 | to bind a gadget, empty string "" to unbind. | ||
18 | |||
19 | bDeviceClass - USB device class code | ||
20 | bDeviceSubClass - USB device subclass code | ||
21 | bDeviceProtocol - USB device protocol code | ||
22 | bMaxPacketSize0 - maximum endpoint 0 packet size | ||
23 | bcdDevice - bcd device release number | ||
24 | bcdUSB - bcd USB specification version number | ||
25 | idProduct - product ID | ||
26 | idVendor - vendor ID | ||
27 | |||
28 | What: /config/usb-gadget/gadget/configs | ||
29 | Date: Jun 2013 | ||
30 | KenelVersion: 3.11 | ||
31 | Description: | ||
32 | This group contains a USB gadget's configurations | ||
33 | |||
34 | What: /config/usb-gadget/gadget/configs/config | ||
35 | Date: Jun 2013 | ||
36 | KernelVersion: 3.11 | ||
37 | Description: | ||
38 | The attributes of a configuration: | ||
39 | |||
40 | bmAttributes - configuration characteristics | ||
41 | MaxPower - maximum power consumption from the bus | ||
42 | |||
43 | What: /config/usb-gadget/gadget/configs/config/strings | ||
44 | Date: Jun 2013 | ||
45 | KernelVersion: 3.11 | ||
46 | Description: | ||
47 | This group contains subdirectories for language-specific | ||
48 | strings for this configuration. | ||
49 | |||
50 | What: /config/usb-gadget/gadget/configs/config/strings/language | ||
51 | Date: Jun 2013 | ||
52 | KernelVersion: 3.11 | ||
53 | Description: | ||
54 | The attributes: | ||
55 | |||
56 | configuration - configuration description | ||
57 | |||
58 | |||
59 | What: /config/usb-gadget/gadget/functions | ||
60 | Date: Jun 2013 | ||
61 | KenelVersion: 3.11 | ||
62 | Description: | ||
63 | This group contains functions available to this USB gadget. | ||
64 | |||
65 | What: /config/usb-gadget/gadget/strings | ||
66 | Date: Jun 2013 | ||
67 | KenelVersion: 3.11 | ||
68 | Description: | ||
69 | This group contains subdirectories for language-specific | ||
70 | strings for this gadget. | ||
71 | |||
72 | What: /config/usb-gadget/gadget/strings/language | ||
73 | Date: Jun 2013 | ||
74 | KenelVersion: 3.11 | ||
75 | Description: | ||
76 | The attributes: | ||
77 | |||
78 | serialnumber - gadget's serial number (string) | ||
79 | product - gadget's product description | ||
80 | manufacturer - gadget's manufacturer description | ||
81 | |||
diff --git a/Documentation/ABI/testing/configfs-usb-gadget-acm b/Documentation/ABI/testing/configfs-usb-gadget-acm new file mode 100644 index 000000000000..5708a568b5f6 --- /dev/null +++ b/Documentation/ABI/testing/configfs-usb-gadget-acm | |||
@@ -0,0 +1,8 @@ | |||
1 | What: /config/usb-gadget/gadget/functions/acm.name | ||
2 | Date: Jun 2013 | ||
3 | KenelVersion: 3.11 | ||
4 | Description: | ||
5 | |||
6 | This item contains just one readonly attribute: port_num. | ||
7 | It contains the port number of the /dev/ttyGS<n> device | ||
8 | associated with acm function's instance "name". | ||
diff --git a/Documentation/ABI/testing/configfs-usb-gadget-ecm b/Documentation/ABI/testing/configfs-usb-gadget-ecm new file mode 100644 index 000000000000..6b9a582ce0b5 --- /dev/null +++ b/Documentation/ABI/testing/configfs-usb-gadget-ecm | |||
@@ -0,0 +1,16 @@ | |||
1 | What: /config/usb-gadget/gadget/functions/ecm.name | ||
2 | Date: Jun 2013 | ||
3 | KenelVersion: 3.11 | ||
4 | Description: | ||
5 | The attributes: | ||
6 | |||
7 | ifname - network device interface name associated with | ||
8 | this function instance | ||
9 | qmult - queue length multiplier for high and | ||
10 | super speed | ||
11 | host_addr - MAC address of host's end of this | ||
12 | Ethernet over USB link | ||
13 | dev_addr - MAC address of device's end of this | ||
14 | Ethernet over USB link | ||
15 | |||
16 | |||
diff --git a/Documentation/ABI/testing/configfs-usb-gadget-eem b/Documentation/ABI/testing/configfs-usb-gadget-eem new file mode 100644 index 000000000000..dbddf36b48b3 --- /dev/null +++ b/Documentation/ABI/testing/configfs-usb-gadget-eem | |||
@@ -0,0 +1,14 @@ | |||
1 | What: /config/usb-gadget/gadget/functions/eem.name | ||
2 | Date: Jun 2013 | ||
3 | KenelVersion: 3.11 | ||
4 | Description: | ||
5 | The attributes: | ||
6 | |||
7 | ifname - network device interface name associated with | ||
8 | this function instance | ||
9 | qmult - queue length multiplier for high and | ||
10 | super speed | ||
11 | host_addr - MAC address of host's end of this | ||
12 | Ethernet over USB link | ||
13 | dev_addr - MAC address of device's end of this | ||
14 | Ethernet over USB link | ||
diff --git a/Documentation/ABI/testing/configfs-usb-gadget-ncm b/Documentation/ABI/testing/configfs-usb-gadget-ncm new file mode 100644 index 000000000000..bc309f42357d --- /dev/null +++ b/Documentation/ABI/testing/configfs-usb-gadget-ncm | |||
@@ -0,0 +1,15 @@ | |||
1 | What: /config/usb-gadget/gadget/functions/ncm.name | ||
2 | Date: Jun 2013 | ||
3 | KenelVersion: 3.11 | ||
4 | Description: | ||
5 | The attributes: | ||
6 | |||
7 | ifname - network device interface name associated with | ||
8 | this function instance | ||
9 | qmult - queue length multiplier for high and | ||
10 | super speed | ||
11 | host_addr - MAC address of host's end of this | ||
12 | Ethernet over USB link | ||
13 | dev_addr - MAC address of device's end of this | ||
14 | Ethernet over USB link | ||
15 | |||
diff --git a/Documentation/ABI/testing/configfs-usb-gadget-obex b/Documentation/ABI/testing/configfs-usb-gadget-obex new file mode 100644 index 000000000000..aaa5c96fb7c6 --- /dev/null +++ b/Documentation/ABI/testing/configfs-usb-gadget-obex | |||
@@ -0,0 +1,9 @@ | |||
1 | What: /config/usb-gadget/gadget/functions/obex.name | ||
2 | Date: Jun 2013 | ||
3 | KenelVersion: 3.11 | ||
4 | Description: | ||
5 | |||
6 | This item contains just one readonly attribute: port_num. | ||
7 | It contains the port number of the /dev/ttyGS<n> device | ||
8 | associated with obex function's instance "name". | ||
9 | |||
diff --git a/Documentation/ABI/testing/configfs-usb-gadget-phonet b/Documentation/ABI/testing/configfs-usb-gadget-phonet new file mode 100644 index 000000000000..3e3b742cdfd7 --- /dev/null +++ b/Documentation/ABI/testing/configfs-usb-gadget-phonet | |||
@@ -0,0 +1,8 @@ | |||
1 | What: /config/usb-gadget/gadget/functions/phonet.name | ||
2 | Date: Jun 2013 | ||
3 | KenelVersion: 3.11 | ||
4 | Description: | ||
5 | |||
6 | This item contains just one readonly attribute: ifname. | ||
7 | It contains the network interface name assigned during | ||
8 | network device registration. | ||
diff --git a/Documentation/ABI/testing/configfs-usb-gadget-rndis b/Documentation/ABI/testing/configfs-usb-gadget-rndis new file mode 100644 index 000000000000..822e6dad8fc0 --- /dev/null +++ b/Documentation/ABI/testing/configfs-usb-gadget-rndis | |||
@@ -0,0 +1,14 @@ | |||
1 | What: /config/usb-gadget/gadget/functions/rndis.name | ||
2 | Date: Jun 2013 | ||
3 | KenelVersion: 3.11 | ||
4 | Description: | ||
5 | The attributes: | ||
6 | |||
7 | ifname - network device interface name associated with | ||
8 | this function instance | ||
9 | qmult - queue length multiplier for high and | ||
10 | super speed | ||
11 | host_addr - MAC address of host's end of this | ||
12 | Ethernet over USB link | ||
13 | dev_addr - MAC address of device's end of this | ||
14 | Ethernet over USB link | ||
diff --git a/Documentation/ABI/testing/configfs-usb-gadget-serial b/Documentation/ABI/testing/configfs-usb-gadget-serial new file mode 100644 index 000000000000..16f130c1501f --- /dev/null +++ b/Documentation/ABI/testing/configfs-usb-gadget-serial | |||
@@ -0,0 +1,9 @@ | |||
1 | What: /config/usb-gadget/gadget/functions/gser.name | ||
2 | Date: Jun 2013 | ||
3 | KenelVersion: 3.11 | ||
4 | Description: | ||
5 | |||
6 | This item contains just one readonly attribute: port_num. | ||
7 | It contains the port number of the /dev/ttyGS<n> device | ||
8 | associated with gser function's instance "name". | ||
9 | |||
diff --git a/Documentation/ABI/testing/configfs-usb-gadget-subset b/Documentation/ABI/testing/configfs-usb-gadget-subset new file mode 100644 index 000000000000..154ae597cd99 --- /dev/null +++ b/Documentation/ABI/testing/configfs-usb-gadget-subset | |||
@@ -0,0 +1,14 @@ | |||
1 | What: /config/usb-gadget/gadget/functions/geth.name | ||
2 | Date: Jun 2013 | ||
3 | KenelVersion: 3.11 | ||
4 | Description: | ||
5 | The attributes: | ||
6 | |||
7 | ifname - network device interface name associated with | ||
8 | this function instance | ||
9 | qmult - queue length multiplier for high and | ||
10 | super speed | ||
11 | host_addr - MAC address of host's end of this | ||
12 | Ethernet over USB link | ||
13 | dev_addr - MAC address of device's end of this | ||
14 | Ethernet over USB link | ||
diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb index f093e59cbe5f..9759b8c91332 100644 --- a/Documentation/ABI/testing/sysfs-bus-usb +++ b/Documentation/ABI/testing/sysfs-bus-usb | |||
@@ -236,3 +236,30 @@ Description: | |||
236 | This attribute is to expose these information to user space. | 236 | This attribute is to expose these information to user space. |
237 | The file will read "hotplug", "wired" and "not used" if the | 237 | The file will read "hotplug", "wired" and "not used" if the |
238 | information is available, and "unknown" otherwise. | 238 | information is available, and "unknown" otherwise. |
239 | |||
240 | What: /sys/bus/usb/devices/.../power/usb2_lpm_l1_timeout | ||
241 | Date: May 2013 | ||
242 | Contact: Mathias Nyman <mathias.nyman@linux.intel.com> | ||
243 | Description: | ||
244 | USB 2.0 devices may support hardware link power management (LPM) | ||
245 | L1 sleep state. The usb2_lpm_l1_timeout attribute allows | ||
246 | tuning the timeout for L1 inactivity timer (LPM timer), e.g. | ||
247 | needed inactivity time before host requests the device to go to L1 sleep. | ||
248 | Useful for power management tuning. | ||
249 | Supported values are 0 - 65535 microseconds. | ||
250 | |||
251 | What: /sys/bus/usb/devices/.../power/usb2_lpm_besl | ||
252 | Date: May 2013 | ||
253 | Contact: Mathias Nyman <mathias.nyman@linux.intel.com> | ||
254 | Description: | ||
255 | USB 2.0 devices that support hardware link power management (LPM) | ||
256 | L1 sleep state now use a best effort service latency value (BESL) to | ||
257 | indicate the best effort to resumption of service to the device after the | ||
258 | initiation of the resume event. | ||
259 | If the device does not have a preferred besl value then the host can select | ||
260 | one instead. This usb2_lpm_besl attribute allows to tune the host selected besl | ||
261 | value in order to tune power saving and service latency. | ||
262 | |||
263 | Supported values are 0 - 15. | ||
264 | More information on how besl values map to microseconds can be found in | ||
265 | USB 2.0 ECN Errata for Link Power Management, section 4.10) | ||
diff --git a/Documentation/ABI/testing/sysfs-class-uwb_rc-wusbhc b/Documentation/ABI/testing/sysfs-class-uwb_rc-wusbhc index 25b1e751b777..5977e2875325 100644 --- a/Documentation/ABI/testing/sysfs-class-uwb_rc-wusbhc +++ b/Documentation/ABI/testing/sysfs-class-uwb_rc-wusbhc | |||
@@ -36,3 +36,22 @@ Description: | |||
36 | 36 | ||
37 | Refer to [ECMA-368] section 10.3.1.1 for the value to | 37 | Refer to [ECMA-368] section 10.3.1.1 for the value to |
38 | use. | 38 | use. |
39 | |||
40 | What: /sys/class/uwb_rc/uwbN/wusbhc/wusb_dnts | ||
41 | Date: June 2013 | ||
42 | KernelVersion: 3.11 | ||
43 | Contact: Thomas Pugliese <thomas.pugliese@gmail.com> | ||
44 | Description: | ||
45 | The device notification time slot (DNTS) count and inverval in | ||
46 | milliseconds that the WUSB host should use. This controls how | ||
47 | often the devices will have the opportunity to send | ||
48 | notifications to the host. | ||
49 | |||
50 | What: /sys/class/uwb_rc/uwbN/wusbhc/wusb_retry_count | ||
51 | Date: June 2013 | ||
52 | KernelVersion: 3.11 | ||
53 | Contact: Thomas Pugliese <thomas.pugliese@gmail.com> | ||
54 | Description: | ||
55 | The number of retries that the WUSB host should attempt | ||
56 | before reporting an error for a bus transaction. The range of | ||
57 | valid values is [0..15], where 0 indicates infinite retries. | ||
diff --git a/Documentation/devicetree/bindings/usb/ci13xxx-imx.txt b/Documentation/devicetree/bindings/usb/ci13xxx-imx.txt index 1c04a4c9515f..b4b5b7906c88 100644 --- a/Documentation/devicetree/bindings/usb/ci13xxx-imx.txt +++ b/Documentation/devicetree/bindings/usb/ci13xxx-imx.txt | |||
@@ -5,6 +5,12 @@ Required properties: | |||
5 | - reg: Should contain registers location and length | 5 | - reg: Should contain registers location and length |
6 | - interrupts: Should contain controller interrupt | 6 | - interrupts: Should contain controller interrupt |
7 | 7 | ||
8 | Recommended properies: | ||
9 | - phy_type: the type of the phy connected to the core. Should be one | ||
10 | of "utmi", "utmi_wide", "ulpi", "serial" or "hsic". Without this | ||
11 | property the PORTSC register won't be touched | ||
12 | - dr_mode: One of "host", "peripheral" or "otg". Defaults to "otg" | ||
13 | |||
8 | Optional properties: | 14 | Optional properties: |
9 | - fsl,usbphy: phandler of usb phy that connects to the only one port | 15 | - fsl,usbphy: phandler of usb phy that connects to the only one port |
10 | - fsl,usbmisc: phandler of non-core register device, with one argument | 16 | - fsl,usbmisc: phandler of non-core register device, with one argument |
diff --git a/Documentation/devicetree/bindings/usb/nvidia,tegra20-ehci.txt b/Documentation/devicetree/bindings/usb/nvidia,tegra20-ehci.txt index 34c952883276..df0933043a5b 100644 --- a/Documentation/devicetree/bindings/usb/nvidia,tegra20-ehci.txt +++ b/Documentation/devicetree/bindings/usb/nvidia,tegra20-ehci.txt | |||
@@ -6,27 +6,10 @@ Practice : Universal Serial Bus" with the following modifications | |||
6 | and additions : | 6 | and additions : |
7 | 7 | ||
8 | Required properties : | 8 | Required properties : |
9 | - compatible : Should be "nvidia,tegra20-ehci" for USB controllers | 9 | - compatible : Should be "nvidia,tegra20-ehci". |
10 | used in host mode. | 10 | - nvidia,phy : phandle of the PHY that the controller is connected to. |
11 | - phy_type : Should be one of "ulpi" or "utmi". | 11 | - clocks : Contains a single entry which defines the USB controller's clock. |
12 | - nvidia,vbus-gpio : If present, specifies a gpio that needs to be | ||
13 | activated for the bus to be powered. | ||
14 | - nvidia,phy : phandle of the PHY instance, the controller is connected to. | ||
15 | |||
16 | Required properties for phy_type == ulpi: | ||
17 | - nvidia,phy-reset-gpio : The GPIO used to reset the PHY. | ||
18 | 12 | ||
19 | Optional properties: | 13 | Optional properties: |
20 | - dr_mode : dual role mode. Indicates the working mode for | 14 | - nvidia,needs-double-reset : boolean is to be set for some of the Tegra20 |
21 | nvidia,tegra20-ehci compatible controllers. Can be "host", "peripheral", | 15 | USB ports, which need reset twice due to hardware issues. |
22 | or "otg". Default to "host" if not defined for backward compatibility. | ||
23 | host means this is a host controller | ||
24 | peripheral means it is device controller | ||
25 | otg means it can operate as either ("on the go") | ||
26 | - nvidia,has-legacy-mode : boolean indicates whether this controller can | ||
27 | operate in legacy mode (as APX 2500 / 2600). In legacy mode some | ||
28 | registers are accessed through the APB_MISC base address instead of | ||
29 | the USB controller. Since this is a legacy issue it probably does not | ||
30 | warrant a compatible string of its own. | ||
31 | - nvidia,needs-double-reset : boolean is to be set for some of the Tegra2 | ||
32 | USB ports, which need reset twice due to hardware issues. | ||
diff --git a/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt b/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt index 6bdaba2f0aa1..c4c9e9e664aa 100644 --- a/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt +++ b/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt | |||
@@ -4,14 +4,49 @@ The device node for Tegra SOC USB PHY: | |||
4 | 4 | ||
5 | Required properties : | 5 | Required properties : |
6 | - compatible : Should be "nvidia,tegra20-usb-phy". | 6 | - compatible : Should be "nvidia,tegra20-usb-phy". |
7 | - reg : Address and length of the register set for the USB PHY interface. | 7 | - reg : Defines the following set of registers, in the order listed: |
8 | - phy_type : Should be one of "ulpi" or "utmi". | 8 | - The PHY's own register set. |
9 | Always present. | ||
10 | - The register set of the PHY containing the UTMI pad control registers. | ||
11 | Present if-and-only-if phy_type == utmi. | ||
12 | - phy_type : Should be one of "utmi", "ulpi" or "hsic". | ||
13 | - clocks : Defines the clocks listed in the clock-names property. | ||
14 | - clock-names : The following clock names must be present: | ||
15 | - reg: The clock needed to access the PHY's own registers. This is the | ||
16 | associated EHCI controller's clock. Always present. | ||
17 | - pll_u: PLL_U. Always present. | ||
18 | - timer: The timeout clock (clk_m). Present if phy_type == utmi. | ||
19 | - utmi-pads: The clock needed to access the UTMI pad control registers. | ||
20 | Present if phy_type == utmi. | ||
21 | - ulpi-link: The clock Tegra provides to the ULPI PHY (cdev2). | ||
22 | Present if phy_type == ulpi, and ULPI link mode is in use. | ||
9 | 23 | ||
10 | Required properties for phy_type == ulpi: | 24 | Required properties for phy_type == ulpi: |
11 | - nvidia,phy-reset-gpio : The GPIO used to reset the PHY. | 25 | - nvidia,phy-reset-gpio : The GPIO used to reset the PHY. |
12 | 26 | ||
27 | Required PHY timing params for utmi phy: | ||
28 | - nvidia,hssync-start-delay : Number of 480 Mhz clock cycles to wait before | ||
29 | start of sync launches RxActive | ||
30 | - nvidia,elastic-limit : Variable FIFO Depth of elastic input store | ||
31 | - nvidia,idle-wait-delay : Number of 480 Mhz clock cycles of idle to wait | ||
32 | before declare IDLE. | ||
33 | - nvidia,term-range-adj : Range adjusment on terminations | ||
34 | - nvidia,xcvr-setup : HS driver output control | ||
35 | - nvidia,xcvr-lsfslew : LS falling slew rate control. | ||
36 | - nvidia,xcvr-lsrslew : LS rising slew rate control. | ||
37 | |||
13 | Optional properties: | 38 | Optional properties: |
14 | - nvidia,has-legacy-mode : boolean indicates whether this controller can | 39 | - nvidia,has-legacy-mode : boolean indicates whether this controller can |
15 | operate in legacy mode (as APX 2500 / 2600). In legacy mode some | 40 | operate in legacy mode (as APX 2500 / 2600). In legacy mode some |
16 | registers are accessed through the APB_MISC base address instead of | 41 | registers are accessed through the APB_MISC base address instead of |
17 | the USB controller. \ No newline at end of file | 42 | the USB controller. |
43 | - nvidia,is-wired : boolean. Indicates whether we can do certain kind of power | ||
44 | optimizations for the devices that are always connected. e.g. modem. | ||
45 | - dr_mode : dual role mode. Indicates the working mode for the PHY. Can be | ||
46 | "host", "peripheral", or "otg". Defaults to "host" if not defined. | ||
47 | host means this is a host controller | ||
48 | peripheral means it is device controller | ||
49 | otg means it can operate as either ("on the go") | ||
50 | |||
51 | Required properties for dr_mode == otg: | ||
52 | - vbus-supply: regulator for VBUS | ||
diff --git a/Documentation/devicetree/bindings/usb/usb3503.txt b/Documentation/devicetree/bindings/usb/usb3503.txt index 6813a715fc7d..8c5be48b43c8 100644 --- a/Documentation/devicetree/bindings/usb/usb3503.txt +++ b/Documentation/devicetree/bindings/usb/usb3503.txt | |||
@@ -4,6 +4,10 @@ Required properties: | |||
4 | - compatible: Should be "smsc,usb3503". | 4 | - compatible: Should be "smsc,usb3503". |
5 | - reg: Specifies the i2c slave address, it should be 0x08. | 5 | - reg: Specifies the i2c slave address, it should be 0x08. |
6 | - connect-gpios: Should specify GPIO for connect. | 6 | - connect-gpios: Should specify GPIO for connect. |
7 | - disabled-ports: Should specify the ports unused. | ||
8 | '1' or '2' or '3' are availe for this property to describe the port | ||
9 | number. 1~3 property values are possible to be desribed. | ||
10 | Do not describe this property if all ports have to be enabled. | ||
7 | - intn-gpios: Should specify GPIO for interrupt. | 11 | - intn-gpios: Should specify GPIO for interrupt. |
8 | - reset-gpios: Should specify GPIO for reset. | 12 | - reset-gpios: Should specify GPIO for reset. |
9 | - initial-mode: Should specify initial mode. | 13 | - initial-mode: Should specify initial mode. |
@@ -14,6 +18,7 @@ Examples: | |||
14 | compatible = "smsc,usb3503"; | 18 | compatible = "smsc,usb3503"; |
15 | reg = <0x08>; | 19 | reg = <0x08>; |
16 | connect-gpios = <&gpx3 0 1>; | 20 | connect-gpios = <&gpx3 0 1>; |
21 | disabled-ports = <2 3>; | ||
17 | intn-gpios = <&gpx3 4 1>; | 22 | intn-gpios = <&gpx3 4 1>; |
18 | reset-gpios = <&gpx3 5 1>; | 23 | reset-gpios = <&gpx3 5 1>; |
19 | initial-mode = <1>; | 24 | initial-mode = <1>; |
diff --git a/Documentation/usb/gadget_configfs.txt b/Documentation/usb/gadget_configfs.txt new file mode 100644 index 000000000000..8ec2a67c39b7 --- /dev/null +++ b/Documentation/usb/gadget_configfs.txt | |||
@@ -0,0 +1,384 @@ | |||
1 | |||
2 | |||
3 | |||
4 | |||
5 | Linux USB gadget configured through configfs | ||
6 | |||
7 | |||
8 | 25th April 2013 | ||
9 | |||
10 | |||
11 | |||
12 | |||
13 | Overview | ||
14 | ======== | ||
15 | |||
16 | A USB Linux Gadget is a device which has a UDC (USB Device Controller) and can | ||
17 | be connected to a USB Host to extend it with additional functions like a serial | ||
18 | port or a mass storage capability. | ||
19 | |||
20 | A gadget is seen by its host as a set of configurations, each of which contains | ||
21 | a number of interfaces which, from the gadget's perspective, are known as | ||
22 | functions, each function representing e.g. a serial connection or a SCSI disk. | ||
23 | |||
24 | Linux provides a number of functions for gadgets to use. | ||
25 | |||
26 | Creating a gadget means deciding what configurations there will be | ||
27 | and which functions each configuration will provide. | ||
28 | |||
29 | Configfs (please see Documentation/filesystems/configfs/*) lends itslef nicely | ||
30 | for the purpose of telling the kernel about the above mentioned decision. | ||
31 | This document is about how to do it. | ||
32 | |||
33 | It also describes how configfs integration into gadget is designed. | ||
34 | |||
35 | |||
36 | |||
37 | |||
38 | Requirements | ||
39 | ============ | ||
40 | |||
41 | In order for this to work configfs must be available, so CONFIGFS_FS must be | ||
42 | 'y' or 'm' in .config. As of this writing USB_LIBCOMPOSITE selects CONFIGFS_FS. | ||
43 | |||
44 | |||
45 | |||
46 | |||
47 | Usage | ||
48 | ===== | ||
49 | |||
50 | (The original post describing the first function | ||
51 | made available through configfs can be seen here: | ||
52 | http://www.spinics.net/lists/linux-usb/msg76388.html) | ||
53 | |||
54 | $ modprobe libcomposite | ||
55 | $ mount none $CONFIGFS_HOME -t configfs | ||
56 | |||
57 | where CONFIGFS_HOME is the mount point for configfs | ||
58 | |||
59 | 1. Creating the gadgets | ||
60 | ----------------------- | ||
61 | |||
62 | For each gadget to be created its corresponding directory must be created: | ||
63 | |||
64 | $ mkdir $CONFIGFS_HOME/usb_gadget/<gadget name> | ||
65 | |||
66 | e.g.: | ||
67 | |||
68 | $ mkdir $CONFIGFS_HOME/usb_gadget/g1 | ||
69 | |||
70 | ... | ||
71 | ... | ||
72 | ... | ||
73 | |||
74 | $ cd $CONFIGFS_HOME/usb_gadget/g1 | ||
75 | |||
76 | Each gadget needs to have its vendor id <VID> and product id <PID> specified: | ||
77 | |||
78 | $ echo <VID> > idVendor | ||
79 | $ echo <PID> > idProduct | ||
80 | |||
81 | A gadget also needs its serial number, manufacturer and product strings. | ||
82 | In order to have a place to store them, a strings subdirectory must be created | ||
83 | for each language, e.g.: | ||
84 | |||
85 | $ mkdir strings/0x409 | ||
86 | |||
87 | Then the strings can be specified: | ||
88 | |||
89 | $ echo <serial number> > strings/0x409/serialnumber | ||
90 | $ echo <manufacturer> > strings/0x409/manufacturer | ||
91 | $ echo <product> > strings/0x409/product | ||
92 | |||
93 | 2. Creating the configurations | ||
94 | ------------------------------ | ||
95 | |||
96 | Each gadget will consist of a number of configurations, their corresponding | ||
97 | directories must be created: | ||
98 | |||
99 | $ mkdir configs/<name>.<number> | ||
100 | |||
101 | where <name> can be any string which is legal in a filesystem and the | ||
102 | <numebr> is the configuration's number, e.g.: | ||
103 | |||
104 | $ mkdir configs/c.1 | ||
105 | |||
106 | ... | ||
107 | ... | ||
108 | ... | ||
109 | |||
110 | Each configuration also needs its strings, so a subdirectory must be created | ||
111 | for each language, e.g.: | ||
112 | |||
113 | $ mkdir configs/c.1/strings/0x409 | ||
114 | |||
115 | Then the configuration string can be specified: | ||
116 | |||
117 | $ echo <configuration> > configs/c.1/strings/0x409/configuration | ||
118 | |||
119 | Some attributes can also be set for a configuration, e.g.: | ||
120 | |||
121 | $ echo 120 > configs/c.1/MaxPower | ||
122 | |||
123 | 3. Creating the functions | ||
124 | ------------------------- | ||
125 | |||
126 | The gadget will provide some functions, for each function its corresponding | ||
127 | directory must be created: | ||
128 | |||
129 | $ mkdir functions/<name>.<instance name> | ||
130 | |||
131 | where <name> corresponds to one of allowed function names and instance name | ||
132 | is an arbitrary string allowed in a filesystem, e.g.: | ||
133 | |||
134 | $ mkdir functions/ncm.usb0 # usb_f_ncm.ko gets loaded with request_module() | ||
135 | |||
136 | ... | ||
137 | ... | ||
138 | ... | ||
139 | |||
140 | Each function provides its specific set of attributes, with either read-only | ||
141 | or read-write access. Where applicable they need to be written to as | ||
142 | appropriate. | ||
143 | Please refer to Documentation/ABI/*/configfs-usb-gadget* for more information. | ||
144 | |||
145 | 4. Associating the functions with their configurations | ||
146 | ------------------------------------------------------ | ||
147 | |||
148 | At this moment a number of gadgets is created, each of which has a number of | ||
149 | configurations specified and a number of functions available. What remains | ||
150 | is specifying which function is available in which configuration (the same | ||
151 | function can be used in multiple configurations). This is achieved with | ||
152 | creating symbolic links: | ||
153 | |||
154 | $ ln -s functions/<name>.<instance name> configs/<name>.<number> | ||
155 | |||
156 | e.g.: | ||
157 | |||
158 | $ ln -s functions/ncm.usb0 configs/c.1 | ||
159 | |||
160 | ... | ||
161 | ... | ||
162 | ... | ||
163 | |||
164 | 5. Enabling the gadget | ||
165 | ---------------------- | ||
166 | |||
167 | All the above steps serve the purpose of composing the gadget of | ||
168 | configurations and functions. | ||
169 | |||
170 | An example directory structure might look like this: | ||
171 | |||
172 | . | ||
173 | ./strings | ||
174 | ./strings/0x409 | ||
175 | ./strings/0x409/serialnumber | ||
176 | ./strings/0x409/product | ||
177 | ./strings/0x409/manufacturer | ||
178 | ./configs | ||
179 | ./configs/c.1 | ||
180 | ./configs/c.1/ncm.usb0 -> ../../../../usb_gadget/g1/functions/ncm.usb0 | ||
181 | ./configs/c.1/strings | ||
182 | ./configs/c.1/strings/0x409 | ||
183 | ./configs/c.1/strings/0x409/configuration | ||
184 | ./configs/c.1/bmAttributes | ||
185 | ./configs/c.1/MaxPower | ||
186 | ./functions | ||
187 | ./functions/ncm.usb0 | ||
188 | ./functions/ncm.usb0/ifname | ||
189 | ./functions/ncm.usb0/qmult | ||
190 | ./functions/ncm.usb0/host_addr | ||
191 | ./functions/ncm.usb0/dev_addr | ||
192 | ./UDC | ||
193 | ./bcdUSB | ||
194 | ./bcdDevice | ||
195 | ./idProduct | ||
196 | ./idVendor | ||
197 | ./bMaxPacketSize0 | ||
198 | ./bDeviceProtocol | ||
199 | ./bDeviceSubClass | ||
200 | ./bDeviceClass | ||
201 | |||
202 | |||
203 | Such a gadget must be finally enabled so that the USB host can enumerate it. | ||
204 | In order to enable the gadget it must be bound to a UDC (USB Device Controller). | ||
205 | |||
206 | $ echo <udc name> > UDC | ||
207 | |||
208 | where <udc name> is one of those found in /sys/class/udc/* | ||
209 | e.g.: | ||
210 | |||
211 | $ echo s3c-hsotg > UDC | ||
212 | |||
213 | |||
214 | 6. Disabling the gadget | ||
215 | ----------------------- | ||
216 | |||
217 | $ echo "" > UDC | ||
218 | |||
219 | 7. Cleaning up | ||
220 | -------------- | ||
221 | |||
222 | Remove functions from configurations: | ||
223 | |||
224 | $ rm configs/<config name>.<number>/<function> | ||
225 | |||
226 | where <config name>.<number> specify the configuration and <function> is | ||
227 | a symlink to a function being removed from the configuration, e.g.: | ||
228 | |||
229 | $ rm configfs/c.1/ncm.usb0 | ||
230 | |||
231 | ... | ||
232 | ... | ||
233 | ... | ||
234 | |||
235 | Remove strings directories in configurations | ||
236 | |||
237 | $ rmdir configs/<config name>.<number>/strings/<lang> | ||
238 | |||
239 | e.g.: | ||
240 | |||
241 | $ rmdir configs/c.1/strings/0x409 | ||
242 | |||
243 | ... | ||
244 | ... | ||
245 | ... | ||
246 | |||
247 | and remove the configurations | ||
248 | |||
249 | $ rmdir configs/<config name>.<number> | ||
250 | |||
251 | e.g.: | ||
252 | |||
253 | rmdir configs/c.1 | ||
254 | |||
255 | ... | ||
256 | ... | ||
257 | ... | ||
258 | |||
259 | Remove functions (function modules are not unloaded, though) | ||
260 | |||
261 | $ rmdir functions/<name>.<instance name> | ||
262 | |||
263 | e.g.: | ||
264 | |||
265 | $ rmdir functions/ncm.usb0 | ||
266 | |||
267 | ... | ||
268 | ... | ||
269 | ... | ||
270 | |||
271 | Remove strings directories in the gadget | ||
272 | |||
273 | $ rmdir strings/<lang> | ||
274 | |||
275 | e.g.: | ||
276 | |||
277 | $ rmdir strings/0x409 | ||
278 | |||
279 | and finally remove the gadget: | ||
280 | |||
281 | $ cd .. | ||
282 | $ rmdir <gadget name> | ||
283 | |||
284 | e.g.: | ||
285 | |||
286 | $ rmdir g1 | ||
287 | |||
288 | |||
289 | |||
290 | |||
291 | Implementation design | ||
292 | ===================== | ||
293 | |||
294 | Below the idea of how configfs works is presented. | ||
295 | In configfs there are items and groups, both represented as directories. | ||
296 | The difference between an item and a group is that a group can contain | ||
297 | other groups. In the picture below only an item is shown. | ||
298 | Both items and groups can have attributes, which are represented as files. | ||
299 | The user can create and remove directories, but cannot remove files, | ||
300 | which can be read-only or read-write, depending on what they represent. | ||
301 | |||
302 | The filesystem part of configfs operates on config_items/groups and | ||
303 | configfs_attributes which are generic and of the same type for all | ||
304 | configured elements. However, they are embedded in usage-specific | ||
305 | larger structures. In the picture below there is a "cs" which contains | ||
306 | a config_item and an "sa" which contains a configfs_attribute. | ||
307 | |||
308 | The filesystem view would be like this: | ||
309 | |||
310 | ./ | ||
311 | ./cs (directory) | ||
312 | | | ||
313 | +--sa (file) | ||
314 | | | ||
315 | . | ||
316 | . | ||
317 | . | ||
318 | |||
319 | Whenever a user reads/writes the "sa" file, a function is called | ||
320 | which accepts a struct config_item and a struct configfs_attribute. | ||
321 | In the said function the "cs" and "sa" are retrieved using the well | ||
322 | known container_of technique and an appropriate sa's function (show or | ||
323 | store) is called and passed the "cs" and a character buffer. The "show" | ||
324 | is for displaying the file's contents (copy data from the cs to the | ||
325 | buffer), while the "store" is for modifying the file's contents (copy data | ||
326 | from the buffer to the cs), but it is up to the implementer of the | ||
327 | two functions to decide what they actually do. | ||
328 | |||
329 | typedef struct configured_structure cs; | ||
330 | typedef struc specific_attribute sa; | ||
331 | |||
332 | sa | ||
333 | +----------------------------------+ | ||
334 | cs | (*show)(cs *, buffer); | | ||
335 | +-----------------+ | (*store)(cs *, buffer, length); | | ||
336 | | | | | | ||
337 | | +-------------+ | | +------------------+ | | ||
338 | | | struct |-|----|------>|struct | | | ||
339 | | | config_item | | | |configfs_attribute| | | ||
340 | | +-------------+ | | +------------------+ | | ||
341 | | | +----------------------------------+ | ||
342 | | data to be set | . | ||
343 | | | . | ||
344 | +-----------------+ . | ||
345 | |||
346 | The file names are decided by the config item/group designer, while | ||
347 | the directories in general can be named at will. A group can have | ||
348 | a number of its default sub-groups created automatically. | ||
349 | |||
350 | For more information on configfs please see | ||
351 | Documentation/filesystems/configfs/*. | ||
352 | |||
353 | The concepts described above translate to USB gadgets like this: | ||
354 | |||
355 | 1. A gadget has its config group, which has some attributes (idVendor, | ||
356 | idProduct etc) and default sub-groups (configs, functions, strings). | ||
357 | Writing to the attributes causes the information to be stored in | ||
358 | appropriate locations. In the configs, functions and strings sub-groups | ||
359 | a user can create their sub-groups to represent configurations, functions, | ||
360 | and groups of strings in a given language. | ||
361 | |||
362 | 2. The user creates configurations and functions, in the configurations | ||
363 | creates symbolic links to functions. This information is used when the | ||
364 | gadget's UDC attribute is written to, which means binding the gadget | ||
365 | to the UDC. The code in drivers/usb/gadget/configfs.c iterates over | ||
366 | all configurations, and in each configuration it iterates over all | ||
367 | functions and binds them. This way the whole gadget is bound. | ||
368 | |||
369 | 3. The file drivers/usb/gadget/configfs.c contains code for | ||
370 | |||
371 | - gadget's config_group | ||
372 | - gadget's default groups (configs, functions, strings) | ||
373 | - associating functions with configurations (symlinks) | ||
374 | |||
375 | 4. Each USB function naturally has its own view of what it wants | ||
376 | configured, so config_groups for particular functions are defined | ||
377 | in the functions implementation files drivers/usb/gadget/f_*.c. | ||
378 | |||
379 | 5. Funciton's code is written in such a way that it uses | ||
380 | |||
381 | usb_get_function_instance(), which, in turn, calls request_module. | ||
382 | So, provided that modprobe works, modules for particular functions | ||
383 | are loaded automatically. Please note that the converse is not true: | ||
384 | after a gadget is disabled and torn down, the modules remain loaded. | ||
diff --git a/arch/arm/boot/dts/tegra20-colibri-512.dtsi b/arch/arm/boot/dts/tegra20-colibri-512.dtsi index a573b94b7c93..c12af78e479c 100644 --- a/arch/arm/boot/dts/tegra20-colibri-512.dtsi +++ b/arch/arm/boot/dts/tegra20-colibri-512.dtsi | |||
@@ -449,7 +449,11 @@ | |||
449 | 449 | ||
450 | usb@c5004000 { | 450 | usb@c5004000 { |
451 | status = "okay"; | 451 | status = "okay"; |
452 | nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */ | 452 | nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */ |
453 | }; | ||
454 | |||
455 | usb-phy@c5004000 { | ||
456 | nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */ | ||
453 | }; | 457 | }; |
454 | 458 | ||
455 | sdhci@c8000600 { | 459 | sdhci@c8000600 { |
diff --git a/arch/arm/boot/dts/tegra20-harmony.dts b/arch/arm/boot/dts/tegra20-harmony.dts index e7d5de4e00b9..ec5293758753 100644 --- a/arch/arm/boot/dts/tegra20-harmony.dts +++ b/arch/arm/boot/dts/tegra20-harmony.dts | |||
@@ -428,17 +428,26 @@ | |||
428 | status = "okay"; | 428 | status = "okay"; |
429 | }; | 429 | }; |
430 | 430 | ||
431 | usb-phy@c5000000 { | ||
432 | status = "okay"; | ||
433 | }; | ||
434 | |||
431 | usb@c5004000 { | 435 | usb@c5004000 { |
432 | status = "okay"; | 436 | status = "okay"; |
433 | nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */ | 437 | nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */ |
438 | }; | ||
439 | |||
440 | usb-phy@c5004000 { | ||
441 | status = "okay"; | ||
442 | nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */ | ||
434 | }; | 443 | }; |
435 | 444 | ||
436 | usb@c5008000 { | 445 | usb@c5008000 { |
437 | status = "okay"; | 446 | status = "okay"; |
438 | }; | 447 | }; |
439 | 448 | ||
440 | usb-phy@c5004400 { | 449 | usb-phy@c5008000 { |
441 | nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */ | 450 | status = "okay"; |
442 | }; | 451 | }; |
443 | 452 | ||
444 | sdhci@c8000200 { | 453 | sdhci@c8000200 { |
diff --git a/arch/arm/boot/dts/tegra20-iris-512.dts b/arch/arm/boot/dts/tegra20-iris-512.dts index 52f1103907d7..9f64f7086881 100644 --- a/arch/arm/boot/dts/tegra20-iris-512.dts +++ b/arch/arm/boot/dts/tegra20-iris-512.dts | |||
@@ -38,13 +38,20 @@ | |||
38 | 38 | ||
39 | usb@c5000000 { | 39 | usb@c5000000 { |
40 | status = "okay"; | 40 | status = "okay"; |
41 | dr_mode = "otg"; | 41 | }; |
42 | |||
43 | usb-phy@c5000000 { | ||
44 | status = "okay"; | ||
42 | }; | 45 | }; |
43 | 46 | ||
44 | usb@c5008000 { | 47 | usb@c5008000 { |
45 | status = "okay"; | 48 | status = "okay"; |
46 | }; | 49 | }; |
47 | 50 | ||
51 | usb-phy@c5008000 { | ||
52 | status = "okay"; | ||
53 | }; | ||
54 | |||
48 | serial@70006000 { | 55 | serial@70006000 { |
49 | status = "okay"; | 56 | status = "okay"; |
50 | }; | 57 | }; |
diff --git a/arch/arm/boot/dts/tegra20-paz00.dts b/arch/arm/boot/dts/tegra20-paz00.dts index e3e0c9977df4..1c17ffaff1ad 100644 --- a/arch/arm/boot/dts/tegra20-paz00.dts +++ b/arch/arm/boot/dts/tegra20-paz00.dts | |||
@@ -427,17 +427,26 @@ | |||
427 | status = "okay"; | 427 | status = "okay"; |
428 | }; | 428 | }; |
429 | 429 | ||
430 | usb-phy@c5000000 { | ||
431 | status = "okay"; | ||
432 | }; | ||
433 | |||
430 | usb@c5004000 { | 434 | usb@c5004000 { |
431 | status = "okay"; | 435 | status = "okay"; |
432 | nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */ | 436 | nvidia,phy-reset-gpio = <&gpio 168 1>; /* gpio PV0, active low */ |
437 | }; | ||
438 | |||
439 | usb-phy@c5004000 { | ||
440 | status = "okay"; | ||
441 | nvidia,phy-reset-gpio = <&gpio 168 1>; /* gpio PV0, active low */ | ||
433 | }; | 442 | }; |
434 | 443 | ||
435 | usb@c5008000 { | 444 | usb@c5008000 { |
436 | status = "okay"; | 445 | status = "okay"; |
437 | }; | 446 | }; |
438 | 447 | ||
439 | usb-phy@c5004400 { | 448 | usb-phy@c5008000 { |
440 | nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */ | 449 | status = "okay"; |
441 | }; | 450 | }; |
442 | 451 | ||
443 | sdhci@c8000000 { | 452 | sdhci@c8000000 { |
diff --git a/arch/arm/boot/dts/tegra20-seaboard.dts b/arch/arm/boot/dts/tegra20-seaboard.dts index cee4c34010fe..009dafecf88b 100644 --- a/arch/arm/boot/dts/tegra20-seaboard.dts +++ b/arch/arm/boot/dts/tegra20-seaboard.dts | |||
@@ -569,17 +569,28 @@ | |||
569 | dr_mode = "otg"; | 569 | dr_mode = "otg"; |
570 | }; | 570 | }; |
571 | 571 | ||
572 | usb-phy@c5000000 { | ||
573 | status = "okay"; | ||
574 | vbus-supply = <&vbus_reg>; | ||
575 | dr_mode = "otg"; | ||
576 | }; | ||
577 | |||
572 | usb@c5004000 { | 578 | usb@c5004000 { |
573 | status = "okay"; | 579 | status = "okay"; |
574 | nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */ | 580 | nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */ |
581 | }; | ||
582 | |||
583 | usb-phy@c5004000 { | ||
584 | status = "okay"; | ||
585 | nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */ | ||
575 | }; | 586 | }; |
576 | 587 | ||
577 | usb@c5008000 { | 588 | usb@c5008000 { |
578 | status = "okay"; | 589 | status = "okay"; |
579 | }; | 590 | }; |
580 | 591 | ||
581 | usb-phy@c5004400 { | 592 | usb-phy@c5008000 { |
582 | nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */ | 593 | status = "okay"; |
583 | }; | 594 | }; |
584 | 595 | ||
585 | sdhci@c8000000 { | 596 | sdhci@c8000000 { |
@@ -807,6 +818,15 @@ | |||
807 | gpio = <&pmic 1 0>; | 818 | gpio = <&pmic 1 0>; |
808 | enable-active-high; | 819 | enable-active-high; |
809 | }; | 820 | }; |
821 | |||
822 | vbus_reg: regulator@3 { | ||
823 | compatible = "regulator-fixed"; | ||
824 | reg = <3>; | ||
825 | regulator-name = "vdd_vbus_wup1"; | ||
826 | regulator-min-microvolt = <5000000>; | ||
827 | regulator-max-microvolt = <5000000>; | ||
828 | gpio = <&gpio 24 0>; /* PD0 */ | ||
829 | }; | ||
810 | }; | 830 | }; |
811 | 831 | ||
812 | sound { | 832 | sound { |
diff --git a/arch/arm/boot/dts/tegra20-tamonten.dtsi b/arch/arm/boot/dts/tegra20-tamonten.dtsi index 50b3ec16b93a..fc2f7d6e70b2 100644 --- a/arch/arm/boot/dts/tegra20-tamonten.dtsi +++ b/arch/arm/boot/dts/tegra20-tamonten.dtsi | |||
@@ -470,6 +470,10 @@ | |||
470 | status = "okay"; | 470 | status = "okay"; |
471 | }; | 471 | }; |
472 | 472 | ||
473 | usb-phy@c5008000 { | ||
474 | status = "okay"; | ||
475 | }; | ||
476 | |||
473 | sdhci@c8000600 { | 477 | sdhci@c8000600 { |
474 | cd-gpios = <&gpio 58 1>; /* gpio PH2 */ | 478 | cd-gpios = <&gpio 58 1>; /* gpio PH2 */ |
475 | wp-gpios = <&gpio 59 0>; /* gpio PH3 */ | 479 | wp-gpios = <&gpio 59 0>; /* gpio PH3 */ |
diff --git a/arch/arm/boot/dts/tegra20-trimslice.dts b/arch/arm/boot/dts/tegra20-trimslice.dts index 9cc78a15d739..0e65c00ec732 100644 --- a/arch/arm/boot/dts/tegra20-trimslice.dts +++ b/arch/arm/boot/dts/tegra20-trimslice.dts | |||
@@ -314,17 +314,27 @@ | |||
314 | nvidia,vbus-gpio = <&gpio 170 0>; /* gpio PV2 */ | 314 | nvidia,vbus-gpio = <&gpio 170 0>; /* gpio PV2 */ |
315 | }; | 315 | }; |
316 | 316 | ||
317 | usb-phy@c5000000 { | ||
318 | status = "okay"; | ||
319 | vbus-supply = <&vbus_reg>; | ||
320 | }; | ||
321 | |||
317 | usb@c5004000 { | 322 | usb@c5004000 { |
318 | status = "okay"; | 323 | status = "okay"; |
319 | nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */ | 324 | nvidia,phy-reset-gpio = <&gpio 168 1>; /* gpio PV0, active low */ |
325 | }; | ||
326 | |||
327 | usb-phy@c5004000 { | ||
328 | status = "okay"; | ||
329 | nvidia,phy-reset-gpio = <&gpio 168 1>; /* gpio PV0, active low */ | ||
320 | }; | 330 | }; |
321 | 331 | ||
322 | usb@c5008000 { | 332 | usb@c5008000 { |
323 | status = "okay"; | 333 | status = "okay"; |
324 | }; | 334 | }; |
325 | 335 | ||
326 | usb-phy@c5004400 { | 336 | usb-phy@c5008000 { |
327 | nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */ | 337 | status = "okay"; |
328 | }; | 338 | }; |
329 | 339 | ||
330 | sdhci@c8000000 { | 340 | sdhci@c8000000 { |
@@ -390,6 +400,15 @@ | |||
390 | regulator-max-microvolt = <1800000>; | 400 | regulator-max-microvolt = <1800000>; |
391 | regulator-always-on; | 401 | regulator-always-on; |
392 | }; | 402 | }; |
403 | |||
404 | vbus_reg: regulator@2 { | ||
405 | compatible = "regulator-fixed"; | ||
406 | reg = <2>; | ||
407 | regulator-name = "usb1_vbus"; | ||
408 | regulator-min-microvolt = <5000000>; | ||
409 | regulator-max-microvolt = <5000000>; | ||
410 | gpio = <&gpio 170 0>; /* PV2 */ | ||
411 | }; | ||
393 | }; | 412 | }; |
394 | 413 | ||
395 | sound { | 414 | sound { |
diff --git a/arch/arm/boot/dts/tegra20-ventana.dts b/arch/arm/boot/dts/tegra20-ventana.dts index dd38f1f03834..e00f89e645f9 100644 --- a/arch/arm/boot/dts/tegra20-ventana.dts +++ b/arch/arm/boot/dts/tegra20-ventana.dts | |||
@@ -505,17 +505,26 @@ | |||
505 | status = "okay"; | 505 | status = "okay"; |
506 | }; | 506 | }; |
507 | 507 | ||
508 | usb-phy@c5000000 { | ||
509 | status = "okay"; | ||
510 | }; | ||
511 | |||
508 | usb@c5004000 { | 512 | usb@c5004000 { |
509 | status = "okay"; | 513 | status = "okay"; |
510 | nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */ | 514 | nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */ |
515 | }; | ||
516 | |||
517 | usb-phy@c5004000 { | ||
518 | status = "okay"; | ||
519 | nvidia,phy-reset-gpio = <&gpio 169 1>; /* gpio PV1, active low */ | ||
511 | }; | 520 | }; |
512 | 521 | ||
513 | usb@c5008000 { | 522 | usb@c5008000 { |
514 | status = "okay"; | 523 | status = "okay"; |
515 | }; | 524 | }; |
516 | 525 | ||
517 | usb-phy@c5004400 { | 526 | usb-phy@c5008000 { |
518 | nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */ | 527 | status = "okay"; |
519 | }; | 528 | }; |
520 | 529 | ||
521 | sdhci@c8000000 { | 530 | sdhci@c8000000 { |
diff --git a/arch/arm/boot/dts/tegra20-whistler.dts b/arch/arm/boot/dts/tegra20-whistler.dts index d2567f83aaff..3c24c9b92b44 100644 --- a/arch/arm/boot/dts/tegra20-whistler.dts +++ b/arch/arm/boot/dts/tegra20-whistler.dts | |||
@@ -511,11 +511,21 @@ | |||
511 | nvidia,vbus-gpio = <&tca6416 0 0>; /* GPIO_PMU0 */ | 511 | nvidia,vbus-gpio = <&tca6416 0 0>; /* GPIO_PMU0 */ |
512 | }; | 512 | }; |
513 | 513 | ||
514 | usb-phy@c5000000 { | ||
515 | status = "okay"; | ||
516 | vbus-supply = <&vbus1_reg>; | ||
517 | }; | ||
518 | |||
514 | usb@c5008000 { | 519 | usb@c5008000 { |
515 | status = "okay"; | 520 | status = "okay"; |
516 | nvidia,vbus-gpio = <&tca6416 1 0>; /* GPIO_PMU1 */ | 521 | nvidia,vbus-gpio = <&tca6416 1 0>; /* GPIO_PMU1 */ |
517 | }; | 522 | }; |
518 | 523 | ||
524 | usb-phy@c5008000 { | ||
525 | status = "okay"; | ||
526 | vbus-supply = <&vbus3_reg>; | ||
527 | }; | ||
528 | |||
519 | sdhci@c8000400 { | 529 | sdhci@c8000400 { |
520 | status = "okay"; | 530 | status = "okay"; |
521 | cd-gpios = <&gpio 69 1>; /* gpio PI5 */ | 531 | cd-gpios = <&gpio 69 1>; /* gpio PI5 */ |
@@ -568,6 +578,24 @@ | |||
568 | regulator-max-microvolt = <5000000>; | 578 | regulator-max-microvolt = <5000000>; |
569 | regulator-always-on; | 579 | regulator-always-on; |
570 | }; | 580 | }; |
581 | |||
582 | vbus1_reg: regulator@2 { | ||
583 | compatible = "regulator-fixed"; | ||
584 | reg = <2>; | ||
585 | regulator-name = "vbus1"; | ||
586 | regulator-min-microvolt = <5000000>; | ||
587 | regulator-max-microvolt = <5000000>; | ||
588 | gpio = <&tca6416 0 0>; /* GPIO_PMU0 */ | ||
589 | }; | ||
590 | |||
591 | vbus3_reg: regulator@3 { | ||
592 | compatible = "regulator-fixed"; | ||
593 | reg = <3>; | ||
594 | regulator-name = "vbus3"; | ||
595 | regulator-min-microvolt = <5000000>; | ||
596 | regulator-max-microvolt = <5000000>; | ||
597 | gpio = <&tca6416 1 0>; /* GPIO_PMU1 */ | ||
598 | }; | ||
571 | }; | 599 | }; |
572 | 600 | ||
573 | sound { | 601 | sound { |
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi index 56a91106041b..96d6d8a3aa72 100644 --- a/arch/arm/boot/dts/tegra20.dtsi +++ b/arch/arm/boot/dts/tegra20.dtsi | |||
@@ -455,13 +455,24 @@ | |||
455 | status = "disabled"; | 455 | status = "disabled"; |
456 | }; | 456 | }; |
457 | 457 | ||
458 | phy1: usb-phy@c5000400 { | 458 | phy1: usb-phy@c5000000 { |
459 | compatible = "nvidia,tegra20-usb-phy"; | 459 | compatible = "nvidia,tegra20-usb-phy"; |
460 | reg = <0xc5000400 0x3c00>; | 460 | reg = <0xc5000000 0x4000 0xc5000000 0x4000>; |
461 | phy_type = "utmi"; | 461 | phy_type = "utmi"; |
462 | clocks = <&tegra_car 22>, | ||
463 | <&tegra_car 127>, | ||
464 | <&tegra_car 106>, | ||
465 | <&tegra_car 22>; | ||
466 | clock-names = "reg", "pll_u", "timer", "utmi-pads"; | ||
462 | nvidia,has-legacy-mode; | 467 | nvidia,has-legacy-mode; |
463 | clocks = <&tegra_car 22>, <&tegra_car 127>; | 468 | hssync_start_delay = <9>; |
464 | clock-names = "phy", "pll_u"; | 469 | idle_wait_delay = <17>; |
470 | elastic_limit = <16>; | ||
471 | term_range_adj = <6>; | ||
472 | xcvr_setup = <9>; | ||
473 | xcvr_lsfslew = <1>; | ||
474 | xcvr_lsrslew = <1>; | ||
475 | status = "disabled"; | ||
465 | }; | 476 | }; |
466 | 477 | ||
467 | usb@c5004000 { | 478 | usb@c5004000 { |
@@ -474,12 +485,15 @@ | |||
474 | status = "disabled"; | 485 | status = "disabled"; |
475 | }; | 486 | }; |
476 | 487 | ||
477 | phy2: usb-phy@c5004400 { | 488 | phy2: usb-phy@c5004000 { |
478 | compatible = "nvidia,tegra20-usb-phy"; | 489 | compatible = "nvidia,tegra20-usb-phy"; |
479 | reg = <0xc5004400 0x3c00>; | 490 | reg = <0xc5004000 0x4000>; |
480 | phy_type = "ulpi"; | 491 | phy_type = "ulpi"; |
481 | clocks = <&tegra_car 93>, <&tegra_car 127>; | 492 | clocks = <&tegra_car 58>, |
482 | clock-names = "phy", "pll_u"; | 493 | <&tegra_car 127>, |
494 | <&tegra_car 93>; | ||
495 | clock-names = "reg", "pll_u", "ulpi-link"; | ||
496 | status = "disabled"; | ||
483 | }; | 497 | }; |
484 | 498 | ||
485 | usb@c5008000 { | 499 | usb@c5008000 { |
@@ -492,12 +506,23 @@ | |||
492 | status = "disabled"; | 506 | status = "disabled"; |
493 | }; | 507 | }; |
494 | 508 | ||
495 | phy3: usb-phy@c5008400 { | 509 | phy3: usb-phy@c5008000 { |
496 | compatible = "nvidia,tegra20-usb-phy"; | 510 | compatible = "nvidia,tegra20-usb-phy"; |
497 | reg = <0xc5008400 0x3c00>; | 511 | reg = <0xc5008000 0x4000 0xc5000000 0x4000>; |
498 | phy_type = "utmi"; | 512 | phy_type = "utmi"; |
499 | clocks = <&tegra_car 22>, <&tegra_car 127>; | 513 | clocks = <&tegra_car 59>, |
500 | clock-names = "phy", "pll_u"; | 514 | <&tegra_car 127>, |
515 | <&tegra_car 106>, | ||
516 | <&tegra_car 22>; | ||
517 | clock-names = "reg", "pll_u", "timer", "utmi-pads"; | ||
518 | hssync_start_delay = <9>; | ||
519 | idle_wait_delay = <17>; | ||
520 | elastic_limit = <16>; | ||
521 | term_range_adj = <6>; | ||
522 | xcvr_setup = <9>; | ||
523 | xcvr_lsfslew = <2>; | ||
524 | xcvr_lsrslew = <2>; | ||
525 | status = "disabled"; | ||
501 | }; | 526 | }; |
502 | 527 | ||
503 | sdhci@c8000000 { | 528 | sdhci@c8000000 { |
diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c index 8a6e5ea476e1..880f5c0011f2 100644 --- a/drivers/staging/serqt_usb2/serqt_usb2.c +++ b/drivers/staging/serqt_usb2/serqt_usb2.c | |||
@@ -873,7 +873,7 @@ static int qt_open(struct tty_struct *tty, | |||
873 | result = qt_get_device(serial, &port0->DeviceData); | 873 | result = qt_get_device(serial, &port0->DeviceData); |
874 | 874 | ||
875 | /* Port specific setups */ | 875 | /* Port specific setups */ |
876 | result = qt_open_channel(serial, port->number, &ChannelData); | 876 | result = qt_open_channel(serial, port->port_number, &ChannelData); |
877 | if (result < 0) { | 877 | if (result < 0) { |
878 | dev_dbg(&port->dev, "qt_open_channel failed\n"); | 878 | dev_dbg(&port->dev, "qt_open_channel failed\n"); |
879 | return result; | 879 | return result; |
@@ -888,7 +888,7 @@ static int qt_open(struct tty_struct *tty, | |||
888 | (SERIAL_MSR_CTS | SERIAL_MSR_DSR | SERIAL_MSR_RI | SERIAL_MSR_CD); | 888 | (SERIAL_MSR_CTS | SERIAL_MSR_DSR | SERIAL_MSR_RI | SERIAL_MSR_CD); |
889 | 889 | ||
890 | /* Set Baud rate to default and turn off (default)flow control here */ | 890 | /* Set Baud rate to default and turn off (default)flow control here */ |
891 | result = qt_setuart(serial, port->number, DEFAULT_DIVISOR, DEFAULT_LCR); | 891 | result = qt_setuart(serial, port->port_number, DEFAULT_DIVISOR, DEFAULT_LCR); |
892 | if (result < 0) { | 892 | if (result < 0) { |
893 | dev_dbg(&port->dev, "qt_setuart failed\n"); | 893 | dev_dbg(&port->dev, "qt_setuart failed\n"); |
894 | return result; | 894 | return result; |
@@ -906,8 +906,7 @@ static int qt_open(struct tty_struct *tty, | |||
906 | qt_submit_urb_from_open(serial, port); | 906 | qt_submit_urb_from_open(serial, port); |
907 | } | 907 | } |
908 | 908 | ||
909 | dev_dbg(&port->dev, "port number is %d\n", port->number); | 909 | dev_dbg(&port->dev, "minor number is %d\n", port->minor); |
910 | dev_dbg(&port->dev, "serial number is %d\n", port->serial->minor); | ||
911 | dev_dbg(&port->dev, | 910 | dev_dbg(&port->dev, |
912 | "Bulkin endpoint is %d\n", port->bulk_in_endpointAddress); | 911 | "Bulkin endpoint is %d\n", port->bulk_in_endpointAddress); |
913 | dev_dbg(&port->dev, | 912 | dev_dbg(&port->dev, |
@@ -1003,7 +1002,7 @@ static void qt_close(struct usb_serial_port *port) | |||
1003 | status = 0; | 1002 | status = 0; |
1004 | 1003 | ||
1005 | tty = tty_port_tty_get(&port->port); | 1004 | tty = tty_port_tty_get(&port->port); |
1006 | index = tty->index - serial->minor; | 1005 | index = port->port_number; |
1007 | 1006 | ||
1008 | qt_port = qt_get_port_private(port); | 1007 | qt_port = qt_get_port_private(port); |
1009 | port0 = qt_get_port_private(serial->port[0]); | 1008 | port0 = qt_get_port_private(serial->port[0]); |
@@ -1022,14 +1021,11 @@ static void qt_close(struct usb_serial_port *port) | |||
1022 | /* Close uart channel */ | 1021 | /* Close uart channel */ |
1023 | status = qt_close_channel(serial, index); | 1022 | status = qt_close_channel(serial, index); |
1024 | if (status < 0) | 1023 | if (status < 0) |
1025 | dev_dbg(&port->dev, | 1024 | dev_dbg(&port->dev, "%s - qt_close_channel failed.\n", __func__); |
1026 | "%s - port %d qt_close_channel failed.\n", | ||
1027 | __func__, port->number); | ||
1028 | 1025 | ||
1029 | port0->open_ports--; | 1026 | port0->open_ports--; |
1030 | 1027 | ||
1031 | dev_dbg(&port->dev, "qt_num_open_ports in close%d:in port%d\n", | 1028 | dev_dbg(&port->dev, "qt_num_open_ports in close%d\n", port0->open_ports); |
1032 | port0->open_ports, port->number); | ||
1033 | 1029 | ||
1034 | if (port0->open_ports == 0) { | 1030 | if (port0->open_ports == 0) { |
1035 | if (serial->port[0]->interrupt_in_urb) { | 1031 | if (serial->port[0]->interrupt_in_urb) { |
@@ -1133,12 +1129,11 @@ static int qt_ioctl(struct tty_struct *tty, | |||
1133 | { | 1129 | { |
1134 | struct usb_serial_port *port = tty->driver_data; | 1130 | struct usb_serial_port *port = tty->driver_data; |
1135 | struct quatech_port *qt_port = qt_get_port_private(port); | 1131 | struct quatech_port *qt_port = qt_get_port_private(port); |
1136 | struct usb_serial *serial = get_usb_serial(port, __func__); | ||
1137 | unsigned int index; | 1132 | unsigned int index; |
1138 | 1133 | ||
1139 | dev_dbg(&port->dev, "%s cmd 0x%04x\n", __func__, cmd); | 1134 | dev_dbg(&port->dev, "%s cmd 0x%04x\n", __func__, cmd); |
1140 | 1135 | ||
1141 | index = tty->index - serial->minor; | 1136 | index = port->port_number; |
1142 | 1137 | ||
1143 | if (cmd == TIOCMIWAIT) { | 1138 | if (cmd == TIOCMIWAIT) { |
1144 | while (qt_port != NULL) { | 1139 | while (qt_port != NULL) { |
@@ -1169,8 +1164,7 @@ static int qt_ioctl(struct tty_struct *tty, | |||
1169 | return 0; | 1164 | return 0; |
1170 | } | 1165 | } |
1171 | 1166 | ||
1172 | dev_dbg(&port->dev, "%s -No ioctl for that one. port = %d\n", | 1167 | dev_dbg(&port->dev, "%s -No ioctl for that one.\n", __func__); |
1173 | __func__, port->number); | ||
1174 | return -ENOIOCTLCMD; | 1168 | return -ENOIOCTLCMD; |
1175 | } | 1169 | } |
1176 | 1170 | ||
@@ -1185,7 +1179,7 @@ static void qt_set_termios(struct tty_struct *tty, | |||
1185 | int baud, divisor, remainder; | 1179 | int baud, divisor, remainder; |
1186 | int status; | 1180 | int status; |
1187 | 1181 | ||
1188 | index = tty->index - port->serial->minor; | 1182 | index = port->port_number; |
1189 | 1183 | ||
1190 | switch (cflag & CSIZE) { | 1184 | switch (cflag & CSIZE) { |
1191 | case CS5: | 1185 | case CS5: |
@@ -1245,8 +1239,7 @@ static void qt_set_termios(struct tty_struct *tty, | |||
1245 | 1239 | ||
1246 | /* Now determine flow control */ | 1240 | /* Now determine flow control */ |
1247 | if (cflag & CRTSCTS) { | 1241 | if (cflag & CRTSCTS) { |
1248 | dev_dbg(&port->dev, "%s - Enabling HW flow control port %d\n", | 1242 | dev_dbg(&port->dev, "%s - Enabling HW flow control\n", __func__); |
1249 | __func__, port->number); | ||
1250 | 1243 | ||
1251 | /* Enable RTS/CTS flow control */ | 1244 | /* Enable RTS/CTS flow control */ |
1252 | status = BoxSetHW_FlowCtrl(port->serial, index, 1); | 1245 | status = BoxSetHW_FlowCtrl(port->serial, index, 1); |
@@ -1258,8 +1251,7 @@ static void qt_set_termios(struct tty_struct *tty, | |||
1258 | } else { | 1251 | } else { |
1259 | /* Disable RTS/CTS flow control */ | 1252 | /* Disable RTS/CTS flow control */ |
1260 | dev_dbg(&port->dev, | 1253 | dev_dbg(&port->dev, |
1261 | "%s - disabling HW flow control port %d\n", | 1254 | "%s - disabling HW flow control\n", __func__); |
1262 | __func__, port->number); | ||
1263 | 1255 | ||
1264 | status = BoxSetHW_FlowCtrl(port->serial, index, 0); | 1256 | status = BoxSetHW_FlowCtrl(port->serial, index, 0); |
1265 | if (status < 0) { | 1257 | if (status < 0) { |
@@ -1303,7 +1295,7 @@ static void qt_break(struct tty_struct *tty, int break_state) | |||
1303 | u16 index, onoff; | 1295 | u16 index, onoff; |
1304 | unsigned int result; | 1296 | unsigned int result; |
1305 | 1297 | ||
1306 | index = tty->index - serial->minor; | 1298 | index = port->port_number; |
1307 | 1299 | ||
1308 | qt_port = qt_get_port_private(port); | 1300 | qt_port = qt_get_port_private(port); |
1309 | 1301 | ||
@@ -1332,7 +1324,7 @@ static inline int qt_real_tiocmget(struct tty_struct *tty, | |||
1332 | int status; | 1324 | int status; |
1333 | unsigned int index; | 1325 | unsigned int index; |
1334 | 1326 | ||
1335 | index = tty->index - serial->minor; | 1327 | index = port->port_number; |
1336 | status = | 1328 | status = |
1337 | BoxGetRegister(port->serial, index, MODEM_CONTROL_REGISTER, &mcr); | 1329 | BoxGetRegister(port->serial, index, MODEM_CONTROL_REGISTER, &mcr); |
1338 | if (status >= 0) { | 1330 | if (status >= 0) { |
@@ -1371,7 +1363,7 @@ static inline int qt_real_tiocmset(struct tty_struct *tty, | |||
1371 | int status; | 1363 | int status; |
1372 | unsigned int index; | 1364 | unsigned int index; |
1373 | 1365 | ||
1374 | index = tty->index - serial->minor; | 1366 | index = port->port_number; |
1375 | status = | 1367 | status = |
1376 | BoxGetRegister(port->serial, index, MODEM_CONTROL_REGISTER, &mcr); | 1368 | BoxGetRegister(port->serial, index, MODEM_CONTROL_REGISTER, &mcr); |
1377 | if (status < 0) | 1369 | if (status < 0) |
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 92e1dc94ecc8..73f62caa8609 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig | |||
@@ -2,59 +2,15 @@ | |||
2 | # USB device configuration | 2 | # USB device configuration |
3 | # | 3 | # |
4 | 4 | ||
5 | # many non-PCI SOC chips embed OHCI | 5 | # These are unused now, remove them once they are no longer selected |
6 | config USB_ARCH_HAS_OHCI | 6 | config USB_ARCH_HAS_OHCI |
7 | boolean | 7 | bool |
8 | # ARM: | 8 | |
9 | default y if SA1111 | ||
10 | default y if ARCH_OMAP | ||
11 | default y if ARCH_S3C24XX | ||
12 | default y if PXA27x | ||
13 | default y if PXA3xx | ||
14 | default y if ARCH_EP93XX | ||
15 | default y if ARCH_AT91 | ||
16 | default y if MFD_TC6393XB | ||
17 | default y if ARCH_W90X900 | ||
18 | default y if ARCH_DAVINCI_DA8XX | ||
19 | default y if ARCH_CNS3XXX | ||
20 | default y if PLAT_SPEAR | ||
21 | default y if ARCH_EXYNOS | ||
22 | # PPC: | ||
23 | default y if STB03xxx | ||
24 | default y if PPC_MPC52xx | ||
25 | # MIPS: | ||
26 | default y if MIPS_ALCHEMY | ||
27 | default y if MACH_JZ4740 | ||
28 | # more: | ||
29 | default PCI | ||
30 | |||
31 | # some non-PCI hcds implement EHCI | ||
32 | config USB_ARCH_HAS_EHCI | 9 | config USB_ARCH_HAS_EHCI |
33 | boolean | 10 | bool |
34 | default y if FSL_SOC | 11 | |
35 | default y if PPC_MPC512x | ||
36 | default y if ARCH_IXP4XX | ||
37 | default y if ARCH_W90X900 | ||
38 | default y if ARCH_AT91 | ||
39 | default y if ARCH_MXC | ||
40 | default y if ARCH_MXS | ||
41 | default y if ARCH_OMAP3 | ||
42 | default y if ARCH_CNS3XXX | ||
43 | default y if ARCH_VT8500 | ||
44 | default y if PLAT_SPEAR | ||
45 | default y if PLAT_S5P | ||
46 | default y if ARCH_MSM | ||
47 | default y if MICROBLAZE | ||
48 | default y if SPARC_LEON | ||
49 | default y if ARCH_MMP | ||
50 | default y if MACH_LOONGSON1 | ||
51 | default y if PLAT_ORION | ||
52 | default PCI | ||
53 | |||
54 | # some non-PCI HCDs implement xHCI | ||
55 | config USB_ARCH_HAS_XHCI | 12 | config USB_ARCH_HAS_XHCI |
56 | boolean | 13 | bool |
57 | default PCI | ||
58 | 14 | ||
59 | menuconfig USB_SUPPORT | 15 | menuconfig USB_SUPPORT |
60 | bool "USB support" | 16 | bool "USB support" |
@@ -71,19 +27,8 @@ config USB_COMMON | |||
71 | default y | 27 | default y |
72 | depends on USB || USB_GADGET | 28 | depends on USB || USB_GADGET |
73 | 29 | ||
74 | # Host-side USB depends on having a host controller | ||
75 | # NOTE: dummy_hcd is always an option, but it's ignored here ... | ||
76 | # NOTE: SL-811 option should be board-specific ... | ||
77 | config USB_ARCH_HAS_HCD | 30 | config USB_ARCH_HAS_HCD |
78 | boolean | 31 | def_bool y |
79 | default y if USB_ARCH_HAS_OHCI | ||
80 | default y if USB_ARCH_HAS_EHCI | ||
81 | default y if USB_ARCH_HAS_XHCI | ||
82 | default y if PCMCIA && !M32R # sl811_cs | ||
83 | default y if ARM # SL-811 | ||
84 | default y if BLACKFIN # SL-811 | ||
85 | default y if SUPERH # r8a66597-hcd | ||
86 | default PCI | ||
87 | 32 | ||
88 | # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface. | 33 | # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface. |
89 | config USB | 34 | config USB |
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index c41feba8d5c0..238c5d47cadb 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile | |||
@@ -25,6 +25,7 @@ obj-$(CONFIG_USB_HWA_HCD) += host/ | |||
25 | obj-$(CONFIG_USB_ISP1760_HCD) += host/ | 25 | obj-$(CONFIG_USB_ISP1760_HCD) += host/ |
26 | obj-$(CONFIG_USB_IMX21_HCD) += host/ | 26 | obj-$(CONFIG_USB_IMX21_HCD) += host/ |
27 | obj-$(CONFIG_USB_FSL_MPH_DR_OF) += host/ | 27 | obj-$(CONFIG_USB_FSL_MPH_DR_OF) += host/ |
28 | obj-$(CONFIG_USB_FUSBH200_HCD) += host/ | ||
28 | 29 | ||
29 | obj-$(CONFIG_USB_C67X00_HCD) += c67x00/ | 30 | obj-$(CONFIG_USB_C67X00_HCD) += c67x00/ |
30 | 31 | ||
diff --git a/drivers/usb/chipidea/Kconfig b/drivers/usb/chipidea/Kconfig index b2df442eb3e5..eb2aa2e5a842 100644 --- a/drivers/usb/chipidea/Kconfig +++ b/drivers/usb/chipidea/Kconfig | |||
@@ -12,15 +12,15 @@ if USB_CHIPIDEA | |||
12 | 12 | ||
13 | config USB_CHIPIDEA_UDC | 13 | config USB_CHIPIDEA_UDC |
14 | bool "ChipIdea device controller" | 14 | bool "ChipIdea device controller" |
15 | depends on USB_GADGET=y || USB_GADGET=USB_CHIPIDEA | 15 | depends on USB_GADGET=y || USB_CHIPIDEA=m |
16 | help | 16 | help |
17 | Say Y here to enable device controller functionality of the | 17 | Say Y here to enable device controller functionality of the |
18 | ChipIdea driver. | 18 | ChipIdea driver. |
19 | 19 | ||
20 | config USB_CHIPIDEA_HOST | 20 | config USB_CHIPIDEA_HOST |
21 | bool "ChipIdea host controller" | 21 | bool "ChipIdea host controller" |
22 | depends on USB=y || USB=USB_CHIPIDEA | 22 | depends on USB=y |
23 | depends on USB_EHCI_HCD=y | 23 | depends on USB_EHCI_HCD=y || USB_CHIPIDEA=m |
24 | select USB_EHCI_ROOT_HUB_TT | 24 | select USB_EHCI_ROOT_HUB_TT |
25 | help | 25 | help |
26 | Say Y here to enable host controller functionality of the | 26 | Say Y here to enable host controller functionality of the |
diff --git a/drivers/usb/chipidea/Makefile b/drivers/usb/chipidea/Makefile index 4ab83e98219b..3bbbcba03815 100644 --- a/drivers/usb/chipidea/Makefile +++ b/drivers/usb/chipidea/Makefile | |||
@@ -9,13 +9,13 @@ ci_hdrc-$(CONFIG_USB_CHIPIDEA_DEBUG) += debug.o | |||
9 | 9 | ||
10 | # Glue/Bridge layers go here | 10 | # Glue/Bridge layers go here |
11 | 11 | ||
12 | obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_msm.o | 12 | obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc_msm.o |
13 | 13 | ||
14 | # PCI doesn't provide stubs, need to check | 14 | # PCI doesn't provide stubs, need to check |
15 | ifneq ($(CONFIG_PCI),) | 15 | ifneq ($(CONFIG_PCI),) |
16 | obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_pci.o | 16 | obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc_pci.o |
17 | endif | 17 | endif |
18 | 18 | ||
19 | ifneq ($(CONFIG_OF_DEVICE),) | 19 | ifneq ($(CONFIG_OF_DEVICE),) |
20 | obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_imx.o usbmisc_imx.o | 20 | obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc_imx.o usbmisc_imx.o |
21 | endif | 21 | endif |
diff --git a/drivers/usb/chipidea/bits.h b/drivers/usb/chipidea/bits.h index 050de8562a04..aefa0261220c 100644 --- a/drivers/usb/chipidea/bits.h +++ b/drivers/usb/chipidea/bits.h | |||
@@ -48,10 +48,24 @@ | |||
48 | #define PORTSC_SUSP BIT(7) | 48 | #define PORTSC_SUSP BIT(7) |
49 | #define PORTSC_HSP BIT(9) | 49 | #define PORTSC_HSP BIT(9) |
50 | #define PORTSC_PTC (0x0FUL << 16) | 50 | #define PORTSC_PTC (0x0FUL << 16) |
51 | /* PTS and PTW for non lpm version only */ | ||
52 | #define PORTSC_PTS(d) \ | ||
53 | ((((d) & 0x3) << 30) | (((d) & 0x4) ? BIT(25) : 0)) | ||
54 | #define PORTSC_PTW BIT(28) | ||
55 | #define PORTSC_STS BIT(29) | ||
51 | 56 | ||
52 | /* DEVLC */ | 57 | /* DEVLC */ |
53 | #define DEVLC_PSPD (0x03UL << 25) | 58 | #define DEVLC_PSPD (0x03UL << 25) |
54 | #define DEVLC_PSPD_HS (0x02UL << 25) | 59 | #define DEVLC_PSPD_HS (0x02UL << 25) |
60 | #define DEVLC_PTW BIT(27) | ||
61 | #define DEVLC_STS BIT(28) | ||
62 | #define DEVLC_PTS(d) (((d) & 0x7) << 29) | ||
63 | |||
64 | /* Encoding for DEVLC_PTS and PORTSC_PTS */ | ||
65 | #define PTS_UTMI 0 | ||
66 | #define PTS_ULPI 2 | ||
67 | #define PTS_SERIAL 3 | ||
68 | #define PTS_HSIC 4 | ||
55 | 69 | ||
56 | /* OTGSC */ | 70 | /* OTGSC */ |
57 | #define OTGSC_IDPU BIT(5) | 71 | #define OTGSC_IDPU BIT(5) |
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h index b0a6bce064ca..33cb29f36e06 100644 --- a/drivers/usb/chipidea/ci.h +++ b/drivers/usb/chipidea/ci.h | |||
@@ -22,14 +22,14 @@ | |||
22 | * DEFINE | 22 | * DEFINE |
23 | *****************************************************************************/ | 23 | *****************************************************************************/ |
24 | #define TD_PAGE_COUNT 5 | 24 | #define TD_PAGE_COUNT 5 |
25 | #define CI13XXX_PAGE_SIZE 4096ul /* page size for TD's */ | 25 | #define CI_HDRC_PAGE_SIZE 4096ul /* page size for TD's */ |
26 | #define ENDPT_MAX 32 | 26 | #define ENDPT_MAX 32 |
27 | 27 | ||
28 | /****************************************************************************** | 28 | /****************************************************************************** |
29 | * STRUCTURES | 29 | * STRUCTURES |
30 | *****************************************************************************/ | 30 | *****************************************************************************/ |
31 | /** | 31 | /** |
32 | * struct ci13xxx_ep - endpoint representation | 32 | * struct ci_hw_ep - endpoint representation |
33 | * @ep: endpoint structure for gadget drivers | 33 | * @ep: endpoint structure for gadget drivers |
34 | * @dir: endpoint direction (TX/RX) | 34 | * @dir: endpoint direction (TX/RX) |
35 | * @num: endpoint number | 35 | * @num: endpoint number |
@@ -41,7 +41,7 @@ | |||
41 | * @lock: pointer to controller's spinlock | 41 | * @lock: pointer to controller's spinlock |
42 | * @td_pool: pointer to controller's TD pool | 42 | * @td_pool: pointer to controller's TD pool |
43 | */ | 43 | */ |
44 | struct ci13xxx_ep { | 44 | struct ci_hw_ep { |
45 | struct usb_ep ep; | 45 | struct usb_ep ep; |
46 | u8 dir; | 46 | u8 dir; |
47 | u8 num; | 47 | u8 num; |
@@ -49,15 +49,16 @@ struct ci13xxx_ep { | |||
49 | char name[16]; | 49 | char name[16]; |
50 | struct { | 50 | struct { |
51 | struct list_head queue; | 51 | struct list_head queue; |
52 | struct ci13xxx_qh *ptr; | 52 | struct ci_hw_qh *ptr; |
53 | dma_addr_t dma; | 53 | dma_addr_t dma; |
54 | } qh; | 54 | } qh; |
55 | int wedge; | 55 | int wedge; |
56 | 56 | ||
57 | /* global resources */ | 57 | /* global resources */ |
58 | struct ci13xxx *ci; | 58 | struct ci_hdrc *ci; |
59 | spinlock_t *lock; | 59 | spinlock_t *lock; |
60 | struct dma_pool *td_pool; | 60 | struct dma_pool *td_pool; |
61 | struct td_node *pending_td; | ||
61 | }; | 62 | }; |
62 | 63 | ||
63 | enum ci_role { | 64 | enum ci_role { |
@@ -74,9 +75,9 @@ enum ci_role { | |||
74 | * name: role name string (host/gadget) | 75 | * name: role name string (host/gadget) |
75 | */ | 76 | */ |
76 | struct ci_role_driver { | 77 | struct ci_role_driver { |
77 | int (*start)(struct ci13xxx *); | 78 | int (*start)(struct ci_hdrc *); |
78 | void (*stop)(struct ci13xxx *); | 79 | void (*stop)(struct ci_hdrc *); |
79 | irqreturn_t (*irq)(struct ci13xxx *); | 80 | irqreturn_t (*irq)(struct ci_hdrc *); |
80 | const char *name; | 81 | const char *name; |
81 | }; | 82 | }; |
82 | 83 | ||
@@ -101,7 +102,7 @@ struct hw_bank { | |||
101 | }; | 102 | }; |
102 | 103 | ||
103 | /** | 104 | /** |
104 | * struct ci13xxx - chipidea device representation | 105 | * struct ci_hdrc - chipidea device representation |
105 | * @dev: pointer to parent device | 106 | * @dev: pointer to parent device |
106 | * @lock: access synchronization | 107 | * @lock: access synchronization |
107 | * @hw_bank: hardware register mapping | 108 | * @hw_bank: hardware register mapping |
@@ -116,7 +117,7 @@ struct hw_bank { | |||
116 | * @gadget: device side representation for peripheral controller | 117 | * @gadget: device side representation for peripheral controller |
117 | * @driver: gadget driver | 118 | * @driver: gadget driver |
118 | * @hw_ep_max: total number of endpoints supported by hardware | 119 | * @hw_ep_max: total number of endpoints supported by hardware |
119 | * @ci13xxx_ep: array of endpoints | 120 | * @ci_hw_ep: array of endpoints |
120 | * @ep0_dir: ep0 direction | 121 | * @ep0_dir: ep0 direction |
121 | * @ep0out: pointer to ep0 OUT endpoint | 122 | * @ep0out: pointer to ep0 OUT endpoint |
122 | * @ep0in: pointer to ep0 IN endpoint | 123 | * @ep0in: pointer to ep0 IN endpoint |
@@ -132,7 +133,7 @@ struct hw_bank { | |||
132 | * @hcd: pointer to usb_hcd for ehci host driver | 133 | * @hcd: pointer to usb_hcd for ehci host driver |
133 | * @debugfs: root dentry for this controller in debugfs | 134 | * @debugfs: root dentry for this controller in debugfs |
134 | */ | 135 | */ |
135 | struct ci13xxx { | 136 | struct ci_hdrc { |
136 | struct device *dev; | 137 | struct device *dev; |
137 | spinlock_t lock; | 138 | spinlock_t lock; |
138 | struct hw_bank hw_bank; | 139 | struct hw_bank hw_bank; |
@@ -149,9 +150,9 @@ struct ci13xxx { | |||
149 | struct usb_gadget gadget; | 150 | struct usb_gadget gadget; |
150 | struct usb_gadget_driver *driver; | 151 | struct usb_gadget_driver *driver; |
151 | unsigned hw_ep_max; | 152 | unsigned hw_ep_max; |
152 | struct ci13xxx_ep ci13xxx_ep[ENDPT_MAX]; | 153 | struct ci_hw_ep ci_hw_ep[ENDPT_MAX]; |
153 | u32 ep0_dir; | 154 | u32 ep0_dir; |
154 | struct ci13xxx_ep *ep0out, *ep0in; | 155 | struct ci_hw_ep *ep0out, *ep0in; |
155 | 156 | ||
156 | struct usb_request *status; | 157 | struct usb_request *status; |
157 | bool setaddr; | 158 | bool setaddr; |
@@ -160,7 +161,7 @@ struct ci13xxx { | |||
160 | u8 suspended; | 161 | u8 suspended; |
161 | u8 test_mode; | 162 | u8 test_mode; |
162 | 163 | ||
163 | struct ci13xxx_platform_data *platdata; | 164 | struct ci_hdrc_platform_data *platdata; |
164 | int vbus_active; | 165 | int vbus_active; |
165 | /* FIXME: some day, we'll not use global phy */ | 166 | /* FIXME: some day, we'll not use global phy */ |
166 | bool global_phy; | 167 | bool global_phy; |
@@ -169,13 +170,13 @@ struct ci13xxx { | |||
169 | struct dentry *debugfs; | 170 | struct dentry *debugfs; |
170 | }; | 171 | }; |
171 | 172 | ||
172 | static inline struct ci_role_driver *ci_role(struct ci13xxx *ci) | 173 | static inline struct ci_role_driver *ci_role(struct ci_hdrc *ci) |
173 | { | 174 | { |
174 | BUG_ON(ci->role >= CI_ROLE_END || !ci->roles[ci->role]); | 175 | BUG_ON(ci->role >= CI_ROLE_END || !ci->roles[ci->role]); |
175 | return ci->roles[ci->role]; | 176 | return ci->roles[ci->role]; |
176 | } | 177 | } |
177 | 178 | ||
178 | static inline int ci_role_start(struct ci13xxx *ci, enum ci_role role) | 179 | static inline int ci_role_start(struct ci_hdrc *ci, enum ci_role role) |
179 | { | 180 | { |
180 | int ret; | 181 | int ret; |
181 | 182 | ||
@@ -191,7 +192,7 @@ static inline int ci_role_start(struct ci13xxx *ci, enum ci_role role) | |||
191 | return ret; | 192 | return ret; |
192 | } | 193 | } |
193 | 194 | ||
194 | static inline void ci_role_stop(struct ci13xxx *ci) | 195 | static inline void ci_role_stop(struct ci_hdrc *ci) |
195 | { | 196 | { |
196 | enum ci_role role = ci->role; | 197 | enum ci_role role = ci->role; |
197 | 198 | ||
@@ -210,7 +211,7 @@ static inline void ci_role_stop(struct ci13xxx *ci) | |||
210 | #define REG_BITS (32) | 211 | #define REG_BITS (32) |
211 | 212 | ||
212 | /* register indices */ | 213 | /* register indices */ |
213 | enum ci13xxx_regs { | 214 | enum ci_hw_regs { |
214 | CAP_CAPLENGTH, | 215 | CAP_CAPLENGTH, |
215 | CAP_HCCPARAMS, | 216 | CAP_HCCPARAMS, |
216 | CAP_DCCPARAMS, | 217 | CAP_DCCPARAMS, |
@@ -242,7 +243,7 @@ enum ci13xxx_regs { | |||
242 | * | 243 | * |
243 | * This function returns register contents | 244 | * This function returns register contents |
244 | */ | 245 | */ |
245 | static inline u32 hw_read(struct ci13xxx *ci, enum ci13xxx_regs reg, u32 mask) | 246 | static inline u32 hw_read(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask) |
246 | { | 247 | { |
247 | return ioread32(ci->hw_bank.regmap[reg]) & mask; | 248 | return ioread32(ci->hw_bank.regmap[reg]) & mask; |
248 | } | 249 | } |
@@ -253,7 +254,7 @@ static inline u32 hw_read(struct ci13xxx *ci, enum ci13xxx_regs reg, u32 mask) | |||
253 | * @mask: bitfield mask | 254 | * @mask: bitfield mask |
254 | * @data: new value | 255 | * @data: new value |
255 | */ | 256 | */ |
256 | static inline void hw_write(struct ci13xxx *ci, enum ci13xxx_regs reg, | 257 | static inline void hw_write(struct ci_hdrc *ci, enum ci_hw_regs reg, |
257 | u32 mask, u32 data) | 258 | u32 mask, u32 data) |
258 | { | 259 | { |
259 | if (~mask) | 260 | if (~mask) |
@@ -270,7 +271,7 @@ static inline void hw_write(struct ci13xxx *ci, enum ci13xxx_regs reg, | |||
270 | * | 271 | * |
271 | * This function returns register contents | 272 | * This function returns register contents |
272 | */ | 273 | */ |
273 | static inline u32 hw_test_and_clear(struct ci13xxx *ci, enum ci13xxx_regs reg, | 274 | static inline u32 hw_test_and_clear(struct ci_hdrc *ci, enum ci_hw_regs reg, |
274 | u32 mask) | 275 | u32 mask) |
275 | { | 276 | { |
276 | u32 val = ioread32(ci->hw_bank.regmap[reg]) & mask; | 277 | u32 val = ioread32(ci->hw_bank.regmap[reg]) & mask; |
@@ -287,7 +288,7 @@ static inline u32 hw_test_and_clear(struct ci13xxx *ci, enum ci13xxx_regs reg, | |||
287 | * | 288 | * |
288 | * This function returns register contents | 289 | * This function returns register contents |
289 | */ | 290 | */ |
290 | static inline u32 hw_test_and_write(struct ci13xxx *ci, enum ci13xxx_regs reg, | 291 | static inline u32 hw_test_and_write(struct ci_hdrc *ci, enum ci_hw_regs reg, |
291 | u32 mask, u32 data) | 292 | u32 mask, u32 data) |
292 | { | 293 | { |
293 | u32 val = hw_read(ci, reg, ~0); | 294 | u32 val = hw_read(ci, reg, ~0); |
@@ -296,10 +297,10 @@ static inline u32 hw_test_and_write(struct ci13xxx *ci, enum ci13xxx_regs reg, | |||
296 | return (val & mask) >> __ffs(mask); | 297 | return (val & mask) >> __ffs(mask); |
297 | } | 298 | } |
298 | 299 | ||
299 | int hw_device_reset(struct ci13xxx *ci, u32 mode); | 300 | int hw_device_reset(struct ci_hdrc *ci, u32 mode); |
300 | 301 | ||
301 | int hw_port_test_set(struct ci13xxx *ci, u8 mode); | 302 | int hw_port_test_set(struct ci_hdrc *ci, u8 mode); |
302 | 303 | ||
303 | u8 hw_port_test_get(struct ci13xxx *ci); | 304 | u8 hw_port_test_get(struct ci_hdrc *ci); |
304 | 305 | ||
305 | #endif /* __DRIVERS_USB_CHIPIDEA_CI_H */ | 306 | #endif /* __DRIVERS_USB_CHIPIDEA_CI_H */ |
diff --git a/drivers/usb/chipidea/ci13xxx_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c index 73f9d5f15adb..14362c00db3f 100644 --- a/drivers/usb/chipidea/ci13xxx_imx.c +++ b/drivers/usb/chipidea/ci_hdrc_imx.c | |||
@@ -20,16 +20,14 @@ | |||
20 | #include <linux/usb/chipidea.h> | 20 | #include <linux/usb/chipidea.h> |
21 | #include <linux/clk.h> | 21 | #include <linux/clk.h> |
22 | #include <linux/regulator/consumer.h> | 22 | #include <linux/regulator/consumer.h> |
23 | #include <linux/pinctrl/consumer.h> | ||
24 | 23 | ||
25 | #include "ci.h" | 24 | #include "ci.h" |
26 | #include "ci13xxx_imx.h" | 25 | #include "ci_hdrc_imx.h" |
27 | 26 | ||
28 | #define pdev_to_phy(pdev) \ | 27 | #define pdev_to_phy(pdev) \ |
29 | ((struct usb_phy *)platform_get_drvdata(pdev)) | 28 | ((struct usb_phy *)platform_get_drvdata(pdev)) |
30 | 29 | ||
31 | struct ci13xxx_imx_data { | 30 | struct ci_hdrc_imx_data { |
32 | struct device_node *phy_np; | ||
33 | struct usb_phy *phy; | 31 | struct usb_phy *phy; |
34 | struct platform_device *ci_pdev; | 32 | struct platform_device *ci_pdev; |
35 | struct clk *clk; | 33 | struct clk *clk; |
@@ -88,22 +86,17 @@ EXPORT_SYMBOL_GPL(usbmisc_get_init_data); | |||
88 | 86 | ||
89 | /* End of common functions shared by usbmisc drivers*/ | 87 | /* End of common functions shared by usbmisc drivers*/ |
90 | 88 | ||
91 | static struct ci13xxx_platform_data ci13xxx_imx_platdata = { | 89 | static int ci_hdrc_imx_probe(struct platform_device *pdev) |
92 | .name = "ci13xxx_imx", | ||
93 | .flags = CI13XXX_REQUIRE_TRANSCEIVER | | ||
94 | CI13XXX_PULLUP_ON_VBUS | | ||
95 | CI13XXX_DISABLE_STREAMING, | ||
96 | .capoffset = DEF_CAPOFFSET, | ||
97 | }; | ||
98 | |||
99 | static int ci13xxx_imx_probe(struct platform_device *pdev) | ||
100 | { | 90 | { |
101 | struct ci13xxx_imx_data *data; | 91 | struct ci_hdrc_imx_data *data; |
102 | struct platform_device *plat_ci, *phy_pdev; | 92 | struct ci_hdrc_platform_data pdata = { |
103 | struct device_node *phy_np; | 93 | .name = "ci_hdrc_imx", |
94 | .capoffset = DEF_CAPOFFSET, | ||
95 | .flags = CI_HDRC_REQUIRE_TRANSCEIVER | | ||
96 | CI_HDRC_PULLUP_ON_VBUS | | ||
97 | CI_HDRC_DISABLE_STREAMING, | ||
98 | }; | ||
104 | struct resource *res; | 99 | struct resource *res; |
105 | struct regulator *reg_vbus; | ||
106 | struct pinctrl *pinctrl; | ||
107 | int ret; | 100 | int ret; |
108 | 101 | ||
109 | if (of_find_property(pdev->dev.of_node, "fsl,usbmisc", NULL) | 102 | if (of_find_property(pdev->dev.of_node, "fsl,usbmisc", NULL) |
@@ -112,7 +105,7 @@ static int ci13xxx_imx_probe(struct platform_device *pdev) | |||
112 | 105 | ||
113 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | 106 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); |
114 | if (!data) { | 107 | if (!data) { |
115 | dev_err(&pdev->dev, "Failed to allocate CI13xxx-IMX data!\n"); | 108 | dev_err(&pdev->dev, "Failed to allocate ci_hdrc-imx data!\n"); |
116 | return -ENOMEM; | 109 | return -ENOMEM; |
117 | } | 110 | } |
118 | 111 | ||
@@ -122,11 +115,6 @@ static int ci13xxx_imx_probe(struct platform_device *pdev) | |||
122 | return -ENOENT; | 115 | return -ENOENT; |
123 | } | 116 | } |
124 | 117 | ||
125 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | ||
126 | if (IS_ERR(pinctrl)) | ||
127 | dev_warn(&pdev->dev, "pinctrl get/select failed, err=%ld\n", | ||
128 | PTR_ERR(pinctrl)); | ||
129 | |||
130 | data->clk = devm_clk_get(&pdev->dev, NULL); | 118 | data->clk = devm_clk_get(&pdev->dev, NULL); |
131 | if (IS_ERR(data->clk)) { | 119 | if (IS_ERR(data->clk)) { |
132 | dev_err(&pdev->dev, | 120 | dev_err(&pdev->dev, |
@@ -141,37 +129,33 @@ static int ci13xxx_imx_probe(struct platform_device *pdev) | |||
141 | return ret; | 129 | return ret; |
142 | } | 130 | } |
143 | 131 | ||
144 | phy_np = of_parse_phandle(pdev->dev.of_node, "fsl,usbphy", 0); | 132 | data->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "fsl,usbphy", 0); |
145 | if (phy_np) { | 133 | if (!IS_ERR(data->phy)) { |
146 | data->phy_np = phy_np; | 134 | ret = usb_phy_init(data->phy); |
147 | phy_pdev = of_find_device_by_node(phy_np); | 135 | if (ret) { |
148 | if (phy_pdev) { | 136 | dev_err(&pdev->dev, "unable to init phy: %d\n", ret); |
149 | struct usb_phy *phy; | 137 | goto err_clk; |
150 | phy = pdev_to_phy(phy_pdev); | ||
151 | if (phy && | ||
152 | try_module_get(phy_pdev->dev.driver->owner)) { | ||
153 | usb_phy_init(phy); | ||
154 | data->phy = phy; | ||
155 | } | ||
156 | } | 138 | } |
139 | } else if (PTR_ERR(data->phy) == -EPROBE_DEFER) { | ||
140 | ret = -EPROBE_DEFER; | ||
141 | goto err_clk; | ||
157 | } | 142 | } |
158 | 143 | ||
159 | /* we only support host now, so enable vbus here */ | 144 | /* we only support host now, so enable vbus here */ |
160 | reg_vbus = devm_regulator_get(&pdev->dev, "vbus"); | 145 | data->reg_vbus = devm_regulator_get(&pdev->dev, "vbus"); |
161 | if (!IS_ERR(reg_vbus)) { | 146 | if (!IS_ERR(data->reg_vbus)) { |
162 | ret = regulator_enable(reg_vbus); | 147 | ret = regulator_enable(data->reg_vbus); |
163 | if (ret) { | 148 | if (ret) { |
164 | dev_err(&pdev->dev, | 149 | dev_err(&pdev->dev, |
165 | "Failed to enable vbus regulator, err=%d\n", | 150 | "Failed to enable vbus regulator, err=%d\n", |
166 | ret); | 151 | ret); |
167 | goto put_np; | 152 | goto err_clk; |
168 | } | 153 | } |
169 | data->reg_vbus = reg_vbus; | ||
170 | } else { | 154 | } else { |
171 | reg_vbus = NULL; | 155 | data->reg_vbus = NULL; |
172 | } | 156 | } |
173 | 157 | ||
174 | ci13xxx_imx_platdata.phy = data->phy; | 158 | pdata.phy = data->phy; |
175 | 159 | ||
176 | if (!pdev->dev.dma_mask) | 160 | if (!pdev->dev.dma_mask) |
177 | pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; | 161 | pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; |
@@ -187,11 +171,11 @@ static int ci13xxx_imx_probe(struct platform_device *pdev) | |||
187 | } | 171 | } |
188 | } | 172 | } |
189 | 173 | ||
190 | plat_ci = ci13xxx_add_device(&pdev->dev, | 174 | data->ci_pdev = ci_hdrc_add_device(&pdev->dev, |
191 | pdev->resource, pdev->num_resources, | 175 | pdev->resource, pdev->num_resources, |
192 | &ci13xxx_imx_platdata); | 176 | &pdata); |
193 | if (IS_ERR(plat_ci)) { | 177 | if (IS_ERR(data->ci_pdev)) { |
194 | ret = PTR_ERR(plat_ci); | 178 | ret = PTR_ERR(data->ci_pdev); |
195 | dev_err(&pdev->dev, | 179 | dev_err(&pdev->dev, |
196 | "Can't register ci_hdrc platform device, err=%d\n", | 180 | "Can't register ci_hdrc platform device, err=%d\n", |
197 | ret); | 181 | ret); |
@@ -203,11 +187,10 @@ static int ci13xxx_imx_probe(struct platform_device *pdev) | |||
203 | if (ret) { | 187 | if (ret) { |
204 | dev_err(&pdev->dev, | 188 | dev_err(&pdev->dev, |
205 | "usbmisc post failed, ret=%d\n", ret); | 189 | "usbmisc post failed, ret=%d\n", ret); |
206 | goto put_np; | 190 | goto disable_device; |
207 | } | 191 | } |
208 | } | 192 | } |
209 | 193 | ||
210 | data->ci_pdev = plat_ci; | ||
211 | platform_set_drvdata(pdev, data); | 194 | platform_set_drvdata(pdev, data); |
212 | 195 | ||
213 | pm_runtime_no_callbacks(&pdev->dev); | 196 | pm_runtime_no_callbacks(&pdev->dev); |
@@ -215,22 +198,22 @@ static int ci13xxx_imx_probe(struct platform_device *pdev) | |||
215 | 198 | ||
216 | return 0; | 199 | return 0; |
217 | 200 | ||
201 | disable_device: | ||
202 | ci_hdrc_remove_device(data->ci_pdev); | ||
218 | err: | 203 | err: |
219 | if (reg_vbus) | 204 | if (data->reg_vbus) |
220 | regulator_disable(reg_vbus); | 205 | regulator_disable(data->reg_vbus); |
221 | put_np: | 206 | err_clk: |
222 | if (phy_np) | ||
223 | of_node_put(phy_np); | ||
224 | clk_disable_unprepare(data->clk); | 207 | clk_disable_unprepare(data->clk); |
225 | return ret; | 208 | return ret; |
226 | } | 209 | } |
227 | 210 | ||
228 | static int ci13xxx_imx_remove(struct platform_device *pdev) | 211 | static int ci_hdrc_imx_remove(struct platform_device *pdev) |
229 | { | 212 | { |
230 | struct ci13xxx_imx_data *data = platform_get_drvdata(pdev); | 213 | struct ci_hdrc_imx_data *data = platform_get_drvdata(pdev); |
231 | 214 | ||
232 | pm_runtime_disable(&pdev->dev); | 215 | pm_runtime_disable(&pdev->dev); |
233 | ci13xxx_remove_device(data->ci_pdev); | 216 | ci_hdrc_remove_device(data->ci_pdev); |
234 | 217 | ||
235 | if (data->reg_vbus) | 218 | if (data->reg_vbus) |
236 | regulator_disable(data->reg_vbus); | 219 | regulator_disable(data->reg_vbus); |
@@ -240,35 +223,31 @@ static int ci13xxx_imx_remove(struct platform_device *pdev) | |||
240 | module_put(data->phy->dev->driver->owner); | 223 | module_put(data->phy->dev->driver->owner); |
241 | } | 224 | } |
242 | 225 | ||
243 | of_node_put(data->phy_np); | ||
244 | |||
245 | clk_disable_unprepare(data->clk); | 226 | clk_disable_unprepare(data->clk); |
246 | 227 | ||
247 | platform_set_drvdata(pdev, NULL); | ||
248 | |||
249 | return 0; | 228 | return 0; |
250 | } | 229 | } |
251 | 230 | ||
252 | static const struct of_device_id ci13xxx_imx_dt_ids[] = { | 231 | static const struct of_device_id ci_hdrc_imx_dt_ids[] = { |
253 | { .compatible = "fsl,imx27-usb", }, | 232 | { .compatible = "fsl,imx27-usb", }, |
254 | { /* sentinel */ } | 233 | { /* sentinel */ } |
255 | }; | 234 | }; |
256 | MODULE_DEVICE_TABLE(of, ci13xxx_imx_dt_ids); | 235 | MODULE_DEVICE_TABLE(of, ci_hdrc_imx_dt_ids); |
257 | 236 | ||
258 | static struct platform_driver ci13xxx_imx_driver = { | 237 | static struct platform_driver ci_hdrc_imx_driver = { |
259 | .probe = ci13xxx_imx_probe, | 238 | .probe = ci_hdrc_imx_probe, |
260 | .remove = ci13xxx_imx_remove, | 239 | .remove = ci_hdrc_imx_remove, |
261 | .driver = { | 240 | .driver = { |
262 | .name = "imx_usb", | 241 | .name = "imx_usb", |
263 | .owner = THIS_MODULE, | 242 | .owner = THIS_MODULE, |
264 | .of_match_table = ci13xxx_imx_dt_ids, | 243 | .of_match_table = ci_hdrc_imx_dt_ids, |
265 | }, | 244 | }, |
266 | }; | 245 | }; |
267 | 246 | ||
268 | module_platform_driver(ci13xxx_imx_driver); | 247 | module_platform_driver(ci_hdrc_imx_driver); |
269 | 248 | ||
270 | MODULE_ALIAS("platform:imx-usb"); | 249 | MODULE_ALIAS("platform:imx-usb"); |
271 | MODULE_LICENSE("GPL v2"); | 250 | MODULE_LICENSE("GPL v2"); |
272 | MODULE_DESCRIPTION("CI13xxx i.MX USB binding"); | 251 | MODULE_DESCRIPTION("CI HDRC i.MX USB binding"); |
273 | MODULE_AUTHOR("Marek Vasut <marex@denx.de>"); | 252 | MODULE_AUTHOR("Marek Vasut <marex@denx.de>"); |
274 | MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>"); | 253 | MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>"); |
diff --git a/drivers/usb/chipidea/ci13xxx_imx.h b/drivers/usb/chipidea/ci_hdrc_imx.h index 550bfa457620..550bfa457620 100644 --- a/drivers/usb/chipidea/ci13xxx_imx.h +++ b/drivers/usb/chipidea/ci_hdrc_imx.h | |||
diff --git a/drivers/usb/chipidea/ci13xxx_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c index 7d16681fd3d2..fb657ef50a9c 100644 --- a/drivers/usb/chipidea/ci13xxx_msm.c +++ b/drivers/usb/chipidea/ci_hdrc_msm.c | |||
@@ -17,19 +17,19 @@ | |||
17 | 17 | ||
18 | #define MSM_USB_BASE (ci->hw_bank.abs) | 18 | #define MSM_USB_BASE (ci->hw_bank.abs) |
19 | 19 | ||
20 | static void ci13xxx_msm_notify_event(struct ci13xxx *ci, unsigned event) | 20 | static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event) |
21 | { | 21 | { |
22 | struct device *dev = ci->gadget.dev.parent; | 22 | struct device *dev = ci->gadget.dev.parent; |
23 | int val; | 23 | int val; |
24 | 24 | ||
25 | switch (event) { | 25 | switch (event) { |
26 | case CI13XXX_CONTROLLER_RESET_EVENT: | 26 | case CI_HDRC_CONTROLLER_RESET_EVENT: |
27 | dev_dbg(dev, "CI13XXX_CONTROLLER_RESET_EVENT received\n"); | 27 | dev_dbg(dev, "CI_HDRC_CONTROLLER_RESET_EVENT received\n"); |
28 | writel(0, USB_AHBBURST); | 28 | writel(0, USB_AHBBURST); |
29 | writel(0, USB_AHBMODE); | 29 | writel(0, USB_AHBMODE); |
30 | break; | 30 | break; |
31 | case CI13XXX_CONTROLLER_STOPPED_EVENT: | 31 | case CI_HDRC_CONTROLLER_STOPPED_EVENT: |
32 | dev_dbg(dev, "CI13XXX_CONTROLLER_STOPPED_EVENT received\n"); | 32 | dev_dbg(dev, "CI_HDRC_CONTROLLER_STOPPED_EVENT received\n"); |
33 | /* | 33 | /* |
34 | * Put the transceiver in non-driving mode. Otherwise host | 34 | * Put the transceiver in non-driving mode. Otherwise host |
35 | * may not detect soft-disconnection. | 35 | * may not detect soft-disconnection. |
@@ -40,32 +40,32 @@ static void ci13xxx_msm_notify_event(struct ci13xxx *ci, unsigned event) | |||
40 | usb_phy_io_write(ci->transceiver, val, ULPI_FUNC_CTRL); | 40 | usb_phy_io_write(ci->transceiver, val, ULPI_FUNC_CTRL); |
41 | break; | 41 | break; |
42 | default: | 42 | default: |
43 | dev_dbg(dev, "unknown ci13xxx event\n"); | 43 | dev_dbg(dev, "unknown ci_hdrc event\n"); |
44 | break; | 44 | break; |
45 | } | 45 | } |
46 | } | 46 | } |
47 | 47 | ||
48 | static struct ci13xxx_platform_data ci13xxx_msm_platdata = { | 48 | static struct ci_hdrc_platform_data ci_hdrc_msm_platdata = { |
49 | .name = "ci13xxx_msm", | 49 | .name = "ci_hdrc_msm", |
50 | .flags = CI13XXX_REGS_SHARED | | 50 | .flags = CI_HDRC_REGS_SHARED | |
51 | CI13XXX_REQUIRE_TRANSCEIVER | | 51 | CI_HDRC_REQUIRE_TRANSCEIVER | |
52 | CI13XXX_PULLUP_ON_VBUS | | 52 | CI_HDRC_PULLUP_ON_VBUS | |
53 | CI13XXX_DISABLE_STREAMING, | 53 | CI_HDRC_DISABLE_STREAMING, |
54 | 54 | ||
55 | .notify_event = ci13xxx_msm_notify_event, | 55 | .notify_event = ci_hdrc_msm_notify_event, |
56 | }; | 56 | }; |
57 | 57 | ||
58 | static int ci13xxx_msm_probe(struct platform_device *pdev) | 58 | static int ci_hdrc_msm_probe(struct platform_device *pdev) |
59 | { | 59 | { |
60 | struct platform_device *plat_ci; | 60 | struct platform_device *plat_ci; |
61 | 61 | ||
62 | dev_dbg(&pdev->dev, "ci13xxx_msm_probe\n"); | 62 | dev_dbg(&pdev->dev, "ci_hdrc_msm_probe\n"); |
63 | 63 | ||
64 | plat_ci = ci13xxx_add_device(&pdev->dev, | 64 | plat_ci = ci_hdrc_add_device(&pdev->dev, |
65 | pdev->resource, pdev->num_resources, | 65 | pdev->resource, pdev->num_resources, |
66 | &ci13xxx_msm_platdata); | 66 | &ci_hdrc_msm_platdata); |
67 | if (IS_ERR(plat_ci)) { | 67 | if (IS_ERR(plat_ci)) { |
68 | dev_err(&pdev->dev, "ci13xxx_add_device failed!\n"); | 68 | dev_err(&pdev->dev, "ci_hdrc_add_device failed!\n"); |
69 | return PTR_ERR(plat_ci); | 69 | return PTR_ERR(plat_ci); |
70 | } | 70 | } |
71 | 71 | ||
@@ -77,23 +77,24 @@ static int ci13xxx_msm_probe(struct platform_device *pdev) | |||
77 | return 0; | 77 | return 0; |
78 | } | 78 | } |
79 | 79 | ||
80 | static int ci13xxx_msm_remove(struct platform_device *pdev) | 80 | static int ci_hdrc_msm_remove(struct platform_device *pdev) |
81 | { | 81 | { |
82 | struct platform_device *plat_ci = platform_get_drvdata(pdev); | 82 | struct platform_device *plat_ci = platform_get_drvdata(pdev); |
83 | 83 | ||
84 | pm_runtime_disable(&pdev->dev); | 84 | pm_runtime_disable(&pdev->dev); |
85 | ci13xxx_remove_device(plat_ci); | 85 | ci_hdrc_remove_device(plat_ci); |
86 | 86 | ||
87 | return 0; | 87 | return 0; |
88 | } | 88 | } |
89 | 89 | ||
90 | static struct platform_driver ci13xxx_msm_driver = { | 90 | static struct platform_driver ci_hdrc_msm_driver = { |
91 | .probe = ci13xxx_msm_probe, | 91 | .probe = ci_hdrc_msm_probe, |
92 | .remove = ci13xxx_msm_remove, | 92 | .remove = ci_hdrc_msm_remove, |
93 | .driver = { .name = "msm_hsusb", }, | 93 | .driver = { .name = "msm_hsusb", }, |
94 | }; | 94 | }; |
95 | 95 | ||
96 | module_platform_driver(ci13xxx_msm_driver); | 96 | module_platform_driver(ci_hdrc_msm_driver); |
97 | 97 | ||
98 | MODULE_ALIAS("platform:msm_hsusb"); | 98 | MODULE_ALIAS("platform:msm_hsusb"); |
99 | MODULE_ALIAS("platform:ci13xxx_msm"); | ||
99 | MODULE_LICENSE("GPL v2"); | 100 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/usb/chipidea/ci13xxx_pci.c b/drivers/usb/chipidea/ci_hdrc_pci.c index 4e1fc61b9d95..042320a6c6c7 100644 --- a/drivers/usb/chipidea/ci13xxx_pci.c +++ b/drivers/usb/chipidea/ci_hdrc_pci.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * ci13xxx_pci.c - MIPS USB IP core family device controller | 2 | * ci_hdrc_pci.c - MIPS USB IP core family device controller |
3 | * | 3 | * |
4 | * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved. | 4 | * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved. |
5 | * | 5 | * |
@@ -18,29 +18,29 @@ | |||
18 | #include <linux/usb/chipidea.h> | 18 | #include <linux/usb/chipidea.h> |
19 | 19 | ||
20 | /* driver name */ | 20 | /* driver name */ |
21 | #define UDC_DRIVER_NAME "ci13xxx_pci" | 21 | #define UDC_DRIVER_NAME "ci_hdrc_pci" |
22 | 22 | ||
23 | /****************************************************************************** | 23 | /****************************************************************************** |
24 | * PCI block | 24 | * PCI block |
25 | *****************************************************************************/ | 25 | *****************************************************************************/ |
26 | static struct ci13xxx_platform_data pci_platdata = { | 26 | static struct ci_hdrc_platform_data pci_platdata = { |
27 | .name = UDC_DRIVER_NAME, | 27 | .name = UDC_DRIVER_NAME, |
28 | .capoffset = DEF_CAPOFFSET, | 28 | .capoffset = DEF_CAPOFFSET, |
29 | }; | 29 | }; |
30 | 30 | ||
31 | static struct ci13xxx_platform_data langwell_pci_platdata = { | 31 | static struct ci_hdrc_platform_data langwell_pci_platdata = { |
32 | .name = UDC_DRIVER_NAME, | 32 | .name = UDC_DRIVER_NAME, |
33 | .capoffset = 0, | 33 | .capoffset = 0, |
34 | }; | 34 | }; |
35 | 35 | ||
36 | static struct ci13xxx_platform_data penwell_pci_platdata = { | 36 | static struct ci_hdrc_platform_data penwell_pci_platdata = { |
37 | .name = UDC_DRIVER_NAME, | 37 | .name = UDC_DRIVER_NAME, |
38 | .capoffset = 0, | 38 | .capoffset = 0, |
39 | .power_budget = 200, | 39 | .power_budget = 200, |
40 | }; | 40 | }; |
41 | 41 | ||
42 | /** | 42 | /** |
43 | * ci13xxx_pci_probe: PCI probe | 43 | * ci_hdrc_pci_probe: PCI probe |
44 | * @pdev: USB device controller being probed | 44 | * @pdev: USB device controller being probed |
45 | * @id: PCI hotplug ID connecting controller to UDC framework | 45 | * @id: PCI hotplug ID connecting controller to UDC framework |
46 | * | 46 | * |
@@ -48,10 +48,10 @@ static struct ci13xxx_platform_data penwell_pci_platdata = { | |||
48 | * Allocates basic PCI resources for this USB device controller, and then | 48 | * Allocates basic PCI resources for this USB device controller, and then |
49 | * invokes the udc_probe() method to start the UDC associated with it | 49 | * invokes the udc_probe() method to start the UDC associated with it |
50 | */ | 50 | */ |
51 | static int ci13xxx_pci_probe(struct pci_dev *pdev, | 51 | static int ci_hdrc_pci_probe(struct pci_dev *pdev, |
52 | const struct pci_device_id *id) | 52 | const struct pci_device_id *id) |
53 | { | 53 | { |
54 | struct ci13xxx_platform_data *platdata = (void *)id->driver_data; | 54 | struct ci_hdrc_platform_data *platdata = (void *)id->driver_data; |
55 | struct platform_device *plat_ci; | 55 | struct platform_device *plat_ci; |
56 | struct resource res[3]; | 56 | struct resource res[3]; |
57 | int retval = 0, nres = 2; | 57 | int retval = 0, nres = 2; |
@@ -61,17 +61,15 @@ static int ci13xxx_pci_probe(struct pci_dev *pdev, | |||
61 | return -ENODEV; | 61 | return -ENODEV; |
62 | } | 62 | } |
63 | 63 | ||
64 | retval = pci_enable_device(pdev); | 64 | retval = pcim_enable_device(pdev); |
65 | if (retval) | 65 | if (retval) |
66 | goto done; | 66 | return retval; |
67 | 67 | ||
68 | if (!pdev->irq) { | 68 | if (!pdev->irq) { |
69 | dev_err(&pdev->dev, "No IRQ, check BIOS/PCI setup!"); | 69 | dev_err(&pdev->dev, "No IRQ, check BIOS/PCI setup!"); |
70 | retval = -ENODEV; | 70 | return -ENODEV; |
71 | goto disable_device; | ||
72 | } | 71 | } |
73 | 72 | ||
74 | pci_set_power_state(pdev, PCI_D0); | ||
75 | pci_set_master(pdev); | 73 | pci_set_master(pdev); |
76 | pci_try_set_mwi(pdev); | 74 | pci_try_set_mwi(pdev); |
77 | 75 | ||
@@ -82,38 +80,30 @@ static int ci13xxx_pci_probe(struct pci_dev *pdev, | |||
82 | res[1].start = pdev->irq; | 80 | res[1].start = pdev->irq; |
83 | res[1].flags = IORESOURCE_IRQ; | 81 | res[1].flags = IORESOURCE_IRQ; |
84 | 82 | ||
85 | plat_ci = ci13xxx_add_device(&pdev->dev, res, nres, platdata); | 83 | plat_ci = ci_hdrc_add_device(&pdev->dev, res, nres, platdata); |
86 | if (IS_ERR(plat_ci)) { | 84 | if (IS_ERR(plat_ci)) { |
87 | dev_err(&pdev->dev, "ci13xxx_add_device failed!\n"); | 85 | dev_err(&pdev->dev, "ci_hdrc_add_device failed!\n"); |
88 | retval = PTR_ERR(plat_ci); | 86 | return PTR_ERR(plat_ci); |
89 | goto disable_device; | ||
90 | } | 87 | } |
91 | 88 | ||
92 | pci_set_drvdata(pdev, plat_ci); | 89 | pci_set_drvdata(pdev, plat_ci); |
93 | 90 | ||
94 | return 0; | 91 | return 0; |
95 | |||
96 | disable_device: | ||
97 | pci_disable_device(pdev); | ||
98 | done: | ||
99 | return retval; | ||
100 | } | 92 | } |
101 | 93 | ||
102 | /** | 94 | /** |
103 | * ci13xxx_pci_remove: PCI remove | 95 | * ci_hdrc_pci_remove: PCI remove |
104 | * @pdev: USB Device Controller being removed | 96 | * @pdev: USB Device Controller being removed |
105 | * | 97 | * |
106 | * Reverses the effect of ci13xxx_pci_probe(), | 98 | * Reverses the effect of ci_hdrc_pci_probe(), |
107 | * first invoking the udc_remove() and then releases | 99 | * first invoking the udc_remove() and then releases |
108 | * all PCI resources allocated for this USB device controller | 100 | * all PCI resources allocated for this USB device controller |
109 | */ | 101 | */ |
110 | static void ci13xxx_pci_remove(struct pci_dev *pdev) | 102 | static void ci_hdrc_pci_remove(struct pci_dev *pdev) |
111 | { | 103 | { |
112 | struct platform_device *plat_ci = pci_get_drvdata(pdev); | 104 | struct platform_device *plat_ci = pci_get_drvdata(pdev); |
113 | 105 | ||
114 | ci13xxx_remove_device(plat_ci); | 106 | ci_hdrc_remove_device(plat_ci); |
115 | pci_set_drvdata(pdev, NULL); | ||
116 | pci_disable_device(pdev); | ||
117 | } | 107 | } |
118 | 108 | ||
119 | /** | 109 | /** |
@@ -122,7 +112,7 @@ static void ci13xxx_pci_remove(struct pci_dev *pdev) | |||
122 | * | 112 | * |
123 | * Check "pci.h" for details | 113 | * Check "pci.h" for details |
124 | */ | 114 | */ |
125 | static DEFINE_PCI_DEVICE_TABLE(ci13xxx_pci_id_table) = { | 115 | static DEFINE_PCI_DEVICE_TABLE(ci_hdrc_pci_id_table) = { |
126 | { | 116 | { |
127 | PCI_DEVICE(0x153F, 0x1004), | 117 | PCI_DEVICE(0x153F, 0x1004), |
128 | .driver_data = (kernel_ulong_t)&pci_platdata, | 118 | .driver_data = (kernel_ulong_t)&pci_platdata, |
@@ -141,18 +131,19 @@ static DEFINE_PCI_DEVICE_TABLE(ci13xxx_pci_id_table) = { | |||
141 | }, | 131 | }, |
142 | { 0, 0, 0, 0, 0, 0, 0 /* end: all zeroes */ } | 132 | { 0, 0, 0, 0, 0, 0, 0 /* end: all zeroes */ } |
143 | }; | 133 | }; |
144 | MODULE_DEVICE_TABLE(pci, ci13xxx_pci_id_table); | 134 | MODULE_DEVICE_TABLE(pci, ci_hdrc_pci_id_table); |
145 | 135 | ||
146 | static struct pci_driver ci13xxx_pci_driver = { | 136 | static struct pci_driver ci_hdrc_pci_driver = { |
147 | .name = UDC_DRIVER_NAME, | 137 | .name = UDC_DRIVER_NAME, |
148 | .id_table = ci13xxx_pci_id_table, | 138 | .id_table = ci_hdrc_pci_id_table, |
149 | .probe = ci13xxx_pci_probe, | 139 | .probe = ci_hdrc_pci_probe, |
150 | .remove = ci13xxx_pci_remove, | 140 | .remove = ci_hdrc_pci_remove, |
151 | }; | 141 | }; |
152 | 142 | ||
153 | module_pci_driver(ci13xxx_pci_driver); | 143 | module_pci_driver(ci_hdrc_pci_driver); |
154 | 144 | ||
155 | MODULE_AUTHOR("MIPS - David Lopo <dlopo@chipidea.mips.com>"); | 145 | MODULE_AUTHOR("MIPS - David Lopo <dlopo@chipidea.mips.com>"); |
156 | MODULE_DESCRIPTION("MIPS CI13XXX USB Peripheral Controller"); | 146 | MODULE_DESCRIPTION("MIPS CI13XXX USB Peripheral Controller"); |
157 | MODULE_LICENSE("GPL"); | 147 | MODULE_LICENSE("GPL"); |
158 | MODULE_VERSION("June 2008"); | 148 | MODULE_VERSION("June 2008"); |
149 | MODULE_ALIAS("platform:ci13xxx_pci"); | ||
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 475c9c114689..a5df24c578fc 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c | |||
@@ -43,8 +43,7 @@ | |||
43 | * | 43 | * |
44 | * TODO List | 44 | * TODO List |
45 | * - OTG | 45 | * - OTG |
46 | * - Isochronous & Interrupt Traffic | 46 | * - Interrupt Traffic |
47 | * - Handle requests which spawns into several TDs | ||
48 | * - GET_STATUS(device) - always reports 0 | 47 | * - GET_STATUS(device) - always reports 0 |
49 | * - Gadget API (majority of optional features) | 48 | * - Gadget API (majority of optional features) |
50 | * - Suspend & Remote Wakeup | 49 | * - Suspend & Remote Wakeup |
@@ -64,6 +63,8 @@ | |||
64 | #include <linux/usb/gadget.h> | 63 | #include <linux/usb/gadget.h> |
65 | #include <linux/usb/otg.h> | 64 | #include <linux/usb/otg.h> |
66 | #include <linux/usb/chipidea.h> | 65 | #include <linux/usb/chipidea.h> |
66 | #include <linux/usb/of.h> | ||
67 | #include <linux/phy.h> | ||
67 | 68 | ||
68 | #include "ci.h" | 69 | #include "ci.h" |
69 | #include "udc.h" | 70 | #include "udc.h" |
@@ -116,7 +117,7 @@ static uintptr_t ci_regs_lpm[] = { | |||
116 | [OP_ENDPTCTRL] = 0x0ECUL, | 117 | [OP_ENDPTCTRL] = 0x0ECUL, |
117 | }; | 118 | }; |
118 | 119 | ||
119 | static int hw_alloc_regmap(struct ci13xxx *ci, bool is_lpm) | 120 | static int hw_alloc_regmap(struct ci_hdrc *ci, bool is_lpm) |
120 | { | 121 | { |
121 | int i; | 122 | int i; |
122 | 123 | ||
@@ -148,7 +149,7 @@ static int hw_alloc_regmap(struct ci13xxx *ci, bool is_lpm) | |||
148 | * | 149 | * |
149 | * This function returns an error code | 150 | * This function returns an error code |
150 | */ | 151 | */ |
151 | int hw_port_test_set(struct ci13xxx *ci, u8 mode) | 152 | int hw_port_test_set(struct ci_hdrc *ci, u8 mode) |
152 | { | 153 | { |
153 | const u8 TEST_MODE_MAX = 7; | 154 | const u8 TEST_MODE_MAX = 7; |
154 | 155 | ||
@@ -164,12 +165,12 @@ int hw_port_test_set(struct ci13xxx *ci, u8 mode) | |||
164 | * | 165 | * |
165 | * This function returns port test mode value | 166 | * This function returns port test mode value |
166 | */ | 167 | */ |
167 | u8 hw_port_test_get(struct ci13xxx *ci) | 168 | u8 hw_port_test_get(struct ci_hdrc *ci) |
168 | { | 169 | { |
169 | return hw_read(ci, OP_PORTSC, PORTSC_PTC) >> __ffs(PORTSC_PTC); | 170 | return hw_read(ci, OP_PORTSC, PORTSC_PTC) >> __ffs(PORTSC_PTC); |
170 | } | 171 | } |
171 | 172 | ||
172 | static int hw_device_init(struct ci13xxx *ci, void __iomem *base) | 173 | static int hw_device_init(struct ci_hdrc *ci, void __iomem *base) |
173 | { | 174 | { |
174 | u32 reg; | 175 | u32 reg; |
175 | 176 | ||
@@ -208,13 +209,52 @@ static int hw_device_init(struct ci13xxx *ci, void __iomem *base) | |||
208 | return 0; | 209 | return 0; |
209 | } | 210 | } |
210 | 211 | ||
212 | static void hw_phymode_configure(struct ci_hdrc *ci) | ||
213 | { | ||
214 | u32 portsc, lpm, sts; | ||
215 | |||
216 | switch (ci->platdata->phy_mode) { | ||
217 | case USBPHY_INTERFACE_MODE_UTMI: | ||
218 | portsc = PORTSC_PTS(PTS_UTMI); | ||
219 | lpm = DEVLC_PTS(PTS_UTMI); | ||
220 | break; | ||
221 | case USBPHY_INTERFACE_MODE_UTMIW: | ||
222 | portsc = PORTSC_PTS(PTS_UTMI) | PORTSC_PTW; | ||
223 | lpm = DEVLC_PTS(PTS_UTMI) | DEVLC_PTW; | ||
224 | break; | ||
225 | case USBPHY_INTERFACE_MODE_ULPI: | ||
226 | portsc = PORTSC_PTS(PTS_ULPI); | ||
227 | lpm = DEVLC_PTS(PTS_ULPI); | ||
228 | break; | ||
229 | case USBPHY_INTERFACE_MODE_SERIAL: | ||
230 | portsc = PORTSC_PTS(PTS_SERIAL); | ||
231 | lpm = DEVLC_PTS(PTS_SERIAL); | ||
232 | sts = 1; | ||
233 | break; | ||
234 | case USBPHY_INTERFACE_MODE_HSIC: | ||
235 | portsc = PORTSC_PTS(PTS_HSIC); | ||
236 | lpm = DEVLC_PTS(PTS_HSIC); | ||
237 | break; | ||
238 | default: | ||
239 | return; | ||
240 | } | ||
241 | |||
242 | if (ci->hw_bank.lpm) { | ||
243 | hw_write(ci, OP_DEVLC, DEVLC_PTS(7) | DEVLC_PTW, lpm); | ||
244 | hw_write(ci, OP_DEVLC, DEVLC_STS, sts); | ||
245 | } else { | ||
246 | hw_write(ci, OP_PORTSC, PORTSC_PTS(7) | PORTSC_PTW, portsc); | ||
247 | hw_write(ci, OP_PORTSC, PORTSC_STS, sts); | ||
248 | } | ||
249 | } | ||
250 | |||
211 | /** | 251 | /** |
212 | * hw_device_reset: resets chip (execute without interruption) | 252 | * hw_device_reset: resets chip (execute without interruption) |
213 | * @ci: the controller | 253 | * @ci: the controller |
214 | * | 254 | * |
215 | * This function returns an error code | 255 | * This function returns an error code |
216 | */ | 256 | */ |
217 | int hw_device_reset(struct ci13xxx *ci, u32 mode) | 257 | int hw_device_reset(struct ci_hdrc *ci, u32 mode) |
218 | { | 258 | { |
219 | /* should flush & stop before reset */ | 259 | /* should flush & stop before reset */ |
220 | hw_write(ci, OP_ENDPTFLUSH, ~0, ~0); | 260 | hw_write(ci, OP_ENDPTFLUSH, ~0, ~0); |
@@ -224,12 +264,13 @@ int hw_device_reset(struct ci13xxx *ci, u32 mode) | |||
224 | while (hw_read(ci, OP_USBCMD, USBCMD_RST)) | 264 | while (hw_read(ci, OP_USBCMD, USBCMD_RST)) |
225 | udelay(10); /* not RTOS friendly */ | 265 | udelay(10); /* not RTOS friendly */ |
226 | 266 | ||
267 | hw_phymode_configure(ci); | ||
227 | 268 | ||
228 | if (ci->platdata->notify_event) | 269 | if (ci->platdata->notify_event) |
229 | ci->platdata->notify_event(ci, | 270 | ci->platdata->notify_event(ci, |
230 | CI13XXX_CONTROLLER_RESET_EVENT); | 271 | CI_HDRC_CONTROLLER_RESET_EVENT); |
231 | 272 | ||
232 | if (ci->platdata->flags & CI13XXX_DISABLE_STREAMING) | 273 | if (ci->platdata->flags & CI_HDRC_DISABLE_STREAMING) |
233 | hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS); | 274 | hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS); |
234 | 275 | ||
235 | /* USBMODE should be configured step by step */ | 276 | /* USBMODE should be configured step by step */ |
@@ -251,7 +292,7 @@ int hw_device_reset(struct ci13xxx *ci, u32 mode) | |||
251 | * ci_otg_role - pick role based on ID pin state | 292 | * ci_otg_role - pick role based on ID pin state |
252 | * @ci: the controller | 293 | * @ci: the controller |
253 | */ | 294 | */ |
254 | static enum ci_role ci_otg_role(struct ci13xxx *ci) | 295 | static enum ci_role ci_otg_role(struct ci_hdrc *ci) |
255 | { | 296 | { |
256 | u32 sts = hw_read(ci, OP_OTGSC, ~0); | 297 | u32 sts = hw_read(ci, OP_OTGSC, ~0); |
257 | enum ci_role role = sts & OTGSC_ID | 298 | enum ci_role role = sts & OTGSC_ID |
@@ -267,7 +308,7 @@ static enum ci_role ci_otg_role(struct ci13xxx *ci) | |||
267 | */ | 308 | */ |
268 | static void ci_role_work(struct work_struct *work) | 309 | static void ci_role_work(struct work_struct *work) |
269 | { | 310 | { |
270 | struct ci13xxx *ci = container_of(work, struct ci13xxx, work); | 311 | struct ci_hdrc *ci = container_of(work, struct ci_hdrc, work); |
271 | enum ci_role role = ci_otg_role(ci); | 312 | enum ci_role role = ci_otg_role(ci); |
272 | 313 | ||
273 | if (role != ci->role) { | 314 | if (role != ci->role) { |
@@ -283,7 +324,7 @@ static void ci_role_work(struct work_struct *work) | |||
283 | 324 | ||
284 | static irqreturn_t ci_irq(int irq, void *data) | 325 | static irqreturn_t ci_irq(int irq, void *data) |
285 | { | 326 | { |
286 | struct ci13xxx *ci = data; | 327 | struct ci_hdrc *ci = data; |
287 | irqreturn_t ret = IRQ_NONE; | 328 | irqreturn_t ret = IRQ_NONE; |
288 | u32 otgsc = 0; | 329 | u32 otgsc = 0; |
289 | 330 | ||
@@ -305,9 +346,9 @@ static irqreturn_t ci_irq(int irq, void *data) | |||
305 | 346 | ||
306 | static DEFINE_IDA(ci_ida); | 347 | static DEFINE_IDA(ci_ida); |
307 | 348 | ||
308 | struct platform_device *ci13xxx_add_device(struct device *dev, | 349 | struct platform_device *ci_hdrc_add_device(struct device *dev, |
309 | struct resource *res, int nres, | 350 | struct resource *res, int nres, |
310 | struct ci13xxx_platform_data *platdata) | 351 | struct ci_hdrc_platform_data *platdata) |
311 | { | 352 | { |
312 | struct platform_device *pdev; | 353 | struct platform_device *pdev; |
313 | int id, ret; | 354 | int id, ret; |
@@ -347,29 +388,33 @@ put_id: | |||
347 | ida_simple_remove(&ci_ida, id); | 388 | ida_simple_remove(&ci_ida, id); |
348 | return ERR_PTR(ret); | 389 | return ERR_PTR(ret); |
349 | } | 390 | } |
350 | EXPORT_SYMBOL_GPL(ci13xxx_add_device); | 391 | EXPORT_SYMBOL_GPL(ci_hdrc_add_device); |
351 | 392 | ||
352 | void ci13xxx_remove_device(struct platform_device *pdev) | 393 | void ci_hdrc_remove_device(struct platform_device *pdev) |
353 | { | 394 | { |
354 | int id = pdev->id; | 395 | int id = pdev->id; |
355 | platform_device_unregister(pdev); | 396 | platform_device_unregister(pdev); |
356 | ida_simple_remove(&ci_ida, id); | 397 | ida_simple_remove(&ci_ida, id); |
357 | } | 398 | } |
358 | EXPORT_SYMBOL_GPL(ci13xxx_remove_device); | 399 | EXPORT_SYMBOL_GPL(ci_hdrc_remove_device); |
359 | 400 | ||
360 | static int ci_hdrc_probe(struct platform_device *pdev) | 401 | static int ci_hdrc_probe(struct platform_device *pdev) |
361 | { | 402 | { |
362 | struct device *dev = &pdev->dev; | 403 | struct device *dev = &pdev->dev; |
363 | struct ci13xxx *ci; | 404 | struct ci_hdrc *ci; |
364 | struct resource *res; | 405 | struct resource *res; |
365 | void __iomem *base; | 406 | void __iomem *base; |
366 | int ret; | 407 | int ret; |
408 | enum usb_dr_mode dr_mode; | ||
367 | 409 | ||
368 | if (!dev->platform_data) { | 410 | if (!dev->platform_data) { |
369 | dev_err(dev, "platform data missing\n"); | 411 | dev_err(dev, "platform data missing\n"); |
370 | return -ENODEV; | 412 | return -ENODEV; |
371 | } | 413 | } |
372 | 414 | ||
415 | if (!dev->of_node && dev->parent) | ||
416 | dev->of_node = dev->parent->of_node; | ||
417 | |||
373 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 418 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
374 | base = devm_ioremap_resource(dev, res); | 419 | base = devm_ioremap_resource(dev, res); |
375 | if (IS_ERR(base)) | 420 | if (IS_ERR(base)) |
@@ -409,14 +454,28 @@ static int ci_hdrc_probe(struct platform_device *pdev) | |||
409 | return -ENODEV; | 454 | return -ENODEV; |
410 | } | 455 | } |
411 | 456 | ||
457 | if (!ci->platdata->phy_mode) | ||
458 | ci->platdata->phy_mode = of_usb_get_phy_mode(dev->of_node); | ||
459 | |||
460 | if (!ci->platdata->dr_mode) | ||
461 | ci->platdata->dr_mode = of_usb_get_dr_mode(dev->of_node); | ||
462 | |||
463 | if (ci->platdata->dr_mode == USB_DR_MODE_UNKNOWN) | ||
464 | ci->platdata->dr_mode = USB_DR_MODE_OTG; | ||
465 | |||
466 | dr_mode = ci->platdata->dr_mode; | ||
412 | /* initialize role(s) before the interrupt is requested */ | 467 | /* initialize role(s) before the interrupt is requested */ |
413 | ret = ci_hdrc_host_init(ci); | 468 | if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_HOST) { |
414 | if (ret) | 469 | ret = ci_hdrc_host_init(ci); |
415 | dev_info(dev, "doesn't support host\n"); | 470 | if (ret) |
471 | dev_info(dev, "doesn't support host\n"); | ||
472 | } | ||
416 | 473 | ||
417 | ret = ci_hdrc_gadget_init(ci); | 474 | if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_PERIPHERAL) { |
418 | if (ret) | 475 | ret = ci_hdrc_gadget_init(ci); |
419 | dev_info(dev, "doesn't support gadget\n"); | 476 | if (ret) |
477 | dev_info(dev, "doesn't support gadget\n"); | ||
478 | } | ||
420 | 479 | ||
421 | if (!ci->roles[CI_ROLE_HOST] && !ci->roles[CI_ROLE_GADGET]) { | 480 | if (!ci->roles[CI_ROLE_HOST] && !ci->roles[CI_ROLE_GADGET]) { |
422 | dev_err(dev, "no supported roles\n"); | 481 | dev_err(dev, "no supported roles\n"); |
@@ -467,7 +526,7 @@ rm_wq: | |||
467 | 526 | ||
468 | static int ci_hdrc_remove(struct platform_device *pdev) | 527 | static int ci_hdrc_remove(struct platform_device *pdev) |
469 | { | 528 | { |
470 | struct ci13xxx *ci = platform_get_drvdata(pdev); | 529 | struct ci_hdrc *ci = platform_get_drvdata(pdev); |
471 | 530 | ||
472 | dbg_remove_files(ci); | 531 | dbg_remove_files(ci); |
473 | flush_workqueue(ci->wq); | 532 | flush_workqueue(ci->wq); |
diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c index 36a7063a6cba..96d899aee473 100644 --- a/drivers/usb/chipidea/debug.c +++ b/drivers/usb/chipidea/debug.c | |||
@@ -18,7 +18,7 @@ | |||
18 | */ | 18 | */ |
19 | static int ci_device_show(struct seq_file *s, void *data) | 19 | static int ci_device_show(struct seq_file *s, void *data) |
20 | { | 20 | { |
21 | struct ci13xxx *ci = s->private; | 21 | struct ci_hdrc *ci = s->private; |
22 | struct usb_gadget *gadget = &ci->gadget; | 22 | struct usb_gadget *gadget = &ci->gadget; |
23 | 23 | ||
24 | seq_printf(s, "speed = %d\n", gadget->speed); | 24 | seq_printf(s, "speed = %d\n", gadget->speed); |
@@ -58,7 +58,7 @@ static const struct file_operations ci_device_fops = { | |||
58 | */ | 58 | */ |
59 | static int ci_port_test_show(struct seq_file *s, void *data) | 59 | static int ci_port_test_show(struct seq_file *s, void *data) |
60 | { | 60 | { |
61 | struct ci13xxx *ci = s->private; | 61 | struct ci_hdrc *ci = s->private; |
62 | unsigned long flags; | 62 | unsigned long flags; |
63 | unsigned mode; | 63 | unsigned mode; |
64 | 64 | ||
@@ -78,7 +78,7 @@ static ssize_t ci_port_test_write(struct file *file, const char __user *ubuf, | |||
78 | size_t count, loff_t *ppos) | 78 | size_t count, loff_t *ppos) |
79 | { | 79 | { |
80 | struct seq_file *s = file->private_data; | 80 | struct seq_file *s = file->private_data; |
81 | struct ci13xxx *ci = s->private; | 81 | struct ci_hdrc *ci = s->private; |
82 | unsigned long flags; | 82 | unsigned long flags; |
83 | unsigned mode; | 83 | unsigned mode; |
84 | char buf[32]; | 84 | char buf[32]; |
@@ -115,7 +115,7 @@ static const struct file_operations ci_port_test_fops = { | |||
115 | */ | 115 | */ |
116 | static int ci_qheads_show(struct seq_file *s, void *data) | 116 | static int ci_qheads_show(struct seq_file *s, void *data) |
117 | { | 117 | { |
118 | struct ci13xxx *ci = s->private; | 118 | struct ci_hdrc *ci = s->private; |
119 | unsigned long flags; | 119 | unsigned long flags; |
120 | unsigned i, j; | 120 | unsigned i, j; |
121 | 121 | ||
@@ -126,15 +126,15 @@ static int ci_qheads_show(struct seq_file *s, void *data) | |||
126 | 126 | ||
127 | spin_lock_irqsave(&ci->lock, flags); | 127 | spin_lock_irqsave(&ci->lock, flags); |
128 | for (i = 0; i < ci->hw_ep_max/2; i++) { | 128 | for (i = 0; i < ci->hw_ep_max/2; i++) { |
129 | struct ci13xxx_ep *mEpRx = &ci->ci13xxx_ep[i]; | 129 | struct ci_hw_ep *hweprx = &ci->ci_hw_ep[i]; |
130 | struct ci13xxx_ep *mEpTx = | 130 | struct ci_hw_ep *hweptx = |
131 | &ci->ci13xxx_ep[i + ci->hw_ep_max/2]; | 131 | &ci->ci_hw_ep[i + ci->hw_ep_max/2]; |
132 | seq_printf(s, "EP=%02i: RX=%08X TX=%08X\n", | 132 | seq_printf(s, "EP=%02i: RX=%08X TX=%08X\n", |
133 | i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma); | 133 | i, (u32)hweprx->qh.dma, (u32)hweptx->qh.dma); |
134 | for (j = 0; j < (sizeof(struct ci13xxx_qh)/sizeof(u32)); j++) | 134 | for (j = 0; j < (sizeof(struct ci_hw_qh)/sizeof(u32)); j++) |
135 | seq_printf(s, " %04X: %08X %08X\n", j, | 135 | seq_printf(s, " %04X: %08X %08X\n", j, |
136 | *((u32 *)mEpRx->qh.ptr + j), | 136 | *((u32 *)hweprx->qh.ptr + j), |
137 | *((u32 *)mEpTx->qh.ptr + j)); | 137 | *((u32 *)hweptx->qh.ptr + j)); |
138 | } | 138 | } |
139 | spin_unlock_irqrestore(&ci->lock, flags); | 139 | spin_unlock_irqrestore(&ci->lock, flags); |
140 | 140 | ||
@@ -158,11 +158,12 @@ static const struct file_operations ci_qheads_fops = { | |||
158 | */ | 158 | */ |
159 | static int ci_requests_show(struct seq_file *s, void *data) | 159 | static int ci_requests_show(struct seq_file *s, void *data) |
160 | { | 160 | { |
161 | struct ci13xxx *ci = s->private; | 161 | struct ci_hdrc *ci = s->private; |
162 | unsigned long flags; | 162 | unsigned long flags; |
163 | struct list_head *ptr = NULL; | 163 | struct list_head *ptr = NULL; |
164 | struct ci13xxx_req *req = NULL; | 164 | struct ci_hw_req *req = NULL; |
165 | unsigned i, j, qsize = sizeof(struct ci13xxx_td)/sizeof(u32); | 165 | struct td_node *node, *tmpnode; |
166 | unsigned i, j, qsize = sizeof(struct ci_hw_td)/sizeof(u32); | ||
166 | 167 | ||
167 | if (ci->role != CI_ROLE_GADGET) { | 168 | if (ci->role != CI_ROLE_GADGET) { |
168 | seq_printf(s, "not in gadget mode\n"); | 169 | seq_printf(s, "not in gadget mode\n"); |
@@ -171,16 +172,20 @@ static int ci_requests_show(struct seq_file *s, void *data) | |||
171 | 172 | ||
172 | spin_lock_irqsave(&ci->lock, flags); | 173 | spin_lock_irqsave(&ci->lock, flags); |
173 | for (i = 0; i < ci->hw_ep_max; i++) | 174 | for (i = 0; i < ci->hw_ep_max; i++) |
174 | list_for_each(ptr, &ci->ci13xxx_ep[i].qh.queue) { | 175 | list_for_each(ptr, &ci->ci_hw_ep[i].qh.queue) { |
175 | req = list_entry(ptr, struct ci13xxx_req, queue); | 176 | req = list_entry(ptr, struct ci_hw_req, queue); |
176 | 177 | ||
177 | seq_printf(s, "EP=%02i: TD=%08X %s\n", | 178 | list_for_each_entry_safe(node, tmpnode, &req->tds, td) { |
178 | i % (ci->hw_ep_max / 2), (u32)req->dma, | 179 | seq_printf(s, "EP=%02i: TD=%08X %s\n", |
179 | ((i < ci->hw_ep_max/2) ? "RX" : "TX")); | 180 | i % (ci->hw_ep_max / 2), |
180 | 181 | (u32)node->dma, | |
181 | for (j = 0; j < qsize; j++) | 182 | ((i < ci->hw_ep_max/2) ? |
182 | seq_printf(s, " %04X: %08X\n", j, | 183 | "RX" : "TX")); |
183 | *((u32 *)req->ptr + j)); | 184 | |
185 | for (j = 0; j < qsize; j++) | ||
186 | seq_printf(s, " %04X: %08X\n", j, | ||
187 | *((u32 *)node->ptr + j)); | ||
188 | } | ||
184 | } | 189 | } |
185 | spin_unlock_irqrestore(&ci->lock, flags); | 190 | spin_unlock_irqrestore(&ci->lock, flags); |
186 | 191 | ||
@@ -201,7 +206,7 @@ static const struct file_operations ci_requests_fops = { | |||
201 | 206 | ||
202 | static int ci_role_show(struct seq_file *s, void *data) | 207 | static int ci_role_show(struct seq_file *s, void *data) |
203 | { | 208 | { |
204 | struct ci13xxx *ci = s->private; | 209 | struct ci_hdrc *ci = s->private; |
205 | 210 | ||
206 | seq_printf(s, "%s\n", ci_role(ci)->name); | 211 | seq_printf(s, "%s\n", ci_role(ci)->name); |
207 | 212 | ||
@@ -212,7 +217,7 @@ static ssize_t ci_role_write(struct file *file, const char __user *ubuf, | |||
212 | size_t count, loff_t *ppos) | 217 | size_t count, loff_t *ppos) |
213 | { | 218 | { |
214 | struct seq_file *s = file->private_data; | 219 | struct seq_file *s = file->private_data; |
215 | struct ci13xxx *ci = s->private; | 220 | struct ci_hdrc *ci = s->private; |
216 | enum ci_role role; | 221 | enum ci_role role; |
217 | char buf[8]; | 222 | char buf[8]; |
218 | int ret; | 223 | int ret; |
@@ -254,7 +259,7 @@ static const struct file_operations ci_role_fops = { | |||
254 | * | 259 | * |
255 | * This function returns an error code | 260 | * This function returns an error code |
256 | */ | 261 | */ |
257 | int dbg_create_files(struct ci13xxx *ci) | 262 | int dbg_create_files(struct ci_hdrc *ci) |
258 | { | 263 | { |
259 | struct dentry *dent; | 264 | struct dentry *dent; |
260 | 265 | ||
@@ -295,7 +300,7 @@ err: | |||
295 | * dbg_remove_files: destroys the attribute interface | 300 | * dbg_remove_files: destroys the attribute interface |
296 | * @ci: device | 301 | * @ci: device |
297 | */ | 302 | */ |
298 | void dbg_remove_files(struct ci13xxx *ci) | 303 | void dbg_remove_files(struct ci_hdrc *ci) |
299 | { | 304 | { |
300 | debugfs_remove_recursive(ci->debugfs); | 305 | debugfs_remove_recursive(ci->debugfs); |
301 | } | 306 | } |
diff --git a/drivers/usb/chipidea/debug.h b/drivers/usb/chipidea/debug.h index 7ca6ca0a24a5..e16478c4a943 100644 --- a/drivers/usb/chipidea/debug.h +++ b/drivers/usb/chipidea/debug.h | |||
@@ -14,15 +14,15 @@ | |||
14 | #define __DRIVERS_USB_CHIPIDEA_DEBUG_H | 14 | #define __DRIVERS_USB_CHIPIDEA_DEBUG_H |
15 | 15 | ||
16 | #ifdef CONFIG_USB_CHIPIDEA_DEBUG | 16 | #ifdef CONFIG_USB_CHIPIDEA_DEBUG |
17 | int dbg_create_files(struct ci13xxx *ci); | 17 | int dbg_create_files(struct ci_hdrc *ci); |
18 | void dbg_remove_files(struct ci13xxx *ci); | 18 | void dbg_remove_files(struct ci_hdrc *ci); |
19 | #else | 19 | #else |
20 | static inline int dbg_create_files(struct ci13xxx *ci) | 20 | static inline int dbg_create_files(struct ci_hdrc *ci) |
21 | { | 21 | { |
22 | return 0; | 22 | return 0; |
23 | } | 23 | } |
24 | 24 | ||
25 | static inline void dbg_remove_files(struct ci13xxx *ci) | 25 | static inline void dbg_remove_files(struct ci_hdrc *ci) |
26 | { | 26 | { |
27 | } | 27 | } |
28 | #endif | 28 | #endif |
diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c index 8e9d31277c43..40d0fda4f66c 100644 --- a/drivers/usb/chipidea/host.c +++ b/drivers/usb/chipidea/host.c | |||
@@ -33,12 +33,12 @@ | |||
33 | 33 | ||
34 | static struct hc_driver __read_mostly ci_ehci_hc_driver; | 34 | static struct hc_driver __read_mostly ci_ehci_hc_driver; |
35 | 35 | ||
36 | static irqreturn_t host_irq(struct ci13xxx *ci) | 36 | static irqreturn_t host_irq(struct ci_hdrc *ci) |
37 | { | 37 | { |
38 | return usb_hcd_irq(ci->irq, ci->hcd); | 38 | return usb_hcd_irq(ci->irq, ci->hcd); |
39 | } | 39 | } |
40 | 40 | ||
41 | static int host_start(struct ci13xxx *ci) | 41 | static int host_start(struct ci_hdrc *ci) |
42 | { | 42 | { |
43 | struct usb_hcd *hcd; | 43 | struct usb_hcd *hcd; |
44 | struct ehci_hcd *ehci; | 44 | struct ehci_hcd *ehci; |
@@ -70,13 +70,13 @@ static int host_start(struct ci13xxx *ci) | |||
70 | else | 70 | else |
71 | ci->hcd = hcd; | 71 | ci->hcd = hcd; |
72 | 72 | ||
73 | if (ci->platdata->flags & CI13XXX_DISABLE_STREAMING) | 73 | if (ci->platdata->flags & CI_HDRC_DISABLE_STREAMING) |
74 | hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS); | 74 | hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS); |
75 | 75 | ||
76 | return ret; | 76 | return ret; |
77 | } | 77 | } |
78 | 78 | ||
79 | static void host_stop(struct ci13xxx *ci) | 79 | static void host_stop(struct ci_hdrc *ci) |
80 | { | 80 | { |
81 | struct usb_hcd *hcd = ci->hcd; | 81 | struct usb_hcd *hcd = ci->hcd; |
82 | 82 | ||
@@ -84,7 +84,7 @@ static void host_stop(struct ci13xxx *ci) | |||
84 | usb_put_hcd(hcd); | 84 | usb_put_hcd(hcd); |
85 | } | 85 | } |
86 | 86 | ||
87 | int ci_hdrc_host_init(struct ci13xxx *ci) | 87 | int ci_hdrc_host_init(struct ci_hdrc *ci) |
88 | { | 88 | { |
89 | struct ci_role_driver *rdrv; | 89 | struct ci_role_driver *rdrv; |
90 | 90 | ||
diff --git a/drivers/usb/chipidea/host.h b/drivers/usb/chipidea/host.h index 761fb1fd6d99..058875c15333 100644 --- a/drivers/usb/chipidea/host.h +++ b/drivers/usb/chipidea/host.h | |||
@@ -3,11 +3,11 @@ | |||
3 | 3 | ||
4 | #ifdef CONFIG_USB_CHIPIDEA_HOST | 4 | #ifdef CONFIG_USB_CHIPIDEA_HOST |
5 | 5 | ||
6 | int ci_hdrc_host_init(struct ci13xxx *ci); | 6 | int ci_hdrc_host_init(struct ci_hdrc *ci); |
7 | 7 | ||
8 | #else | 8 | #else |
9 | 9 | ||
10 | static inline int ci_hdrc_host_init(struct ci13xxx *ci) | 10 | static inline int ci_hdrc_host_init(struct ci_hdrc *ci) |
11 | { | 11 | { |
12 | return -ENXIO; | 12 | return -ENXIO; |
13 | } | 13 | } |
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index b501346484ae..e475fcda1d68 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c | |||
@@ -61,7 +61,7 @@ static inline int hw_ep_bit(int num, int dir) | |||
61 | return num + (dir ? 16 : 0); | 61 | return num + (dir ? 16 : 0); |
62 | } | 62 | } |
63 | 63 | ||
64 | static inline int ep_to_bit(struct ci13xxx *ci, int n) | 64 | static inline int ep_to_bit(struct ci_hdrc *ci, int n) |
65 | { | 65 | { |
66 | int fill = 16 - ci->hw_ep_max / 2; | 66 | int fill = 16 - ci->hw_ep_max / 2; |
67 | 67 | ||
@@ -77,7 +77,7 @@ static inline int ep_to_bit(struct ci13xxx *ci, int n) | |||
77 | * | 77 | * |
78 | * This function returns an error code | 78 | * This function returns an error code |
79 | */ | 79 | */ |
80 | static int hw_device_state(struct ci13xxx *ci, u32 dma) | 80 | static int hw_device_state(struct ci_hdrc *ci, u32 dma) |
81 | { | 81 | { |
82 | if (dma) { | 82 | if (dma) { |
83 | hw_write(ci, OP_ENDPTLISTADDR, ~0, dma); | 83 | hw_write(ci, OP_ENDPTLISTADDR, ~0, dma); |
@@ -97,7 +97,7 @@ static int hw_device_state(struct ci13xxx *ci, u32 dma) | |||
97 | * | 97 | * |
98 | * This function returns an error code | 98 | * This function returns an error code |
99 | */ | 99 | */ |
100 | static int hw_ep_flush(struct ci13xxx *ci, int num, int dir) | 100 | static int hw_ep_flush(struct ci_hdrc *ci, int num, int dir) |
101 | { | 101 | { |
102 | int n = hw_ep_bit(num, dir); | 102 | int n = hw_ep_bit(num, dir); |
103 | 103 | ||
@@ -118,7 +118,7 @@ static int hw_ep_flush(struct ci13xxx *ci, int num, int dir) | |||
118 | * | 118 | * |
119 | * This function returns an error code | 119 | * This function returns an error code |
120 | */ | 120 | */ |
121 | static int hw_ep_disable(struct ci13xxx *ci, int num, int dir) | 121 | static int hw_ep_disable(struct ci_hdrc *ci, int num, int dir) |
122 | { | 122 | { |
123 | hw_ep_flush(ci, num, dir); | 123 | hw_ep_flush(ci, num, dir); |
124 | hw_write(ci, OP_ENDPTCTRL + num, | 124 | hw_write(ci, OP_ENDPTCTRL + num, |
@@ -134,7 +134,7 @@ static int hw_ep_disable(struct ci13xxx *ci, int num, int dir) | |||
134 | * | 134 | * |
135 | * This function returns an error code | 135 | * This function returns an error code |
136 | */ | 136 | */ |
137 | static int hw_ep_enable(struct ci13xxx *ci, int num, int dir, int type) | 137 | static int hw_ep_enable(struct ci_hdrc *ci, int num, int dir, int type) |
138 | { | 138 | { |
139 | u32 mask, data; | 139 | u32 mask, data; |
140 | 140 | ||
@@ -168,7 +168,7 @@ static int hw_ep_enable(struct ci13xxx *ci, int num, int dir, int type) | |||
168 | * | 168 | * |
169 | * This function returns 1 if endpoint halted | 169 | * This function returns 1 if endpoint halted |
170 | */ | 170 | */ |
171 | static int hw_ep_get_halt(struct ci13xxx *ci, int num, int dir) | 171 | static int hw_ep_get_halt(struct ci_hdrc *ci, int num, int dir) |
172 | { | 172 | { |
173 | u32 mask = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS; | 173 | u32 mask = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS; |
174 | 174 | ||
@@ -182,7 +182,7 @@ static int hw_ep_get_halt(struct ci13xxx *ci, int num, int dir) | |||
182 | * | 182 | * |
183 | * This function returns setup status | 183 | * This function returns setup status |
184 | */ | 184 | */ |
185 | static int hw_test_and_clear_setup_status(struct ci13xxx *ci, int n) | 185 | static int hw_test_and_clear_setup_status(struct ci_hdrc *ci, int n) |
186 | { | 186 | { |
187 | n = ep_to_bit(ci, n); | 187 | n = ep_to_bit(ci, n); |
188 | return hw_test_and_clear(ci, OP_ENDPTSETUPSTAT, BIT(n)); | 188 | return hw_test_and_clear(ci, OP_ENDPTSETUPSTAT, BIT(n)); |
@@ -196,7 +196,7 @@ static int hw_test_and_clear_setup_status(struct ci13xxx *ci, int n) | |||
196 | * | 196 | * |
197 | * This function returns an error code | 197 | * This function returns an error code |
198 | */ | 198 | */ |
199 | static int hw_ep_prime(struct ci13xxx *ci, int num, int dir, int is_ctrl) | 199 | static int hw_ep_prime(struct ci_hdrc *ci, int num, int dir, int is_ctrl) |
200 | { | 200 | { |
201 | int n = hw_ep_bit(num, dir); | 201 | int n = hw_ep_bit(num, dir); |
202 | 202 | ||
@@ -223,13 +223,13 @@ static int hw_ep_prime(struct ci13xxx *ci, int num, int dir, int is_ctrl) | |||
223 | * | 223 | * |
224 | * This function returns an error code | 224 | * This function returns an error code |
225 | */ | 225 | */ |
226 | static int hw_ep_set_halt(struct ci13xxx *ci, int num, int dir, int value) | 226 | static int hw_ep_set_halt(struct ci_hdrc *ci, int num, int dir, int value) |
227 | { | 227 | { |
228 | if (value != 0 && value != 1) | 228 | if (value != 0 && value != 1) |
229 | return -EINVAL; | 229 | return -EINVAL; |
230 | 230 | ||
231 | do { | 231 | do { |
232 | enum ci13xxx_regs reg = OP_ENDPTCTRL + num; | 232 | enum ci_hw_regs reg = OP_ENDPTCTRL + num; |
233 | u32 mask_xs = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS; | 233 | u32 mask_xs = dir ? ENDPTCTRL_TXS : ENDPTCTRL_RXS; |
234 | u32 mask_xr = dir ? ENDPTCTRL_TXR : ENDPTCTRL_RXR; | 234 | u32 mask_xr = dir ? ENDPTCTRL_TXR : ENDPTCTRL_RXR; |
235 | 235 | ||
@@ -246,7 +246,7 @@ static int hw_ep_set_halt(struct ci13xxx *ci, int num, int dir, int value) | |||
246 | * | 246 | * |
247 | * This function returns true if high speed port | 247 | * This function returns true if high speed port |
248 | */ | 248 | */ |
249 | static int hw_port_is_high_speed(struct ci13xxx *ci) | 249 | static int hw_port_is_high_speed(struct ci_hdrc *ci) |
250 | { | 250 | { |
251 | return ci->hw_bank.lpm ? hw_read(ci, OP_DEVLC, DEVLC_PSPD) : | 251 | return ci->hw_bank.lpm ? hw_read(ci, OP_DEVLC, DEVLC_PSPD) : |
252 | hw_read(ci, OP_PORTSC, PORTSC_HSP); | 252 | hw_read(ci, OP_PORTSC, PORTSC_HSP); |
@@ -257,7 +257,7 @@ static int hw_port_is_high_speed(struct ci13xxx *ci) | |||
257 | * | 257 | * |
258 | * This function returns register data | 258 | * This function returns register data |
259 | */ | 259 | */ |
260 | static u32 hw_read_intr_enable(struct ci13xxx *ci) | 260 | static u32 hw_read_intr_enable(struct ci_hdrc *ci) |
261 | { | 261 | { |
262 | return hw_read(ci, OP_USBINTR, ~0); | 262 | return hw_read(ci, OP_USBINTR, ~0); |
263 | } | 263 | } |
@@ -267,7 +267,7 @@ static u32 hw_read_intr_enable(struct ci13xxx *ci) | |||
267 | * | 267 | * |
268 | * This function returns register data | 268 | * This function returns register data |
269 | */ | 269 | */ |
270 | static u32 hw_read_intr_status(struct ci13xxx *ci) | 270 | static u32 hw_read_intr_status(struct ci_hdrc *ci) |
271 | { | 271 | { |
272 | return hw_read(ci, OP_USBSTS, ~0); | 272 | return hw_read(ci, OP_USBSTS, ~0); |
273 | } | 273 | } |
@@ -279,7 +279,7 @@ static u32 hw_read_intr_status(struct ci13xxx *ci) | |||
279 | * | 279 | * |
280 | * This function returns complete status | 280 | * This function returns complete status |
281 | */ | 281 | */ |
282 | static int hw_test_and_clear_complete(struct ci13xxx *ci, int n) | 282 | static int hw_test_and_clear_complete(struct ci_hdrc *ci, int n) |
283 | { | 283 | { |
284 | n = ep_to_bit(ci, n); | 284 | n = ep_to_bit(ci, n); |
285 | return hw_test_and_clear(ci, OP_ENDPTCOMPLETE, BIT(n)); | 285 | return hw_test_and_clear(ci, OP_ENDPTCOMPLETE, BIT(n)); |
@@ -291,7 +291,7 @@ static int hw_test_and_clear_complete(struct ci13xxx *ci, int n) | |||
291 | * | 291 | * |
292 | * This function returns active interrutps | 292 | * This function returns active interrutps |
293 | */ | 293 | */ |
294 | static u32 hw_test_and_clear_intr_active(struct ci13xxx *ci) | 294 | static u32 hw_test_and_clear_intr_active(struct ci_hdrc *ci) |
295 | { | 295 | { |
296 | u32 reg = hw_read_intr_status(ci) & hw_read_intr_enable(ci); | 296 | u32 reg = hw_read_intr_status(ci) & hw_read_intr_enable(ci); |
297 | 297 | ||
@@ -305,7 +305,7 @@ static u32 hw_test_and_clear_intr_active(struct ci13xxx *ci) | |||
305 | * | 305 | * |
306 | * This function returns guard value | 306 | * This function returns guard value |
307 | */ | 307 | */ |
308 | static int hw_test_and_clear_setup_guard(struct ci13xxx *ci) | 308 | static int hw_test_and_clear_setup_guard(struct ci_hdrc *ci) |
309 | { | 309 | { |
310 | return hw_test_and_write(ci, OP_USBCMD, USBCMD_SUTW, 0); | 310 | return hw_test_and_write(ci, OP_USBCMD, USBCMD_SUTW, 0); |
311 | } | 311 | } |
@@ -316,7 +316,7 @@ static int hw_test_and_clear_setup_guard(struct ci13xxx *ci) | |||
316 | * | 316 | * |
317 | * This function returns guard value | 317 | * This function returns guard value |
318 | */ | 318 | */ |
319 | static int hw_test_and_set_setup_guard(struct ci13xxx *ci) | 319 | static int hw_test_and_set_setup_guard(struct ci_hdrc *ci) |
320 | { | 320 | { |
321 | return hw_test_and_write(ci, OP_USBCMD, USBCMD_SUTW, USBCMD_SUTW); | 321 | return hw_test_and_write(ci, OP_USBCMD, USBCMD_SUTW, USBCMD_SUTW); |
322 | } | 322 | } |
@@ -328,7 +328,7 @@ static int hw_test_and_set_setup_guard(struct ci13xxx *ci) | |||
328 | * This function explicitly sets the address, without the "USBADRA" (advance) | 328 | * This function explicitly sets the address, without the "USBADRA" (advance) |
329 | * feature, which is not supported by older versions of the controller. | 329 | * feature, which is not supported by older versions of the controller. |
330 | */ | 330 | */ |
331 | static void hw_usb_set_address(struct ci13xxx *ci, u8 value) | 331 | static void hw_usb_set_address(struct ci_hdrc *ci, u8 value) |
332 | { | 332 | { |
333 | hw_write(ci, OP_DEVICEADDR, DEVICEADDR_USBADR, | 333 | hw_write(ci, OP_DEVICEADDR, DEVICEADDR_USBADR, |
334 | value << __ffs(DEVICEADDR_USBADR)); | 334 | value << __ffs(DEVICEADDR_USBADR)); |
@@ -340,7 +340,7 @@ static void hw_usb_set_address(struct ci13xxx *ci, u8 value) | |||
340 | * | 340 | * |
341 | * This function returns an error code | 341 | * This function returns an error code |
342 | */ | 342 | */ |
343 | static int hw_usb_reset(struct ci13xxx *ci) | 343 | static int hw_usb_reset(struct ci_hdrc *ci) |
344 | { | 344 | { |
345 | hw_usb_set_address(ci, 0); | 345 | hw_usb_set_address(ci, 0); |
346 | 346 | ||
@@ -368,11 +368,60 @@ static int hw_usb_reset(struct ci13xxx *ci) | |||
368 | /****************************************************************************** | 368 | /****************************************************************************** |
369 | * UTIL block | 369 | * UTIL block |
370 | *****************************************************************************/ | 370 | *****************************************************************************/ |
371 | |||
372 | static int add_td_to_list(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq, | ||
373 | unsigned length) | ||
374 | { | ||
375 | int i; | ||
376 | u32 temp; | ||
377 | struct td_node *lastnode, *node = kzalloc(sizeof(struct td_node), | ||
378 | GFP_ATOMIC); | ||
379 | |||
380 | if (node == NULL) | ||
381 | return -ENOMEM; | ||
382 | |||
383 | node->ptr = dma_pool_alloc(hwep->td_pool, GFP_ATOMIC, | ||
384 | &node->dma); | ||
385 | if (node->ptr == NULL) { | ||
386 | kfree(node); | ||
387 | return -ENOMEM; | ||
388 | } | ||
389 | |||
390 | memset(node->ptr, 0, sizeof(struct ci_hw_td)); | ||
391 | node->ptr->token = cpu_to_le32(length << __ffs(TD_TOTAL_BYTES)); | ||
392 | node->ptr->token &= cpu_to_le32(TD_TOTAL_BYTES); | ||
393 | node->ptr->token |= cpu_to_le32(TD_STATUS_ACTIVE); | ||
394 | |||
395 | temp = (u32) (hwreq->req.dma + hwreq->req.actual); | ||
396 | if (length) { | ||
397 | node->ptr->page[0] = cpu_to_le32(temp); | ||
398 | for (i = 1; i < TD_PAGE_COUNT; i++) { | ||
399 | u32 page = temp + i * CI_HDRC_PAGE_SIZE; | ||
400 | page &= ~TD_RESERVED_MASK; | ||
401 | node->ptr->page[i] = cpu_to_le32(page); | ||
402 | } | ||
403 | } | ||
404 | |||
405 | hwreq->req.actual += length; | ||
406 | |||
407 | if (!list_empty(&hwreq->tds)) { | ||
408 | /* get the last entry */ | ||
409 | lastnode = list_entry(hwreq->tds.prev, | ||
410 | struct td_node, td); | ||
411 | lastnode->ptr->next = cpu_to_le32(node->dma); | ||
412 | } | ||
413 | |||
414 | INIT_LIST_HEAD(&node->td); | ||
415 | list_add_tail(&node->td, &hwreq->tds); | ||
416 | |||
417 | return 0; | ||
418 | } | ||
419 | |||
371 | /** | 420 | /** |
372 | * _usb_addr: calculates endpoint address from direction & number | 421 | * _usb_addr: calculates endpoint address from direction & number |
373 | * @ep: endpoint | 422 | * @ep: endpoint |
374 | */ | 423 | */ |
375 | static inline u8 _usb_addr(struct ci13xxx_ep *ep) | 424 | static inline u8 _usb_addr(struct ci_hw_ep *ep) |
376 | { | 425 | { |
377 | return ((ep->dir == TX) ? USB_ENDPOINT_DIR_MASK : 0) | ep->num; | 426 | return ((ep->dir == TX) ? USB_ENDPOINT_DIR_MASK : 0) | ep->num; |
378 | } | 427 | } |
@@ -380,75 +429,73 @@ static inline u8 _usb_addr(struct ci13xxx_ep *ep) | |||
380 | /** | 429 | /** |
381 | * _hardware_queue: configures a request at hardware level | 430 | * _hardware_queue: configures a request at hardware level |
382 | * @gadget: gadget | 431 | * @gadget: gadget |
383 | * @mEp: endpoint | 432 | * @hwep: endpoint |
384 | * | 433 | * |
385 | * This function returns an error code | 434 | * This function returns an error code |
386 | */ | 435 | */ |
387 | static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq) | 436 | static int _hardware_enqueue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq) |
388 | { | 437 | { |
389 | struct ci13xxx *ci = mEp->ci; | 438 | struct ci_hdrc *ci = hwep->ci; |
390 | unsigned i; | ||
391 | int ret = 0; | 439 | int ret = 0; |
392 | unsigned length = mReq->req.length; | 440 | unsigned rest = hwreq->req.length; |
441 | int pages = TD_PAGE_COUNT; | ||
442 | struct td_node *firstnode, *lastnode; | ||
393 | 443 | ||
394 | /* don't queue twice */ | 444 | /* don't queue twice */ |
395 | if (mReq->req.status == -EALREADY) | 445 | if (hwreq->req.status == -EALREADY) |
396 | return -EALREADY; | 446 | return -EALREADY; |
397 | 447 | ||
398 | mReq->req.status = -EALREADY; | 448 | hwreq->req.status = -EALREADY; |
399 | |||
400 | if (mReq->req.zero && length && (length % mEp->ep.maxpacket == 0)) { | ||
401 | mReq->zptr = dma_pool_alloc(mEp->td_pool, GFP_ATOMIC, | ||
402 | &mReq->zdma); | ||
403 | if (mReq->zptr == NULL) | ||
404 | return -ENOMEM; | ||
405 | 449 | ||
406 | memset(mReq->zptr, 0, sizeof(*mReq->zptr)); | 450 | ret = usb_gadget_map_request(&ci->gadget, &hwreq->req, hwep->dir); |
407 | mReq->zptr->next = cpu_to_le32(TD_TERMINATE); | ||
408 | mReq->zptr->token = cpu_to_le32(TD_STATUS_ACTIVE); | ||
409 | if (!mReq->req.no_interrupt) | ||
410 | mReq->zptr->token |= cpu_to_le32(TD_IOC); | ||
411 | } | ||
412 | ret = usb_gadget_map_request(&ci->gadget, &mReq->req, mEp->dir); | ||
413 | if (ret) | 451 | if (ret) |
414 | return ret; | 452 | return ret; |
415 | 453 | ||
416 | /* | 454 | /* |
417 | * TD configuration | 455 | * The first buffer could be not page aligned. |
418 | * TODO - handle requests which spawns into several TDs | 456 | * In that case we have to span into one extra td. |
419 | */ | 457 | */ |
420 | memset(mReq->ptr, 0, sizeof(*mReq->ptr)); | 458 | if (hwreq->req.dma % PAGE_SIZE) |
421 | mReq->ptr->token = cpu_to_le32(length << __ffs(TD_TOTAL_BYTES)); | 459 | pages--; |
422 | mReq->ptr->token &= cpu_to_le32(TD_TOTAL_BYTES); | 460 | |
423 | mReq->ptr->token |= cpu_to_le32(TD_STATUS_ACTIVE); | 461 | if (rest == 0) |
424 | if (mReq->zptr) { | 462 | add_td_to_list(hwep, hwreq, 0); |
425 | mReq->ptr->next = cpu_to_le32(mReq->zdma); | 463 | |
426 | } else { | 464 | while (rest > 0) { |
427 | mReq->ptr->next = cpu_to_le32(TD_TERMINATE); | 465 | unsigned count = min(hwreq->req.length - hwreq->req.actual, |
428 | if (!mReq->req.no_interrupt) | 466 | (unsigned)(pages * CI_HDRC_PAGE_SIZE)); |
429 | mReq->ptr->token |= cpu_to_le32(TD_IOC); | 467 | add_td_to_list(hwep, hwreq, count); |
430 | } | 468 | rest -= count; |
431 | mReq->ptr->page[0] = cpu_to_le32(mReq->req.dma); | ||
432 | for (i = 1; i < TD_PAGE_COUNT; i++) { | ||
433 | u32 page = mReq->req.dma + i * CI13XXX_PAGE_SIZE; | ||
434 | page &= ~TD_RESERVED_MASK; | ||
435 | mReq->ptr->page[i] = cpu_to_le32(page); | ||
436 | } | 469 | } |
437 | 470 | ||
471 | if (hwreq->req.zero && hwreq->req.length | ||
472 | && (hwreq->req.length % hwep->ep.maxpacket == 0)) | ||
473 | add_td_to_list(hwep, hwreq, 0); | ||
474 | |||
475 | firstnode = list_first_entry(&hwreq->tds, struct td_node, td); | ||
476 | |||
477 | lastnode = list_entry(hwreq->tds.prev, | ||
478 | struct td_node, td); | ||
479 | |||
480 | lastnode->ptr->next = cpu_to_le32(TD_TERMINATE); | ||
481 | if (!hwreq->req.no_interrupt) | ||
482 | lastnode->ptr->token |= cpu_to_le32(TD_IOC); | ||
438 | wmb(); | 483 | wmb(); |
439 | 484 | ||
440 | if (!list_empty(&mEp->qh.queue)) { | 485 | hwreq->req.actual = 0; |
441 | struct ci13xxx_req *mReqPrev; | 486 | if (!list_empty(&hwep->qh.queue)) { |
442 | int n = hw_ep_bit(mEp->num, mEp->dir); | 487 | struct ci_hw_req *hwreqprev; |
488 | int n = hw_ep_bit(hwep->num, hwep->dir); | ||
443 | int tmp_stat; | 489 | int tmp_stat; |
444 | u32 next = mReq->dma & TD_ADDR_MASK; | 490 | struct td_node *prevlastnode; |
445 | 491 | u32 next = firstnode->dma & TD_ADDR_MASK; | |
446 | mReqPrev = list_entry(mEp->qh.queue.prev, | 492 | |
447 | struct ci13xxx_req, queue); | 493 | hwreqprev = list_entry(hwep->qh.queue.prev, |
448 | if (mReqPrev->zptr) | 494 | struct ci_hw_req, queue); |
449 | mReqPrev->zptr->next = cpu_to_le32(next); | 495 | prevlastnode = list_entry(hwreqprev->tds.prev, |
450 | else | 496 | struct td_node, td); |
451 | mReqPrev->ptr->next = cpu_to_le32(next); | 497 | |
498 | prevlastnode->ptr->next = cpu_to_le32(next); | ||
452 | wmb(); | 499 | wmb(); |
453 | if (hw_read(ci, OP_ENDPTPRIME, BIT(n))) | 500 | if (hw_read(ci, OP_ENDPTPRIME, BIT(n))) |
454 | goto done; | 501 | goto done; |
@@ -462,99 +509,152 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq) | |||
462 | } | 509 | } |
463 | 510 | ||
464 | /* QH configuration */ | 511 | /* QH configuration */ |
465 | mEp->qh.ptr->td.next = cpu_to_le32(mReq->dma); /* TERMINATE = 0 */ | 512 | hwep->qh.ptr->td.next = cpu_to_le32(firstnode->dma); |
466 | mEp->qh.ptr->td.token &= | 513 | hwep->qh.ptr->td.token &= |
467 | cpu_to_le32(~(TD_STATUS_HALTED|TD_STATUS_ACTIVE)); | 514 | cpu_to_le32(~(TD_STATUS_HALTED|TD_STATUS_ACTIVE)); |
468 | 515 | ||
516 | if (hwep->type == USB_ENDPOINT_XFER_ISOC) { | ||
517 | u32 mul = hwreq->req.length / hwep->ep.maxpacket; | ||
518 | |||
519 | if (hwreq->req.length % hwep->ep.maxpacket) | ||
520 | mul++; | ||
521 | hwep->qh.ptr->cap |= mul << __ffs(QH_MULT); | ||
522 | } | ||
523 | |||
469 | wmb(); /* synchronize before ep prime */ | 524 | wmb(); /* synchronize before ep prime */ |
470 | 525 | ||
471 | ret = hw_ep_prime(ci, mEp->num, mEp->dir, | 526 | ret = hw_ep_prime(ci, hwep->num, hwep->dir, |
472 | mEp->type == USB_ENDPOINT_XFER_CONTROL); | 527 | hwep->type == USB_ENDPOINT_XFER_CONTROL); |
473 | done: | 528 | done: |
474 | return ret; | 529 | return ret; |
475 | } | 530 | } |
476 | 531 | ||
532 | /* | ||
533 | * free_pending_td: remove a pending request for the endpoint | ||
534 | * @hwep: endpoint | ||
535 | */ | ||
536 | static void free_pending_td(struct ci_hw_ep *hwep) | ||
537 | { | ||
538 | struct td_node *pending = hwep->pending_td; | ||
539 | |||
540 | dma_pool_free(hwep->td_pool, pending->ptr, pending->dma); | ||
541 | hwep->pending_td = NULL; | ||
542 | kfree(pending); | ||
543 | } | ||
544 | |||
477 | /** | 545 | /** |
478 | * _hardware_dequeue: handles a request at hardware level | 546 | * _hardware_dequeue: handles a request at hardware level |
479 | * @gadget: gadget | 547 | * @gadget: gadget |
480 | * @mEp: endpoint | 548 | * @hwep: endpoint |
481 | * | 549 | * |
482 | * This function returns an error code | 550 | * This function returns an error code |
483 | */ | 551 | */ |
484 | static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq) | 552 | static int _hardware_dequeue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq) |
485 | { | 553 | { |
486 | u32 tmptoken = le32_to_cpu(mReq->ptr->token); | 554 | u32 tmptoken; |
555 | struct td_node *node, *tmpnode; | ||
556 | unsigned remaining_length; | ||
557 | unsigned actual = hwreq->req.length; | ||
487 | 558 | ||
488 | if (mReq->req.status != -EALREADY) | 559 | if (hwreq->req.status != -EALREADY) |
489 | return -EINVAL; | 560 | return -EINVAL; |
490 | 561 | ||
491 | if ((TD_STATUS_ACTIVE & tmptoken) != 0) | 562 | hwreq->req.status = 0; |
492 | return -EBUSY; | ||
493 | 563 | ||
494 | if (mReq->zptr) { | 564 | list_for_each_entry_safe(node, tmpnode, &hwreq->tds, td) { |
495 | if ((cpu_to_le32(TD_STATUS_ACTIVE) & mReq->zptr->token) != 0) | 565 | tmptoken = le32_to_cpu(node->ptr->token); |
566 | if ((TD_STATUS_ACTIVE & tmptoken) != 0) { | ||
567 | hwreq->req.status = -EALREADY; | ||
496 | return -EBUSY; | 568 | return -EBUSY; |
497 | dma_pool_free(mEp->td_pool, mReq->zptr, mReq->zdma); | 569 | } |
498 | mReq->zptr = NULL; | ||
499 | } | ||
500 | 570 | ||
501 | mReq->req.status = 0; | 571 | remaining_length = (tmptoken & TD_TOTAL_BYTES); |
572 | remaining_length >>= __ffs(TD_TOTAL_BYTES); | ||
573 | actual -= remaining_length; | ||
574 | |||
575 | hwreq->req.status = tmptoken & TD_STATUS; | ||
576 | if ((TD_STATUS_HALTED & hwreq->req.status)) { | ||
577 | hwreq->req.status = -EPIPE; | ||
578 | break; | ||
579 | } else if ((TD_STATUS_DT_ERR & hwreq->req.status)) { | ||
580 | hwreq->req.status = -EPROTO; | ||
581 | break; | ||
582 | } else if ((TD_STATUS_TR_ERR & hwreq->req.status)) { | ||
583 | hwreq->req.status = -EILSEQ; | ||
584 | break; | ||
585 | } | ||
502 | 586 | ||
503 | usb_gadget_unmap_request(&mEp->ci->gadget, &mReq->req, mEp->dir); | 587 | if (remaining_length) { |
588 | if (hwep->dir) { | ||
589 | hwreq->req.status = -EPROTO; | ||
590 | break; | ||
591 | } | ||
592 | } | ||
593 | /* | ||
594 | * As the hardware could still address the freed td | ||
595 | * which will run the udc unusable, the cleanup of the | ||
596 | * td has to be delayed by one. | ||
597 | */ | ||
598 | if (hwep->pending_td) | ||
599 | free_pending_td(hwep); | ||
504 | 600 | ||
505 | mReq->req.status = tmptoken & TD_STATUS; | 601 | hwep->pending_td = node; |
506 | if ((TD_STATUS_HALTED & mReq->req.status) != 0) | 602 | list_del_init(&node->td); |
507 | mReq->req.status = -1; | 603 | } |
508 | else if ((TD_STATUS_DT_ERR & mReq->req.status) != 0) | ||
509 | mReq->req.status = -1; | ||
510 | else if ((TD_STATUS_TR_ERR & mReq->req.status) != 0) | ||
511 | mReq->req.status = -1; | ||
512 | 604 | ||
513 | mReq->req.actual = tmptoken & TD_TOTAL_BYTES; | 605 | usb_gadget_unmap_request(&hwep->ci->gadget, &hwreq->req, hwep->dir); |
514 | mReq->req.actual >>= __ffs(TD_TOTAL_BYTES); | ||
515 | mReq->req.actual = mReq->req.length - mReq->req.actual; | ||
516 | mReq->req.actual = mReq->req.status ? 0 : mReq->req.actual; | ||
517 | 606 | ||
518 | return mReq->req.actual; | 607 | hwreq->req.actual += actual; |
608 | |||
609 | if (hwreq->req.status) | ||
610 | return hwreq->req.status; | ||
611 | |||
612 | return hwreq->req.actual; | ||
519 | } | 613 | } |
520 | 614 | ||
521 | /** | 615 | /** |
522 | * _ep_nuke: dequeues all endpoint requests | 616 | * _ep_nuke: dequeues all endpoint requests |
523 | * @mEp: endpoint | 617 | * @hwep: endpoint |
524 | * | 618 | * |
525 | * This function returns an error code | 619 | * This function returns an error code |
526 | * Caller must hold lock | 620 | * Caller must hold lock |
527 | */ | 621 | */ |
528 | static int _ep_nuke(struct ci13xxx_ep *mEp) | 622 | static int _ep_nuke(struct ci_hw_ep *hwep) |
529 | __releases(mEp->lock) | 623 | __releases(hwep->lock) |
530 | __acquires(mEp->lock) | 624 | __acquires(hwep->lock) |
531 | { | 625 | { |
532 | if (mEp == NULL) | 626 | struct td_node *node, *tmpnode; |
627 | if (hwep == NULL) | ||
533 | return -EINVAL; | 628 | return -EINVAL; |
534 | 629 | ||
535 | hw_ep_flush(mEp->ci, mEp->num, mEp->dir); | 630 | hw_ep_flush(hwep->ci, hwep->num, hwep->dir); |
536 | 631 | ||
537 | while (!list_empty(&mEp->qh.queue)) { | 632 | while (!list_empty(&hwep->qh.queue)) { |
538 | 633 | ||
539 | /* pop oldest request */ | 634 | /* pop oldest request */ |
540 | struct ci13xxx_req *mReq = \ | 635 | struct ci_hw_req *hwreq = list_entry(hwep->qh.queue.next, |
541 | list_entry(mEp->qh.queue.next, | 636 | struct ci_hw_req, queue); |
542 | struct ci13xxx_req, queue); | 637 | |
543 | 638 | list_for_each_entry_safe(node, tmpnode, &hwreq->tds, td) { | |
544 | if (mReq->zptr) { | 639 | dma_pool_free(hwep->td_pool, node->ptr, node->dma); |
545 | dma_pool_free(mEp->td_pool, mReq->zptr, mReq->zdma); | 640 | list_del_init(&node->td); |
546 | mReq->zptr = NULL; | 641 | node->ptr = NULL; |
642 | kfree(node); | ||
547 | } | 643 | } |
548 | 644 | ||
549 | list_del_init(&mReq->queue); | 645 | list_del_init(&hwreq->queue); |
550 | mReq->req.status = -ESHUTDOWN; | 646 | hwreq->req.status = -ESHUTDOWN; |
551 | 647 | ||
552 | if (mReq->req.complete != NULL) { | 648 | if (hwreq->req.complete != NULL) { |
553 | spin_unlock(mEp->lock); | 649 | spin_unlock(hwep->lock); |
554 | mReq->req.complete(&mEp->ep, &mReq->req); | 650 | hwreq->req.complete(&hwep->ep, &hwreq->req); |
555 | spin_lock(mEp->lock); | 651 | spin_lock(hwep->lock); |
556 | } | 652 | } |
557 | } | 653 | } |
654 | |||
655 | if (hwep->pending_td) | ||
656 | free_pending_td(hwep); | ||
657 | |||
558 | return 0; | 658 | return 0; |
559 | } | 659 | } |
560 | 660 | ||
@@ -567,7 +667,7 @@ __acquires(mEp->lock) | |||
567 | static int _gadget_stop_activity(struct usb_gadget *gadget) | 667 | static int _gadget_stop_activity(struct usb_gadget *gadget) |
568 | { | 668 | { |
569 | struct usb_ep *ep; | 669 | struct usb_ep *ep; |
570 | struct ci13xxx *ci = container_of(gadget, struct ci13xxx, gadget); | 670 | struct ci_hdrc *ci = container_of(gadget, struct ci_hdrc, gadget); |
571 | unsigned long flags; | 671 | unsigned long flags; |
572 | 672 | ||
573 | spin_lock_irqsave(&ci->lock, flags); | 673 | spin_lock_irqsave(&ci->lock, flags); |
@@ -608,7 +708,7 @@ static int _gadget_stop_activity(struct usb_gadget *gadget) | |||
608 | * | 708 | * |
609 | * This function resets USB engine after a bus reset occurred | 709 | * This function resets USB engine after a bus reset occurred |
610 | */ | 710 | */ |
611 | static void isr_reset_handler(struct ci13xxx *ci) | 711 | static void isr_reset_handler(struct ci_hdrc *ci) |
612 | __releases(ci->lock) | 712 | __releases(ci->lock) |
613 | __acquires(ci->lock) | 713 | __acquires(ci->lock) |
614 | { | 714 | { |
@@ -658,47 +758,48 @@ static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req) | |||
658 | static int _ep_queue(struct usb_ep *ep, struct usb_request *req, | 758 | static int _ep_queue(struct usb_ep *ep, struct usb_request *req, |
659 | gfp_t __maybe_unused gfp_flags) | 759 | gfp_t __maybe_unused gfp_flags) |
660 | { | 760 | { |
661 | struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); | 761 | struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); |
662 | struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req); | 762 | struct ci_hw_req *hwreq = container_of(req, struct ci_hw_req, req); |
663 | struct ci13xxx *ci = mEp->ci; | 763 | struct ci_hdrc *ci = hwep->ci; |
664 | int retval = 0; | 764 | int retval = 0; |
665 | 765 | ||
666 | if (ep == NULL || req == NULL || mEp->ep.desc == NULL) | 766 | if (ep == NULL || req == NULL || hwep->ep.desc == NULL) |
667 | return -EINVAL; | 767 | return -EINVAL; |
668 | 768 | ||
669 | if (mEp->type == USB_ENDPOINT_XFER_CONTROL) { | 769 | if (hwep->type == USB_ENDPOINT_XFER_CONTROL) { |
670 | if (req->length) | 770 | if (req->length) |
671 | mEp = (ci->ep0_dir == RX) ? | 771 | hwep = (ci->ep0_dir == RX) ? |
672 | ci->ep0out : ci->ep0in; | 772 | ci->ep0out : ci->ep0in; |
673 | if (!list_empty(&mEp->qh.queue)) { | 773 | if (!list_empty(&hwep->qh.queue)) { |
674 | _ep_nuke(mEp); | 774 | _ep_nuke(hwep); |
675 | retval = -EOVERFLOW; | 775 | retval = -EOVERFLOW; |
676 | dev_warn(mEp->ci->dev, "endpoint ctrl %X nuked\n", | 776 | dev_warn(hwep->ci->dev, "endpoint ctrl %X nuked\n", |
677 | _usb_addr(mEp)); | 777 | _usb_addr(hwep)); |
678 | } | 778 | } |
679 | } | 779 | } |
680 | 780 | ||
681 | /* first nuke then test link, e.g. previous status has not sent */ | 781 | if (usb_endpoint_xfer_isoc(hwep->ep.desc) && |
682 | if (!list_empty(&mReq->queue)) { | 782 | hwreq->req.length > (1 + hwep->ep.mult) * hwep->ep.maxpacket) { |
683 | dev_err(mEp->ci->dev, "request already in queue\n"); | 783 | dev_err(hwep->ci->dev, "request length too big for isochronous\n"); |
684 | return -EBUSY; | 784 | return -EMSGSIZE; |
685 | } | 785 | } |
686 | 786 | ||
687 | if (req->length > (TD_PAGE_COUNT - 1) * CI13XXX_PAGE_SIZE) { | 787 | /* first nuke then test link, e.g. previous status has not sent */ |
688 | dev_err(mEp->ci->dev, "request bigger than one td\n"); | 788 | if (!list_empty(&hwreq->queue)) { |
689 | return -EMSGSIZE; | 789 | dev_err(hwep->ci->dev, "request already in queue\n"); |
790 | return -EBUSY; | ||
690 | } | 791 | } |
691 | 792 | ||
692 | /* push request */ | 793 | /* push request */ |
693 | mReq->req.status = -EINPROGRESS; | 794 | hwreq->req.status = -EINPROGRESS; |
694 | mReq->req.actual = 0; | 795 | hwreq->req.actual = 0; |
695 | 796 | ||
696 | retval = _hardware_enqueue(mEp, mReq); | 797 | retval = _hardware_enqueue(hwep, hwreq); |
697 | 798 | ||
698 | if (retval == -EALREADY) | 799 | if (retval == -EALREADY) |
699 | retval = 0; | 800 | retval = 0; |
700 | if (!retval) | 801 | if (!retval) |
701 | list_add_tail(&mReq->queue, &mEp->qh.queue); | 802 | list_add_tail(&hwreq->queue, &hwep->qh.queue); |
702 | 803 | ||
703 | return retval; | 804 | return retval; |
704 | } | 805 | } |
@@ -710,22 +811,22 @@ static int _ep_queue(struct usb_ep *ep, struct usb_request *req, | |||
710 | * | 811 | * |
711 | * This function returns an error code | 812 | * This function returns an error code |
712 | */ | 813 | */ |
713 | static int isr_get_status_response(struct ci13xxx *ci, | 814 | static int isr_get_status_response(struct ci_hdrc *ci, |
714 | struct usb_ctrlrequest *setup) | 815 | struct usb_ctrlrequest *setup) |
715 | __releases(mEp->lock) | 816 | __releases(hwep->lock) |
716 | __acquires(mEp->lock) | 817 | __acquires(hwep->lock) |
717 | { | 818 | { |
718 | struct ci13xxx_ep *mEp = ci->ep0in; | 819 | struct ci_hw_ep *hwep = ci->ep0in; |
719 | struct usb_request *req = NULL; | 820 | struct usb_request *req = NULL; |
720 | gfp_t gfp_flags = GFP_ATOMIC; | 821 | gfp_t gfp_flags = GFP_ATOMIC; |
721 | int dir, num, retval; | 822 | int dir, num, retval; |
722 | 823 | ||
723 | if (mEp == NULL || setup == NULL) | 824 | if (hwep == NULL || setup == NULL) |
724 | return -EINVAL; | 825 | return -EINVAL; |
725 | 826 | ||
726 | spin_unlock(mEp->lock); | 827 | spin_unlock(hwep->lock); |
727 | req = usb_ep_alloc_request(&mEp->ep, gfp_flags); | 828 | req = usb_ep_alloc_request(&hwep->ep, gfp_flags); |
728 | spin_lock(mEp->lock); | 829 | spin_lock(hwep->lock); |
729 | if (req == NULL) | 830 | if (req == NULL) |
730 | return -ENOMEM; | 831 | return -ENOMEM; |
731 | 832 | ||
@@ -750,7 +851,7 @@ __acquires(mEp->lock) | |||
750 | } | 851 | } |
751 | /* else do nothing; reserved for future use */ | 852 | /* else do nothing; reserved for future use */ |
752 | 853 | ||
753 | retval = _ep_queue(&mEp->ep, req, gfp_flags); | 854 | retval = _ep_queue(&hwep->ep, req, gfp_flags); |
754 | if (retval) | 855 | if (retval) |
755 | goto err_free_buf; | 856 | goto err_free_buf; |
756 | 857 | ||
@@ -759,9 +860,9 @@ __acquires(mEp->lock) | |||
759 | err_free_buf: | 860 | err_free_buf: |
760 | kfree(req->buf); | 861 | kfree(req->buf); |
761 | err_free_req: | 862 | err_free_req: |
762 | spin_unlock(mEp->lock); | 863 | spin_unlock(hwep->lock); |
763 | usb_ep_free_request(&mEp->ep, req); | 864 | usb_ep_free_request(&hwep->ep, req); |
764 | spin_lock(mEp->lock); | 865 | spin_lock(hwep->lock); |
765 | return retval; | 866 | return retval; |
766 | } | 867 | } |
767 | 868 | ||
@@ -776,7 +877,7 @@ __acquires(mEp->lock) | |||
776 | static void | 877 | static void |
777 | isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req) | 878 | isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req) |
778 | { | 879 | { |
779 | struct ci13xxx *ci = req->context; | 880 | struct ci_hdrc *ci = req->context; |
780 | unsigned long flags; | 881 | unsigned long flags; |
781 | 882 | ||
782 | if (ci->setaddr) { | 883 | if (ci->setaddr) { |
@@ -796,48 +897,48 @@ isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req) | |||
796 | * | 897 | * |
797 | * This function returns an error code | 898 | * This function returns an error code |
798 | */ | 899 | */ |
799 | static int isr_setup_status_phase(struct ci13xxx *ci) | 900 | static int isr_setup_status_phase(struct ci_hdrc *ci) |
800 | { | 901 | { |
801 | int retval; | 902 | int retval; |
802 | struct ci13xxx_ep *mEp; | 903 | struct ci_hw_ep *hwep; |
803 | 904 | ||
804 | mEp = (ci->ep0_dir == TX) ? ci->ep0out : ci->ep0in; | 905 | hwep = (ci->ep0_dir == TX) ? ci->ep0out : ci->ep0in; |
805 | ci->status->context = ci; | 906 | ci->status->context = ci; |
806 | ci->status->complete = isr_setup_status_complete; | 907 | ci->status->complete = isr_setup_status_complete; |
807 | 908 | ||
808 | retval = _ep_queue(&mEp->ep, ci->status, GFP_ATOMIC); | 909 | retval = _ep_queue(&hwep->ep, ci->status, GFP_ATOMIC); |
809 | 910 | ||
810 | return retval; | 911 | return retval; |
811 | } | 912 | } |
812 | 913 | ||
813 | /** | 914 | /** |
814 | * isr_tr_complete_low: transaction complete low level handler | 915 | * isr_tr_complete_low: transaction complete low level handler |
815 | * @mEp: endpoint | 916 | * @hwep: endpoint |
816 | * | 917 | * |
817 | * This function returns an error code | 918 | * This function returns an error code |
818 | * Caller must hold lock | 919 | * Caller must hold lock |
819 | */ | 920 | */ |
820 | static int isr_tr_complete_low(struct ci13xxx_ep *mEp) | 921 | static int isr_tr_complete_low(struct ci_hw_ep *hwep) |
821 | __releases(mEp->lock) | 922 | __releases(hwep->lock) |
822 | __acquires(mEp->lock) | 923 | __acquires(hwep->lock) |
823 | { | 924 | { |
824 | struct ci13xxx_req *mReq, *mReqTemp; | 925 | struct ci_hw_req *hwreq, *hwreqtemp; |
825 | struct ci13xxx_ep *mEpTemp = mEp; | 926 | struct ci_hw_ep *hweptemp = hwep; |
826 | int retval = 0; | 927 | int retval = 0; |
827 | 928 | ||
828 | list_for_each_entry_safe(mReq, mReqTemp, &mEp->qh.queue, | 929 | list_for_each_entry_safe(hwreq, hwreqtemp, &hwep->qh.queue, |
829 | queue) { | 930 | queue) { |
830 | retval = _hardware_dequeue(mEp, mReq); | 931 | retval = _hardware_dequeue(hwep, hwreq); |
831 | if (retval < 0) | 932 | if (retval < 0) |
832 | break; | 933 | break; |
833 | list_del_init(&mReq->queue); | 934 | list_del_init(&hwreq->queue); |
834 | if (mReq->req.complete != NULL) { | 935 | if (hwreq->req.complete != NULL) { |
835 | spin_unlock(mEp->lock); | 936 | spin_unlock(hwep->lock); |
836 | if ((mEp->type == USB_ENDPOINT_XFER_CONTROL) && | 937 | if ((hwep->type == USB_ENDPOINT_XFER_CONTROL) && |
837 | mReq->req.length) | 938 | hwreq->req.length) |
838 | mEpTemp = mEp->ci->ep0in; | 939 | hweptemp = hwep->ci->ep0in; |
839 | mReq->req.complete(&mEpTemp->ep, &mReq->req); | 940 | hwreq->req.complete(&hweptemp->ep, &hwreq->req); |
840 | spin_lock(mEp->lock); | 941 | spin_lock(hwep->lock); |
841 | } | 942 | } |
842 | } | 943 | } |
843 | 944 | ||
@@ -853,7 +954,7 @@ __acquires(mEp->lock) | |||
853 | * | 954 | * |
854 | * This function handles traffic events | 955 | * This function handles traffic events |
855 | */ | 956 | */ |
856 | static void isr_tr_complete_handler(struct ci13xxx *ci) | 957 | static void isr_tr_complete_handler(struct ci_hdrc *ci) |
857 | __releases(ci->lock) | 958 | __releases(ci->lock) |
858 | __acquires(ci->lock) | 959 | __acquires(ci->lock) |
859 | { | 960 | { |
@@ -861,21 +962,21 @@ __acquires(ci->lock) | |||
861 | u8 tmode = 0; | 962 | u8 tmode = 0; |
862 | 963 | ||
863 | for (i = 0; i < ci->hw_ep_max; i++) { | 964 | for (i = 0; i < ci->hw_ep_max; i++) { |
864 | struct ci13xxx_ep *mEp = &ci->ci13xxx_ep[i]; | 965 | struct ci_hw_ep *hwep = &ci->ci_hw_ep[i]; |
865 | int type, num, dir, err = -EINVAL; | 966 | int type, num, dir, err = -EINVAL; |
866 | struct usb_ctrlrequest req; | 967 | struct usb_ctrlrequest req; |
867 | 968 | ||
868 | if (mEp->ep.desc == NULL) | 969 | if (hwep->ep.desc == NULL) |
869 | continue; /* not configured */ | 970 | continue; /* not configured */ |
870 | 971 | ||
871 | if (hw_test_and_clear_complete(ci, i)) { | 972 | if (hw_test_and_clear_complete(ci, i)) { |
872 | err = isr_tr_complete_low(mEp); | 973 | err = isr_tr_complete_low(hwep); |
873 | if (mEp->type == USB_ENDPOINT_XFER_CONTROL) { | 974 | if (hwep->type == USB_ENDPOINT_XFER_CONTROL) { |
874 | if (err > 0) /* needs status phase */ | 975 | if (err > 0) /* needs status phase */ |
875 | err = isr_setup_status_phase(ci); | 976 | err = isr_setup_status_phase(ci); |
876 | if (err < 0) { | 977 | if (err < 0) { |
877 | spin_unlock(&ci->lock); | 978 | spin_unlock(&ci->lock); |
878 | if (usb_ep_set_halt(&mEp->ep)) | 979 | if (usb_ep_set_halt(&hwep->ep)) |
879 | dev_err(ci->dev, | 980 | dev_err(ci->dev, |
880 | "error: ep_set_halt\n"); | 981 | "error: ep_set_halt\n"); |
881 | spin_lock(&ci->lock); | 982 | spin_lock(&ci->lock); |
@@ -883,7 +984,7 @@ __acquires(ci->lock) | |||
883 | } | 984 | } |
884 | } | 985 | } |
885 | 986 | ||
886 | if (mEp->type != USB_ENDPOINT_XFER_CONTROL || | 987 | if (hwep->type != USB_ENDPOINT_XFER_CONTROL || |
887 | !hw_test_and_clear_setup_status(ci, i)) | 988 | !hw_test_and_clear_setup_status(ci, i)) |
888 | continue; | 989 | continue; |
889 | 990 | ||
@@ -902,7 +1003,7 @@ __acquires(ci->lock) | |||
902 | /* read_setup_packet */ | 1003 | /* read_setup_packet */ |
903 | do { | 1004 | do { |
904 | hw_test_and_set_setup_guard(ci); | 1005 | hw_test_and_set_setup_guard(ci); |
905 | memcpy(&req, &mEp->qh.ptr->setup, sizeof(req)); | 1006 | memcpy(&req, &hwep->qh.ptr->setup, sizeof(req)); |
906 | } while (!hw_test_and_clear_setup_guard(ci)); | 1007 | } while (!hw_test_and_clear_setup_guard(ci)); |
907 | 1008 | ||
908 | type = req.bRequestType; | 1009 | type = req.bRequestType; |
@@ -921,10 +1022,10 @@ __acquires(ci->lock) | |||
921 | num &= USB_ENDPOINT_NUMBER_MASK; | 1022 | num &= USB_ENDPOINT_NUMBER_MASK; |
922 | if (dir) /* TX */ | 1023 | if (dir) /* TX */ |
923 | num += ci->hw_ep_max/2; | 1024 | num += ci->hw_ep_max/2; |
924 | if (!ci->ci13xxx_ep[num].wedge) { | 1025 | if (!ci->ci_hw_ep[num].wedge) { |
925 | spin_unlock(&ci->lock); | 1026 | spin_unlock(&ci->lock); |
926 | err = usb_ep_clear_halt( | 1027 | err = usb_ep_clear_halt( |
927 | &ci->ci13xxx_ep[num].ep); | 1028 | &ci->ci_hw_ep[num].ep); |
928 | spin_lock(&ci->lock); | 1029 | spin_lock(&ci->lock); |
929 | if (err) | 1030 | if (err) |
930 | break; | 1031 | break; |
@@ -974,7 +1075,7 @@ __acquires(ci->lock) | |||
974 | num += ci->hw_ep_max/2; | 1075 | num += ci->hw_ep_max/2; |
975 | 1076 | ||
976 | spin_unlock(&ci->lock); | 1077 | spin_unlock(&ci->lock); |
977 | err = usb_ep_set_halt(&ci->ci13xxx_ep[num].ep); | 1078 | err = usb_ep_set_halt(&ci->ci_hw_ep[num].ep); |
978 | spin_lock(&ci->lock); | 1079 | spin_lock(&ci->lock); |
979 | if (!err) | 1080 | if (!err) |
980 | isr_setup_status_phase(ci); | 1081 | isr_setup_status_phase(ci); |
@@ -1021,7 +1122,7 @@ delegate: | |||
1021 | 1122 | ||
1022 | if (err < 0) { | 1123 | if (err < 0) { |
1023 | spin_unlock(&ci->lock); | 1124 | spin_unlock(&ci->lock); |
1024 | if (usb_ep_set_halt(&mEp->ep)) | 1125 | if (usb_ep_set_halt(&hwep->ep)) |
1025 | dev_err(ci->dev, "error: ep_set_halt\n"); | 1126 | dev_err(ci->dev, "error: ep_set_halt\n"); |
1026 | spin_lock(&ci->lock); | 1127 | spin_lock(&ci->lock); |
1027 | } | 1128 | } |
@@ -1039,7 +1140,7 @@ delegate: | |||
1039 | static int ep_enable(struct usb_ep *ep, | 1140 | static int ep_enable(struct usb_ep *ep, |
1040 | const struct usb_endpoint_descriptor *desc) | 1141 | const struct usb_endpoint_descriptor *desc) |
1041 | { | 1142 | { |
1042 | struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); | 1143 | struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); |
1043 | int retval = 0; | 1144 | int retval = 0; |
1044 | unsigned long flags; | 1145 | unsigned long flags; |
1045 | u32 cap = 0; | 1146 | u32 cap = 0; |
@@ -1047,39 +1148,41 @@ static int ep_enable(struct usb_ep *ep, | |||
1047 | if (ep == NULL || desc == NULL) | 1148 | if (ep == NULL || desc == NULL) |
1048 | return -EINVAL; | 1149 | return -EINVAL; |
1049 | 1150 | ||
1050 | spin_lock_irqsave(mEp->lock, flags); | 1151 | spin_lock_irqsave(hwep->lock, flags); |
1051 | 1152 | ||
1052 | /* only internal SW should enable ctrl endpts */ | 1153 | /* only internal SW should enable ctrl endpts */ |
1053 | 1154 | ||
1054 | mEp->ep.desc = desc; | 1155 | hwep->ep.desc = desc; |
1055 | 1156 | ||
1056 | if (!list_empty(&mEp->qh.queue)) | 1157 | if (!list_empty(&hwep->qh.queue)) |
1057 | dev_warn(mEp->ci->dev, "enabling a non-empty endpoint!\n"); | 1158 | dev_warn(hwep->ci->dev, "enabling a non-empty endpoint!\n"); |
1058 | 1159 | ||
1059 | mEp->dir = usb_endpoint_dir_in(desc) ? TX : RX; | 1160 | hwep->dir = usb_endpoint_dir_in(desc) ? TX : RX; |
1060 | mEp->num = usb_endpoint_num(desc); | 1161 | hwep->num = usb_endpoint_num(desc); |
1061 | mEp->type = usb_endpoint_type(desc); | 1162 | hwep->type = usb_endpoint_type(desc); |
1062 | 1163 | ||
1063 | mEp->ep.maxpacket = usb_endpoint_maxp(desc); | 1164 | hwep->ep.maxpacket = usb_endpoint_maxp(desc) & 0x07ff; |
1165 | hwep->ep.mult = QH_ISO_MULT(usb_endpoint_maxp(desc)); | ||
1064 | 1166 | ||
1065 | if (mEp->type == USB_ENDPOINT_XFER_CONTROL) | 1167 | if (hwep->type == USB_ENDPOINT_XFER_CONTROL) |
1066 | cap |= QH_IOS; | 1168 | cap |= QH_IOS; |
1067 | if (mEp->num) | 1169 | if (hwep->num) |
1068 | cap |= QH_ZLT; | 1170 | cap |= QH_ZLT; |
1069 | cap |= (mEp->ep.maxpacket << __ffs(QH_MAX_PKT)) & QH_MAX_PKT; | 1171 | cap |= (hwep->ep.maxpacket << __ffs(QH_MAX_PKT)) & QH_MAX_PKT; |
1070 | 1172 | ||
1071 | mEp->qh.ptr->cap = cpu_to_le32(cap); | 1173 | hwep->qh.ptr->cap = cpu_to_le32(cap); |
1072 | 1174 | ||
1073 | mEp->qh.ptr->td.next |= cpu_to_le32(TD_TERMINATE); /* needed? */ | 1175 | hwep->qh.ptr->td.next |= cpu_to_le32(TD_TERMINATE); /* needed? */ |
1074 | 1176 | ||
1075 | /* | 1177 | /* |
1076 | * Enable endpoints in the HW other than ep0 as ep0 | 1178 | * Enable endpoints in the HW other than ep0 as ep0 |
1077 | * is always enabled | 1179 | * is always enabled |
1078 | */ | 1180 | */ |
1079 | if (mEp->num) | 1181 | if (hwep->num) |
1080 | retval |= hw_ep_enable(mEp->ci, mEp->num, mEp->dir, mEp->type); | 1182 | retval |= hw_ep_enable(hwep->ci, hwep->num, hwep->dir, |
1183 | hwep->type); | ||
1081 | 1184 | ||
1082 | spin_unlock_irqrestore(mEp->lock, flags); | 1185 | spin_unlock_irqrestore(hwep->lock, flags); |
1083 | return retval; | 1186 | return retval; |
1084 | } | 1187 | } |
1085 | 1188 | ||
@@ -1090,32 +1193,32 @@ static int ep_enable(struct usb_ep *ep, | |||
1090 | */ | 1193 | */ |
1091 | static int ep_disable(struct usb_ep *ep) | 1194 | static int ep_disable(struct usb_ep *ep) |
1092 | { | 1195 | { |
1093 | struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); | 1196 | struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); |
1094 | int direction, retval = 0; | 1197 | int direction, retval = 0; |
1095 | unsigned long flags; | 1198 | unsigned long flags; |
1096 | 1199 | ||
1097 | if (ep == NULL) | 1200 | if (ep == NULL) |
1098 | return -EINVAL; | 1201 | return -EINVAL; |
1099 | else if (mEp->ep.desc == NULL) | 1202 | else if (hwep->ep.desc == NULL) |
1100 | return -EBUSY; | 1203 | return -EBUSY; |
1101 | 1204 | ||
1102 | spin_lock_irqsave(mEp->lock, flags); | 1205 | spin_lock_irqsave(hwep->lock, flags); |
1103 | 1206 | ||
1104 | /* only internal SW should disable ctrl endpts */ | 1207 | /* only internal SW should disable ctrl endpts */ |
1105 | 1208 | ||
1106 | direction = mEp->dir; | 1209 | direction = hwep->dir; |
1107 | do { | 1210 | do { |
1108 | retval |= _ep_nuke(mEp); | 1211 | retval |= _ep_nuke(hwep); |
1109 | retval |= hw_ep_disable(mEp->ci, mEp->num, mEp->dir); | 1212 | retval |= hw_ep_disable(hwep->ci, hwep->num, hwep->dir); |
1110 | 1213 | ||
1111 | if (mEp->type == USB_ENDPOINT_XFER_CONTROL) | 1214 | if (hwep->type == USB_ENDPOINT_XFER_CONTROL) |
1112 | mEp->dir = (mEp->dir == TX) ? RX : TX; | 1215 | hwep->dir = (hwep->dir == TX) ? RX : TX; |
1113 | 1216 | ||
1114 | } while (mEp->dir != direction); | 1217 | } while (hwep->dir != direction); |
1115 | 1218 | ||
1116 | mEp->ep.desc = NULL; | 1219 | hwep->ep.desc = NULL; |
1117 | 1220 | ||
1118 | spin_unlock_irqrestore(mEp->lock, flags); | 1221 | spin_unlock_irqrestore(hwep->lock, flags); |
1119 | return retval; | 1222 | return retval; |
1120 | } | 1223 | } |
1121 | 1224 | ||
@@ -1126,25 +1229,18 @@ static int ep_disable(struct usb_ep *ep) | |||
1126 | */ | 1229 | */ |
1127 | static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) | 1230 | static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) |
1128 | { | 1231 | { |
1129 | struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); | 1232 | struct ci_hw_req *hwreq = NULL; |
1130 | struct ci13xxx_req *mReq = NULL; | ||
1131 | 1233 | ||
1132 | if (ep == NULL) | 1234 | if (ep == NULL) |
1133 | return NULL; | 1235 | return NULL; |
1134 | 1236 | ||
1135 | mReq = kzalloc(sizeof(struct ci13xxx_req), gfp_flags); | 1237 | hwreq = kzalloc(sizeof(struct ci_hw_req), gfp_flags); |
1136 | if (mReq != NULL) { | 1238 | if (hwreq != NULL) { |
1137 | INIT_LIST_HEAD(&mReq->queue); | 1239 | INIT_LIST_HEAD(&hwreq->queue); |
1138 | 1240 | INIT_LIST_HEAD(&hwreq->tds); | |
1139 | mReq->ptr = dma_pool_alloc(mEp->td_pool, gfp_flags, | ||
1140 | &mReq->dma); | ||
1141 | if (mReq->ptr == NULL) { | ||
1142 | kfree(mReq); | ||
1143 | mReq = NULL; | ||
1144 | } | ||
1145 | } | 1241 | } |
1146 | 1242 | ||
1147 | return (mReq == NULL) ? NULL : &mReq->req; | 1243 | return (hwreq == NULL) ? NULL : &hwreq->req; |
1148 | } | 1244 | } |
1149 | 1245 | ||
1150 | /** | 1246 | /** |
@@ -1154,24 +1250,30 @@ static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags) | |||
1154 | */ | 1250 | */ |
1155 | static void ep_free_request(struct usb_ep *ep, struct usb_request *req) | 1251 | static void ep_free_request(struct usb_ep *ep, struct usb_request *req) |
1156 | { | 1252 | { |
1157 | struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); | 1253 | struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); |
1158 | struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req); | 1254 | struct ci_hw_req *hwreq = container_of(req, struct ci_hw_req, req); |
1255 | struct td_node *node, *tmpnode; | ||
1159 | unsigned long flags; | 1256 | unsigned long flags; |
1160 | 1257 | ||
1161 | if (ep == NULL || req == NULL) { | 1258 | if (ep == NULL || req == NULL) { |
1162 | return; | 1259 | return; |
1163 | } else if (!list_empty(&mReq->queue)) { | 1260 | } else if (!list_empty(&hwreq->queue)) { |
1164 | dev_err(mEp->ci->dev, "freeing queued request\n"); | 1261 | dev_err(hwep->ci->dev, "freeing queued request\n"); |
1165 | return; | 1262 | return; |
1166 | } | 1263 | } |
1167 | 1264 | ||
1168 | spin_lock_irqsave(mEp->lock, flags); | 1265 | spin_lock_irqsave(hwep->lock, flags); |
1169 | 1266 | ||
1170 | if (mReq->ptr) | 1267 | list_for_each_entry_safe(node, tmpnode, &hwreq->tds, td) { |
1171 | dma_pool_free(mEp->td_pool, mReq->ptr, mReq->dma); | 1268 | dma_pool_free(hwep->td_pool, node->ptr, node->dma); |
1172 | kfree(mReq); | 1269 | list_del_init(&node->td); |
1270 | node->ptr = NULL; | ||
1271 | kfree(node); | ||
1272 | } | ||
1273 | |||
1274 | kfree(hwreq); | ||
1173 | 1275 | ||
1174 | spin_unlock_irqrestore(mEp->lock, flags); | 1276 | spin_unlock_irqrestore(hwep->lock, flags); |
1175 | } | 1277 | } |
1176 | 1278 | ||
1177 | /** | 1279 | /** |
@@ -1182,16 +1284,16 @@ static void ep_free_request(struct usb_ep *ep, struct usb_request *req) | |||
1182 | static int ep_queue(struct usb_ep *ep, struct usb_request *req, | 1284 | static int ep_queue(struct usb_ep *ep, struct usb_request *req, |
1183 | gfp_t __maybe_unused gfp_flags) | 1285 | gfp_t __maybe_unused gfp_flags) |
1184 | { | 1286 | { |
1185 | struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); | 1287 | struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); |
1186 | int retval = 0; | 1288 | int retval = 0; |
1187 | unsigned long flags; | 1289 | unsigned long flags; |
1188 | 1290 | ||
1189 | if (ep == NULL || req == NULL || mEp->ep.desc == NULL) | 1291 | if (ep == NULL || req == NULL || hwep->ep.desc == NULL) |
1190 | return -EINVAL; | 1292 | return -EINVAL; |
1191 | 1293 | ||
1192 | spin_lock_irqsave(mEp->lock, flags); | 1294 | spin_lock_irqsave(hwep->lock, flags); |
1193 | retval = _ep_queue(ep, req, gfp_flags); | 1295 | retval = _ep_queue(ep, req, gfp_flags); |
1194 | spin_unlock_irqrestore(mEp->lock, flags); | 1296 | spin_unlock_irqrestore(hwep->lock, flags); |
1195 | return retval; | 1297 | return retval; |
1196 | } | 1298 | } |
1197 | 1299 | ||
@@ -1202,33 +1304,33 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req, | |||
1202 | */ | 1304 | */ |
1203 | static int ep_dequeue(struct usb_ep *ep, struct usb_request *req) | 1305 | static int ep_dequeue(struct usb_ep *ep, struct usb_request *req) |
1204 | { | 1306 | { |
1205 | struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); | 1307 | struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); |
1206 | struct ci13xxx_req *mReq = container_of(req, struct ci13xxx_req, req); | 1308 | struct ci_hw_req *hwreq = container_of(req, struct ci_hw_req, req); |
1207 | unsigned long flags; | 1309 | unsigned long flags; |
1208 | 1310 | ||
1209 | if (ep == NULL || req == NULL || mReq->req.status != -EALREADY || | 1311 | if (ep == NULL || req == NULL || hwreq->req.status != -EALREADY || |
1210 | mEp->ep.desc == NULL || list_empty(&mReq->queue) || | 1312 | hwep->ep.desc == NULL || list_empty(&hwreq->queue) || |
1211 | list_empty(&mEp->qh.queue)) | 1313 | list_empty(&hwep->qh.queue)) |
1212 | return -EINVAL; | 1314 | return -EINVAL; |
1213 | 1315 | ||
1214 | spin_lock_irqsave(mEp->lock, flags); | 1316 | spin_lock_irqsave(hwep->lock, flags); |
1215 | 1317 | ||
1216 | hw_ep_flush(mEp->ci, mEp->num, mEp->dir); | 1318 | hw_ep_flush(hwep->ci, hwep->num, hwep->dir); |
1217 | 1319 | ||
1218 | /* pop request */ | 1320 | /* pop request */ |
1219 | list_del_init(&mReq->queue); | 1321 | list_del_init(&hwreq->queue); |
1220 | 1322 | ||
1221 | usb_gadget_unmap_request(&mEp->ci->gadget, req, mEp->dir); | 1323 | usb_gadget_unmap_request(&hwep->ci->gadget, req, hwep->dir); |
1222 | 1324 | ||
1223 | req->status = -ECONNRESET; | 1325 | req->status = -ECONNRESET; |
1224 | 1326 | ||
1225 | if (mReq->req.complete != NULL) { | 1327 | if (hwreq->req.complete != NULL) { |
1226 | spin_unlock(mEp->lock); | 1328 | spin_unlock(hwep->lock); |
1227 | mReq->req.complete(&mEp->ep, &mReq->req); | 1329 | hwreq->req.complete(&hwep->ep, &hwreq->req); |
1228 | spin_lock(mEp->lock); | 1330 | spin_lock(hwep->lock); |
1229 | } | 1331 | } |
1230 | 1332 | ||
1231 | spin_unlock_irqrestore(mEp->lock, flags); | 1333 | spin_unlock_irqrestore(hwep->lock, flags); |
1232 | return 0; | 1334 | return 0; |
1233 | } | 1335 | } |
1234 | 1336 | ||
@@ -1239,37 +1341,40 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req) | |||
1239 | */ | 1341 | */ |
1240 | static int ep_set_halt(struct usb_ep *ep, int value) | 1342 | static int ep_set_halt(struct usb_ep *ep, int value) |
1241 | { | 1343 | { |
1242 | struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); | 1344 | struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); |
1243 | int direction, retval = 0; | 1345 | int direction, retval = 0; |
1244 | unsigned long flags; | 1346 | unsigned long flags; |
1245 | 1347 | ||
1246 | if (ep == NULL || mEp->ep.desc == NULL) | 1348 | if (ep == NULL || hwep->ep.desc == NULL) |
1247 | return -EINVAL; | 1349 | return -EINVAL; |
1248 | 1350 | ||
1249 | spin_lock_irqsave(mEp->lock, flags); | 1351 | if (usb_endpoint_xfer_isoc(hwep->ep.desc)) |
1352 | return -EOPNOTSUPP; | ||
1353 | |||
1354 | spin_lock_irqsave(hwep->lock, flags); | ||
1250 | 1355 | ||
1251 | #ifndef STALL_IN | 1356 | #ifndef STALL_IN |
1252 | /* g_file_storage MS compliant but g_zero fails chapter 9 compliance */ | 1357 | /* g_file_storage MS compliant but g_zero fails chapter 9 compliance */ |
1253 | if (value && mEp->type == USB_ENDPOINT_XFER_BULK && mEp->dir == TX && | 1358 | if (value && hwep->type == USB_ENDPOINT_XFER_BULK && hwep->dir == TX && |
1254 | !list_empty(&mEp->qh.queue)) { | 1359 | !list_empty(&hwep->qh.queue)) { |
1255 | spin_unlock_irqrestore(mEp->lock, flags); | 1360 | spin_unlock_irqrestore(hwep->lock, flags); |
1256 | return -EAGAIN; | 1361 | return -EAGAIN; |
1257 | } | 1362 | } |
1258 | #endif | 1363 | #endif |
1259 | 1364 | ||
1260 | direction = mEp->dir; | 1365 | direction = hwep->dir; |
1261 | do { | 1366 | do { |
1262 | retval |= hw_ep_set_halt(mEp->ci, mEp->num, mEp->dir, value); | 1367 | retval |= hw_ep_set_halt(hwep->ci, hwep->num, hwep->dir, value); |
1263 | 1368 | ||
1264 | if (!value) | 1369 | if (!value) |
1265 | mEp->wedge = 0; | 1370 | hwep->wedge = 0; |
1266 | 1371 | ||
1267 | if (mEp->type == USB_ENDPOINT_XFER_CONTROL) | 1372 | if (hwep->type == USB_ENDPOINT_XFER_CONTROL) |
1268 | mEp->dir = (mEp->dir == TX) ? RX : TX; | 1373 | hwep->dir = (hwep->dir == TX) ? RX : TX; |
1269 | 1374 | ||
1270 | } while (mEp->dir != direction); | 1375 | } while (hwep->dir != direction); |
1271 | 1376 | ||
1272 | spin_unlock_irqrestore(mEp->lock, flags); | 1377 | spin_unlock_irqrestore(hwep->lock, flags); |
1273 | return retval; | 1378 | return retval; |
1274 | } | 1379 | } |
1275 | 1380 | ||
@@ -1280,15 +1385,15 @@ static int ep_set_halt(struct usb_ep *ep, int value) | |||
1280 | */ | 1385 | */ |
1281 | static int ep_set_wedge(struct usb_ep *ep) | 1386 | static int ep_set_wedge(struct usb_ep *ep) |
1282 | { | 1387 | { |
1283 | struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); | 1388 | struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); |
1284 | unsigned long flags; | 1389 | unsigned long flags; |
1285 | 1390 | ||
1286 | if (ep == NULL || mEp->ep.desc == NULL) | 1391 | if (ep == NULL || hwep->ep.desc == NULL) |
1287 | return -EINVAL; | 1392 | return -EINVAL; |
1288 | 1393 | ||
1289 | spin_lock_irqsave(mEp->lock, flags); | 1394 | spin_lock_irqsave(hwep->lock, flags); |
1290 | mEp->wedge = 1; | 1395 | hwep->wedge = 1; |
1291 | spin_unlock_irqrestore(mEp->lock, flags); | 1396 | spin_unlock_irqrestore(hwep->lock, flags); |
1292 | 1397 | ||
1293 | return usb_ep_set_halt(ep); | 1398 | return usb_ep_set_halt(ep); |
1294 | } | 1399 | } |
@@ -1300,19 +1405,19 @@ static int ep_set_wedge(struct usb_ep *ep) | |||
1300 | */ | 1405 | */ |
1301 | static void ep_fifo_flush(struct usb_ep *ep) | 1406 | static void ep_fifo_flush(struct usb_ep *ep) |
1302 | { | 1407 | { |
1303 | struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); | 1408 | struct ci_hw_ep *hwep = container_of(ep, struct ci_hw_ep, ep); |
1304 | unsigned long flags; | 1409 | unsigned long flags; |
1305 | 1410 | ||
1306 | if (ep == NULL) { | 1411 | if (ep == NULL) { |
1307 | dev_err(mEp->ci->dev, "%02X: -EINVAL\n", _usb_addr(mEp)); | 1412 | dev_err(hwep->ci->dev, "%02X: -EINVAL\n", _usb_addr(hwep)); |
1308 | return; | 1413 | return; |
1309 | } | 1414 | } |
1310 | 1415 | ||
1311 | spin_lock_irqsave(mEp->lock, flags); | 1416 | spin_lock_irqsave(hwep->lock, flags); |
1312 | 1417 | ||
1313 | hw_ep_flush(mEp->ci, mEp->num, mEp->dir); | 1418 | hw_ep_flush(hwep->ci, hwep->num, hwep->dir); |
1314 | 1419 | ||
1315 | spin_unlock_irqrestore(mEp->lock, flags); | 1420 | spin_unlock_irqrestore(hwep->lock, flags); |
1316 | } | 1421 | } |
1317 | 1422 | ||
1318 | /** | 1423 | /** |
@@ -1334,13 +1439,13 @@ static const struct usb_ep_ops usb_ep_ops = { | |||
1334 | /****************************************************************************** | 1439 | /****************************************************************************** |
1335 | * GADGET block | 1440 | * GADGET block |
1336 | *****************************************************************************/ | 1441 | *****************************************************************************/ |
1337 | static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active) | 1442 | static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active) |
1338 | { | 1443 | { |
1339 | struct ci13xxx *ci = container_of(_gadget, struct ci13xxx, gadget); | 1444 | struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget); |
1340 | unsigned long flags; | 1445 | unsigned long flags; |
1341 | int gadget_ready = 0; | 1446 | int gadget_ready = 0; |
1342 | 1447 | ||
1343 | if (!(ci->platdata->flags & CI13XXX_PULLUP_ON_VBUS)) | 1448 | if (!(ci->platdata->flags & CI_HDRC_PULLUP_ON_VBUS)) |
1344 | return -EOPNOTSUPP; | 1449 | return -EOPNOTSUPP; |
1345 | 1450 | ||
1346 | spin_lock_irqsave(&ci->lock, flags); | 1451 | spin_lock_irqsave(&ci->lock, flags); |
@@ -1358,7 +1463,7 @@ static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active) | |||
1358 | hw_device_state(ci, 0); | 1463 | hw_device_state(ci, 0); |
1359 | if (ci->platdata->notify_event) | 1464 | if (ci->platdata->notify_event) |
1360 | ci->platdata->notify_event(ci, | 1465 | ci->platdata->notify_event(ci, |
1361 | CI13XXX_CONTROLLER_STOPPED_EVENT); | 1466 | CI_HDRC_CONTROLLER_STOPPED_EVENT); |
1362 | _gadget_stop_activity(&ci->gadget); | 1467 | _gadget_stop_activity(&ci->gadget); |
1363 | pm_runtime_put_sync(&_gadget->dev); | 1468 | pm_runtime_put_sync(&_gadget->dev); |
1364 | } | 1469 | } |
@@ -1367,9 +1472,9 @@ static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active) | |||
1367 | return 0; | 1472 | return 0; |
1368 | } | 1473 | } |
1369 | 1474 | ||
1370 | static int ci13xxx_wakeup(struct usb_gadget *_gadget) | 1475 | static int ci_udc_wakeup(struct usb_gadget *_gadget) |
1371 | { | 1476 | { |
1372 | struct ci13xxx *ci = container_of(_gadget, struct ci13xxx, gadget); | 1477 | struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget); |
1373 | unsigned long flags; | 1478 | unsigned long flags; |
1374 | int ret = 0; | 1479 | int ret = 0; |
1375 | 1480 | ||
@@ -1388,21 +1493,21 @@ out: | |||
1388 | return ret; | 1493 | return ret; |
1389 | } | 1494 | } |
1390 | 1495 | ||
1391 | static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA) | 1496 | static int ci_udc_vbus_draw(struct usb_gadget *_gadget, unsigned ma) |
1392 | { | 1497 | { |
1393 | struct ci13xxx *ci = container_of(_gadget, struct ci13xxx, gadget); | 1498 | struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget); |
1394 | 1499 | ||
1395 | if (ci->transceiver) | 1500 | if (ci->transceiver) |
1396 | return usb_phy_set_power(ci->transceiver, mA); | 1501 | return usb_phy_set_power(ci->transceiver, ma); |
1397 | return -ENOTSUPP; | 1502 | return -ENOTSUPP; |
1398 | } | 1503 | } |
1399 | 1504 | ||
1400 | /* Change Data+ pullup status | 1505 | /* Change Data+ pullup status |
1401 | * this func is used by usb_gadget_connect/disconnet | 1506 | * this func is used by usb_gadget_connect/disconnet |
1402 | */ | 1507 | */ |
1403 | static int ci13xxx_pullup(struct usb_gadget *_gadget, int is_on) | 1508 | static int ci_udc_pullup(struct usb_gadget *_gadget, int is_on) |
1404 | { | 1509 | { |
1405 | struct ci13xxx *ci = container_of(_gadget, struct ci13xxx, gadget); | 1510 | struct ci_hdrc *ci = container_of(_gadget, struct ci_hdrc, gadget); |
1406 | 1511 | ||
1407 | if (is_on) | 1512 | if (is_on) |
1408 | hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS); | 1513 | hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS); |
@@ -1412,9 +1517,9 @@ static int ci13xxx_pullup(struct usb_gadget *_gadget, int is_on) | |||
1412 | return 0; | 1517 | return 0; |
1413 | } | 1518 | } |
1414 | 1519 | ||
1415 | static int ci13xxx_start(struct usb_gadget *gadget, | 1520 | static int ci_udc_start(struct usb_gadget *gadget, |
1416 | struct usb_gadget_driver *driver); | 1521 | struct usb_gadget_driver *driver); |
1417 | static int ci13xxx_stop(struct usb_gadget *gadget, | 1522 | static int ci_udc_stop(struct usb_gadget *gadget, |
1418 | struct usb_gadget_driver *driver); | 1523 | struct usb_gadget_driver *driver); |
1419 | /** | 1524 | /** |
1420 | * Device operations part of the API to the USB controller hardware, | 1525 | * Device operations part of the API to the USB controller hardware, |
@@ -1422,46 +1527,46 @@ static int ci13xxx_stop(struct usb_gadget *gadget, | |||
1422 | * Check "usb_gadget.h" for details | 1527 | * Check "usb_gadget.h" for details |
1423 | */ | 1528 | */ |
1424 | static const struct usb_gadget_ops usb_gadget_ops = { | 1529 | static const struct usb_gadget_ops usb_gadget_ops = { |
1425 | .vbus_session = ci13xxx_vbus_session, | 1530 | .vbus_session = ci_udc_vbus_session, |
1426 | .wakeup = ci13xxx_wakeup, | 1531 | .wakeup = ci_udc_wakeup, |
1427 | .pullup = ci13xxx_pullup, | 1532 | .pullup = ci_udc_pullup, |
1428 | .vbus_draw = ci13xxx_vbus_draw, | 1533 | .vbus_draw = ci_udc_vbus_draw, |
1429 | .udc_start = ci13xxx_start, | 1534 | .udc_start = ci_udc_start, |
1430 | .udc_stop = ci13xxx_stop, | 1535 | .udc_stop = ci_udc_stop, |
1431 | }; | 1536 | }; |
1432 | 1537 | ||
1433 | static int init_eps(struct ci13xxx *ci) | 1538 | static int init_eps(struct ci_hdrc *ci) |
1434 | { | 1539 | { |
1435 | int retval = 0, i, j; | 1540 | int retval = 0, i, j; |
1436 | 1541 | ||
1437 | for (i = 0; i < ci->hw_ep_max/2; i++) | 1542 | for (i = 0; i < ci->hw_ep_max/2; i++) |
1438 | for (j = RX; j <= TX; j++) { | 1543 | for (j = RX; j <= TX; j++) { |
1439 | int k = i + j * ci->hw_ep_max/2; | 1544 | int k = i + j * ci->hw_ep_max/2; |
1440 | struct ci13xxx_ep *mEp = &ci->ci13xxx_ep[k]; | 1545 | struct ci_hw_ep *hwep = &ci->ci_hw_ep[k]; |
1441 | 1546 | ||
1442 | scnprintf(mEp->name, sizeof(mEp->name), "ep%i%s", i, | 1547 | scnprintf(hwep->name, sizeof(hwep->name), "ep%i%s", i, |
1443 | (j == TX) ? "in" : "out"); | 1548 | (j == TX) ? "in" : "out"); |
1444 | 1549 | ||
1445 | mEp->ci = ci; | 1550 | hwep->ci = ci; |
1446 | mEp->lock = &ci->lock; | 1551 | hwep->lock = &ci->lock; |
1447 | mEp->td_pool = ci->td_pool; | 1552 | hwep->td_pool = ci->td_pool; |
1448 | 1553 | ||
1449 | mEp->ep.name = mEp->name; | 1554 | hwep->ep.name = hwep->name; |
1450 | mEp->ep.ops = &usb_ep_ops; | 1555 | hwep->ep.ops = &usb_ep_ops; |
1451 | /* | 1556 | /* |
1452 | * for ep0: maxP defined in desc, for other | 1557 | * for ep0: maxP defined in desc, for other |
1453 | * eps, maxP is set by epautoconfig() called | 1558 | * eps, maxP is set by epautoconfig() called |
1454 | * by gadget layer | 1559 | * by gadget layer |
1455 | */ | 1560 | */ |
1456 | mEp->ep.maxpacket = (unsigned short)~0; | 1561 | hwep->ep.maxpacket = (unsigned short)~0; |
1457 | 1562 | ||
1458 | INIT_LIST_HEAD(&mEp->qh.queue); | 1563 | INIT_LIST_HEAD(&hwep->qh.queue); |
1459 | mEp->qh.ptr = dma_pool_alloc(ci->qh_pool, GFP_KERNEL, | 1564 | hwep->qh.ptr = dma_pool_alloc(ci->qh_pool, GFP_KERNEL, |
1460 | &mEp->qh.dma); | 1565 | &hwep->qh.dma); |
1461 | if (mEp->qh.ptr == NULL) | 1566 | if (hwep->qh.ptr == NULL) |
1462 | retval = -ENOMEM; | 1567 | retval = -ENOMEM; |
1463 | else | 1568 | else |
1464 | memset(mEp->qh.ptr, 0, sizeof(*mEp->qh.ptr)); | 1569 | memset(hwep->qh.ptr, 0, sizeof(*hwep->qh.ptr)); |
1465 | 1570 | ||
1466 | /* | 1571 | /* |
1467 | * set up shorthands for ep0 out and in endpoints, | 1572 | * set up shorthands for ep0 out and in endpoints, |
@@ -1469,42 +1574,42 @@ static int init_eps(struct ci13xxx *ci) | |||
1469 | */ | 1574 | */ |
1470 | if (i == 0) { | 1575 | if (i == 0) { |
1471 | if (j == RX) | 1576 | if (j == RX) |
1472 | ci->ep0out = mEp; | 1577 | ci->ep0out = hwep; |
1473 | else | 1578 | else |
1474 | ci->ep0in = mEp; | 1579 | ci->ep0in = hwep; |
1475 | 1580 | ||
1476 | mEp->ep.maxpacket = CTRL_PAYLOAD_MAX; | 1581 | hwep->ep.maxpacket = CTRL_PAYLOAD_MAX; |
1477 | continue; | 1582 | continue; |
1478 | } | 1583 | } |
1479 | 1584 | ||
1480 | list_add_tail(&mEp->ep.ep_list, &ci->gadget.ep_list); | 1585 | list_add_tail(&hwep->ep.ep_list, &ci->gadget.ep_list); |
1481 | } | 1586 | } |
1482 | 1587 | ||
1483 | return retval; | 1588 | return retval; |
1484 | } | 1589 | } |
1485 | 1590 | ||
1486 | static void destroy_eps(struct ci13xxx *ci) | 1591 | static void destroy_eps(struct ci_hdrc *ci) |
1487 | { | 1592 | { |
1488 | int i; | 1593 | int i; |
1489 | 1594 | ||
1490 | for (i = 0; i < ci->hw_ep_max; i++) { | 1595 | for (i = 0; i < ci->hw_ep_max; i++) { |
1491 | struct ci13xxx_ep *mEp = &ci->ci13xxx_ep[i]; | 1596 | struct ci_hw_ep *hwep = &ci->ci_hw_ep[i]; |
1492 | 1597 | ||
1493 | dma_pool_free(ci->qh_pool, mEp->qh.ptr, mEp->qh.dma); | 1598 | dma_pool_free(ci->qh_pool, hwep->qh.ptr, hwep->qh.dma); |
1494 | } | 1599 | } |
1495 | } | 1600 | } |
1496 | 1601 | ||
1497 | /** | 1602 | /** |
1498 | * ci13xxx_start: register a gadget driver | 1603 | * ci_udc_start: register a gadget driver |
1499 | * @gadget: our gadget | 1604 | * @gadget: our gadget |
1500 | * @driver: the driver being registered | 1605 | * @driver: the driver being registered |
1501 | * | 1606 | * |
1502 | * Interrupts are enabled here. | 1607 | * Interrupts are enabled here. |
1503 | */ | 1608 | */ |
1504 | static int ci13xxx_start(struct usb_gadget *gadget, | 1609 | static int ci_udc_start(struct usb_gadget *gadget, |
1505 | struct usb_gadget_driver *driver) | 1610 | struct usb_gadget_driver *driver) |
1506 | { | 1611 | { |
1507 | struct ci13xxx *ci = container_of(gadget, struct ci13xxx, gadget); | 1612 | struct ci_hdrc *ci = container_of(gadget, struct ci_hdrc, gadget); |
1508 | unsigned long flags; | 1613 | unsigned long flags; |
1509 | int retval = -ENOMEM; | 1614 | int retval = -ENOMEM; |
1510 | 1615 | ||
@@ -1525,9 +1630,9 @@ static int ci13xxx_start(struct usb_gadget *gadget, | |||
1525 | 1630 | ||
1526 | ci->driver = driver; | 1631 | ci->driver = driver; |
1527 | pm_runtime_get_sync(&ci->gadget.dev); | 1632 | pm_runtime_get_sync(&ci->gadget.dev); |
1528 | if (ci->platdata->flags & CI13XXX_PULLUP_ON_VBUS) { | 1633 | if (ci->platdata->flags & CI_HDRC_PULLUP_ON_VBUS) { |
1529 | if (ci->vbus_active) { | 1634 | if (ci->vbus_active) { |
1530 | if (ci->platdata->flags & CI13XXX_REGS_SHARED) | 1635 | if (ci->platdata->flags & CI_HDRC_REGS_SHARED) |
1531 | hw_device_reset(ci, USBMODE_CM_DC); | 1636 | hw_device_reset(ci, USBMODE_CM_DC); |
1532 | } else { | 1637 | } else { |
1533 | pm_runtime_put_sync(&ci->gadget.dev); | 1638 | pm_runtime_put_sync(&ci->gadget.dev); |
@@ -1545,22 +1650,22 @@ static int ci13xxx_start(struct usb_gadget *gadget, | |||
1545 | } | 1650 | } |
1546 | 1651 | ||
1547 | /** | 1652 | /** |
1548 | * ci13xxx_stop: unregister a gadget driver | 1653 | * ci_udc_stop: unregister a gadget driver |
1549 | */ | 1654 | */ |
1550 | static int ci13xxx_stop(struct usb_gadget *gadget, | 1655 | static int ci_udc_stop(struct usb_gadget *gadget, |
1551 | struct usb_gadget_driver *driver) | 1656 | struct usb_gadget_driver *driver) |
1552 | { | 1657 | { |
1553 | struct ci13xxx *ci = container_of(gadget, struct ci13xxx, gadget); | 1658 | struct ci_hdrc *ci = container_of(gadget, struct ci_hdrc, gadget); |
1554 | unsigned long flags; | 1659 | unsigned long flags; |
1555 | 1660 | ||
1556 | spin_lock_irqsave(&ci->lock, flags); | 1661 | spin_lock_irqsave(&ci->lock, flags); |
1557 | 1662 | ||
1558 | if (!(ci->platdata->flags & CI13XXX_PULLUP_ON_VBUS) || | 1663 | if (!(ci->platdata->flags & CI_HDRC_PULLUP_ON_VBUS) || |
1559 | ci->vbus_active) { | 1664 | ci->vbus_active) { |
1560 | hw_device_state(ci, 0); | 1665 | hw_device_state(ci, 0); |
1561 | if (ci->platdata->notify_event) | 1666 | if (ci->platdata->notify_event) |
1562 | ci->platdata->notify_event(ci, | 1667 | ci->platdata->notify_event(ci, |
1563 | CI13XXX_CONTROLLER_STOPPED_EVENT); | 1668 | CI_HDRC_CONTROLLER_STOPPED_EVENT); |
1564 | ci->driver = NULL; | 1669 | ci->driver = NULL; |
1565 | spin_unlock_irqrestore(&ci->lock, flags); | 1670 | spin_unlock_irqrestore(&ci->lock, flags); |
1566 | _gadget_stop_activity(&ci->gadget); | 1671 | _gadget_stop_activity(&ci->gadget); |
@@ -1582,7 +1687,7 @@ static int ci13xxx_stop(struct usb_gadget *gadget, | |||
1582 | * This function returns IRQ_HANDLED if the IRQ has been handled | 1687 | * This function returns IRQ_HANDLED if the IRQ has been handled |
1583 | * It locks access to registers | 1688 | * It locks access to registers |
1584 | */ | 1689 | */ |
1585 | static irqreturn_t udc_irq(struct ci13xxx *ci) | 1690 | static irqreturn_t udc_irq(struct ci_hdrc *ci) |
1586 | { | 1691 | { |
1587 | irqreturn_t retval; | 1692 | irqreturn_t retval; |
1588 | u32 intr; | 1693 | u32 intr; |
@@ -1592,7 +1697,7 @@ static irqreturn_t udc_irq(struct ci13xxx *ci) | |||
1592 | 1697 | ||
1593 | spin_lock(&ci->lock); | 1698 | spin_lock(&ci->lock); |
1594 | 1699 | ||
1595 | if (ci->platdata->flags & CI13XXX_REGS_SHARED) { | 1700 | if (ci->platdata->flags & CI_HDRC_REGS_SHARED) { |
1596 | if (hw_read(ci, OP_USBMODE, USBMODE_CM) != | 1701 | if (hw_read(ci, OP_USBMODE, USBMODE_CM) != |
1597 | USBMODE_CM_DC) { | 1702 | USBMODE_CM_DC) { |
1598 | spin_unlock(&ci->lock); | 1703 | spin_unlock(&ci->lock); |
@@ -1642,7 +1747,7 @@ static irqreturn_t udc_irq(struct ci13xxx *ci) | |||
1642 | * udc_start: initialize gadget role | 1747 | * udc_start: initialize gadget role |
1643 | * @ci: chipidea controller | 1748 | * @ci: chipidea controller |
1644 | */ | 1749 | */ |
1645 | static int udc_start(struct ci13xxx *ci) | 1750 | static int udc_start(struct ci_hdrc *ci) |
1646 | { | 1751 | { |
1647 | struct device *dev = ci->dev; | 1752 | struct device *dev = ci->dev; |
1648 | int retval = 0; | 1753 | int retval = 0; |
@@ -1658,15 +1763,15 @@ static int udc_start(struct ci13xxx *ci) | |||
1658 | INIT_LIST_HEAD(&ci->gadget.ep_list); | 1763 | INIT_LIST_HEAD(&ci->gadget.ep_list); |
1659 | 1764 | ||
1660 | /* alloc resources */ | 1765 | /* alloc resources */ |
1661 | ci->qh_pool = dma_pool_create("ci13xxx_qh", dev, | 1766 | ci->qh_pool = dma_pool_create("ci_hw_qh", dev, |
1662 | sizeof(struct ci13xxx_qh), | 1767 | sizeof(struct ci_hw_qh), |
1663 | 64, CI13XXX_PAGE_SIZE); | 1768 | 64, CI_HDRC_PAGE_SIZE); |
1664 | if (ci->qh_pool == NULL) | 1769 | if (ci->qh_pool == NULL) |
1665 | return -ENOMEM; | 1770 | return -ENOMEM; |
1666 | 1771 | ||
1667 | ci->td_pool = dma_pool_create("ci13xxx_td", dev, | 1772 | ci->td_pool = dma_pool_create("ci_hw_td", dev, |
1668 | sizeof(struct ci13xxx_td), | 1773 | sizeof(struct ci_hw_td), |
1669 | 64, CI13XXX_PAGE_SIZE); | 1774 | 64, CI_HDRC_PAGE_SIZE); |
1670 | if (ci->td_pool == NULL) { | 1775 | if (ci->td_pool == NULL) { |
1671 | retval = -ENOMEM; | 1776 | retval = -ENOMEM; |
1672 | goto free_qh_pool; | 1777 | goto free_qh_pool; |
@@ -1684,14 +1789,14 @@ static int udc_start(struct ci13xxx *ci) | |||
1684 | ci->transceiver = NULL; | 1789 | ci->transceiver = NULL; |
1685 | } | 1790 | } |
1686 | 1791 | ||
1687 | if (ci->platdata->flags & CI13XXX_REQUIRE_TRANSCEIVER) { | 1792 | if (ci->platdata->flags & CI_HDRC_REQUIRE_TRANSCEIVER) { |
1688 | if (ci->transceiver == NULL) { | 1793 | if (ci->transceiver == NULL) { |
1689 | retval = -ENODEV; | 1794 | retval = -ENODEV; |
1690 | goto destroy_eps; | 1795 | goto destroy_eps; |
1691 | } | 1796 | } |
1692 | } | 1797 | } |
1693 | 1798 | ||
1694 | if (!(ci->platdata->flags & CI13XXX_REGS_SHARED)) { | 1799 | if (!(ci->platdata->flags & CI_HDRC_REGS_SHARED)) { |
1695 | retval = hw_device_reset(ci, USBMODE_CM_DC); | 1800 | retval = hw_device_reset(ci, USBMODE_CM_DC); |
1696 | if (retval) | 1801 | if (retval) |
1697 | goto put_transceiver; | 1802 | goto put_transceiver; |
@@ -1738,7 +1843,7 @@ free_qh_pool: | |||
1738 | * | 1843 | * |
1739 | * No interrupts active, the IRQ has been released | 1844 | * No interrupts active, the IRQ has been released |
1740 | */ | 1845 | */ |
1741 | static void udc_stop(struct ci13xxx *ci) | 1846 | static void udc_stop(struct ci_hdrc *ci) |
1742 | { | 1847 | { |
1743 | if (ci == NULL) | 1848 | if (ci == NULL) |
1744 | return; | 1849 | return; |
@@ -1765,7 +1870,7 @@ static void udc_stop(struct ci13xxx *ci) | |||
1765 | * | 1870 | * |
1766 | * This function enables the gadget role, if the device is "device capable". | 1871 | * This function enables the gadget role, if the device is "device capable". |
1767 | */ | 1872 | */ |
1768 | int ci_hdrc_gadget_init(struct ci13xxx *ci) | 1873 | int ci_hdrc_gadget_init(struct ci_hdrc *ci) |
1769 | { | 1874 | { |
1770 | struct ci_role_driver *rdrv; | 1875 | struct ci_role_driver *rdrv; |
1771 | 1876 | ||
diff --git a/drivers/usb/chipidea/udc.h b/drivers/usb/chipidea/udc.h index d12e8b59b110..455ac2169226 100644 --- a/drivers/usb/chipidea/udc.h +++ b/drivers/usb/chipidea/udc.h | |||
@@ -20,7 +20,7 @@ | |||
20 | #define TX 1 /* similar to USB_DIR_IN but can be used as an index */ | 20 | #define TX 1 /* similar to USB_DIR_IN but can be used as an index */ |
21 | 21 | ||
22 | /* DMA layout of transfer descriptors */ | 22 | /* DMA layout of transfer descriptors */ |
23 | struct ci13xxx_td { | 23 | struct ci_hw_td { |
24 | /* 0 */ | 24 | /* 0 */ |
25 | u32 next; | 25 | u32 next; |
26 | #define TD_TERMINATE BIT(0) | 26 | #define TD_TERMINATE BIT(0) |
@@ -43,24 +43,31 @@ struct ci13xxx_td { | |||
43 | } __attribute__ ((packed, aligned(4))); | 43 | } __attribute__ ((packed, aligned(4))); |
44 | 44 | ||
45 | /* DMA layout of queue heads */ | 45 | /* DMA layout of queue heads */ |
46 | struct ci13xxx_qh { | 46 | struct ci_hw_qh { |
47 | /* 0 */ | 47 | /* 0 */ |
48 | u32 cap; | 48 | u32 cap; |
49 | #define QH_IOS BIT(15) | 49 | #define QH_IOS BIT(15) |
50 | #define QH_MAX_PKT (0x07FFUL << 16) | 50 | #define QH_MAX_PKT (0x07FFUL << 16) |
51 | #define QH_ZLT BIT(29) | 51 | #define QH_ZLT BIT(29) |
52 | #define QH_MULT (0x0003UL << 30) | 52 | #define QH_MULT (0x0003UL << 30) |
53 | #define QH_ISO_MULT(x) ((x >> 11) & 0x03) | ||
53 | /* 1 */ | 54 | /* 1 */ |
54 | u32 curr; | 55 | u32 curr; |
55 | /* 2 - 8 */ | 56 | /* 2 - 8 */ |
56 | struct ci13xxx_td td; | 57 | struct ci_hw_td td; |
57 | /* 9 */ | 58 | /* 9 */ |
58 | u32 RESERVED; | 59 | u32 RESERVED; |
59 | struct usb_ctrlrequest setup; | 60 | struct usb_ctrlrequest setup; |
60 | } __attribute__ ((packed, aligned(4))); | 61 | } __attribute__ ((packed, aligned(4))); |
61 | 62 | ||
63 | struct td_node { | ||
64 | struct list_head td; | ||
65 | dma_addr_t dma; | ||
66 | struct ci_hw_td *ptr; | ||
67 | }; | ||
68 | |||
62 | /** | 69 | /** |
63 | * struct ci13xxx_req - usb request representation | 70 | * struct ci_hw_req - usb request representation |
64 | * @req: request structure for gadget drivers | 71 | * @req: request structure for gadget drivers |
65 | * @queue: link to QH list | 72 | * @queue: link to QH list |
66 | * @ptr: transfer descriptor for this request | 73 | * @ptr: transfer descriptor for this request |
@@ -68,22 +75,19 @@ struct ci13xxx_qh { | |||
68 | * @zptr: transfer descriptor for the zero packet | 75 | * @zptr: transfer descriptor for the zero packet |
69 | * @zdma: dma address of the zero packet's transfer descriptor | 76 | * @zdma: dma address of the zero packet's transfer descriptor |
70 | */ | 77 | */ |
71 | struct ci13xxx_req { | 78 | struct ci_hw_req { |
72 | struct usb_request req; | 79 | struct usb_request req; |
73 | struct list_head queue; | 80 | struct list_head queue; |
74 | struct ci13xxx_td *ptr; | 81 | struct list_head tds; |
75 | dma_addr_t dma; | ||
76 | struct ci13xxx_td *zptr; | ||
77 | dma_addr_t zdma; | ||
78 | }; | 82 | }; |
79 | 83 | ||
80 | #ifdef CONFIG_USB_CHIPIDEA_UDC | 84 | #ifdef CONFIG_USB_CHIPIDEA_UDC |
81 | 85 | ||
82 | int ci_hdrc_gadget_init(struct ci13xxx *ci); | 86 | int ci_hdrc_gadget_init(struct ci_hdrc *ci); |
83 | 87 | ||
84 | #else | 88 | #else |
85 | 89 | ||
86 | static inline int ci_hdrc_gadget_init(struct ci13xxx *ci) | 90 | static inline int ci_hdrc_gadget_init(struct ci_hdrc *ci) |
87 | { | 91 | { |
88 | return -ENXIO; | 92 | return -ENXIO; |
89 | } | 93 | } |
diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c index 714a6bd810ed..ac5a46155200 100644 --- a/drivers/usb/chipidea/usbmisc_imx.c +++ b/drivers/usb/chipidea/usbmisc_imx.c | |||
@@ -16,7 +16,7 @@ | |||
16 | #include <linux/io.h> | 16 | #include <linux/io.h> |
17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
18 | 18 | ||
19 | #include "ci13xxx_imx.h" | 19 | #include "ci_hdrc_imx.h" |
20 | 20 | ||
21 | #define USB_DEV_MAX 4 | 21 | #define USB_DEV_MAX 4 |
22 | 22 | ||
@@ -175,6 +175,7 @@ static const struct of_device_id usbmisc_imx_dt_ids[] = { | |||
175 | }, | 175 | }, |
176 | { /* sentinel */ } | 176 | { /* sentinel */ } |
177 | }; | 177 | }; |
178 | MODULE_DEVICE_TABLE(of, usbmisc_imx_dt_ids); | ||
178 | 179 | ||
179 | static int usbmisc_imx_probe(struct platform_device *pdev) | 180 | static int usbmisc_imx_probe(struct platform_device *pdev) |
180 | { | 181 | { |
@@ -243,17 +244,7 @@ static struct platform_driver usbmisc_imx_driver = { | |||
243 | }, | 244 | }, |
244 | }; | 245 | }; |
245 | 246 | ||
246 | int usbmisc_imx_drv_init(void) | 247 | module_platform_driver(usbmisc_imx_driver); |
247 | { | ||
248 | return platform_driver_register(&usbmisc_imx_driver); | ||
249 | } | ||
250 | subsys_initcall(usbmisc_imx_drv_init); | ||
251 | |||
252 | void usbmisc_imx_drv_exit(void) | ||
253 | { | ||
254 | platform_driver_unregister(&usbmisc_imx_driver); | ||
255 | } | ||
256 | module_exit(usbmisc_imx_drv_exit); | ||
257 | 248 | ||
258 | MODULE_ALIAS("platform:usbmisc-imx"); | 249 | MODULE_ALIAS("platform:usbmisc-imx"); |
259 | MODULE_LICENSE("GPL v2"); | 250 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 9b1cbcf8fb7f..9f49bfe4c6f4 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
@@ -216,38 +216,6 @@ static int acm_start_wb(struct acm *acm, struct acm_wb *wb) | |||
216 | return rc; | 216 | return rc; |
217 | } | 217 | } |
218 | 218 | ||
219 | static int acm_write_start(struct acm *acm, int wbn) | ||
220 | { | ||
221 | unsigned long flags; | ||
222 | struct acm_wb *wb = &acm->wb[wbn]; | ||
223 | int rc; | ||
224 | |||
225 | spin_lock_irqsave(&acm->write_lock, flags); | ||
226 | if (!acm->dev) { | ||
227 | wb->use = 0; | ||
228 | spin_unlock_irqrestore(&acm->write_lock, flags); | ||
229 | return -ENODEV; | ||
230 | } | ||
231 | |||
232 | dev_vdbg(&acm->data->dev, "%s - susp_count %d\n", __func__, | ||
233 | acm->susp_count); | ||
234 | usb_autopm_get_interface_async(acm->control); | ||
235 | if (acm->susp_count) { | ||
236 | if (!acm->delayed_wb) | ||
237 | acm->delayed_wb = wb; | ||
238 | else | ||
239 | usb_autopm_put_interface_async(acm->control); | ||
240 | spin_unlock_irqrestore(&acm->write_lock, flags); | ||
241 | return 0; /* A white lie */ | ||
242 | } | ||
243 | usb_mark_last_busy(acm->dev); | ||
244 | |||
245 | rc = acm_start_wb(acm, wb); | ||
246 | spin_unlock_irqrestore(&acm->write_lock, flags); | ||
247 | |||
248 | return rc; | ||
249 | |||
250 | } | ||
251 | /* | 219 | /* |
252 | * attributes exported through sysfs | 220 | * attributes exported through sysfs |
253 | */ | 221 | */ |
@@ -653,13 +621,31 @@ static int acm_tty_write(struct tty_struct *tty, | |||
653 | } | 621 | } |
654 | wb = &acm->wb[wbn]; | 622 | wb = &acm->wb[wbn]; |
655 | 623 | ||
624 | if (!acm->dev) { | ||
625 | wb->use = 0; | ||
626 | spin_unlock_irqrestore(&acm->write_lock, flags); | ||
627 | return -ENODEV; | ||
628 | } | ||
629 | |||
656 | count = (count > acm->writesize) ? acm->writesize : count; | 630 | count = (count > acm->writesize) ? acm->writesize : count; |
657 | dev_vdbg(&acm->data->dev, "%s - write %d\n", __func__, count); | 631 | dev_vdbg(&acm->data->dev, "%s - write %d\n", __func__, count); |
658 | memcpy(wb->buf, buf, count); | 632 | memcpy(wb->buf, buf, count); |
659 | wb->len = count; | 633 | wb->len = count; |
634 | |||
635 | usb_autopm_get_interface_async(acm->control); | ||
636 | if (acm->susp_count) { | ||
637 | if (!acm->delayed_wb) | ||
638 | acm->delayed_wb = wb; | ||
639 | else | ||
640 | usb_autopm_put_interface_async(acm->control); | ||
641 | spin_unlock_irqrestore(&acm->write_lock, flags); | ||
642 | return count; /* A white lie */ | ||
643 | } | ||
644 | usb_mark_last_busy(acm->dev); | ||
645 | |||
646 | stat = acm_start_wb(acm, wb); | ||
660 | spin_unlock_irqrestore(&acm->write_lock, flags); | 647 | spin_unlock_irqrestore(&acm->write_lock, flags); |
661 | 648 | ||
662 | stat = acm_write_start(acm, wbn); | ||
663 | if (stat < 0) | 649 | if (stat < 0) |
664 | return stat; | 650 | return stat; |
665 | return count; | 651 | return count; |
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 4c5506ae5e45..609dbc2f7151 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c | |||
@@ -31,6 +31,8 @@ | |||
31 | #include <linux/usb/tmc.h> | 31 | #include <linux/usb/tmc.h> |
32 | 32 | ||
33 | 33 | ||
34 | #define RIGOL 1 | ||
35 | #define USBTMC_HEADER_SIZE 12 | ||
34 | #define USBTMC_MINOR_BASE 176 | 36 | #define USBTMC_MINOR_BASE 176 |
35 | 37 | ||
36 | /* | 38 | /* |
@@ -84,6 +86,8 @@ struct usbtmc_device_data { | |||
84 | u8 bTag_last_write; /* needed for abort */ | 86 | u8 bTag_last_write; /* needed for abort */ |
85 | u8 bTag_last_read; /* needed for abort */ | 87 | u8 bTag_last_read; /* needed for abort */ |
86 | 88 | ||
89 | u8 rigol_quirk; | ||
90 | |||
87 | /* attributes from the USB TMC spec for this device */ | 91 | /* attributes from the USB TMC spec for this device */ |
88 | u8 TermChar; | 92 | u8 TermChar; |
89 | bool TermCharEnabled; | 93 | bool TermCharEnabled; |
@@ -97,6 +101,16 @@ struct usbtmc_device_data { | |||
97 | }; | 101 | }; |
98 | #define to_usbtmc_data(d) container_of(d, struct usbtmc_device_data, kref) | 102 | #define to_usbtmc_data(d) container_of(d, struct usbtmc_device_data, kref) |
99 | 103 | ||
104 | struct usbtmc_ID_rigol_quirk { | ||
105 | __u16 idVendor; | ||
106 | __u16 idProduct; | ||
107 | }; | ||
108 | |||
109 | static const struct usbtmc_ID_rigol_quirk usbtmc_id_quirk[] = { | ||
110 | { 0x1ab1, 0x0588 }, | ||
111 | { 0, 0 } | ||
112 | }; | ||
113 | |||
100 | /* Forward declarations */ | 114 | /* Forward declarations */ |
101 | static struct usb_driver usbtmc_driver; | 115 | static struct usb_driver usbtmc_driver; |
102 | 116 | ||
@@ -361,6 +375,59 @@ exit: | |||
361 | return rv; | 375 | return rv; |
362 | } | 376 | } |
363 | 377 | ||
378 | /* | ||
379 | * Sends a REQUEST_DEV_DEP_MSG_IN message on the Bulk-IN endpoint. | ||
380 | * @transfer_size: number of bytes to request from the device. | ||
381 | * | ||
382 | * See the USBTMC specification, Table 4. | ||
383 | * | ||
384 | * Also updates bTag_last_write. | ||
385 | */ | ||
386 | static int send_request_dev_dep_msg_in(struct usbtmc_device_data *data, size_t transfer_size) | ||
387 | { | ||
388 | int retval; | ||
389 | u8 buffer[USBTMC_HEADER_SIZE]; | ||
390 | int actual; | ||
391 | |||
392 | /* Setup IO buffer for REQUEST_DEV_DEP_MSG_IN message | ||
393 | * Refer to class specs for details | ||
394 | */ | ||
395 | buffer[0] = 2; | ||
396 | buffer[1] = data->bTag; | ||
397 | buffer[2] = ~(data->bTag); | ||
398 | buffer[3] = 0; /* Reserved */ | ||
399 | buffer[4] = (transfer_size) & 255; | ||
400 | buffer[5] = ((transfer_size) >> 8) & 255; | ||
401 | buffer[6] = ((transfer_size) >> 16) & 255; | ||
402 | buffer[7] = ((transfer_size) >> 24) & 255; | ||
403 | buffer[8] = data->TermCharEnabled * 2; | ||
404 | /* Use term character? */ | ||
405 | buffer[9] = data->TermChar; | ||
406 | buffer[10] = 0; /* Reserved */ | ||
407 | buffer[11] = 0; /* Reserved */ | ||
408 | |||
409 | /* Send bulk URB */ | ||
410 | retval = usb_bulk_msg(data->usb_dev, | ||
411 | usb_sndbulkpipe(data->usb_dev, | ||
412 | data->bulk_out), | ||
413 | buffer, USBTMC_HEADER_SIZE, &actual, USBTMC_TIMEOUT); | ||
414 | |||
415 | /* Store bTag (in case we need to abort) */ | ||
416 | data->bTag_last_write = data->bTag; | ||
417 | |||
418 | /* Increment bTag -- and increment again if zero */ | ||
419 | data->bTag++; | ||
420 | if (!data->bTag) | ||
421 | (data->bTag)++; | ||
422 | |||
423 | if (retval < 0) { | ||
424 | dev_err(&data->intf->dev, "usb_bulk_msg in send_request_dev_dep_msg_in() returned %d\n", retval); | ||
425 | return retval; | ||
426 | } | ||
427 | |||
428 | return 0; | ||
429 | } | ||
430 | |||
364 | static ssize_t usbtmc_read(struct file *filp, char __user *buf, | 431 | static ssize_t usbtmc_read(struct file *filp, char __user *buf, |
365 | size_t count, loff_t *f_pos) | 432 | size_t count, loff_t *f_pos) |
366 | { | 433 | { |
@@ -388,51 +455,39 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, | |||
388 | goto exit; | 455 | goto exit; |
389 | } | 456 | } |
390 | 457 | ||
391 | remaining = count; | 458 | if (data->rigol_quirk) { |
392 | done = 0; | 459 | dev_dbg(dev, "usb_bulk_msg_in: count(%zu)\n", count); |
393 | 460 | ||
394 | while (remaining > 0) { | 461 | retval = send_request_dev_dep_msg_in(data, count); |
395 | if (remaining > USBTMC_SIZE_IOBUFFER - 12 - 3) | ||
396 | this_part = USBTMC_SIZE_IOBUFFER - 12 - 3; | ||
397 | else | ||
398 | this_part = remaining; | ||
399 | 462 | ||
400 | /* Setup IO buffer for DEV_DEP_MSG_IN message | 463 | if (retval < 0) { |
401 | * Refer to class specs for details | 464 | if (data->auto_abort) |
402 | */ | 465 | usbtmc_ioctl_abort_bulk_out(data); |
403 | buffer[0] = 2; | 466 | goto exit; |
404 | buffer[1] = data->bTag; | 467 | } |
405 | buffer[2] = ~(data->bTag); | 468 | } |
406 | buffer[3] = 0; /* Reserved */ | ||
407 | buffer[4] = (this_part) & 255; | ||
408 | buffer[5] = ((this_part) >> 8) & 255; | ||
409 | buffer[6] = ((this_part) >> 16) & 255; | ||
410 | buffer[7] = ((this_part) >> 24) & 255; | ||
411 | buffer[8] = data->TermCharEnabled * 2; | ||
412 | /* Use term character? */ | ||
413 | buffer[9] = data->TermChar; | ||
414 | buffer[10] = 0; /* Reserved */ | ||
415 | buffer[11] = 0; /* Reserved */ | ||
416 | 469 | ||
417 | /* Send bulk URB */ | 470 | /* Loop until we have fetched everything we requested */ |
418 | retval = usb_bulk_msg(data->usb_dev, | 471 | remaining = count; |
419 | usb_sndbulkpipe(data->usb_dev, | 472 | this_part = remaining; |
420 | data->bulk_out), | 473 | done = 0; |
421 | buffer, 12, &actual, USBTMC_TIMEOUT); | ||
422 | 474 | ||
423 | /* Store bTag (in case we need to abort) */ | 475 | while (remaining > 0) { |
424 | data->bTag_last_write = data->bTag; | 476 | if (!(data->rigol_quirk)) { |
477 | dev_dbg(dev, "usb_bulk_msg_in: remaining(%zu), count(%zu)\n", remaining, count); | ||
425 | 478 | ||
426 | /* Increment bTag -- and increment again if zero */ | 479 | if (remaining > USBTMC_SIZE_IOBUFFER - USBTMC_HEADER_SIZE - 3) |
427 | data->bTag++; | 480 | this_part = USBTMC_SIZE_IOBUFFER - USBTMC_HEADER_SIZE - 3; |
428 | if (!data->bTag) | 481 | else |
429 | (data->bTag)++; | 482 | this_part = remaining; |
430 | 483 | ||
431 | if (retval < 0) { | 484 | retval = send_request_dev_dep_msg_in(data, this_part); |
485 | if (retval < 0) { | ||
432 | dev_err(dev, "usb_bulk_msg returned %d\n", retval); | 486 | dev_err(dev, "usb_bulk_msg returned %d\n", retval); |
433 | if (data->auto_abort) | 487 | if (data->auto_abort) |
434 | usbtmc_ioctl_abort_bulk_out(data); | 488 | usbtmc_ioctl_abort_bulk_out(data); |
435 | goto exit; | 489 | goto exit; |
490 | } | ||
436 | } | 491 | } |
437 | 492 | ||
438 | /* Send bulk URB */ | 493 | /* Send bulk URB */ |
@@ -442,51 +497,109 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, | |||
442 | buffer, USBTMC_SIZE_IOBUFFER, &actual, | 497 | buffer, USBTMC_SIZE_IOBUFFER, &actual, |
443 | USBTMC_TIMEOUT); | 498 | USBTMC_TIMEOUT); |
444 | 499 | ||
500 | dev_dbg(dev, "usb_bulk_msg: retval(%u), done(%zu), remaining(%zu), actual(%d)\n", retval, done, remaining, actual); | ||
501 | |||
445 | /* Store bTag (in case we need to abort) */ | 502 | /* Store bTag (in case we need to abort) */ |
446 | data->bTag_last_read = data->bTag; | 503 | data->bTag_last_read = data->bTag; |
447 | 504 | ||
448 | if (retval < 0) { | 505 | if (retval < 0) { |
449 | dev_err(dev, "Unable to read data, error %d\n", retval); | 506 | dev_dbg(dev, "Unable to read data, error %d\n", retval); |
450 | if (data->auto_abort) | 507 | if (data->auto_abort) |
451 | usbtmc_ioctl_abort_bulk_in(data); | 508 | usbtmc_ioctl_abort_bulk_in(data); |
452 | goto exit; | 509 | goto exit; |
453 | } | 510 | } |
454 | 511 | ||
455 | /* How many characters did the instrument send? */ | 512 | /* Parse header in first packet */ |
456 | n_characters = buffer[4] + | 513 | if ((done == 0) || (!(data->rigol_quirk))) { |
457 | (buffer[5] << 8) + | 514 | /* Sanity checks for the header */ |
458 | (buffer[6] << 16) + | 515 | if (actual < USBTMC_HEADER_SIZE) { |
459 | (buffer[7] << 24); | 516 | dev_err(dev, "Device sent too small first packet: %u < %u\n", actual, USBTMC_HEADER_SIZE); |
517 | if (data->auto_abort) | ||
518 | usbtmc_ioctl_abort_bulk_in(data); | ||
519 | goto exit; | ||
520 | } | ||
460 | 521 | ||
461 | /* Ensure the instrument doesn't lie about it */ | 522 | if (buffer[0] != 2) { |
462 | if(n_characters > actual - 12) { | 523 | dev_err(dev, "Device sent reply with wrong MsgID: %u != 2\n", buffer[0]); |
463 | dev_err(dev, "Device lies about message size: %u > %d\n", n_characters, actual - 12); | 524 | if (data->auto_abort) |
464 | n_characters = actual - 12; | 525 | usbtmc_ioctl_abort_bulk_in(data); |
465 | } | 526 | goto exit; |
527 | } | ||
466 | 528 | ||
467 | /* Ensure the instrument doesn't send more back than requested */ | 529 | if (buffer[1] != data->bTag_last_write) { |
468 | if(n_characters > this_part) { | 530 | dev_err(dev, "Device sent reply with wrong bTag: %u != %u\n", buffer[1], data->bTag_last_write); |
469 | dev_err(dev, "Device returns more than requested: %zu > %zu\n", done + n_characters, done + this_part); | 531 | if (data->auto_abort) |
470 | n_characters = this_part; | 532 | usbtmc_ioctl_abort_bulk_in(data); |
471 | } | 533 | goto exit; |
534 | } | ||
472 | 535 | ||
473 | /* Bound amount of data received by amount of data requested */ | 536 | /* How many characters did the instrument send? */ |
474 | if (n_characters > this_part) | 537 | n_characters = buffer[4] + |
475 | n_characters = this_part; | 538 | (buffer[5] << 8) + |
539 | (buffer[6] << 16) + | ||
540 | (buffer[7] << 24); | ||
476 | 541 | ||
477 | /* Copy buffer to user space */ | 542 | if (n_characters > this_part) { |
478 | if (copy_to_user(buf + done, &buffer[12], n_characters)) { | 543 | dev_err(dev, "Device wants to return more data than requested: %u > %zu\n", n_characters, count); |
479 | /* There must have been an addressing problem */ | 544 | if (data->auto_abort) |
480 | retval = -EFAULT; | 545 | usbtmc_ioctl_abort_bulk_in(data); |
481 | goto exit; | 546 | goto exit; |
547 | } | ||
548 | |||
549 | /* Remove the USBTMC header */ | ||
550 | actual -= USBTMC_HEADER_SIZE; | ||
551 | |||
552 | /* Check if the message is smaller than requested */ | ||
553 | if (data->rigol_quirk) { | ||
554 | if (remaining > n_characters) | ||
555 | remaining = n_characters; | ||
556 | /* Remove padding if it exists */ | ||
557 | if (actual > remaining) | ||
558 | actual = remaining; | ||
559 | } | ||
560 | else { | ||
561 | if (this_part > n_characters) | ||
562 | this_part = n_characters; | ||
563 | /* Remove padding if it exists */ | ||
564 | if (actual > this_part) | ||
565 | actual = this_part; | ||
566 | } | ||
567 | |||
568 | dev_dbg(dev, "Bulk-IN header: N_characters(%u), bTransAttr(%u)\n", n_characters, buffer[8]); | ||
569 | |||
570 | remaining -= actual; | ||
571 | |||
572 | /* Terminate if end-of-message bit received from device */ | ||
573 | if ((buffer[8] & 0x01) && (actual >= n_characters)) | ||
574 | remaining = 0; | ||
575 | |||
576 | dev_dbg(dev, "Bulk-IN header: remaining(%zu), buf(%p), buffer(%p) done(%zu)\n", remaining,buf,buffer,done); | ||
577 | |||
578 | |||
579 | /* Copy buffer to user space */ | ||
580 | if (copy_to_user(buf + done, &buffer[USBTMC_HEADER_SIZE], actual)) { | ||
581 | /* There must have been an addressing problem */ | ||
582 | retval = -EFAULT; | ||
583 | goto exit; | ||
584 | } | ||
585 | done += actual; | ||
482 | } | 586 | } |
587 | else { | ||
588 | if (actual > remaining) | ||
589 | actual = remaining; | ||
590 | |||
591 | remaining -= actual; | ||
592 | |||
593 | dev_dbg(dev, "Bulk-IN header cont: actual(%u), done(%zu), remaining(%zu), buf(%p), buffer(%p)\n", actual, done, remaining,buf,buffer); | ||
483 | 594 | ||
484 | done += n_characters; | 595 | /* Copy buffer to user space */ |
485 | /* Terminate if end-of-message bit received from device */ | 596 | if (copy_to_user(buf + done, buffer, actual)) { |
486 | if ((buffer[8] & 0x01) && (actual >= n_characters + 12)) | 597 | /* There must have been an addressing problem */ |
487 | remaining = 0; | 598 | retval = -EFAULT; |
488 | else | 599 | goto exit; |
489 | remaining -= n_characters; | 600 | } |
601 | done += actual; | ||
602 | } | ||
490 | } | 603 | } |
491 | 604 | ||
492 | /* Update file position value */ | 605 | /* Update file position value */ |
@@ -527,8 +640,8 @@ static ssize_t usbtmc_write(struct file *filp, const char __user *buf, | |||
527 | done = 0; | 640 | done = 0; |
528 | 641 | ||
529 | while (remaining > 0) { | 642 | while (remaining > 0) { |
530 | if (remaining > USBTMC_SIZE_IOBUFFER - 12) { | 643 | if (remaining > USBTMC_SIZE_IOBUFFER - USBTMC_HEADER_SIZE) { |
531 | this_part = USBTMC_SIZE_IOBUFFER - 12; | 644 | this_part = USBTMC_SIZE_IOBUFFER - USBTMC_HEADER_SIZE; |
532 | buffer[8] = 0; | 645 | buffer[8] = 0; |
533 | } else { | 646 | } else { |
534 | this_part = remaining; | 647 | this_part = remaining; |
@@ -549,13 +662,13 @@ static ssize_t usbtmc_write(struct file *filp, const char __user *buf, | |||
549 | buffer[10] = 0; /* Reserved */ | 662 | buffer[10] = 0; /* Reserved */ |
550 | buffer[11] = 0; /* Reserved */ | 663 | buffer[11] = 0; /* Reserved */ |
551 | 664 | ||
552 | if (copy_from_user(&buffer[12], buf + done, this_part)) { | 665 | if (copy_from_user(&buffer[USBTMC_HEADER_SIZE], buf + done, this_part)) { |
553 | retval = -EFAULT; | 666 | retval = -EFAULT; |
554 | goto exit; | 667 | goto exit; |
555 | } | 668 | } |
556 | 669 | ||
557 | n_bytes = roundup(12 + this_part, 4); | 670 | n_bytes = roundup(USBTMC_HEADER_SIZE + this_part, 4); |
558 | memset(buffer + 12 + this_part, 0, n_bytes - (12 + this_part)); | 671 | memset(buffer + USBTMC_HEADER_SIZE + this_part, 0, n_bytes - (USBTMC_HEADER_SIZE + this_part)); |
559 | 672 | ||
560 | do { | 673 | do { |
561 | retval = usb_bulk_msg(data->usb_dev, | 674 | retval = usb_bulk_msg(data->usb_dev, |
@@ -1003,6 +1116,20 @@ static int usbtmc_probe(struct usb_interface *intf, | |||
1003 | mutex_init(&data->io_mutex); | 1116 | mutex_init(&data->io_mutex); |
1004 | data->zombie = 0; | 1117 | data->zombie = 0; |
1005 | 1118 | ||
1119 | /* Determine if it is a Rigol or not */ | ||
1120 | data->rigol_quirk = 0; | ||
1121 | dev_dbg(&intf->dev, "Trying to find if device Vendor 0x%04X Product 0x%04X has the RIGOL quirk\n", | ||
1122 | data->usb_dev->descriptor.idVendor, | ||
1123 | data->usb_dev->descriptor.idProduct); | ||
1124 | for(n = 0; usbtmc_id_quirk[n].idVendor > 0; n++) { | ||
1125 | if ((usbtmc_id_quirk[n].idVendor == data->usb_dev->descriptor.idVendor) && | ||
1126 | (usbtmc_id_quirk[n].idProduct == data->usb_dev->descriptor.idProduct)) { | ||
1127 | dev_dbg(&intf->dev, "Setting this device as having the RIGOL quirk\n"); | ||
1128 | data->rigol_quirk = 1; | ||
1129 | break; | ||
1130 | } | ||
1131 | } | ||
1132 | |||
1006 | /* Initialize USBTMC bTag and other fields */ | 1133 | /* Initialize USBTMC bTag and other fields */ |
1007 | data->bTag = 1; | 1134 | data->bTag = 1; |
1008 | data->TermCharEnabled = 0; | 1135 | data->TermCharEnabled = 0; |
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index c88c4fb9459d..05986507b585 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c | |||
@@ -49,14 +49,14 @@ | |||
49 | #include <linux/security.h> | 49 | #include <linux/security.h> |
50 | #include <linux/user_namespace.h> | 50 | #include <linux/user_namespace.h> |
51 | #include <linux/scatterlist.h> | 51 | #include <linux/scatterlist.h> |
52 | #include <asm/uaccess.h> | 52 | #include <linux/uaccess.h> |
53 | #include <asm/byteorder.h> | 53 | #include <asm/byteorder.h> |
54 | #include <linux/moduleparam.h> | 54 | #include <linux/moduleparam.h> |
55 | 55 | ||
56 | #include "usb.h" | 56 | #include "usb.h" |
57 | 57 | ||
58 | #define USB_MAXBUS 64 | 58 | #define USB_MAXBUS 64 |
59 | #define USB_DEVICE_MAX USB_MAXBUS * 128 | 59 | #define USB_DEVICE_MAX (USB_MAXBUS * 128) |
60 | #define USB_SG_SIZE 16384 /* split-size for large txs */ | 60 | #define USB_SG_SIZE 16384 /* split-size for large txs */ |
61 | 61 | ||
62 | /* Mutual exclusion for removal, open, and release */ | 62 | /* Mutual exclusion for removal, open, and release */ |
@@ -1804,7 +1804,8 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl) | |||
1804 | 1804 | ||
1805 | /* alloc buffer */ | 1805 | /* alloc buffer */ |
1806 | if ((size = _IOC_SIZE(ctl->ioctl_code)) > 0) { | 1806 | if ((size = _IOC_SIZE(ctl->ioctl_code)) > 0) { |
1807 | if ((buf = kmalloc(size, GFP_KERNEL)) == NULL) | 1807 | buf = kmalloc(size, GFP_KERNEL); |
1808 | if (buf == NULL) | ||
1808 | return -ENOMEM; | 1809 | return -ENOMEM; |
1809 | if ((_IOC_DIR(ctl->ioctl_code) & _IOC_WRITE)) { | 1810 | if ((_IOC_DIR(ctl->ioctl_code) & _IOC_WRITE)) { |
1810 | if (copy_from_user(buf, ctl->data, size)) { | 1811 | if (copy_from_user(buf, ctl->data, size)) { |
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index e5387a47ef6f..6a4c40766f0f 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c | |||
@@ -94,7 +94,7 @@ static int init_usb_class(void) | |||
94 | kref_init(&usb_class->kref); | 94 | kref_init(&usb_class->kref); |
95 | usb_class->class = class_create(THIS_MODULE, "usbmisc"); | 95 | usb_class->class = class_create(THIS_MODULE, "usbmisc"); |
96 | if (IS_ERR(usb_class->class)) { | 96 | if (IS_ERR(usb_class->class)) { |
97 | result = IS_ERR(usb_class->class); | 97 | result = PTR_ERR(usb_class->class); |
98 | printk(KERN_ERR "class_create failed for usb devices\n"); | 98 | printk(KERN_ERR "class_create failed for usb devices\n"); |
99 | kfree(usb_class); | 99 | kfree(usb_class); |
100 | usb_class = NULL; | 100 | usb_class = NULL; |
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index d53547d2e4c7..014dc996b4f6 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
@@ -149,6 +149,27 @@ static const u8 usb3_rh_dev_descriptor[18] = { | |||
149 | 0x01 /* __u8 bNumConfigurations; */ | 149 | 0x01 /* __u8 bNumConfigurations; */ |
150 | }; | 150 | }; |
151 | 151 | ||
152 | /* usb 2.5 (wireless USB 1.0) root hub device descriptor */ | ||
153 | static const u8 usb25_rh_dev_descriptor[18] = { | ||
154 | 0x12, /* __u8 bLength; */ | ||
155 | 0x01, /* __u8 bDescriptorType; Device */ | ||
156 | 0x50, 0x02, /* __le16 bcdUSB; v2.5 */ | ||
157 | |||
158 | 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ | ||
159 | 0x00, /* __u8 bDeviceSubClass; */ | ||
160 | 0x00, /* __u8 bDeviceProtocol; [ usb 2.0 no TT ] */ | ||
161 | 0xFF, /* __u8 bMaxPacketSize0; always 0xFF (WUSB Spec 7.4.1). */ | ||
162 | |||
163 | 0x6b, 0x1d, /* __le16 idVendor; Linux Foundation 0x1d6b */ | ||
164 | 0x02, 0x00, /* __le16 idProduct; device 0x0002 */ | ||
165 | KERNEL_VER, KERNEL_REL, /* __le16 bcdDevice */ | ||
166 | |||
167 | 0x03, /* __u8 iManufacturer; */ | ||
168 | 0x02, /* __u8 iProduct; */ | ||
169 | 0x01, /* __u8 iSerialNumber; */ | ||
170 | 0x01 /* __u8 bNumConfigurations; */ | ||
171 | }; | ||
172 | |||
152 | /* usb 2.0 root hub device descriptor */ | 173 | /* usb 2.0 root hub device descriptor */ |
153 | static const u8 usb2_rh_dev_descriptor [18] = { | 174 | static const u8 usb2_rh_dev_descriptor [18] = { |
154 | 0x12, /* __u8 bLength; */ | 175 | 0x12, /* __u8 bLength; */ |
@@ -527,6 +548,9 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) | |||
527 | case HCD_USB3: | 548 | case HCD_USB3: |
528 | bufp = usb3_rh_dev_descriptor; | 549 | bufp = usb3_rh_dev_descriptor; |
529 | break; | 550 | break; |
551 | case HCD_USB25: | ||
552 | bufp = usb25_rh_dev_descriptor; | ||
553 | break; | ||
530 | case HCD_USB2: | 554 | case HCD_USB2: |
531 | bufp = usb2_rh_dev_descriptor; | 555 | bufp = usb2_rh_dev_descriptor; |
532 | break; | 556 | break; |
@@ -546,6 +570,7 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) | |||
546 | bufp = ss_rh_config_descriptor; | 570 | bufp = ss_rh_config_descriptor; |
547 | len = sizeof ss_rh_config_descriptor; | 571 | len = sizeof ss_rh_config_descriptor; |
548 | break; | 572 | break; |
573 | case HCD_USB25: | ||
549 | case HCD_USB2: | 574 | case HCD_USB2: |
550 | bufp = hs_rh_config_descriptor; | 575 | bufp = hs_rh_config_descriptor; |
551 | len = sizeof hs_rh_config_descriptor; | 576 | len = sizeof hs_rh_config_descriptor; |
@@ -2511,6 +2536,9 @@ int usb_add_hcd(struct usb_hcd *hcd, | |||
2511 | case HCD_USB2: | 2536 | case HCD_USB2: |
2512 | rhdev->speed = USB_SPEED_HIGH; | 2537 | rhdev->speed = USB_SPEED_HIGH; |
2513 | break; | 2538 | break; |
2539 | case HCD_USB25: | ||
2540 | rhdev->speed = USB_SPEED_WIRELESS; | ||
2541 | break; | ||
2514 | case HCD_USB3: | 2542 | case HCD_USB3: |
2515 | rhdev->speed = USB_SPEED_SUPER; | 2543 | rhdev->speed = USB_SPEED_SUPER; |
2516 | break; | 2544 | break; |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index feef9351463d..4191db32f12c 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -718,18 +718,18 @@ static void hub_tt_work(struct work_struct *work) | |||
718 | 718 | ||
719 | /** | 719 | /** |
720 | * usb_hub_set_port_power - control hub port's power state | 720 | * usb_hub_set_port_power - control hub port's power state |
721 | * @hdev: target hub | 721 | * @hdev: USB device belonging to the usb hub |
722 | * @hub: target hub | ||
722 | * @port1: port index | 723 | * @port1: port index |
723 | * @set: expected status | 724 | * @set: expected status |
724 | * | 725 | * |
725 | * call this function to control port's power via setting or | 726 | * call this function to control port's power via setting or |
726 | * clearing the port's PORT_POWER feature. | 727 | * clearing the port's PORT_POWER feature. |
727 | */ | 728 | */ |
728 | int usb_hub_set_port_power(struct usb_device *hdev, int port1, | 729 | int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub, |
729 | bool set) | 730 | int port1, bool set) |
730 | { | 731 | { |
731 | int ret; | 732 | int ret; |
732 | struct usb_hub *hub = usb_hub_to_struct_hub(hdev); | ||
733 | struct usb_port *port_dev = hub->ports[port1 - 1]; | 733 | struct usb_port *port_dev = hub->ports[port1 - 1]; |
734 | 734 | ||
735 | if (set) | 735 | if (set) |
@@ -1769,15 +1769,17 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data) | |||
1769 | static int find_port_owner(struct usb_device *hdev, unsigned port1, | 1769 | static int find_port_owner(struct usb_device *hdev, unsigned port1, |
1770 | struct dev_state ***ppowner) | 1770 | struct dev_state ***ppowner) |
1771 | { | 1771 | { |
1772 | struct usb_hub *hub = usb_hub_to_struct_hub(hdev); | ||
1773 | |||
1772 | if (hdev->state == USB_STATE_NOTATTACHED) | 1774 | if (hdev->state == USB_STATE_NOTATTACHED) |
1773 | return -ENODEV; | 1775 | return -ENODEV; |
1774 | if (port1 == 0 || port1 > hdev->maxchild) | 1776 | if (port1 == 0 || port1 > hdev->maxchild) |
1775 | return -EINVAL; | 1777 | return -EINVAL; |
1776 | 1778 | ||
1777 | /* This assumes that devices not managed by the hub driver | 1779 | /* Devices not managed by the hub driver |
1778 | * will always have maxchild equal to 0. | 1780 | * will always have maxchild equal to 0. |
1779 | */ | 1781 | */ |
1780 | *ppowner = &(usb_hub_to_struct_hub(hdev)->ports[port1 - 1]->port_owner); | 1782 | *ppowner = &(hub->ports[port1 - 1]->port_owner); |
1781 | return 0; | 1783 | return 0; |
1782 | } | 1784 | } |
1783 | 1785 | ||
@@ -5323,7 +5325,8 @@ void usb_set_hub_port_connect_type(struct usb_device *hdev, int port1, | |||
5323 | { | 5325 | { |
5324 | struct usb_hub *hub = usb_hub_to_struct_hub(hdev); | 5326 | struct usb_hub *hub = usb_hub_to_struct_hub(hdev); |
5325 | 5327 | ||
5326 | hub->ports[port1 - 1]->connect_type = type; | 5328 | if (hub) |
5329 | hub->ports[port1 - 1]->connect_type = type; | ||
5327 | } | 5330 | } |
5328 | 5331 | ||
5329 | /** | 5332 | /** |
@@ -5339,6 +5342,9 @@ usb_get_hub_port_connect_type(struct usb_device *hdev, int port1) | |||
5339 | { | 5342 | { |
5340 | struct usb_hub *hub = usb_hub_to_struct_hub(hdev); | 5343 | struct usb_hub *hub = usb_hub_to_struct_hub(hdev); |
5341 | 5344 | ||
5345 | if (!hub) | ||
5346 | return USB_PORT_CONNECT_TYPE_UNKNOWN; | ||
5347 | |||
5342 | return hub->ports[port1 - 1]->connect_type; | 5348 | return hub->ports[port1 - 1]->connect_type; |
5343 | } | 5349 | } |
5344 | 5350 | ||
@@ -5397,6 +5403,9 @@ acpi_handle usb_get_hub_port_acpi_handle(struct usb_device *hdev, | |||
5397 | { | 5403 | { |
5398 | struct usb_hub *hub = usb_hub_to_struct_hub(hdev); | 5404 | struct usb_hub *hub = usb_hub_to_struct_hub(hdev); |
5399 | 5405 | ||
5406 | if (!hub) | ||
5407 | return NULL; | ||
5408 | |||
5400 | return DEVICE_ACPI_HANDLE(&hub->ports[port1 - 1]->dev); | 5409 | return DEVICE_ACPI_HANDLE(&hub->ports[port1 - 1]->dev); |
5401 | } | 5410 | } |
5402 | #endif | 5411 | #endif |
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h index 80ab9ee07017..6508e02b3dac 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h | |||
@@ -100,7 +100,7 @@ extern int usb_hub_create_port_device(struct usb_hub *hub, | |||
100 | int port1); | 100 | int port1); |
101 | extern void usb_hub_remove_port_device(struct usb_hub *hub, | 101 | extern void usb_hub_remove_port_device(struct usb_hub *hub, |
102 | int port1); | 102 | int port1); |
103 | extern int usb_hub_set_port_power(struct usb_device *hdev, | 103 | extern int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub, |
104 | int port1, bool set); | 104 | int port1, bool set); |
105 | extern struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev); | 105 | extern struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev); |
106 | extern int hub_port_debounce(struct usb_hub *hub, int port1, | 106 | extern int hub_port_debounce(struct usb_hub *hub, int port1, |
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 444d30e3a78b..e7ee1e451660 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c | |||
@@ -252,7 +252,7 @@ static void sg_clean(struct usb_sg_request *io) | |||
252 | { | 252 | { |
253 | if (io->urbs) { | 253 | if (io->urbs) { |
254 | while (io->entries--) | 254 | while (io->entries--) |
255 | usb_free_urb(io->urbs [io->entries]); | 255 | usb_free_urb(io->urbs[io->entries]); |
256 | kfree(io->urbs); | 256 | kfree(io->urbs); |
257 | io->urbs = NULL; | 257 | io->urbs = NULL; |
258 | } | 258 | } |
@@ -300,10 +300,10 @@ static void sg_complete(struct urb *urb) | |||
300 | */ | 300 | */ |
301 | spin_unlock(&io->lock); | 301 | spin_unlock(&io->lock); |
302 | for (i = 0, found = 0; i < io->entries; i++) { | 302 | for (i = 0, found = 0; i < io->entries; i++) { |
303 | if (!io->urbs [i] || !io->urbs [i]->dev) | 303 | if (!io->urbs[i] || !io->urbs[i]->dev) |
304 | continue; | 304 | continue; |
305 | if (found) { | 305 | if (found) { |
306 | retval = usb_unlink_urb(io->urbs [i]); | 306 | retval = usb_unlink_urb(io->urbs[i]); |
307 | if (retval != -EINPROGRESS && | 307 | if (retval != -EINPROGRESS && |
308 | retval != -ENODEV && | 308 | retval != -ENODEV && |
309 | retval != -EBUSY && | 309 | retval != -EBUSY && |
@@ -311,7 +311,7 @@ static void sg_complete(struct urb *urb) | |||
311 | dev_err(&io->dev->dev, | 311 | dev_err(&io->dev->dev, |
312 | "%s, unlink --> %d\n", | 312 | "%s, unlink --> %d\n", |
313 | __func__, retval); | 313 | __func__, retval); |
314 | } else if (urb == io->urbs [i]) | 314 | } else if (urb == io->urbs[i]) |
315 | found = 1; | 315 | found = 1; |
316 | } | 316 | } |
317 | spin_lock(&io->lock); | 317 | spin_lock(&io->lock); |
@@ -379,7 +379,7 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev, | |||
379 | } | 379 | } |
380 | 380 | ||
381 | /* initialize all the urbs we'll use */ | 381 | /* initialize all the urbs we'll use */ |
382 | io->urbs = kmalloc(io->entries * sizeof *io->urbs, mem_flags); | 382 | io->urbs = kmalloc(io->entries * sizeof(*io->urbs), mem_flags); |
383 | if (!io->urbs) | 383 | if (!io->urbs) |
384 | goto nomem; | 384 | goto nomem; |
385 | 385 | ||
@@ -511,7 +511,7 @@ void usb_sg_wait(struct usb_sg_request *io) | |||
511 | int retval; | 511 | int retval; |
512 | 512 | ||
513 | io->urbs[i]->dev = io->dev; | 513 | io->urbs[i]->dev = io->dev; |
514 | retval = usb_submit_urb(io->urbs [i], GFP_ATOMIC); | 514 | retval = usb_submit_urb(io->urbs[i], GFP_ATOMIC); |
515 | 515 | ||
516 | /* after we submit, let completions or cancelations fire; | 516 | /* after we submit, let completions or cancelations fire; |
517 | * we handshake using io->status. | 517 | * we handshake using io->status. |
@@ -586,9 +586,9 @@ void usb_sg_cancel(struct usb_sg_request *io) | |||
586 | for (i = 0; i < io->entries; i++) { | 586 | for (i = 0; i < io->entries; i++) { |
587 | int retval; | 587 | int retval; |
588 | 588 | ||
589 | if (!io->urbs [i]->dev) | 589 | if (!io->urbs[i]->dev) |
590 | continue; | 590 | continue; |
591 | retval = usb_unlink_urb(io->urbs [i]); | 591 | retval = usb_unlink_urb(io->urbs[i]); |
592 | if (retval != -EINPROGRESS | 592 | if (retval != -EINPROGRESS |
593 | && retval != -ENODEV | 593 | && retval != -ENODEV |
594 | && retval != -EBUSY | 594 | && retval != -EBUSY |
diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index b8bad294eeb8..5fd3fee58f8b 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c | |||
@@ -86,7 +86,7 @@ static int usb_port_runtime_resume(struct device *dev) | |||
86 | usb_autopm_get_interface(intf); | 86 | usb_autopm_get_interface(intf); |
87 | set_bit(port1, hub->busy_bits); | 87 | set_bit(port1, hub->busy_bits); |
88 | 88 | ||
89 | retval = usb_hub_set_port_power(hdev, port1, true); | 89 | retval = usb_hub_set_port_power(hdev, hub, port1, true); |
90 | if (port_dev->child && !retval) { | 90 | if (port_dev->child && !retval) { |
91 | /* | 91 | /* |
92 | * Wait for usb hub port to be reconnected in order to make | 92 | * Wait for usb hub port to be reconnected in order to make |
@@ -128,7 +128,7 @@ static int usb_port_runtime_suspend(struct device *dev) | |||
128 | 128 | ||
129 | usb_autopm_get_interface(intf); | 129 | usb_autopm_get_interface(intf); |
130 | set_bit(port1, hub->busy_bits); | 130 | set_bit(port1, hub->busy_bits); |
131 | retval = usb_hub_set_port_power(hdev, port1, false); | 131 | retval = usb_hub_set_port_power(hdev, hub, port1, false); |
132 | usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_CONNECTION); | 132 | usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_CONNECTION); |
133 | usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_ENABLE); | 133 | usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_ENABLE); |
134 | clear_bit(port1, hub->busy_bits); | 134 | clear_bit(port1, hub->busy_bits); |
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index aa38db44818a..d9284b998bd7 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c | |||
@@ -497,8 +497,62 @@ set_usb2_hardware_lpm(struct device *dev, struct device_attribute *attr, | |||
497 | static DEVICE_ATTR(usb2_hardware_lpm, S_IRUGO | S_IWUSR, show_usb2_hardware_lpm, | 497 | static DEVICE_ATTR(usb2_hardware_lpm, S_IRUGO | S_IWUSR, show_usb2_hardware_lpm, |
498 | set_usb2_hardware_lpm); | 498 | set_usb2_hardware_lpm); |
499 | 499 | ||
500 | static ssize_t | ||
501 | show_usb2_lpm_l1_timeout(struct device *dev, struct device_attribute *attr, | ||
502 | char *buf) | ||
503 | { | ||
504 | struct usb_device *udev = to_usb_device(dev); | ||
505 | return sprintf(buf, "%d\n", udev->l1_params.timeout); | ||
506 | } | ||
507 | |||
508 | static ssize_t | ||
509 | set_usb2_lpm_l1_timeout(struct device *dev, struct device_attribute *attr, | ||
510 | const char *buf, size_t count) | ||
511 | { | ||
512 | struct usb_device *udev = to_usb_device(dev); | ||
513 | u16 timeout; | ||
514 | |||
515 | if (kstrtou16(buf, 0, &timeout)) | ||
516 | return -EINVAL; | ||
517 | |||
518 | udev->l1_params.timeout = timeout; | ||
519 | |||
520 | return count; | ||
521 | } | ||
522 | |||
523 | static DEVICE_ATTR(usb2_lpm_l1_timeout, S_IRUGO | S_IWUSR, | ||
524 | show_usb2_lpm_l1_timeout, set_usb2_lpm_l1_timeout); | ||
525 | |||
526 | static ssize_t | ||
527 | show_usb2_lpm_besl(struct device *dev, struct device_attribute *attr, | ||
528 | char *buf) | ||
529 | { | ||
530 | struct usb_device *udev = to_usb_device(dev); | ||
531 | return sprintf(buf, "%d\n", udev->l1_params.besl); | ||
532 | } | ||
533 | |||
534 | static ssize_t | ||
535 | set_usb2_lpm_besl(struct device *dev, struct device_attribute *attr, | ||
536 | const char *buf, size_t count) | ||
537 | { | ||
538 | struct usb_device *udev = to_usb_device(dev); | ||
539 | u8 besl; | ||
540 | |||
541 | if (kstrtou8(buf, 0, &besl) || besl > 15) | ||
542 | return -EINVAL; | ||
543 | |||
544 | udev->l1_params.besl = besl; | ||
545 | |||
546 | return count; | ||
547 | } | ||
548 | |||
549 | static DEVICE_ATTR(usb2_lpm_besl, S_IRUGO | S_IWUSR, | ||
550 | show_usb2_lpm_besl, set_usb2_lpm_besl); | ||
551 | |||
500 | static struct attribute *usb2_hardware_lpm_attr[] = { | 552 | static struct attribute *usb2_hardware_lpm_attr[] = { |
501 | &dev_attr_usb2_hardware_lpm.attr, | 553 | &dev_attr_usb2_hardware_lpm.attr, |
554 | &dev_attr_usb2_lpm_l1_timeout.attr, | ||
555 | &dev_attr_usb2_lpm_besl.attr, | ||
502 | NULL, | 556 | NULL, |
503 | }; | 557 | }; |
504 | static struct attribute_group usb2_hardware_lpm_attr_group = { | 558 | static struct attribute_group usb2_hardware_lpm_attr_group = { |
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index b10da720f2b4..7dad603dde43 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c | |||
@@ -209,6 +209,39 @@ struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor) | |||
209 | } | 209 | } |
210 | EXPORT_SYMBOL_GPL(usb_find_interface); | 210 | EXPORT_SYMBOL_GPL(usb_find_interface); |
211 | 211 | ||
212 | struct each_dev_arg { | ||
213 | void *data; | ||
214 | int (*fn)(struct usb_device *, void *); | ||
215 | }; | ||
216 | |||
217 | static int __each_dev(struct device *dev, void *data) | ||
218 | { | ||
219 | struct each_dev_arg *arg = (struct each_dev_arg *)data; | ||
220 | |||
221 | /* There are struct usb_interface on the same bus, filter them out */ | ||
222 | if (!is_usb_device(dev)) | ||
223 | return 0; | ||
224 | |||
225 | return arg->fn(container_of(dev, struct usb_device, dev), arg->data); | ||
226 | } | ||
227 | |||
228 | /** | ||
229 | * usb_for_each_dev - iterate over all USB devices in the system | ||
230 | * @data: data pointer that will be handed to the callback function | ||
231 | * @fn: callback function to be called for each USB device | ||
232 | * | ||
233 | * Iterate over all USB devices and call @fn for each, passing it @data. If it | ||
234 | * returns anything other than 0, we break the iteration prematurely and return | ||
235 | * that value. | ||
236 | */ | ||
237 | int usb_for_each_dev(void *data, int (*fn)(struct usb_device *, void *)) | ||
238 | { | ||
239 | struct each_dev_arg arg = {data, fn}; | ||
240 | |||
241 | return bus_for_each_dev(&usb_bus_type, NULL, &arg, __each_dev); | ||
242 | } | ||
243 | EXPORT_SYMBOL_GPL(usb_for_each_dev); | ||
244 | |||
212 | /** | 245 | /** |
213 | * usb_release_dev - free a usb device structure when all users of it are finished. | 246 | * usb_release_dev - free a usb device structure when all users of it are finished. |
214 | * @dev: device that's been disconnected | 247 | * @dev: device that's been disconnected |
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 34638b92500d..077f110bd746 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c | |||
@@ -61,21 +61,46 @@ | |||
61 | #define USBOTGSS_REVISION 0x0000 | 61 | #define USBOTGSS_REVISION 0x0000 |
62 | #define USBOTGSS_SYSCONFIG 0x0010 | 62 | #define USBOTGSS_SYSCONFIG 0x0010 |
63 | #define USBOTGSS_IRQ_EOI 0x0020 | 63 | #define USBOTGSS_IRQ_EOI 0x0020 |
64 | #define USBOTGSS_EOI_OFFSET 0x0008 | ||
64 | #define USBOTGSS_IRQSTATUS_RAW_0 0x0024 | 65 | #define USBOTGSS_IRQSTATUS_RAW_0 0x0024 |
65 | #define USBOTGSS_IRQSTATUS_0 0x0028 | 66 | #define USBOTGSS_IRQSTATUS_0 0x0028 |
66 | #define USBOTGSS_IRQENABLE_SET_0 0x002c | 67 | #define USBOTGSS_IRQENABLE_SET_0 0x002c |
67 | #define USBOTGSS_IRQENABLE_CLR_0 0x0030 | 68 | #define USBOTGSS_IRQENABLE_CLR_0 0x0030 |
68 | #define USBOTGSS_IRQSTATUS_RAW_1 0x0034 | 69 | #define USBOTGSS_IRQ0_OFFSET 0x0004 |
69 | #define USBOTGSS_IRQSTATUS_1 0x0038 | 70 | #define USBOTGSS_IRQSTATUS_RAW_1 0x0030 |
70 | #define USBOTGSS_IRQENABLE_SET_1 0x003c | 71 | #define USBOTGSS_IRQSTATUS_1 0x0034 |
71 | #define USBOTGSS_IRQENABLE_CLR_1 0x0040 | 72 | #define USBOTGSS_IRQENABLE_SET_1 0x0038 |
73 | #define USBOTGSS_IRQENABLE_CLR_1 0x003c | ||
74 | #define USBOTGSS_IRQSTATUS_RAW_2 0x0040 | ||
75 | #define USBOTGSS_IRQSTATUS_2 0x0044 | ||
76 | #define USBOTGSS_IRQENABLE_SET_2 0x0048 | ||
77 | #define USBOTGSS_IRQENABLE_CLR_2 0x004c | ||
78 | #define USBOTGSS_IRQSTATUS_RAW_3 0x0050 | ||
79 | #define USBOTGSS_IRQSTATUS_3 0x0054 | ||
80 | #define USBOTGSS_IRQENABLE_SET_3 0x0058 | ||
81 | #define USBOTGSS_IRQENABLE_CLR_3 0x005c | ||
82 | #define USBOTGSS_IRQSTATUS_EOI_MISC 0x0030 | ||
83 | #define USBOTGSS_IRQSTATUS_RAW_MISC 0x0034 | ||
84 | #define USBOTGSS_IRQSTATUS_MISC 0x0038 | ||
85 | #define USBOTGSS_IRQENABLE_SET_MISC 0x003c | ||
86 | #define USBOTGSS_IRQENABLE_CLR_MISC 0x0040 | ||
87 | #define USBOTGSS_IRQMISC_OFFSET 0x03fc | ||
72 | #define USBOTGSS_UTMI_OTG_CTRL 0x0080 | 88 | #define USBOTGSS_UTMI_OTG_CTRL 0x0080 |
73 | #define USBOTGSS_UTMI_OTG_STATUS 0x0084 | 89 | #define USBOTGSS_UTMI_OTG_STATUS 0x0084 |
90 | #define USBOTGSS_UTMI_OTG_OFFSET 0x0480 | ||
91 | #define USBOTGSS_TXFIFO_DEPTH 0x0508 | ||
92 | #define USBOTGSS_RXFIFO_DEPTH 0x050c | ||
74 | #define USBOTGSS_MMRAM_OFFSET 0x0100 | 93 | #define USBOTGSS_MMRAM_OFFSET 0x0100 |
75 | #define USBOTGSS_FLADJ 0x0104 | 94 | #define USBOTGSS_FLADJ 0x0104 |
76 | #define USBOTGSS_DEBUG_CFG 0x0108 | 95 | #define USBOTGSS_DEBUG_CFG 0x0108 |
77 | #define USBOTGSS_DEBUG_DATA 0x010c | 96 | #define USBOTGSS_DEBUG_DATA 0x010c |
97 | #define USBOTGSS_DEV_EBC_EN 0x0110 | ||
98 | #define USBOTGSS_DEBUG_OFFSET 0x0600 | ||
78 | 99 | ||
100 | /* REVISION REGISTER */ | ||
101 | #define USBOTGSS_REVISION_XMAJOR(reg) ((reg >> 8) & 0x7) | ||
102 | #define USBOTGSS_REVISION_XMAJOR1 1 | ||
103 | #define USBOTGSS_REVISION_XMAJOR2 2 | ||
79 | /* SYSCONFIG REGISTER */ | 104 | /* SYSCONFIG REGISTER */ |
80 | #define USBOTGSS_SYSCONFIG_DMADISABLE (1 << 16) | 105 | #define USBOTGSS_SYSCONFIG_DMADISABLE (1 << 16) |
81 | 106 | ||
@@ -85,17 +110,17 @@ | |||
85 | /* IRQS0 BITS */ | 110 | /* IRQS0 BITS */ |
86 | #define USBOTGSS_IRQO_COREIRQ_ST (1 << 0) | 111 | #define USBOTGSS_IRQO_COREIRQ_ST (1 << 0) |
87 | 112 | ||
88 | /* IRQ1 BITS */ | 113 | /* IRQMISC BITS */ |
89 | #define USBOTGSS_IRQ1_DMADISABLECLR (1 << 17) | 114 | #define USBOTGSS_IRQMISC_DMADISABLECLR (1 << 17) |
90 | #define USBOTGSS_IRQ1_OEVT (1 << 16) | 115 | #define USBOTGSS_IRQMISC_OEVT (1 << 16) |
91 | #define USBOTGSS_IRQ1_DRVVBUS_RISE (1 << 13) | 116 | #define USBOTGSS_IRQMISC_DRVVBUS_RISE (1 << 13) |
92 | #define USBOTGSS_IRQ1_CHRGVBUS_RISE (1 << 12) | 117 | #define USBOTGSS_IRQMISC_CHRGVBUS_RISE (1 << 12) |
93 | #define USBOTGSS_IRQ1_DISCHRGVBUS_RISE (1 << 11) | 118 | #define USBOTGSS_IRQMISC_DISCHRGVBUS_RISE (1 << 11) |
94 | #define USBOTGSS_IRQ1_IDPULLUP_RISE (1 << 8) | 119 | #define USBOTGSS_IRQMISC_IDPULLUP_RISE (1 << 8) |
95 | #define USBOTGSS_IRQ1_DRVVBUS_FALL (1 << 5) | 120 | #define USBOTGSS_IRQMISC_DRVVBUS_FALL (1 << 5) |
96 | #define USBOTGSS_IRQ1_CHRGVBUS_FALL (1 << 4) | 121 | #define USBOTGSS_IRQMISC_CHRGVBUS_FALL (1 << 4) |
97 | #define USBOTGSS_IRQ1_DISCHRGVBUS_FALL (1 << 3) | 122 | #define USBOTGSS_IRQMISC_DISCHRGVBUS_FALL (1 << 3) |
98 | #define USBOTGSS_IRQ1_IDPULLUP_FALL (1 << 0) | 123 | #define USBOTGSS_IRQMISC_IDPULLUP_FALL (1 << 0) |
99 | 124 | ||
100 | /* UTMI_OTG_CTRL REGISTER */ | 125 | /* UTMI_OTG_CTRL REGISTER */ |
101 | #define USBOTGSS_UTMI_OTG_CTRL_DRVVBUS (1 << 5) | 126 | #define USBOTGSS_UTMI_OTG_CTRL_DRVVBUS (1 << 5) |
@@ -122,6 +147,12 @@ struct dwc3_omap { | |||
122 | void __iomem *base; | 147 | void __iomem *base; |
123 | 148 | ||
124 | u32 utmi_otg_status; | 149 | u32 utmi_otg_status; |
150 | u32 utmi_otg_offset; | ||
151 | u32 irqmisc_offset; | ||
152 | u32 irq_eoi_offset; | ||
153 | u32 debug_offset; | ||
154 | u32 irq0_offset; | ||
155 | u32 revision; | ||
125 | 156 | ||
126 | u32 dma_status:1; | 157 | u32 dma_status:1; |
127 | }; | 158 | }; |
@@ -138,6 +169,58 @@ static inline void dwc3_omap_writel(void __iomem *base, u32 offset, u32 value) | |||
138 | writel(value, base + offset); | 169 | writel(value, base + offset); |
139 | } | 170 | } |
140 | 171 | ||
172 | static u32 dwc3_omap_read_utmi_status(struct dwc3_omap *omap) | ||
173 | { | ||
174 | return dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS + | ||
175 | omap->utmi_otg_offset); | ||
176 | } | ||
177 | |||
178 | static void dwc3_omap_write_utmi_status(struct dwc3_omap *omap, u32 value) | ||
179 | { | ||
180 | dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS + | ||
181 | omap->utmi_otg_offset, value); | ||
182 | |||
183 | } | ||
184 | |||
185 | static u32 dwc3_omap_read_irq0_status(struct dwc3_omap *omap) | ||
186 | { | ||
187 | return dwc3_omap_readl(omap->base, USBOTGSS_IRQSTATUS_0 - | ||
188 | omap->irq0_offset); | ||
189 | } | ||
190 | |||
191 | static void dwc3_omap_write_irq0_status(struct dwc3_omap *omap, u32 value) | ||
192 | { | ||
193 | dwc3_omap_writel(omap->base, USBOTGSS_IRQSTATUS_0 - | ||
194 | omap->irq0_offset, value); | ||
195 | |||
196 | } | ||
197 | |||
198 | static u32 dwc3_omap_read_irqmisc_status(struct dwc3_omap *omap) | ||
199 | { | ||
200 | return dwc3_omap_readl(omap->base, USBOTGSS_IRQSTATUS_MISC + | ||
201 | omap->irqmisc_offset); | ||
202 | } | ||
203 | |||
204 | static void dwc3_omap_write_irqmisc_status(struct dwc3_omap *omap, u32 value) | ||
205 | { | ||
206 | dwc3_omap_writel(omap->base, USBOTGSS_IRQSTATUS_MISC + | ||
207 | omap->irqmisc_offset, value); | ||
208 | |||
209 | } | ||
210 | |||
211 | static void dwc3_omap_write_irqmisc_set(struct dwc3_omap *omap, u32 value) | ||
212 | { | ||
213 | dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_MISC + | ||
214 | omap->irqmisc_offset, value); | ||
215 | |||
216 | } | ||
217 | |||
218 | static void dwc3_omap_write_irq0_set(struct dwc3_omap *omap, u32 value) | ||
219 | { | ||
220 | dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_0 - | ||
221 | omap->irq0_offset, value); | ||
222 | } | ||
223 | |||
141 | int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status) | 224 | int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status) |
142 | { | 225 | { |
143 | u32 val; | 226 | u32 val; |
@@ -150,38 +233,38 @@ int dwc3_omap_mailbox(enum omap_dwc3_vbus_id_status status) | |||
150 | case OMAP_DWC3_ID_GROUND: | 233 | case OMAP_DWC3_ID_GROUND: |
151 | dev_dbg(omap->dev, "ID GND\n"); | 234 | dev_dbg(omap->dev, "ID GND\n"); |
152 | 235 | ||
153 | val = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS); | 236 | val = dwc3_omap_read_utmi_status(omap); |
154 | val &= ~(USBOTGSS_UTMI_OTG_STATUS_IDDIG | 237 | val &= ~(USBOTGSS_UTMI_OTG_STATUS_IDDIG |
155 | | USBOTGSS_UTMI_OTG_STATUS_VBUSVALID | 238 | | USBOTGSS_UTMI_OTG_STATUS_VBUSVALID |
156 | | USBOTGSS_UTMI_OTG_STATUS_SESSEND); | 239 | | USBOTGSS_UTMI_OTG_STATUS_SESSEND); |
157 | val |= USBOTGSS_UTMI_OTG_STATUS_SESSVALID | 240 | val |= USBOTGSS_UTMI_OTG_STATUS_SESSVALID |
158 | | USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT; | 241 | | USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT; |
159 | dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, val); | 242 | dwc3_omap_write_utmi_status(omap, val); |
160 | break; | 243 | break; |
161 | 244 | ||
162 | case OMAP_DWC3_VBUS_VALID: | 245 | case OMAP_DWC3_VBUS_VALID: |
163 | dev_dbg(omap->dev, "VBUS Connect\n"); | 246 | dev_dbg(omap->dev, "VBUS Connect\n"); |
164 | 247 | ||
165 | val = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS); | 248 | val = dwc3_omap_read_utmi_status(omap); |
166 | val &= ~USBOTGSS_UTMI_OTG_STATUS_SESSEND; | 249 | val &= ~USBOTGSS_UTMI_OTG_STATUS_SESSEND; |
167 | val |= USBOTGSS_UTMI_OTG_STATUS_IDDIG | 250 | val |= USBOTGSS_UTMI_OTG_STATUS_IDDIG |
168 | | USBOTGSS_UTMI_OTG_STATUS_VBUSVALID | 251 | | USBOTGSS_UTMI_OTG_STATUS_VBUSVALID |
169 | | USBOTGSS_UTMI_OTG_STATUS_SESSVALID | 252 | | USBOTGSS_UTMI_OTG_STATUS_SESSVALID |
170 | | USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT; | 253 | | USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT; |
171 | dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, val); | 254 | dwc3_omap_write_utmi_status(omap, val); |
172 | break; | 255 | break; |
173 | 256 | ||
174 | case OMAP_DWC3_ID_FLOAT: | 257 | case OMAP_DWC3_ID_FLOAT: |
175 | case OMAP_DWC3_VBUS_OFF: | 258 | case OMAP_DWC3_VBUS_OFF: |
176 | dev_dbg(omap->dev, "VBUS Disconnect\n"); | 259 | dev_dbg(omap->dev, "VBUS Disconnect\n"); |
177 | 260 | ||
178 | val = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS); | 261 | val = dwc3_omap_read_utmi_status(omap); |
179 | val &= ~(USBOTGSS_UTMI_OTG_STATUS_SESSVALID | 262 | val &= ~(USBOTGSS_UTMI_OTG_STATUS_SESSVALID |
180 | | USBOTGSS_UTMI_OTG_STATUS_VBUSVALID | 263 | | USBOTGSS_UTMI_OTG_STATUS_VBUSVALID |
181 | | USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT); | 264 | | USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT); |
182 | val |= USBOTGSS_UTMI_OTG_STATUS_SESSEND | 265 | val |= USBOTGSS_UTMI_OTG_STATUS_SESSEND |
183 | | USBOTGSS_UTMI_OTG_STATUS_IDDIG; | 266 | | USBOTGSS_UTMI_OTG_STATUS_IDDIG; |
184 | dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, val); | 267 | dwc3_omap_write_utmi_status(omap, val); |
185 | break; | 268 | break; |
186 | 269 | ||
187 | default: | 270 | default: |
@@ -199,44 +282,45 @@ static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap) | |||
199 | 282 | ||
200 | spin_lock(&omap->lock); | 283 | spin_lock(&omap->lock); |
201 | 284 | ||
202 | reg = dwc3_omap_readl(omap->base, USBOTGSS_IRQSTATUS_1); | 285 | reg = dwc3_omap_read_irqmisc_status(omap); |
203 | 286 | ||
204 | if (reg & USBOTGSS_IRQ1_DMADISABLECLR) { | 287 | if (reg & USBOTGSS_IRQMISC_DMADISABLECLR) { |
205 | dev_dbg(omap->dev, "DMA Disable was Cleared\n"); | 288 | dev_dbg(omap->dev, "DMA Disable was Cleared\n"); |
206 | omap->dma_status = false; | 289 | omap->dma_status = false; |
207 | } | 290 | } |
208 | 291 | ||
209 | if (reg & USBOTGSS_IRQ1_OEVT) | 292 | if (reg & USBOTGSS_IRQMISC_OEVT) |
210 | dev_dbg(omap->dev, "OTG Event\n"); | 293 | dev_dbg(omap->dev, "OTG Event\n"); |
211 | 294 | ||
212 | if (reg & USBOTGSS_IRQ1_DRVVBUS_RISE) | 295 | if (reg & USBOTGSS_IRQMISC_DRVVBUS_RISE) |
213 | dev_dbg(omap->dev, "DRVVBUS Rise\n"); | 296 | dev_dbg(omap->dev, "DRVVBUS Rise\n"); |
214 | 297 | ||
215 | if (reg & USBOTGSS_IRQ1_CHRGVBUS_RISE) | 298 | if (reg & USBOTGSS_IRQMISC_CHRGVBUS_RISE) |
216 | dev_dbg(omap->dev, "CHRGVBUS Rise\n"); | 299 | dev_dbg(omap->dev, "CHRGVBUS Rise\n"); |
217 | 300 | ||
218 | if (reg & USBOTGSS_IRQ1_DISCHRGVBUS_RISE) | 301 | if (reg & USBOTGSS_IRQMISC_DISCHRGVBUS_RISE) |
219 | dev_dbg(omap->dev, "DISCHRGVBUS Rise\n"); | 302 | dev_dbg(omap->dev, "DISCHRGVBUS Rise\n"); |
220 | 303 | ||
221 | if (reg & USBOTGSS_IRQ1_IDPULLUP_RISE) | 304 | if (reg & USBOTGSS_IRQMISC_IDPULLUP_RISE) |
222 | dev_dbg(omap->dev, "IDPULLUP Rise\n"); | 305 | dev_dbg(omap->dev, "IDPULLUP Rise\n"); |
223 | 306 | ||
224 | if (reg & USBOTGSS_IRQ1_DRVVBUS_FALL) | 307 | if (reg & USBOTGSS_IRQMISC_DRVVBUS_FALL) |
225 | dev_dbg(omap->dev, "DRVVBUS Fall\n"); | 308 | dev_dbg(omap->dev, "DRVVBUS Fall\n"); |
226 | 309 | ||
227 | if (reg & USBOTGSS_IRQ1_CHRGVBUS_FALL) | 310 | if (reg & USBOTGSS_IRQMISC_CHRGVBUS_FALL) |
228 | dev_dbg(omap->dev, "CHRGVBUS Fall\n"); | 311 | dev_dbg(omap->dev, "CHRGVBUS Fall\n"); |
229 | 312 | ||
230 | if (reg & USBOTGSS_IRQ1_DISCHRGVBUS_FALL) | 313 | if (reg & USBOTGSS_IRQMISC_DISCHRGVBUS_FALL) |
231 | dev_dbg(omap->dev, "DISCHRGVBUS Fall\n"); | 314 | dev_dbg(omap->dev, "DISCHRGVBUS Fall\n"); |
232 | 315 | ||
233 | if (reg & USBOTGSS_IRQ1_IDPULLUP_FALL) | 316 | if (reg & USBOTGSS_IRQMISC_IDPULLUP_FALL) |
234 | dev_dbg(omap->dev, "IDPULLUP Fall\n"); | 317 | dev_dbg(omap->dev, "IDPULLUP Fall\n"); |
235 | 318 | ||
236 | dwc3_omap_writel(omap->base, USBOTGSS_IRQSTATUS_1, reg); | 319 | dwc3_omap_write_irqmisc_status(omap, reg); |
320 | |||
321 | reg = dwc3_omap_read_irq0_status(omap); | ||
237 | 322 | ||
238 | reg = dwc3_omap_readl(omap->base, USBOTGSS_IRQSTATUS_0); | 323 | dwc3_omap_write_irq0_status(omap, reg); |
239 | dwc3_omap_writel(omap->base, USBOTGSS_IRQSTATUS_0, reg); | ||
240 | 324 | ||
241 | spin_unlock(&omap->lock); | 325 | spin_unlock(&omap->lock); |
242 | 326 | ||
@@ -258,26 +342,26 @@ static void dwc3_omap_enable_irqs(struct dwc3_omap *omap) | |||
258 | 342 | ||
259 | /* enable all IRQs */ | 343 | /* enable all IRQs */ |
260 | reg = USBOTGSS_IRQO_COREIRQ_ST; | 344 | reg = USBOTGSS_IRQO_COREIRQ_ST; |
261 | dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, reg); | 345 | dwc3_omap_write_irq0_set(omap, reg); |
262 | 346 | ||
263 | reg = (USBOTGSS_IRQ1_OEVT | | 347 | reg = (USBOTGSS_IRQMISC_OEVT | |
264 | USBOTGSS_IRQ1_DRVVBUS_RISE | | 348 | USBOTGSS_IRQMISC_DRVVBUS_RISE | |
265 | USBOTGSS_IRQ1_CHRGVBUS_RISE | | 349 | USBOTGSS_IRQMISC_CHRGVBUS_RISE | |
266 | USBOTGSS_IRQ1_DISCHRGVBUS_RISE | | 350 | USBOTGSS_IRQMISC_DISCHRGVBUS_RISE | |
267 | USBOTGSS_IRQ1_IDPULLUP_RISE | | 351 | USBOTGSS_IRQMISC_IDPULLUP_RISE | |
268 | USBOTGSS_IRQ1_DRVVBUS_FALL | | 352 | USBOTGSS_IRQMISC_DRVVBUS_FALL | |
269 | USBOTGSS_IRQ1_CHRGVBUS_FALL | | 353 | USBOTGSS_IRQMISC_CHRGVBUS_FALL | |
270 | USBOTGSS_IRQ1_DISCHRGVBUS_FALL | | 354 | USBOTGSS_IRQMISC_DISCHRGVBUS_FALL | |
271 | USBOTGSS_IRQ1_IDPULLUP_FALL); | 355 | USBOTGSS_IRQMISC_IDPULLUP_FALL); |
272 | 356 | ||
273 | dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, reg); | 357 | dwc3_omap_write_irqmisc_set(omap, reg); |
274 | } | 358 | } |
275 | 359 | ||
276 | static void dwc3_omap_disable_irqs(struct dwc3_omap *omap) | 360 | static void dwc3_omap_disable_irqs(struct dwc3_omap *omap) |
277 | { | 361 | { |
278 | /* disable all IRQs */ | 362 | /* disable all IRQs */ |
279 | dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_1, 0x00); | 363 | dwc3_omap_write_irqmisc_set(omap, 0x00); |
280 | dwc3_omap_writel(omap->base, USBOTGSS_IRQENABLE_SET_0, 0x00); | 364 | dwc3_omap_write_irq0_set(omap, 0x00); |
281 | } | 365 | } |
282 | 366 | ||
283 | static u64 dwc3_omap_dma_mask = DMA_BIT_MASK(32); | 367 | static u64 dwc3_omap_dma_mask = DMA_BIT_MASK(32); |
@@ -294,6 +378,7 @@ static int dwc3_omap_probe(struct platform_device *pdev) | |||
294 | int irq; | 378 | int irq; |
295 | 379 | ||
296 | int utmi_mode = 0; | 380 | int utmi_mode = 0; |
381 | int x_major; | ||
297 | 382 | ||
298 | u32 reg; | 383 | u32 reg; |
299 | 384 | ||
@@ -347,10 +432,46 @@ static int dwc3_omap_probe(struct platform_device *pdev) | |||
347 | ret = pm_runtime_get_sync(dev); | 432 | ret = pm_runtime_get_sync(dev); |
348 | if (ret < 0) { | 433 | if (ret < 0) { |
349 | dev_err(dev, "get_sync failed with err %d\n", ret); | 434 | dev_err(dev, "get_sync failed with err %d\n", ret); |
350 | return ret; | 435 | goto err0; |
351 | } | 436 | } |
352 | 437 | ||
353 | reg = dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS); | 438 | reg = dwc3_omap_readl(omap->base, USBOTGSS_REVISION); |
439 | omap->revision = reg; | ||
440 | x_major = USBOTGSS_REVISION_XMAJOR(reg); | ||
441 | |||
442 | /* Differentiate between OMAP5 and AM437x */ | ||
443 | switch (x_major) { | ||
444 | case USBOTGSS_REVISION_XMAJOR1: | ||
445 | case USBOTGSS_REVISION_XMAJOR2: | ||
446 | omap->irq_eoi_offset = 0; | ||
447 | omap->irq0_offset = 0; | ||
448 | omap->irqmisc_offset = 0; | ||
449 | omap->utmi_otg_offset = 0; | ||
450 | omap->debug_offset = 0; | ||
451 | break; | ||
452 | default: | ||
453 | /* Default to the latest revision */ | ||
454 | omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET; | ||
455 | omap->irq0_offset = USBOTGSS_IRQ0_OFFSET; | ||
456 | omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET; | ||
457 | omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET; | ||
458 | omap->debug_offset = USBOTGSS_DEBUG_OFFSET; | ||
459 | break; | ||
460 | } | ||
461 | |||
462 | /* For OMAP5(ES2.0) and AM437x x_major is 2 even though there are | ||
463 | * changes in wrapper registers, Using dt compatible for aegis | ||
464 | */ | ||
465 | |||
466 | if (of_device_is_compatible(node, "ti,am437x-dwc3")) { | ||
467 | omap->irq_eoi_offset = USBOTGSS_EOI_OFFSET; | ||
468 | omap->irq0_offset = USBOTGSS_IRQ0_OFFSET; | ||
469 | omap->irqmisc_offset = USBOTGSS_IRQMISC_OFFSET; | ||
470 | omap->utmi_otg_offset = USBOTGSS_UTMI_OTG_OFFSET; | ||
471 | omap->debug_offset = USBOTGSS_DEBUG_OFFSET; | ||
472 | } | ||
473 | |||
474 | reg = dwc3_omap_read_utmi_status(omap); | ||
354 | 475 | ||
355 | of_property_read_u32(node, "utmi-mode", &utmi_mode); | 476 | of_property_read_u32(node, "utmi-mode", &utmi_mode); |
356 | 477 | ||
@@ -365,7 +486,7 @@ static int dwc3_omap_probe(struct platform_device *pdev) | |||
365 | dev_dbg(dev, "UNKNOWN utmi mode %d\n", utmi_mode); | 486 | dev_dbg(dev, "UNKNOWN utmi mode %d\n", utmi_mode); |
366 | } | 487 | } |
367 | 488 | ||
368 | dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, reg); | 489 | dwc3_omap_write_utmi_status(omap, reg); |
369 | 490 | ||
370 | /* check the DMA Status */ | 491 | /* check the DMA Status */ |
371 | reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG); | 492 | reg = dwc3_omap_readl(omap->base, USBOTGSS_SYSCONFIG); |
@@ -376,7 +497,7 @@ static int dwc3_omap_probe(struct platform_device *pdev) | |||
376 | if (ret) { | 497 | if (ret) { |
377 | dev_err(dev, "failed to request IRQ #%d --> %d\n", | 498 | dev_err(dev, "failed to request IRQ #%d --> %d\n", |
378 | omap->irq, ret); | 499 | omap->irq, ret); |
379 | return ret; | 500 | goto err1; |
380 | } | 501 | } |
381 | 502 | ||
382 | dwc3_omap_enable_irqs(omap); | 503 | dwc3_omap_enable_irqs(omap); |
@@ -384,10 +505,21 @@ static int dwc3_omap_probe(struct platform_device *pdev) | |||
384 | ret = of_platform_populate(node, NULL, NULL, dev); | 505 | ret = of_platform_populate(node, NULL, NULL, dev); |
385 | if (ret) { | 506 | if (ret) { |
386 | dev_err(&pdev->dev, "failed to create dwc3 core\n"); | 507 | dev_err(&pdev->dev, "failed to create dwc3 core\n"); |
387 | return ret; | 508 | goto err2; |
388 | } | 509 | } |
389 | 510 | ||
390 | return 0; | 511 | return 0; |
512 | |||
513 | err2: | ||
514 | dwc3_omap_disable_irqs(omap); | ||
515 | |||
516 | err1: | ||
517 | pm_runtime_put_sync(dev); | ||
518 | |||
519 | err0: | ||
520 | pm_runtime_disable(dev); | ||
521 | |||
522 | return ret; | ||
391 | } | 523 | } |
392 | 524 | ||
393 | static int dwc3_omap_remove(struct platform_device *pdev) | 525 | static int dwc3_omap_remove(struct platform_device *pdev) |
@@ -406,6 +538,9 @@ static const struct of_device_id of_dwc3_match[] = { | |||
406 | { | 538 | { |
407 | .compatible = "ti,dwc3" | 539 | .compatible = "ti,dwc3" |
408 | }, | 540 | }, |
541 | { | ||
542 | .compatible = "ti,am437x-dwc3" | ||
543 | }, | ||
409 | { }, | 544 | { }, |
410 | }; | 545 | }; |
411 | MODULE_DEVICE_TABLE(of, of_dwc3_match); | 546 | MODULE_DEVICE_TABLE(of, of_dwc3_match); |
@@ -431,8 +566,7 @@ static int dwc3_omap_suspend(struct device *dev) | |||
431 | { | 566 | { |
432 | struct dwc3_omap *omap = dev_get_drvdata(dev); | 567 | struct dwc3_omap *omap = dev_get_drvdata(dev); |
433 | 568 | ||
434 | omap->utmi_otg_status = dwc3_omap_readl(omap->base, | 569 | omap->utmi_otg_status = dwc3_omap_read_utmi_status(omap); |
435 | USBOTGSS_UTMI_OTG_STATUS); | ||
436 | 570 | ||
437 | return 0; | 571 | return 0; |
438 | } | 572 | } |
@@ -441,8 +575,7 @@ static int dwc3_omap_resume(struct device *dev) | |||
441 | { | 575 | { |
442 | struct dwc3_omap *omap = dev_get_drvdata(dev); | 576 | struct dwc3_omap *omap = dev_get_drvdata(dev); |
443 | 577 | ||
444 | dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, | 578 | dwc3_omap_write_utmi_status(omap, omap->utmi_otg_status); |
445 | omap->utmi_otg_status); | ||
446 | 579 | ||
447 | pm_runtime_disable(dev); | 580 | pm_runtime_disable(dev); |
448 | pm_runtime_set_active(dev); | 581 | pm_runtime_set_active(dev); |
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index eba9e2baf32b..ed07ec04a962 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c | |||
@@ -133,7 +133,6 @@ static int dwc3_pci_probe(struct pci_dev *pci, | |||
133 | return -ENODEV; | 133 | return -ENODEV; |
134 | } | 134 | } |
135 | 135 | ||
136 | pci_set_power_state(pci, PCI_D0); | ||
137 | pci_set_master(pci); | 136 | pci_set_master(pci); |
138 | 137 | ||
139 | ret = dwc3_pci_register_phys(glue); | 138 | ret = dwc3_pci_register_phys(glue); |
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index f41aa0d0c414..01b8229fa862 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig | |||
@@ -192,6 +192,16 @@ config USB_FUSB300 | |||
192 | help | 192 | help |
193 | Faraday usb device controller FUSB300 driver | 193 | Faraday usb device controller FUSB300 driver |
194 | 194 | ||
195 | config USB_FOTG210_UDC | ||
196 | tristate "Faraday FOTG210 USB Peripheral Controller" | ||
197 | help | ||
198 | Faraday USB2.0 OTG controller which can be configured as | ||
199 | high speed or full speed USB device. This driver supppors | ||
200 | Bulk Transfer so far. | ||
201 | |||
202 | Say "y" to link the driver statically, or "m" to build a | ||
203 | dynamically linked module called "fotg210_udc". | ||
204 | |||
195 | config USB_OMAP | 205 | config USB_OMAP |
196 | tristate "OMAP USB Device Controller" | 206 | tristate "OMAP USB Device Controller" |
197 | depends on ARCH_OMAP1 | 207 | depends on ARCH_OMAP1 |
@@ -334,14 +344,6 @@ config USB_MV_U3D | |||
334 | # Controllers available in both integrated and discrete versions | 344 | # Controllers available in both integrated and discrete versions |
335 | # | 345 | # |
336 | 346 | ||
337 | # musb builds in ../musb along with host support | ||
338 | config USB_GADGET_MUSB_HDRC | ||
339 | tristate "Inventra HDRC USB Peripheral (TI, ADI, ...)" | ||
340 | depends on USB_MUSB_HDRC | ||
341 | help | ||
342 | This OTG-capable silicon IP is used in dual designs including | ||
343 | the TI DaVinci, OMAP 243x, OMAP 343x, TUSB 6010, and ADI Blackfin | ||
344 | |||
345 | config USB_M66592 | 347 | config USB_M66592 |
346 | tristate "Renesas M66592 USB Peripheral Controller" | 348 | tristate "Renesas M66592 USB Peripheral Controller" |
347 | help | 349 | help |
@@ -507,12 +509,36 @@ config USB_F_SS_LB | |||
507 | config USB_U_SERIAL | 509 | config USB_U_SERIAL |
508 | tristate | 510 | tristate |
509 | 511 | ||
512 | config USB_U_ETHER | ||
513 | tristate | ||
514 | |||
515 | config USB_U_RNDIS | ||
516 | tristate | ||
517 | |||
510 | config USB_F_SERIAL | 518 | config USB_F_SERIAL |
511 | tristate | 519 | tristate |
512 | 520 | ||
513 | config USB_F_OBEX | 521 | config USB_F_OBEX |
514 | tristate | 522 | tristate |
515 | 523 | ||
524 | config USB_F_NCM | ||
525 | tristate | ||
526 | |||
527 | config USB_F_ECM | ||
528 | tristate | ||
529 | |||
530 | config USB_F_PHONET | ||
531 | tristate | ||
532 | |||
533 | config USB_F_EEM | ||
534 | tristate | ||
535 | |||
536 | config USB_F_SUBSET | ||
537 | tristate | ||
538 | |||
539 | config USB_F_RNDIS | ||
540 | tristate | ||
541 | |||
516 | choice | 542 | choice |
517 | tristate "USB Gadget Drivers" | 543 | tristate "USB Gadget Drivers" |
518 | default USB_ETH | 544 | default USB_ETH |
@@ -534,6 +560,121 @@ choice | |||
534 | 560 | ||
535 | # this first set of drivers all depend on bulk-capable hardware. | 561 | # this first set of drivers all depend on bulk-capable hardware. |
536 | 562 | ||
563 | config USB_CONFIGFS | ||
564 | tristate "USB functions configurable through configfs" | ||
565 | select USB_LIBCOMPOSITE | ||
566 | help | ||
567 | A Linux USB "gadget" can be set up through configfs. | ||
568 | If this is the case, the USB functions (which from the host's | ||
569 | perspective are seen as interfaces) and configurations are | ||
570 | specified simply by creating appropriate directories in configfs. | ||
571 | Associating functions with configurations is done by creating | ||
572 | appropriate symbolic links. | ||
573 | For more information see Documentation/usb/gadget-configfs.txt. | ||
574 | |||
575 | config USB_CONFIGFS_SERIAL | ||
576 | boolean "Generic serial bulk in/out" | ||
577 | depends on USB_CONFIGFS | ||
578 | depends on TTY | ||
579 | select USB_U_SERIAL | ||
580 | select USB_F_SERIAL | ||
581 | help | ||
582 | The function talks to the Linux-USB generic serial driver. | ||
583 | |||
584 | config USB_CONFIGFS_ACM | ||
585 | boolean "Abstract Control Model (CDC ACM)" | ||
586 | depends on USB_CONFIGFS | ||
587 | depends on TTY | ||
588 | select USB_U_SERIAL | ||
589 | select USB_F_ACM | ||
590 | help | ||
591 | ACM serial link. This function can be used to interoperate with | ||
592 | MS-Windows hosts or with the Linux-USB "cdc-acm" driver. | ||
593 | |||
594 | config USB_CONFIGFS_OBEX | ||
595 | boolean "Object Exchange Model (CDC OBEX)" | ||
596 | depends on USB_CONFIGFS | ||
597 | depends on TTY | ||
598 | select USB_U_SERIAL | ||
599 | select USB_F_OBEX | ||
600 | help | ||
601 | You will need a user space OBEX server talking to /dev/ttyGS*, | ||
602 | since the kernel itself doesn't implement the OBEX protocol. | ||
603 | |||
604 | config USB_CONFIGFS_NCM | ||
605 | boolean "Network Control Model (CDC NCM)" | ||
606 | depends on USB_CONFIGFS | ||
607 | depends on NET | ||
608 | select USB_U_ETHER | ||
609 | select USB_F_NCM | ||
610 | help | ||
611 | NCM is an advanced protocol for Ethernet encapsulation, allows | ||
612 | grouping of several ethernet frames into one USB transfer and | ||
613 | different alignment possibilities. | ||
614 | |||
615 | config USB_CONFIGFS_ECM | ||
616 | boolean "Ethernet Control Model (CDC ECM)" | ||
617 | depends on USB_CONFIGFS | ||
618 | depends on NET | ||
619 | select USB_U_ETHER | ||
620 | select USB_F_ECM | ||
621 | help | ||
622 | The "Communication Device Class" (CDC) Ethernet Control Model. | ||
623 | That protocol is often avoided with pure Ethernet adapters, in | ||
624 | favor of simpler vendor-specific hardware, but is widely | ||
625 | supported by firmware for smart network devices. | ||
626 | |||
627 | config USB_CONFIGFS_ECM_SUBSET | ||
628 | boolean "Ethernet Control Model (CDC ECM) subset" | ||
629 | depends on USB_CONFIGFS | ||
630 | depends on NET | ||
631 | select USB_U_ETHER | ||
632 | select USB_F_SUBSET | ||
633 | help | ||
634 | On hardware that can't implement the full protocol, | ||
635 | a simple CDC subset is used, placing fewer demands on USB. | ||
636 | |||
637 | config USB_CONFIGFS_RNDIS | ||
638 | bool "RNDIS" | ||
639 | depends on USB_CONFIGFS | ||
640 | depends on NET | ||
641 | select USB_U_ETHER | ||
642 | select USB_F_RNDIS | ||
643 | help | ||
644 | Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol, | ||
645 | and Microsoft provides redistributable binary RNDIS drivers for | ||
646 | older versions of Windows. | ||
647 | |||
648 | To make MS-Windows work with this, use Documentation/usb/linux.inf | ||
649 | as the "driver info file". For versions of MS-Windows older than | ||
650 | XP, you'll need to download drivers from Microsoft's website; a URL | ||
651 | is given in comments found in that info file. | ||
652 | |||
653 | config USB_CONFIGFS_EEM | ||
654 | bool "Ethernet Emulation Model (EEM)" | ||
655 | depends on USB_CONFIGFS | ||
656 | depends on NET | ||
657 | select USB_U_ETHER | ||
658 | select USB_F_EEM | ||
659 | help | ||
660 | CDC EEM is a newer USB standard that is somewhat simpler than CDC ECM | ||
661 | and therefore can be supported by more hardware. Technically ECM and | ||
662 | EEM are designed for different applications. The ECM model extends | ||
663 | the network interface to the target (e.g. a USB cable modem), and the | ||
664 | EEM model is for mobile devices to communicate with hosts using | ||
665 | ethernet over USB. For Linux gadgets, however, the interface with | ||
666 | the host is the same (a usbX device), so the differences are minimal. | ||
667 | |||
668 | config USB_CONFIGFS_PHONET | ||
669 | boolean "Phonet protocol" | ||
670 | depends on USB_CONFIGFS | ||
671 | depends on NET | ||
672 | depends on PHONET | ||
673 | select USB_U_ETHER | ||
674 | select USB_F_PHONET | ||
675 | help | ||
676 | The Phonet protocol implementation for USB device. | ||
677 | |||
537 | config USB_ZERO | 678 | config USB_ZERO |
538 | tristate "Gadget Zero (DEVELOPMENT)" | 679 | tristate "Gadget Zero (DEVELOPMENT)" |
539 | select USB_LIBCOMPOSITE | 680 | select USB_LIBCOMPOSITE |
@@ -603,6 +744,10 @@ config USB_ETH | |||
603 | tristate "Ethernet Gadget (with CDC Ethernet support)" | 744 | tristate "Ethernet Gadget (with CDC Ethernet support)" |
604 | depends on NET | 745 | depends on NET |
605 | select USB_LIBCOMPOSITE | 746 | select USB_LIBCOMPOSITE |
747 | select USB_U_ETHER | ||
748 | select USB_U_RNDIS | ||
749 | select USB_F_ECM | ||
750 | select USB_F_SUBSET | ||
606 | select CRC32 | 751 | select CRC32 |
607 | help | 752 | help |
608 | This driver implements Ethernet style communication, in one of | 753 | This driver implements Ethernet style communication, in one of |
@@ -639,6 +784,7 @@ config USB_ETH_RNDIS | |||
639 | bool "RNDIS support" | 784 | bool "RNDIS support" |
640 | depends on USB_ETH | 785 | depends on USB_ETH |
641 | select USB_LIBCOMPOSITE | 786 | select USB_LIBCOMPOSITE |
787 | select USB_F_RNDIS | ||
642 | default y | 788 | default y |
643 | help | 789 | help |
644 | Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol, | 790 | Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol, |
@@ -658,6 +804,7 @@ config USB_ETH_EEM | |||
658 | bool "Ethernet Emulation Model (EEM) support" | 804 | bool "Ethernet Emulation Model (EEM) support" |
659 | depends on USB_ETH | 805 | depends on USB_ETH |
660 | select USB_LIBCOMPOSITE | 806 | select USB_LIBCOMPOSITE |
807 | select USB_F_EEM | ||
661 | default n | 808 | default n |
662 | help | 809 | help |
663 | CDC EEM is a newer USB standard that is somewhat simpler than CDC ECM | 810 | CDC EEM is a newer USB standard that is somewhat simpler than CDC ECM |
@@ -675,6 +822,8 @@ config USB_G_NCM | |||
675 | tristate "Network Control Model (NCM) support" | 822 | tristate "Network Control Model (NCM) support" |
676 | depends on NET | 823 | depends on NET |
677 | select USB_LIBCOMPOSITE | 824 | select USB_LIBCOMPOSITE |
825 | select USB_U_ETHER | ||
826 | select USB_F_NCM | ||
678 | select CRC32 | 827 | select CRC32 |
679 | help | 828 | help |
680 | This driver implements USB CDC NCM subclass standard. NCM is | 829 | This driver implements USB CDC NCM subclass standard. NCM is |
@@ -718,6 +867,7 @@ config USB_FUNCTIONFS | |||
718 | config USB_FUNCTIONFS_ETH | 867 | config USB_FUNCTIONFS_ETH |
719 | bool "Include configuration with CDC ECM (Ethernet)" | 868 | bool "Include configuration with CDC ECM (Ethernet)" |
720 | depends on USB_FUNCTIONFS && NET | 869 | depends on USB_FUNCTIONFS && NET |
870 | select USB_U_ETHER | ||
721 | help | 871 | help |
722 | Include a configuration with CDC ECM function (Ethernet) and the | 872 | Include a configuration with CDC ECM function (Ethernet) and the |
723 | Function Filesystem. | 873 | Function Filesystem. |
@@ -725,6 +875,8 @@ config USB_FUNCTIONFS_ETH | |||
725 | config USB_FUNCTIONFS_RNDIS | 875 | config USB_FUNCTIONFS_RNDIS |
726 | bool "Include configuration with RNDIS (Ethernet)" | 876 | bool "Include configuration with RNDIS (Ethernet)" |
727 | depends on USB_FUNCTIONFS && NET | 877 | depends on USB_FUNCTIONFS && NET |
878 | select USB_U_ETHER | ||
879 | select USB_U_RNDIS | ||
728 | help | 880 | help |
729 | Include a configuration with RNDIS function (Ethernet) and the Filesystem. | 881 | Include a configuration with RNDIS function (Ethernet) and the Filesystem. |
730 | 882 | ||
@@ -825,7 +977,9 @@ config USB_CDC_COMPOSITE | |||
825 | depends on NET | 977 | depends on NET |
826 | select USB_LIBCOMPOSITE | 978 | select USB_LIBCOMPOSITE |
827 | select USB_U_SERIAL | 979 | select USB_U_SERIAL |
980 | select USB_U_ETHER | ||
828 | select USB_F_ACM | 981 | select USB_F_ACM |
982 | select USB_F_ECM | ||
829 | help | 983 | help |
830 | This driver provides two functions in one configuration: | 984 | This driver provides two functions in one configuration: |
831 | a CDC Ethernet (ECM) link, and a CDC ACM (serial port) link. | 985 | a CDC Ethernet (ECM) link, and a CDC ACM (serial port) link. |
@@ -842,7 +996,11 @@ config USB_G_NOKIA | |||
842 | depends on PHONET | 996 | depends on PHONET |
843 | select USB_LIBCOMPOSITE | 997 | select USB_LIBCOMPOSITE |
844 | select USB_U_SERIAL | 998 | select USB_U_SERIAL |
999 | select USB_U_ETHER | ||
845 | select USB_F_ACM | 1000 | select USB_F_ACM |
1001 | select USB_F_OBEX | ||
1002 | select USB_F_PHONET | ||
1003 | select USB_F_ECM | ||
846 | help | 1004 | help |
847 | The Nokia composite gadget provides support for acm, obex | 1005 | The Nokia composite gadget provides support for acm, obex |
848 | and phonet in only one composite gadget driver. | 1006 | and phonet in only one composite gadget driver. |
@@ -869,6 +1027,8 @@ config USB_G_MULTI | |||
869 | select USB_G_MULTI_CDC if !USB_G_MULTI_RNDIS | 1027 | select USB_G_MULTI_CDC if !USB_G_MULTI_RNDIS |
870 | select USB_LIBCOMPOSITE | 1028 | select USB_LIBCOMPOSITE |
871 | select USB_U_SERIAL | 1029 | select USB_U_SERIAL |
1030 | select USB_U_ETHER | ||
1031 | select USB_U_RNDIS | ||
872 | select USB_F_ACM | 1032 | select USB_F_ACM |
873 | help | 1033 | help |
874 | The Multifunction Composite Gadget provides Ethernet (RNDIS | 1034 | The Multifunction Composite Gadget provides Ethernet (RNDIS |
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 6afd16659e78..bad08e66f369 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile | |||
@@ -33,6 +33,7 @@ obj-$(CONFIG_USB_EG20T) += pch_udc.o | |||
33 | obj-$(CONFIG_USB_MV_UDC) += mv_udc.o | 33 | obj-$(CONFIG_USB_MV_UDC) += mv_udc.o |
34 | mv_udc-y := mv_udc_core.o | 34 | mv_udc-y := mv_udc_core.o |
35 | obj-$(CONFIG_USB_FUSB300) += fusb300_udc.o | 35 | obj-$(CONFIG_USB_FUSB300) += fusb300_udc.o |
36 | obj-$(CONFIG_USB_FOTG210_UDC) += fotg210-udc.o | ||
36 | obj-$(CONFIG_USB_MV_U3D) += mv_u3d_core.o | 37 | obj-$(CONFIG_USB_MV_U3D) += mv_u3d_core.o |
37 | 38 | ||
38 | # USB Functions | 39 | # USB Functions |
@@ -45,6 +46,21 @@ usb_f_serial-y := f_serial.o | |||
45 | obj-$(CONFIG_USB_F_SERIAL) += usb_f_serial.o | 46 | obj-$(CONFIG_USB_F_SERIAL) += usb_f_serial.o |
46 | usb_f_obex-y := f_obex.o | 47 | usb_f_obex-y := f_obex.o |
47 | obj-$(CONFIG_USB_F_OBEX) += usb_f_obex.o | 48 | obj-$(CONFIG_USB_F_OBEX) += usb_f_obex.o |
49 | obj-$(CONFIG_USB_U_ETHER) += u_ether.o | ||
50 | u_rndis-y := rndis.o | ||
51 | obj-$(CONFIG_USB_U_RNDIS) += u_rndis.o | ||
52 | usb_f_ncm-y := f_ncm.o | ||
53 | obj-$(CONFIG_USB_F_NCM) += usb_f_ncm.o | ||
54 | usb_f_ecm-y := f_ecm.o | ||
55 | obj-$(CONFIG_USB_F_ECM) += usb_f_ecm.o | ||
56 | usb_f_phonet-y := f_phonet.o | ||
57 | obj-$(CONFIG_USB_F_PHONET) += usb_f_phonet.o | ||
58 | usb_f_eem-y := f_eem.o | ||
59 | obj-$(CONFIG_USB_F_EEM) += usb_f_eem.o | ||
60 | usb_f_ecm_subset-y := f_subset.o | ||
61 | obj-$(CONFIG_USB_F_SUBSET) += usb_f_ecm_subset.o | ||
62 | usb_f_rndis-y := f_rndis.o | ||
63 | obj-$(CONFIG_USB_F_RNDIS) += usb_f_rndis.o | ||
48 | 64 | ||
49 | # | 65 | # |
50 | # USB gadget drivers | 66 | # USB gadget drivers |
diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c index 2c5255182769..5a5acf22c694 100644 --- a/drivers/usb/gadget/cdc2.c +++ b/drivers/usb/gadget/cdc2.c | |||
@@ -15,6 +15,7 @@ | |||
15 | 15 | ||
16 | #include "u_ether.h" | 16 | #include "u_ether.h" |
17 | #include "u_serial.h" | 17 | #include "u_serial.h" |
18 | #include "u_ecm.h" | ||
18 | 19 | ||
19 | 20 | ||
20 | #define DRIVER_DESC "CDC Composite Gadget" | 21 | #define DRIVER_DESC "CDC Composite Gadget" |
@@ -32,18 +33,9 @@ | |||
32 | #define CDC_VENDOR_NUM 0x0525 /* NetChip */ | 33 | #define CDC_VENDOR_NUM 0x0525 /* NetChip */ |
33 | #define CDC_PRODUCT_NUM 0xa4aa /* CDC Composite: ECM + ACM */ | 34 | #define CDC_PRODUCT_NUM 0xa4aa /* CDC Composite: ECM + ACM */ |
34 | 35 | ||
35 | /*-------------------------------------------------------------------------*/ | ||
36 | USB_GADGET_COMPOSITE_OPTIONS(); | 36 | USB_GADGET_COMPOSITE_OPTIONS(); |
37 | 37 | ||
38 | /* | 38 | USB_ETHERNET_MODULE_PARAMETERS(); |
39 | * Kbuild is not very cooperative with respect to linking separately | ||
40 | * compiled library objects into one module. So for now we won't use | ||
41 | * separate compilation ... ensuring init/exit sections work to shrink | ||
42 | * the runtime footprint, and giving us at least some parts of what | ||
43 | * a "gcc --combine ... part1.c part2.c part3.c ... " build would. | ||
44 | */ | ||
45 | #include "f_ecm.c" | ||
46 | #include "u_ether.c" | ||
47 | 39 | ||
48 | /*-------------------------------------------------------------------------*/ | 40 | /*-------------------------------------------------------------------------*/ |
49 | 41 | ||
@@ -102,12 +94,13 @@ static struct usb_gadget_strings *dev_strings[] = { | |||
102 | NULL, | 94 | NULL, |
103 | }; | 95 | }; |
104 | 96 | ||
105 | static u8 hostaddr[ETH_ALEN]; | ||
106 | static struct eth_dev *the_dev; | ||
107 | /*-------------------------------------------------------------------------*/ | 97 | /*-------------------------------------------------------------------------*/ |
108 | static struct usb_function *f_acm; | 98 | static struct usb_function *f_acm; |
109 | static struct usb_function_instance *fi_serial; | 99 | static struct usb_function_instance *fi_serial; |
110 | 100 | ||
101 | static struct usb_function *f_ecm; | ||
102 | static struct usb_function_instance *fi_ecm; | ||
103 | |||
111 | /* | 104 | /* |
112 | * We _always_ have both CDC ECM and CDC ACM functions. | 105 | * We _always_ have both CDC ECM and CDC ACM functions. |
113 | */ | 106 | */ |
@@ -120,13 +113,27 @@ static int __init cdc_do_config(struct usb_configuration *c) | |||
120 | c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; | 113 | c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; |
121 | } | 114 | } |
122 | 115 | ||
123 | status = ecm_bind_config(c, hostaddr, the_dev); | 116 | fi_ecm = usb_get_function_instance("ecm"); |
124 | if (status < 0) | 117 | if (IS_ERR(fi_ecm)) { |
125 | return status; | 118 | status = PTR_ERR(fi_ecm); |
119 | goto err_func_ecm; | ||
120 | } | ||
121 | |||
122 | f_ecm = usb_get_function(fi_ecm); | ||
123 | if (IS_ERR(f_ecm)) { | ||
124 | status = PTR_ERR(f_ecm); | ||
125 | goto err_get_ecm; | ||
126 | } | ||
127 | |||
128 | status = usb_add_function(c, f_ecm); | ||
129 | if (status) | ||
130 | goto err_add_ecm; | ||
126 | 131 | ||
127 | fi_serial = usb_get_function_instance("acm"); | 132 | fi_serial = usb_get_function_instance("acm"); |
128 | if (IS_ERR(fi_serial)) | 133 | if (IS_ERR(fi_serial)) { |
129 | return PTR_ERR(fi_serial); | 134 | status = PTR_ERR(fi_serial); |
135 | goto err_get_acm; | ||
136 | } | ||
130 | 137 | ||
131 | f_acm = usb_get_function(fi_serial); | 138 | f_acm = usb_get_function(fi_serial); |
132 | if (IS_ERR(f_acm)) { | 139 | if (IS_ERR(f_acm)) { |
@@ -136,12 +143,21 @@ static int __init cdc_do_config(struct usb_configuration *c) | |||
136 | 143 | ||
137 | status = usb_add_function(c, f_acm); | 144 | status = usb_add_function(c, f_acm); |
138 | if (status) | 145 | if (status) |
139 | goto err_conf; | 146 | goto err_add_acm; |
147 | |||
140 | return 0; | 148 | return 0; |
141 | err_conf: | 149 | |
150 | err_add_acm: | ||
142 | usb_put_function(f_acm); | 151 | usb_put_function(f_acm); |
143 | err_func_acm: | 152 | err_func_acm: |
144 | usb_put_function_instance(fi_serial); | 153 | usb_put_function_instance(fi_serial); |
154 | err_get_acm: | ||
155 | usb_remove_function(c, f_ecm); | ||
156 | err_add_ecm: | ||
157 | usb_put_function(f_ecm); | ||
158 | err_get_ecm: | ||
159 | usb_put_function_instance(fi_ecm); | ||
160 | err_func_ecm: | ||
145 | return status; | 161 | return status; |
146 | } | 162 | } |
147 | 163 | ||
@@ -157,6 +173,7 @@ static struct usb_configuration cdc_config_driver = { | |||
157 | static int __init cdc_bind(struct usb_composite_dev *cdev) | 173 | static int __init cdc_bind(struct usb_composite_dev *cdev) |
158 | { | 174 | { |
159 | struct usb_gadget *gadget = cdev->gadget; | 175 | struct usb_gadget *gadget = cdev->gadget; |
176 | struct f_ecm_opts *ecm_opts; | ||
160 | int status; | 177 | int status; |
161 | 178 | ||
162 | if (!can_support_ecm(cdev->gadget)) { | 179 | if (!can_support_ecm(cdev->gadget)) { |
@@ -165,10 +182,23 @@ static int __init cdc_bind(struct usb_composite_dev *cdev) | |||
165 | return -EINVAL; | 182 | return -EINVAL; |
166 | } | 183 | } |
167 | 184 | ||
168 | /* set up network link layer */ | 185 | fi_ecm = usb_get_function_instance("ecm"); |
169 | the_dev = gether_setup(cdev->gadget, hostaddr); | 186 | if (IS_ERR(fi_ecm)) |
170 | if (IS_ERR(the_dev)) | 187 | return PTR_ERR(fi_ecm); |
171 | return PTR_ERR(the_dev); | 188 | |
189 | ecm_opts = container_of(fi_ecm, struct f_ecm_opts, func_inst); | ||
190 | |||
191 | gether_set_qmult(ecm_opts->net, qmult); | ||
192 | if (!gether_set_host_addr(ecm_opts->net, host_addr)) | ||
193 | pr_info("using host ethernet address: %s", host_addr); | ||
194 | if (!gether_set_dev_addr(ecm_opts->net, dev_addr)) | ||
195 | pr_info("using self ethernet address: %s", dev_addr); | ||
196 | |||
197 | fi_serial = usb_get_function_instance("acm"); | ||
198 | if (IS_ERR(fi_serial)) { | ||
199 | status = PTR_ERR(fi_serial); | ||
200 | goto fail; | ||
201 | } | ||
172 | 202 | ||
173 | /* Allocate string descriptor numbers ... note that string | 203 | /* Allocate string descriptor numbers ... note that string |
174 | * contents can be overridden by the composite_dev glue. | 204 | * contents can be overridden by the composite_dev glue. |
@@ -192,7 +222,9 @@ static int __init cdc_bind(struct usb_composite_dev *cdev) | |||
192 | return 0; | 222 | return 0; |
193 | 223 | ||
194 | fail1: | 224 | fail1: |
195 | gether_cleanup(the_dev); | 225 | usb_put_function_instance(fi_serial); |
226 | fail: | ||
227 | usb_put_function_instance(fi_ecm); | ||
196 | return status; | 228 | return status; |
197 | } | 229 | } |
198 | 230 | ||
@@ -200,7 +232,10 @@ static int __exit cdc_unbind(struct usb_composite_dev *cdev) | |||
200 | { | 232 | { |
201 | usb_put_function(f_acm); | 233 | usb_put_function(f_acm); |
202 | usb_put_function_instance(fi_serial); | 234 | usb_put_function_instance(fi_serial); |
203 | gether_cleanup(the_dev); | 235 | if (!IS_ERR_OR_NULL(f_ecm)) |
236 | usb_put_function(f_ecm); | ||
237 | if (!IS_ERR_OR_NULL(fi_ecm)) | ||
238 | usb_put_function_instance(fi_ecm); | ||
204 | return 0; | 239 | return 0; |
205 | } | 240 | } |
206 | 241 | ||
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 56c8ecae9bc3..f48712ffe261 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c | |||
@@ -14,6 +14,7 @@ | |||
14 | /* #define VERBOSE_DEBUG */ | 14 | /* #define VERBOSE_DEBUG */ |
15 | 15 | ||
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/netdevice.h> | ||
17 | 18 | ||
18 | #if defined USB_ETH_RNDIS | 19 | #if defined USB_ETH_RNDIS |
19 | # undef USB_ETH_RNDIS | 20 | # undef USB_ETH_RNDIS |
@@ -91,27 +92,23 @@ static inline bool has_rndis(void) | |||
91 | #endif | 92 | #endif |
92 | } | 93 | } |
93 | 94 | ||
94 | /*-------------------------------------------------------------------------*/ | 95 | #include <linux/module.h> |
95 | 96 | ||
96 | /* | 97 | #include "u_ecm.h" |
97 | * Kbuild is not very cooperative with respect to linking separately | 98 | #include "u_gether.h" |
98 | * compiled library objects into one module. So for now we won't use | ||
99 | * separate compilation ... ensuring init/exit sections work to shrink | ||
100 | * the runtime footprint, and giving us at least some parts of what | ||
101 | * a "gcc --combine ... part1.c part2.c part3.c ... " build would. | ||
102 | */ | ||
103 | #include "f_ecm.c" | ||
104 | #include "f_subset.c" | ||
105 | #ifdef USB_ETH_RNDIS | 99 | #ifdef USB_ETH_RNDIS |
106 | #include "f_rndis.c" | 100 | #include "u_rndis.h" |
107 | #include "rndis.c" | 101 | #include "rndis.h" |
102 | #else | ||
103 | #define rndis_borrow_net(...) do {} while (0) | ||
108 | #endif | 104 | #endif |
109 | #include "f_eem.c" | 105 | #include "u_eem.h" |
110 | #include "u_ether.c" | ||
111 | 106 | ||
112 | /*-------------------------------------------------------------------------*/ | 107 | /*-------------------------------------------------------------------------*/ |
113 | USB_GADGET_COMPOSITE_OPTIONS(); | 108 | USB_GADGET_COMPOSITE_OPTIONS(); |
114 | 109 | ||
110 | USB_ETHERNET_MODULE_PARAMETERS(); | ||
111 | |||
115 | /* DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! | 112 | /* DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! |
116 | * Instead: allocate your own, using normal USB-IF procedures. | 113 | * Instead: allocate your own, using normal USB-IF procedures. |
117 | */ | 114 | */ |
@@ -206,8 +203,18 @@ static struct usb_gadget_strings *dev_strings[] = { | |||
206 | NULL, | 203 | NULL, |
207 | }; | 204 | }; |
208 | 205 | ||
209 | static u8 hostaddr[ETH_ALEN]; | 206 | static struct usb_function_instance *fi_ecm; |
210 | static struct eth_dev *the_dev; | 207 | static struct usb_function *f_ecm; |
208 | |||
209 | static struct usb_function_instance *fi_eem; | ||
210 | static struct usb_function *f_eem; | ||
211 | |||
212 | static struct usb_function_instance *fi_geth; | ||
213 | static struct usb_function *f_geth; | ||
214 | |||
215 | static struct usb_function_instance *fi_rndis; | ||
216 | static struct usb_function *f_rndis; | ||
217 | |||
211 | /*-------------------------------------------------------------------------*/ | 218 | /*-------------------------------------------------------------------------*/ |
212 | 219 | ||
213 | /* | 220 | /* |
@@ -217,6 +224,8 @@ static struct eth_dev *the_dev; | |||
217 | */ | 224 | */ |
218 | static int __init rndis_do_config(struct usb_configuration *c) | 225 | static int __init rndis_do_config(struct usb_configuration *c) |
219 | { | 226 | { |
227 | int status; | ||
228 | |||
220 | /* FIXME alloc iConfiguration string, set it in c->strings */ | 229 | /* FIXME alloc iConfiguration string, set it in c->strings */ |
221 | 230 | ||
222 | if (gadget_is_otg(c->cdev->gadget)) { | 231 | if (gadget_is_otg(c->cdev->gadget)) { |
@@ -224,7 +233,15 @@ static int __init rndis_do_config(struct usb_configuration *c) | |||
224 | c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; | 233 | c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; |
225 | } | 234 | } |
226 | 235 | ||
227 | return rndis_bind_config(c, hostaddr, the_dev); | 236 | f_rndis = usb_get_function(fi_rndis); |
237 | if (IS_ERR(f_rndis)) | ||
238 | return PTR_ERR(f_rndis); | ||
239 | |||
240 | status = usb_add_function(c, f_rndis); | ||
241 | if (status < 0) | ||
242 | usb_put_function(f_rndis); | ||
243 | |||
244 | return status; | ||
228 | } | 245 | } |
229 | 246 | ||
230 | static struct usb_configuration rndis_config_driver = { | 247 | static struct usb_configuration rndis_config_driver = { |
@@ -249,6 +266,8 @@ MODULE_PARM_DESC(use_eem, "use CDC EEM mode"); | |||
249 | */ | 266 | */ |
250 | static int __init eth_do_config(struct usb_configuration *c) | 267 | static int __init eth_do_config(struct usb_configuration *c) |
251 | { | 268 | { |
269 | int status = 0; | ||
270 | |||
252 | /* FIXME alloc iConfiguration string, set it in c->strings */ | 271 | /* FIXME alloc iConfiguration string, set it in c->strings */ |
253 | 272 | ||
254 | if (gadget_is_otg(c->cdev->gadget)) { | 273 | if (gadget_is_otg(c->cdev->gadget)) { |
@@ -256,12 +275,38 @@ static int __init eth_do_config(struct usb_configuration *c) | |||
256 | c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; | 275 | c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; |
257 | } | 276 | } |
258 | 277 | ||
259 | if (use_eem) | 278 | if (use_eem) { |
260 | return eem_bind_config(c, the_dev); | 279 | f_eem = usb_get_function(fi_eem); |
261 | else if (can_support_ecm(c->cdev->gadget)) | 280 | if (IS_ERR(f_eem)) |
262 | return ecm_bind_config(c, hostaddr, the_dev); | 281 | return PTR_ERR(f_eem); |
263 | else | 282 | |
264 | return geth_bind_config(c, hostaddr, the_dev); | 283 | status = usb_add_function(c, f_eem); |
284 | if (status < 0) | ||
285 | usb_put_function(f_eem); | ||
286 | |||
287 | return status; | ||
288 | } else if (can_support_ecm(c->cdev->gadget)) { | ||
289 | f_ecm = usb_get_function(fi_ecm); | ||
290 | if (IS_ERR(f_ecm)) | ||
291 | return PTR_ERR(f_ecm); | ||
292 | |||
293 | status = usb_add_function(c, f_ecm); | ||
294 | if (status < 0) | ||
295 | usb_put_function(f_ecm); | ||
296 | |||
297 | return status; | ||
298 | } else { | ||
299 | f_geth = usb_get_function(fi_geth); | ||
300 | if (IS_ERR(f_geth)) | ||
301 | return PTR_ERR(f_geth); | ||
302 | |||
303 | status = usb_add_function(c, f_geth); | ||
304 | if (status < 0) | ||
305 | usb_put_function(f_geth); | ||
306 | |||
307 | return status; | ||
308 | } | ||
309 | |||
265 | } | 310 | } |
266 | 311 | ||
267 | static struct usb_configuration eth_config_driver = { | 312 | static struct usb_configuration eth_config_driver = { |
@@ -276,24 +321,50 @@ static struct usb_configuration eth_config_driver = { | |||
276 | static int __init eth_bind(struct usb_composite_dev *cdev) | 321 | static int __init eth_bind(struct usb_composite_dev *cdev) |
277 | { | 322 | { |
278 | struct usb_gadget *gadget = cdev->gadget; | 323 | struct usb_gadget *gadget = cdev->gadget; |
324 | struct f_eem_opts *eem_opts = NULL; | ||
325 | struct f_ecm_opts *ecm_opts = NULL; | ||
326 | struct f_gether_opts *geth_opts = NULL; | ||
327 | struct net_device *net; | ||
279 | int status; | 328 | int status; |
280 | 329 | ||
281 | /* set up network link layer */ | ||
282 | the_dev = gether_setup(cdev->gadget, hostaddr); | ||
283 | if (IS_ERR(the_dev)) | ||
284 | return PTR_ERR(the_dev); | ||
285 | |||
286 | /* set up main config label and device descriptor */ | 330 | /* set up main config label and device descriptor */ |
287 | if (use_eem) { | 331 | if (use_eem) { |
288 | /* EEM */ | 332 | /* EEM */ |
333 | fi_eem = usb_get_function_instance("eem"); | ||
334 | if (IS_ERR(fi_eem)) | ||
335 | return PTR_ERR(fi_eem); | ||
336 | |||
337 | eem_opts = container_of(fi_eem, struct f_eem_opts, func_inst); | ||
338 | |||
339 | net = eem_opts->net; | ||
340 | |||
289 | eth_config_driver.label = "CDC Ethernet (EEM)"; | 341 | eth_config_driver.label = "CDC Ethernet (EEM)"; |
290 | device_desc.idVendor = cpu_to_le16(EEM_VENDOR_NUM); | 342 | device_desc.idVendor = cpu_to_le16(EEM_VENDOR_NUM); |
291 | device_desc.idProduct = cpu_to_le16(EEM_PRODUCT_NUM); | 343 | device_desc.idProduct = cpu_to_le16(EEM_PRODUCT_NUM); |
292 | } else if (can_support_ecm(cdev->gadget)) { | 344 | } else if (can_support_ecm(gadget)) { |
293 | /* ECM */ | 345 | /* ECM */ |
346 | |||
347 | fi_ecm = usb_get_function_instance("ecm"); | ||
348 | if (IS_ERR(fi_ecm)) | ||
349 | return PTR_ERR(fi_ecm); | ||
350 | |||
351 | ecm_opts = container_of(fi_ecm, struct f_ecm_opts, func_inst); | ||
352 | |||
353 | net = ecm_opts->net; | ||
354 | |||
294 | eth_config_driver.label = "CDC Ethernet (ECM)"; | 355 | eth_config_driver.label = "CDC Ethernet (ECM)"; |
295 | } else { | 356 | } else { |
296 | /* CDC Subset */ | 357 | /* CDC Subset */ |
358 | |||
359 | fi_geth = usb_get_function_instance("geth"); | ||
360 | if (IS_ERR(fi_geth)) | ||
361 | return PTR_ERR(fi_geth); | ||
362 | |||
363 | geth_opts = container_of(fi_geth, struct f_gether_opts, | ||
364 | func_inst); | ||
365 | |||
366 | net = geth_opts->net; | ||
367 | |||
297 | eth_config_driver.label = "CDC Subset/SAFE"; | 368 | eth_config_driver.label = "CDC Subset/SAFE"; |
298 | 369 | ||
299 | device_desc.idVendor = cpu_to_le16(SIMPLE_VENDOR_NUM); | 370 | device_desc.idVendor = cpu_to_le16(SIMPLE_VENDOR_NUM); |
@@ -302,8 +373,34 @@ static int __init eth_bind(struct usb_composite_dev *cdev) | |||
302 | device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC; | 373 | device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC; |
303 | } | 374 | } |
304 | 375 | ||
376 | gether_set_qmult(net, qmult); | ||
377 | if (!gether_set_host_addr(net, host_addr)) | ||
378 | pr_info("using host ethernet address: %s", host_addr); | ||
379 | if (!gether_set_dev_addr(net, dev_addr)) | ||
380 | pr_info("using self ethernet address: %s", dev_addr); | ||
381 | |||
305 | if (has_rndis()) { | 382 | if (has_rndis()) { |
306 | /* RNDIS plus ECM-or-Subset */ | 383 | /* RNDIS plus ECM-or-Subset */ |
384 | gether_set_gadget(net, cdev->gadget); | ||
385 | status = gether_register_netdev(net); | ||
386 | if (status) | ||
387 | goto fail; | ||
388 | |||
389 | if (use_eem) | ||
390 | eem_opts->bound = true; | ||
391 | else if (can_support_ecm(gadget)) | ||
392 | ecm_opts->bound = true; | ||
393 | else | ||
394 | geth_opts->bound = true; | ||
395 | |||
396 | fi_rndis = usb_get_function_instance("rndis"); | ||
397 | if (IS_ERR(fi_rndis)) { | ||
398 | status = PTR_ERR(fi_rndis); | ||
399 | goto fail; | ||
400 | } | ||
401 | |||
402 | rndis_borrow_net(fi_rndis, net); | ||
403 | |||
307 | device_desc.idVendor = cpu_to_le16(RNDIS_VENDOR_NUM); | 404 | device_desc.idVendor = cpu_to_le16(RNDIS_VENDOR_NUM); |
308 | device_desc.idProduct = cpu_to_le16(RNDIS_PRODUCT_NUM); | 405 | device_desc.idProduct = cpu_to_le16(RNDIS_PRODUCT_NUM); |
309 | device_desc.bNumConfigurations = 2; | 406 | device_desc.bNumConfigurations = 2; |
@@ -315,7 +412,7 @@ static int __init eth_bind(struct usb_composite_dev *cdev) | |||
315 | 412 | ||
316 | status = usb_string_ids_tab(cdev, strings_dev); | 413 | status = usb_string_ids_tab(cdev, strings_dev); |
317 | if (status < 0) | 414 | if (status < 0) |
318 | goto fail; | 415 | goto fail1; |
319 | device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; | 416 | device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; |
320 | device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; | 417 | device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; |
321 | 418 | ||
@@ -324,12 +421,12 @@ static int __init eth_bind(struct usb_composite_dev *cdev) | |||
324 | status = usb_add_config(cdev, &rndis_config_driver, | 421 | status = usb_add_config(cdev, &rndis_config_driver, |
325 | rndis_do_config); | 422 | rndis_do_config); |
326 | if (status < 0) | 423 | if (status < 0) |
327 | goto fail; | 424 | goto fail1; |
328 | } | 425 | } |
329 | 426 | ||
330 | status = usb_add_config(cdev, ð_config_driver, eth_do_config); | 427 | status = usb_add_config(cdev, ð_config_driver, eth_do_config); |
331 | if (status < 0) | 428 | if (status < 0) |
332 | goto fail; | 429 | goto fail1; |
333 | 430 | ||
334 | usb_composite_overwrite_options(cdev, &coverwrite); | 431 | usb_composite_overwrite_options(cdev, &coverwrite); |
335 | dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n", | 432 | dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n", |
@@ -337,14 +434,29 @@ static int __init eth_bind(struct usb_composite_dev *cdev) | |||
337 | 434 | ||
338 | return 0; | 435 | return 0; |
339 | 436 | ||
437 | fail1: | ||
438 | if (has_rndis()) | ||
439 | usb_put_function_instance(fi_rndis); | ||
340 | fail: | 440 | fail: |
341 | gether_cleanup(the_dev); | 441 | if (use_eem) |
442 | usb_put_function_instance(fi_eem); | ||
443 | else if (can_support_ecm(gadget)) | ||
444 | usb_put_function_instance(fi_ecm); | ||
445 | else | ||
446 | usb_put_function_instance(fi_geth); | ||
342 | return status; | 447 | return status; |
343 | } | 448 | } |
344 | 449 | ||
345 | static int __exit eth_unbind(struct usb_composite_dev *cdev) | 450 | static int __exit eth_unbind(struct usb_composite_dev *cdev) |
346 | { | 451 | { |
347 | gether_cleanup(the_dev); | 452 | if (has_rndis()) |
453 | usb_put_function_instance(fi_rndis); | ||
454 | if (use_eem) | ||
455 | usb_put_function_instance(fi_eem); | ||
456 | else if (can_support_ecm(cdev->gadget)) | ||
457 | usb_put_function_instance(fi_ecm); | ||
458 | else | ||
459 | usb_put_function_instance(fi_geth); | ||
348 | return 0; | 460 | return 0; |
349 | } | 461 | } |
350 | 462 | ||
diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c index abf8a31ae146..5d3561ea1c15 100644 --- a/drivers/usb/gadget/f_ecm.c +++ b/drivers/usb/gadget/f_ecm.c | |||
@@ -14,10 +14,13 @@ | |||
14 | 14 | ||
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/module.h> | ||
17 | #include <linux/device.h> | 18 | #include <linux/device.h> |
18 | #include <linux/etherdevice.h> | 19 | #include <linux/etherdevice.h> |
19 | 20 | ||
20 | #include "u_ether.h" | 21 | #include "u_ether.h" |
22 | #include "u_ether_configfs.h" | ||
23 | #include "u_ecm.h" | ||
21 | 24 | ||
22 | 25 | ||
23 | /* | 26 | /* |
@@ -684,9 +687,44 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f) | |||
684 | { | 687 | { |
685 | struct usb_composite_dev *cdev = c->cdev; | 688 | struct usb_composite_dev *cdev = c->cdev; |
686 | struct f_ecm *ecm = func_to_ecm(f); | 689 | struct f_ecm *ecm = func_to_ecm(f); |
690 | struct usb_string *us; | ||
687 | int status; | 691 | int status; |
688 | struct usb_ep *ep; | 692 | struct usb_ep *ep; |
689 | 693 | ||
694 | #ifndef USBF_ECM_INCLUDED | ||
695 | struct f_ecm_opts *ecm_opts; | ||
696 | |||
697 | if (!can_support_ecm(cdev->gadget)) | ||
698 | return -EINVAL; | ||
699 | |||
700 | ecm_opts = container_of(f->fi, struct f_ecm_opts, func_inst); | ||
701 | |||
702 | /* | ||
703 | * in drivers/usb/gadget/configfs.c:configfs_composite_bind() | ||
704 | * configurations are bound in sequence with list_for_each_entry, | ||
705 | * in each configuration its functions are bound in sequence | ||
706 | * with list_for_each_entry, so we assume no race condition | ||
707 | * with regard to ecm_opts->bound access | ||
708 | */ | ||
709 | if (!ecm_opts->bound) { | ||
710 | mutex_lock(&ecm_opts->lock); | ||
711 | gether_set_gadget(ecm_opts->net, cdev->gadget); | ||
712 | status = gether_register_netdev(ecm_opts->net); | ||
713 | mutex_unlock(&ecm_opts->lock); | ||
714 | if (status) | ||
715 | return status; | ||
716 | ecm_opts->bound = true; | ||
717 | } | ||
718 | #endif | ||
719 | us = usb_gstrings_attach(cdev, ecm_strings, | ||
720 | ARRAY_SIZE(ecm_string_defs)); | ||
721 | if (IS_ERR(us)) | ||
722 | return PTR_ERR(us); | ||
723 | ecm_control_intf.iInterface = us[0].id; | ||
724 | ecm_data_intf.iInterface = us[2].id; | ||
725 | ecm_desc.iMACAddress = us[1].id; | ||
726 | ecm_iad_descriptor.iFunction = us[3].id; | ||
727 | |||
690 | /* allocate instance-specific interface IDs */ | 728 | /* allocate instance-specific interface IDs */ |
691 | status = usb_interface_id(c, f); | 729 | status = usb_interface_id(c, f); |
692 | if (status < 0) | 730 | if (status < 0) |
@@ -796,14 +834,15 @@ fail: | |||
796 | return status; | 834 | return status; |
797 | } | 835 | } |
798 | 836 | ||
837 | #ifdef USBF_ECM_INCLUDED | ||
838 | |||
799 | static void | 839 | static void |
800 | ecm_unbind(struct usb_configuration *c, struct usb_function *f) | 840 | ecm_old_unbind(struct usb_configuration *c, struct usb_function *f) |
801 | { | 841 | { |
802 | struct f_ecm *ecm = func_to_ecm(f); | 842 | struct f_ecm *ecm = func_to_ecm(f); |
803 | 843 | ||
804 | DBG(c->cdev, "ecm unbind\n"); | 844 | DBG(c->cdev, "ecm unbind\n"); |
805 | 845 | ||
806 | ecm_string_defs[0].id = 0; | ||
807 | usb_free_all_descriptors(f); | 846 | usb_free_all_descriptors(f); |
808 | 847 | ||
809 | kfree(ecm->notify_req->buf); | 848 | kfree(ecm->notify_req->buf); |
@@ -834,17 +873,6 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], | |||
834 | if (!can_support_ecm(c->cdev->gadget) || !ethaddr) | 873 | if (!can_support_ecm(c->cdev->gadget) || !ethaddr) |
835 | return -EINVAL; | 874 | return -EINVAL; |
836 | 875 | ||
837 | if (ecm_string_defs[0].id == 0) { | ||
838 | status = usb_string_ids_tab(c->cdev, ecm_string_defs); | ||
839 | if (status) | ||
840 | return status; | ||
841 | |||
842 | ecm_control_intf.iInterface = ecm_string_defs[0].id; | ||
843 | ecm_data_intf.iInterface = ecm_string_defs[2].id; | ||
844 | ecm_desc.iMACAddress = ecm_string_defs[1].id; | ||
845 | ecm_iad_descriptor.iFunction = ecm_string_defs[3].id; | ||
846 | } | ||
847 | |||
848 | /* allocate and initialize one new instance */ | 876 | /* allocate and initialize one new instance */ |
849 | ecm = kzalloc(sizeof *ecm, GFP_KERNEL); | 877 | ecm = kzalloc(sizeof *ecm, GFP_KERNEL); |
850 | if (!ecm) | 878 | if (!ecm) |
@@ -858,10 +886,9 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], | |||
858 | ecm->port.cdc_filter = DEFAULT_FILTER; | 886 | ecm->port.cdc_filter = DEFAULT_FILTER; |
859 | 887 | ||
860 | ecm->port.func.name = "cdc_ethernet"; | 888 | ecm->port.func.name = "cdc_ethernet"; |
861 | ecm->port.func.strings = ecm_strings; | ||
862 | /* descriptors are per-instance copies */ | 889 | /* descriptors are per-instance copies */ |
863 | ecm->port.func.bind = ecm_bind; | 890 | ecm->port.func.bind = ecm_bind; |
864 | ecm->port.func.unbind = ecm_unbind; | 891 | ecm->port.func.unbind = ecm_old_unbind; |
865 | ecm->port.func.set_alt = ecm_set_alt; | 892 | ecm->port.func.set_alt = ecm_set_alt; |
866 | ecm->port.func.get_alt = ecm_get_alt; | 893 | ecm->port.func.get_alt = ecm_get_alt; |
867 | ecm->port.func.setup = ecm_setup; | 894 | ecm->port.func.setup = ecm_setup; |
@@ -872,3 +899,143 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], | |||
872 | kfree(ecm); | 899 | kfree(ecm); |
873 | return status; | 900 | return status; |
874 | } | 901 | } |
902 | |||
903 | #else | ||
904 | |||
905 | static inline struct f_ecm_opts *to_f_ecm_opts(struct config_item *item) | ||
906 | { | ||
907 | return container_of(to_config_group(item), struct f_ecm_opts, | ||
908 | func_inst.group); | ||
909 | } | ||
910 | |||
911 | /* f_ecm_item_ops */ | ||
912 | USB_ETHERNET_CONFIGFS_ITEM(ecm); | ||
913 | |||
914 | /* f_ecm_opts_dev_addr */ | ||
915 | USB_ETHERNET_CONFIGFS_ITEM_ATTR_DEV_ADDR(ecm); | ||
916 | |||
917 | /* f_ecm_opts_host_addr */ | ||
918 | USB_ETHERNET_CONFIGFS_ITEM_ATTR_HOST_ADDR(ecm); | ||
919 | |||
920 | /* f_ecm_opts_qmult */ | ||
921 | USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(ecm); | ||
922 | |||
923 | /* f_ecm_opts_ifname */ | ||
924 | USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(ecm); | ||
925 | |||
926 | static struct configfs_attribute *ecm_attrs[] = { | ||
927 | &f_ecm_opts_dev_addr.attr, | ||
928 | &f_ecm_opts_host_addr.attr, | ||
929 | &f_ecm_opts_qmult.attr, | ||
930 | &f_ecm_opts_ifname.attr, | ||
931 | NULL, | ||
932 | }; | ||
933 | |||
934 | static struct config_item_type ecm_func_type = { | ||
935 | .ct_item_ops = &ecm_item_ops, | ||
936 | .ct_attrs = ecm_attrs, | ||
937 | .ct_owner = THIS_MODULE, | ||
938 | }; | ||
939 | |||
940 | static void ecm_free_inst(struct usb_function_instance *f) | ||
941 | { | ||
942 | struct f_ecm_opts *opts; | ||
943 | |||
944 | opts = container_of(f, struct f_ecm_opts, func_inst); | ||
945 | if (opts->bound) | ||
946 | gether_cleanup(netdev_priv(opts->net)); | ||
947 | else | ||
948 | free_netdev(opts->net); | ||
949 | kfree(opts); | ||
950 | } | ||
951 | |||
952 | static struct usb_function_instance *ecm_alloc_inst(void) | ||
953 | { | ||
954 | struct f_ecm_opts *opts; | ||
955 | |||
956 | opts = kzalloc(sizeof(*opts), GFP_KERNEL); | ||
957 | if (!opts) | ||
958 | return ERR_PTR(-ENOMEM); | ||
959 | mutex_init(&opts->lock); | ||
960 | opts->func_inst.free_func_inst = ecm_free_inst; | ||
961 | opts->net = gether_setup_default(); | ||
962 | if (IS_ERR(opts->net)) | ||
963 | return ERR_PTR(PTR_ERR(opts->net)); | ||
964 | |||
965 | config_group_init_type_name(&opts->func_inst.group, "", &ecm_func_type); | ||
966 | |||
967 | return &opts->func_inst; | ||
968 | } | ||
969 | |||
970 | static void ecm_free(struct usb_function *f) | ||
971 | { | ||
972 | struct f_ecm *ecm; | ||
973 | struct f_ecm_opts *opts; | ||
974 | |||
975 | ecm = func_to_ecm(f); | ||
976 | opts = container_of(f->fi, struct f_ecm_opts, func_inst); | ||
977 | kfree(ecm); | ||
978 | mutex_lock(&opts->lock); | ||
979 | opts->refcnt--; | ||
980 | mutex_unlock(&opts->lock); | ||
981 | } | ||
982 | |||
983 | static void ecm_unbind(struct usb_configuration *c, struct usb_function *f) | ||
984 | { | ||
985 | struct f_ecm *ecm = func_to_ecm(f); | ||
986 | |||
987 | DBG(c->cdev, "ecm unbind\n"); | ||
988 | |||
989 | usb_free_all_descriptors(f); | ||
990 | |||
991 | kfree(ecm->notify_req->buf); | ||
992 | usb_ep_free_request(ecm->notify, ecm->notify_req); | ||
993 | } | ||
994 | |||
995 | struct usb_function *ecm_alloc(struct usb_function_instance *fi) | ||
996 | { | ||
997 | struct f_ecm *ecm; | ||
998 | struct f_ecm_opts *opts; | ||
999 | int status; | ||
1000 | |||
1001 | /* allocate and initialize one new instance */ | ||
1002 | ecm = kzalloc(sizeof(*ecm), GFP_KERNEL); | ||
1003 | if (!ecm) | ||
1004 | return ERR_PTR(-ENOMEM); | ||
1005 | |||
1006 | opts = container_of(fi, struct f_ecm_opts, func_inst); | ||
1007 | mutex_lock(&opts->lock); | ||
1008 | opts->refcnt++; | ||
1009 | |||
1010 | /* export host's Ethernet address in CDC format */ | ||
1011 | status = gether_get_host_addr_cdc(opts->net, ecm->ethaddr, | ||
1012 | sizeof(ecm->ethaddr)); | ||
1013 | if (status < 12) { | ||
1014 | kfree(ecm); | ||
1015 | mutex_unlock(&opts->lock); | ||
1016 | return ERR_PTR(-EINVAL); | ||
1017 | } | ||
1018 | ecm_string_defs[1].s = ecm->ethaddr; | ||
1019 | |||
1020 | ecm->port.ioport = netdev_priv(opts->net); | ||
1021 | mutex_unlock(&opts->lock); | ||
1022 | ecm->port.cdc_filter = DEFAULT_FILTER; | ||
1023 | |||
1024 | ecm->port.func.name = "cdc_ethernet"; | ||
1025 | /* descriptors are per-instance copies */ | ||
1026 | ecm->port.func.bind = ecm_bind; | ||
1027 | ecm->port.func.unbind = ecm_unbind; | ||
1028 | ecm->port.func.set_alt = ecm_set_alt; | ||
1029 | ecm->port.func.get_alt = ecm_get_alt; | ||
1030 | ecm->port.func.setup = ecm_setup; | ||
1031 | ecm->port.func.disable = ecm_disable; | ||
1032 | ecm->port.func.free_func = ecm_free; | ||
1033 | |||
1034 | return &ecm->port.func; | ||
1035 | } | ||
1036 | |||
1037 | DECLARE_USB_FUNCTION_INIT(ecm, ecm_alloc_inst, ecm_alloc); | ||
1038 | MODULE_LICENSE("GPL"); | ||
1039 | MODULE_AUTHOR("David Brownell"); | ||
1040 | |||
1041 | #endif | ||
diff --git a/drivers/usb/gadget/f_eem.c b/drivers/usb/gadget/f_eem.c index f4e0bbef602a..90ee8022e8d8 100644 --- a/drivers/usb/gadget/f_eem.c +++ b/drivers/usb/gadget/f_eem.c | |||
@@ -12,12 +12,15 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/module.h> | ||
15 | #include <linux/device.h> | 16 | #include <linux/device.h> |
16 | #include <linux/etherdevice.h> | 17 | #include <linux/etherdevice.h> |
17 | #include <linux/crc32.h> | 18 | #include <linux/crc32.h> |
18 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
19 | 20 | ||
20 | #include "u_ether.h" | 21 | #include "u_ether.h" |
22 | #include "u_ether_configfs.h" | ||
23 | #include "u_eem.h" | ||
21 | 24 | ||
22 | #define EEM_HLEN 2 | 25 | #define EEM_HLEN 2 |
23 | 26 | ||
@@ -40,7 +43,7 @@ static inline struct f_eem *func_to_eem(struct usb_function *f) | |||
40 | 43 | ||
41 | /* interface descriptor: */ | 44 | /* interface descriptor: */ |
42 | 45 | ||
43 | static struct usb_interface_descriptor eem_intf __initdata = { | 46 | static struct usb_interface_descriptor eem_intf = { |
44 | .bLength = sizeof eem_intf, | 47 | .bLength = sizeof eem_intf, |
45 | .bDescriptorType = USB_DT_INTERFACE, | 48 | .bDescriptorType = USB_DT_INTERFACE, |
46 | 49 | ||
@@ -54,7 +57,7 @@ static struct usb_interface_descriptor eem_intf __initdata = { | |||
54 | 57 | ||
55 | /* full speed support: */ | 58 | /* full speed support: */ |
56 | 59 | ||
57 | static struct usb_endpoint_descriptor eem_fs_in_desc __initdata = { | 60 | static struct usb_endpoint_descriptor eem_fs_in_desc = { |
58 | .bLength = USB_DT_ENDPOINT_SIZE, | 61 | .bLength = USB_DT_ENDPOINT_SIZE, |
59 | .bDescriptorType = USB_DT_ENDPOINT, | 62 | .bDescriptorType = USB_DT_ENDPOINT, |
60 | 63 | ||
@@ -62,7 +65,7 @@ static struct usb_endpoint_descriptor eem_fs_in_desc __initdata = { | |||
62 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 65 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
63 | }; | 66 | }; |
64 | 67 | ||
65 | static struct usb_endpoint_descriptor eem_fs_out_desc __initdata = { | 68 | static struct usb_endpoint_descriptor eem_fs_out_desc = { |
66 | .bLength = USB_DT_ENDPOINT_SIZE, | 69 | .bLength = USB_DT_ENDPOINT_SIZE, |
67 | .bDescriptorType = USB_DT_ENDPOINT, | 70 | .bDescriptorType = USB_DT_ENDPOINT, |
68 | 71 | ||
@@ -70,7 +73,7 @@ static struct usb_endpoint_descriptor eem_fs_out_desc __initdata = { | |||
70 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 73 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
71 | }; | 74 | }; |
72 | 75 | ||
73 | static struct usb_descriptor_header *eem_fs_function[] __initdata = { | 76 | static struct usb_descriptor_header *eem_fs_function[] = { |
74 | /* CDC EEM control descriptors */ | 77 | /* CDC EEM control descriptors */ |
75 | (struct usb_descriptor_header *) &eem_intf, | 78 | (struct usb_descriptor_header *) &eem_intf, |
76 | (struct usb_descriptor_header *) &eem_fs_in_desc, | 79 | (struct usb_descriptor_header *) &eem_fs_in_desc, |
@@ -80,7 +83,7 @@ static struct usb_descriptor_header *eem_fs_function[] __initdata = { | |||
80 | 83 | ||
81 | /* high speed support: */ | 84 | /* high speed support: */ |
82 | 85 | ||
83 | static struct usb_endpoint_descriptor eem_hs_in_desc __initdata = { | 86 | static struct usb_endpoint_descriptor eem_hs_in_desc = { |
84 | .bLength = USB_DT_ENDPOINT_SIZE, | 87 | .bLength = USB_DT_ENDPOINT_SIZE, |
85 | .bDescriptorType = USB_DT_ENDPOINT, | 88 | .bDescriptorType = USB_DT_ENDPOINT, |
86 | 89 | ||
@@ -89,7 +92,7 @@ static struct usb_endpoint_descriptor eem_hs_in_desc __initdata = { | |||
89 | .wMaxPacketSize = cpu_to_le16(512), | 92 | .wMaxPacketSize = cpu_to_le16(512), |
90 | }; | 93 | }; |
91 | 94 | ||
92 | static struct usb_endpoint_descriptor eem_hs_out_desc __initdata = { | 95 | static struct usb_endpoint_descriptor eem_hs_out_desc = { |
93 | .bLength = USB_DT_ENDPOINT_SIZE, | 96 | .bLength = USB_DT_ENDPOINT_SIZE, |
94 | .bDescriptorType = USB_DT_ENDPOINT, | 97 | .bDescriptorType = USB_DT_ENDPOINT, |
95 | 98 | ||
@@ -98,7 +101,7 @@ static struct usb_endpoint_descriptor eem_hs_out_desc __initdata = { | |||
98 | .wMaxPacketSize = cpu_to_le16(512), | 101 | .wMaxPacketSize = cpu_to_le16(512), |
99 | }; | 102 | }; |
100 | 103 | ||
101 | static struct usb_descriptor_header *eem_hs_function[] __initdata = { | 104 | static struct usb_descriptor_header *eem_hs_function[] = { |
102 | /* CDC EEM control descriptors */ | 105 | /* CDC EEM control descriptors */ |
103 | (struct usb_descriptor_header *) &eem_intf, | 106 | (struct usb_descriptor_header *) &eem_intf, |
104 | (struct usb_descriptor_header *) &eem_hs_in_desc, | 107 | (struct usb_descriptor_header *) &eem_hs_in_desc, |
@@ -108,7 +111,7 @@ static struct usb_descriptor_header *eem_hs_function[] __initdata = { | |||
108 | 111 | ||
109 | /* super speed support: */ | 112 | /* super speed support: */ |
110 | 113 | ||
111 | static struct usb_endpoint_descriptor eem_ss_in_desc __initdata = { | 114 | static struct usb_endpoint_descriptor eem_ss_in_desc = { |
112 | .bLength = USB_DT_ENDPOINT_SIZE, | 115 | .bLength = USB_DT_ENDPOINT_SIZE, |
113 | .bDescriptorType = USB_DT_ENDPOINT, | 116 | .bDescriptorType = USB_DT_ENDPOINT, |
114 | 117 | ||
@@ -117,7 +120,7 @@ static struct usb_endpoint_descriptor eem_ss_in_desc __initdata = { | |||
117 | .wMaxPacketSize = cpu_to_le16(1024), | 120 | .wMaxPacketSize = cpu_to_le16(1024), |
118 | }; | 121 | }; |
119 | 122 | ||
120 | static struct usb_endpoint_descriptor eem_ss_out_desc __initdata = { | 123 | static struct usb_endpoint_descriptor eem_ss_out_desc = { |
121 | .bLength = USB_DT_ENDPOINT_SIZE, | 124 | .bLength = USB_DT_ENDPOINT_SIZE, |
122 | .bDescriptorType = USB_DT_ENDPOINT, | 125 | .bDescriptorType = USB_DT_ENDPOINT, |
123 | 126 | ||
@@ -126,7 +129,7 @@ static struct usb_endpoint_descriptor eem_ss_out_desc __initdata = { | |||
126 | .wMaxPacketSize = cpu_to_le16(1024), | 129 | .wMaxPacketSize = cpu_to_le16(1024), |
127 | }; | 130 | }; |
128 | 131 | ||
129 | static struct usb_ss_ep_comp_descriptor eem_ss_bulk_comp_desc __initdata = { | 132 | static struct usb_ss_ep_comp_descriptor eem_ss_bulk_comp_desc = { |
130 | .bLength = sizeof eem_ss_bulk_comp_desc, | 133 | .bLength = sizeof eem_ss_bulk_comp_desc, |
131 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, | 134 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, |
132 | 135 | ||
@@ -135,7 +138,7 @@ static struct usb_ss_ep_comp_descriptor eem_ss_bulk_comp_desc __initdata = { | |||
135 | /* .bmAttributes = 0, */ | 138 | /* .bmAttributes = 0, */ |
136 | }; | 139 | }; |
137 | 140 | ||
138 | static struct usb_descriptor_header *eem_ss_function[] __initdata = { | 141 | static struct usb_descriptor_header *eem_ss_function[] = { |
139 | /* CDC EEM control descriptors */ | 142 | /* CDC EEM control descriptors */ |
140 | (struct usb_descriptor_header *) &eem_intf, | 143 | (struct usb_descriptor_header *) &eem_intf, |
141 | (struct usb_descriptor_header *) &eem_ss_in_desc, | 144 | (struct usb_descriptor_header *) &eem_ss_in_desc, |
@@ -242,14 +245,40 @@ static void eem_disable(struct usb_function *f) | |||
242 | 245 | ||
243 | /* EEM function driver setup/binding */ | 246 | /* EEM function driver setup/binding */ |
244 | 247 | ||
245 | static int __init | 248 | static int eem_bind(struct usb_configuration *c, struct usb_function *f) |
246 | eem_bind(struct usb_configuration *c, struct usb_function *f) | ||
247 | { | 249 | { |
248 | struct usb_composite_dev *cdev = c->cdev; | 250 | struct usb_composite_dev *cdev = c->cdev; |
249 | struct f_eem *eem = func_to_eem(f); | 251 | struct f_eem *eem = func_to_eem(f); |
252 | struct usb_string *us; | ||
250 | int status; | 253 | int status; |
251 | struct usb_ep *ep; | 254 | struct usb_ep *ep; |
252 | 255 | ||
256 | struct f_eem_opts *eem_opts; | ||
257 | |||
258 | eem_opts = container_of(f->fi, struct f_eem_opts, func_inst); | ||
259 | /* | ||
260 | * in drivers/usb/gadget/configfs.c:configfs_composite_bind() | ||
261 | * configurations are bound in sequence with list_for_each_entry, | ||
262 | * in each configuration its functions are bound in sequence | ||
263 | * with list_for_each_entry, so we assume no race condition | ||
264 | * with regard to eem_opts->bound access | ||
265 | */ | ||
266 | if (!eem_opts->bound) { | ||
267 | mutex_lock(&eem_opts->lock); | ||
268 | gether_set_gadget(eem_opts->net, cdev->gadget); | ||
269 | status = gether_register_netdev(eem_opts->net); | ||
270 | mutex_unlock(&eem_opts->lock); | ||
271 | if (status) | ||
272 | return status; | ||
273 | eem_opts->bound = true; | ||
274 | } | ||
275 | |||
276 | us = usb_gstrings_attach(cdev, eem_strings, | ||
277 | ARRAY_SIZE(eem_string_defs)); | ||
278 | if (IS_ERR(us)) | ||
279 | return PTR_ERR(us); | ||
280 | eem_intf.iInterface = us[0].id; | ||
281 | |||
253 | /* allocate instance-specific interface IDs */ | 282 | /* allocate instance-specific interface IDs */ |
254 | status = usb_interface_id(c, f); | 283 | status = usb_interface_id(c, f); |
255 | if (status < 0) | 284 | if (status < 0) |
@@ -307,17 +336,6 @@ fail: | |||
307 | return status; | 336 | return status; |
308 | } | 337 | } |
309 | 338 | ||
310 | static void | ||
311 | eem_unbind(struct usb_configuration *c, struct usb_function *f) | ||
312 | { | ||
313 | struct f_eem *eem = func_to_eem(f); | ||
314 | |||
315 | DBG(c->cdev, "eem unbind\n"); | ||
316 | |||
317 | usb_free_all_descriptors(f); | ||
318 | kfree(eem); | ||
319 | } | ||
320 | |||
321 | static void eem_cmd_complete(struct usb_ep *ep, struct usb_request *req) | 339 | static void eem_cmd_complete(struct usb_ep *ep, struct usb_request *req) |
322 | { | 340 | { |
323 | struct sk_buff *skb = (struct sk_buff *)req->context; | 341 | struct sk_buff *skb = (struct sk_buff *)req->context; |
@@ -518,55 +536,124 @@ error: | |||
518 | return status; | 536 | return status; |
519 | } | 537 | } |
520 | 538 | ||
521 | /** | 539 | static inline struct f_eem_opts *to_f_eem_opts(struct config_item *item) |
522 | * eem_bind_config - add CDC Ethernet (EEM) network link to a configuration | ||
523 | * @c: the configuration to support the network link | ||
524 | * Context: single threaded during gadget setup | ||
525 | * | ||
526 | * Returns zero on success, else negative errno. | ||
527 | * | ||
528 | * Caller must have called @gether_setup(). Caller is also responsible | ||
529 | * for calling @gether_cleanup() before module unload. | ||
530 | */ | ||
531 | int __init eem_bind_config(struct usb_configuration *c, struct eth_dev *dev) | ||
532 | { | 540 | { |
533 | struct f_eem *eem; | 541 | return container_of(to_config_group(item), struct f_eem_opts, |
534 | int status; | 542 | func_inst.group); |
543 | } | ||
535 | 544 | ||
536 | /* maybe allocate device-global string IDs */ | 545 | /* f_eem_item_ops */ |
537 | if (eem_string_defs[0].id == 0) { | 546 | USB_ETHERNET_CONFIGFS_ITEM(eem); |
538 | 547 | ||
539 | /* control interface label */ | 548 | /* f_eem_opts_dev_addr */ |
540 | status = usb_string_id(c->cdev); | 549 | USB_ETHERNET_CONFIGFS_ITEM_ATTR_DEV_ADDR(eem); |
541 | if (status < 0) | 550 | |
542 | return status; | 551 | /* f_eem_opts_host_addr */ |
543 | eem_string_defs[0].id = status; | 552 | USB_ETHERNET_CONFIGFS_ITEM_ATTR_HOST_ADDR(eem); |
544 | eem_intf.iInterface = status; | 553 | |
545 | } | 554 | /* f_eem_opts_qmult */ |
555 | USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(eem); | ||
556 | |||
557 | /* f_eem_opts_ifname */ | ||
558 | USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(eem); | ||
559 | |||
560 | static struct configfs_attribute *eem_attrs[] = { | ||
561 | &f_eem_opts_dev_addr.attr, | ||
562 | &f_eem_opts_host_addr.attr, | ||
563 | &f_eem_opts_qmult.attr, | ||
564 | &f_eem_opts_ifname.attr, | ||
565 | NULL, | ||
566 | }; | ||
567 | |||
568 | static struct config_item_type eem_func_type = { | ||
569 | .ct_item_ops = &eem_item_ops, | ||
570 | .ct_attrs = eem_attrs, | ||
571 | .ct_owner = THIS_MODULE, | ||
572 | }; | ||
573 | |||
574 | static void eem_free_inst(struct usb_function_instance *f) | ||
575 | { | ||
576 | struct f_eem_opts *opts; | ||
577 | |||
578 | opts = container_of(f, struct f_eem_opts, func_inst); | ||
579 | if (opts->bound) | ||
580 | gether_cleanup(netdev_priv(opts->net)); | ||
581 | else | ||
582 | free_netdev(opts->net); | ||
583 | kfree(opts); | ||
584 | } | ||
585 | |||
586 | static struct usb_function_instance *eem_alloc_inst(void) | ||
587 | { | ||
588 | struct f_eem_opts *opts; | ||
589 | |||
590 | opts = kzalloc(sizeof(*opts), GFP_KERNEL); | ||
591 | if (!opts) | ||
592 | return ERR_PTR(-ENOMEM); | ||
593 | mutex_init(&opts->lock); | ||
594 | opts->func_inst.free_func_inst = eem_free_inst; | ||
595 | opts->net = gether_setup_default(); | ||
596 | if (IS_ERR(opts->net)) | ||
597 | return ERR_CAST(opts->net); | ||
598 | |||
599 | config_group_init_type_name(&opts->func_inst.group, "", &eem_func_type); | ||
600 | |||
601 | return &opts->func_inst; | ||
602 | } | ||
603 | |||
604 | static void eem_free(struct usb_function *f) | ||
605 | { | ||
606 | struct f_eem *eem; | ||
607 | struct f_eem_opts *opts; | ||
608 | |||
609 | eem = func_to_eem(f); | ||
610 | opts = container_of(f->fi, struct f_eem_opts, func_inst); | ||
611 | kfree(eem); | ||
612 | mutex_lock(&opts->lock); | ||
613 | opts->refcnt--; | ||
614 | mutex_unlock(&opts->lock); | ||
615 | } | ||
616 | |||
617 | static void eem_unbind(struct usb_configuration *c, struct usb_function *f) | ||
618 | { | ||
619 | DBG(c->cdev, "eem unbind\n"); | ||
620 | |||
621 | usb_free_all_descriptors(f); | ||
622 | } | ||
623 | |||
624 | struct usb_function *eem_alloc(struct usb_function_instance *fi) | ||
625 | { | ||
626 | struct f_eem *eem; | ||
627 | struct f_eem_opts *opts; | ||
546 | 628 | ||
547 | /* allocate and initialize one new instance */ | 629 | /* allocate and initialize one new instance */ |
548 | eem = kzalloc(sizeof *eem, GFP_KERNEL); | 630 | eem = kzalloc(sizeof(*eem), GFP_KERNEL); |
549 | if (!eem) | 631 | if (!eem) |
550 | return -ENOMEM; | 632 | return ERR_PTR(-ENOMEM); |
551 | 633 | ||
552 | eem->port.ioport = dev; | 634 | opts = container_of(fi, struct f_eem_opts, func_inst); |
635 | mutex_lock(&opts->lock); | ||
636 | opts->refcnt++; | ||
637 | |||
638 | eem->port.ioport = netdev_priv(opts->net); | ||
639 | mutex_unlock(&opts->lock); | ||
553 | eem->port.cdc_filter = DEFAULT_FILTER; | 640 | eem->port.cdc_filter = DEFAULT_FILTER; |
554 | 641 | ||
555 | eem->port.func.name = "cdc_eem"; | 642 | eem->port.func.name = "cdc_eem"; |
556 | eem->port.func.strings = eem_strings; | ||
557 | /* descriptors are per-instance copies */ | 643 | /* descriptors are per-instance copies */ |
558 | eem->port.func.bind = eem_bind; | 644 | eem->port.func.bind = eem_bind; |
559 | eem->port.func.unbind = eem_unbind; | 645 | eem->port.func.unbind = eem_unbind; |
560 | eem->port.func.set_alt = eem_set_alt; | 646 | eem->port.func.set_alt = eem_set_alt; |
561 | eem->port.func.setup = eem_setup; | 647 | eem->port.func.setup = eem_setup; |
562 | eem->port.func.disable = eem_disable; | 648 | eem->port.func.disable = eem_disable; |
649 | eem->port.func.free_func = eem_free; | ||
563 | eem->port.wrap = eem_wrap; | 650 | eem->port.wrap = eem_wrap; |
564 | eem->port.unwrap = eem_unwrap; | 651 | eem->port.unwrap = eem_unwrap; |
565 | eem->port.header_len = EEM_HLEN; | 652 | eem->port.header_len = EEM_HLEN; |
566 | 653 | ||
567 | status = usb_add_function(c, &eem->port.func); | 654 | return &eem->port.func; |
568 | if (status) | ||
569 | kfree(eem); | ||
570 | return status; | ||
571 | } | 655 | } |
572 | 656 | ||
657 | DECLARE_USB_FUNCTION_INIT(eem, eem_alloc_inst, eem_alloc); | ||
658 | MODULE_LICENSE("GPL"); | ||
659 | MODULE_AUTHOR("David Brownell"); | ||
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 97666e8b1b95..56f1fd1cba25 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c | |||
@@ -413,6 +413,7 @@ static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep) | |||
413 | /* Caller must hold fsg->lock */ | 413 | /* Caller must hold fsg->lock */ |
414 | static void wakeup_thread(struct fsg_common *common) | 414 | static void wakeup_thread(struct fsg_common *common) |
415 | { | 415 | { |
416 | smp_wmb(); /* ensure the write of bh->state is complete */ | ||
416 | /* Tell the main thread that something has happened */ | 417 | /* Tell the main thread that something has happened */ |
417 | common->thread_wakeup_needed = 1; | 418 | common->thread_wakeup_needed = 1; |
418 | if (common->thread_task) | 419 | if (common->thread_task) |
@@ -632,6 +633,7 @@ static int sleep_thread(struct fsg_common *common) | |||
632 | } | 633 | } |
633 | __set_current_state(TASK_RUNNING); | 634 | __set_current_state(TASK_RUNNING); |
634 | common->thread_wakeup_needed = 0; | 635 | common->thread_wakeup_needed = 0; |
636 | smp_rmb(); /* ensure the latest bh->state is visible */ | ||
635 | return rc; | 637 | return rc; |
636 | } | 638 | } |
637 | 639 | ||
@@ -2745,8 +2747,8 @@ buffhds_first_it: | |||
2745 | "%-8s%-16s%04x", cfg->vendor_name ?: "Linux", | 2747 | "%-8s%-16s%04x", cfg->vendor_name ?: "Linux", |
2746 | /* Assume product name dependent on the first LUN */ | 2748 | /* Assume product name dependent on the first LUN */ |
2747 | cfg->product_name ?: (common->luns->cdrom | 2749 | cfg->product_name ?: (common->luns->cdrom |
2748 | ? "File-Stor Gadget" | 2750 | ? "File-CD Gadget" |
2749 | : "File-CD Gadget"), | 2751 | : "File-Stor Gadget"), |
2750 | i); | 2752 | i); |
2751 | 2753 | ||
2752 | /* | 2754 | /* |
diff --git a/drivers/usb/gadget/f_ncm.c b/drivers/usb/gadget/f_ncm.c index ee19bc8d0040..952177f7eb9b 100644 --- a/drivers/usb/gadget/f_ncm.c +++ b/drivers/usb/gadget/f_ncm.c | |||
@@ -16,6 +16,7 @@ | |||
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/module.h> | ||
19 | #include <linux/device.h> | 20 | #include <linux/device.h> |
20 | #include <linux/etherdevice.h> | 21 | #include <linux/etherdevice.h> |
21 | #include <linux/crc32.h> | 22 | #include <linux/crc32.h> |
@@ -23,6 +24,8 @@ | |||
23 | #include <linux/usb/cdc.h> | 24 | #include <linux/usb/cdc.h> |
24 | 25 | ||
25 | #include "u_ether.h" | 26 | #include "u_ether.h" |
27 | #include "u_ether_configfs.h" | ||
28 | #include "u_ncm.h" | ||
26 | 29 | ||
27 | /* | 30 | /* |
28 | * This function is a "CDC Network Control Model" (CDC NCM) Ethernet link. | 31 | * This function is a "CDC Network Control Model" (CDC NCM) Ethernet link. |
@@ -125,7 +128,7 @@ static struct usb_cdc_ncm_ntb_parameters ntb_parameters = { | |||
125 | #define NCM_STATUS_INTERVAL_MS 32 | 128 | #define NCM_STATUS_INTERVAL_MS 32 |
126 | #define NCM_STATUS_BYTECOUNT 16 /* 8 byte header + data */ | 129 | #define NCM_STATUS_BYTECOUNT 16 /* 8 byte header + data */ |
127 | 130 | ||
128 | static struct usb_interface_assoc_descriptor ncm_iad_desc __initdata = { | 131 | static struct usb_interface_assoc_descriptor ncm_iad_desc = { |
129 | .bLength = sizeof ncm_iad_desc, | 132 | .bLength = sizeof ncm_iad_desc, |
130 | .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, | 133 | .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, |
131 | 134 | ||
@@ -139,7 +142,7 @@ static struct usb_interface_assoc_descriptor ncm_iad_desc __initdata = { | |||
139 | 142 | ||
140 | /* interface descriptor: */ | 143 | /* interface descriptor: */ |
141 | 144 | ||
142 | static struct usb_interface_descriptor ncm_control_intf __initdata = { | 145 | static struct usb_interface_descriptor ncm_control_intf = { |
143 | .bLength = sizeof ncm_control_intf, | 146 | .bLength = sizeof ncm_control_intf, |
144 | .bDescriptorType = USB_DT_INTERFACE, | 147 | .bDescriptorType = USB_DT_INTERFACE, |
145 | 148 | ||
@@ -151,7 +154,7 @@ static struct usb_interface_descriptor ncm_control_intf __initdata = { | |||
151 | /* .iInterface = DYNAMIC */ | 154 | /* .iInterface = DYNAMIC */ |
152 | }; | 155 | }; |
153 | 156 | ||
154 | static struct usb_cdc_header_desc ncm_header_desc __initdata = { | 157 | static struct usb_cdc_header_desc ncm_header_desc = { |
155 | .bLength = sizeof ncm_header_desc, | 158 | .bLength = sizeof ncm_header_desc, |
156 | .bDescriptorType = USB_DT_CS_INTERFACE, | 159 | .bDescriptorType = USB_DT_CS_INTERFACE, |
157 | .bDescriptorSubType = USB_CDC_HEADER_TYPE, | 160 | .bDescriptorSubType = USB_CDC_HEADER_TYPE, |
@@ -159,7 +162,7 @@ static struct usb_cdc_header_desc ncm_header_desc __initdata = { | |||
159 | .bcdCDC = cpu_to_le16(0x0110), | 162 | .bcdCDC = cpu_to_le16(0x0110), |
160 | }; | 163 | }; |
161 | 164 | ||
162 | static struct usb_cdc_union_desc ncm_union_desc __initdata = { | 165 | static struct usb_cdc_union_desc ncm_union_desc = { |
163 | .bLength = sizeof(ncm_union_desc), | 166 | .bLength = sizeof(ncm_union_desc), |
164 | .bDescriptorType = USB_DT_CS_INTERFACE, | 167 | .bDescriptorType = USB_DT_CS_INTERFACE, |
165 | .bDescriptorSubType = USB_CDC_UNION_TYPE, | 168 | .bDescriptorSubType = USB_CDC_UNION_TYPE, |
@@ -167,7 +170,7 @@ static struct usb_cdc_union_desc ncm_union_desc __initdata = { | |||
167 | /* .bSlaveInterface0 = DYNAMIC */ | 170 | /* .bSlaveInterface0 = DYNAMIC */ |
168 | }; | 171 | }; |
169 | 172 | ||
170 | static struct usb_cdc_ether_desc ecm_desc __initdata = { | 173 | static struct usb_cdc_ether_desc ecm_desc = { |
171 | .bLength = sizeof ecm_desc, | 174 | .bLength = sizeof ecm_desc, |
172 | .bDescriptorType = USB_DT_CS_INTERFACE, | 175 | .bDescriptorType = USB_DT_CS_INTERFACE, |
173 | .bDescriptorSubType = USB_CDC_ETHERNET_TYPE, | 176 | .bDescriptorSubType = USB_CDC_ETHERNET_TYPE, |
@@ -182,7 +185,7 @@ static struct usb_cdc_ether_desc ecm_desc __initdata = { | |||
182 | 185 | ||
183 | #define NCAPS (USB_CDC_NCM_NCAP_ETH_FILTER | USB_CDC_NCM_NCAP_CRC_MODE) | 186 | #define NCAPS (USB_CDC_NCM_NCAP_ETH_FILTER | USB_CDC_NCM_NCAP_CRC_MODE) |
184 | 187 | ||
185 | static struct usb_cdc_ncm_desc ncm_desc __initdata = { | 188 | static struct usb_cdc_ncm_desc ncm_desc = { |
186 | .bLength = sizeof ncm_desc, | 189 | .bLength = sizeof ncm_desc, |
187 | .bDescriptorType = USB_DT_CS_INTERFACE, | 190 | .bDescriptorType = USB_DT_CS_INTERFACE, |
188 | .bDescriptorSubType = USB_CDC_NCM_TYPE, | 191 | .bDescriptorSubType = USB_CDC_NCM_TYPE, |
@@ -194,7 +197,7 @@ static struct usb_cdc_ncm_desc ncm_desc __initdata = { | |||
194 | 197 | ||
195 | /* the default data interface has no endpoints ... */ | 198 | /* the default data interface has no endpoints ... */ |
196 | 199 | ||
197 | static struct usb_interface_descriptor ncm_data_nop_intf __initdata = { | 200 | static struct usb_interface_descriptor ncm_data_nop_intf = { |
198 | .bLength = sizeof ncm_data_nop_intf, | 201 | .bLength = sizeof ncm_data_nop_intf, |
199 | .bDescriptorType = USB_DT_INTERFACE, | 202 | .bDescriptorType = USB_DT_INTERFACE, |
200 | 203 | ||
@@ -209,7 +212,7 @@ static struct usb_interface_descriptor ncm_data_nop_intf __initdata = { | |||
209 | 212 | ||
210 | /* ... but the "real" data interface has two bulk endpoints */ | 213 | /* ... but the "real" data interface has two bulk endpoints */ |
211 | 214 | ||
212 | static struct usb_interface_descriptor ncm_data_intf __initdata = { | 215 | static struct usb_interface_descriptor ncm_data_intf = { |
213 | .bLength = sizeof ncm_data_intf, | 216 | .bLength = sizeof ncm_data_intf, |
214 | .bDescriptorType = USB_DT_INTERFACE, | 217 | .bDescriptorType = USB_DT_INTERFACE, |
215 | 218 | ||
@@ -224,7 +227,7 @@ static struct usb_interface_descriptor ncm_data_intf __initdata = { | |||
224 | 227 | ||
225 | /* full speed support: */ | 228 | /* full speed support: */ |
226 | 229 | ||
227 | static struct usb_endpoint_descriptor fs_ncm_notify_desc __initdata = { | 230 | static struct usb_endpoint_descriptor fs_ncm_notify_desc = { |
228 | .bLength = USB_DT_ENDPOINT_SIZE, | 231 | .bLength = USB_DT_ENDPOINT_SIZE, |
229 | .bDescriptorType = USB_DT_ENDPOINT, | 232 | .bDescriptorType = USB_DT_ENDPOINT, |
230 | 233 | ||
@@ -234,7 +237,7 @@ static struct usb_endpoint_descriptor fs_ncm_notify_desc __initdata = { | |||
234 | .bInterval = NCM_STATUS_INTERVAL_MS, | 237 | .bInterval = NCM_STATUS_INTERVAL_MS, |
235 | }; | 238 | }; |
236 | 239 | ||
237 | static struct usb_endpoint_descriptor fs_ncm_in_desc __initdata = { | 240 | static struct usb_endpoint_descriptor fs_ncm_in_desc = { |
238 | .bLength = USB_DT_ENDPOINT_SIZE, | 241 | .bLength = USB_DT_ENDPOINT_SIZE, |
239 | .bDescriptorType = USB_DT_ENDPOINT, | 242 | .bDescriptorType = USB_DT_ENDPOINT, |
240 | 243 | ||
@@ -242,7 +245,7 @@ static struct usb_endpoint_descriptor fs_ncm_in_desc __initdata = { | |||
242 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 245 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
243 | }; | 246 | }; |
244 | 247 | ||
245 | static struct usb_endpoint_descriptor fs_ncm_out_desc __initdata = { | 248 | static struct usb_endpoint_descriptor fs_ncm_out_desc = { |
246 | .bLength = USB_DT_ENDPOINT_SIZE, | 249 | .bLength = USB_DT_ENDPOINT_SIZE, |
247 | .bDescriptorType = USB_DT_ENDPOINT, | 250 | .bDescriptorType = USB_DT_ENDPOINT, |
248 | 251 | ||
@@ -250,7 +253,7 @@ static struct usb_endpoint_descriptor fs_ncm_out_desc __initdata = { | |||
250 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 253 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
251 | }; | 254 | }; |
252 | 255 | ||
253 | static struct usb_descriptor_header *ncm_fs_function[] __initdata = { | 256 | static struct usb_descriptor_header *ncm_fs_function[] = { |
254 | (struct usb_descriptor_header *) &ncm_iad_desc, | 257 | (struct usb_descriptor_header *) &ncm_iad_desc, |
255 | /* CDC NCM control descriptors */ | 258 | /* CDC NCM control descriptors */ |
256 | (struct usb_descriptor_header *) &ncm_control_intf, | 259 | (struct usb_descriptor_header *) &ncm_control_intf, |
@@ -269,7 +272,7 @@ static struct usb_descriptor_header *ncm_fs_function[] __initdata = { | |||
269 | 272 | ||
270 | /* high speed support: */ | 273 | /* high speed support: */ |
271 | 274 | ||
272 | static struct usb_endpoint_descriptor hs_ncm_notify_desc __initdata = { | 275 | static struct usb_endpoint_descriptor hs_ncm_notify_desc = { |
273 | .bLength = USB_DT_ENDPOINT_SIZE, | 276 | .bLength = USB_DT_ENDPOINT_SIZE, |
274 | .bDescriptorType = USB_DT_ENDPOINT, | 277 | .bDescriptorType = USB_DT_ENDPOINT, |
275 | 278 | ||
@@ -278,7 +281,7 @@ static struct usb_endpoint_descriptor hs_ncm_notify_desc __initdata = { | |||
278 | .wMaxPacketSize = cpu_to_le16(NCM_STATUS_BYTECOUNT), | 281 | .wMaxPacketSize = cpu_to_le16(NCM_STATUS_BYTECOUNT), |
279 | .bInterval = USB_MS_TO_HS_INTERVAL(NCM_STATUS_INTERVAL_MS), | 282 | .bInterval = USB_MS_TO_HS_INTERVAL(NCM_STATUS_INTERVAL_MS), |
280 | }; | 283 | }; |
281 | static struct usb_endpoint_descriptor hs_ncm_in_desc __initdata = { | 284 | static struct usb_endpoint_descriptor hs_ncm_in_desc = { |
282 | .bLength = USB_DT_ENDPOINT_SIZE, | 285 | .bLength = USB_DT_ENDPOINT_SIZE, |
283 | .bDescriptorType = USB_DT_ENDPOINT, | 286 | .bDescriptorType = USB_DT_ENDPOINT, |
284 | 287 | ||
@@ -287,7 +290,7 @@ static struct usb_endpoint_descriptor hs_ncm_in_desc __initdata = { | |||
287 | .wMaxPacketSize = cpu_to_le16(512), | 290 | .wMaxPacketSize = cpu_to_le16(512), |
288 | }; | 291 | }; |
289 | 292 | ||
290 | static struct usb_endpoint_descriptor hs_ncm_out_desc __initdata = { | 293 | static struct usb_endpoint_descriptor hs_ncm_out_desc = { |
291 | .bLength = USB_DT_ENDPOINT_SIZE, | 294 | .bLength = USB_DT_ENDPOINT_SIZE, |
292 | .bDescriptorType = USB_DT_ENDPOINT, | 295 | .bDescriptorType = USB_DT_ENDPOINT, |
293 | 296 | ||
@@ -296,7 +299,7 @@ static struct usb_endpoint_descriptor hs_ncm_out_desc __initdata = { | |||
296 | .wMaxPacketSize = cpu_to_le16(512), | 299 | .wMaxPacketSize = cpu_to_le16(512), |
297 | }; | 300 | }; |
298 | 301 | ||
299 | static struct usb_descriptor_header *ncm_hs_function[] __initdata = { | 302 | static struct usb_descriptor_header *ncm_hs_function[] = { |
300 | (struct usb_descriptor_header *) &ncm_iad_desc, | 303 | (struct usb_descriptor_header *) &ncm_iad_desc, |
301 | /* CDC NCM control descriptors */ | 304 | /* CDC NCM control descriptors */ |
302 | (struct usb_descriptor_header *) &ncm_control_intf, | 305 | (struct usb_descriptor_header *) &ncm_control_intf, |
@@ -1152,13 +1155,44 @@ static void ncm_close(struct gether *geth) | |||
1152 | 1155 | ||
1153 | /* ethernet function driver setup/binding */ | 1156 | /* ethernet function driver setup/binding */ |
1154 | 1157 | ||
1155 | static int __init | 1158 | static int ncm_bind(struct usb_configuration *c, struct usb_function *f) |
1156 | ncm_bind(struct usb_configuration *c, struct usb_function *f) | ||
1157 | { | 1159 | { |
1158 | struct usb_composite_dev *cdev = c->cdev; | 1160 | struct usb_composite_dev *cdev = c->cdev; |
1159 | struct f_ncm *ncm = func_to_ncm(f); | 1161 | struct f_ncm *ncm = func_to_ncm(f); |
1162 | struct usb_string *us; | ||
1160 | int status; | 1163 | int status; |
1161 | struct usb_ep *ep; | 1164 | struct usb_ep *ep; |
1165 | struct f_ncm_opts *ncm_opts; | ||
1166 | |||
1167 | if (!can_support_ecm(cdev->gadget)) | ||
1168 | return -EINVAL; | ||
1169 | |||
1170 | ncm_opts = container_of(f->fi, struct f_ncm_opts, func_inst); | ||
1171 | /* | ||
1172 | * in drivers/usb/gadget/configfs.c:configfs_composite_bind() | ||
1173 | * configurations are bound in sequence with list_for_each_entry, | ||
1174 | * in each configuration its functions are bound in sequence | ||
1175 | * with list_for_each_entry, so we assume no race condition | ||
1176 | * with regard to ncm_opts->bound access | ||
1177 | */ | ||
1178 | if (!ncm_opts->bound) { | ||
1179 | mutex_lock(&ncm_opts->lock); | ||
1180 | gether_set_gadget(ncm_opts->net, cdev->gadget); | ||
1181 | status = gether_register_netdev(ncm_opts->net); | ||
1182 | mutex_unlock(&ncm_opts->lock); | ||
1183 | if (status) | ||
1184 | return status; | ||
1185 | ncm_opts->bound = true; | ||
1186 | } | ||
1187 | us = usb_gstrings_attach(cdev, ncm_strings, | ||
1188 | ARRAY_SIZE(ncm_string_defs)); | ||
1189 | if (IS_ERR(us)) | ||
1190 | return PTR_ERR(us); | ||
1191 | ncm_control_intf.iInterface = us[STRING_CTRL_IDX].id; | ||
1192 | ncm_data_nop_intf.iInterface = us[STRING_DATA_IDX].id; | ||
1193 | ncm_data_intf.iInterface = us[STRING_DATA_IDX].id; | ||
1194 | ecm_desc.iMACAddress = us[STRING_MAC_IDX].id; | ||
1195 | ncm_iad_desc.iFunction = us[STRING_IAD_IDX].id; | ||
1162 | 1196 | ||
1163 | /* allocate instance-specific interface IDs */ | 1197 | /* allocate instance-specific interface IDs */ |
1164 | status = usb_interface_id(c, f); | 1198 | status = usb_interface_id(c, f); |
@@ -1259,74 +1293,128 @@ fail: | |||
1259 | return status; | 1293 | return status; |
1260 | } | 1294 | } |
1261 | 1295 | ||
1262 | static void | 1296 | static inline struct f_ncm_opts *to_f_ncm_opts(struct config_item *item) |
1263 | ncm_unbind(struct usb_configuration *c, struct usb_function *f) | ||
1264 | { | 1297 | { |
1265 | struct f_ncm *ncm = func_to_ncm(f); | 1298 | return container_of(to_config_group(item), struct f_ncm_opts, |
1299 | func_inst.group); | ||
1300 | } | ||
1266 | 1301 | ||
1267 | DBG(c->cdev, "ncm unbind\n"); | 1302 | /* f_ncm_item_ops */ |
1303 | USB_ETHERNET_CONFIGFS_ITEM(ncm); | ||
1268 | 1304 | ||
1269 | ncm_string_defs[0].id = 0; | 1305 | /* f_ncm_opts_dev_addr */ |
1270 | usb_free_all_descriptors(f); | 1306 | USB_ETHERNET_CONFIGFS_ITEM_ATTR_DEV_ADDR(ncm); |
1271 | 1307 | ||
1272 | kfree(ncm->notify_req->buf); | 1308 | /* f_ncm_opts_host_addr */ |
1273 | usb_ep_free_request(ncm->notify, ncm->notify_req); | 1309 | USB_ETHERNET_CONFIGFS_ITEM_ATTR_HOST_ADDR(ncm); |
1274 | 1310 | ||
1311 | /* f_ncm_opts_qmult */ | ||
1312 | USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(ncm); | ||
1313 | |||
1314 | /* f_ncm_opts_ifname */ | ||
1315 | USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(ncm); | ||
1316 | |||
1317 | static struct configfs_attribute *ncm_attrs[] = { | ||
1318 | &f_ncm_opts_dev_addr.attr, | ||
1319 | &f_ncm_opts_host_addr.attr, | ||
1320 | &f_ncm_opts_qmult.attr, | ||
1321 | &f_ncm_opts_ifname.attr, | ||
1322 | NULL, | ||
1323 | }; | ||
1324 | |||
1325 | static struct config_item_type ncm_func_type = { | ||
1326 | .ct_item_ops = &ncm_item_ops, | ||
1327 | .ct_attrs = ncm_attrs, | ||
1328 | .ct_owner = THIS_MODULE, | ||
1329 | }; | ||
1330 | |||
1331 | static void ncm_free_inst(struct usb_function_instance *f) | ||
1332 | { | ||
1333 | struct f_ncm_opts *opts; | ||
1334 | |||
1335 | opts = container_of(f, struct f_ncm_opts, func_inst); | ||
1336 | if (opts->bound) | ||
1337 | gether_cleanup(netdev_priv(opts->net)); | ||
1338 | else | ||
1339 | free_netdev(opts->net); | ||
1340 | kfree(opts); | ||
1341 | } | ||
1342 | |||
1343 | static struct usb_function_instance *ncm_alloc_inst(void) | ||
1344 | { | ||
1345 | struct f_ncm_opts *opts; | ||
1346 | |||
1347 | opts = kzalloc(sizeof(*opts), GFP_KERNEL); | ||
1348 | if (!opts) | ||
1349 | return ERR_PTR(-ENOMEM); | ||
1350 | mutex_init(&opts->lock); | ||
1351 | opts->func_inst.free_func_inst = ncm_free_inst; | ||
1352 | opts->net = gether_setup_default(); | ||
1353 | if (IS_ERR(opts->net)) | ||
1354 | return ERR_PTR(PTR_ERR(opts->net)); | ||
1355 | |||
1356 | config_group_init_type_name(&opts->func_inst.group, "", &ncm_func_type); | ||
1357 | |||
1358 | return &opts->func_inst; | ||
1359 | } | ||
1360 | |||
1361 | static void ncm_free(struct usb_function *f) | ||
1362 | { | ||
1363 | struct f_ncm *ncm; | ||
1364 | struct f_ncm_opts *opts; | ||
1365 | |||
1366 | ncm = func_to_ncm(f); | ||
1367 | opts = container_of(f->fi, struct f_ncm_opts, func_inst); | ||
1275 | kfree(ncm); | 1368 | kfree(ncm); |
1369 | mutex_lock(&opts->lock); | ||
1370 | opts->refcnt--; | ||
1371 | mutex_unlock(&opts->lock); | ||
1276 | } | 1372 | } |
1277 | 1373 | ||
1278 | /** | 1374 | static void ncm_unbind(struct usb_configuration *c, struct usb_function *f) |
1279 | * ncm_bind_config - add CDC Network link to a configuration | ||
1280 | * @c: the configuration to support the network link | ||
1281 | * @ethaddr: a buffer in which the ethernet address of the host side | ||
1282 | * side of the link was recorded | ||
1283 | * Context: single threaded during gadget setup | ||
1284 | * | ||
1285 | * Returns zero on success, else negative errno. | ||
1286 | * | ||
1287 | * Caller must have called @gether_setup(). Caller is also responsible | ||
1288 | * for calling @gether_cleanup() before module unload. | ||
1289 | */ | ||
1290 | int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], | ||
1291 | struct eth_dev *dev) | ||
1292 | { | 1375 | { |
1293 | struct f_ncm *ncm; | 1376 | struct f_ncm *ncm = func_to_ncm(f); |
1294 | int status; | ||
1295 | 1377 | ||
1296 | if (!can_support_ecm(c->cdev->gadget) || !ethaddr) | 1378 | DBG(c->cdev, "ncm unbind\n"); |
1297 | return -EINVAL; | ||
1298 | 1379 | ||
1299 | if (ncm_string_defs[0].id == 0) { | 1380 | usb_free_all_descriptors(f); |
1300 | status = usb_string_ids_tab(c->cdev, ncm_string_defs); | ||
1301 | if (status < 0) | ||
1302 | return status; | ||
1303 | ncm_control_intf.iInterface = | ||
1304 | ncm_string_defs[STRING_CTRL_IDX].id; | ||
1305 | 1381 | ||
1306 | status = ncm_string_defs[STRING_DATA_IDX].id; | 1382 | kfree(ncm->notify_req->buf); |
1307 | ncm_data_nop_intf.iInterface = status; | 1383 | usb_ep_free_request(ncm->notify, ncm->notify_req); |
1308 | ncm_data_intf.iInterface = status; | 1384 | } |
1309 | 1385 | ||
1310 | ecm_desc.iMACAddress = ncm_string_defs[STRING_MAC_IDX].id; | 1386 | struct usb_function *ncm_alloc(struct usb_function_instance *fi) |
1311 | ncm_iad_desc.iFunction = ncm_string_defs[STRING_IAD_IDX].id; | 1387 | { |
1312 | } | 1388 | struct f_ncm *ncm; |
1389 | struct f_ncm_opts *opts; | ||
1390 | int status; | ||
1313 | 1391 | ||
1314 | /* allocate and initialize one new instance */ | 1392 | /* allocate and initialize one new instance */ |
1315 | ncm = kzalloc(sizeof *ncm, GFP_KERNEL); | 1393 | ncm = kzalloc(sizeof(*ncm), GFP_KERNEL); |
1316 | if (!ncm) | 1394 | if (!ncm) |
1317 | return -ENOMEM; | 1395 | return ERR_PTR(-ENOMEM); |
1396 | |||
1397 | opts = container_of(fi, struct f_ncm_opts, func_inst); | ||
1398 | mutex_lock(&opts->lock); | ||
1399 | opts->refcnt++; | ||
1318 | 1400 | ||
1319 | /* export host's Ethernet address in CDC format */ | 1401 | /* export host's Ethernet address in CDC format */ |
1320 | snprintf(ncm->ethaddr, sizeof ncm->ethaddr, "%pm", ethaddr); | 1402 | status = gether_get_host_addr_cdc(opts->net, ncm->ethaddr, |
1403 | sizeof(ncm->ethaddr)); | ||
1404 | if (status < 12) { /* strlen("01234567890a") */ | ||
1405 | kfree(ncm); | ||
1406 | mutex_unlock(&opts->lock); | ||
1407 | return ERR_PTR(-EINVAL); | ||
1408 | } | ||
1321 | ncm_string_defs[STRING_MAC_IDX].s = ncm->ethaddr; | 1409 | ncm_string_defs[STRING_MAC_IDX].s = ncm->ethaddr; |
1322 | 1410 | ||
1323 | spin_lock_init(&ncm->lock); | 1411 | spin_lock_init(&ncm->lock); |
1324 | ncm_reset_values(ncm); | 1412 | ncm_reset_values(ncm); |
1325 | ncm->port.ioport = dev; | 1413 | ncm->port.ioport = netdev_priv(opts->net); |
1414 | mutex_unlock(&opts->lock); | ||
1326 | ncm->port.is_fixed = true; | 1415 | ncm->port.is_fixed = true; |
1327 | 1416 | ||
1328 | ncm->port.func.name = "cdc_network"; | 1417 | ncm->port.func.name = "cdc_network"; |
1329 | ncm->port.func.strings = ncm_strings; | ||
1330 | /* descriptors are per-instance copies */ | 1418 | /* descriptors are per-instance copies */ |
1331 | ncm->port.func.bind = ncm_bind; | 1419 | ncm->port.func.bind = ncm_bind; |
1332 | ncm->port.func.unbind = ncm_unbind; | 1420 | ncm->port.func.unbind = ncm_unbind; |
@@ -1334,12 +1422,14 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], | |||
1334 | ncm->port.func.get_alt = ncm_get_alt; | 1422 | ncm->port.func.get_alt = ncm_get_alt; |
1335 | ncm->port.func.setup = ncm_setup; | 1423 | ncm->port.func.setup = ncm_setup; |
1336 | ncm->port.func.disable = ncm_disable; | 1424 | ncm->port.func.disable = ncm_disable; |
1425 | ncm->port.func.free_func = ncm_free; | ||
1337 | 1426 | ||
1338 | ncm->port.wrap = ncm_wrap_ntb; | 1427 | ncm->port.wrap = ncm_wrap_ntb; |
1339 | ncm->port.unwrap = ncm_unwrap_ntb; | 1428 | ncm->port.unwrap = ncm_unwrap_ntb; |
1340 | 1429 | ||
1341 | status = usb_add_function(c, &ncm->port.func); | 1430 | return &ncm->port.func; |
1342 | if (status) | ||
1343 | kfree(ncm); | ||
1344 | return status; | ||
1345 | } | 1431 | } |
1432 | |||
1433 | DECLARE_USB_FUNCTION_INIT(ncm, ncm_alloc_inst, ncm_alloc); | ||
1434 | MODULE_LICENSE("GPL"); | ||
1435 | MODULE_AUTHOR("Yauheni Kaliuta"); | ||
diff --git a/drivers/usb/gadget/f_obex.c b/drivers/usb/gadget/f_obex.c index 8aa2be5329bc..ad39f1dacba3 100644 --- a/drivers/usb/gadget/f_obex.c +++ b/drivers/usb/gadget/f_obex.c | |||
@@ -309,23 +309,20 @@ static int obex_bind(struct usb_configuration *c, struct usb_function *f) | |||
309 | { | 309 | { |
310 | struct usb_composite_dev *cdev = c->cdev; | 310 | struct usb_composite_dev *cdev = c->cdev; |
311 | struct f_obex *obex = func_to_obex(f); | 311 | struct f_obex *obex = func_to_obex(f); |
312 | struct usb_string *us; | ||
312 | int status; | 313 | int status; |
313 | struct usb_ep *ep; | 314 | struct usb_ep *ep; |
314 | 315 | ||
315 | if (!can_support_obex(c)) | 316 | if (!can_support_obex(c)) |
316 | return -EINVAL; | 317 | return -EINVAL; |
317 | 318 | ||
318 | if (obex_string_defs[OBEX_CTRL_IDX].id == 0) { | 319 | us = usb_gstrings_attach(cdev, obex_strings, |
319 | status = usb_string_ids_tab(c->cdev, obex_string_defs); | 320 | ARRAY_SIZE(obex_string_defs)); |
320 | if (status < 0) | 321 | if (IS_ERR(us)) |
321 | return status; | 322 | return PTR_ERR(us); |
322 | obex_control_intf.iInterface = | 323 | obex_control_intf.iInterface = us[OBEX_CTRL_IDX].id; |
323 | obex_string_defs[OBEX_CTRL_IDX].id; | 324 | obex_data_nop_intf.iInterface = us[OBEX_DATA_IDX].id; |
324 | 325 | obex_data_intf.iInterface = us[OBEX_DATA_IDX].id; | |
325 | status = obex_string_defs[OBEX_DATA_IDX].id; | ||
326 | obex_data_nop_intf.iInterface = status; | ||
327 | obex_data_intf.iInterface = status; | ||
328 | } | ||
329 | 326 | ||
330 | /* allocate instance-specific interface IDs, and patch descriptors */ | 327 | /* allocate instance-specific interface IDs, and patch descriptors */ |
331 | 328 | ||
@@ -406,57 +403,6 @@ fail: | |||
406 | return status; | 403 | return status; |
407 | } | 404 | } |
408 | 405 | ||
409 | #ifdef USBF_OBEX_INCLUDED | ||
410 | |||
411 | static void | ||
412 | obex_old_unbind(struct usb_configuration *c, struct usb_function *f) | ||
413 | { | ||
414 | obex_string_defs[OBEX_CTRL_IDX].id = 0; | ||
415 | usb_free_all_descriptors(f); | ||
416 | kfree(func_to_obex(f)); | ||
417 | } | ||
418 | |||
419 | /** | ||
420 | * obex_bind_config - add a CDC OBEX function to a configuration | ||
421 | * @c: the configuration to support the CDC OBEX instance | ||
422 | * @port_num: /dev/ttyGS* port this interface will use | ||
423 | * Context: single threaded during gadget setup | ||
424 | * | ||
425 | * Returns zero on success, else negative errno. | ||
426 | */ | ||
427 | int __init obex_bind_config(struct usb_configuration *c, u8 port_num) | ||
428 | { | ||
429 | struct f_obex *obex; | ||
430 | int status; | ||
431 | |||
432 | /* allocate and initialize one new instance */ | ||
433 | obex = kzalloc(sizeof *obex, GFP_KERNEL); | ||
434 | if (!obex) | ||
435 | return -ENOMEM; | ||
436 | |||
437 | obex->port_num = port_num; | ||
438 | |||
439 | obex->port.connect = obex_connect; | ||
440 | obex->port.disconnect = obex_disconnect; | ||
441 | |||
442 | obex->port.func.name = "obex"; | ||
443 | obex->port.func.strings = obex_strings; | ||
444 | /* descriptors are per-instance copies */ | ||
445 | obex->port.func.bind = obex_bind; | ||
446 | obex->port.func.unbind = obex_old_unbind; | ||
447 | obex->port.func.set_alt = obex_set_alt; | ||
448 | obex->port.func.get_alt = obex_get_alt; | ||
449 | obex->port.func.disable = obex_disable; | ||
450 | |||
451 | status = usb_add_function(c, &obex->port.func); | ||
452 | if (status) | ||
453 | kfree(obex); | ||
454 | |||
455 | return status; | ||
456 | } | ||
457 | |||
458 | #else | ||
459 | |||
460 | static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item) | 406 | static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item) |
461 | { | 407 | { |
462 | return container_of(to_config_group(item), struct f_serial_opts, | 408 | return container_of(to_config_group(item), struct f_serial_opts, |
@@ -550,7 +496,6 @@ static void obex_free(struct usb_function *f) | |||
550 | 496 | ||
551 | static void obex_unbind(struct usb_configuration *c, struct usb_function *f) | 497 | static void obex_unbind(struct usb_configuration *c, struct usb_function *f) |
552 | { | 498 | { |
553 | obex_string_defs[OBEX_CTRL_IDX].id = 0; | ||
554 | usb_free_all_descriptors(f); | 499 | usb_free_all_descriptors(f); |
555 | } | 500 | } |
556 | 501 | ||
@@ -572,7 +517,6 @@ struct usb_function *obex_alloc(struct usb_function_instance *fi) | |||
572 | obex->port.disconnect = obex_disconnect; | 517 | obex->port.disconnect = obex_disconnect; |
573 | 518 | ||
574 | obex->port.func.name = "obex"; | 519 | obex->port.func.name = "obex"; |
575 | obex->port.func.strings = obex_strings; | ||
576 | /* descriptors are per-instance copies */ | 520 | /* descriptors are per-instance copies */ |
577 | obex->port.func.bind = obex_bind; | 521 | obex->port.func.bind = obex_bind; |
578 | obex->port.func.unbind = obex_unbind; | 522 | obex->port.func.unbind = obex_unbind; |
@@ -585,8 +529,5 @@ struct usb_function *obex_alloc(struct usb_function_instance *fi) | |||
585 | } | 529 | } |
586 | 530 | ||
587 | DECLARE_USB_FUNCTION_INIT(obex, obex_alloc_inst, obex_alloc); | 531 | DECLARE_USB_FUNCTION_INIT(obex, obex_alloc_inst, obex_alloc); |
588 | |||
589 | #endif | ||
590 | |||
591 | MODULE_AUTHOR("Felipe Balbi"); | 532 | MODULE_AUTHOR("Felipe Balbi"); |
592 | MODULE_LICENSE("GPL"); | 533 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/usb/gadget/f_phonet.c b/drivers/usb/gadget/f_phonet.c index b21ab558b6c0..7944fb0efe3b 100644 --- a/drivers/usb/gadget/f_phonet.c +++ b/drivers/usb/gadget/f_phonet.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/mm.h> | 13 | #include <linux/mm.h> |
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/module.h> | ||
16 | #include <linux/device.h> | 17 | #include <linux/device.h> |
17 | 18 | ||
18 | #include <linux/netdevice.h> | 19 | #include <linux/netdevice.h> |
@@ -25,6 +26,7 @@ | |||
25 | #include <linux/usb/composite.h> | 26 | #include <linux/usb/composite.h> |
26 | 27 | ||
27 | #include "u_phonet.h" | 28 | #include "u_phonet.h" |
29 | #include "u_ether.h" | ||
28 | 30 | ||
29 | #define PN_MEDIA_USB 0x1B | 31 | #define PN_MEDIA_USB 0x1B |
30 | #define MAXPACKET 512 | 32 | #define MAXPACKET 512 |
@@ -478,8 +480,7 @@ static void pn_disconnect(struct usb_function *f) | |||
478 | 480 | ||
479 | /*-------------------------------------------------------------------------*/ | 481 | /*-------------------------------------------------------------------------*/ |
480 | 482 | ||
481 | static __init | 483 | static int pn_bind(struct usb_configuration *c, struct usb_function *f) |
482 | int pn_bind(struct usb_configuration *c, struct usb_function *f) | ||
483 | { | 484 | { |
484 | struct usb_composite_dev *cdev = c->cdev; | 485 | struct usb_composite_dev *cdev = c->cdev; |
485 | struct usb_gadget *gadget = cdev->gadget; | 486 | struct usb_gadget *gadget = cdev->gadget; |
@@ -487,6 +488,27 @@ int pn_bind(struct usb_configuration *c, struct usb_function *f) | |||
487 | struct usb_ep *ep; | 488 | struct usb_ep *ep; |
488 | int status, i; | 489 | int status, i; |
489 | 490 | ||
491 | #ifndef USBF_PHONET_INCLUDED | ||
492 | struct f_phonet_opts *phonet_opts; | ||
493 | |||
494 | phonet_opts = container_of(f->fi, struct f_phonet_opts, func_inst); | ||
495 | |||
496 | /* | ||
497 | * in drivers/usb/gadget/configfs.c:configfs_composite_bind() | ||
498 | * configurations are bound in sequence with list_for_each_entry, | ||
499 | * in each configuration its functions are bound in sequence | ||
500 | * with list_for_each_entry, so we assume no race condition | ||
501 | * with regard to phonet_opts->bound access | ||
502 | */ | ||
503 | if (!phonet_opts->bound) { | ||
504 | gphonet_set_gadget(phonet_opts->net, gadget); | ||
505 | status = gphonet_register_netdev(phonet_opts->net); | ||
506 | if (status) | ||
507 | return status; | ||
508 | phonet_opts->bound = true; | ||
509 | } | ||
510 | #endif | ||
511 | |||
490 | /* Reserve interface IDs */ | 512 | /* Reserve interface IDs */ |
491 | status = usb_interface_id(c, f); | 513 | status = usb_interface_id(c, f); |
492 | if (status < 0) | 514 | if (status < 0) |
@@ -560,8 +582,98 @@ err: | |||
560 | return status; | 582 | return status; |
561 | } | 583 | } |
562 | 584 | ||
563 | static void | 585 | static inline struct f_phonet_opts *to_f_phonet_opts(struct config_item *item) |
564 | pn_unbind(struct usb_configuration *c, struct usb_function *f) | 586 | { |
587 | return container_of(to_config_group(item), struct f_phonet_opts, | ||
588 | func_inst.group); | ||
589 | } | ||
590 | |||
591 | CONFIGFS_ATTR_STRUCT(f_phonet_opts); | ||
592 | static ssize_t f_phonet_attr_show(struct config_item *item, | ||
593 | struct configfs_attribute *attr, | ||
594 | char *page) | ||
595 | { | ||
596 | struct f_phonet_opts *opts = to_f_phonet_opts(item); | ||
597 | struct f_phonet_opts_attribute *f_phonet_opts_attr = | ||
598 | container_of(attr, struct f_phonet_opts_attribute, attr); | ||
599 | ssize_t ret = 0; | ||
600 | |||
601 | if (f_phonet_opts_attr->show) | ||
602 | ret = f_phonet_opts_attr->show(opts, page); | ||
603 | return ret; | ||
604 | } | ||
605 | |||
606 | static void phonet_attr_release(struct config_item *item) | ||
607 | { | ||
608 | struct f_phonet_opts *opts = to_f_phonet_opts(item); | ||
609 | |||
610 | usb_put_function_instance(&opts->func_inst); | ||
611 | } | ||
612 | |||
613 | static struct configfs_item_operations phonet_item_ops = { | ||
614 | .release = phonet_attr_release, | ||
615 | .show_attribute = f_phonet_attr_show, | ||
616 | }; | ||
617 | |||
618 | static ssize_t f_phonet_ifname_show(struct f_phonet_opts *opts, char *page) | ||
619 | { | ||
620 | return gether_get_ifname(opts->net, page, PAGE_SIZE); | ||
621 | } | ||
622 | |||
623 | static struct f_phonet_opts_attribute f_phonet_ifname = | ||
624 | __CONFIGFS_ATTR_RO(ifname, f_phonet_ifname_show); | ||
625 | |||
626 | static struct configfs_attribute *phonet_attrs[] = { | ||
627 | &f_phonet_ifname.attr, | ||
628 | NULL, | ||
629 | }; | ||
630 | |||
631 | static struct config_item_type phonet_func_type = { | ||
632 | .ct_item_ops = &phonet_item_ops, | ||
633 | .ct_attrs = phonet_attrs, | ||
634 | .ct_owner = THIS_MODULE, | ||
635 | }; | ||
636 | |||
637 | static void phonet_free_inst(struct usb_function_instance *f) | ||
638 | { | ||
639 | struct f_phonet_opts *opts; | ||
640 | |||
641 | opts = container_of(f, struct f_phonet_opts, func_inst); | ||
642 | if (opts->bound) | ||
643 | gphonet_cleanup(opts->net); | ||
644 | else | ||
645 | free_netdev(opts->net); | ||
646 | kfree(opts); | ||
647 | } | ||
648 | |||
649 | static struct usb_function_instance *phonet_alloc_inst(void) | ||
650 | { | ||
651 | struct f_phonet_opts *opts; | ||
652 | |||
653 | opts = kzalloc(sizeof(*opts), GFP_KERNEL); | ||
654 | if (!opts) | ||
655 | return ERR_PTR(-ENOMEM); | ||
656 | |||
657 | opts->func_inst.free_func_inst = phonet_free_inst; | ||
658 | opts->net = gphonet_setup_default(); | ||
659 | if (IS_ERR(opts->net)) | ||
660 | return ERR_PTR(PTR_ERR(opts->net)); | ||
661 | |||
662 | config_group_init_type_name(&opts->func_inst.group, "", | ||
663 | &phonet_func_type); | ||
664 | |||
665 | return &opts->func_inst; | ||
666 | } | ||
667 | |||
668 | static void phonet_free(struct usb_function *f) | ||
669 | { | ||
670 | struct f_phonet *phonet; | ||
671 | |||
672 | phonet = func_to_pn(f); | ||
673 | kfree(phonet); | ||
674 | } | ||
675 | |||
676 | static void pn_unbind(struct usb_configuration *c, struct usb_function *f) | ||
565 | { | 677 | { |
566 | struct f_phonet *fp = func_to_pn(f); | 678 | struct f_phonet *fp = func_to_pn(f); |
567 | int i; | 679 | int i; |
@@ -574,61 +686,72 @@ pn_unbind(struct usb_configuration *c, struct usb_function *f) | |||
574 | usb_ep_free_request(fp->out_ep, fp->out_reqv[i]); | 686 | usb_ep_free_request(fp->out_ep, fp->out_reqv[i]); |
575 | 687 | ||
576 | usb_free_all_descriptors(f); | 688 | usb_free_all_descriptors(f); |
577 | kfree(fp); | ||
578 | } | 689 | } |
579 | 690 | ||
580 | /*-------------------------------------------------------------------------*/ | 691 | struct usb_function *phonet_alloc(struct usb_function_instance *fi) |
581 | |||
582 | static struct net_device *dev; | ||
583 | |||
584 | int __init phonet_bind_config(struct usb_configuration *c) | ||
585 | { | 692 | { |
586 | struct f_phonet *fp; | 693 | struct f_phonet *fp; |
587 | int err, size; | 694 | struct f_phonet_opts *opts; |
695 | int size; | ||
588 | 696 | ||
589 | size = sizeof(*fp) + (phonet_rxq_size * sizeof(struct usb_request *)); | 697 | size = sizeof(*fp) + (phonet_rxq_size * sizeof(struct usb_request *)); |
590 | fp = kzalloc(size, GFP_KERNEL); | 698 | fp = kzalloc(size, GFP_KERNEL); |
591 | if (!fp) | 699 | if (!fp) |
592 | return -ENOMEM; | 700 | return ERR_PTR(-ENOMEM); |
701 | |||
702 | opts = container_of(fi, struct f_phonet_opts, func_inst); | ||
593 | 703 | ||
594 | fp->dev = dev; | 704 | fp->dev = opts->net; |
595 | fp->function.name = "phonet"; | 705 | fp->function.name = "phonet"; |
596 | fp->function.bind = pn_bind; | 706 | fp->function.bind = pn_bind; |
597 | fp->function.unbind = pn_unbind; | 707 | fp->function.unbind = pn_unbind; |
598 | fp->function.set_alt = pn_set_alt; | 708 | fp->function.set_alt = pn_set_alt; |
599 | fp->function.get_alt = pn_get_alt; | 709 | fp->function.get_alt = pn_get_alt; |
600 | fp->function.disable = pn_disconnect; | 710 | fp->function.disable = pn_disconnect; |
711 | fp->function.free_func = phonet_free; | ||
601 | spin_lock_init(&fp->rx.lock); | 712 | spin_lock_init(&fp->rx.lock); |
602 | 713 | ||
603 | err = usb_add_function(c, &fp->function); | 714 | return &fp->function; |
604 | if (err) | ||
605 | kfree(fp); | ||
606 | return err; | ||
607 | } | 715 | } |
608 | 716 | ||
609 | int __init gphonet_setup(struct usb_gadget *gadget) | 717 | struct net_device *gphonet_setup_default(void) |
610 | { | 718 | { |
719 | struct net_device *dev; | ||
611 | struct phonet_port *port; | 720 | struct phonet_port *port; |
612 | int err; | ||
613 | 721 | ||
614 | /* Create net device */ | 722 | /* Create net device */ |
615 | BUG_ON(dev); | ||
616 | dev = alloc_netdev(sizeof(*port), "upnlink%d", pn_net_setup); | 723 | dev = alloc_netdev(sizeof(*port), "upnlink%d", pn_net_setup); |
617 | if (!dev) | 724 | if (!dev) |
618 | return -ENOMEM; | 725 | return ERR_PTR(-ENOMEM); |
619 | 726 | ||
620 | port = netdev_priv(dev); | 727 | port = netdev_priv(dev); |
621 | spin_lock_init(&port->lock); | 728 | spin_lock_init(&port->lock); |
622 | netif_carrier_off(dev); | 729 | netif_carrier_off(dev); |
623 | SET_NETDEV_DEV(dev, &gadget->dev); | ||
624 | 730 | ||
625 | err = register_netdev(dev); | 731 | return dev; |
626 | if (err) | 732 | } |
627 | free_netdev(dev); | 733 | |
628 | return err; | 734 | void gphonet_set_gadget(struct net_device *net, struct usb_gadget *g) |
735 | { | ||
736 | SET_NETDEV_DEV(net, &g->dev); | ||
737 | } | ||
738 | |||
739 | int gphonet_register_netdev(struct net_device *net) | ||
740 | { | ||
741 | int status; | ||
742 | |||
743 | status = register_netdev(net); | ||
744 | if (status) | ||
745 | free_netdev(net); | ||
746 | |||
747 | return status; | ||
629 | } | 748 | } |
630 | 749 | ||
631 | void gphonet_cleanup(void) | 750 | void gphonet_cleanup(struct net_device *dev) |
632 | { | 751 | { |
633 | unregister_netdev(dev); | 752 | unregister_netdev(dev); |
634 | } | 753 | } |
754 | |||
755 | DECLARE_USB_FUNCTION_INIT(phonet, phonet_alloc_inst, phonet_alloc); | ||
756 | MODULE_AUTHOR("Rémi Denis-Courmont"); | ||
757 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index 36e8c44d8e5e..191df35ae69d 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c | |||
@@ -17,15 +17,17 @@ | |||
17 | 17 | ||
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
20 | #include <linux/module.h> | ||
20 | #include <linux/device.h> | 21 | #include <linux/device.h> |
21 | #include <linux/etherdevice.h> | 22 | #include <linux/etherdevice.h> |
22 | 23 | ||
23 | #include <linux/atomic.h> | 24 | #include <linux/atomic.h> |
24 | 25 | ||
25 | #include "u_ether.h" | 26 | #include "u_ether.h" |
27 | #include "u_ether_configfs.h" | ||
28 | #include "u_rndis.h" | ||
26 | #include "rndis.h" | 29 | #include "rndis.h" |
27 | 30 | ||
28 | |||
29 | /* | 31 | /* |
30 | * This function is an RNDIS Ethernet port -- a Microsoft protocol that's | 32 | * This function is an RNDIS Ethernet port -- a Microsoft protocol that's |
31 | * been promoted instead of the standard CDC Ethernet. The published RNDIS | 33 | * been promoted instead of the standard CDC Ethernet. The published RNDIS |
@@ -655,6 +657,13 @@ static void rndis_close(struct gether *geth) | |||
655 | 657 | ||
656 | /*-------------------------------------------------------------------------*/ | 658 | /*-------------------------------------------------------------------------*/ |
657 | 659 | ||
660 | /* Some controllers can't support RNDIS ... */ | ||
661 | static inline bool can_support_rndis(struct usb_configuration *c) | ||
662 | { | ||
663 | /* everything else is *presumably* fine */ | ||
664 | return true; | ||
665 | } | ||
666 | |||
658 | /* ethernet function driver setup/binding */ | 667 | /* ethernet function driver setup/binding */ |
659 | 668 | ||
660 | static int | 669 | static int |
@@ -662,9 +671,41 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) | |||
662 | { | 671 | { |
663 | struct usb_composite_dev *cdev = c->cdev; | 672 | struct usb_composite_dev *cdev = c->cdev; |
664 | struct f_rndis *rndis = func_to_rndis(f); | 673 | struct f_rndis *rndis = func_to_rndis(f); |
674 | struct usb_string *us; | ||
665 | int status; | 675 | int status; |
666 | struct usb_ep *ep; | 676 | struct usb_ep *ep; |
667 | 677 | ||
678 | #ifndef USB_FRNDIS_INCLUDED | ||
679 | struct f_rndis_opts *rndis_opts; | ||
680 | |||
681 | if (!can_support_rndis(c)) | ||
682 | return -EINVAL; | ||
683 | |||
684 | rndis_opts = container_of(f->fi, struct f_rndis_opts, func_inst); | ||
685 | |||
686 | /* | ||
687 | * in drivers/usb/gadget/configfs.c:configfs_composite_bind() | ||
688 | * configurations are bound in sequence with list_for_each_entry, | ||
689 | * in each configuration its functions are bound in sequence | ||
690 | * with list_for_each_entry, so we assume no race condition | ||
691 | * with regard to rndis_opts->bound access | ||
692 | */ | ||
693 | if (!rndis_opts->bound) { | ||
694 | gether_set_gadget(rndis_opts->net, cdev->gadget); | ||
695 | status = gether_register_netdev(rndis_opts->net); | ||
696 | if (status) | ||
697 | return status; | ||
698 | rndis_opts->bound = true; | ||
699 | } | ||
700 | #endif | ||
701 | us = usb_gstrings_attach(cdev, rndis_strings, | ||
702 | ARRAY_SIZE(rndis_string_defs)); | ||
703 | if (IS_ERR(us)) | ||
704 | return PTR_ERR(us); | ||
705 | rndis_control_intf.iInterface = us[0].id; | ||
706 | rndis_data_intf.iInterface = us[1].id; | ||
707 | rndis_iad_descriptor.iFunction = us[2].id; | ||
708 | |||
668 | /* allocate instance-specific interface IDs */ | 709 | /* allocate instance-specific interface IDs */ |
669 | status = usb_interface_id(c, f); | 710 | status = usb_interface_id(c, f); |
670 | if (status < 0) | 711 | if (status < 0) |
@@ -741,10 +782,12 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) | |||
741 | rndis->port.open = rndis_open; | 782 | rndis->port.open = rndis_open; |
742 | rndis->port.close = rndis_close; | 783 | rndis->port.close = rndis_close; |
743 | 784 | ||
785 | #ifdef USB_FRNDIS_INCLUDED | ||
744 | status = rndis_register(rndis_response_available, rndis); | 786 | status = rndis_register(rndis_response_available, rndis); |
745 | if (status < 0) | 787 | if (status < 0) |
746 | goto fail; | 788 | goto fail; |
747 | rndis->config = status; | 789 | rndis->config = status; |
790 | #endif | ||
748 | 791 | ||
749 | rndis_set_param_medium(rndis->config, RNDIS_MEDIUM_802_3, 0); | 792 | rndis_set_param_medium(rndis->config, RNDIS_MEDIUM_802_3, 0); |
750 | rndis_set_host_mac(rndis->config, rndis->ethaddr); | 793 | rndis_set_host_mac(rndis->config, rndis->ethaddr); |
@@ -787,15 +830,15 @@ fail: | |||
787 | return status; | 830 | return status; |
788 | } | 831 | } |
789 | 832 | ||
833 | #ifdef USB_FRNDIS_INCLUDED | ||
834 | |||
790 | static void | 835 | static void |
791 | rndis_unbind(struct usb_configuration *c, struct usb_function *f) | 836 | rndis_old_unbind(struct usb_configuration *c, struct usb_function *f) |
792 | { | 837 | { |
793 | struct f_rndis *rndis = func_to_rndis(f); | 838 | struct f_rndis *rndis = func_to_rndis(f); |
794 | 839 | ||
795 | rndis_deregister(rndis->config); | 840 | rndis_deregister(rndis->config); |
796 | rndis_exit(); | ||
797 | 841 | ||
798 | rndis_string_defs[0].id = 0; | ||
799 | usb_free_all_descriptors(f); | 842 | usb_free_all_descriptors(f); |
800 | 843 | ||
801 | kfree(rndis->notify_req->buf); | 844 | kfree(rndis->notify_req->buf); |
@@ -804,13 +847,6 @@ rndis_unbind(struct usb_configuration *c, struct usb_function *f) | |||
804 | kfree(rndis); | 847 | kfree(rndis); |
805 | } | 848 | } |
806 | 849 | ||
807 | /* Some controllers can't support RNDIS ... */ | ||
808 | static inline bool can_support_rndis(struct usb_configuration *c) | ||
809 | { | ||
810 | /* everything else is *presumably* fine */ | ||
811 | return true; | ||
812 | } | ||
813 | |||
814 | int | 850 | int |
815 | rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], | 851 | rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], |
816 | u32 vendorID, const char *manufacturer, struct eth_dev *dev) | 852 | u32 vendorID, const char *manufacturer, struct eth_dev *dev) |
@@ -818,24 +854,6 @@ rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], | |||
818 | struct f_rndis *rndis; | 854 | struct f_rndis *rndis; |
819 | int status; | 855 | int status; |
820 | 856 | ||
821 | if (!can_support_rndis(c) || !ethaddr) | ||
822 | return -EINVAL; | ||
823 | |||
824 | if (rndis_string_defs[0].id == 0) { | ||
825 | /* ... and setup RNDIS itself */ | ||
826 | status = rndis_init(); | ||
827 | if (status < 0) | ||
828 | return status; | ||
829 | |||
830 | status = usb_string_ids_tab(c->cdev, rndis_string_defs); | ||
831 | if (status) | ||
832 | return status; | ||
833 | |||
834 | rndis_control_intf.iInterface = rndis_string_defs[0].id; | ||
835 | rndis_data_intf.iInterface = rndis_string_defs[1].id; | ||
836 | rndis_iad_descriptor.iFunction = rndis_string_defs[2].id; | ||
837 | } | ||
838 | |||
839 | /* allocate and initialize one new instance */ | 857 | /* allocate and initialize one new instance */ |
840 | status = -ENOMEM; | 858 | status = -ENOMEM; |
841 | rndis = kzalloc(sizeof *rndis, GFP_KERNEL); | 859 | rndis = kzalloc(sizeof *rndis, GFP_KERNEL); |
@@ -856,19 +874,178 @@ rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], | |||
856 | rndis->port.unwrap = rndis_rm_hdr; | 874 | rndis->port.unwrap = rndis_rm_hdr; |
857 | 875 | ||
858 | rndis->port.func.name = "rndis"; | 876 | rndis->port.func.name = "rndis"; |
859 | rndis->port.func.strings = rndis_strings; | ||
860 | /* descriptors are per-instance copies */ | 877 | /* descriptors are per-instance copies */ |
861 | rndis->port.func.bind = rndis_bind; | 878 | rndis->port.func.bind = rndis_bind; |
862 | rndis->port.func.unbind = rndis_unbind; | 879 | rndis->port.func.unbind = rndis_old_unbind; |
863 | rndis->port.func.set_alt = rndis_set_alt; | 880 | rndis->port.func.set_alt = rndis_set_alt; |
864 | rndis->port.func.setup = rndis_setup; | 881 | rndis->port.func.setup = rndis_setup; |
865 | rndis->port.func.disable = rndis_disable; | 882 | rndis->port.func.disable = rndis_disable; |
866 | 883 | ||
867 | status = usb_add_function(c, &rndis->port.func); | 884 | status = usb_add_function(c, &rndis->port.func); |
868 | if (status) { | 885 | if (status) |
869 | kfree(rndis); | 886 | kfree(rndis); |
870 | fail: | 887 | fail: |
871 | rndis_exit(); | ||
872 | } | ||
873 | return status; | 888 | return status; |
874 | } | 889 | } |
890 | |||
891 | #else | ||
892 | |||
893 | void rndis_borrow_net(struct usb_function_instance *f, struct net_device *net) | ||
894 | { | ||
895 | struct f_rndis_opts *opts; | ||
896 | |||
897 | opts = container_of(f, struct f_rndis_opts, func_inst); | ||
898 | if (opts->bound) | ||
899 | gether_cleanup(netdev_priv(opts->net)); | ||
900 | else | ||
901 | free_netdev(opts->net); | ||
902 | opts->borrowed_net = opts->bound = true; | ||
903 | opts->net = net; | ||
904 | } | ||
905 | EXPORT_SYMBOL(rndis_borrow_net); | ||
906 | |||
907 | static inline struct f_rndis_opts *to_f_rndis_opts(struct config_item *item) | ||
908 | { | ||
909 | return container_of(to_config_group(item), struct f_rndis_opts, | ||
910 | func_inst.group); | ||
911 | } | ||
912 | |||
913 | /* f_rndis_item_ops */ | ||
914 | USB_ETHERNET_CONFIGFS_ITEM(rndis); | ||
915 | |||
916 | /* f_rndis_opts_dev_addr */ | ||
917 | USB_ETHERNET_CONFIGFS_ITEM_ATTR_DEV_ADDR(rndis); | ||
918 | |||
919 | /* f_rndis_opts_host_addr */ | ||
920 | USB_ETHERNET_CONFIGFS_ITEM_ATTR_HOST_ADDR(rndis); | ||
921 | |||
922 | /* f_rndis_opts_qmult */ | ||
923 | USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(rndis); | ||
924 | |||
925 | /* f_rndis_opts_ifname */ | ||
926 | USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(rndis); | ||
927 | |||
928 | static struct configfs_attribute *rndis_attrs[] = { | ||
929 | &f_rndis_opts_dev_addr.attr, | ||
930 | &f_rndis_opts_host_addr.attr, | ||
931 | &f_rndis_opts_qmult.attr, | ||
932 | &f_rndis_opts_ifname.attr, | ||
933 | NULL, | ||
934 | }; | ||
935 | |||
936 | static struct config_item_type rndis_func_type = { | ||
937 | .ct_item_ops = &rndis_item_ops, | ||
938 | .ct_attrs = rndis_attrs, | ||
939 | .ct_owner = THIS_MODULE, | ||
940 | }; | ||
941 | |||
942 | static void rndis_free_inst(struct usb_function_instance *f) | ||
943 | { | ||
944 | struct f_rndis_opts *opts; | ||
945 | |||
946 | opts = container_of(f, struct f_rndis_opts, func_inst); | ||
947 | if (!opts->borrowed_net) { | ||
948 | if (opts->bound) | ||
949 | gether_cleanup(netdev_priv(opts->net)); | ||
950 | else | ||
951 | free_netdev(opts->net); | ||
952 | } | ||
953 | kfree(opts); | ||
954 | } | ||
955 | |||
956 | static struct usb_function_instance *rndis_alloc_inst(void) | ||
957 | { | ||
958 | struct f_rndis_opts *opts; | ||
959 | |||
960 | opts = kzalloc(sizeof(*opts), GFP_KERNEL); | ||
961 | if (!opts) | ||
962 | return ERR_PTR(-ENOMEM); | ||
963 | mutex_init(&opts->lock); | ||
964 | opts->func_inst.free_func_inst = rndis_free_inst; | ||
965 | opts->net = gether_setup_default(); | ||
966 | if (IS_ERR(opts->net)) | ||
967 | return ERR_CAST(opts->net); | ||
968 | |||
969 | config_group_init_type_name(&opts->func_inst.group, "", | ||
970 | &rndis_func_type); | ||
971 | |||
972 | return &opts->func_inst; | ||
973 | } | ||
974 | |||
975 | static void rndis_free(struct usb_function *f) | ||
976 | { | ||
977 | struct f_rndis *rndis; | ||
978 | struct f_rndis_opts *opts; | ||
979 | |||
980 | rndis = func_to_rndis(f); | ||
981 | rndis_deregister(rndis->config); | ||
982 | opts = container_of(f->fi, struct f_rndis_opts, func_inst); | ||
983 | kfree(rndis); | ||
984 | mutex_lock(&opts->lock); | ||
985 | opts->refcnt--; | ||
986 | mutex_unlock(&opts->lock); | ||
987 | } | ||
988 | |||
989 | static void rndis_unbind(struct usb_configuration *c, struct usb_function *f) | ||
990 | { | ||
991 | struct f_rndis *rndis = func_to_rndis(f); | ||
992 | |||
993 | usb_free_all_descriptors(f); | ||
994 | |||
995 | kfree(rndis->notify_req->buf); | ||
996 | usb_ep_free_request(rndis->notify, rndis->notify_req); | ||
997 | } | ||
998 | |||
999 | static struct usb_function *rndis_alloc(struct usb_function_instance *fi) | ||
1000 | { | ||
1001 | struct f_rndis *rndis; | ||
1002 | struct f_rndis_opts *opts; | ||
1003 | int status; | ||
1004 | |||
1005 | /* allocate and initialize one new instance */ | ||
1006 | rndis = kzalloc(sizeof(*rndis), GFP_KERNEL); | ||
1007 | if (!rndis) | ||
1008 | return ERR_PTR(-ENOMEM); | ||
1009 | |||
1010 | opts = container_of(fi, struct f_rndis_opts, func_inst); | ||
1011 | mutex_lock(&opts->lock); | ||
1012 | opts->refcnt++; | ||
1013 | |||
1014 | gether_get_host_addr_u8(opts->net, rndis->ethaddr); | ||
1015 | rndis->vendorID = opts->vendor_id; | ||
1016 | rndis->manufacturer = opts->manufacturer; | ||
1017 | |||
1018 | rndis->port.ioport = netdev_priv(opts->net); | ||
1019 | mutex_unlock(&opts->lock); | ||
1020 | /* RNDIS activates when the host changes this filter */ | ||
1021 | rndis->port.cdc_filter = 0; | ||
1022 | |||
1023 | /* RNDIS has special (and complex) framing */ | ||
1024 | rndis->port.header_len = sizeof(struct rndis_packet_msg_type); | ||
1025 | rndis->port.wrap = rndis_add_header; | ||
1026 | rndis->port.unwrap = rndis_rm_hdr; | ||
1027 | |||
1028 | rndis->port.func.name = "rndis"; | ||
1029 | /* descriptors are per-instance copies */ | ||
1030 | rndis->port.func.bind = rndis_bind; | ||
1031 | rndis->port.func.unbind = rndis_unbind; | ||
1032 | rndis->port.func.set_alt = rndis_set_alt; | ||
1033 | rndis->port.func.setup = rndis_setup; | ||
1034 | rndis->port.func.disable = rndis_disable; | ||
1035 | rndis->port.func.free_func = rndis_free; | ||
1036 | |||
1037 | status = rndis_register(rndis_response_available, rndis); | ||
1038 | if (status < 0) { | ||
1039 | kfree(rndis); | ||
1040 | return ERR_PTR(status); | ||
1041 | } | ||
1042 | rndis->config = status; | ||
1043 | |||
1044 | return &rndis->port.func; | ||
1045 | } | ||
1046 | |||
1047 | DECLARE_USB_FUNCTION_INIT(rndis, rndis_alloc_inst, rndis_alloc); | ||
1048 | MODULE_LICENSE("GPL"); | ||
1049 | MODULE_AUTHOR("David Brownell"); | ||
1050 | |||
1051 | #endif | ||
diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c index 7be04b342494..5601e1d96c4f 100644 --- a/drivers/usb/gadget/f_subset.c +++ b/drivers/usb/gadget/f_subset.c | |||
@@ -12,11 +12,13 @@ | |||
12 | 12 | ||
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/module.h> | ||
15 | #include <linux/device.h> | 16 | #include <linux/device.h> |
16 | #include <linux/etherdevice.h> | 17 | #include <linux/etherdevice.h> |
17 | 18 | ||
18 | #include "u_ether.h" | 19 | #include "u_ether.h" |
19 | 20 | #include "u_ether_configfs.h" | |
21 | #include "u_gether.h" | ||
20 | 22 | ||
21 | /* | 23 | /* |
22 | * This function packages a simple "CDC Subset" Ethernet port with no real | 24 | * This function packages a simple "CDC Subset" Ethernet port with no real |
@@ -295,9 +297,40 @@ geth_bind(struct usb_configuration *c, struct usb_function *f) | |||
295 | { | 297 | { |
296 | struct usb_composite_dev *cdev = c->cdev; | 298 | struct usb_composite_dev *cdev = c->cdev; |
297 | struct f_gether *geth = func_to_geth(f); | 299 | struct f_gether *geth = func_to_geth(f); |
300 | struct usb_string *us; | ||
298 | int status; | 301 | int status; |
299 | struct usb_ep *ep; | 302 | struct usb_ep *ep; |
300 | 303 | ||
304 | #ifndef USB_FSUBSET_INCLUDED | ||
305 | struct f_gether_opts *gether_opts; | ||
306 | |||
307 | gether_opts = container_of(f->fi, struct f_gether_opts, func_inst); | ||
308 | |||
309 | /* | ||
310 | * in drivers/usb/gadget/configfs.c:configfs_composite_bind() | ||
311 | * configurations are bound in sequence with list_for_each_entry, | ||
312 | * in each configuration its functions are bound in sequence | ||
313 | * with list_for_each_entry, so we assume no race condition | ||
314 | * with regard to gether_opts->bound access | ||
315 | */ | ||
316 | if (!gether_opts->bound) { | ||
317 | mutex_lock(&gether_opts->lock); | ||
318 | gether_set_gadget(gether_opts->net, cdev->gadget); | ||
319 | status = gether_register_netdev(gether_opts->net); | ||
320 | mutex_unlock(&gether_opts->lock); | ||
321 | if (status) | ||
322 | return status; | ||
323 | gether_opts->bound = true; | ||
324 | } | ||
325 | #endif | ||
326 | us = usb_gstrings_attach(cdev, geth_strings, | ||
327 | ARRAY_SIZE(geth_string_defs)); | ||
328 | if (IS_ERR(us)) | ||
329 | return PTR_ERR(us); | ||
330 | |||
331 | subset_data_intf.iInterface = us[0].id; | ||
332 | ether_desc.iMACAddress = us[1].id; | ||
333 | |||
301 | /* allocate instance-specific interface IDs */ | 334 | /* allocate instance-specific interface IDs */ |
302 | status = usb_interface_id(c, f); | 335 | status = usb_interface_id(c, f); |
303 | if (status < 0) | 336 | if (status < 0) |
@@ -360,8 +393,10 @@ fail: | |||
360 | return status; | 393 | return status; |
361 | } | 394 | } |
362 | 395 | ||
396 | #ifdef USB_FSUBSET_INCLUDED | ||
397 | |||
363 | static void | 398 | static void |
364 | geth_unbind(struct usb_configuration *c, struct usb_function *f) | 399 | geth_old_unbind(struct usb_configuration *c, struct usb_function *f) |
365 | { | 400 | { |
366 | geth_string_defs[0].id = 0; | 401 | geth_string_defs[0].id = 0; |
367 | usb_free_all_descriptors(f); | 402 | usb_free_all_descriptors(f); |
@@ -387,18 +422,6 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], | |||
387 | struct f_gether *geth; | 422 | struct f_gether *geth; |
388 | int status; | 423 | int status; |
389 | 424 | ||
390 | if (!ethaddr) | ||
391 | return -EINVAL; | ||
392 | |||
393 | /* maybe allocate device-global string IDs */ | ||
394 | if (geth_string_defs[0].id == 0) { | ||
395 | status = usb_string_ids_tab(c->cdev, geth_string_defs); | ||
396 | if (status < 0) | ||
397 | return status; | ||
398 | subset_data_intf.iInterface = geth_string_defs[0].id; | ||
399 | ether_desc.iMACAddress = geth_string_defs[1].id; | ||
400 | } | ||
401 | |||
402 | /* allocate and initialize one new instance */ | 425 | /* allocate and initialize one new instance */ |
403 | geth = kzalloc(sizeof *geth, GFP_KERNEL); | 426 | geth = kzalloc(sizeof *geth, GFP_KERNEL); |
404 | if (!geth) | 427 | if (!geth) |
@@ -412,9 +435,8 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], | |||
412 | geth->port.cdc_filter = DEFAULT_FILTER; | 435 | geth->port.cdc_filter = DEFAULT_FILTER; |
413 | 436 | ||
414 | geth->port.func.name = "cdc_subset"; | 437 | geth->port.func.name = "cdc_subset"; |
415 | geth->port.func.strings = geth_strings; | ||
416 | geth->port.func.bind = geth_bind; | 438 | geth->port.func.bind = geth_bind; |
417 | geth->port.func.unbind = geth_unbind; | 439 | geth->port.func.unbind = geth_old_unbind; |
418 | geth->port.func.set_alt = geth_set_alt; | 440 | geth->port.func.set_alt = geth_set_alt; |
419 | geth->port.func.disable = geth_disable; | 441 | geth->port.func.disable = geth_disable; |
420 | 442 | ||
@@ -423,3 +445,130 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], | |||
423 | kfree(geth); | 445 | kfree(geth); |
424 | return status; | 446 | return status; |
425 | } | 447 | } |
448 | |||
449 | #else | ||
450 | |||
451 | static inline struct f_gether_opts *to_f_gether_opts(struct config_item *item) | ||
452 | { | ||
453 | return container_of(to_config_group(item), struct f_gether_opts, | ||
454 | func_inst.group); | ||
455 | } | ||
456 | |||
457 | /* f_gether_item_ops */ | ||
458 | USB_ETHERNET_CONFIGFS_ITEM(gether); | ||
459 | |||
460 | /* f_gether_opts_dev_addr */ | ||
461 | USB_ETHERNET_CONFIGFS_ITEM_ATTR_DEV_ADDR(gether); | ||
462 | |||
463 | /* f_gether_opts_host_addr */ | ||
464 | USB_ETHERNET_CONFIGFS_ITEM_ATTR_HOST_ADDR(gether); | ||
465 | |||
466 | /* f_gether_opts_qmult */ | ||
467 | USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(gether); | ||
468 | |||
469 | /* f_gether_opts_ifname */ | ||
470 | USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(gether); | ||
471 | |||
472 | static struct configfs_attribute *gether_attrs[] = { | ||
473 | &f_gether_opts_dev_addr.attr, | ||
474 | &f_gether_opts_host_addr.attr, | ||
475 | &f_gether_opts_qmult.attr, | ||
476 | &f_gether_opts_ifname.attr, | ||
477 | NULL, | ||
478 | }; | ||
479 | |||
480 | static struct config_item_type gether_func_type = { | ||
481 | .ct_item_ops = &gether_item_ops, | ||
482 | .ct_attrs = gether_attrs, | ||
483 | .ct_owner = THIS_MODULE, | ||
484 | }; | ||
485 | |||
486 | static void geth_free_inst(struct usb_function_instance *f) | ||
487 | { | ||
488 | struct f_gether_opts *opts; | ||
489 | |||
490 | opts = container_of(f, struct f_gether_opts, func_inst); | ||
491 | if (opts->bound) | ||
492 | gether_cleanup(netdev_priv(opts->net)); | ||
493 | else | ||
494 | free_netdev(opts->net); | ||
495 | kfree(opts); | ||
496 | } | ||
497 | |||
498 | static struct usb_function_instance *geth_alloc_inst(void) | ||
499 | { | ||
500 | struct f_gether_opts *opts; | ||
501 | |||
502 | opts = kzalloc(sizeof(*opts), GFP_KERNEL); | ||
503 | if (!opts) | ||
504 | return ERR_PTR(-ENOMEM); | ||
505 | mutex_init(&opts->lock); | ||
506 | opts->func_inst.free_func_inst = geth_free_inst; | ||
507 | opts->net = gether_setup_default(); | ||
508 | if (IS_ERR(opts->net)) | ||
509 | return ERR_CAST(opts->net); | ||
510 | |||
511 | config_group_init_type_name(&opts->func_inst.group, "", | ||
512 | &gether_func_type); | ||
513 | |||
514 | return &opts->func_inst; | ||
515 | } | ||
516 | |||
517 | static void geth_free(struct usb_function *f) | ||
518 | { | ||
519 | struct f_gether *eth; | ||
520 | |||
521 | eth = func_to_geth(f); | ||
522 | kfree(eth); | ||
523 | } | ||
524 | |||
525 | static void geth_unbind(struct usb_configuration *c, struct usb_function *f) | ||
526 | { | ||
527 | geth_string_defs[0].id = 0; | ||
528 | usb_free_all_descriptors(f); | ||
529 | } | ||
530 | |||
531 | static struct usb_function *geth_alloc(struct usb_function_instance *fi) | ||
532 | { | ||
533 | struct f_gether *geth; | ||
534 | struct f_gether_opts *opts; | ||
535 | int status; | ||
536 | |||
537 | /* allocate and initialize one new instance */ | ||
538 | geth = kzalloc(sizeof(*geth), GFP_KERNEL); | ||
539 | if (!geth) | ||
540 | return ERR_PTR(-ENOMEM); | ||
541 | |||
542 | opts = container_of(fi, struct f_gether_opts, func_inst); | ||
543 | |||
544 | mutex_lock(&opts->lock); | ||
545 | opts->refcnt++; | ||
546 | /* export host's Ethernet address in CDC format */ | ||
547 | status = gether_get_host_addr_cdc(opts->net, geth->ethaddr, | ||
548 | sizeof(geth->ethaddr)); | ||
549 | if (status < 12) { | ||
550 | kfree(geth); | ||
551 | mutex_unlock(&opts->lock); | ||
552 | return ERR_PTR(-EINVAL); | ||
553 | } | ||
554 | geth_string_defs[1].s = geth->ethaddr; | ||
555 | |||
556 | geth->port.ioport = netdev_priv(opts->net); | ||
557 | mutex_unlock(&opts->lock); | ||
558 | geth->port.cdc_filter = DEFAULT_FILTER; | ||
559 | |||
560 | geth->port.func.name = "cdc_subset"; | ||
561 | geth->port.func.bind = geth_bind; | ||
562 | geth->port.func.unbind = geth_unbind; | ||
563 | geth->port.func.set_alt = geth_set_alt; | ||
564 | geth->port.func.disable = geth_disable; | ||
565 | geth->port.func.free_func = geth_free; | ||
566 | |||
567 | return &geth->port.func; | ||
568 | } | ||
569 | |||
570 | DECLARE_USB_FUNCTION_INIT(geth, geth_alloc_inst, geth_alloc); | ||
571 | MODULE_LICENSE("GPL"); | ||
572 | MODULE_AUTHOR("David Brownell"); | ||
573 | |||
574 | #endif | ||
diff --git a/drivers/usb/gadget/f_uac2.c b/drivers/usb/gadget/f_uac2.c index 03c1fb686644..2f23566e53d8 100644 --- a/drivers/usb/gadget/f_uac2.c +++ b/drivers/usb/gadget/f_uac2.c | |||
@@ -90,6 +90,7 @@ struct uac2_req { | |||
90 | }; | 90 | }; |
91 | 91 | ||
92 | struct uac2_rtd_params { | 92 | struct uac2_rtd_params { |
93 | struct snd_uac2_chip *uac2; /* parent chip */ | ||
93 | bool ep_enabled; /* if the ep is enabled */ | 94 | bool ep_enabled; /* if the ep is enabled */ |
94 | /* Size of the ring buffer */ | 95 | /* Size of the ring buffer */ |
95 | size_t dma_bytes; | 96 | size_t dma_bytes; |
@@ -169,18 +170,6 @@ struct snd_uac2_chip *pdev_to_uac2(struct platform_device *p) | |||
169 | } | 170 | } |
170 | 171 | ||
171 | static inline | 172 | static inline |
172 | struct snd_uac2_chip *prm_to_uac2(struct uac2_rtd_params *r) | ||
173 | { | ||
174 | struct snd_uac2_chip *uac2 = container_of(r, | ||
175 | struct snd_uac2_chip, c_prm); | ||
176 | |||
177 | if (&uac2->c_prm != r) | ||
178 | uac2 = container_of(r, struct snd_uac2_chip, p_prm); | ||
179 | |||
180 | return uac2; | ||
181 | } | ||
182 | |||
183 | static inline | ||
184 | uint num_channels(uint chanmask) | 173 | uint num_channels(uint chanmask) |
185 | { | 174 | { |
186 | uint num = 0; | 175 | uint num = 0; |
@@ -204,7 +193,7 @@ agdev_iso_complete(struct usb_ep *ep, struct usb_request *req) | |||
204 | struct uac2_req *ur = req->context; | 193 | struct uac2_req *ur = req->context; |
205 | struct snd_pcm_substream *substream; | 194 | struct snd_pcm_substream *substream; |
206 | struct uac2_rtd_params *prm = ur->pp; | 195 | struct uac2_rtd_params *prm = ur->pp; |
207 | struct snd_uac2_chip *uac2 = prm_to_uac2(prm); | 196 | struct snd_uac2_chip *uac2 = prm->uac2; |
208 | 197 | ||
209 | /* i/f shutting down */ | 198 | /* i/f shutting down */ |
210 | if (!prm->ep_enabled) | 199 | if (!prm->ep_enabled) |
@@ -894,7 +883,7 @@ struct cntrl_range_lay3 { | |||
894 | static inline void | 883 | static inline void |
895 | free_ep(struct uac2_rtd_params *prm, struct usb_ep *ep) | 884 | free_ep(struct uac2_rtd_params *prm, struct usb_ep *ep) |
896 | { | 885 | { |
897 | struct snd_uac2_chip *uac2 = prm_to_uac2(prm); | 886 | struct snd_uac2_chip *uac2 = prm->uac2; |
898 | int i; | 887 | int i; |
899 | 888 | ||
900 | prm->ep_enabled = false; | 889 | prm->ep_enabled = false; |
@@ -970,6 +959,9 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) | |||
970 | } | 959 | } |
971 | agdev->in_ep->driver_data = agdev; | 960 | agdev->in_ep->driver_data = agdev; |
972 | 961 | ||
962 | uac2->p_prm.uac2 = uac2; | ||
963 | uac2->c_prm.uac2 = uac2; | ||
964 | |||
973 | hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress; | 965 | hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress; |
974 | hs_epout_desc.wMaxPacketSize = fs_epout_desc.wMaxPacketSize; | 966 | hs_epout_desc.wMaxPacketSize = fs_epout_desc.wMaxPacketSize; |
975 | hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress; | 967 | hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress; |
diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c index 38dcedddc52c..5f91c7a59946 100644 --- a/drivers/usb/gadget/f_uvc.c +++ b/drivers/usb/gadget/f_uvc.c | |||
@@ -156,8 +156,6 @@ static struct usb_endpoint_descriptor uvc_fs_streaming_ep __initdata = { | |||
156 | /* The wMaxPacketSize and bInterval values will be initialized from | 156 | /* The wMaxPacketSize and bInterval values will be initialized from |
157 | * module parameters. | 157 | * module parameters. |
158 | */ | 158 | */ |
159 | .wMaxPacketSize = 0, | ||
160 | .bInterval = 0, | ||
161 | }; | 159 | }; |
162 | 160 | ||
163 | static struct usb_endpoint_descriptor uvc_hs_streaming_ep __initdata = { | 161 | static struct usb_endpoint_descriptor uvc_hs_streaming_ep __initdata = { |
@@ -169,8 +167,6 @@ static struct usb_endpoint_descriptor uvc_hs_streaming_ep __initdata = { | |||
169 | /* The wMaxPacketSize and bInterval values will be initialized from | 167 | /* The wMaxPacketSize and bInterval values will be initialized from |
170 | * module parameters. | 168 | * module parameters. |
171 | */ | 169 | */ |
172 | .wMaxPacketSize = 0, | ||
173 | .bInterval = 0, | ||
174 | }; | 170 | }; |
175 | 171 | ||
176 | static struct usb_endpoint_descriptor uvc_ss_streaming_ep __initdata = { | 172 | static struct usb_endpoint_descriptor uvc_ss_streaming_ep __initdata = { |
@@ -183,17 +179,14 @@ static struct usb_endpoint_descriptor uvc_ss_streaming_ep __initdata = { | |||
183 | /* The wMaxPacketSize and bInterval values will be initialized from | 179 | /* The wMaxPacketSize and bInterval values will be initialized from |
184 | * module parameters. | 180 | * module parameters. |
185 | */ | 181 | */ |
186 | .wMaxPacketSize = 0, | ||
187 | .bInterval = 0, | ||
188 | }; | 182 | }; |
189 | 183 | ||
190 | static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp __initdata = { | 184 | static struct usb_ss_ep_comp_descriptor uvc_ss_streaming_comp __initdata = { |
191 | .bLength = sizeof(uvc_ss_streaming_comp), | 185 | .bLength = sizeof(uvc_ss_streaming_comp), |
192 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, | 186 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, |
193 | /* The following 3 values can be tweaked if necessary. */ | 187 | /* The bMaxBurst, bmAttributes and wBytesPerInterval values will be |
194 | .bMaxBurst = 0, | 188 | * initialized from module parameters. |
195 | .bmAttributes = 0, | 189 | */ |
196 | .wBytesPerInterval = cpu_to_le16(1024), | ||
197 | }; | 190 | }; |
198 | 191 | ||
199 | static const struct usb_descriptor_header * const uvc_fs_streaming[] = { | 192 | static const struct usb_descriptor_header * const uvc_fs_streaming[] = { |
diff --git a/drivers/usb/gadget/fotg210-udc.c b/drivers/usb/gadget/fotg210-udc.c new file mode 100644 index 000000000000..cce5535b1dc6 --- /dev/null +++ b/drivers/usb/gadget/fotg210-udc.c | |||
@@ -0,0 +1,1219 @@ | |||
1 | /* | ||
2 | * FOTG210 UDC Driver supports Bulk transfer so far | ||
3 | * | ||
4 | * Copyright (C) 2013 Faraday Technology Corporation | ||
5 | * | ||
6 | * Author : Yuan-Hsin Chen <yhchen@faraday-tech.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; version 2 of the License. | ||
11 | */ | ||
12 | |||
13 | #include <linux/dma-mapping.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/usb/ch9.h> | ||
20 | #include <linux/usb/gadget.h> | ||
21 | |||
22 | #include "fotg210.h" | ||
23 | |||
24 | #define DRIVER_DESC "FOTG210 USB Device Controller Driver" | ||
25 | #define DRIVER_VERSION "30-April-2013" | ||
26 | |||
27 | static const char udc_name[] = "fotg210_udc"; | ||
28 | static const char * const fotg210_ep_name[] = { | ||
29 | "ep0", "ep1", "ep2", "ep3", "ep4"}; | ||
30 | |||
31 | static void fotg210_disable_fifo_int(struct fotg210_ep *ep) | ||
32 | { | ||
33 | u32 value = ioread32(ep->fotg210->reg + FOTG210_DMISGR1); | ||
34 | |||
35 | if (ep->dir_in) | ||
36 | value |= DMISGR1_MF_IN_INT(ep->epnum - 1); | ||
37 | else | ||
38 | value |= DMISGR1_MF_OUTSPK_INT(ep->epnum - 1); | ||
39 | iowrite32(value, ep->fotg210->reg + FOTG210_DMISGR1); | ||
40 | } | ||
41 | |||
42 | static void fotg210_enable_fifo_int(struct fotg210_ep *ep) | ||
43 | { | ||
44 | u32 value = ioread32(ep->fotg210->reg + FOTG210_DMISGR1); | ||
45 | |||
46 | if (ep->dir_in) | ||
47 | value &= ~DMISGR1_MF_IN_INT(ep->epnum - 1); | ||
48 | else | ||
49 | value &= ~DMISGR1_MF_OUTSPK_INT(ep->epnum - 1); | ||
50 | iowrite32(value, ep->fotg210->reg + FOTG210_DMISGR1); | ||
51 | } | ||
52 | |||
53 | static void fotg210_set_cxdone(struct fotg210_udc *fotg210) | ||
54 | { | ||
55 | u32 value = ioread32(fotg210->reg + FOTG210_DCFESR); | ||
56 | |||
57 | value |= DCFESR_CX_DONE; | ||
58 | iowrite32(value, fotg210->reg + FOTG210_DCFESR); | ||
59 | } | ||
60 | |||
61 | static void fotg210_done(struct fotg210_ep *ep, struct fotg210_request *req, | ||
62 | int status) | ||
63 | { | ||
64 | list_del_init(&req->queue); | ||
65 | |||
66 | /* don't modify queue heads during completion callback */ | ||
67 | if (ep->fotg210->gadget.speed == USB_SPEED_UNKNOWN) | ||
68 | req->req.status = -ESHUTDOWN; | ||
69 | else | ||
70 | req->req.status = status; | ||
71 | |||
72 | spin_unlock(&ep->fotg210->lock); | ||
73 | req->req.complete(&ep->ep, &req->req); | ||
74 | spin_lock(&ep->fotg210->lock); | ||
75 | |||
76 | if (ep->epnum) { | ||
77 | if (list_empty(&ep->queue)) | ||
78 | fotg210_disable_fifo_int(ep); | ||
79 | } else { | ||
80 | fotg210_set_cxdone(ep->fotg210); | ||
81 | } | ||
82 | } | ||
83 | |||
84 | static void fotg210_fifo_ep_mapping(struct fotg210_ep *ep, u32 epnum, | ||
85 | u32 dir_in) | ||
86 | { | ||
87 | struct fotg210_udc *fotg210 = ep->fotg210; | ||
88 | u32 val; | ||
89 | |||
90 | /* Driver should map an ep to a fifo and then map the fifo | ||
91 | * to the ep. What a brain-damaged design! | ||
92 | */ | ||
93 | |||
94 | /* map a fifo to an ep */ | ||
95 | val = ioread32(fotg210->reg + FOTG210_EPMAP); | ||
96 | val &= ~EPMAP_FIFONOMSK(epnum, dir_in); | ||
97 | val |= EPMAP_FIFONO(epnum, dir_in); | ||
98 | iowrite32(val, fotg210->reg + FOTG210_EPMAP); | ||
99 | |||
100 | /* map the ep to the fifo */ | ||
101 | val = ioread32(fotg210->reg + FOTG210_FIFOMAP); | ||
102 | val &= ~FIFOMAP_EPNOMSK(epnum); | ||
103 | val |= FIFOMAP_EPNO(epnum); | ||
104 | iowrite32(val, fotg210->reg + FOTG210_FIFOMAP); | ||
105 | |||
106 | /* enable fifo */ | ||
107 | val = ioread32(fotg210->reg + FOTG210_FIFOCF); | ||
108 | val |= FIFOCF_FIFO_EN(epnum - 1); | ||
109 | iowrite32(val, fotg210->reg + FOTG210_FIFOCF); | ||
110 | } | ||
111 | |||
112 | static void fotg210_set_fifo_dir(struct fotg210_ep *ep, u32 epnum, u32 dir_in) | ||
113 | { | ||
114 | struct fotg210_udc *fotg210 = ep->fotg210; | ||
115 | u32 val; | ||
116 | |||
117 | val = ioread32(fotg210->reg + FOTG210_FIFOMAP); | ||
118 | val |= (dir_in ? FIFOMAP_DIRIN(epnum - 1) : FIFOMAP_DIROUT(epnum - 1)); | ||
119 | iowrite32(val, fotg210->reg + FOTG210_FIFOMAP); | ||
120 | } | ||
121 | |||
122 | static void fotg210_set_tfrtype(struct fotg210_ep *ep, u32 epnum, u32 type) | ||
123 | { | ||
124 | struct fotg210_udc *fotg210 = ep->fotg210; | ||
125 | u32 val; | ||
126 | |||
127 | val = ioread32(fotg210->reg + FOTG210_FIFOCF); | ||
128 | val |= FIFOCF_TYPE(type, epnum - 1); | ||
129 | iowrite32(val, fotg210->reg + FOTG210_FIFOCF); | ||
130 | } | ||
131 | |||
132 | static void fotg210_set_mps(struct fotg210_ep *ep, u32 epnum, u32 mps, | ||
133 | u32 dir_in) | ||
134 | { | ||
135 | struct fotg210_udc *fotg210 = ep->fotg210; | ||
136 | u32 val; | ||
137 | u32 offset = dir_in ? FOTG210_INEPMPSR(epnum) : | ||
138 | FOTG210_OUTEPMPSR(epnum); | ||
139 | |||
140 | val = ioread32(fotg210->reg + offset); | ||
141 | val |= INOUTEPMPSR_MPS(mps); | ||
142 | iowrite32(val, fotg210->reg + offset); | ||
143 | } | ||
144 | |||
145 | static int fotg210_config_ep(struct fotg210_ep *ep, | ||
146 | const struct usb_endpoint_descriptor *desc) | ||
147 | { | ||
148 | struct fotg210_udc *fotg210 = ep->fotg210; | ||
149 | |||
150 | fotg210_set_fifo_dir(ep, ep->epnum, ep->dir_in); | ||
151 | fotg210_set_tfrtype(ep, ep->epnum, ep->type); | ||
152 | fotg210_set_mps(ep, ep->epnum, ep->ep.maxpacket, ep->dir_in); | ||
153 | fotg210_fifo_ep_mapping(ep, ep->epnum, ep->dir_in); | ||
154 | |||
155 | fotg210->ep[ep->epnum] = ep; | ||
156 | |||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | static int fotg210_ep_enable(struct usb_ep *_ep, | ||
161 | const struct usb_endpoint_descriptor *desc) | ||
162 | { | ||
163 | struct fotg210_ep *ep; | ||
164 | |||
165 | ep = container_of(_ep, struct fotg210_ep, ep); | ||
166 | |||
167 | ep->desc = desc; | ||
168 | ep->epnum = usb_endpoint_num(desc); | ||
169 | ep->type = usb_endpoint_type(desc); | ||
170 | ep->dir_in = usb_endpoint_dir_in(desc); | ||
171 | ep->ep.maxpacket = usb_endpoint_maxp(desc); | ||
172 | |||
173 | return fotg210_config_ep(ep, desc); | ||
174 | } | ||
175 | |||
176 | static void fotg210_reset_tseq(struct fotg210_udc *fotg210, u8 epnum) | ||
177 | { | ||
178 | struct fotg210_ep *ep = fotg210->ep[epnum]; | ||
179 | u32 value; | ||
180 | void __iomem *reg; | ||
181 | |||
182 | reg = (ep->dir_in) ? | ||
183 | fotg210->reg + FOTG210_INEPMPSR(epnum) : | ||
184 | fotg210->reg + FOTG210_OUTEPMPSR(epnum); | ||
185 | |||
186 | /* Note: Driver needs to set and clear INOUTEPMPSR_RESET_TSEQ | ||
187 | * bit. Controller wouldn't clear this bit. WTF!!! | ||
188 | */ | ||
189 | |||
190 | value = ioread32(reg); | ||
191 | value |= INOUTEPMPSR_RESET_TSEQ; | ||
192 | iowrite32(value, reg); | ||
193 | |||
194 | value = ioread32(reg); | ||
195 | value &= ~INOUTEPMPSR_RESET_TSEQ; | ||
196 | iowrite32(value, reg); | ||
197 | } | ||
198 | |||
199 | static int fotg210_ep_release(struct fotg210_ep *ep) | ||
200 | { | ||
201 | if (!ep->epnum) | ||
202 | return 0; | ||
203 | ep->epnum = 0; | ||
204 | ep->stall = 0; | ||
205 | ep->wedged = 0; | ||
206 | |||
207 | fotg210_reset_tseq(ep->fotg210, ep->epnum); | ||
208 | |||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static int fotg210_ep_disable(struct usb_ep *_ep) | ||
213 | { | ||
214 | struct fotg210_ep *ep; | ||
215 | struct fotg210_request *req; | ||
216 | unsigned long flags; | ||
217 | |||
218 | BUG_ON(!_ep); | ||
219 | |||
220 | ep = container_of(_ep, struct fotg210_ep, ep); | ||
221 | |||
222 | while (!list_empty(&ep->queue)) { | ||
223 | req = list_entry(ep->queue.next, | ||
224 | struct fotg210_request, queue); | ||
225 | spin_lock_irqsave(&ep->fotg210->lock, flags); | ||
226 | fotg210_done(ep, req, -ECONNRESET); | ||
227 | spin_unlock_irqrestore(&ep->fotg210->lock, flags); | ||
228 | } | ||
229 | |||
230 | return fotg210_ep_release(ep); | ||
231 | } | ||
232 | |||
233 | static struct usb_request *fotg210_ep_alloc_request(struct usb_ep *_ep, | ||
234 | gfp_t gfp_flags) | ||
235 | { | ||
236 | struct fotg210_request *req; | ||
237 | |||
238 | req = kzalloc(sizeof(struct fotg210_request), gfp_flags); | ||
239 | if (!req) | ||
240 | return NULL; | ||
241 | |||
242 | INIT_LIST_HEAD(&req->queue); | ||
243 | |||
244 | return &req->req; | ||
245 | } | ||
246 | |||
247 | static void fotg210_ep_free_request(struct usb_ep *_ep, | ||
248 | struct usb_request *_req) | ||
249 | { | ||
250 | struct fotg210_request *req; | ||
251 | |||
252 | req = container_of(_req, struct fotg210_request, req); | ||
253 | kfree(req); | ||
254 | } | ||
255 | |||
256 | static void fotg210_enable_dma(struct fotg210_ep *ep, | ||
257 | dma_addr_t d, u32 len) | ||
258 | { | ||
259 | u32 value; | ||
260 | struct fotg210_udc *fotg210 = ep->fotg210; | ||
261 | |||
262 | /* set transfer length and direction */ | ||
263 | value = ioread32(fotg210->reg + FOTG210_DMACPSR1); | ||
264 | value &= ~(DMACPSR1_DMA_LEN(0xFFFF) | DMACPSR1_DMA_TYPE(1)); | ||
265 | value |= DMACPSR1_DMA_LEN(len) | DMACPSR1_DMA_TYPE(ep->dir_in); | ||
266 | iowrite32(value, fotg210->reg + FOTG210_DMACPSR1); | ||
267 | |||
268 | /* set device DMA target FIFO number */ | ||
269 | value = ioread32(fotg210->reg + FOTG210_DMATFNR); | ||
270 | if (ep->epnum) | ||
271 | value |= DMATFNR_ACC_FN(ep->epnum - 1); | ||
272 | else | ||
273 | value |= DMATFNR_ACC_CXF; | ||
274 | iowrite32(value, fotg210->reg + FOTG210_DMATFNR); | ||
275 | |||
276 | /* set DMA memory address */ | ||
277 | iowrite32(d, fotg210->reg + FOTG210_DMACPSR2); | ||
278 | |||
279 | /* enable MDMA_EROR and MDMA_CMPLT interrupt */ | ||
280 | value = ioread32(fotg210->reg + FOTG210_DMISGR2); | ||
281 | value &= ~(DMISGR2_MDMA_CMPLT | DMISGR2_MDMA_ERROR); | ||
282 | iowrite32(value, fotg210->reg + FOTG210_DMISGR2); | ||
283 | |||
284 | /* start DMA */ | ||
285 | value = ioread32(fotg210->reg + FOTG210_DMACPSR1); | ||
286 | value |= DMACPSR1_DMA_START; | ||
287 | iowrite32(value, fotg210->reg + FOTG210_DMACPSR1); | ||
288 | } | ||
289 | |||
290 | static void fotg210_disable_dma(struct fotg210_ep *ep) | ||
291 | { | ||
292 | iowrite32(DMATFNR_DISDMA, ep->fotg210->reg + FOTG210_DMATFNR); | ||
293 | } | ||
294 | |||
295 | static void fotg210_wait_dma_done(struct fotg210_ep *ep) | ||
296 | { | ||
297 | u32 value; | ||
298 | |||
299 | do { | ||
300 | value = ioread32(ep->fotg210->reg + FOTG210_DISGR2); | ||
301 | if ((value & DISGR2_USBRST_INT) || | ||
302 | (value & DISGR2_DMA_ERROR)) | ||
303 | goto dma_reset; | ||
304 | } while (!(value & DISGR2_DMA_CMPLT)); | ||
305 | |||
306 | value &= ~DISGR2_DMA_CMPLT; | ||
307 | iowrite32(value, ep->fotg210->reg + FOTG210_DISGR2); | ||
308 | return; | ||
309 | |||
310 | dma_reset: | ||
311 | value = ioread32(ep->fotg210->reg + FOTG210_DMACPSR1); | ||
312 | value |= DMACPSR1_DMA_ABORT; | ||
313 | iowrite32(value, ep->fotg210->reg + FOTG210_DMACPSR1); | ||
314 | |||
315 | /* reset fifo */ | ||
316 | if (ep->epnum) { | ||
317 | value = ioread32(ep->fotg210->reg + | ||
318 | FOTG210_FIBCR(ep->epnum - 1)); | ||
319 | value |= FIBCR_FFRST; | ||
320 | iowrite32(value, ep->fotg210->reg + | ||
321 | FOTG210_FIBCR(ep->epnum - 1)); | ||
322 | } else { | ||
323 | value = ioread32(ep->fotg210->reg + FOTG210_DCFESR); | ||
324 | value |= DCFESR_CX_CLR; | ||
325 | iowrite32(value, ep->fotg210->reg + FOTG210_DCFESR); | ||
326 | } | ||
327 | } | ||
328 | |||
329 | static void fotg210_start_dma(struct fotg210_ep *ep, | ||
330 | struct fotg210_request *req) | ||
331 | { | ||
332 | dma_addr_t d; | ||
333 | u8 *buffer; | ||
334 | u32 length; | ||
335 | |||
336 | if (ep->epnum) { | ||
337 | if (ep->dir_in) { | ||
338 | buffer = req->req.buf; | ||
339 | length = req->req.length; | ||
340 | } else { | ||
341 | buffer = req->req.buf + req->req.actual; | ||
342 | length = ioread32(ep->fotg210->reg + | ||
343 | FOTG210_FIBCR(ep->epnum - 1)); | ||
344 | length &= FIBCR_BCFX; | ||
345 | } | ||
346 | } else { | ||
347 | buffer = req->req.buf + req->req.actual; | ||
348 | if (req->req.length - req->req.actual > ep->ep.maxpacket) | ||
349 | length = ep->ep.maxpacket; | ||
350 | else | ||
351 | length = req->req.length; | ||
352 | } | ||
353 | |||
354 | d = dma_map_single(NULL, buffer, length, | ||
355 | ep->dir_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE); | ||
356 | |||
357 | if (dma_mapping_error(NULL, d)) { | ||
358 | pr_err("dma_mapping_error\n"); | ||
359 | return; | ||
360 | } | ||
361 | |||
362 | dma_sync_single_for_device(NULL, d, length, | ||
363 | ep->dir_in ? DMA_TO_DEVICE : | ||
364 | DMA_FROM_DEVICE); | ||
365 | |||
366 | fotg210_enable_dma(ep, d, length); | ||
367 | |||
368 | /* check if dma is done */ | ||
369 | fotg210_wait_dma_done(ep); | ||
370 | |||
371 | fotg210_disable_dma(ep); | ||
372 | |||
373 | /* update actual transfer length */ | ||
374 | req->req.actual += length; | ||
375 | |||
376 | dma_unmap_single(NULL, d, length, DMA_TO_DEVICE); | ||
377 | } | ||
378 | |||
379 | static void fotg210_ep0_queue(struct fotg210_ep *ep, | ||
380 | struct fotg210_request *req) | ||
381 | { | ||
382 | if (!req->req.length) { | ||
383 | fotg210_done(ep, req, 0); | ||
384 | return; | ||
385 | } | ||
386 | if (ep->dir_in) { /* if IN */ | ||
387 | if (req->req.length) { | ||
388 | fotg210_start_dma(ep, req); | ||
389 | } else { | ||
390 | pr_err("%s : req->req.length = 0x%x\n", | ||
391 | __func__, req->req.length); | ||
392 | } | ||
393 | if ((req->req.length == req->req.actual) || | ||
394 | (req->req.actual < ep->ep.maxpacket)) | ||
395 | fotg210_done(ep, req, 0); | ||
396 | } else { /* OUT */ | ||
397 | if (!req->req.length) { | ||
398 | fotg210_done(ep, req, 0); | ||
399 | } else { | ||
400 | u32 value = ioread32(ep->fotg210->reg + | ||
401 | FOTG210_DMISGR0); | ||
402 | |||
403 | value &= ~DMISGR0_MCX_OUT_INT; | ||
404 | iowrite32(value, ep->fotg210->reg + FOTG210_DMISGR0); | ||
405 | } | ||
406 | } | ||
407 | } | ||
408 | |||
409 | static int fotg210_ep_queue(struct usb_ep *_ep, struct usb_request *_req, | ||
410 | gfp_t gfp_flags) | ||
411 | { | ||
412 | struct fotg210_ep *ep; | ||
413 | struct fotg210_request *req; | ||
414 | unsigned long flags; | ||
415 | int request = 0; | ||
416 | |||
417 | ep = container_of(_ep, struct fotg210_ep, ep); | ||
418 | req = container_of(_req, struct fotg210_request, req); | ||
419 | |||
420 | if (ep->fotg210->gadget.speed == USB_SPEED_UNKNOWN) | ||
421 | return -ESHUTDOWN; | ||
422 | |||
423 | spin_lock_irqsave(&ep->fotg210->lock, flags); | ||
424 | |||
425 | if (list_empty(&ep->queue)) | ||
426 | request = 1; | ||
427 | |||
428 | list_add_tail(&req->queue, &ep->queue); | ||
429 | |||
430 | req->req.actual = 0; | ||
431 | req->req.status = -EINPROGRESS; | ||
432 | |||
433 | if (!ep->epnum) /* ep0 */ | ||
434 | fotg210_ep0_queue(ep, req); | ||
435 | else if (request && !ep->stall) | ||
436 | fotg210_enable_fifo_int(ep); | ||
437 | |||
438 | spin_unlock_irqrestore(&ep->fotg210->lock, flags); | ||
439 | |||
440 | return 0; | ||
441 | } | ||
442 | |||
443 | static int fotg210_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) | ||
444 | { | ||
445 | struct fotg210_ep *ep; | ||
446 | struct fotg210_request *req; | ||
447 | unsigned long flags; | ||
448 | |||
449 | ep = container_of(_ep, struct fotg210_ep, ep); | ||
450 | req = container_of(_req, struct fotg210_request, req); | ||
451 | |||
452 | spin_lock_irqsave(&ep->fotg210->lock, flags); | ||
453 | if (!list_empty(&ep->queue)) | ||
454 | fotg210_done(ep, req, -ECONNRESET); | ||
455 | spin_unlock_irqrestore(&ep->fotg210->lock, flags); | ||
456 | |||
457 | return 0; | ||
458 | } | ||
459 | |||
460 | static void fotg210_set_epnstall(struct fotg210_ep *ep) | ||
461 | { | ||
462 | struct fotg210_udc *fotg210 = ep->fotg210; | ||
463 | u32 value; | ||
464 | void __iomem *reg; | ||
465 | |||
466 | /* check if IN FIFO is empty before stall */ | ||
467 | if (ep->dir_in) { | ||
468 | do { | ||
469 | value = ioread32(fotg210->reg + FOTG210_DCFESR); | ||
470 | } while (!(value & DCFESR_FIFO_EMPTY(ep->epnum - 1))); | ||
471 | } | ||
472 | |||
473 | reg = (ep->dir_in) ? | ||
474 | fotg210->reg + FOTG210_INEPMPSR(ep->epnum) : | ||
475 | fotg210->reg + FOTG210_OUTEPMPSR(ep->epnum); | ||
476 | value = ioread32(reg); | ||
477 | value |= INOUTEPMPSR_STL_EP; | ||
478 | iowrite32(value, reg); | ||
479 | } | ||
480 | |||
481 | static void fotg210_clear_epnstall(struct fotg210_ep *ep) | ||
482 | { | ||
483 | struct fotg210_udc *fotg210 = ep->fotg210; | ||
484 | u32 value; | ||
485 | void __iomem *reg; | ||
486 | |||
487 | reg = (ep->dir_in) ? | ||
488 | fotg210->reg + FOTG210_INEPMPSR(ep->epnum) : | ||
489 | fotg210->reg + FOTG210_OUTEPMPSR(ep->epnum); | ||
490 | value = ioread32(reg); | ||
491 | value &= ~INOUTEPMPSR_STL_EP; | ||
492 | iowrite32(value, reg); | ||
493 | } | ||
494 | |||
495 | static int fotg210_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedge) | ||
496 | { | ||
497 | struct fotg210_ep *ep; | ||
498 | struct fotg210_udc *fotg210; | ||
499 | unsigned long flags; | ||
500 | int ret = 0; | ||
501 | |||
502 | ep = container_of(_ep, struct fotg210_ep, ep); | ||
503 | |||
504 | fotg210 = ep->fotg210; | ||
505 | |||
506 | spin_lock_irqsave(&ep->fotg210->lock, flags); | ||
507 | |||
508 | if (value) { | ||
509 | fotg210_set_epnstall(ep); | ||
510 | ep->stall = 1; | ||
511 | if (wedge) | ||
512 | ep->wedged = 1; | ||
513 | } else { | ||
514 | fotg210_reset_tseq(fotg210, ep->epnum); | ||
515 | fotg210_clear_epnstall(ep); | ||
516 | ep->stall = 0; | ||
517 | ep->wedged = 0; | ||
518 | if (!list_empty(&ep->queue)) | ||
519 | fotg210_enable_fifo_int(ep); | ||
520 | } | ||
521 | |||
522 | spin_unlock_irqrestore(&ep->fotg210->lock, flags); | ||
523 | return ret; | ||
524 | } | ||
525 | |||
526 | static int fotg210_ep_set_halt(struct usb_ep *_ep, int value) | ||
527 | { | ||
528 | return fotg210_set_halt_and_wedge(_ep, value, 0); | ||
529 | } | ||
530 | |||
531 | static int fotg210_ep_set_wedge(struct usb_ep *_ep) | ||
532 | { | ||
533 | return fotg210_set_halt_and_wedge(_ep, 1, 1); | ||
534 | } | ||
535 | |||
536 | static void fotg210_ep_fifo_flush(struct usb_ep *_ep) | ||
537 | { | ||
538 | } | ||
539 | |||
540 | static struct usb_ep_ops fotg210_ep_ops = { | ||
541 | .enable = fotg210_ep_enable, | ||
542 | .disable = fotg210_ep_disable, | ||
543 | |||
544 | .alloc_request = fotg210_ep_alloc_request, | ||
545 | .free_request = fotg210_ep_free_request, | ||
546 | |||
547 | .queue = fotg210_ep_queue, | ||
548 | .dequeue = fotg210_ep_dequeue, | ||
549 | |||
550 | .set_halt = fotg210_ep_set_halt, | ||
551 | .fifo_flush = fotg210_ep_fifo_flush, | ||
552 | .set_wedge = fotg210_ep_set_wedge, | ||
553 | }; | ||
554 | |||
555 | static void fotg210_clear_tx0byte(struct fotg210_udc *fotg210) | ||
556 | { | ||
557 | u32 value = ioread32(fotg210->reg + FOTG210_TX0BYTE); | ||
558 | |||
559 | value &= ~(TX0BYTE_EP1 | TX0BYTE_EP2 | TX0BYTE_EP3 | ||
560 | | TX0BYTE_EP4); | ||
561 | iowrite32(value, fotg210->reg + FOTG210_TX0BYTE); | ||
562 | } | ||
563 | |||
564 | static void fotg210_clear_rx0byte(struct fotg210_udc *fotg210) | ||
565 | { | ||
566 | u32 value = ioread32(fotg210->reg + FOTG210_RX0BYTE); | ||
567 | |||
568 | value &= ~(RX0BYTE_EP1 | RX0BYTE_EP2 | RX0BYTE_EP3 | ||
569 | | RX0BYTE_EP4); | ||
570 | iowrite32(value, fotg210->reg + FOTG210_RX0BYTE); | ||
571 | } | ||
572 | |||
573 | /* read 8-byte setup packet only */ | ||
574 | static void fotg210_rdsetupp(struct fotg210_udc *fotg210, | ||
575 | u8 *buffer) | ||
576 | { | ||
577 | int i = 0; | ||
578 | u8 *tmp = buffer; | ||
579 | u32 data; | ||
580 | u32 length = 8; | ||
581 | |||
582 | iowrite32(DMATFNR_ACC_CXF, fotg210->reg + FOTG210_DMATFNR); | ||
583 | |||
584 | for (i = (length >> 2); i > 0; i--) { | ||
585 | data = ioread32(fotg210->reg + FOTG210_CXPORT); | ||
586 | *tmp = data & 0xFF; | ||
587 | *(tmp + 1) = (data >> 8) & 0xFF; | ||
588 | *(tmp + 2) = (data >> 16) & 0xFF; | ||
589 | *(tmp + 3) = (data >> 24) & 0xFF; | ||
590 | tmp = tmp + 4; | ||
591 | } | ||
592 | |||
593 | switch (length % 4) { | ||
594 | case 1: | ||
595 | data = ioread32(fotg210->reg + FOTG210_CXPORT); | ||
596 | *tmp = data & 0xFF; | ||
597 | break; | ||
598 | case 2: | ||
599 | data = ioread32(fotg210->reg + FOTG210_CXPORT); | ||
600 | *tmp = data & 0xFF; | ||
601 | *(tmp + 1) = (data >> 8) & 0xFF; | ||
602 | break; | ||
603 | case 3: | ||
604 | data = ioread32(fotg210->reg + FOTG210_CXPORT); | ||
605 | *tmp = data & 0xFF; | ||
606 | *(tmp + 1) = (data >> 8) & 0xFF; | ||
607 | *(tmp + 2) = (data >> 16) & 0xFF; | ||
608 | break; | ||
609 | default: | ||
610 | break; | ||
611 | } | ||
612 | |||
613 | iowrite32(DMATFNR_DISDMA, fotg210->reg + FOTG210_DMATFNR); | ||
614 | } | ||
615 | |||
616 | static void fotg210_set_configuration(struct fotg210_udc *fotg210) | ||
617 | { | ||
618 | u32 value = ioread32(fotg210->reg + FOTG210_DAR); | ||
619 | |||
620 | value |= DAR_AFT_CONF; | ||
621 | iowrite32(value, fotg210->reg + FOTG210_DAR); | ||
622 | } | ||
623 | |||
624 | static void fotg210_set_dev_addr(struct fotg210_udc *fotg210, u32 addr) | ||
625 | { | ||
626 | u32 value = ioread32(fotg210->reg + FOTG210_DAR); | ||
627 | |||
628 | value |= (addr & 0x7F); | ||
629 | iowrite32(value, fotg210->reg + FOTG210_DAR); | ||
630 | } | ||
631 | |||
632 | static void fotg210_set_cxstall(struct fotg210_udc *fotg210) | ||
633 | { | ||
634 | u32 value = ioread32(fotg210->reg + FOTG210_DCFESR); | ||
635 | |||
636 | value |= DCFESR_CX_STL; | ||
637 | iowrite32(value, fotg210->reg + FOTG210_DCFESR); | ||
638 | } | ||
639 | |||
640 | static void fotg210_request_error(struct fotg210_udc *fotg210) | ||
641 | { | ||
642 | fotg210_set_cxstall(fotg210); | ||
643 | pr_err("request error!!\n"); | ||
644 | } | ||
645 | |||
646 | static void fotg210_set_address(struct fotg210_udc *fotg210, | ||
647 | struct usb_ctrlrequest *ctrl) | ||
648 | { | ||
649 | if (ctrl->wValue >= 0x0100) { | ||
650 | fotg210_request_error(fotg210); | ||
651 | } else { | ||
652 | fotg210_set_dev_addr(fotg210, ctrl->wValue); | ||
653 | fotg210_set_cxdone(fotg210); | ||
654 | } | ||
655 | } | ||
656 | |||
657 | static void fotg210_set_feature(struct fotg210_udc *fotg210, | ||
658 | struct usb_ctrlrequest *ctrl) | ||
659 | { | ||
660 | switch (ctrl->bRequestType & USB_RECIP_MASK) { | ||
661 | case USB_RECIP_DEVICE: | ||
662 | fotg210_set_cxdone(fotg210); | ||
663 | break; | ||
664 | case USB_RECIP_INTERFACE: | ||
665 | fotg210_set_cxdone(fotg210); | ||
666 | break; | ||
667 | case USB_RECIP_ENDPOINT: { | ||
668 | u8 epnum; | ||
669 | epnum = le16_to_cpu(ctrl->wIndex) & USB_ENDPOINT_NUMBER_MASK; | ||
670 | if (epnum) | ||
671 | fotg210_set_epnstall(fotg210->ep[epnum]); | ||
672 | else | ||
673 | fotg210_set_cxstall(fotg210); | ||
674 | fotg210_set_cxdone(fotg210); | ||
675 | } | ||
676 | break; | ||
677 | default: | ||
678 | fotg210_request_error(fotg210); | ||
679 | break; | ||
680 | } | ||
681 | } | ||
682 | |||
683 | static void fotg210_clear_feature(struct fotg210_udc *fotg210, | ||
684 | struct usb_ctrlrequest *ctrl) | ||
685 | { | ||
686 | struct fotg210_ep *ep = | ||
687 | fotg210->ep[ctrl->wIndex & USB_ENDPOINT_NUMBER_MASK]; | ||
688 | |||
689 | switch (ctrl->bRequestType & USB_RECIP_MASK) { | ||
690 | case USB_RECIP_DEVICE: | ||
691 | fotg210_set_cxdone(fotg210); | ||
692 | break; | ||
693 | case USB_RECIP_INTERFACE: | ||
694 | fotg210_set_cxdone(fotg210); | ||
695 | break; | ||
696 | case USB_RECIP_ENDPOINT: | ||
697 | if (ctrl->wIndex & USB_ENDPOINT_NUMBER_MASK) { | ||
698 | if (ep->wedged) { | ||
699 | fotg210_set_cxdone(fotg210); | ||
700 | break; | ||
701 | } | ||
702 | if (ep->stall) | ||
703 | fotg210_set_halt_and_wedge(&ep->ep, 0, 0); | ||
704 | } | ||
705 | fotg210_set_cxdone(fotg210); | ||
706 | break; | ||
707 | default: | ||
708 | fotg210_request_error(fotg210); | ||
709 | break; | ||
710 | } | ||
711 | } | ||
712 | |||
713 | static int fotg210_is_epnstall(struct fotg210_ep *ep) | ||
714 | { | ||
715 | struct fotg210_udc *fotg210 = ep->fotg210; | ||
716 | u32 value; | ||
717 | void __iomem *reg; | ||
718 | |||
719 | reg = (ep->dir_in) ? | ||
720 | fotg210->reg + FOTG210_INEPMPSR(ep->epnum) : | ||
721 | fotg210->reg + FOTG210_OUTEPMPSR(ep->epnum); | ||
722 | value = ioread32(reg); | ||
723 | return value & INOUTEPMPSR_STL_EP ? 1 : 0; | ||
724 | } | ||
725 | |||
726 | static void fotg210_get_status(struct fotg210_udc *fotg210, | ||
727 | struct usb_ctrlrequest *ctrl) | ||
728 | { | ||
729 | u8 epnum; | ||
730 | |||
731 | switch (ctrl->bRequestType & USB_RECIP_MASK) { | ||
732 | case USB_RECIP_DEVICE: | ||
733 | fotg210->ep0_data = 1 << USB_DEVICE_SELF_POWERED; | ||
734 | break; | ||
735 | case USB_RECIP_INTERFACE: | ||
736 | fotg210->ep0_data = 0; | ||
737 | break; | ||
738 | case USB_RECIP_ENDPOINT: | ||
739 | epnum = ctrl->wIndex & USB_ENDPOINT_NUMBER_MASK; | ||
740 | if (epnum) | ||
741 | fotg210->ep0_data = | ||
742 | fotg210_is_epnstall(fotg210->ep[epnum]) | ||
743 | << USB_ENDPOINT_HALT; | ||
744 | else | ||
745 | fotg210_request_error(fotg210); | ||
746 | break; | ||
747 | |||
748 | default: | ||
749 | fotg210_request_error(fotg210); | ||
750 | return; /* exit */ | ||
751 | } | ||
752 | |||
753 | fotg210->ep0_req->buf = &fotg210->ep0_data; | ||
754 | fotg210->ep0_req->length = 2; | ||
755 | |||
756 | spin_unlock(&fotg210->lock); | ||
757 | fotg210_ep_queue(fotg210->gadget.ep0, fotg210->ep0_req, GFP_KERNEL); | ||
758 | spin_lock(&fotg210->lock); | ||
759 | } | ||
760 | |||
761 | static int fotg210_setup_packet(struct fotg210_udc *fotg210, | ||
762 | struct usb_ctrlrequest *ctrl) | ||
763 | { | ||
764 | u8 *p = (u8 *)ctrl; | ||
765 | u8 ret = 0; | ||
766 | |||
767 | fotg210_rdsetupp(fotg210, p); | ||
768 | |||
769 | fotg210->ep[0]->dir_in = ctrl->bRequestType & USB_DIR_IN; | ||
770 | |||
771 | if (fotg210->gadget.speed == USB_SPEED_UNKNOWN) { | ||
772 | u32 value = ioread32(fotg210->reg + FOTG210_DMCR); | ||
773 | fotg210->gadget.speed = value & DMCR_HS_EN ? | ||
774 | USB_SPEED_HIGH : USB_SPEED_FULL; | ||
775 | } | ||
776 | |||
777 | /* check request */ | ||
778 | if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) { | ||
779 | switch (ctrl->bRequest) { | ||
780 | case USB_REQ_GET_STATUS: | ||
781 | fotg210_get_status(fotg210, ctrl); | ||
782 | break; | ||
783 | case USB_REQ_CLEAR_FEATURE: | ||
784 | fotg210_clear_feature(fotg210, ctrl); | ||
785 | break; | ||
786 | case USB_REQ_SET_FEATURE: | ||
787 | fotg210_set_feature(fotg210, ctrl); | ||
788 | break; | ||
789 | case USB_REQ_SET_ADDRESS: | ||
790 | fotg210_set_address(fotg210, ctrl); | ||
791 | break; | ||
792 | case USB_REQ_SET_CONFIGURATION: | ||
793 | fotg210_set_configuration(fotg210); | ||
794 | ret = 1; | ||
795 | break; | ||
796 | default: | ||
797 | ret = 1; | ||
798 | break; | ||
799 | } | ||
800 | } else { | ||
801 | ret = 1; | ||
802 | } | ||
803 | |||
804 | return ret; | ||
805 | } | ||
806 | |||
807 | static void fotg210_ep0out(struct fotg210_udc *fotg210) | ||
808 | { | ||
809 | struct fotg210_ep *ep = fotg210->ep[0]; | ||
810 | |||
811 | if (!list_empty(&ep->queue) && !ep->dir_in) { | ||
812 | struct fotg210_request *req; | ||
813 | |||
814 | req = list_first_entry(&ep->queue, | ||
815 | struct fotg210_request, queue); | ||
816 | |||
817 | if (req->req.length) | ||
818 | fotg210_start_dma(ep, req); | ||
819 | |||
820 | if ((req->req.length - req->req.actual) < ep->ep.maxpacket) | ||
821 | fotg210_done(ep, req, 0); | ||
822 | } else { | ||
823 | pr_err("%s : empty queue\n", __func__); | ||
824 | } | ||
825 | } | ||
826 | |||
827 | static void fotg210_ep0in(struct fotg210_udc *fotg210) | ||
828 | { | ||
829 | struct fotg210_ep *ep = fotg210->ep[0]; | ||
830 | |||
831 | if ((!list_empty(&ep->queue)) && (ep->dir_in)) { | ||
832 | struct fotg210_request *req; | ||
833 | |||
834 | req = list_entry(ep->queue.next, | ||
835 | struct fotg210_request, queue); | ||
836 | |||
837 | if (req->req.length) | ||
838 | fotg210_start_dma(ep, req); | ||
839 | |||
840 | if ((req->req.length - req->req.actual) < ep->ep.maxpacket) | ||
841 | fotg210_done(ep, req, 0); | ||
842 | } else { | ||
843 | fotg210_set_cxdone(fotg210); | ||
844 | } | ||
845 | } | ||
846 | |||
847 | static void fotg210_clear_comabt_int(struct fotg210_udc *fotg210) | ||
848 | { | ||
849 | u32 value = ioread32(fotg210->reg + FOTG210_DISGR0); | ||
850 | |||
851 | value &= ~DISGR0_CX_COMABT_INT; | ||
852 | iowrite32(value, fotg210->reg + FOTG210_DISGR0); | ||
853 | } | ||
854 | |||
855 | static void fotg210_in_fifo_handler(struct fotg210_ep *ep) | ||
856 | { | ||
857 | struct fotg210_request *req = list_entry(ep->queue.next, | ||
858 | struct fotg210_request, queue); | ||
859 | |||
860 | if (req->req.length) | ||
861 | fotg210_start_dma(ep, req); | ||
862 | fotg210_done(ep, req, 0); | ||
863 | } | ||
864 | |||
865 | static void fotg210_out_fifo_handler(struct fotg210_ep *ep) | ||
866 | { | ||
867 | struct fotg210_request *req = list_entry(ep->queue.next, | ||
868 | struct fotg210_request, queue); | ||
869 | |||
870 | fotg210_start_dma(ep, req); | ||
871 | |||
872 | /* finish out transfer */ | ||
873 | if (req->req.length == req->req.actual || | ||
874 | req->req.actual < ep->ep.maxpacket) | ||
875 | fotg210_done(ep, req, 0); | ||
876 | } | ||
877 | |||
878 | static irqreturn_t fotg210_irq(int irq, void *_fotg210) | ||
879 | { | ||
880 | struct fotg210_udc *fotg210 = _fotg210; | ||
881 | u32 int_grp = ioread32(fotg210->reg + FOTG210_DIGR); | ||
882 | u32 int_msk = ioread32(fotg210->reg + FOTG210_DMIGR); | ||
883 | |||
884 | int_grp &= ~int_msk; | ||
885 | |||
886 | spin_lock(&fotg210->lock); | ||
887 | |||
888 | if (int_grp & DIGR_INT_G2) { | ||
889 | void __iomem *reg = fotg210->reg + FOTG210_DISGR2; | ||
890 | u32 int_grp2 = ioread32(reg); | ||
891 | u32 int_msk2 = ioread32(fotg210->reg + FOTG210_DMISGR2); | ||
892 | u32 value; | ||
893 | |||
894 | int_grp2 &= ~int_msk2; | ||
895 | |||
896 | if (int_grp2 & DISGR2_USBRST_INT) { | ||
897 | value = ioread32(reg); | ||
898 | value &= ~DISGR2_USBRST_INT; | ||
899 | iowrite32(value, reg); | ||
900 | pr_info("fotg210 udc reset\n"); | ||
901 | } | ||
902 | if (int_grp2 & DISGR2_SUSP_INT) { | ||
903 | value = ioread32(reg); | ||
904 | value &= ~DISGR2_SUSP_INT; | ||
905 | iowrite32(value, reg); | ||
906 | pr_info("fotg210 udc suspend\n"); | ||
907 | } | ||
908 | if (int_grp2 & DISGR2_RESM_INT) { | ||
909 | value = ioread32(reg); | ||
910 | value &= ~DISGR2_RESM_INT; | ||
911 | iowrite32(value, reg); | ||
912 | pr_info("fotg210 udc resume\n"); | ||
913 | } | ||
914 | if (int_grp2 & DISGR2_ISO_SEQ_ERR_INT) { | ||
915 | value = ioread32(reg); | ||
916 | value &= ~DISGR2_ISO_SEQ_ERR_INT; | ||
917 | iowrite32(value, reg); | ||
918 | pr_info("fotg210 iso sequence error\n"); | ||
919 | } | ||
920 | if (int_grp2 & DISGR2_ISO_SEQ_ABORT_INT) { | ||
921 | value = ioread32(reg); | ||
922 | value &= ~DISGR2_ISO_SEQ_ABORT_INT; | ||
923 | iowrite32(value, reg); | ||
924 | pr_info("fotg210 iso sequence abort\n"); | ||
925 | } | ||
926 | if (int_grp2 & DISGR2_TX0BYTE_INT) { | ||
927 | fotg210_clear_tx0byte(fotg210); | ||
928 | value = ioread32(reg); | ||
929 | value &= ~DISGR2_TX0BYTE_INT; | ||
930 | iowrite32(value, reg); | ||
931 | pr_info("fotg210 transferred 0 byte\n"); | ||
932 | } | ||
933 | if (int_grp2 & DISGR2_RX0BYTE_INT) { | ||
934 | fotg210_clear_rx0byte(fotg210); | ||
935 | value = ioread32(reg); | ||
936 | value &= ~DISGR2_RX0BYTE_INT; | ||
937 | iowrite32(value, reg); | ||
938 | pr_info("fotg210 received 0 byte\n"); | ||
939 | } | ||
940 | if (int_grp2 & DISGR2_DMA_ERROR) { | ||
941 | value = ioread32(reg); | ||
942 | value &= ~DISGR2_DMA_ERROR; | ||
943 | iowrite32(value, reg); | ||
944 | } | ||
945 | } | ||
946 | |||
947 | if (int_grp & DIGR_INT_G0) { | ||
948 | void __iomem *reg = fotg210->reg + FOTG210_DISGR0; | ||
949 | u32 int_grp0 = ioread32(reg); | ||
950 | u32 int_msk0 = ioread32(fotg210->reg + FOTG210_DMISGR0); | ||
951 | struct usb_ctrlrequest ctrl; | ||
952 | |||
953 | int_grp0 &= ~int_msk0; | ||
954 | |||
955 | /* the highest priority in this source register */ | ||
956 | if (int_grp0 & DISGR0_CX_COMABT_INT) { | ||
957 | fotg210_clear_comabt_int(fotg210); | ||
958 | pr_info("fotg210 CX command abort\n"); | ||
959 | } | ||
960 | |||
961 | if (int_grp0 & DISGR0_CX_SETUP_INT) { | ||
962 | if (fotg210_setup_packet(fotg210, &ctrl)) { | ||
963 | spin_unlock(&fotg210->lock); | ||
964 | if (fotg210->driver->setup(&fotg210->gadget, | ||
965 | &ctrl) < 0) | ||
966 | fotg210_set_cxstall(fotg210); | ||
967 | spin_lock(&fotg210->lock); | ||
968 | } | ||
969 | } | ||
970 | if (int_grp0 & DISGR0_CX_COMEND_INT) | ||
971 | pr_info("fotg210 cmd end\n"); | ||
972 | |||
973 | if (int_grp0 & DISGR0_CX_IN_INT) | ||
974 | fotg210_ep0in(fotg210); | ||
975 | |||
976 | if (int_grp0 & DISGR0_CX_OUT_INT) | ||
977 | fotg210_ep0out(fotg210); | ||
978 | |||
979 | if (int_grp0 & DISGR0_CX_COMFAIL_INT) { | ||
980 | fotg210_set_cxstall(fotg210); | ||
981 | pr_info("fotg210 ep0 fail\n"); | ||
982 | } | ||
983 | } | ||
984 | |||
985 | if (int_grp & DIGR_INT_G1) { | ||
986 | void __iomem *reg = fotg210->reg + FOTG210_DISGR1; | ||
987 | u32 int_grp1 = ioread32(reg); | ||
988 | u32 int_msk1 = ioread32(fotg210->reg + FOTG210_DMISGR1); | ||
989 | int fifo; | ||
990 | |||
991 | int_grp1 &= ~int_msk1; | ||
992 | |||
993 | for (fifo = 0; fifo < FOTG210_MAX_FIFO_NUM; fifo++) { | ||
994 | if (int_grp1 & DISGR1_IN_INT(fifo)) | ||
995 | fotg210_in_fifo_handler(fotg210->ep[fifo + 1]); | ||
996 | |||
997 | if ((int_grp1 & DISGR1_OUT_INT(fifo)) || | ||
998 | (int_grp1 & DISGR1_SPK_INT(fifo))) | ||
999 | fotg210_out_fifo_handler(fotg210->ep[fifo + 1]); | ||
1000 | } | ||
1001 | } | ||
1002 | |||
1003 | spin_unlock(&fotg210->lock); | ||
1004 | |||
1005 | return IRQ_HANDLED; | ||
1006 | } | ||
1007 | |||
1008 | static void fotg210_disable_unplug(struct fotg210_udc *fotg210) | ||
1009 | { | ||
1010 | u32 reg = ioread32(fotg210->reg + FOTG210_PHYTMSR); | ||
1011 | |||
1012 | reg &= ~PHYTMSR_UNPLUG; | ||
1013 | iowrite32(reg, fotg210->reg + FOTG210_PHYTMSR); | ||
1014 | } | ||
1015 | |||
1016 | static int fotg210_udc_start(struct usb_gadget *g, | ||
1017 | struct usb_gadget_driver *driver) | ||
1018 | { | ||
1019 | struct fotg210_udc *fotg210 = gadget_to_fotg210(g); | ||
1020 | u32 value; | ||
1021 | |||
1022 | /* hook up the driver */ | ||
1023 | driver->driver.bus = NULL; | ||
1024 | fotg210->driver = driver; | ||
1025 | |||
1026 | /* enable device global interrupt */ | ||
1027 | value = ioread32(fotg210->reg + FOTG210_DMCR); | ||
1028 | value |= DMCR_GLINT_EN; | ||
1029 | iowrite32(value, fotg210->reg + FOTG210_DMCR); | ||
1030 | |||
1031 | return 0; | ||
1032 | } | ||
1033 | |||
1034 | static void fotg210_init(struct fotg210_udc *fotg210) | ||
1035 | { | ||
1036 | u32 value; | ||
1037 | |||
1038 | /* disable global interrupt and set int polarity to active high */ | ||
1039 | iowrite32(GMIR_MHC_INT | GMIR_MOTG_INT | GMIR_INT_POLARITY, | ||
1040 | fotg210->reg + FOTG210_GMIR); | ||
1041 | |||
1042 | /* disable device global interrupt */ | ||
1043 | value = ioread32(fotg210->reg + FOTG210_DMCR); | ||
1044 | value &= ~DMCR_GLINT_EN; | ||
1045 | iowrite32(value, fotg210->reg + FOTG210_DMCR); | ||
1046 | |||
1047 | /* disable all fifo interrupt */ | ||
1048 | iowrite32(~(u32)0, fotg210->reg + FOTG210_DMISGR1); | ||
1049 | |||
1050 | /* disable cmd end */ | ||
1051 | value = ioread32(fotg210->reg + FOTG210_DMISGR0); | ||
1052 | value |= DMISGR0_MCX_COMEND; | ||
1053 | iowrite32(value, fotg210->reg + FOTG210_DMISGR0); | ||
1054 | } | ||
1055 | |||
1056 | static int fotg210_udc_stop(struct usb_gadget *g, | ||
1057 | struct usb_gadget_driver *driver) | ||
1058 | { | ||
1059 | struct fotg210_udc *fotg210 = gadget_to_fotg210(g); | ||
1060 | unsigned long flags; | ||
1061 | |||
1062 | spin_lock_irqsave(&fotg210->lock, flags); | ||
1063 | |||
1064 | fotg210_init(fotg210); | ||
1065 | fotg210->driver = NULL; | ||
1066 | |||
1067 | spin_unlock_irqrestore(&fotg210->lock, flags); | ||
1068 | |||
1069 | return 0; | ||
1070 | } | ||
1071 | |||
1072 | static struct usb_gadget_ops fotg210_gadget_ops = { | ||
1073 | .udc_start = fotg210_udc_start, | ||
1074 | .udc_stop = fotg210_udc_stop, | ||
1075 | }; | ||
1076 | |||
1077 | static int __exit fotg210_udc_remove(struct platform_device *pdev) | ||
1078 | { | ||
1079 | struct fotg210_udc *fotg210 = dev_get_drvdata(&pdev->dev); | ||
1080 | |||
1081 | usb_del_gadget_udc(&fotg210->gadget); | ||
1082 | iounmap(fotg210->reg); | ||
1083 | free_irq(platform_get_irq(pdev, 0), fotg210); | ||
1084 | |||
1085 | fotg210_ep_free_request(&fotg210->ep[0]->ep, fotg210->ep0_req); | ||
1086 | kfree(fotg210); | ||
1087 | |||
1088 | return 0; | ||
1089 | } | ||
1090 | |||
1091 | static int __init fotg210_udc_probe(struct platform_device *pdev) | ||
1092 | { | ||
1093 | struct resource *res, *ires; | ||
1094 | struct fotg210_udc *fotg210 = NULL; | ||
1095 | struct fotg210_ep *_ep[FOTG210_MAX_NUM_EP]; | ||
1096 | int ret = 0; | ||
1097 | int i; | ||
1098 | |||
1099 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1100 | if (!res) { | ||
1101 | pr_err("platform_get_resource error.\n"); | ||
1102 | return -ENODEV; | ||
1103 | } | ||
1104 | |||
1105 | ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
1106 | if (!ires) { | ||
1107 | pr_err("platform_get_resource IORESOURCE_IRQ error.\n"); | ||
1108 | return -ENODEV; | ||
1109 | } | ||
1110 | |||
1111 | ret = -ENOMEM; | ||
1112 | |||
1113 | /* initialize udc */ | ||
1114 | fotg210 = kzalloc(sizeof(struct fotg210_udc), GFP_KERNEL); | ||
1115 | if (fotg210 == NULL) { | ||
1116 | pr_err("kzalloc error\n"); | ||
1117 | goto err_alloc; | ||
1118 | } | ||
1119 | |||
1120 | for (i = 0; i < FOTG210_MAX_NUM_EP; i++) { | ||
1121 | _ep[i] = kzalloc(sizeof(struct fotg210_ep), GFP_KERNEL); | ||
1122 | if (_ep[i] == NULL) { | ||
1123 | pr_err("_ep kzalloc error\n"); | ||
1124 | goto err_alloc; | ||
1125 | } | ||
1126 | fotg210->ep[i] = _ep[i]; | ||
1127 | } | ||
1128 | |||
1129 | fotg210->reg = ioremap(res->start, resource_size(res)); | ||
1130 | if (fotg210->reg == NULL) { | ||
1131 | pr_err("ioremap error.\n"); | ||
1132 | goto err_map; | ||
1133 | } | ||
1134 | |||
1135 | spin_lock_init(&fotg210->lock); | ||
1136 | |||
1137 | dev_set_drvdata(&pdev->dev, fotg210); | ||
1138 | |||
1139 | fotg210->gadget.ops = &fotg210_gadget_ops; | ||
1140 | |||
1141 | fotg210->gadget.max_speed = USB_SPEED_HIGH; | ||
1142 | fotg210->gadget.dev.parent = &pdev->dev; | ||
1143 | fotg210->gadget.dev.dma_mask = pdev->dev.dma_mask; | ||
1144 | fotg210->gadget.name = udc_name; | ||
1145 | |||
1146 | INIT_LIST_HEAD(&fotg210->gadget.ep_list); | ||
1147 | |||
1148 | for (i = 0; i < FOTG210_MAX_NUM_EP; i++) { | ||
1149 | struct fotg210_ep *ep = fotg210->ep[i]; | ||
1150 | |||
1151 | if (i) { | ||
1152 | INIT_LIST_HEAD(&fotg210->ep[i]->ep.ep_list); | ||
1153 | list_add_tail(&fotg210->ep[i]->ep.ep_list, | ||
1154 | &fotg210->gadget.ep_list); | ||
1155 | } | ||
1156 | ep->fotg210 = fotg210; | ||
1157 | INIT_LIST_HEAD(&ep->queue); | ||
1158 | ep->ep.name = fotg210_ep_name[i]; | ||
1159 | ep->ep.ops = &fotg210_ep_ops; | ||
1160 | } | ||
1161 | fotg210->ep[0]->ep.maxpacket = 0x40; | ||
1162 | fotg210->gadget.ep0 = &fotg210->ep[0]->ep; | ||
1163 | INIT_LIST_HEAD(&fotg210->gadget.ep0->ep_list); | ||
1164 | |||
1165 | fotg210->ep0_req = fotg210_ep_alloc_request(&fotg210->ep[0]->ep, | ||
1166 | GFP_KERNEL); | ||
1167 | if (fotg210->ep0_req == NULL) | ||
1168 | goto err_req; | ||
1169 | |||
1170 | fotg210_init(fotg210); | ||
1171 | |||
1172 | fotg210_disable_unplug(fotg210); | ||
1173 | |||
1174 | ret = request_irq(ires->start, fotg210_irq, IRQF_SHARED, | ||
1175 | udc_name, fotg210); | ||
1176 | if (ret < 0) { | ||
1177 | pr_err("request_irq error (%d)\n", ret); | ||
1178 | goto err_irq; | ||
1179 | } | ||
1180 | |||
1181 | ret = usb_add_gadget_udc(&pdev->dev, &fotg210->gadget); | ||
1182 | if (ret) | ||
1183 | goto err_add_udc; | ||
1184 | |||
1185 | dev_info(&pdev->dev, "version %s\n", DRIVER_VERSION); | ||
1186 | |||
1187 | return 0; | ||
1188 | |||
1189 | err_add_udc: | ||
1190 | err_irq: | ||
1191 | free_irq(ires->start, fotg210); | ||
1192 | |||
1193 | err_req: | ||
1194 | fotg210_ep_free_request(&fotg210->ep[0]->ep, fotg210->ep0_req); | ||
1195 | |||
1196 | err_map: | ||
1197 | if (fotg210->reg) | ||
1198 | iounmap(fotg210->reg); | ||
1199 | |||
1200 | err_alloc: | ||
1201 | kfree(fotg210); | ||
1202 | |||
1203 | return ret; | ||
1204 | } | ||
1205 | |||
1206 | static struct platform_driver fotg210_driver = { | ||
1207 | .driver = { | ||
1208 | .name = (char *)udc_name, | ||
1209 | .owner = THIS_MODULE, | ||
1210 | }, | ||
1211 | .probe = fotg210_udc_probe, | ||
1212 | .remove = fotg210_udc_remove, | ||
1213 | }; | ||
1214 | |||
1215 | module_platform_driver(fotg210_driver); | ||
1216 | |||
1217 | MODULE_AUTHOR("Yuan-Hsin Chen <yhchen@faraday-tech.com>"); | ||
1218 | MODULE_LICENSE("GPL"); | ||
1219 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
diff --git a/drivers/usb/gadget/fotg210.h b/drivers/usb/gadget/fotg210.h new file mode 100644 index 000000000000..bbf991bcbe7c --- /dev/null +++ b/drivers/usb/gadget/fotg210.h | |||
@@ -0,0 +1,253 @@ | |||
1 | /* | ||
2 | * Faraday FOTG210 USB OTG controller | ||
3 | * | ||
4 | * Copyright (C) 2013 Faraday Technology Corporation | ||
5 | * Author: Yuan-Hsin Chen <yhchen@faraday-tech.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | |||
15 | #define FOTG210_MAX_NUM_EP 5 /* ep0...ep4 */ | ||
16 | #define FOTG210_MAX_FIFO_NUM 4 /* fifo0...fifo4 */ | ||
17 | |||
18 | /* Global Mask of HC/OTG/DEV interrupt Register(0xC4) */ | ||
19 | #define FOTG210_GMIR 0xC4 | ||
20 | #define GMIR_INT_POLARITY 0x8 /*Active High*/ | ||
21 | #define GMIR_MHC_INT 0x4 | ||
22 | #define GMIR_MOTG_INT 0x2 | ||
23 | #define GMIR_MDEV_INT 0x1 | ||
24 | |||
25 | /* Device Main Control Register(0x100) */ | ||
26 | #define FOTG210_DMCR 0x100 | ||
27 | #define DMCR_HS_EN (1 << 6) | ||
28 | #define DMCR_CHIP_EN (1 << 5) | ||
29 | #define DMCR_SFRST (1 << 4) | ||
30 | #define DMCR_GOSUSP (1 << 3) | ||
31 | #define DMCR_GLINT_EN (1 << 2) | ||
32 | #define DMCR_HALF_SPEED (1 << 1) | ||
33 | #define DMCR_CAP_RMWAKUP (1 << 0) | ||
34 | |||
35 | /* Device Address Register(0x104) */ | ||
36 | #define FOTG210_DAR 0x104 | ||
37 | #define DAR_AFT_CONF (1 << 7) | ||
38 | |||
39 | /* Device Test Register(0x108) */ | ||
40 | #define FOTG210_DTR 0x108 | ||
41 | #define DTR_TST_CLRFF (1 << 0) | ||
42 | |||
43 | /* PHY Test Mode Selector register(0x114) */ | ||
44 | #define FOTG210_PHYTMSR 0x114 | ||
45 | #define PHYTMSR_TST_PKT (1 << 4) | ||
46 | #define PHYTMSR_TST_SE0NAK (1 << 3) | ||
47 | #define PHYTMSR_TST_KSTA (1 << 2) | ||
48 | #define PHYTMSR_TST_JSTA (1 << 1) | ||
49 | #define PHYTMSR_UNPLUG (1 << 0) | ||
50 | |||
51 | /* Cx configuration and FIFO Empty Status register(0x120) */ | ||
52 | #define FOTG210_DCFESR 0x120 | ||
53 | #define DCFESR_FIFO_EMPTY(fifo) (1 << 8 << (fifo)) | ||
54 | #define DCFESR_CX_EMP (1 << 5) | ||
55 | #define DCFESR_CX_CLR (1 << 3) | ||
56 | #define DCFESR_CX_STL (1 << 2) | ||
57 | #define DCFESR_TST_PKDONE (1 << 1) | ||
58 | #define DCFESR_CX_DONE (1 << 0) | ||
59 | |||
60 | /* Device IDLE Counter Register(0x124) */ | ||
61 | #define FOTG210_DICR 0x124 | ||
62 | |||
63 | /* Device Mask of Interrupt Group Register (0x130) */ | ||
64 | #define FOTG210_DMIGR 0x130 | ||
65 | #define DMIGR_MINT_G0 (1 << 0) | ||
66 | |||
67 | /* Device Mask of Interrupt Source Group 0(0x134) */ | ||
68 | #define FOTG210_DMISGR0 0x134 | ||
69 | #define DMISGR0_MCX_COMEND (1 << 3) | ||
70 | #define DMISGR0_MCX_OUT_INT (1 << 2) | ||
71 | #define DMISGR0_MCX_IN_INT (1 << 1) | ||
72 | #define DMISGR0_MCX_SETUP_INT (1 << 0) | ||
73 | |||
74 | /* Device Mask of Interrupt Source Group 1 Register(0x138)*/ | ||
75 | #define FOTG210_DMISGR1 0x138 | ||
76 | #define DMISGR1_MF3_IN_INT (1 << 19) | ||
77 | #define DMISGR1_MF2_IN_INT (1 << 18) | ||
78 | #define DMISGR1_MF1_IN_INT (1 << 17) | ||
79 | #define DMISGR1_MF0_IN_INT (1 << 16) | ||
80 | #define DMISGR1_MF_IN_INT(fifo) (1 << (16 + (fifo))) | ||
81 | #define DMISGR1_MF3_SPK_INT (1 << 7) | ||
82 | #define DMISGR1_MF3_OUT_INT (1 << 6) | ||
83 | #define DMISGR1_MF2_SPK_INT (1 << 5) | ||
84 | #define DMISGR1_MF2_OUT_INT (1 << 4) | ||
85 | #define DMISGR1_MF1_SPK_INT (1 << 3) | ||
86 | #define DMISGR1_MF1_OUT_INT (1 << 2) | ||
87 | #define DMISGR1_MF0_SPK_INT (1 << 1) | ||
88 | #define DMISGR1_MF0_OUT_INT (1 << 0) | ||
89 | #define DMISGR1_MF_OUTSPK_INT(fifo) (0x3 << (fifo) * 2) | ||
90 | |||
91 | /* Device Mask of Interrupt Source Group 2 Register (0x13C) */ | ||
92 | #define FOTG210_DMISGR2 0x13C | ||
93 | #define DMISGR2_MDMA_ERROR (1 << 8) | ||
94 | #define DMISGR2_MDMA_CMPLT (1 << 7) | ||
95 | |||
96 | /* Device Interrupt group Register (0x140) */ | ||
97 | #define FOTG210_DIGR 0x140 | ||
98 | #define DIGR_INT_G2 (1 << 2) | ||
99 | #define DIGR_INT_G1 (1 << 1) | ||
100 | #define DIGR_INT_G0 (1 << 0) | ||
101 | |||
102 | /* Device Interrupt Source Group 0 Register (0x144) */ | ||
103 | #define FOTG210_DISGR0 0x144 | ||
104 | #define DISGR0_CX_COMABT_INT (1 << 5) | ||
105 | #define DISGR0_CX_COMFAIL_INT (1 << 4) | ||
106 | #define DISGR0_CX_COMEND_INT (1 << 3) | ||
107 | #define DISGR0_CX_OUT_INT (1 << 2) | ||
108 | #define DISGR0_CX_IN_INT (1 << 1) | ||
109 | #define DISGR0_CX_SETUP_INT (1 << 0) | ||
110 | |||
111 | /* Device Interrupt Source Group 1 Register (0x148) */ | ||
112 | #define FOTG210_DISGR1 0x148 | ||
113 | #define DISGR1_OUT_INT(fifo) (1 << ((fifo) * 2)) | ||
114 | #define DISGR1_SPK_INT(fifo) (1 << 1 << ((fifo) * 2)) | ||
115 | #define DISGR1_IN_INT(fifo) (1 << 16 << (fifo)) | ||
116 | |||
117 | /* Device Interrupt Source Group 2 Register (0x14C) */ | ||
118 | #define FOTG210_DISGR2 0x14C | ||
119 | #define DISGR2_DMA_ERROR (1 << 8) | ||
120 | #define DISGR2_DMA_CMPLT (1 << 7) | ||
121 | #define DISGR2_RX0BYTE_INT (1 << 6) | ||
122 | #define DISGR2_TX0BYTE_INT (1 << 5) | ||
123 | #define DISGR2_ISO_SEQ_ABORT_INT (1 << 4) | ||
124 | #define DISGR2_ISO_SEQ_ERR_INT (1 << 3) | ||
125 | #define DISGR2_RESM_INT (1 << 2) | ||
126 | #define DISGR2_SUSP_INT (1 << 1) | ||
127 | #define DISGR2_USBRST_INT (1 << 0) | ||
128 | |||
129 | /* Device Receive Zero-Length Data Packet Register (0x150)*/ | ||
130 | #define FOTG210_RX0BYTE 0x150 | ||
131 | #define RX0BYTE_EP8 (1 << 7) | ||
132 | #define RX0BYTE_EP7 (1 << 6) | ||
133 | #define RX0BYTE_EP6 (1 << 5) | ||
134 | #define RX0BYTE_EP5 (1 << 4) | ||
135 | #define RX0BYTE_EP4 (1 << 3) | ||
136 | #define RX0BYTE_EP3 (1 << 2) | ||
137 | #define RX0BYTE_EP2 (1 << 1) | ||
138 | #define RX0BYTE_EP1 (1 << 0) | ||
139 | |||
140 | /* Device Transfer Zero-Length Data Packet Register (0x154)*/ | ||
141 | #define FOTG210_TX0BYTE 0x154 | ||
142 | #define TX0BYTE_EP8 (1 << 7) | ||
143 | #define TX0BYTE_EP7 (1 << 6) | ||
144 | #define TX0BYTE_EP6 (1 << 5) | ||
145 | #define TX0BYTE_EP5 (1 << 4) | ||
146 | #define TX0BYTE_EP4 (1 << 3) | ||
147 | #define TX0BYTE_EP3 (1 << 2) | ||
148 | #define TX0BYTE_EP2 (1 << 1) | ||
149 | #define TX0BYTE_EP1 (1 << 0) | ||
150 | |||
151 | /* Device IN Endpoint x MaxPacketSize Register(0x160+4*(x-1)) */ | ||
152 | #define FOTG210_INEPMPSR(ep) (0x160 + 4 * ((ep) - 1)) | ||
153 | #define INOUTEPMPSR_MPS(mps) ((mps) & 0x2FF) | ||
154 | #define INOUTEPMPSR_STL_EP (1 << 11) | ||
155 | #define INOUTEPMPSR_RESET_TSEQ (1 << 12) | ||
156 | |||
157 | /* Device OUT Endpoint x MaxPacketSize Register(0x180+4*(x-1)) */ | ||
158 | #define FOTG210_OUTEPMPSR(ep) (0x180 + 4 * ((ep) - 1)) | ||
159 | |||
160 | /* Device Endpoint 1~4 Map Register (0x1A0) */ | ||
161 | #define FOTG210_EPMAP 0x1A0 | ||
162 | #define EPMAP_FIFONO(ep, dir) \ | ||
163 | ((((ep) - 1) << ((ep) - 1) * 8) << ((dir) ? 0 : 4)) | ||
164 | #define EPMAP_FIFONOMSK(ep, dir) \ | ||
165 | ((3 << ((ep) - 1) * 8) << ((dir) ? 0 : 4)) | ||
166 | |||
167 | /* Device FIFO Map Register (0x1A8) */ | ||
168 | #define FOTG210_FIFOMAP 0x1A8 | ||
169 | #define FIFOMAP_DIROUT(fifo) (0x0 << 4 << (fifo) * 8) | ||
170 | #define FIFOMAP_DIRIN(fifo) (0x1 << 4 << (fifo) * 8) | ||
171 | #define FIFOMAP_BIDIR(fifo) (0x2 << 4 << (fifo) * 8) | ||
172 | #define FIFOMAP_NA(fifo) (0x3 << 4 << (fifo) * 8) | ||
173 | #define FIFOMAP_EPNO(ep) ((ep) << ((ep) - 1) * 8) | ||
174 | #define FIFOMAP_EPNOMSK(ep) (0xF << ((ep) - 1) * 8) | ||
175 | |||
176 | /* Device FIFO Confuguration Register (0x1AC) */ | ||
177 | #define FOTG210_FIFOCF 0x1AC | ||
178 | #define FIFOCF_TYPE(type, fifo) ((type) << (fifo) * 8) | ||
179 | #define FIFOCF_BLK_SIN(fifo) (0x0 << (fifo) * 8 << 2) | ||
180 | #define FIFOCF_BLK_DUB(fifo) (0x1 << (fifo) * 8 << 2) | ||
181 | #define FIFOCF_BLK_TRI(fifo) (0x2 << (fifo) * 8 << 2) | ||
182 | #define FIFOCF_BLKSZ_512(fifo) (0x0 << (fifo) * 8 << 4) | ||
183 | #define FIFOCF_BLKSZ_1024(fifo) (0x1 << (fifo) * 8 << 4) | ||
184 | #define FIFOCF_FIFO_EN(fifo) (0x1 << (fifo) * 8 << 5) | ||
185 | |||
186 | /* Device FIFO n Instruction and Byte Count Register (0x1B0+4*n) */ | ||
187 | #define FOTG210_FIBCR(fifo) (0x1B0 + (fifo) * 4) | ||
188 | #define FIBCR_BCFX 0x7FF | ||
189 | #define FIBCR_FFRST (1 << 12) | ||
190 | |||
191 | /* Device DMA Target FIFO Number Register (0x1C0) */ | ||
192 | #define FOTG210_DMATFNR 0x1C0 | ||
193 | #define DMATFNR_ACC_CXF (1 << 4) | ||
194 | #define DMATFNR_ACC_F3 (1 << 3) | ||
195 | #define DMATFNR_ACC_F2 (1 << 2) | ||
196 | #define DMATFNR_ACC_F1 (1 << 1) | ||
197 | #define DMATFNR_ACC_F0 (1 << 0) | ||
198 | #define DMATFNR_ACC_FN(fifo) (1 << (fifo)) | ||
199 | #define DMATFNR_DISDMA 0 | ||
200 | |||
201 | /* Device DMA Controller Parameter setting 1 Register (0x1C8) */ | ||
202 | #define FOTG210_DMACPSR1 0x1C8 | ||
203 | #define DMACPSR1_DMA_LEN(len) (((len) & 0xFFFF) << 8) | ||
204 | #define DMACPSR1_DMA_ABORT (1 << 3) | ||
205 | #define DMACPSR1_DMA_TYPE(dir_in) (((dir_in) ? 1 : 0) << 1) | ||
206 | #define DMACPSR1_DMA_START (1 << 0) | ||
207 | |||
208 | /* Device DMA Controller Parameter setting 2 Register (0x1CC) */ | ||
209 | #define FOTG210_DMACPSR2 0x1CC | ||
210 | |||
211 | /* Device DMA Controller Parameter setting 3 Register (0x1CC) */ | ||
212 | #define FOTG210_CXPORT 0x1D0 | ||
213 | |||
214 | struct fotg210_request { | ||
215 | struct usb_request req; | ||
216 | struct list_head queue; | ||
217 | }; | ||
218 | |||
219 | struct fotg210_ep { | ||
220 | struct usb_ep ep; | ||
221 | struct fotg210_udc *fotg210; | ||
222 | |||
223 | struct list_head queue; | ||
224 | unsigned stall:1; | ||
225 | unsigned wedged:1; | ||
226 | unsigned use_dma:1; | ||
227 | |||
228 | unsigned char epnum; | ||
229 | unsigned char type; | ||
230 | unsigned char dir_in; | ||
231 | unsigned int maxp; | ||
232 | const struct usb_endpoint_descriptor *desc; | ||
233 | }; | ||
234 | |||
235 | struct fotg210_udc { | ||
236 | spinlock_t lock; /* protect the struct */ | ||
237 | void __iomem *reg; | ||
238 | |||
239 | unsigned long irq_trigger; | ||
240 | |||
241 | struct usb_gadget gadget; | ||
242 | struct usb_gadget_driver *driver; | ||
243 | |||
244 | struct fotg210_ep *ep[FOTG210_MAX_NUM_EP]; | ||
245 | |||
246 | struct usb_request *ep0_req; /* for internal request */ | ||
247 | __le16 ep0_data; | ||
248 | u8 ep0_dir; /* 0/0x80 out/in */ | ||
249 | |||
250 | u8 reenum; /* if re-enumeration */ | ||
251 | }; | ||
252 | |||
253 | #define gadget_to_fotg210(g) container_of((g), struct fotg210_udc, gadget) | ||
diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c index 9a7ee3347e4d..f3bb363f1d4a 100644 --- a/drivers/usb/gadget/fsl_qe_udc.c +++ b/drivers/usb/gadget/fsl_qe_udc.c | |||
@@ -2589,7 +2589,7 @@ static int qe_udc_probe(struct platform_device *ofdev) | |||
2589 | if (ret) | 2589 | if (ret) |
2590 | goto err6; | 2590 | goto err6; |
2591 | 2591 | ||
2592 | dev_set_drvdata(&ofdev->dev, udc); | 2592 | platform_set_drvdata(ofdev, udc); |
2593 | dev_info(udc->dev, | 2593 | dev_info(udc->dev, |
2594 | "%s USB controller initialized as device\n", | 2594 | "%s USB controller initialized as device\n", |
2595 | (udc->soc_type == PORT_QE) ? "QE" : "CPM"); | 2595 | (udc->soc_type == PORT_QE) ? "QE" : "CPM"); |
@@ -2640,7 +2640,7 @@ static int qe_udc_resume(struct platform_device *dev) | |||
2640 | 2640 | ||
2641 | static int qe_udc_remove(struct platform_device *ofdev) | 2641 | static int qe_udc_remove(struct platform_device *ofdev) |
2642 | { | 2642 | { |
2643 | struct qe_udc *udc = dev_get_drvdata(&ofdev->dev); | 2643 | struct qe_udc *udc = platform_get_drvdata(ofdev); |
2644 | struct qe_ep *ep; | 2644 | struct qe_ep *ep; |
2645 | unsigned int size; | 2645 | unsigned int size; |
2646 | DECLARE_COMPLETION(done); | 2646 | DECLARE_COMPLETION(done); |
diff --git a/drivers/usb/gadget/fusb300_udc.c b/drivers/usb/gadget/fusb300_udc.c index b8632d40f8bf..c83f3e165325 100644 --- a/drivers/usb/gadget/fusb300_udc.c +++ b/drivers/usb/gadget/fusb300_udc.c | |||
@@ -1347,7 +1347,7 @@ static const struct usb_gadget_ops fusb300_gadget_ops = { | |||
1347 | 1347 | ||
1348 | static int __exit fusb300_remove(struct platform_device *pdev) | 1348 | static int __exit fusb300_remove(struct platform_device *pdev) |
1349 | { | 1349 | { |
1350 | struct fusb300 *fusb300 = dev_get_drvdata(&pdev->dev); | 1350 | struct fusb300 *fusb300 = platform_get_drvdata(pdev); |
1351 | 1351 | ||
1352 | usb_del_gadget_udc(&fusb300->gadget); | 1352 | usb_del_gadget_udc(&fusb300->gadget); |
1353 | iounmap(fusb300->reg); | 1353 | iounmap(fusb300->reg); |
@@ -1416,7 +1416,7 @@ static int __init fusb300_probe(struct platform_device *pdev) | |||
1416 | 1416 | ||
1417 | spin_lock_init(&fusb300->lock); | 1417 | spin_lock_init(&fusb300->lock); |
1418 | 1418 | ||
1419 | dev_set_drvdata(&pdev->dev, fusb300); | 1419 | platform_set_drvdata(pdev, fusb300); |
1420 | 1420 | ||
1421 | fusb300->gadget.ops = &fusb300_gadget_ops; | 1421 | fusb300->gadget.ops = &fusb300_gadget_ops; |
1422 | 1422 | ||
diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index 787a78e92aa2..5327c82472ed 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c | |||
@@ -28,15 +28,18 @@ | |||
28 | # define USB_ETH_RNDIS y | 28 | # define USB_ETH_RNDIS y |
29 | # endif | 29 | # endif |
30 | 30 | ||
31 | #define USBF_ECM_INCLUDED | ||
31 | # include "f_ecm.c" | 32 | # include "f_ecm.c" |
33 | #define USB_FSUBSET_INCLUDED | ||
32 | # include "f_subset.c" | 34 | # include "f_subset.c" |
33 | # ifdef USB_ETH_RNDIS | 35 | # ifdef USB_ETH_RNDIS |
36 | # define USB_FRNDIS_INCLUDED | ||
34 | # include "f_rndis.c" | 37 | # include "f_rndis.c" |
35 | # include "rndis.c" | 38 | # include "rndis.h" |
36 | # endif | 39 | # endif |
37 | # include "u_ether.c" | 40 | # include "u_ether.h" |
38 | 41 | ||
39 | static u8 gfs_hostaddr[ETH_ALEN]; | 42 | static u8 gfs_host_mac[ETH_ALEN]; |
40 | static struct eth_dev *the_dev; | 43 | static struct eth_dev *the_dev; |
41 | # ifdef CONFIG_USB_FUNCTIONFS_ETH | 44 | # ifdef CONFIG_USB_FUNCTIONFS_ETH |
42 | static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], | 45 | static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], |
@@ -45,7 +48,7 @@ static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], | |||
45 | #else | 48 | #else |
46 | # define the_dev NULL | 49 | # define the_dev NULL |
47 | # define gether_cleanup(dev) do { } while (0) | 50 | # define gether_cleanup(dev) do { } while (0) |
48 | # define gfs_hostaddr NULL | 51 | # define gfs_host_mac NULL |
49 | struct eth_dev; | 52 | struct eth_dev; |
50 | #endif | 53 | #endif |
51 | 54 | ||
@@ -73,6 +76,8 @@ struct gfs_ffs_obj { | |||
73 | 76 | ||
74 | USB_GADGET_COMPOSITE_OPTIONS(); | 77 | USB_GADGET_COMPOSITE_OPTIONS(); |
75 | 78 | ||
79 | USB_ETHERNET_MODULE_PARAMETERS(); | ||
80 | |||
76 | static struct usb_device_descriptor gfs_dev_desc = { | 81 | static struct usb_device_descriptor gfs_dev_desc = { |
77 | .bLength = sizeof gfs_dev_desc, | 82 | .bLength = sizeof gfs_dev_desc, |
78 | .bDescriptorType = USB_DT_DEVICE, | 83 | .bDescriptorType = USB_DT_DEVICE, |
@@ -350,7 +355,8 @@ static int gfs_bind(struct usb_composite_dev *cdev) | |||
350 | if (missing_funcs) | 355 | if (missing_funcs) |
351 | return -ENODEV; | 356 | return -ENODEV; |
352 | #if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS | 357 | #if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS |
353 | the_dev = gether_setup(cdev->gadget, gfs_hostaddr); | 358 | the_dev = gether_setup(cdev->gadget, dev_addr, host_addr, gfs_host_mac, |
359 | qmult); | ||
354 | #endif | 360 | #endif |
355 | if (IS_ERR(the_dev)) { | 361 | if (IS_ERR(the_dev)) { |
356 | ret = PTR_ERR(the_dev); | 362 | ret = PTR_ERR(the_dev); |
@@ -446,7 +452,7 @@ static int gfs_do_config(struct usb_configuration *c) | |||
446 | } | 452 | } |
447 | 453 | ||
448 | if (gc->eth) { | 454 | if (gc->eth) { |
449 | ret = gc->eth(c, gfs_hostaddr, the_dev); | 455 | ret = gc->eth(c, gfs_host_mac, the_dev); |
450 | if (unlikely(ret < 0)) | 456 | if (unlikely(ret < 0)) |
451 | return ret; | 457 | return ret; |
452 | } | 458 | } |
diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c index 51cfe72da5bb..46ba9838c3a0 100644 --- a/drivers/usb/gadget/m66592-udc.c +++ b/drivers/usb/gadget/m66592-udc.c | |||
@@ -1533,7 +1533,7 @@ static const struct usb_gadget_ops m66592_gadget_ops = { | |||
1533 | 1533 | ||
1534 | static int __exit m66592_remove(struct platform_device *pdev) | 1534 | static int __exit m66592_remove(struct platform_device *pdev) |
1535 | { | 1535 | { |
1536 | struct m66592 *m66592 = dev_get_drvdata(&pdev->dev); | 1536 | struct m66592 *m66592 = platform_get_drvdata(pdev); |
1537 | 1537 | ||
1538 | usb_del_gadget_udc(&m66592->gadget); | 1538 | usb_del_gadget_udc(&m66592->gadget); |
1539 | 1539 | ||
@@ -1602,7 +1602,7 @@ static int __init m66592_probe(struct platform_device *pdev) | |||
1602 | m66592->irq_trigger = ires->flags & IRQF_TRIGGER_MASK; | 1602 | m66592->irq_trigger = ires->flags & IRQF_TRIGGER_MASK; |
1603 | 1603 | ||
1604 | spin_lock_init(&m66592->lock); | 1604 | spin_lock_init(&m66592->lock); |
1605 | dev_set_drvdata(&pdev->dev, m66592); | 1605 | platform_set_drvdata(pdev, m66592); |
1606 | 1606 | ||
1607 | m66592->gadget.ops = &m66592_gadget_ops; | 1607 | m66592->gadget.ops = &m66592_gadget_ops; |
1608 | m66592->gadget.max_speed = USB_SPEED_HIGH; | 1608 | m66592->gadget.max_speed = USB_SPEED_HIGH; |
diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c index 4a45e80c6e38..032b96a51ce4 100644 --- a/drivers/usb/gadget/multi.c +++ b/drivers/usb/gadget/multi.c | |||
@@ -43,16 +43,19 @@ MODULE_LICENSE("GPL"); | |||
43 | */ | 43 | */ |
44 | #include "f_mass_storage.c" | 44 | #include "f_mass_storage.c" |
45 | 45 | ||
46 | #define USBF_ECM_INCLUDED | ||
46 | #include "f_ecm.c" | 47 | #include "f_ecm.c" |
47 | #include "f_subset.c" | ||
48 | #ifdef USB_ETH_RNDIS | 48 | #ifdef USB_ETH_RNDIS |
49 | # define USB_FRNDIS_INCLUDED | ||
49 | # include "f_rndis.c" | 50 | # include "f_rndis.c" |
50 | # include "rndis.c" | 51 | # include "rndis.h" |
51 | #endif | 52 | #endif |
52 | #include "u_ether.c" | 53 | #include "u_ether.h" |
53 | 54 | ||
54 | USB_GADGET_COMPOSITE_OPTIONS(); | 55 | USB_GADGET_COMPOSITE_OPTIONS(); |
55 | 56 | ||
57 | USB_ETHERNET_MODULE_PARAMETERS(); | ||
58 | |||
56 | /***************************** Device Descriptor ****************************/ | 59 | /***************************** Device Descriptor ****************************/ |
57 | 60 | ||
58 | #define MULTI_VENDOR_NUM 0x1d6b /* Linux Foundation */ | 61 | #define MULTI_VENDOR_NUM 0x1d6b /* Linux Foundation */ |
@@ -133,7 +136,7 @@ FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data); | |||
133 | 136 | ||
134 | static struct fsg_common fsg_common; | 137 | static struct fsg_common fsg_common; |
135 | 138 | ||
136 | static u8 hostaddr[ETH_ALEN]; | 139 | static u8 host_mac[ETH_ALEN]; |
137 | 140 | ||
138 | static struct usb_function_instance *fi_acm; | 141 | static struct usb_function_instance *fi_acm; |
139 | static struct eth_dev *the_dev; | 142 | static struct eth_dev *the_dev; |
@@ -152,7 +155,7 @@ static __init int rndis_do_config(struct usb_configuration *c) | |||
152 | c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; | 155 | c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; |
153 | } | 156 | } |
154 | 157 | ||
155 | ret = rndis_bind_config(c, hostaddr, the_dev); | 158 | ret = rndis_bind_config(c, host_mac, the_dev); |
156 | if (ret < 0) | 159 | if (ret < 0) |
157 | return ret; | 160 | return ret; |
158 | 161 | ||
@@ -216,7 +219,7 @@ static __init int cdc_do_config(struct usb_configuration *c) | |||
216 | c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; | 219 | c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; |
217 | } | 220 | } |
218 | 221 | ||
219 | ret = ecm_bind_config(c, hostaddr, the_dev); | 222 | ret = ecm_bind_config(c, host_mac, the_dev); |
220 | if (ret < 0) | 223 | if (ret < 0) |
221 | return ret; | 224 | return ret; |
222 | 225 | ||
@@ -280,7 +283,8 @@ static int __ref multi_bind(struct usb_composite_dev *cdev) | |||
280 | } | 283 | } |
281 | 284 | ||
282 | /* set up network link layer */ | 285 | /* set up network link layer */ |
283 | the_dev = gether_setup(cdev->gadget, hostaddr); | 286 | the_dev = gether_setup(cdev->gadget, dev_addr, host_addr, host_mac, |
287 | qmult); | ||
284 | if (IS_ERR(the_dev)) | 288 | if (IS_ERR(the_dev)) |
285 | return PTR_ERR(the_dev); | 289 | return PTR_ERR(the_dev); |
286 | 290 | ||
diff --git a/drivers/usb/gadget/mv_u3d_core.c b/drivers/usb/gadget/mv_u3d_core.c index 58288e9cf728..07fdb3eaf48a 100644 --- a/drivers/usb/gadget/mv_u3d_core.c +++ b/drivers/usb/gadget/mv_u3d_core.c | |||
@@ -1786,8 +1786,6 @@ static int mv_u3d_remove(struct platform_device *dev) | |||
1786 | 1786 | ||
1787 | clk_put(u3d->clk); | 1787 | clk_put(u3d->clk); |
1788 | 1788 | ||
1789 | platform_set_drvdata(dev, NULL); | ||
1790 | |||
1791 | kfree(u3d); | 1789 | kfree(u3d); |
1792 | 1790 | ||
1793 | return 0; | 1791 | return 0; |
@@ -1997,7 +1995,6 @@ err_map_cap_regs: | |||
1997 | err_get_cap_regs: | 1995 | err_get_cap_regs: |
1998 | err_get_clk: | 1996 | err_get_clk: |
1999 | clk_put(u3d->clk); | 1997 | clk_put(u3d->clk); |
2000 | platform_set_drvdata(dev, NULL); | ||
2001 | kfree(u3d); | 1998 | kfree(u3d); |
2002 | err_alloc_private: | 1999 | err_alloc_private: |
2003 | err_pdata: | 2000 | err_pdata: |
@@ -2053,7 +2050,7 @@ static SIMPLE_DEV_PM_OPS(mv_u3d_pm_ops, mv_u3d_suspend, mv_u3d_resume); | |||
2053 | 2050 | ||
2054 | static void mv_u3d_shutdown(struct platform_device *dev) | 2051 | static void mv_u3d_shutdown(struct platform_device *dev) |
2055 | { | 2052 | { |
2056 | struct mv_u3d *u3d = dev_get_drvdata(&dev->dev); | 2053 | struct mv_u3d *u3d = platform_get_drvdata(dev); |
2057 | u32 tmp; | 2054 | u32 tmp; |
2058 | 2055 | ||
2059 | tmp = ioread32(&u3d->op_regs->usbcmd); | 2056 | tmp = ioread32(&u3d->op_regs->usbcmd); |
diff --git a/drivers/usb/gadget/ncm.c b/drivers/usb/gadget/ncm.c index 3b02fd4649ce..81956feca1bd 100644 --- a/drivers/usb/gadget/ncm.c +++ b/drivers/usb/gadget/ncm.c | |||
@@ -24,23 +24,12 @@ | |||
24 | #include <linux/usb/composite.h> | 24 | #include <linux/usb/composite.h> |
25 | 25 | ||
26 | #include "u_ether.h" | 26 | #include "u_ether.h" |
27 | #include "u_ncm.h" | ||
27 | 28 | ||
28 | #define DRIVER_DESC "NCM Gadget" | 29 | #define DRIVER_DESC "NCM Gadget" |
29 | 30 | ||
30 | /*-------------------------------------------------------------------------*/ | 31 | /*-------------------------------------------------------------------------*/ |
31 | 32 | ||
32 | /* | ||
33 | * Kbuild is not very cooperative with respect to linking separately | ||
34 | * compiled library objects into one module. So for now we won't use | ||
35 | * separate compilation ... ensuring init/exit sections work to shrink | ||
36 | * the runtime footprint, and giving us at least some parts of what | ||
37 | * a "gcc --combine ... part1.c part2.c part3.c ... " build would. | ||
38 | */ | ||
39 | #include "f_ncm.c" | ||
40 | #include "u_ether.c" | ||
41 | |||
42 | /*-------------------------------------------------------------------------*/ | ||
43 | |||
44 | /* DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! | 33 | /* DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! |
45 | * Instead: allocate your own, using normal USB-IF procedures. | 34 | * Instead: allocate your own, using normal USB-IF procedures. |
46 | */ | 35 | */ |
@@ -54,6 +43,8 @@ | |||
54 | /*-------------------------------------------------------------------------*/ | 43 | /*-------------------------------------------------------------------------*/ |
55 | USB_GADGET_COMPOSITE_OPTIONS(); | 44 | USB_GADGET_COMPOSITE_OPTIONS(); |
56 | 45 | ||
46 | USB_ETHERNET_MODULE_PARAMETERS(); | ||
47 | |||
57 | static struct usb_device_descriptor device_desc = { | 48 | static struct usb_device_descriptor device_desc = { |
58 | .bLength = sizeof device_desc, | 49 | .bLength = sizeof device_desc, |
59 | .bDescriptorType = USB_DT_DEVICE, | 50 | .bDescriptorType = USB_DT_DEVICE, |
@@ -111,13 +102,15 @@ static struct usb_gadget_strings *dev_strings[] = { | |||
111 | NULL, | 102 | NULL, |
112 | }; | 103 | }; |
113 | 104 | ||
114 | struct eth_dev *the_dev; | 105 | static struct usb_function_instance *f_ncm_inst; |
115 | static u8 hostaddr[ETH_ALEN]; | 106 | static struct usb_function *f_ncm; |
116 | 107 | ||
117 | /*-------------------------------------------------------------------------*/ | 108 | /*-------------------------------------------------------------------------*/ |
118 | 109 | ||
119 | static int __init ncm_do_config(struct usb_configuration *c) | 110 | static int __init ncm_do_config(struct usb_configuration *c) |
120 | { | 111 | { |
112 | int status; | ||
113 | |||
121 | /* FIXME alloc iConfiguration string, set it in c->strings */ | 114 | /* FIXME alloc iConfiguration string, set it in c->strings */ |
122 | 115 | ||
123 | if (gadget_is_otg(c->cdev->gadget)) { | 116 | if (gadget_is_otg(c->cdev->gadget)) { |
@@ -125,7 +118,19 @@ static int __init ncm_do_config(struct usb_configuration *c) | |||
125 | c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; | 118 | c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; |
126 | } | 119 | } |
127 | 120 | ||
128 | return ncm_bind_config(c, hostaddr, the_dev); | 121 | f_ncm = usb_get_function(f_ncm_inst); |
122 | if (IS_ERR(f_ncm)) { | ||
123 | status = PTR_ERR(f_ncm); | ||
124 | return status; | ||
125 | } | ||
126 | |||
127 | status = usb_add_function(c, f_ncm); | ||
128 | if (status < 0) { | ||
129 | usb_put_function(f_ncm); | ||
130 | return status; | ||
131 | } | ||
132 | |||
133 | return 0; | ||
129 | } | 134 | } |
130 | 135 | ||
131 | static struct usb_configuration ncm_config_driver = { | 136 | static struct usb_configuration ncm_config_driver = { |
@@ -141,12 +146,20 @@ static struct usb_configuration ncm_config_driver = { | |||
141 | static int __init gncm_bind(struct usb_composite_dev *cdev) | 146 | static int __init gncm_bind(struct usb_composite_dev *cdev) |
142 | { | 147 | { |
143 | struct usb_gadget *gadget = cdev->gadget; | 148 | struct usb_gadget *gadget = cdev->gadget; |
149 | struct f_ncm_opts *ncm_opts; | ||
144 | int status; | 150 | int status; |
145 | 151 | ||
146 | /* set up network link layer */ | 152 | f_ncm_inst = usb_get_function_instance("ncm"); |
147 | the_dev = gether_setup(cdev->gadget, hostaddr); | 153 | if (IS_ERR(f_ncm_inst)) |
148 | if (IS_ERR(the_dev)) | 154 | return PTR_ERR(f_ncm_inst); |
149 | return PTR_ERR(the_dev); | 155 | |
156 | ncm_opts = container_of(f_ncm_inst, struct f_ncm_opts, func_inst); | ||
157 | |||
158 | gether_set_qmult(ncm_opts->net, qmult); | ||
159 | if (!gether_set_host_addr(ncm_opts->net, host_addr)) | ||
160 | pr_info("using host ethernet address: %s", host_addr); | ||
161 | if (!gether_set_dev_addr(ncm_opts->net, dev_addr)) | ||
162 | pr_info("using self ethernet address: %s", dev_addr); | ||
150 | 163 | ||
151 | /* Allocate string descriptor numbers ... note that string | 164 | /* Allocate string descriptor numbers ... note that string |
152 | * contents can be overridden by the composite_dev glue. | 165 | * contents can be overridden by the composite_dev glue. |
@@ -169,13 +182,16 @@ static int __init gncm_bind(struct usb_composite_dev *cdev) | |||
169 | return 0; | 182 | return 0; |
170 | 183 | ||
171 | fail: | 184 | fail: |
172 | gether_cleanup(the_dev); | 185 | usb_put_function_instance(f_ncm_inst); |
173 | return status; | 186 | return status; |
174 | } | 187 | } |
175 | 188 | ||
176 | static int __exit gncm_unbind(struct usb_composite_dev *cdev) | 189 | static int __exit gncm_unbind(struct usb_composite_dev *cdev) |
177 | { | 190 | { |
178 | gether_cleanup(the_dev); | 191 | if (!IS_ERR_OR_NULL(f_ncm)) |
192 | usb_put_function(f_ncm); | ||
193 | if (!IS_ERR_OR_NULL(f_ncm_inst)) | ||
194 | usb_put_function_instance(f_ncm_inst); | ||
179 | return 0; | 195 | return 0; |
180 | } | 196 | } |
181 | 197 | ||
diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c index 3b344b41a167..0a8099a488c4 100644 --- a/drivers/usb/gadget/nokia.c +++ b/drivers/usb/gadget/nokia.c | |||
@@ -16,11 +16,13 @@ | |||
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/module.h> | ||
19 | #include <linux/device.h> | 20 | #include <linux/device.h> |
20 | 21 | ||
21 | #include "u_serial.h" | 22 | #include "u_serial.h" |
22 | #include "u_ether.h" | 23 | #include "u_ether.h" |
23 | #include "u_phonet.h" | 24 | #include "u_phonet.h" |
25 | #include "u_ecm.h" | ||
24 | #include "gadget_chips.h" | 26 | #include "gadget_chips.h" |
25 | 27 | ||
26 | /* Defines */ | 28 | /* Defines */ |
@@ -28,24 +30,10 @@ | |||
28 | #define NOKIA_VERSION_NUM 0x0211 | 30 | #define NOKIA_VERSION_NUM 0x0211 |
29 | #define NOKIA_LONG_NAME "N900 (PC-Suite Mode)" | 31 | #define NOKIA_LONG_NAME "N900 (PC-Suite Mode)" |
30 | 32 | ||
31 | /*-------------------------------------------------------------------------*/ | ||
32 | |||
33 | /* | ||
34 | * Kbuild is not very cooperative with respect to linking separately | ||
35 | * compiled library objects into one module. So for now we won't use | ||
36 | * separate compilation ... ensuring init/exit sections work to shrink | ||
37 | * the runtime footprint, and giving us at least some parts of what | ||
38 | * a "gcc --combine ... part1.c part2.c part3.c ... " build would. | ||
39 | */ | ||
40 | #define USBF_OBEX_INCLUDED | ||
41 | #include "f_ecm.c" | ||
42 | #include "f_obex.c" | ||
43 | #include "f_phonet.c" | ||
44 | #include "u_ether.c" | ||
45 | |||
46 | /*-------------------------------------------------------------------------*/ | ||
47 | USB_GADGET_COMPOSITE_OPTIONS(); | 33 | USB_GADGET_COMPOSITE_OPTIONS(); |
48 | 34 | ||
35 | USB_ETHERNET_MODULE_PARAMETERS(); | ||
36 | |||
49 | #define NOKIA_VENDOR_ID 0x0421 /* Nokia */ | 37 | #define NOKIA_VENDOR_ID 0x0421 /* Nokia */ |
50 | #define NOKIA_PRODUCT_ID 0x01c8 /* Nokia Gadget */ | 38 | #define NOKIA_PRODUCT_ID 0x01c8 /* Nokia Gadget */ |
51 | 39 | ||
@@ -98,16 +86,15 @@ MODULE_LICENSE("GPL"); | |||
98 | /*-------------------------------------------------------------------------*/ | 86 | /*-------------------------------------------------------------------------*/ |
99 | static struct usb_function *f_acm_cfg1; | 87 | static struct usb_function *f_acm_cfg1; |
100 | static struct usb_function *f_acm_cfg2; | 88 | static struct usb_function *f_acm_cfg2; |
101 | static u8 hostaddr[ETH_ALEN]; | 89 | static struct usb_function *f_ecm_cfg1; |
102 | static struct eth_dev *the_dev; | 90 | static struct usb_function *f_ecm_cfg2; |
103 | 91 | static struct usb_function *f_obex1_cfg1; | |
104 | enum { | 92 | static struct usb_function *f_obex2_cfg1; |
105 | TTY_PORT_OBEX0, | 93 | static struct usb_function *f_obex1_cfg2; |
106 | TTY_PORT_OBEX1, | 94 | static struct usb_function *f_obex2_cfg2; |
107 | TTY_PORTS_MAX, | 95 | static struct usb_function *f_phonet_cfg1; |
108 | }; | 96 | static struct usb_function *f_phonet_cfg2; |
109 | 97 | ||
110 | static unsigned char tty_lines[TTY_PORTS_MAX]; | ||
111 | 98 | ||
112 | static struct usb_configuration nokia_config_500ma_driver = { | 99 | static struct usb_configuration nokia_config_500ma_driver = { |
113 | .label = "Bus Powered", | 100 | .label = "Bus Powered", |
@@ -126,47 +113,114 @@ static struct usb_configuration nokia_config_100ma_driver = { | |||
126 | }; | 113 | }; |
127 | 114 | ||
128 | static struct usb_function_instance *fi_acm; | 115 | static struct usb_function_instance *fi_acm; |
116 | static struct usb_function_instance *fi_ecm; | ||
117 | static struct usb_function_instance *fi_obex1; | ||
118 | static struct usb_function_instance *fi_obex2; | ||
119 | static struct usb_function_instance *fi_phonet; | ||
129 | 120 | ||
130 | static int __init nokia_bind_config(struct usb_configuration *c) | 121 | static int __init nokia_bind_config(struct usb_configuration *c) |
131 | { | 122 | { |
132 | struct usb_function *f_acm; | 123 | struct usb_function *f_acm; |
124 | struct usb_function *f_phonet = NULL; | ||
125 | struct usb_function *f_obex1 = NULL; | ||
126 | struct usb_function *f_ecm; | ||
127 | struct usb_function *f_obex2 = NULL; | ||
133 | int status = 0; | 128 | int status = 0; |
129 | int obex1_stat = 0; | ||
130 | int obex2_stat = 0; | ||
131 | int phonet_stat = 0; | ||
132 | |||
133 | if (!IS_ERR(fi_phonet)) { | ||
134 | f_phonet = usb_get_function(fi_phonet); | ||
135 | if (IS_ERR(f_phonet)) | ||
136 | pr_debug("could not get phonet function\n"); | ||
137 | } | ||
134 | 138 | ||
135 | status = phonet_bind_config(c); | 139 | if (!IS_ERR(fi_obex1)) { |
136 | if (status) | 140 | f_obex1 = usb_get_function(fi_obex1); |
137 | printk(KERN_DEBUG "could not bind phonet config\n"); | 141 | if (IS_ERR(f_obex1)) |
138 | 142 | pr_debug("could not get obex function 0\n"); | |
139 | status = obex_bind_config(c, tty_lines[TTY_PORT_OBEX0]); | 143 | } |
140 | if (status) | ||
141 | printk(KERN_DEBUG "could not bind obex config %d\n", 0); | ||
142 | 144 | ||
143 | status = obex_bind_config(c, tty_lines[TTY_PORT_OBEX1]); | 145 | if (!IS_ERR(fi_obex2)) { |
144 | if (status) | 146 | f_obex2 = usb_get_function(fi_obex2); |
145 | printk(KERN_DEBUG "could not bind obex config %d\n", 0); | 147 | if (IS_ERR(f_obex2)) |
148 | pr_debug("could not get obex function 1\n"); | ||
149 | } | ||
146 | 150 | ||
147 | f_acm = usb_get_function(fi_acm); | 151 | f_acm = usb_get_function(fi_acm); |
148 | if (IS_ERR(f_acm)) | 152 | if (IS_ERR(f_acm)) { |
149 | return PTR_ERR(f_acm); | 153 | status = PTR_ERR(f_acm); |
154 | goto err_get_acm; | ||
155 | } | ||
156 | |||
157 | f_ecm = usb_get_function(fi_ecm); | ||
158 | if (IS_ERR(f_ecm)) { | ||
159 | status = PTR_ERR(f_ecm); | ||
160 | goto err_get_ecm; | ||
161 | } | ||
162 | |||
163 | if (!IS_ERR_OR_NULL(f_phonet)) { | ||
164 | phonet_stat = usb_add_function(c, f_phonet); | ||
165 | if (phonet_stat) | ||
166 | pr_debug("could not add phonet function\n"); | ||
167 | } | ||
168 | |||
169 | if (!IS_ERR_OR_NULL(f_obex1)) { | ||
170 | obex1_stat = usb_add_function(c, f_obex1); | ||
171 | if (obex1_stat) | ||
172 | pr_debug("could not add obex function 0\n"); | ||
173 | } | ||
174 | |||
175 | if (!IS_ERR_OR_NULL(f_obex2)) { | ||
176 | obex2_stat = usb_add_function(c, f_obex2); | ||
177 | if (obex2_stat) | ||
178 | pr_debug("could not add obex function 1\n"); | ||
179 | } | ||
150 | 180 | ||
151 | status = usb_add_function(c, f_acm); | 181 | status = usb_add_function(c, f_acm); |
152 | if (status) | 182 | if (status) |
153 | goto err_conf; | 183 | goto err_conf; |
154 | 184 | ||
155 | status = ecm_bind_config(c, hostaddr, the_dev); | 185 | status = usb_add_function(c, f_ecm); |
156 | if (status) { | 186 | if (status) { |
157 | pr_debug("could not bind ecm config %d\n", status); | 187 | pr_debug("could not bind ecm config %d\n", status); |
158 | goto err_ecm; | 188 | goto err_ecm; |
159 | } | 189 | } |
160 | if (c == &nokia_config_500ma_driver) | 190 | if (c == &nokia_config_500ma_driver) { |
161 | f_acm_cfg1 = f_acm; | 191 | f_acm_cfg1 = f_acm; |
162 | else | 192 | f_ecm_cfg1 = f_ecm; |
193 | f_phonet_cfg1 = f_phonet; | ||
194 | f_obex1_cfg1 = f_obex1; | ||
195 | f_obex2_cfg1 = f_obex2; | ||
196 | } else { | ||
163 | f_acm_cfg2 = f_acm; | 197 | f_acm_cfg2 = f_acm; |
198 | f_ecm_cfg2 = f_ecm; | ||
199 | f_phonet_cfg2 = f_phonet; | ||
200 | f_obex1_cfg2 = f_obex1; | ||
201 | f_obex2_cfg2 = f_obex2; | ||
202 | } | ||
164 | 203 | ||
165 | return status; | 204 | return status; |
166 | err_ecm: | 205 | err_ecm: |
167 | usb_remove_function(c, f_acm); | 206 | usb_remove_function(c, f_acm); |
168 | err_conf: | 207 | err_conf: |
208 | if (!obex2_stat) | ||
209 | usb_remove_function(c, f_obex2); | ||
210 | if (!obex1_stat) | ||
211 | usb_remove_function(c, f_obex1); | ||
212 | if (!phonet_stat) | ||
213 | usb_remove_function(c, f_phonet); | ||
214 | usb_put_function(f_ecm); | ||
215 | err_get_ecm: | ||
169 | usb_put_function(f_acm); | 216 | usb_put_function(f_acm); |
217 | err_get_acm: | ||
218 | if (!IS_ERR_OR_NULL(f_obex2)) | ||
219 | usb_put_function(f_obex2); | ||
220 | if (!IS_ERR_OR_NULL(f_obex1)) | ||
221 | usb_put_function(f_obex1); | ||
222 | if (!IS_ERR_OR_NULL(f_phonet)) | ||
223 | usb_put_function(f_phonet); | ||
170 | return status; | 224 | return status; |
171 | } | 225 | } |
172 | 226 | ||
@@ -174,23 +228,6 @@ static int __init nokia_bind(struct usb_composite_dev *cdev) | |||
174 | { | 228 | { |
175 | struct usb_gadget *gadget = cdev->gadget; | 229 | struct usb_gadget *gadget = cdev->gadget; |
176 | int status; | 230 | int status; |
177 | int cur_line; | ||
178 | |||
179 | status = gphonet_setup(cdev->gadget); | ||
180 | if (status < 0) | ||
181 | goto err_phonet; | ||
182 | |||
183 | for (cur_line = 0; cur_line < TTY_PORTS_MAX; cur_line++) { | ||
184 | status = gserial_alloc_line(&tty_lines[cur_line]); | ||
185 | if (status) | ||
186 | goto err_ether; | ||
187 | } | ||
188 | |||
189 | the_dev = gether_setup(cdev->gadget, hostaddr); | ||
190 | if (IS_ERR(the_dev)) { | ||
191 | status = PTR_ERR(the_dev); | ||
192 | goto err_ether; | ||
193 | } | ||
194 | 231 | ||
195 | status = usb_string_ids_tab(cdev, strings_dev); | 232 | status = usb_string_ids_tab(cdev, strings_dev); |
196 | if (status < 0) | 233 | if (status < 0) |
@@ -201,18 +238,40 @@ static int __init nokia_bind(struct usb_composite_dev *cdev) | |||
201 | nokia_config_500ma_driver.iConfiguration = status; | 238 | nokia_config_500ma_driver.iConfiguration = status; |
202 | nokia_config_100ma_driver.iConfiguration = status; | 239 | nokia_config_100ma_driver.iConfiguration = status; |
203 | 240 | ||
204 | if (!gadget_supports_altsettings(gadget)) | 241 | if (!gadget_supports_altsettings(gadget)) { |
242 | status = -ENODEV; | ||
205 | goto err_usb; | 243 | goto err_usb; |
244 | } | ||
245 | |||
246 | fi_phonet = usb_get_function_instance("phonet"); | ||
247 | if (IS_ERR(fi_phonet)) | ||
248 | pr_debug("could not find phonet function\n"); | ||
249 | |||
250 | fi_obex1 = usb_get_function_instance("obex"); | ||
251 | if (IS_ERR(fi_obex1)) | ||
252 | pr_debug("could not find obex function 1\n"); | ||
253 | |||
254 | fi_obex2 = usb_get_function_instance("obex"); | ||
255 | if (IS_ERR(fi_obex2)) | ||
256 | pr_debug("could not find obex function 2\n"); | ||
206 | 257 | ||
207 | fi_acm = usb_get_function_instance("acm"); | 258 | fi_acm = usb_get_function_instance("acm"); |
208 | if (IS_ERR(fi_acm)) | 259 | if (IS_ERR(fi_acm)) { |
209 | goto err_usb; | 260 | status = PTR_ERR(fi_acm); |
261 | goto err_obex2_inst; | ||
262 | } | ||
263 | |||
264 | fi_ecm = usb_get_function_instance("ecm"); | ||
265 | if (IS_ERR(fi_ecm)) { | ||
266 | status = PTR_ERR(fi_ecm); | ||
267 | goto err_acm_inst; | ||
268 | } | ||
210 | 269 | ||
211 | /* finally register the configuration */ | 270 | /* finally register the configuration */ |
212 | status = usb_add_config(cdev, &nokia_config_500ma_driver, | 271 | status = usb_add_config(cdev, &nokia_config_500ma_driver, |
213 | nokia_bind_config); | 272 | nokia_bind_config); |
214 | if (status < 0) | 273 | if (status < 0) |
215 | goto err_acm_inst; | 274 | goto err_ecm_inst; |
216 | 275 | ||
217 | status = usb_add_config(cdev, &nokia_config_100ma_driver, | 276 | status = usb_add_config(cdev, &nokia_config_100ma_driver, |
218 | nokia_bind_config); | 277 | nokia_bind_config); |
@@ -226,33 +285,55 @@ static int __init nokia_bind(struct usb_composite_dev *cdev) | |||
226 | 285 | ||
227 | err_put_cfg1: | 286 | err_put_cfg1: |
228 | usb_put_function(f_acm_cfg1); | 287 | usb_put_function(f_acm_cfg1); |
288 | if (!IS_ERR_OR_NULL(f_obex1_cfg1)) | ||
289 | usb_put_function(f_obex1_cfg1); | ||
290 | if (!IS_ERR_OR_NULL(f_obex2_cfg1)) | ||
291 | usb_put_function(f_obex2_cfg1); | ||
292 | if (!IS_ERR_OR_NULL(f_phonet_cfg1)) | ||
293 | usb_put_function(f_phonet_cfg1); | ||
294 | usb_put_function(f_ecm_cfg1); | ||
295 | err_ecm_inst: | ||
296 | usb_put_function_instance(fi_ecm); | ||
229 | err_acm_inst: | 297 | err_acm_inst: |
230 | usb_put_function_instance(fi_acm); | 298 | usb_put_function_instance(fi_acm); |
299 | err_obex2_inst: | ||
300 | if (!IS_ERR(fi_obex2)) | ||
301 | usb_put_function_instance(fi_obex2); | ||
302 | if (!IS_ERR(fi_obex1)) | ||
303 | usb_put_function_instance(fi_obex1); | ||
304 | if (!IS_ERR(fi_phonet)) | ||
305 | usb_put_function_instance(fi_phonet); | ||
231 | err_usb: | 306 | err_usb: |
232 | gether_cleanup(the_dev); | ||
233 | err_ether: | ||
234 | cur_line--; | ||
235 | while (cur_line >= 0) | ||
236 | gserial_free_line(tty_lines[cur_line--]); | ||
237 | |||
238 | gphonet_cleanup(); | ||
239 | err_phonet: | ||
240 | return status; | 307 | return status; |
241 | } | 308 | } |
242 | 309 | ||
243 | static int __exit nokia_unbind(struct usb_composite_dev *cdev) | 310 | static int __exit nokia_unbind(struct usb_composite_dev *cdev) |
244 | { | 311 | { |
245 | int i; | 312 | if (!IS_ERR_OR_NULL(f_obex1_cfg2)) |
246 | 313 | usb_put_function(f_obex1_cfg2); | |
314 | if (!IS_ERR_OR_NULL(f_obex2_cfg2)) | ||
315 | usb_put_function(f_obex2_cfg2); | ||
316 | if (!IS_ERR_OR_NULL(f_obex1_cfg1)) | ||
317 | usb_put_function(f_obex1_cfg1); | ||
318 | if (!IS_ERR_OR_NULL(f_obex2_cfg1)) | ||
319 | usb_put_function(f_obex2_cfg1); | ||
320 | if (!IS_ERR_OR_NULL(f_phonet_cfg1)) | ||
321 | usb_put_function(f_phonet_cfg1); | ||
322 | if (!IS_ERR_OR_NULL(f_phonet_cfg2)) | ||
323 | usb_put_function(f_phonet_cfg2); | ||
247 | usb_put_function(f_acm_cfg1); | 324 | usb_put_function(f_acm_cfg1); |
248 | usb_put_function(f_acm_cfg2); | 325 | usb_put_function(f_acm_cfg2); |
326 | usb_put_function(f_ecm_cfg1); | ||
327 | usb_put_function(f_ecm_cfg2); | ||
328 | |||
329 | usb_put_function_instance(fi_ecm); | ||
330 | if (!IS_ERR(fi_obex2)) | ||
331 | usb_put_function_instance(fi_obex2); | ||
332 | if (!IS_ERR(fi_obex1)) | ||
333 | usb_put_function_instance(fi_obex1); | ||
334 | if (!IS_ERR(fi_phonet)) | ||
335 | usb_put_function_instance(fi_phonet); | ||
249 | usb_put_function_instance(fi_acm); | 336 | usb_put_function_instance(fi_acm); |
250 | gphonet_cleanup(); | ||
251 | |||
252 | for (i = 0; i < TTY_PORTS_MAX; i++) | ||
253 | gserial_free_line(tty_lines[i]); | ||
254 | |||
255 | gether_cleanup(the_dev); | ||
256 | 337 | ||
257 | return 0; | 338 | return 0; |
258 | } | 339 | } |
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 6b4c7d95853f..41cea9566ac8 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c | |||
@@ -2505,7 +2505,6 @@ static int pxa_udc_remove(struct platform_device *_dev) | |||
2505 | usb_put_phy(udc->transceiver); | 2505 | usb_put_phy(udc->transceiver); |
2506 | 2506 | ||
2507 | udc->transceiver = NULL; | 2507 | udc->transceiver = NULL; |
2508 | platform_set_drvdata(_dev, NULL); | ||
2509 | the_controller = NULL; | 2508 | the_controller = NULL; |
2510 | clk_put(udc->clk); | 2509 | clk_put(udc->clk); |
2511 | iounmap(udc->regs); | 2510 | iounmap(udc->regs); |
diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c index 7ff7d9cf2061..c6af649f3240 100644 --- a/drivers/usb/gadget/r8a66597-udc.c +++ b/drivers/usb/gadget/r8a66597-udc.c | |||
@@ -1469,11 +1469,11 @@ static irqreturn_t r8a66597_irq(int irq, void *_r8a66597) | |||
1469 | u16 savepipe; | 1469 | u16 savepipe; |
1470 | u16 mask0; | 1470 | u16 mask0; |
1471 | 1471 | ||
1472 | spin_lock(&r8a66597->lock); | ||
1473 | |||
1472 | if (r8a66597_is_sudmac(r8a66597)) | 1474 | if (r8a66597_is_sudmac(r8a66597)) |
1473 | r8a66597_sudmac_irq(r8a66597); | 1475 | r8a66597_sudmac_irq(r8a66597); |
1474 | 1476 | ||
1475 | spin_lock(&r8a66597->lock); | ||
1476 | |||
1477 | intsts0 = r8a66597_read(r8a66597, INTSTS0); | 1477 | intsts0 = r8a66597_read(r8a66597, INTSTS0); |
1478 | intenb0 = r8a66597_read(r8a66597, INTENB0); | 1478 | intenb0 = r8a66597_read(r8a66597, INTENB0); |
1479 | 1479 | ||
@@ -1822,7 +1822,7 @@ static const struct usb_gadget_ops r8a66597_gadget_ops = { | |||
1822 | 1822 | ||
1823 | static int __exit r8a66597_remove(struct platform_device *pdev) | 1823 | static int __exit r8a66597_remove(struct platform_device *pdev) |
1824 | { | 1824 | { |
1825 | struct r8a66597 *r8a66597 = dev_get_drvdata(&pdev->dev); | 1825 | struct r8a66597 *r8a66597 = platform_get_drvdata(pdev); |
1826 | 1826 | ||
1827 | usb_del_gadget_udc(&r8a66597->gadget); | 1827 | usb_del_gadget_udc(&r8a66597->gadget); |
1828 | del_timer_sync(&r8a66597->timer); | 1828 | del_timer_sync(&r8a66597->timer); |
@@ -1909,7 +1909,7 @@ static int __init r8a66597_probe(struct platform_device *pdev) | |||
1909 | } | 1909 | } |
1910 | 1910 | ||
1911 | spin_lock_init(&r8a66597->lock); | 1911 | spin_lock_init(&r8a66597->lock); |
1912 | dev_set_drvdata(&pdev->dev, r8a66597); | 1912 | platform_set_drvdata(pdev, r8a66597); |
1913 | r8a66597->pdata = pdev->dev.platform_data; | 1913 | r8a66597->pdata = pdev->dev.platform_data; |
1914 | r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW; | 1914 | r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW; |
1915 | 1915 | ||
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index 1e4cfb05f70b..3e3ea7203030 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c | |||
@@ -761,6 +761,7 @@ int rndis_signal_connect(int configNr) | |||
761 | return rndis_indicate_status_msg(configNr, | 761 | return rndis_indicate_status_msg(configNr, |
762 | RNDIS_STATUS_MEDIA_CONNECT); | 762 | RNDIS_STATUS_MEDIA_CONNECT); |
763 | } | 763 | } |
764 | EXPORT_SYMBOL(rndis_signal_connect); | ||
764 | 765 | ||
765 | int rndis_signal_disconnect(int configNr) | 766 | int rndis_signal_disconnect(int configNr) |
766 | { | 767 | { |
@@ -769,6 +770,7 @@ int rndis_signal_disconnect(int configNr) | |||
769 | return rndis_indicate_status_msg(configNr, | 770 | return rndis_indicate_status_msg(configNr, |
770 | RNDIS_STATUS_MEDIA_DISCONNECT); | 771 | RNDIS_STATUS_MEDIA_DISCONNECT); |
771 | } | 772 | } |
773 | EXPORT_SYMBOL(rndis_signal_disconnect); | ||
772 | 774 | ||
773 | void rndis_uninit(int configNr) | 775 | void rndis_uninit(int configNr) |
774 | { | 776 | { |
@@ -783,11 +785,13 @@ void rndis_uninit(int configNr) | |||
783 | while ((buf = rndis_get_next_response(configNr, &length))) | 785 | while ((buf = rndis_get_next_response(configNr, &length))) |
784 | rndis_free_response(configNr, buf); | 786 | rndis_free_response(configNr, buf); |
785 | } | 787 | } |
788 | EXPORT_SYMBOL(rndis_uninit); | ||
786 | 789 | ||
787 | void rndis_set_host_mac(int configNr, const u8 *addr) | 790 | void rndis_set_host_mac(int configNr, const u8 *addr) |
788 | { | 791 | { |
789 | rndis_per_dev_params[configNr].host_mac = addr; | 792 | rndis_per_dev_params[configNr].host_mac = addr; |
790 | } | 793 | } |
794 | EXPORT_SYMBOL(rndis_set_host_mac); | ||
791 | 795 | ||
792 | /* | 796 | /* |
793 | * Message Parser | 797 | * Message Parser |
@@ -870,6 +874,7 @@ int rndis_msg_parser(u8 configNr, u8 *buf) | |||
870 | 874 | ||
871 | return -ENOTSUPP; | 875 | return -ENOTSUPP; |
872 | } | 876 | } |
877 | EXPORT_SYMBOL(rndis_msg_parser); | ||
873 | 878 | ||
874 | int rndis_register(void (*resp_avail)(void *v), void *v) | 879 | int rndis_register(void (*resp_avail)(void *v), void *v) |
875 | { | 880 | { |
@@ -891,6 +896,7 @@ int rndis_register(void (*resp_avail)(void *v), void *v) | |||
891 | 896 | ||
892 | return -ENODEV; | 897 | return -ENODEV; |
893 | } | 898 | } |
899 | EXPORT_SYMBOL(rndis_register); | ||
894 | 900 | ||
895 | void rndis_deregister(int configNr) | 901 | void rndis_deregister(int configNr) |
896 | { | 902 | { |
@@ -899,6 +905,7 @@ void rndis_deregister(int configNr) | |||
899 | if (configNr >= RNDIS_MAX_CONFIGS) return; | 905 | if (configNr >= RNDIS_MAX_CONFIGS) return; |
900 | rndis_per_dev_params[configNr].used = 0; | 906 | rndis_per_dev_params[configNr].used = 0; |
901 | } | 907 | } |
908 | EXPORT_SYMBOL(rndis_deregister); | ||
902 | 909 | ||
903 | int rndis_set_param_dev(u8 configNr, struct net_device *dev, u16 *cdc_filter) | 910 | int rndis_set_param_dev(u8 configNr, struct net_device *dev, u16 *cdc_filter) |
904 | { | 911 | { |
@@ -912,6 +919,7 @@ int rndis_set_param_dev(u8 configNr, struct net_device *dev, u16 *cdc_filter) | |||
912 | 919 | ||
913 | return 0; | 920 | return 0; |
914 | } | 921 | } |
922 | EXPORT_SYMBOL(rndis_set_param_dev); | ||
915 | 923 | ||
916 | int rndis_set_param_vendor(u8 configNr, u32 vendorID, const char *vendorDescr) | 924 | int rndis_set_param_vendor(u8 configNr, u32 vendorID, const char *vendorDescr) |
917 | { | 925 | { |
@@ -924,6 +932,7 @@ int rndis_set_param_vendor(u8 configNr, u32 vendorID, const char *vendorDescr) | |||
924 | 932 | ||
925 | return 0; | 933 | return 0; |
926 | } | 934 | } |
935 | EXPORT_SYMBOL(rndis_set_param_vendor); | ||
927 | 936 | ||
928 | int rndis_set_param_medium(u8 configNr, u32 medium, u32 speed) | 937 | int rndis_set_param_medium(u8 configNr, u32 medium, u32 speed) |
929 | { | 938 | { |
@@ -935,6 +944,7 @@ int rndis_set_param_medium(u8 configNr, u32 medium, u32 speed) | |||
935 | 944 | ||
936 | return 0; | 945 | return 0; |
937 | } | 946 | } |
947 | EXPORT_SYMBOL(rndis_set_param_medium); | ||
938 | 948 | ||
939 | void rndis_add_hdr(struct sk_buff *skb) | 949 | void rndis_add_hdr(struct sk_buff *skb) |
940 | { | 950 | { |
@@ -949,6 +959,7 @@ void rndis_add_hdr(struct sk_buff *skb) | |||
949 | header->DataOffset = cpu_to_le32(36); | 959 | header->DataOffset = cpu_to_le32(36); |
950 | header->DataLength = cpu_to_le32(skb->len - sizeof(*header)); | 960 | header->DataLength = cpu_to_le32(skb->len - sizeof(*header)); |
951 | } | 961 | } |
962 | EXPORT_SYMBOL(rndis_add_hdr); | ||
952 | 963 | ||
953 | void rndis_free_response(int configNr, u8 *buf) | 964 | void rndis_free_response(int configNr, u8 *buf) |
954 | { | 965 | { |
@@ -965,6 +976,7 @@ void rndis_free_response(int configNr, u8 *buf) | |||
965 | } | 976 | } |
966 | } | 977 | } |
967 | } | 978 | } |
979 | EXPORT_SYMBOL(rndis_free_response); | ||
968 | 980 | ||
969 | u8 *rndis_get_next_response(int configNr, u32 *length) | 981 | u8 *rndis_get_next_response(int configNr, u32 *length) |
970 | { | 982 | { |
@@ -986,6 +998,7 @@ u8 *rndis_get_next_response(int configNr, u32 *length) | |||
986 | 998 | ||
987 | return NULL; | 999 | return NULL; |
988 | } | 1000 | } |
1001 | EXPORT_SYMBOL(rndis_get_next_response); | ||
989 | 1002 | ||
990 | static rndis_resp_t *rndis_add_response(int configNr, u32 length) | 1003 | static rndis_resp_t *rndis_add_response(int configNr, u32 length) |
991 | { | 1004 | { |
@@ -1029,6 +1042,7 @@ int rndis_rm_hdr(struct gether *port, | |||
1029 | skb_queue_tail(list, skb); | 1042 | skb_queue_tail(list, skb); |
1030 | return 0; | 1043 | return 0; |
1031 | } | 1044 | } |
1045 | EXPORT_SYMBOL(rndis_rm_hdr); | ||
1032 | 1046 | ||
1033 | #ifdef CONFIG_USB_GADGET_DEBUG_FILES | 1047 | #ifdef CONFIG_USB_GADGET_DEBUG_FILES |
1034 | 1048 | ||
@@ -1160,6 +1174,7 @@ int rndis_init(void) | |||
1160 | 1174 | ||
1161 | return 0; | 1175 | return 0; |
1162 | } | 1176 | } |
1177 | module_init(rndis_init); | ||
1163 | 1178 | ||
1164 | void rndis_exit(void) | 1179 | void rndis_exit(void) |
1165 | { | 1180 | { |
@@ -1173,3 +1188,6 @@ void rndis_exit(void) | |||
1173 | } | 1188 | } |
1174 | #endif | 1189 | #endif |
1175 | } | 1190 | } |
1191 | module_exit(rndis_exit); | ||
1192 | |||
1193 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/gadget/rndis.h b/drivers/usb/gadget/rndis.h index 0647f2f34e89..0f4abb4c3775 100644 --- a/drivers/usb/gadget/rndis.h +++ b/drivers/usb/gadget/rndis.h | |||
@@ -16,6 +16,7 @@ | |||
16 | #define _LINUX_RNDIS_H | 16 | #define _LINUX_RNDIS_H |
17 | 17 | ||
18 | #include <linux/rndis.h> | 18 | #include <linux/rndis.h> |
19 | #include "u_ether.h" | ||
19 | #include "ndis.h" | 20 | #include "ndis.h" |
20 | 21 | ||
21 | #define RNDIS_MAXIMUM_FRAME_SIZE 1518 | 22 | #define RNDIS_MAXIMUM_FRAME_SIZE 1518 |
@@ -216,7 +217,4 @@ int rndis_signal_disconnect (int configNr); | |||
216 | int rndis_state (int configNr); | 217 | int rndis_state (int configNr); |
217 | extern void rndis_set_host_mac (int configNr, const u8 *addr); | 218 | extern void rndis_set_host_mac (int configNr, const u8 *addr); |
218 | 219 | ||
219 | int rndis_init(void); | ||
220 | void rndis_exit (void); | ||
221 | |||
222 | #endif /* _LINUX_RNDIS_H */ | 220 | #endif /* _LINUX_RNDIS_H */ |
diff --git a/drivers/usb/gadget/u_ecm.h b/drivers/usb/gadget/u_ecm.h new file mode 100644 index 000000000000..262cc03cc2c0 --- /dev/null +++ b/drivers/usb/gadget/u_ecm.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * u_ecm.h | ||
3 | * | ||
4 | * Utility definitions for the ecm function | ||
5 | * | ||
6 | * Copyright (c) 2013 Samsung Electronics Co., Ltd. | ||
7 | * http://www.samsung.com | ||
8 | * | ||
9 | * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #ifndef U_ECM_H | ||
17 | #define U_ECM_H | ||
18 | |||
19 | #include <linux/usb/composite.h> | ||
20 | |||
21 | struct f_ecm_opts { | ||
22 | struct usb_function_instance func_inst; | ||
23 | struct net_device *net; | ||
24 | bool bound; | ||
25 | |||
26 | /* | ||
27 | * Read/write access to configfs attributes is handled by configfs. | ||
28 | * | ||
29 | * This is to protect the data from concurrent access by read/write | ||
30 | * and create symlink/remove symlink. | ||
31 | */ | ||
32 | struct mutex lock; | ||
33 | int refcnt; | ||
34 | }; | ||
35 | |||
36 | #endif /* U_ECM_H */ | ||
diff --git a/drivers/usb/gadget/u_eem.h b/drivers/usb/gadget/u_eem.h new file mode 100644 index 000000000000..e3ae97874c4f --- /dev/null +++ b/drivers/usb/gadget/u_eem.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * u_eem.h | ||
3 | * | ||
4 | * Utility definitions for the eem function | ||
5 | * | ||
6 | * Copyright (c) 2013 Samsung Electronics Co., Ltd. | ||
7 | * http://www.samsung.com | ||
8 | * | ||
9 | * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #ifndef U_EEM_H | ||
17 | #define U_EEM_H | ||
18 | |||
19 | #include <linux/usb/composite.h> | ||
20 | |||
21 | struct f_eem_opts { | ||
22 | struct usb_function_instance func_inst; | ||
23 | struct net_device *net; | ||
24 | bool bound; | ||
25 | |||
26 | /* | ||
27 | * Read/write access to configfs attributes is handled by configfs. | ||
28 | * | ||
29 | * This is to protect the data from concurrent access by read/write | ||
30 | * and create symlink/remove symlink. | ||
31 | */ | ||
32 | struct mutex lock; | ||
33 | int refcnt; | ||
34 | }; | ||
35 | |||
36 | #endif /* U_EEM_H */ | ||
diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c index 4b76124ce96b..2aae0d61bb19 100644 --- a/drivers/usb/gadget/u_ether.c +++ b/drivers/usb/gadget/u_ether.c | |||
@@ -63,6 +63,8 @@ struct eth_dev { | |||
63 | 63 | ||
64 | struct sk_buff_head rx_frames; | 64 | struct sk_buff_head rx_frames; |
65 | 65 | ||
66 | unsigned qmult; | ||
67 | |||
66 | unsigned header_len; | 68 | unsigned header_len; |
67 | struct sk_buff *(*wrap)(struct gether *, struct sk_buff *skb); | 69 | struct sk_buff *(*wrap)(struct gether *, struct sk_buff *skb); |
68 | int (*unwrap)(struct gether *, | 70 | int (*unwrap)(struct gether *, |
@@ -76,6 +78,7 @@ struct eth_dev { | |||
76 | 78 | ||
77 | bool zlp; | 79 | bool zlp; |
78 | u8 host_mac[ETH_ALEN]; | 80 | u8 host_mac[ETH_ALEN]; |
81 | u8 dev_mac[ETH_ALEN]; | ||
79 | }; | 82 | }; |
80 | 83 | ||
81 | /*-------------------------------------------------------------------------*/ | 84 | /*-------------------------------------------------------------------------*/ |
@@ -84,12 +87,8 @@ struct eth_dev { | |||
84 | 87 | ||
85 | #define DEFAULT_QLEN 2 /* double buffering by default */ | 88 | #define DEFAULT_QLEN 2 /* double buffering by default */ |
86 | 89 | ||
87 | static unsigned qmult = 5; | ||
88 | module_param(qmult, uint, S_IRUGO|S_IWUSR); | ||
89 | MODULE_PARM_DESC(qmult, "queue length multiplier at high/super speed"); | ||
90 | |||
91 | /* for dual-speed hardware, use deeper queues at high/super speed */ | 90 | /* for dual-speed hardware, use deeper queues at high/super speed */ |
92 | static inline int qlen(struct usb_gadget *gadget) | 91 | static inline int qlen(struct usb_gadget *gadget, unsigned qmult) |
93 | { | 92 | { |
94 | if (gadget_is_dualspeed(gadget) && (gadget->speed == USB_SPEED_HIGH || | 93 | if (gadget_is_dualspeed(gadget) && (gadget->speed == USB_SPEED_HIGH || |
95 | gadget->speed == USB_SPEED_SUPER)) | 94 | gadget->speed == USB_SPEED_SUPER)) |
@@ -588,7 +587,7 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb, | |||
588 | if (gadget_is_dualspeed(dev->gadget)) | 587 | if (gadget_is_dualspeed(dev->gadget)) |
589 | req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH || | 588 | req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH || |
590 | dev->gadget->speed == USB_SPEED_SUPER) | 589 | dev->gadget->speed == USB_SPEED_SUPER) |
591 | ? ((atomic_read(&dev->tx_qlen) % qmult) != 0) | 590 | ? ((atomic_read(&dev->tx_qlen) % dev->qmult) != 0) |
592 | : 0; | 591 | : 0; |
593 | 592 | ||
594 | retval = usb_ep_queue(in, req, GFP_ATOMIC); | 593 | retval = usb_ep_queue(in, req, GFP_ATOMIC); |
@@ -697,16 +696,6 @@ static int eth_stop(struct net_device *net) | |||
697 | 696 | ||
698 | /*-------------------------------------------------------------------------*/ | 697 | /*-------------------------------------------------------------------------*/ |
699 | 698 | ||
700 | /* initial value, changed by "ifconfig usb0 hw ether xx:xx:xx:xx:xx:xx" */ | ||
701 | static char *dev_addr; | ||
702 | module_param(dev_addr, charp, S_IRUGO); | ||
703 | MODULE_PARM_DESC(dev_addr, "Device Ethernet Address"); | ||
704 | |||
705 | /* this address is invisible to ifconfig */ | ||
706 | static char *host_addr; | ||
707 | module_param(host_addr, charp, S_IRUGO); | ||
708 | MODULE_PARM_DESC(host_addr, "Host Ethernet Address"); | ||
709 | |||
710 | static int get_ether_addr(const char *str, u8 *dev_addr) | 699 | static int get_ether_addr(const char *str, u8 *dev_addr) |
711 | { | 700 | { |
712 | if (str) { | 701 | if (str) { |
@@ -728,6 +717,17 @@ static int get_ether_addr(const char *str, u8 *dev_addr) | |||
728 | return 1; | 717 | return 1; |
729 | } | 718 | } |
730 | 719 | ||
720 | static int get_ether_addr_str(u8 dev_addr[ETH_ALEN], char *str, int len) | ||
721 | { | ||
722 | if (len < 18) | ||
723 | return -EINVAL; | ||
724 | |||
725 | snprintf(str, len, "%02x:%02x:%02x:%02x:%02x:%02x", | ||
726 | dev_addr[0], dev_addr[1], dev_addr[2], | ||
727 | dev_addr[3], dev_addr[4], dev_addr[5]); | ||
728 | return 18; | ||
729 | } | ||
730 | |||
731 | static const struct net_device_ops eth_netdev_ops = { | 731 | static const struct net_device_ops eth_netdev_ops = { |
732 | .ndo_open = eth_open, | 732 | .ndo_open = eth_open, |
733 | .ndo_stop = eth_stop, | 733 | .ndo_stop = eth_stop, |
@@ -755,8 +755,9 @@ static struct device_type gadget_type = { | |||
755 | * | 755 | * |
756 | * Returns negative errno, or zero on success | 756 | * Returns negative errno, or zero on success |
757 | */ | 757 | */ |
758 | struct eth_dev *gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN], | 758 | struct eth_dev *gether_setup_name(struct usb_gadget *g, |
759 | const char *netname) | 759 | const char *dev_addr, const char *host_addr, |
760 | u8 ethaddr[ETH_ALEN], unsigned qmult, const char *netname) | ||
760 | { | 761 | { |
761 | struct eth_dev *dev; | 762 | struct eth_dev *dev; |
762 | struct net_device *net; | 763 | struct net_device *net; |
@@ -777,6 +778,7 @@ struct eth_dev *gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN], | |||
777 | 778 | ||
778 | /* network device setup */ | 779 | /* network device setup */ |
779 | dev->net = net; | 780 | dev->net = net; |
781 | dev->qmult = qmult; | ||
780 | snprintf(net->name, sizeof(net->name), "%s%%d", netname); | 782 | snprintf(net->name, sizeof(net->name), "%s%%d", netname); |
781 | 783 | ||
782 | if (get_ether_addr(dev_addr, net->dev_addr)) | 784 | if (get_ether_addr(dev_addr, net->dev_addr)) |
@@ -806,7 +808,8 @@ struct eth_dev *gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN], | |||
806 | INFO(dev, "MAC %pM\n", net->dev_addr); | 808 | INFO(dev, "MAC %pM\n", net->dev_addr); |
807 | INFO(dev, "HOST MAC %pM\n", dev->host_mac); | 809 | INFO(dev, "HOST MAC %pM\n", dev->host_mac); |
808 | 810 | ||
809 | /* two kinds of host-initiated state changes: | 811 | /* |
812 | * two kinds of host-initiated state changes: | ||
810 | * - iff DATA transfer is active, carrier is "on" | 813 | * - iff DATA transfer is active, carrier is "on" |
811 | * - tx queueing enabled if open *and* carrier is "on" | 814 | * - tx queueing enabled if open *and* carrier is "on" |
812 | */ | 815 | */ |
@@ -815,6 +818,186 @@ struct eth_dev *gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN], | |||
815 | 818 | ||
816 | return dev; | 819 | return dev; |
817 | } | 820 | } |
821 | EXPORT_SYMBOL(gether_setup_name); | ||
822 | |||
823 | struct net_device *gether_setup_name_default(const char *netname) | ||
824 | { | ||
825 | struct net_device *net; | ||
826 | struct eth_dev *dev; | ||
827 | |||
828 | net = alloc_etherdev(sizeof(*dev)); | ||
829 | if (!net) | ||
830 | return ERR_PTR(-ENOMEM); | ||
831 | |||
832 | dev = netdev_priv(net); | ||
833 | spin_lock_init(&dev->lock); | ||
834 | spin_lock_init(&dev->req_lock); | ||
835 | INIT_WORK(&dev->work, eth_work); | ||
836 | INIT_LIST_HEAD(&dev->tx_reqs); | ||
837 | INIT_LIST_HEAD(&dev->rx_reqs); | ||
838 | |||
839 | skb_queue_head_init(&dev->rx_frames); | ||
840 | |||
841 | /* network device setup */ | ||
842 | dev->net = net; | ||
843 | dev->qmult = QMULT_DEFAULT; | ||
844 | snprintf(net->name, sizeof(net->name), "%s%%d", netname); | ||
845 | |||
846 | eth_random_addr(dev->dev_mac); | ||
847 | pr_warn("using random %s ethernet address\n", "self"); | ||
848 | eth_random_addr(dev->host_mac); | ||
849 | pr_warn("using random %s ethernet address\n", "host"); | ||
850 | |||
851 | net->netdev_ops = ð_netdev_ops; | ||
852 | |||
853 | SET_ETHTOOL_OPS(net, &ops); | ||
854 | SET_NETDEV_DEVTYPE(net, &gadget_type); | ||
855 | |||
856 | return net; | ||
857 | } | ||
858 | EXPORT_SYMBOL(gether_setup_name_default); | ||
859 | |||
860 | int gether_register_netdev(struct net_device *net) | ||
861 | { | ||
862 | struct eth_dev *dev; | ||
863 | struct usb_gadget *g; | ||
864 | struct sockaddr sa; | ||
865 | int status; | ||
866 | |||
867 | if (!net->dev.parent) | ||
868 | return -EINVAL; | ||
869 | dev = netdev_priv(net); | ||
870 | g = dev->gadget; | ||
871 | status = register_netdev(net); | ||
872 | if (status < 0) { | ||
873 | dev_dbg(&g->dev, "register_netdev failed, %d\n", status); | ||
874 | return status; | ||
875 | } else { | ||
876 | INFO(dev, "HOST MAC %pM\n", dev->host_mac); | ||
877 | |||
878 | /* two kinds of host-initiated state changes: | ||
879 | * - iff DATA transfer is active, carrier is "on" | ||
880 | * - tx queueing enabled if open *and* carrier is "on" | ||
881 | */ | ||
882 | netif_carrier_off(net); | ||
883 | } | ||
884 | sa.sa_family = net->type; | ||
885 | memcpy(sa.sa_data, dev->dev_mac, ETH_ALEN); | ||
886 | rtnl_lock(); | ||
887 | status = dev_set_mac_address(net, &sa); | ||
888 | rtnl_unlock(); | ||
889 | if (status) | ||
890 | pr_warn("cannot set self ethernet address: %d\n", status); | ||
891 | else | ||
892 | INFO(dev, "MAC %pM\n", dev->dev_mac); | ||
893 | |||
894 | return status; | ||
895 | } | ||
896 | EXPORT_SYMBOL(gether_register_netdev); | ||
897 | |||
898 | void gether_set_gadget(struct net_device *net, struct usb_gadget *g) | ||
899 | { | ||
900 | struct eth_dev *dev; | ||
901 | |||
902 | dev = netdev_priv(net); | ||
903 | dev->gadget = g; | ||
904 | SET_NETDEV_DEV(net, &g->dev); | ||
905 | } | ||
906 | EXPORT_SYMBOL(gether_set_gadget); | ||
907 | |||
908 | int gether_set_dev_addr(struct net_device *net, const char *dev_addr) | ||
909 | { | ||
910 | struct eth_dev *dev; | ||
911 | u8 new_addr[ETH_ALEN]; | ||
912 | |||
913 | dev = netdev_priv(net); | ||
914 | if (get_ether_addr(dev_addr, new_addr)) | ||
915 | return -EINVAL; | ||
916 | memcpy(dev->dev_mac, new_addr, ETH_ALEN); | ||
917 | return 0; | ||
918 | } | ||
919 | EXPORT_SYMBOL(gether_set_dev_addr); | ||
920 | |||
921 | int gether_get_dev_addr(struct net_device *net, char *dev_addr, int len) | ||
922 | { | ||
923 | struct eth_dev *dev; | ||
924 | |||
925 | dev = netdev_priv(net); | ||
926 | return get_ether_addr_str(dev->dev_mac, dev_addr, len); | ||
927 | } | ||
928 | EXPORT_SYMBOL(gether_get_dev_addr); | ||
929 | |||
930 | int gether_set_host_addr(struct net_device *net, const char *host_addr) | ||
931 | { | ||
932 | struct eth_dev *dev; | ||
933 | u8 new_addr[ETH_ALEN]; | ||
934 | |||
935 | dev = netdev_priv(net); | ||
936 | if (get_ether_addr(host_addr, new_addr)) | ||
937 | return -EINVAL; | ||
938 | memcpy(dev->host_mac, new_addr, ETH_ALEN); | ||
939 | return 0; | ||
940 | } | ||
941 | EXPORT_SYMBOL(gether_set_host_addr); | ||
942 | |||
943 | int gether_get_host_addr(struct net_device *net, char *host_addr, int len) | ||
944 | { | ||
945 | struct eth_dev *dev; | ||
946 | |||
947 | dev = netdev_priv(net); | ||
948 | return get_ether_addr_str(dev->host_mac, host_addr, len); | ||
949 | } | ||
950 | EXPORT_SYMBOL(gether_get_host_addr); | ||
951 | |||
952 | int gether_get_host_addr_cdc(struct net_device *net, char *host_addr, int len) | ||
953 | { | ||
954 | struct eth_dev *dev; | ||
955 | |||
956 | if (len < 13) | ||
957 | return -EINVAL; | ||
958 | |||
959 | dev = netdev_priv(net); | ||
960 | snprintf(host_addr, len, "%pm", dev->host_mac); | ||
961 | |||
962 | return strlen(host_addr); | ||
963 | } | ||
964 | EXPORT_SYMBOL(gether_get_host_addr_cdc); | ||
965 | |||
966 | void gether_get_host_addr_u8(struct net_device *net, u8 host_mac[ETH_ALEN]) | ||
967 | { | ||
968 | struct eth_dev *dev; | ||
969 | |||
970 | dev = netdev_priv(net); | ||
971 | memcpy(host_mac, dev->host_mac, ETH_ALEN); | ||
972 | } | ||
973 | EXPORT_SYMBOL(gether_get_host_addr_u8); | ||
974 | |||
975 | void gether_set_qmult(struct net_device *net, unsigned qmult) | ||
976 | { | ||
977 | struct eth_dev *dev; | ||
978 | |||
979 | dev = netdev_priv(net); | ||
980 | dev->qmult = qmult; | ||
981 | } | ||
982 | EXPORT_SYMBOL(gether_set_qmult); | ||
983 | |||
984 | unsigned gether_get_qmult(struct net_device *net) | ||
985 | { | ||
986 | struct eth_dev *dev; | ||
987 | |||
988 | dev = netdev_priv(net); | ||
989 | return dev->qmult; | ||
990 | } | ||
991 | EXPORT_SYMBOL(gether_get_qmult); | ||
992 | |||
993 | int gether_get_ifname(struct net_device *net, char *name, int len) | ||
994 | { | ||
995 | rtnl_lock(); | ||
996 | strlcpy(name, netdev_name(net), len); | ||
997 | rtnl_unlock(); | ||
998 | return strlen(name); | ||
999 | } | ||
1000 | EXPORT_SYMBOL(gether_get_ifname); | ||
818 | 1001 | ||
819 | /** | 1002 | /** |
820 | * gether_cleanup - remove Ethernet-over-USB device | 1003 | * gether_cleanup - remove Ethernet-over-USB device |
@@ -831,6 +1014,7 @@ void gether_cleanup(struct eth_dev *dev) | |||
831 | flush_work(&dev->work); | 1014 | flush_work(&dev->work); |
832 | free_netdev(dev->net); | 1015 | free_netdev(dev->net); |
833 | } | 1016 | } |
1017 | EXPORT_SYMBOL(gether_cleanup); | ||
834 | 1018 | ||
835 | /** | 1019 | /** |
836 | * gether_connect - notify network layer that USB link is active | 1020 | * gether_connect - notify network layer that USB link is active |
@@ -873,11 +1057,12 @@ struct net_device *gether_connect(struct gether *link) | |||
873 | } | 1057 | } |
874 | 1058 | ||
875 | if (result == 0) | 1059 | if (result == 0) |
876 | result = alloc_requests(dev, link, qlen(dev->gadget)); | 1060 | result = alloc_requests(dev, link, qlen(dev->gadget, |
1061 | dev->qmult)); | ||
877 | 1062 | ||
878 | if (result == 0) { | 1063 | if (result == 0) { |
879 | dev->zlp = link->is_zlp_ok; | 1064 | dev->zlp = link->is_zlp_ok; |
880 | DBG(dev, "qlen %d\n", qlen(dev->gadget)); | 1065 | DBG(dev, "qlen %d\n", qlen(dev->gadget, dev->qmult)); |
881 | 1066 | ||
882 | dev->header_len = link->header_len; | 1067 | dev->header_len = link->header_len; |
883 | dev->unwrap = link->unwrap; | 1068 | dev->unwrap = link->unwrap; |
@@ -910,6 +1095,7 @@ fail0: | |||
910 | return ERR_PTR(result); | 1095 | return ERR_PTR(result); |
911 | return dev->net; | 1096 | return dev->net; |
912 | } | 1097 | } |
1098 | EXPORT_SYMBOL(gether_connect); | ||
913 | 1099 | ||
914 | /** | 1100 | /** |
915 | * gether_disconnect - notify network layer that USB link is inactive | 1101 | * gether_disconnect - notify network layer that USB link is inactive |
@@ -980,3 +1166,7 @@ void gether_disconnect(struct gether *link) | |||
980 | dev->port_usb = NULL; | 1166 | dev->port_usb = NULL; |
981 | spin_unlock(&dev->lock); | 1167 | spin_unlock(&dev->lock); |
982 | } | 1168 | } |
1169 | EXPORT_SYMBOL(gether_disconnect); | ||
1170 | |||
1171 | MODULE_LICENSE("GPL"); | ||
1172 | MODULE_AUTHOR("David Brownell"); | ||
diff --git a/drivers/usb/gadget/u_ether.h b/drivers/usb/gadget/u_ether.h index 02522338a708..fb23d1fde8eb 100644 --- a/drivers/usb/gadget/u_ether.h +++ b/drivers/usb/gadget/u_ether.h | |||
@@ -21,6 +21,26 @@ | |||
21 | 21 | ||
22 | #include "gadget_chips.h" | 22 | #include "gadget_chips.h" |
23 | 23 | ||
24 | #define QMULT_DEFAULT 5 | ||
25 | |||
26 | /* | ||
27 | * dev_addr: initial value | ||
28 | * changed by "ifconfig usb0 hw ether xx:xx:xx:xx:xx:xx" | ||
29 | * host_addr: this address is invisible to ifconfig | ||
30 | */ | ||
31 | #define USB_ETHERNET_MODULE_PARAMETERS() \ | ||
32 | static unsigned qmult = QMULT_DEFAULT; \ | ||
33 | module_param(qmult, uint, S_IRUGO|S_IWUSR); \ | ||
34 | MODULE_PARM_DESC(qmult, "queue length multiplier at high/super speed");\ | ||
35 | \ | ||
36 | static char *dev_addr; \ | ||
37 | module_param(dev_addr, charp, S_IRUGO); \ | ||
38 | MODULE_PARM_DESC(dev_addr, "Device Ethernet Address"); \ | ||
39 | \ | ||
40 | static char *host_addr; \ | ||
41 | module_param(host_addr, charp, S_IRUGO); \ | ||
42 | MODULE_PARM_DESC(host_addr, "Host Ethernet Address") | ||
43 | |||
24 | struct eth_dev; | 44 | struct eth_dev; |
25 | 45 | ||
26 | /* | 46 | /* |
@@ -71,8 +91,9 @@ struct gether { | |||
71 | |USB_CDC_PACKET_TYPE_DIRECTED) | 91 | |USB_CDC_PACKET_TYPE_DIRECTED) |
72 | 92 | ||
73 | /* variant of gether_setup that allows customizing network device name */ | 93 | /* variant of gether_setup that allows customizing network device name */ |
74 | struct eth_dev *gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN], | 94 | struct eth_dev *gether_setup_name(struct usb_gadget *g, |
75 | const char *netname); | 95 | const char *dev_addr, const char *host_addr, |
96 | u8 ethaddr[ETH_ALEN], unsigned qmult, const char *netname); | ||
76 | 97 | ||
77 | /* netdev setup/teardown as directed by the gadget driver */ | 98 | /* netdev setup/teardown as directed by the gadget driver */ |
78 | /* gether_setup - initialize one ethernet-over-usb link | 99 | /* gether_setup - initialize one ethernet-over-usb link |
@@ -88,11 +109,145 @@ struct eth_dev *gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN], | |||
88 | * Returns negative errno, or zero on success | 109 | * Returns negative errno, or zero on success |
89 | */ | 110 | */ |
90 | static inline struct eth_dev *gether_setup(struct usb_gadget *g, | 111 | static inline struct eth_dev *gether_setup(struct usb_gadget *g, |
91 | u8 ethaddr[ETH_ALEN]) | 112 | const char *dev_addr, const char *host_addr, |
113 | u8 ethaddr[ETH_ALEN], unsigned qmult) | ||
92 | { | 114 | { |
93 | return gether_setup_name(g, ethaddr, "usb"); | 115 | return gether_setup_name(g, dev_addr, host_addr, ethaddr, qmult, "usb"); |
94 | } | 116 | } |
95 | 117 | ||
118 | /* | ||
119 | * variant of gether_setup_default that allows customizing | ||
120 | * network device name | ||
121 | */ | ||
122 | struct net_device *gether_setup_name_default(const char *netname); | ||
123 | |||
124 | /* | ||
125 | * gether_register_netdev - register the net device | ||
126 | * @net: net device to register | ||
127 | * | ||
128 | * Registers the net device associated with this ethernet-over-usb link | ||
129 | * | ||
130 | */ | ||
131 | int gether_register_netdev(struct net_device *net); | ||
132 | |||
133 | /* gether_setup_default - initialize one ethernet-over-usb link | ||
134 | * Context: may sleep | ||
135 | * | ||
136 | * This sets up the single network link that may be exported by a | ||
137 | * gadget driver using this framework. The link layer addresses | ||
138 | * are set to random values. | ||
139 | * | ||
140 | * Returns negative errno, or zero on success | ||
141 | */ | ||
142 | static inline struct net_device *gether_setup_default(void) | ||
143 | { | ||
144 | return gether_setup_name_default("usb"); | ||
145 | } | ||
146 | |||
147 | /** | ||
148 | * gether_set_gadget - initialize one ethernet-over-usb link with a gadget | ||
149 | * @net: device representing this link | ||
150 | * @g: the gadget to initialize with | ||
151 | * | ||
152 | * This associates one ethernet-over-usb link with a gadget. | ||
153 | */ | ||
154 | void gether_set_gadget(struct net_device *net, struct usb_gadget *g); | ||
155 | |||
156 | /** | ||
157 | * gether_set_dev_addr - initialize an ethernet-over-usb link with eth address | ||
158 | * @net: device representing this link | ||
159 | * @dev_addr: eth address of this device | ||
160 | * | ||
161 | * This sets the device-side Ethernet address of this ethernet-over-usb link | ||
162 | * if dev_addr is correct. | ||
163 | * Returns negative errno if the new address is incorrect. | ||
164 | */ | ||
165 | int gether_set_dev_addr(struct net_device *net, const char *dev_addr); | ||
166 | |||
167 | /** | ||
168 | * gether_get_dev_addr - get an ethernet-over-usb link eth address | ||
169 | * @net: device representing this link | ||
170 | * @dev_addr: place to store device's eth address | ||
171 | * @len: length of the @dev_addr buffer | ||
172 | * | ||
173 | * This gets the device-side Ethernet address of this ethernet-over-usb link. | ||
174 | * Returns zero on success, else negative errno. | ||
175 | */ | ||
176 | int gether_get_dev_addr(struct net_device *net, char *dev_addr, int len); | ||
177 | |||
178 | /** | ||
179 | * gether_set_host_addr - initialize an ethernet-over-usb link with host address | ||
180 | * @net: device representing this link | ||
181 | * @host_addr: eth address of the host | ||
182 | * | ||
183 | * This sets the host-side Ethernet address of this ethernet-over-usb link | ||
184 | * if host_addr is correct. | ||
185 | * Returns negative errno if the new address is incorrect. | ||
186 | */ | ||
187 | int gether_set_host_addr(struct net_device *net, const char *host_addr); | ||
188 | |||
189 | /** | ||
190 | * gether_get_host_addr - get an ethernet-over-usb link host address | ||
191 | * @net: device representing this link | ||
192 | * @host_addr: place to store eth address of the host | ||
193 | * @len: length of the @host_addr buffer | ||
194 | * | ||
195 | * This gets the host-side Ethernet address of this ethernet-over-usb link. | ||
196 | * Returns zero on success, else negative errno. | ||
197 | */ | ||
198 | int gether_get_host_addr(struct net_device *net, char *host_addr, int len); | ||
199 | |||
200 | /** | ||
201 | * gether_get_host_addr_cdc - get an ethernet-over-usb link host address | ||
202 | * @net: device representing this link | ||
203 | * @host_addr: place to store eth address of the host | ||
204 | * @len: length of the @host_addr buffer | ||
205 | * | ||
206 | * This gets the CDC formatted host-side Ethernet address of this | ||
207 | * ethernet-over-usb link. | ||
208 | * Returns zero on success, else negative errno. | ||
209 | */ | ||
210 | int gether_get_host_addr_cdc(struct net_device *net, char *host_addr, int len); | ||
211 | |||
212 | /** | ||
213 | * gether_get_host_addr_u8 - get an ethernet-over-usb link host address | ||
214 | * @net: device representing this link | ||
215 | * @host_mac: place to store the eth address of the host | ||
216 | * | ||
217 | * This gets the binary formatted host-side Ethernet address of this | ||
218 | * ethernet-over-usb link. | ||
219 | */ | ||
220 | void gether_get_host_addr_u8(struct net_device *net, u8 host_mac[ETH_ALEN]); | ||
221 | |||
222 | /** | ||
223 | * gether_set_qmult - initialize an ethernet-over-usb link with a multiplier | ||
224 | * @net: device representing this link | ||
225 | * @qmult: queue multiplier | ||
226 | * | ||
227 | * This sets the queue length multiplier of this ethernet-over-usb link. | ||
228 | * For higher speeds use longer queues. | ||
229 | */ | ||
230 | void gether_set_qmult(struct net_device *net, unsigned qmult); | ||
231 | |||
232 | /** | ||
233 | * gether_get_qmult - get an ethernet-over-usb link multiplier | ||
234 | * @net: device representing this link | ||
235 | * | ||
236 | * This gets the queue length multiplier of this ethernet-over-usb link. | ||
237 | */ | ||
238 | unsigned gether_get_qmult(struct net_device *net); | ||
239 | |||
240 | /** | ||
241 | * gether_get_ifname - get an ethernet-over-usb link interface name | ||
242 | * @net: device representing this link | ||
243 | * @name: place to store the interface name | ||
244 | * @len: length of the @name buffer | ||
245 | * | ||
246 | * This gets the interface name of this ethernet-over-usb link. | ||
247 | * Returns zero on success, else negative errno. | ||
248 | */ | ||
249 | int gether_get_ifname(struct net_device *net, char *name, int len); | ||
250 | |||
96 | void gether_cleanup(struct eth_dev *dev); | 251 | void gether_cleanup(struct eth_dev *dev); |
97 | 252 | ||
98 | /* connect/disconnect is handled by individual functions */ | 253 | /* connect/disconnect is handled by individual functions */ |
@@ -117,9 +272,6 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], | |||
117 | struct eth_dev *dev); | 272 | struct eth_dev *dev); |
118 | int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], | 273 | int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], |
119 | struct eth_dev *dev); | 274 | struct eth_dev *dev); |
120 | int ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], | ||
121 | struct eth_dev *dev); | ||
122 | int eem_bind_config(struct usb_configuration *c, struct eth_dev *dev); | ||
123 | 275 | ||
124 | #ifdef USB_ETH_RNDIS | 276 | #ifdef USB_ETH_RNDIS |
125 | 277 | ||
diff --git a/drivers/usb/gadget/u_ether_configfs.h b/drivers/usb/gadget/u_ether_configfs.h new file mode 100644 index 000000000000..bcbd30146cfd --- /dev/null +++ b/drivers/usb/gadget/u_ether_configfs.h | |||
@@ -0,0 +1,164 @@ | |||
1 | /* | ||
2 | * u_ether_configfs.h | ||
3 | * | ||
4 | * Utility definitions for configfs support in USB Ethernet functions | ||
5 | * | ||
6 | * Copyright (c) 2013 Samsung Electronics Co., Ltd. | ||
7 | * http://www.samsung.com | ||
8 | * | ||
9 | * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #ifndef __U_ETHER_CONFIGFS_H | ||
17 | #define __U_ETHER_CONFIGFS_H | ||
18 | |||
19 | #define USB_ETHERNET_CONFIGFS_ITEM(_f_) \ | ||
20 | CONFIGFS_ATTR_STRUCT(f_##_f_##_opts); \ | ||
21 | CONFIGFS_ATTR_OPS(f_##_f_##_opts); \ | ||
22 | \ | ||
23 | static void _f_##_attr_release(struct config_item *item) \ | ||
24 | { \ | ||
25 | struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ | ||
26 | \ | ||
27 | usb_put_function_instance(&opts->func_inst); \ | ||
28 | } \ | ||
29 | \ | ||
30 | static struct configfs_item_operations _f_##_item_ops = { \ | ||
31 | .release = _f_##_attr_release, \ | ||
32 | .show_attribute = f_##_f_##_opts_attr_show, \ | ||
33 | .store_attribute = f_##_f_##_opts_attr_store, \ | ||
34 | } | ||
35 | |||
36 | #define USB_ETHERNET_CONFIGFS_ITEM_ATTR_DEV_ADDR(_f_) \ | ||
37 | static ssize_t _f_##_opts_dev_addr_show(struct f_##_f_##_opts *opts, \ | ||
38 | char *page) \ | ||
39 | { \ | ||
40 | int result; \ | ||
41 | \ | ||
42 | mutex_lock(&opts->lock); \ | ||
43 | result = gether_get_dev_addr(opts->net, page, PAGE_SIZE); \ | ||
44 | mutex_unlock(&opts->lock); \ | ||
45 | \ | ||
46 | return result; \ | ||
47 | } \ | ||
48 | \ | ||
49 | static ssize_t _f_##_opts_dev_addr_store(struct f_##_f_##_opts *opts, \ | ||
50 | const char *page, size_t len)\ | ||
51 | { \ | ||
52 | int ret; \ | ||
53 | \ | ||
54 | mutex_lock(&opts->lock); \ | ||
55 | if (opts->refcnt) { \ | ||
56 | mutex_unlock(&opts->lock); \ | ||
57 | return -EBUSY; \ | ||
58 | } \ | ||
59 | \ | ||
60 | ret = gether_set_dev_addr(opts->net, page); \ | ||
61 | mutex_unlock(&opts->lock); \ | ||
62 | if (!ret) \ | ||
63 | ret = len; \ | ||
64 | return ret; \ | ||
65 | } \ | ||
66 | \ | ||
67 | static struct f_##_f_##_opts_attribute f_##_f_##_opts_dev_addr = \ | ||
68 | __CONFIGFS_ATTR(dev_addr, S_IRUGO | S_IWUSR, \ | ||
69 | _f_##_opts_dev_addr_show, \ | ||
70 | _f_##_opts_dev_addr_store) | ||
71 | |||
72 | #define USB_ETHERNET_CONFIGFS_ITEM_ATTR_HOST_ADDR(_f_) \ | ||
73 | static ssize_t _f_##_opts_host_addr_show(struct f_##_f_##_opts *opts, \ | ||
74 | char *page) \ | ||
75 | { \ | ||
76 | int result; \ | ||
77 | \ | ||
78 | mutex_lock(&opts->lock); \ | ||
79 | result = gether_get_host_addr(opts->net, page, PAGE_SIZE); \ | ||
80 | mutex_unlock(&opts->lock); \ | ||
81 | \ | ||
82 | return result; \ | ||
83 | } \ | ||
84 | \ | ||
85 | static ssize_t _f_##_opts_host_addr_store(struct f_##_f_##_opts *opts, \ | ||
86 | const char *page, size_t len)\ | ||
87 | { \ | ||
88 | int ret; \ | ||
89 | \ | ||
90 | mutex_lock(&opts->lock); \ | ||
91 | if (opts->refcnt) { \ | ||
92 | mutex_unlock(&opts->lock); \ | ||
93 | return -EBUSY; \ | ||
94 | } \ | ||
95 | \ | ||
96 | ret = gether_set_host_addr(opts->net, page); \ | ||
97 | mutex_unlock(&opts->lock); \ | ||
98 | if (!ret) \ | ||
99 | ret = len; \ | ||
100 | return ret; \ | ||
101 | } \ | ||
102 | \ | ||
103 | static struct f_##_f_##_opts_attribute f_##_f_##_opts_host_addr = \ | ||
104 | __CONFIGFS_ATTR(host_addr, S_IRUGO | S_IWUSR, \ | ||
105 | _f_##_opts_host_addr_show, \ | ||
106 | _f_##_opts_host_addr_store) | ||
107 | |||
108 | #define USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(_f_) \ | ||
109 | static ssize_t _f_##_opts_qmult_show(struct f_##_f_##_opts *opts, \ | ||
110 | char *page) \ | ||
111 | { \ | ||
112 | unsigned qmult; \ | ||
113 | \ | ||
114 | mutex_lock(&opts->lock); \ | ||
115 | qmult = gether_get_qmult(opts->net); \ | ||
116 | mutex_unlock(&opts->lock); \ | ||
117 | return sprintf(page, "%d", qmult); \ | ||
118 | } \ | ||
119 | \ | ||
120 | static ssize_t _f_##_opts_qmult_store(struct f_##_f_##_opts *opts, \ | ||
121 | const char *page, size_t len)\ | ||
122 | { \ | ||
123 | u8 val; \ | ||
124 | int ret; \ | ||
125 | \ | ||
126 | mutex_lock(&opts->lock); \ | ||
127 | if (opts->refcnt) { \ | ||
128 | ret = -EBUSY; \ | ||
129 | goto out; \ | ||
130 | } \ | ||
131 | \ | ||
132 | ret = kstrtou8(page, 0, &val); \ | ||
133 | if (ret) \ | ||
134 | goto out; \ | ||
135 | \ | ||
136 | gether_set_qmult(opts->net, val); \ | ||
137 | ret = len; \ | ||
138 | out: \ | ||
139 | mutex_unlock(&opts->lock); \ | ||
140 | return ret; \ | ||
141 | } \ | ||
142 | \ | ||
143 | static struct f_##_f_##_opts_attribute f_##_f_##_opts_qmult = \ | ||
144 | __CONFIGFS_ATTR(qmult, S_IRUGO | S_IWUSR, \ | ||
145 | _f_##_opts_qmult_show, \ | ||
146 | _f_##_opts_qmult_store) | ||
147 | |||
148 | #define USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(_f_) \ | ||
149 | static ssize_t _f_##_opts_ifname_show(struct f_##_f_##_opts *opts, \ | ||
150 | char *page) \ | ||
151 | { \ | ||
152 | int ret; \ | ||
153 | \ | ||
154 | mutex_lock(&opts->lock); \ | ||
155 | ret = gether_get_ifname(opts->net, page, PAGE_SIZE); \ | ||
156 | mutex_unlock(&opts->lock); \ | ||
157 | \ | ||
158 | return ret; \ | ||
159 | } \ | ||
160 | \ | ||
161 | static struct f_##_f_##_opts_attribute f_##_f_##_opts_ifname = \ | ||
162 | __CONFIGFS_ATTR_RO(ifname, _f_##_opts_ifname_show) | ||
163 | |||
164 | #endif /* __U_ETHER_CONFIGFS_H */ | ||
diff --git a/drivers/usb/gadget/u_gether.h b/drivers/usb/gadget/u_gether.h new file mode 100644 index 000000000000..d4078426ba5d --- /dev/null +++ b/drivers/usb/gadget/u_gether.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * u_gether.h | ||
3 | * | ||
4 | * Utility definitions for the subset function | ||
5 | * | ||
6 | * Copyright (c) 2013 Samsung Electronics Co., Ltd. | ||
7 | * http://www.samsung.com | ||
8 | * | ||
9 | * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #ifndef U_GETHER_H | ||
17 | #define U_GETHER_H | ||
18 | |||
19 | #include <linux/usb/composite.h> | ||
20 | |||
21 | struct f_gether_opts { | ||
22 | struct usb_function_instance func_inst; | ||
23 | struct net_device *net; | ||
24 | bool bound; | ||
25 | |||
26 | /* | ||
27 | * Read/write access to configfs attributes is handled by configfs. | ||
28 | * | ||
29 | * This is to protect the data from concurrent access by read/write | ||
30 | * and create symlink/remove symlink. | ||
31 | */ | ||
32 | struct mutex lock; | ||
33 | int refcnt; | ||
34 | }; | ||
35 | |||
36 | #endif /* U_GETHER_H */ | ||
diff --git a/drivers/usb/gadget/u_ncm.h b/drivers/usb/gadget/u_ncm.h new file mode 100644 index 000000000000..ce0f3a78ca13 --- /dev/null +++ b/drivers/usb/gadget/u_ncm.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * u_ncm.h | ||
3 | * | ||
4 | * Utility definitions for the ncm function | ||
5 | * | ||
6 | * Copyright (c) 2013 Samsung Electronics Co., Ltd. | ||
7 | * http://www.samsung.com | ||
8 | * | ||
9 | * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #ifndef U_NCM_H | ||
17 | #define U_NCM_H | ||
18 | |||
19 | #include <linux/usb/composite.h> | ||
20 | |||
21 | struct f_ncm_opts { | ||
22 | struct usb_function_instance func_inst; | ||
23 | struct net_device *net; | ||
24 | bool bound; | ||
25 | |||
26 | /* | ||
27 | * Read/write access to configfs attributes is handled by configfs. | ||
28 | * | ||
29 | * This is to protect the data from concurrent access by read/write | ||
30 | * and create symlink/remove symlink. | ||
31 | */ | ||
32 | struct mutex lock; | ||
33 | int refcnt; | ||
34 | }; | ||
35 | |||
36 | #endif /* U_NCM_H */ | ||
diff --git a/drivers/usb/gadget/u_phonet.h b/drivers/usb/gadget/u_phonet.h index 09a75259b6cd..98ced18779ea 100644 --- a/drivers/usb/gadget/u_phonet.h +++ b/drivers/usb/gadget/u_phonet.h | |||
@@ -14,8 +14,16 @@ | |||
14 | #include <linux/usb/composite.h> | 14 | #include <linux/usb/composite.h> |
15 | #include <linux/usb/cdc.h> | 15 | #include <linux/usb/cdc.h> |
16 | 16 | ||
17 | int gphonet_setup(struct usb_gadget *gadget); | 17 | struct f_phonet_opts { |
18 | int phonet_bind_config(struct usb_configuration *c); | 18 | struct usb_function_instance func_inst; |
19 | void gphonet_cleanup(void); | 19 | bool bound; |
20 | struct net_device *net; | ||
21 | }; | ||
22 | |||
23 | struct net_device *gphonet_setup_default(void); | ||
24 | void gphonet_set_gadget(struct net_device *net, struct usb_gadget *g); | ||
25 | int gphonet_register_netdev(struct net_device *net); | ||
26 | int phonet_bind_config(struct usb_configuration *c, struct net_device *dev); | ||
27 | void gphonet_cleanup(struct net_device *dev); | ||
20 | 28 | ||
21 | #endif /* __U_PHONET_H */ | 29 | #endif /* __U_PHONET_H */ |
diff --git a/drivers/usb/gadget/u_rndis.h b/drivers/usb/gadget/u_rndis.h new file mode 100644 index 000000000000..c62ba82e9600 --- /dev/null +++ b/drivers/usb/gadget/u_rndis.h | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | * u_rndis.h | ||
3 | * | ||
4 | * Utility definitions for the subset function | ||
5 | * | ||
6 | * Copyright (c) 2013 Samsung Electronics Co., Ltd. | ||
7 | * http://www.samsung.com | ||
8 | * | ||
9 | * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #ifndef U_RNDIS_H | ||
17 | #define U_RNDIS_H | ||
18 | |||
19 | #include <linux/usb/composite.h> | ||
20 | |||
21 | struct f_rndis_opts { | ||
22 | struct usb_function_instance func_inst; | ||
23 | u32 vendor_id; | ||
24 | const char *manufacturer; | ||
25 | struct net_device *net; | ||
26 | bool bound; | ||
27 | bool borrowed_net; | ||
28 | |||
29 | /* | ||
30 | * Read/write access to configfs attributes is handled by configfs. | ||
31 | * | ||
32 | * This is to protect the data from concurrent access by read/write | ||
33 | * and create symlink/remove symlink. | ||
34 | */ | ||
35 | struct mutex lock; | ||
36 | int refcnt; | ||
37 | }; | ||
38 | |||
39 | void rndis_borrow_net(struct usb_function_instance *f, struct net_device *net); | ||
40 | |||
41 | #endif /* U_RNDIS_H */ | ||
diff --git a/drivers/usb/gadget/uvc_queue.c b/drivers/usb/gadget/uvc_queue.c index 7ce27e35550b..e6170478ea9f 100644 --- a/drivers/usb/gadget/uvc_queue.c +++ b/drivers/usb/gadget/uvc_queue.c | |||
@@ -103,10 +103,26 @@ static void uvc_buffer_queue(struct vb2_buffer *vb) | |||
103 | spin_unlock_irqrestore(&queue->irqlock, flags); | 103 | spin_unlock_irqrestore(&queue->irqlock, flags); |
104 | } | 104 | } |
105 | 105 | ||
106 | static void uvc_wait_prepare(struct vb2_queue *vq) | ||
107 | { | ||
108 | struct uvc_video_queue *queue = vb2_get_drv_priv(vq); | ||
109 | |||
110 | mutex_unlock(&queue->mutex); | ||
111 | } | ||
112 | |||
113 | static void uvc_wait_finish(struct vb2_queue *vq) | ||
114 | { | ||
115 | struct uvc_video_queue *queue = vb2_get_drv_priv(vq); | ||
116 | |||
117 | mutex_lock(&queue->mutex); | ||
118 | } | ||
119 | |||
106 | static struct vb2_ops uvc_queue_qops = { | 120 | static struct vb2_ops uvc_queue_qops = { |
107 | .queue_setup = uvc_queue_setup, | 121 | .queue_setup = uvc_queue_setup, |
108 | .buf_prepare = uvc_buffer_prepare, | 122 | .buf_prepare = uvc_buffer_prepare, |
109 | .buf_queue = uvc_buffer_queue, | 123 | .buf_queue = uvc_buffer_queue, |
124 | .wait_prepare = uvc_wait_prepare, | ||
125 | .wait_finish = uvc_wait_finish, | ||
110 | }; | 126 | }; |
111 | 127 | ||
112 | static int uvc_queue_init(struct uvc_video_queue *queue, | 128 | static int uvc_queue_init(struct uvc_video_queue *queue, |
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 344d5e2f87d7..7d0aa5f58f7a 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig | |||
@@ -17,7 +17,6 @@ config USB_C67X00_HCD | |||
17 | 17 | ||
18 | config USB_XHCI_HCD | 18 | config USB_XHCI_HCD |
19 | tristate "xHCI HCD (USB 3.0) support" | 19 | tristate "xHCI HCD (USB 3.0) support" |
20 | depends on USB_ARCH_HAS_XHCI | ||
21 | ---help--- | 20 | ---help--- |
22 | The eXtensible Host Controller Interface (xHCI) is standard for USB 3.0 | 21 | The eXtensible Host Controller Interface (xHCI) is standard for USB 3.0 |
23 | "SuperSpeed" host controller hardware. | 22 | "SuperSpeed" host controller hardware. |
@@ -43,7 +42,6 @@ endif # USB_XHCI_HCD | |||
43 | 42 | ||
44 | config USB_EHCI_HCD | 43 | config USB_EHCI_HCD |
45 | tristate "EHCI HCD (USB 2.0) support" | 44 | tristate "EHCI HCD (USB 2.0) support" |
46 | depends on USB_ARCH_HAS_EHCI | ||
47 | ---help--- | 45 | ---help--- |
48 | The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0 | 46 | The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0 |
49 | "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware. | 47 | "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware. |
@@ -200,7 +198,7 @@ config USB_EHCI_MSM | |||
200 | has an external PHY. | 198 | has an external PHY. |
201 | 199 | ||
202 | config USB_EHCI_TEGRA | 200 | config USB_EHCI_TEGRA |
203 | boolean "NVIDIA Tegra HCD support" | 201 | tristate "NVIDIA Tegra HCD support" |
204 | depends on ARCH_TEGRA | 202 | depends on ARCH_TEGRA |
205 | select USB_EHCI_ROOT_HUB_TT | 203 | select USB_EHCI_ROOT_HUB_TT |
206 | select USB_PHY | 204 | select USB_PHY |
@@ -345,9 +343,19 @@ config USB_ISP1362_HCD | |||
345 | To compile this driver as a module, choose M here: the | 343 | To compile this driver as a module, choose M here: the |
346 | module will be called isp1362-hcd. | 344 | module will be called isp1362-hcd. |
347 | 345 | ||
346 | config USB_FUSBH200_HCD | ||
347 | tristate "FUSBH200 HCD support" | ||
348 | depends on USB | ||
349 | default N | ||
350 | ---help--- | ||
351 | Faraday FUSBH200 is designed to meet USB2.0 EHCI specification | ||
352 | with minor modification. | ||
353 | |||
354 | To compile this driver as a module, choose M here: the | ||
355 | module will be called fusbh200-hcd. | ||
356 | |||
348 | config USB_OHCI_HCD | 357 | config USB_OHCI_HCD |
349 | tristate "OHCI HCD support" | 358 | tristate "OHCI HCD (USB 1.1) support" |
350 | depends on USB_ARCH_HAS_OHCI | ||
351 | select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 | 359 | select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 |
352 | depends on USB_ISP1301 || !ARCH_LPC32XX | 360 | depends on USB_ISP1301 || !ARCH_LPC32XX |
353 | ---help--- | 361 | ---help--- |
@@ -415,8 +423,8 @@ config USB_OHCI_HCD_PPC_OF | |||
415 | default USB_OHCI_HCD_PPC_OF_BE || USB_OHCI_HCD_PPC_OF_LE | 423 | default USB_OHCI_HCD_PPC_OF_BE || USB_OHCI_HCD_PPC_OF_LE |
416 | 424 | ||
417 | config USB_OHCI_HCD_PCI | 425 | config USB_OHCI_HCD_PCI |
418 | bool "OHCI support for PCI-bus USB controllers" | 426 | tristate "OHCI support for PCI-bus USB controllers" |
419 | depends on PCI && (STB03xxx || PPC_MPC52xx || USB_OHCI_HCD_PPC_OF) | 427 | depends on PCI |
420 | default y | 428 | default y |
421 | select USB_OHCI_LITTLE_ENDIAN | 429 | select USB_OHCI_LITTLE_ENDIAN |
422 | ---help--- | 430 | ---help--- |
@@ -470,7 +478,7 @@ config USB_CNS3XXX_OHCI | |||
470 | It is needed for low-speed USB 1.0 device support. | 478 | It is needed for low-speed USB 1.0 device support. |
471 | 479 | ||
472 | config USB_OHCI_HCD_PLATFORM | 480 | config USB_OHCI_HCD_PLATFORM |
473 | bool "Generic OHCI driver for a platform device" | 481 | tristate "Generic OHCI driver for a platform device" |
474 | default n | 482 | default n |
475 | ---help--- | 483 | ---help--- |
476 | Adds an OHCI host driver for a generic platform device, which | 484 | Adds an OHCI host driver for a generic platform device, which |
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 4fb73c156d72..bea71127b15f 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile | |||
@@ -33,11 +33,16 @@ obj-$(CONFIG_USB_EHCI_HCD_SPEAR) += ehci-spear.o | |||
33 | obj-$(CONFIG_USB_EHCI_S5P) += ehci-s5p.o | 33 | obj-$(CONFIG_USB_EHCI_S5P) += ehci-s5p.o |
34 | obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-atmel.o | 34 | obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-atmel.o |
35 | obj-$(CONFIG_USB_EHCI_MSM) += ehci-msm.o | 35 | obj-$(CONFIG_USB_EHCI_MSM) += ehci-msm.o |
36 | obj-$(CONFIG_USB_EHCI_TEGRA) += ehci-tegra.o | ||
36 | 37 | ||
37 | obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o | 38 | obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o |
38 | obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o | 39 | obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o |
39 | obj-$(CONFIG_USB_ISP1362_HCD) += isp1362-hcd.o | 40 | obj-$(CONFIG_USB_ISP1362_HCD) += isp1362-hcd.o |
41 | |||
40 | obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o | 42 | obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o |
43 | obj-$(CONFIG_USB_OHCI_HCD_PCI) += ohci-pci.o | ||
44 | obj-$(CONFIG_USB_OHCI_HCD_PLATFORM) += ohci-platform.o | ||
45 | |||
41 | obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o | 46 | obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o |
42 | obj-$(CONFIG_USB_FHCI_HCD) += fhci.o | 47 | obj-$(CONFIG_USB_FHCI_HCD) += fhci.o |
43 | obj-$(CONFIG_USB_XHCI_HCD) += xhci-hcd.o | 48 | obj-$(CONFIG_USB_XHCI_HCD) += xhci-hcd.o |
@@ -52,3 +57,4 @@ obj-$(CONFIG_USB_FSL_MPH_DR_OF) += fsl-mph-dr-of.o | |||
52 | obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o | 57 | obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o |
53 | obj-$(CONFIG_USB_HCD_BCMA) += bcma-hcd.o | 58 | obj-$(CONFIG_USB_HCD_BCMA) += bcma-hcd.o |
54 | obj-$(CONFIG_USB_HCD_SSB) += ssb-hcd.o | 59 | obj-$(CONFIG_USB_HCD_SSB) += ssb-hcd.o |
60 | obj-$(CONFIG_USB_FUSBH200_HCD) += fusbh200-hcd.o | ||
diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c index 02f4611faa62..3b645ff46f7b 100644 --- a/drivers/usb/host/ehci-atmel.c +++ b/drivers/usb/host/ehci-atmel.c | |||
@@ -37,15 +37,15 @@ static int clocked; | |||
37 | 37 | ||
38 | static void atmel_start_clock(void) | 38 | static void atmel_start_clock(void) |
39 | { | 39 | { |
40 | clk_enable(iclk); | 40 | clk_prepare_enable(iclk); |
41 | clk_enable(fclk); | 41 | clk_prepare_enable(fclk); |
42 | clocked = 1; | 42 | clocked = 1; |
43 | } | 43 | } |
44 | 44 | ||
45 | static void atmel_stop_clock(void) | 45 | static void atmel_stop_clock(void) |
46 | { | 46 | { |
47 | clk_disable(fclk); | 47 | clk_disable_unprepare(fclk); |
48 | clk_disable(iclk); | 48 | clk_disable_unprepare(iclk); |
49 | clocked = 0; | 49 | clocked = 0; |
50 | } | 50 | } |
51 | 51 | ||
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 3be3df233a0e..bd831ec06dcd 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c | |||
@@ -732,6 +732,7 @@ static struct platform_driver ehci_fsl_driver = { | |||
732 | .shutdown = usb_hcd_platform_shutdown, | 732 | .shutdown = usb_hcd_platform_shutdown, |
733 | .driver = { | 733 | .driver = { |
734 | .name = "fsl-ehci", | 734 | .name = "fsl-ehci", |
735 | .owner = THIS_MODULE, | ||
735 | .pm = EHCI_FSL_PM_OPS, | 736 | .pm = EHCI_FSL_PM_OPS, |
736 | }, | 737 | }, |
737 | }; | 738 | }; |
diff --git a/drivers/usb/host/ehci-grlib.c b/drivers/usb/host/ehci-grlib.c index 5d75de9729b6..a77bd8dc33f4 100644 --- a/drivers/usb/host/ehci-grlib.c +++ b/drivers/usb/host/ehci-grlib.c | |||
@@ -153,9 +153,7 @@ err_irq: | |||
153 | 153 | ||
154 | static int ehci_hcd_grlib_remove(struct platform_device *op) | 154 | static int ehci_hcd_grlib_remove(struct platform_device *op) |
155 | { | 155 | { |
156 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); | 156 | struct usb_hcd *hcd = platform_get_drvdata(op); |
157 | |||
158 | dev_set_drvdata(&op->dev, NULL); | ||
159 | 157 | ||
160 | dev_dbg(&op->dev, "stopping GRLIB GRUSBHC EHCI USB Controller\n"); | 158 | dev_dbg(&op->dev, "stopping GRLIB GRUSBHC EHCI USB Controller\n"); |
161 | 159 | ||
@@ -171,7 +169,7 @@ static int ehci_hcd_grlib_remove(struct platform_device *op) | |||
171 | 169 | ||
172 | static void ehci_hcd_grlib_shutdown(struct platform_device *op) | 170 | static void ehci_hcd_grlib_shutdown(struct platform_device *op) |
173 | { | 171 | { |
174 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); | 172 | struct usb_hcd *hcd = platform_get_drvdata(op); |
175 | 173 | ||
176 | if (hcd->driver->shutdown) | 174 | if (hcd->driver->shutdown) |
177 | hcd->driver->shutdown(hcd); | 175 | hcd->driver->shutdown(hcd); |
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 246e124e6ac5..7abf1ce3a670 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -139,7 +139,7 @@ static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci) | |||
139 | /*-------------------------------------------------------------------------*/ | 139 | /*-------------------------------------------------------------------------*/ |
140 | 140 | ||
141 | /* | 141 | /* |
142 | * handshake - spin reading hc until handshake completes or fails | 142 | * ehci_handshake - spin reading hc until handshake completes or fails |
143 | * @ptr: address of hc register to be read | 143 | * @ptr: address of hc register to be read |
144 | * @mask: bits to look at in result of read | 144 | * @mask: bits to look at in result of read |
145 | * @done: value of those bits when handshake succeeds | 145 | * @done: value of those bits when handshake succeeds |
@@ -155,8 +155,8 @@ static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci) | |||
155 | * before driver shutdown. But it also seems to be caused by bugs in cardbus | 155 | * before driver shutdown. But it also seems to be caused by bugs in cardbus |
156 | * bridge shutdown: shutting down the bridge before the devices using it. | 156 | * bridge shutdown: shutting down the bridge before the devices using it. |
157 | */ | 157 | */ |
158 | static int handshake (struct ehci_hcd *ehci, void __iomem *ptr, | 158 | int ehci_handshake(struct ehci_hcd *ehci, void __iomem *ptr, |
159 | u32 mask, u32 done, int usec) | 159 | u32 mask, u32 done, int usec) |
160 | { | 160 | { |
161 | u32 result; | 161 | u32 result; |
162 | 162 | ||
@@ -172,6 +172,7 @@ static int handshake (struct ehci_hcd *ehci, void __iomem *ptr, | |||
172 | } while (usec > 0); | 172 | } while (usec > 0); |
173 | return -ETIMEDOUT; | 173 | return -ETIMEDOUT; |
174 | } | 174 | } |
175 | EXPORT_SYMBOL_GPL(ehci_handshake); | ||
175 | 176 | ||
176 | /* check TDI/ARC silicon is in host mode */ | 177 | /* check TDI/ARC silicon is in host mode */ |
177 | static int tdi_in_host_mode (struct ehci_hcd *ehci) | 178 | static int tdi_in_host_mode (struct ehci_hcd *ehci) |
@@ -212,7 +213,7 @@ static int ehci_halt (struct ehci_hcd *ehci) | |||
212 | spin_unlock_irq(&ehci->lock); | 213 | spin_unlock_irq(&ehci->lock); |
213 | synchronize_irq(ehci_to_hcd(ehci)->irq); | 214 | synchronize_irq(ehci_to_hcd(ehci)->irq); |
214 | 215 | ||
215 | return handshake(ehci, &ehci->regs->status, | 216 | return ehci_handshake(ehci, &ehci->regs->status, |
216 | STS_HALT, STS_HALT, 16 * 125); | 217 | STS_HALT, STS_HALT, 16 * 125); |
217 | } | 218 | } |
218 | 219 | ||
@@ -251,7 +252,7 @@ static int ehci_reset (struct ehci_hcd *ehci) | |||
251 | ehci_writel(ehci, command, &ehci->regs->command); | 252 | ehci_writel(ehci, command, &ehci->regs->command); |
252 | ehci->rh_state = EHCI_RH_HALTED; | 253 | ehci->rh_state = EHCI_RH_HALTED; |
253 | ehci->next_statechange = jiffies; | 254 | ehci->next_statechange = jiffies; |
254 | retval = handshake (ehci, &ehci->regs->command, | 255 | retval = ehci_handshake(ehci, &ehci->regs->command, |
255 | CMD_RESET, 0, 250 * 1000); | 256 | CMD_RESET, 0, 250 * 1000); |
256 | 257 | ||
257 | if (ehci->has_hostpc) { | 258 | if (ehci->has_hostpc) { |
@@ -286,7 +287,8 @@ static void ehci_quiesce (struct ehci_hcd *ehci) | |||
286 | 287 | ||
287 | /* wait for any schedule enables/disables to take effect */ | 288 | /* wait for any schedule enables/disables to take effect */ |
288 | temp = (ehci->command << 10) & (STS_ASS | STS_PSS); | 289 | temp = (ehci->command << 10) & (STS_ASS | STS_PSS); |
289 | handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, temp, 16 * 125); | 290 | ehci_handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, temp, |
291 | 16 * 125); | ||
290 | 292 | ||
291 | /* then disable anything that's still active */ | 293 | /* then disable anything that's still active */ |
292 | spin_lock_irq(&ehci->lock); | 294 | spin_lock_irq(&ehci->lock); |
@@ -295,7 +297,8 @@ static void ehci_quiesce (struct ehci_hcd *ehci) | |||
295 | spin_unlock_irq(&ehci->lock); | 297 | spin_unlock_irq(&ehci->lock); |
296 | 298 | ||
297 | /* hardware can take 16 microframes to turn off ... */ | 299 | /* hardware can take 16 microframes to turn off ... */ |
298 | handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, 0, 16 * 125); | 300 | ehci_handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, 0, |
301 | 16 * 125); | ||
299 | } | 302 | } |
300 | 303 | ||
301 | /*-------------------------------------------------------------------------*/ | 304 | /*-------------------------------------------------------------------------*/ |
@@ -1266,11 +1269,6 @@ MODULE_LICENSE ("GPL"); | |||
1266 | #define PLATFORM_DRIVER ehci_hcd_msp_driver | 1269 | #define PLATFORM_DRIVER ehci_hcd_msp_driver |
1267 | #endif | 1270 | #endif |
1268 | 1271 | ||
1269 | #ifdef CONFIG_USB_EHCI_TEGRA | ||
1270 | #include "ehci-tegra.c" | ||
1271 | #define PLATFORM_DRIVER tegra_ehci_driver | ||
1272 | #endif | ||
1273 | |||
1274 | #ifdef CONFIG_SPARC_LEON | 1272 | #ifdef CONFIG_SPARC_LEON |
1275 | #include "ehci-grlib.c" | 1273 | #include "ehci-grlib.c" |
1276 | #define PLATFORM_DRIVER ehci_grlib_driver | 1274 | #define PLATFORM_DRIVER ehci_grlib_driver |
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 9ab4a4d9768a..2b702772d04d 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c | |||
@@ -42,6 +42,12 @@ static int ehci_hub_control( | |||
42 | u16 wLength | 42 | u16 wLength |
43 | ); | 43 | ); |
44 | 44 | ||
45 | static int persist_enabled_on_companion(struct usb_device *udev, void *unused) | ||
46 | { | ||
47 | return !udev->maxchild && udev->persist_enabled && | ||
48 | udev->bus->root_hub->speed < USB_SPEED_HIGH; | ||
49 | } | ||
50 | |||
45 | /* After a power loss, ports that were owned by the companion must be | 51 | /* After a power loss, ports that were owned by the companion must be |
46 | * reset so that the companion can still own them. | 52 | * reset so that the companion can still own them. |
47 | */ | 53 | */ |
@@ -56,6 +62,16 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci) | |||
56 | if (!ehci->owned_ports) | 62 | if (!ehci->owned_ports) |
57 | return; | 63 | return; |
58 | 64 | ||
65 | /* | ||
66 | * USB 1.1 devices are mostly HIDs, which don't need to persist across | ||
67 | * suspends. If we ensure that none of our companion's devices have | ||
68 | * persist_enabled (by looking through all USB 1.1 buses in the system), | ||
69 | * we can skip this and avoid slowing resume down. Devices without | ||
70 | * persist will just get reenumerated shortly after resume anyway. | ||
71 | */ | ||
72 | if (!usb_for_each_dev(NULL, persist_enabled_on_companion)) | ||
73 | return; | ||
74 | |||
59 | /* Make sure the ports are powered */ | 75 | /* Make sure the ports are powered */ |
60 | port = HCS_N_PORTS(ehci->hcs_params); | 76 | port = HCS_N_PORTS(ehci->hcs_params); |
61 | while (port--) { | 77 | while (port--) { |
@@ -876,7 +892,7 @@ static int ehci_hub_control ( | |||
876 | PORT_SUSPEND | PORT_RESUME); | 892 | PORT_SUSPEND | PORT_RESUME); |
877 | ehci_writel(ehci, temp, status_reg); | 893 | ehci_writel(ehci, temp, status_reg); |
878 | clear_bit(wIndex, &ehci->resuming_ports); | 894 | clear_bit(wIndex, &ehci->resuming_ports); |
879 | retval = handshake(ehci, status_reg, | 895 | retval = ehci_handshake(ehci, status_reg, |
880 | PORT_RESUME, 0, 2000 /* 2msec */); | 896 | PORT_RESUME, 0, 2000 /* 2msec */); |
881 | if (retval != 0) { | 897 | if (retval != 0) { |
882 | ehci_err(ehci, | 898 | ehci_err(ehci, |
@@ -902,7 +918,7 @@ static int ehci_hub_control ( | |||
902 | /* REVISIT: some hardware needs 550+ usec to clear | 918 | /* REVISIT: some hardware needs 550+ usec to clear |
903 | * this bit; seems too long to spin routinely... | 919 | * this bit; seems too long to spin routinely... |
904 | */ | 920 | */ |
905 | retval = handshake(ehci, status_reg, | 921 | retval = ehci_handshake(ehci, status_reg, |
906 | PORT_RESET, 0, 1000); | 922 | PORT_RESET, 0, 1000); |
907 | if (retval != 0) { | 923 | if (retval != 0) { |
908 | ehci_err (ehci, "port %d reset error %d\n", | 924 | ehci_err (ehci, "port %d reset error %d\n", |
diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c index 402062973f03..915c2db96dce 100644 --- a/drivers/usb/host/ehci-mv.c +++ b/drivers/usb/host/ehci-mv.c | |||
@@ -166,14 +166,14 @@ static int mv_ehci_probe(struct platform_device *pdev) | |||
166 | if (IS_ERR(ehci_mv->clk)) { | 166 | if (IS_ERR(ehci_mv->clk)) { |
167 | dev_err(&pdev->dev, "error getting clock\n"); | 167 | dev_err(&pdev->dev, "error getting clock\n"); |
168 | retval = PTR_ERR(ehci_mv->clk); | 168 | retval = PTR_ERR(ehci_mv->clk); |
169 | goto err_clear_drvdata; | 169 | goto err_put_hcd; |
170 | } | 170 | } |
171 | 171 | ||
172 | r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phyregs"); | 172 | r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phyregs"); |
173 | if (r == NULL) { | 173 | if (r == NULL) { |
174 | dev_err(&pdev->dev, "no phy I/O memory resource defined\n"); | 174 | dev_err(&pdev->dev, "no phy I/O memory resource defined\n"); |
175 | retval = -ENODEV; | 175 | retval = -ENODEV; |
176 | goto err_clear_drvdata; | 176 | goto err_put_hcd; |
177 | } | 177 | } |
178 | 178 | ||
179 | ehci_mv->phy_regs = devm_ioremap(&pdev->dev, r->start, | 179 | ehci_mv->phy_regs = devm_ioremap(&pdev->dev, r->start, |
@@ -181,14 +181,14 @@ static int mv_ehci_probe(struct platform_device *pdev) | |||
181 | if (ehci_mv->phy_regs == 0) { | 181 | if (ehci_mv->phy_regs == 0) { |
182 | dev_err(&pdev->dev, "failed to map phy I/O memory\n"); | 182 | dev_err(&pdev->dev, "failed to map phy I/O memory\n"); |
183 | retval = -EFAULT; | 183 | retval = -EFAULT; |
184 | goto err_clear_drvdata; | 184 | goto err_put_hcd; |
185 | } | 185 | } |
186 | 186 | ||
187 | r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "capregs"); | 187 | r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "capregs"); |
188 | if (!r) { | 188 | if (!r) { |
189 | dev_err(&pdev->dev, "no I/O memory resource defined\n"); | 189 | dev_err(&pdev->dev, "no I/O memory resource defined\n"); |
190 | retval = -ENODEV; | 190 | retval = -ENODEV; |
191 | goto err_clear_drvdata; | 191 | goto err_put_hcd; |
192 | } | 192 | } |
193 | 193 | ||
194 | ehci_mv->cap_regs = devm_ioremap(&pdev->dev, r->start, | 194 | ehci_mv->cap_regs = devm_ioremap(&pdev->dev, r->start, |
@@ -196,13 +196,13 @@ static int mv_ehci_probe(struct platform_device *pdev) | |||
196 | if (ehci_mv->cap_regs == NULL) { | 196 | if (ehci_mv->cap_regs == NULL) { |
197 | dev_err(&pdev->dev, "failed to map I/O memory\n"); | 197 | dev_err(&pdev->dev, "failed to map I/O memory\n"); |
198 | retval = -EFAULT; | 198 | retval = -EFAULT; |
199 | goto err_clear_drvdata; | 199 | goto err_put_hcd; |
200 | } | 200 | } |
201 | 201 | ||
202 | retval = mv_ehci_enable(ehci_mv); | 202 | retval = mv_ehci_enable(ehci_mv); |
203 | if (retval) { | 203 | if (retval) { |
204 | dev_err(&pdev->dev, "init phy error %d\n", retval); | 204 | dev_err(&pdev->dev, "init phy error %d\n", retval); |
205 | goto err_clear_drvdata; | 205 | goto err_put_hcd; |
206 | } | 206 | } |
207 | 207 | ||
208 | offset = readl(ehci_mv->cap_regs) & CAPLENGTH_MASK; | 208 | offset = readl(ehci_mv->cap_regs) & CAPLENGTH_MASK; |
@@ -274,8 +274,6 @@ err_set_vbus: | |||
274 | pdata->set_vbus(0); | 274 | pdata->set_vbus(0); |
275 | err_disable_clk: | 275 | err_disable_clk: |
276 | mv_ehci_disable(ehci_mv); | 276 | mv_ehci_disable(ehci_mv); |
277 | err_clear_drvdata: | ||
278 | platform_set_drvdata(pdev, NULL); | ||
279 | err_put_hcd: | 277 | err_put_hcd: |
280 | usb_put_hcd(hcd); | 278 | usb_put_hcd(hcd); |
281 | 279 | ||
@@ -300,8 +298,6 @@ static int mv_ehci_remove(struct platform_device *pdev) | |||
300 | mv_ehci_disable(ehci_mv); | 298 | mv_ehci_disable(ehci_mv); |
301 | } | 299 | } |
302 | 300 | ||
303 | platform_set_drvdata(pdev, NULL); | ||
304 | |||
305 | usb_put_hcd(hcd); | 301 | usb_put_hcd(hcd); |
306 | 302 | ||
307 | return 0; | 303 | return 0; |
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index c369767b00e2..e4c34ac386c0 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c | |||
@@ -194,7 +194,6 @@ static int ehci_mxc_drv_remove(struct platform_device *pdev) | |||
194 | clk_disable_unprepare(priv->phyclk); | 194 | clk_disable_unprepare(priv->phyclk); |
195 | 195 | ||
196 | usb_put_hcd(hcd); | 196 | usb_put_hcd(hcd); |
197 | platform_set_drvdata(pdev, NULL); | ||
198 | return 0; | 197 | return 0; |
199 | } | 198 | } |
200 | 199 | ||
diff --git a/drivers/usb/host/ehci-octeon.c b/drivers/usb/host/ehci-octeon.c index a89750fff4ff..45cc00158412 100644 --- a/drivers/usb/host/ehci-octeon.c +++ b/drivers/usb/host/ehci-octeon.c | |||
@@ -182,8 +182,6 @@ static int ehci_octeon_drv_remove(struct platform_device *pdev) | |||
182 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | 182 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
183 | usb_put_hcd(hcd); | 183 | usb_put_hcd(hcd); |
184 | 184 | ||
185 | platform_set_drvdata(pdev, NULL); | ||
186 | |||
187 | return 0; | 185 | return 0; |
188 | } | 186 | } |
189 | 187 | ||
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 16d7150e8557..9bd7dfe3315b 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c | |||
@@ -187,6 +187,12 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) | |||
187 | } | 187 | } |
188 | 188 | ||
189 | omap->phy[i] = phy; | 189 | omap->phy[i] = phy; |
190 | |||
191 | if (pdata->port_mode[i] == OMAP_EHCI_PORT_MODE_PHY) { | ||
192 | usb_phy_init(omap->phy[i]); | ||
193 | /* bring PHY out of suspend */ | ||
194 | usb_phy_set_suspend(omap->phy[i], 0); | ||
195 | } | ||
190 | } | 196 | } |
191 | 197 | ||
192 | pm_runtime_enable(dev); | 198 | pm_runtime_enable(dev); |
@@ -211,13 +217,14 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) | |||
211 | } | 217 | } |
212 | 218 | ||
213 | /* | 219 | /* |
214 | * Bring PHYs out of reset. | 220 | * Bring PHYs out of reset for non PHY modes. |
215 | * Even though HSIC mode is a PHY-less mode, the reset | 221 | * Even though HSIC mode is a PHY-less mode, the reset |
216 | * line exists between the chips and can be modelled | 222 | * line exists between the chips and can be modelled |
217 | * as a PHY device for reset control. | 223 | * as a PHY device for reset control. |
218 | */ | 224 | */ |
219 | for (i = 0; i < omap->nports; i++) { | 225 | for (i = 0; i < omap->nports; i++) { |
220 | if (!omap->phy[i]) | 226 | if (!omap->phy[i] || |
227 | pdata->port_mode[i] == OMAP_EHCI_PORT_MODE_PHY) | ||
221 | continue; | 228 | continue; |
222 | 229 | ||
223 | usb_phy_init(omap->phy[i]); | 230 | usb_phy_init(omap->phy[i]); |
@@ -294,7 +301,7 @@ static struct platform_driver ehci_hcd_omap_driver = { | |||
294 | /*.resume = ehci_hcd_omap_resume, */ | 301 | /*.resume = ehci_hcd_omap_resume, */ |
295 | .driver = { | 302 | .driver = { |
296 | .name = hcd_name, | 303 | .name = hcd_name, |
297 | .of_match_table = of_match_ptr(omap_ehci_dt_ids), | 304 | .of_match_table = omap_ehci_dt_ids, |
298 | } | 305 | } |
299 | }; | 306 | }; |
300 | 307 | ||
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c index efbc588b48c5..1a450aa13ebf 100644 --- a/drivers/usb/host/ehci-orion.c +++ b/drivers/usb/host/ehci-orion.c | |||
@@ -303,7 +303,7 @@ static struct platform_driver ehci_orion_driver = { | |||
303 | .driver = { | 303 | .driver = { |
304 | .name = "orion-ehci", | 304 | .name = "orion-ehci", |
305 | .owner = THIS_MODULE, | 305 | .owner = THIS_MODULE, |
306 | .of_match_table = of_match_ptr(ehci_orion_dt_ids), | 306 | .of_match_table = ehci_orion_dt_ids, |
307 | }, | 307 | }, |
308 | }; | 308 | }; |
309 | 309 | ||
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index f47f2594c9d4..5733f8ed98f1 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c | |||
@@ -146,7 +146,6 @@ static int ehci_platform_remove(struct platform_device *dev) | |||
146 | 146 | ||
147 | usb_remove_hcd(hcd); | 147 | usb_remove_hcd(hcd); |
148 | usb_put_hcd(hcd); | 148 | usb_put_hcd(hcd); |
149 | platform_set_drvdata(dev, NULL); | ||
150 | 149 | ||
151 | if (pdata->power_off) | 150 | if (pdata->power_off) |
152 | pdata->power_off(dev); | 151 | pdata->power_off(dev); |
@@ -224,7 +223,7 @@ static struct platform_driver ehci_platform_driver = { | |||
224 | .owner = THIS_MODULE, | 223 | .owner = THIS_MODULE, |
225 | .name = "ehci-platform", | 224 | .name = "ehci-platform", |
226 | .pm = &ehci_platform_pm_ops, | 225 | .pm = &ehci_platform_pm_ops, |
227 | .of_match_table = of_match_ptr(vt8500_ehci_ids), | 226 | .of_match_table = vt8500_ehci_ids, |
228 | } | 227 | } |
229 | }; | 228 | }; |
230 | 229 | ||
diff --git a/drivers/usb/host/ehci-pmcmsp.c b/drivers/usb/host/ehci-pmcmsp.c index 363890ee41d2..601e208bd782 100644 --- a/drivers/usb/host/ehci-pmcmsp.c +++ b/drivers/usb/host/ehci-pmcmsp.c | |||
@@ -291,8 +291,7 @@ static const struct hc_driver ehci_msp_hc_driver = { | |||
291 | /* | 291 | /* |
292 | * basic lifecycle operations | 292 | * basic lifecycle operations |
293 | */ | 293 | */ |
294 | .reset = ehci_msp_setup, | 294 | .reset = ehci_msp_setup, |
295 | .start = ehci_run, | ||
296 | .shutdown = ehci_shutdown, | 295 | .shutdown = ehci_shutdown, |
297 | .start = ehci_run, | 296 | .start = ehci_run, |
298 | .stop = ehci_stop, | 297 | .stop = ehci_stop, |
diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c index 56dc732bf451..86da09c0f8d0 100644 --- a/drivers/usb/host/ehci-ppc-of.c +++ b/drivers/usb/host/ehci-ppc-of.c | |||
@@ -180,14 +180,12 @@ err_irq: | |||
180 | 180 | ||
181 | static int ehci_hcd_ppc_of_remove(struct platform_device *op) | 181 | static int ehci_hcd_ppc_of_remove(struct platform_device *op) |
182 | { | 182 | { |
183 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); | 183 | struct usb_hcd *hcd = platform_get_drvdata(op); |
184 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | 184 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
185 | 185 | ||
186 | struct device_node *np; | 186 | struct device_node *np; |
187 | struct resource res; | 187 | struct resource res; |
188 | 188 | ||
189 | dev_set_drvdata(&op->dev, NULL); | ||
190 | |||
191 | dev_dbg(&op->dev, "stopping PPC-OF USB Controller\n"); | 189 | dev_dbg(&op->dev, "stopping PPC-OF USB Controller\n"); |
192 | 190 | ||
193 | usb_remove_hcd(hcd); | 191 | usb_remove_hcd(hcd); |
@@ -219,7 +217,7 @@ static int ehci_hcd_ppc_of_remove(struct platform_device *op) | |||
219 | 217 | ||
220 | static void ehci_hcd_ppc_of_shutdown(struct platform_device *op) | 218 | static void ehci_hcd_ppc_of_shutdown(struct platform_device *op) |
221 | { | 219 | { |
222 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); | 220 | struct usb_hcd *hcd = platform_get_drvdata(op); |
223 | 221 | ||
224 | if (hcd->driver->shutdown) | 222 | if (hcd->driver->shutdown) |
225 | hcd->driver->shutdown(hcd); | 223 | hcd->driver->shutdown(hcd); |
diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c index 379037f51a2f..7cc26e621aa7 100644 --- a/drivers/usb/host/ehci-s5p.c +++ b/drivers/usb/host/ehci-s5p.c | |||
@@ -50,6 +50,8 @@ struct s5p_ehci_hcd { | |||
50 | struct s5p_ehci_platdata *pdata; | 50 | struct s5p_ehci_platdata *pdata; |
51 | }; | 51 | }; |
52 | 52 | ||
53 | static struct s5p_ehci_platdata empty_platdata; | ||
54 | |||
53 | #define to_s5p_ehci(hcd) (struct s5p_ehci_hcd *)(hcd_to_ehci(hcd)->priv) | 55 | #define to_s5p_ehci(hcd) (struct s5p_ehci_hcd *)(hcd_to_ehci(hcd)->priv) |
54 | 56 | ||
55 | static void s5p_setup_vbus_gpio(struct platform_device *pdev) | 57 | static void s5p_setup_vbus_gpio(struct platform_device *pdev) |
@@ -101,6 +103,13 @@ static int s5p_ehci_probe(struct platform_device *pdev) | |||
101 | return -ENOMEM; | 103 | return -ENOMEM; |
102 | } | 104 | } |
103 | s5p_ehci = to_s5p_ehci(hcd); | 105 | s5p_ehci = to_s5p_ehci(hcd); |
106 | |||
107 | if (of_device_is_compatible(pdev->dev.of_node, | ||
108 | "samsung,exynos5440-ehci")) { | ||
109 | s5p_ehci->pdata = &empty_platdata; | ||
110 | goto skip_phy; | ||
111 | } | ||
112 | |||
104 | phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); | 113 | phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); |
105 | if (IS_ERR(phy)) { | 114 | if (IS_ERR(phy)) { |
106 | /* Fallback to pdata */ | 115 | /* Fallback to pdata */ |
@@ -116,6 +125,8 @@ static int s5p_ehci_probe(struct platform_device *pdev) | |||
116 | s5p_ehci->otg = phy->otg; | 125 | s5p_ehci->otg = phy->otg; |
117 | } | 126 | } |
118 | 127 | ||
128 | skip_phy: | ||
129 | |||
119 | s5p_ehci->clk = devm_clk_get(&pdev->dev, "usbhost"); | 130 | s5p_ehci->clk = devm_clk_get(&pdev->dev, "usbhost"); |
120 | 131 | ||
121 | if (IS_ERR(s5p_ehci->clk)) { | 132 | if (IS_ERR(s5p_ehci->clk)) { |
@@ -277,6 +288,7 @@ static const struct dev_pm_ops s5p_ehci_pm_ops = { | |||
277 | #ifdef CONFIG_OF | 288 | #ifdef CONFIG_OF |
278 | static const struct of_device_id exynos_ehci_match[] = { | 289 | static const struct of_device_id exynos_ehci_match[] = { |
279 | { .compatible = "samsung,exynos4210-ehci" }, | 290 | { .compatible = "samsung,exynos4210-ehci" }, |
291 | { .compatible = "samsung,exynos5440-ehci" }, | ||
280 | {}, | 292 | {}, |
281 | }; | 293 | }; |
282 | MODULE_DEVICE_TABLE(of, exynos_ehci_match); | 294 | MODULE_DEVICE_TABLE(of, exynos_ehci_match); |
diff --git a/drivers/usb/host/ehci-sead3.c b/drivers/usb/host/ehci-sead3.c index f55477c5a1be..b2de52d39614 100644 --- a/drivers/usb/host/ehci-sead3.c +++ b/drivers/usb/host/ehci-sead3.c | |||
@@ -140,7 +140,6 @@ static int ehci_hcd_sead3_drv_remove(struct platform_device *pdev) | |||
140 | 140 | ||
141 | usb_remove_hcd(hcd); | 141 | usb_remove_hcd(hcd); |
142 | usb_put_hcd(hcd); | 142 | usb_put_hcd(hcd); |
143 | platform_set_drvdata(pdev, NULL); | ||
144 | 143 | ||
145 | return 0; | 144 | return 0; |
146 | } | 145 | } |
diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c index b44d716ddc82..c4c0ee92a397 100644 --- a/drivers/usb/host/ehci-sh.c +++ b/drivers/usb/host/ehci-sh.c | |||
@@ -176,7 +176,6 @@ static int ehci_hcd_sh_remove(struct platform_device *pdev) | |||
176 | 176 | ||
177 | usb_remove_hcd(hcd); | 177 | usb_remove_hcd(hcd); |
178 | usb_put_hcd(hcd); | 178 | usb_put_hcd(hcd); |
179 | platform_set_drvdata(pdev, NULL); | ||
180 | 179 | ||
181 | clk_disable(priv->fclk); | 180 | clk_disable(priv->fclk); |
182 | clk_disable(priv->iclk); | 181 | clk_disable(priv->iclk); |
diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c index bd3e5cbc6240..1cf0adba3fc8 100644 --- a/drivers/usb/host/ehci-spear.c +++ b/drivers/usb/host/ehci-spear.c | |||
@@ -148,10 +148,6 @@ static int spear_ehci_hcd_drv_remove(struct platform_device *pdev) | |||
148 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | 148 | struct usb_hcd *hcd = platform_get_drvdata(pdev); |
149 | struct spear_ehci *sehci = to_spear_ehci(hcd); | 149 | struct spear_ehci *sehci = to_spear_ehci(hcd); |
150 | 150 | ||
151 | if (!hcd) | ||
152 | return 0; | ||
153 | if (in_interrupt()) | ||
154 | BUG(); | ||
155 | usb_remove_hcd(hcd); | 151 | usb_remove_hcd(hcd); |
156 | 152 | ||
157 | if (sehci->clk) | 153 | if (sehci->clk) |
@@ -174,7 +170,7 @@ static struct platform_driver spear_ehci_hcd_driver = { | |||
174 | .name = "spear-ehci", | 170 | .name = "spear-ehci", |
175 | .bus = &platform_bus_type, | 171 | .bus = &platform_bus_type, |
176 | .pm = &ehci_spear_pm_ops, | 172 | .pm = &ehci_spear_pm_ops, |
177 | .of_match_table = of_match_ptr(spear_ehci_id_table), | 173 | .of_match_table = spear_ehci_id_table, |
178 | } | 174 | } |
179 | }; | 175 | }; |
180 | 176 | ||
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 59d111bf44a9..6ee7ef79b4f8 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c | |||
@@ -17,59 +17,53 @@ | |||
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/clk.h> | 19 | #include <linux/clk.h> |
20 | #include <linux/clk/tegra.h> | ||
21 | #include <linux/dma-mapping.h> | ||
20 | #include <linux/err.h> | 22 | #include <linux/err.h> |
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/platform_data/tegra_usb.h> | ||
23 | #include <linux/irq.h> | ||
24 | #include <linux/usb/otg.h> | ||
25 | #include <linux/gpio.h> | 23 | #include <linux/gpio.h> |
24 | #include <linux/io.h> | ||
25 | #include <linux/irq.h> | ||
26 | #include <linux/module.h> | ||
26 | #include <linux/of.h> | 27 | #include <linux/of.h> |
27 | #include <linux/of_gpio.h> | 28 | #include <linux/of_gpio.h> |
29 | #include <linux/platform_device.h> | ||
30 | #include <linux/platform_data/tegra_usb.h> | ||
28 | #include <linux/pm_runtime.h> | 31 | #include <linux/pm_runtime.h> |
32 | #include <linux/slab.h> | ||
29 | #include <linux/usb/ehci_def.h> | 33 | #include <linux/usb/ehci_def.h> |
30 | #include <linux/usb/tegra_usb_phy.h> | 34 | #include <linux/usb/tegra_usb_phy.h> |
31 | #include <linux/clk/tegra.h> | 35 | #include <linux/usb.h> |
36 | #include <linux/usb/hcd.h> | ||
37 | #include <linux/usb/otg.h> | ||
38 | |||
39 | #include "ehci.h" | ||
32 | 40 | ||
33 | #define TEGRA_USB_BASE 0xC5000000 | 41 | #define TEGRA_USB_BASE 0xC5000000 |
34 | #define TEGRA_USB2_BASE 0xC5004000 | 42 | #define TEGRA_USB2_BASE 0xC5004000 |
35 | #define TEGRA_USB3_BASE 0xC5008000 | 43 | #define TEGRA_USB3_BASE 0xC5008000 |
36 | 44 | ||
37 | /* PORTSC registers */ | 45 | #define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E) |
38 | #define TEGRA_USB_PORTSC1 0x184 | ||
39 | #define TEGRA_USB_PORTSC1_PTS(x) (((x) & 0x3) << 30) | ||
40 | #define TEGRA_USB_PORTSC1_PHCD (1 << 23) | ||
41 | 46 | ||
42 | #define TEGRA_USB_DMA_ALIGN 32 | 47 | #define TEGRA_USB_DMA_ALIGN 32 |
43 | 48 | ||
49 | #define DRIVER_DESC "Tegra EHCI driver" | ||
50 | #define DRV_NAME "tegra-ehci" | ||
51 | |||
52 | static struct hc_driver __read_mostly tegra_ehci_hc_driver; | ||
53 | |||
54 | static int (*orig_hub_control)(struct usb_hcd *hcd, | ||
55 | u16 typeReq, u16 wValue, u16 wIndex, | ||
56 | char *buf, u16 wLength); | ||
57 | |||
44 | struct tegra_ehci_hcd { | 58 | struct tegra_ehci_hcd { |
45 | struct ehci_hcd *ehci; | ||
46 | struct tegra_usb_phy *phy; | 59 | struct tegra_usb_phy *phy; |
47 | struct clk *clk; | 60 | struct clk *clk; |
48 | struct usb_phy *transceiver; | 61 | struct usb_phy *transceiver; |
49 | int host_resumed; | ||
50 | int port_resuming; | 62 | int port_resuming; |
51 | bool needs_double_reset; | 63 | bool needs_double_reset; |
52 | enum tegra_usb_phy_port_speed port_speed; | 64 | enum tegra_usb_phy_port_speed port_speed; |
53 | }; | 65 | }; |
54 | 66 | ||
55 | static void tegra_ehci_power_up(struct usb_hcd *hcd) | ||
56 | { | ||
57 | struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); | ||
58 | |||
59 | clk_prepare_enable(tegra->clk); | ||
60 | usb_phy_set_suspend(hcd->phy, 0); | ||
61 | tegra->host_resumed = 1; | ||
62 | } | ||
63 | |||
64 | static void tegra_ehci_power_down(struct usb_hcd *hcd) | ||
65 | { | ||
66 | struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); | ||
67 | |||
68 | tegra->host_resumed = 0; | ||
69 | usb_phy_set_suspend(hcd->phy, 1); | ||
70 | clk_disable_unprepare(tegra->clk); | ||
71 | } | ||
72 | |||
73 | static int tegra_ehci_internal_port_reset( | 67 | static int tegra_ehci_internal_port_reset( |
74 | struct ehci_hcd *ehci, | 68 | struct ehci_hcd *ehci, |
75 | u32 __iomem *portsc_reg | 69 | u32 __iomem *portsc_reg |
@@ -144,8 +138,8 @@ static int tegra_ehci_hub_control( | |||
144 | u16 wLength | 138 | u16 wLength |
145 | ) | 139 | ) |
146 | { | 140 | { |
147 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | 141 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
148 | struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); | 142 | struct tegra_ehci_hcd *tegra = (struct tegra_ehci_hcd *)ehci->priv; |
149 | u32 __iomem *status_reg; | 143 | u32 __iomem *status_reg; |
150 | u32 temp; | 144 | u32 temp; |
151 | unsigned long flags; | 145 | unsigned long flags; |
@@ -179,7 +173,7 @@ static int tegra_ehci_hub_control( | |||
179 | * If a transaction is in progress, there may be a delay in | 173 | * If a transaction is in progress, there may be a delay in |
180 | * suspending the port. Poll until the port is suspended. | 174 | * suspending the port. Poll until the port is suspended. |
181 | */ | 175 | */ |
182 | if (handshake(ehci, status_reg, PORT_SUSPEND, | 176 | if (ehci_handshake(ehci, status_reg, PORT_SUSPEND, |
183 | PORT_SUSPEND, 5000)) | 177 | PORT_SUSPEND, 5000)) |
184 | pr_err("%s: timeout waiting for SUSPEND\n", __func__); | 178 | pr_err("%s: timeout waiting for SUSPEND\n", __func__); |
185 | 179 | ||
@@ -227,9 +221,9 @@ static int tegra_ehci_hub_control( | |||
227 | spin_lock_irqsave(&ehci->lock, flags); | 221 | spin_lock_irqsave(&ehci->lock, flags); |
228 | 222 | ||
229 | /* Poll until the controller clears RESUME and SUSPEND */ | 223 | /* Poll until the controller clears RESUME and SUSPEND */ |
230 | if (handshake(ehci, status_reg, PORT_RESUME, 0, 2000)) | 224 | if (ehci_handshake(ehci, status_reg, PORT_RESUME, 0, 2000)) |
231 | pr_err("%s: timeout waiting for RESUME\n", __func__); | 225 | pr_err("%s: timeout waiting for RESUME\n", __func__); |
232 | if (handshake(ehci, status_reg, PORT_SUSPEND, 0, 2000)) | 226 | if (ehci_handshake(ehci, status_reg, PORT_SUSPEND, 0, 2000)) |
233 | pr_err("%s: timeout waiting for SUSPEND\n", __func__); | 227 | pr_err("%s: timeout waiting for SUSPEND\n", __func__); |
234 | 228 | ||
235 | ehci->reset_done[wIndex-1] = 0; | 229 | ehci->reset_done[wIndex-1] = 0; |
@@ -242,58 +236,13 @@ static int tegra_ehci_hub_control( | |||
242 | spin_unlock_irqrestore(&ehci->lock, flags); | 236 | spin_unlock_irqrestore(&ehci->lock, flags); |
243 | 237 | ||
244 | /* Handle the hub control events here */ | 238 | /* Handle the hub control events here */ |
245 | return ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); | 239 | return orig_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); |
240 | |||
246 | done: | 241 | done: |
247 | spin_unlock_irqrestore(&ehci->lock, flags); | 242 | spin_unlock_irqrestore(&ehci->lock, flags); |
248 | return retval; | 243 | return retval; |
249 | } | 244 | } |
250 | 245 | ||
251 | static void tegra_ehci_restart(struct usb_hcd *hcd) | ||
252 | { | ||
253 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | ||
254 | |||
255 | ehci_reset(ehci); | ||
256 | |||
257 | /* setup the frame list and Async q heads */ | ||
258 | ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list); | ||
259 | ehci_writel(ehci, (u32)ehci->async->qh_dma, &ehci->regs->async_next); | ||
260 | /* setup the command register and set the controller in RUN mode */ | ||
261 | ehci->command &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET); | ||
262 | ehci->command |= CMD_RUN; | ||
263 | ehci_writel(ehci, ehci->command, &ehci->regs->command); | ||
264 | |||
265 | down_write(&ehci_cf_port_reset_rwsem); | ||
266 | ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); | ||
267 | /* flush posted writes */ | ||
268 | ehci_readl(ehci, &ehci->regs->command); | ||
269 | up_write(&ehci_cf_port_reset_rwsem); | ||
270 | } | ||
271 | |||
272 | static void tegra_ehci_shutdown(struct usb_hcd *hcd) | ||
273 | { | ||
274 | struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); | ||
275 | |||
276 | /* ehci_shutdown touches the USB controller registers, make sure | ||
277 | * controller has clocks to it */ | ||
278 | if (!tegra->host_resumed) | ||
279 | tegra_ehci_power_up(hcd); | ||
280 | |||
281 | ehci_shutdown(hcd); | ||
282 | } | ||
283 | |||
284 | static int tegra_ehci_setup(struct usb_hcd *hcd) | ||
285 | { | ||
286 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | ||
287 | |||
288 | /* EHCI registers start at offset 0x100 */ | ||
289 | ehci->caps = hcd->regs + 0x100; | ||
290 | |||
291 | /* switch to host mode */ | ||
292 | hcd->has_tt = 1; | ||
293 | |||
294 | return ehci_setup(hcd); | ||
295 | } | ||
296 | |||
297 | struct dma_aligned_buffer { | 246 | struct dma_aligned_buffer { |
298 | void *kmalloc_ptr; | 247 | void *kmalloc_ptr; |
299 | void *old_xfer_buffer; | 248 | void *old_xfer_buffer; |
@@ -373,38 +322,6 @@ static void tegra_ehci_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) | |||
373 | free_dma_aligned_buffer(urb); | 322 | free_dma_aligned_buffer(urb); |
374 | } | 323 | } |
375 | 324 | ||
376 | static const struct hc_driver tegra_ehci_hc_driver = { | ||
377 | .description = hcd_name, | ||
378 | .product_desc = "Tegra EHCI Host Controller", | ||
379 | .hcd_priv_size = sizeof(struct ehci_hcd), | ||
380 | .flags = HCD_USB2 | HCD_MEMORY, | ||
381 | |||
382 | /* standard ehci functions */ | ||
383 | .irq = ehci_irq, | ||
384 | .start = ehci_run, | ||
385 | .stop = ehci_stop, | ||
386 | .urb_enqueue = ehci_urb_enqueue, | ||
387 | .urb_dequeue = ehci_urb_dequeue, | ||
388 | .endpoint_disable = ehci_endpoint_disable, | ||
389 | .endpoint_reset = ehci_endpoint_reset, | ||
390 | .get_frame_number = ehci_get_frame, | ||
391 | .hub_status_data = ehci_hub_status_data, | ||
392 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
393 | .relinquish_port = ehci_relinquish_port, | ||
394 | .port_handed_over = ehci_port_handed_over, | ||
395 | |||
396 | /* modified ehci functions for tegra */ | ||
397 | .reset = tegra_ehci_setup, | ||
398 | .shutdown = tegra_ehci_shutdown, | ||
399 | .map_urb_for_dma = tegra_ehci_map_urb_for_dma, | ||
400 | .unmap_urb_for_dma = tegra_ehci_unmap_urb_for_dma, | ||
401 | .hub_control = tegra_ehci_hub_control, | ||
402 | #ifdef CONFIG_PM | ||
403 | .bus_suspend = ehci_bus_suspend, | ||
404 | .bus_resume = ehci_bus_resume, | ||
405 | #endif | ||
406 | }; | ||
407 | |||
408 | static int setup_vbus_gpio(struct platform_device *pdev, | 325 | static int setup_vbus_gpio(struct platform_device *pdev, |
409 | struct tegra_ehci_platform_data *pdata) | 326 | struct tegra_ehci_platform_data *pdata) |
410 | { | 327 | { |
@@ -432,220 +349,16 @@ static int setup_vbus_gpio(struct platform_device *pdev, | |||
432 | return err; | 349 | return err; |
433 | } | 350 | } |
434 | 351 | ||
435 | #ifdef CONFIG_PM | ||
436 | |||
437 | static int controller_suspend(struct device *dev) | ||
438 | { | ||
439 | struct tegra_ehci_hcd *tegra = | ||
440 | platform_get_drvdata(to_platform_device(dev)); | ||
441 | struct ehci_hcd *ehci = tegra->ehci; | ||
442 | struct usb_hcd *hcd = ehci_to_hcd(ehci); | ||
443 | struct ehci_regs __iomem *hw = ehci->regs; | ||
444 | unsigned long flags; | ||
445 | |||
446 | if (time_before(jiffies, ehci->next_statechange)) | ||
447 | msleep(10); | ||
448 | |||
449 | ehci_halt(ehci); | ||
450 | |||
451 | spin_lock_irqsave(&ehci->lock, flags); | ||
452 | tegra->port_speed = (readl(&hw->port_status[0]) >> 26) & 0x3; | ||
453 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | ||
454 | spin_unlock_irqrestore(&ehci->lock, flags); | ||
455 | |||
456 | tegra_ehci_power_down(hcd); | ||
457 | return 0; | ||
458 | } | ||
459 | |||
460 | static int controller_resume(struct device *dev) | ||
461 | { | ||
462 | struct tegra_ehci_hcd *tegra = | ||
463 | platform_get_drvdata(to_platform_device(dev)); | ||
464 | struct ehci_hcd *ehci = tegra->ehci; | ||
465 | struct usb_hcd *hcd = ehci_to_hcd(ehci); | ||
466 | struct ehci_regs __iomem *hw = ehci->regs; | ||
467 | unsigned long val; | ||
468 | |||
469 | set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | ||
470 | tegra_ehci_power_up(hcd); | ||
471 | |||
472 | if (tegra->port_speed > TEGRA_USB_PHY_PORT_SPEED_HIGH) { | ||
473 | /* Wait for the phy to detect new devices | ||
474 | * before we restart the controller */ | ||
475 | msleep(10); | ||
476 | goto restart; | ||
477 | } | ||
478 | |||
479 | /* Force the phy to keep data lines in suspend state */ | ||
480 | tegra_ehci_phy_restore_start(hcd->phy, tegra->port_speed); | ||
481 | |||
482 | /* Enable host mode */ | ||
483 | tdi_reset(ehci); | ||
484 | |||
485 | /* Enable Port Power */ | ||
486 | val = readl(&hw->port_status[0]); | ||
487 | val |= PORT_POWER; | ||
488 | writel(val, &hw->port_status[0]); | ||
489 | udelay(10); | ||
490 | |||
491 | /* Check if the phy resume from LP0. When the phy resume from LP0 | ||
492 | * USB register will be reset. */ | ||
493 | if (!readl(&hw->async_next)) { | ||
494 | /* Program the field PTC based on the saved speed mode */ | ||
495 | val = readl(&hw->port_status[0]); | ||
496 | val &= ~PORT_TEST(~0); | ||
497 | if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_HIGH) | ||
498 | val |= PORT_TEST_FORCE; | ||
499 | else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_FULL) | ||
500 | val |= PORT_TEST(6); | ||
501 | else if (tegra->port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW) | ||
502 | val |= PORT_TEST(7); | ||
503 | writel(val, &hw->port_status[0]); | ||
504 | udelay(10); | ||
505 | |||
506 | /* Disable test mode by setting PTC field to NORMAL_OP */ | ||
507 | val = readl(&hw->port_status[0]); | ||
508 | val &= ~PORT_TEST(~0); | ||
509 | writel(val, &hw->port_status[0]); | ||
510 | udelay(10); | ||
511 | } | ||
512 | |||
513 | /* Poll until CCS is enabled */ | ||
514 | if (handshake(ehci, &hw->port_status[0], PORT_CONNECT, | ||
515 | PORT_CONNECT, 2000)) { | ||
516 | pr_err("%s: timeout waiting for PORT_CONNECT\n", __func__); | ||
517 | goto restart; | ||
518 | } | ||
519 | |||
520 | /* Poll until PE is enabled */ | ||
521 | if (handshake(ehci, &hw->port_status[0], PORT_PE, | ||
522 | PORT_PE, 2000)) { | ||
523 | pr_err("%s: timeout waiting for USB_PORTSC1_PE\n", __func__); | ||
524 | goto restart; | ||
525 | } | ||
526 | |||
527 | /* Clear the PCI status, to avoid an interrupt taken upon resume */ | ||
528 | val = readl(&hw->status); | ||
529 | val |= STS_PCD; | ||
530 | writel(val, &hw->status); | ||
531 | |||
532 | /* Put controller in suspend mode by writing 1 to SUSP bit of PORTSC */ | ||
533 | val = readl(&hw->port_status[0]); | ||
534 | if ((val & PORT_POWER) && (val & PORT_PE)) { | ||
535 | val |= PORT_SUSPEND; | ||
536 | writel(val, &hw->port_status[0]); | ||
537 | |||
538 | /* Wait until port suspend completes */ | ||
539 | if (handshake(ehci, &hw->port_status[0], PORT_SUSPEND, | ||
540 | PORT_SUSPEND, 1000)) { | ||
541 | pr_err("%s: timeout waiting for PORT_SUSPEND\n", | ||
542 | __func__); | ||
543 | goto restart; | ||
544 | } | ||
545 | } | ||
546 | |||
547 | tegra_ehci_phy_restore_end(hcd->phy); | ||
548 | goto done; | ||
549 | |||
550 | restart: | ||
551 | if (tegra->port_speed <= TEGRA_USB_PHY_PORT_SPEED_HIGH) | ||
552 | tegra_ehci_phy_restore_end(hcd->phy); | ||
553 | |||
554 | tegra_ehci_restart(hcd); | ||
555 | |||
556 | done: | ||
557 | tegra_usb_phy_preresume(hcd->phy); | ||
558 | tegra->port_resuming = 1; | ||
559 | return 0; | ||
560 | } | ||
561 | |||
562 | static int tegra_ehci_suspend(struct device *dev) | ||
563 | { | ||
564 | struct tegra_ehci_hcd *tegra = | ||
565 | platform_get_drvdata(to_platform_device(dev)); | ||
566 | struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci); | ||
567 | int rc = 0; | ||
568 | |||
569 | /* | ||
570 | * When system sleep is supported and USB controller wakeup is | ||
571 | * implemented: If the controller is runtime-suspended and the | ||
572 | * wakeup setting needs to be changed, call pm_runtime_resume(). | ||
573 | */ | ||
574 | if (HCD_HW_ACCESSIBLE(hcd)) | ||
575 | rc = controller_suspend(dev); | ||
576 | return rc; | ||
577 | } | ||
578 | |||
579 | static int tegra_ehci_resume(struct device *dev) | ||
580 | { | ||
581 | int rc; | ||
582 | |||
583 | rc = controller_resume(dev); | ||
584 | if (rc == 0) { | ||
585 | pm_runtime_disable(dev); | ||
586 | pm_runtime_set_active(dev); | ||
587 | pm_runtime_enable(dev); | ||
588 | } | ||
589 | return rc; | ||
590 | } | ||
591 | |||
592 | static int tegra_ehci_runtime_suspend(struct device *dev) | ||
593 | { | ||
594 | return controller_suspend(dev); | ||
595 | } | ||
596 | |||
597 | static int tegra_ehci_runtime_resume(struct device *dev) | ||
598 | { | ||
599 | return controller_resume(dev); | ||
600 | } | ||
601 | |||
602 | static const struct dev_pm_ops tegra_ehci_pm_ops = { | ||
603 | .suspend = tegra_ehci_suspend, | ||
604 | .resume = tegra_ehci_resume, | ||
605 | .runtime_suspend = tegra_ehci_runtime_suspend, | ||
606 | .runtime_resume = tegra_ehci_runtime_resume, | ||
607 | }; | ||
608 | |||
609 | #endif | ||
610 | |||
611 | /* Bits of PORTSC1, which will get cleared by writing 1 into them */ | ||
612 | #define TEGRA_PORTSC1_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC) | ||
613 | |||
614 | static void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val) | ||
615 | { | ||
616 | unsigned long val; | ||
617 | struct usb_hcd *hcd = bus_to_hcd(x->otg->host); | ||
618 | void __iomem *base = hcd->regs; | ||
619 | |||
620 | val = readl(base + TEGRA_USB_PORTSC1) & ~TEGRA_PORTSC1_RWC_BITS; | ||
621 | val &= ~TEGRA_USB_PORTSC1_PTS(3); | ||
622 | val |= TEGRA_USB_PORTSC1_PTS(pts_val & 3); | ||
623 | writel(val, base + TEGRA_USB_PORTSC1); | ||
624 | } | ||
625 | |||
626 | static void tegra_ehci_set_phcd(struct usb_phy *x, bool enable) | ||
627 | { | ||
628 | unsigned long val; | ||
629 | struct usb_hcd *hcd = bus_to_hcd(x->otg->host); | ||
630 | void __iomem *base = hcd->regs; | ||
631 | |||
632 | val = readl(base + TEGRA_USB_PORTSC1) & ~TEGRA_PORTSC1_RWC_BITS; | ||
633 | if (enable) | ||
634 | val |= TEGRA_USB_PORTSC1_PHCD; | ||
635 | else | ||
636 | val &= ~TEGRA_USB_PORTSC1_PHCD; | ||
637 | writel(val, base + TEGRA_USB_PORTSC1); | ||
638 | } | ||
639 | |||
640 | static int tegra_ehci_probe(struct platform_device *pdev) | 352 | static int tegra_ehci_probe(struct platform_device *pdev) |
641 | { | 353 | { |
642 | struct resource *res; | 354 | struct resource *res; |
643 | struct usb_hcd *hcd; | 355 | struct usb_hcd *hcd; |
356 | struct ehci_hcd *ehci; | ||
644 | struct tegra_ehci_hcd *tegra; | 357 | struct tegra_ehci_hcd *tegra; |
645 | struct tegra_ehci_platform_data *pdata; | 358 | struct tegra_ehci_platform_data *pdata; |
646 | int err = 0; | 359 | int err = 0; |
647 | int irq; | 360 | int irq; |
648 | int instance = pdev->id; | 361 | struct device_node *np_phy; |
649 | struct usb_phy *u_phy; | 362 | struct usb_phy *u_phy; |
650 | 363 | ||
651 | pdata = pdev->dev.platform_data; | 364 | pdata = pdev->dev.platform_data; |
@@ -665,35 +378,47 @@ static int tegra_ehci_probe(struct platform_device *pdev) | |||
665 | 378 | ||
666 | setup_vbus_gpio(pdev, pdata); | 379 | setup_vbus_gpio(pdev, pdata); |
667 | 380 | ||
668 | tegra = devm_kzalloc(&pdev->dev, sizeof(struct tegra_ehci_hcd), | ||
669 | GFP_KERNEL); | ||
670 | if (!tegra) | ||
671 | return -ENOMEM; | ||
672 | |||
673 | hcd = usb_create_hcd(&tegra_ehci_hc_driver, &pdev->dev, | 381 | hcd = usb_create_hcd(&tegra_ehci_hc_driver, &pdev->dev, |
674 | dev_name(&pdev->dev)); | 382 | dev_name(&pdev->dev)); |
675 | if (!hcd) { | 383 | if (!hcd) { |
676 | dev_err(&pdev->dev, "Unable to create HCD\n"); | 384 | dev_err(&pdev->dev, "Unable to create HCD\n"); |
677 | return -ENOMEM; | 385 | err = -ENOMEM; |
386 | goto cleanup_vbus_gpio; | ||
678 | } | 387 | } |
388 | platform_set_drvdata(pdev, hcd); | ||
389 | ehci = hcd_to_ehci(hcd); | ||
390 | tegra = (struct tegra_ehci_hcd *)ehci->priv; | ||
679 | 391 | ||
680 | platform_set_drvdata(pdev, tegra); | 392 | hcd->has_tt = 1; |
681 | 393 | ||
682 | tegra->clk = devm_clk_get(&pdev->dev, NULL); | 394 | tegra->clk = devm_clk_get(&pdev->dev, NULL); |
683 | if (IS_ERR(tegra->clk)) { | 395 | if (IS_ERR(tegra->clk)) { |
684 | dev_err(&pdev->dev, "Can't get ehci clock\n"); | 396 | dev_err(&pdev->dev, "Can't get ehci clock\n"); |
685 | err = PTR_ERR(tegra->clk); | 397 | err = PTR_ERR(tegra->clk); |
686 | goto fail_clk; | 398 | goto cleanup_hcd_create; |
687 | } | 399 | } |
688 | 400 | ||
689 | err = clk_prepare_enable(tegra->clk); | 401 | err = clk_prepare_enable(tegra->clk); |
690 | if (err) | 402 | if (err) |
691 | goto fail_clk; | 403 | goto cleanup_clk_get; |
692 | 404 | ||
693 | tegra_periph_reset_assert(tegra->clk); | 405 | tegra_periph_reset_assert(tegra->clk); |
694 | udelay(1); | 406 | udelay(1); |
695 | tegra_periph_reset_deassert(tegra->clk); | 407 | tegra_periph_reset_deassert(tegra->clk); |
696 | 408 | ||
409 | np_phy = of_parse_phandle(pdev->dev.of_node, "nvidia,phy", 0); | ||
410 | if (!np_phy) { | ||
411 | err = -ENODEV; | ||
412 | goto cleanup_clk_en; | ||
413 | } | ||
414 | |||
415 | u_phy = tegra_usb_get_phy(np_phy); | ||
416 | if (IS_ERR(u_phy)) { | ||
417 | err = PTR_ERR(u_phy); | ||
418 | goto cleanup_clk_en; | ||
419 | } | ||
420 | hcd->phy = u_phy; | ||
421 | |||
697 | tegra->needs_double_reset = of_property_read_bool(pdev->dev.of_node, | 422 | tegra->needs_double_reset = of_property_read_bool(pdev->dev.of_node, |
698 | "nvidia,needs-double-reset"); | 423 | "nvidia,needs-double-reset"); |
699 | 424 | ||
@@ -701,7 +426,7 @@ static int tegra_ehci_probe(struct platform_device *pdev) | |||
701 | if (!res) { | 426 | if (!res) { |
702 | dev_err(&pdev->dev, "Failed to get I/O memory\n"); | 427 | dev_err(&pdev->dev, "Failed to get I/O memory\n"); |
703 | err = -ENXIO; | 428 | err = -ENXIO; |
704 | goto fail_io; | 429 | goto cleanup_clk_en; |
705 | } | 430 | } |
706 | hcd->rsrc_start = res->start; | 431 | hcd->rsrc_start = res->start; |
707 | hcd->rsrc_len = resource_size(res); | 432 | hcd->rsrc_len = resource_size(res); |
@@ -709,68 +434,36 @@ static int tegra_ehci_probe(struct platform_device *pdev) | |||
709 | if (!hcd->regs) { | 434 | if (!hcd->regs) { |
710 | dev_err(&pdev->dev, "Failed to remap I/O memory\n"); | 435 | dev_err(&pdev->dev, "Failed to remap I/O memory\n"); |
711 | err = -ENOMEM; | 436 | err = -ENOMEM; |
712 | goto fail_io; | 437 | goto cleanup_clk_en; |
713 | } | ||
714 | |||
715 | /* This is pretty ugly and needs to be fixed when we do only | ||
716 | * device-tree probing. Old code relies on the platform_device | ||
717 | * numbering that we lack for device-tree-instantiated devices. | ||
718 | */ | ||
719 | if (instance < 0) { | ||
720 | switch (res->start) { | ||
721 | case TEGRA_USB_BASE: | ||
722 | instance = 0; | ||
723 | break; | ||
724 | case TEGRA_USB2_BASE: | ||
725 | instance = 1; | ||
726 | break; | ||
727 | case TEGRA_USB3_BASE: | ||
728 | instance = 2; | ||
729 | break; | ||
730 | default: | ||
731 | err = -ENODEV; | ||
732 | dev_err(&pdev->dev, "unknown usb instance\n"); | ||
733 | goto fail_io; | ||
734 | } | ||
735 | } | 438 | } |
439 | ehci->caps = hcd->regs + 0x100; | ||
736 | 440 | ||
737 | tegra->phy = tegra_usb_phy_open(&pdev->dev, instance, hcd->regs, | 441 | err = usb_phy_init(hcd->phy); |
738 | pdata->phy_config, | 442 | if (err) { |
739 | TEGRA_USB_PHY_MODE_HOST, | 443 | dev_err(&pdev->dev, "Failed to initialize phy\n"); |
740 | tegra_ehci_set_pts, | 444 | goto cleanup_clk_en; |
741 | tegra_ehci_set_phcd); | ||
742 | if (IS_ERR(tegra->phy)) { | ||
743 | dev_err(&pdev->dev, "Failed to open USB phy\n"); | ||
744 | err = -ENXIO; | ||
745 | goto fail_io; | ||
746 | } | 445 | } |
747 | 446 | ||
748 | hcd->phy = u_phy = &tegra->phy->u_phy; | ||
749 | usb_phy_init(hcd->phy); | ||
750 | |||
751 | u_phy->otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg), | 447 | u_phy->otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg), |
752 | GFP_KERNEL); | 448 | GFP_KERNEL); |
753 | if (!u_phy->otg) { | 449 | if (!u_phy->otg) { |
754 | dev_err(&pdev->dev, "Failed to alloc memory for otg\n"); | 450 | dev_err(&pdev->dev, "Failed to alloc memory for otg\n"); |
755 | err = -ENOMEM; | 451 | err = -ENOMEM; |
756 | goto fail_io; | 452 | goto cleanup_phy; |
757 | } | 453 | } |
758 | u_phy->otg->host = hcd_to_bus(hcd); | 454 | u_phy->otg->host = hcd_to_bus(hcd); |
759 | 455 | ||
760 | err = usb_phy_set_suspend(hcd->phy, 0); | 456 | err = usb_phy_set_suspend(hcd->phy, 0); |
761 | if (err) { | 457 | if (err) { |
762 | dev_err(&pdev->dev, "Failed to power on the phy\n"); | 458 | dev_err(&pdev->dev, "Failed to power on the phy\n"); |
763 | goto fail_phy; | 459 | goto cleanup_phy; |
764 | } | 460 | } |
765 | 461 | ||
766 | tegra->host_resumed = 1; | ||
767 | tegra->ehci = hcd_to_ehci(hcd); | ||
768 | |||
769 | irq = platform_get_irq(pdev, 0); | 462 | irq = platform_get_irq(pdev, 0); |
770 | if (!irq) { | 463 | if (!irq) { |
771 | dev_err(&pdev->dev, "Failed to get IRQ\n"); | 464 | dev_err(&pdev->dev, "Failed to get IRQ\n"); |
772 | err = -ENODEV; | 465 | err = -ENODEV; |
773 | goto fail_phy; | 466 | goto cleanup_phy; |
774 | } | 467 | } |
775 | 468 | ||
776 | if (pdata->operating_mode == TEGRA_USB_OTG) { | 469 | if (pdata->operating_mode == TEGRA_USB_OTG) { |
@@ -785,39 +478,32 @@ static int tegra_ehci_probe(struct platform_device *pdev) | |||
785 | err = usb_add_hcd(hcd, irq, IRQF_SHARED); | 478 | err = usb_add_hcd(hcd, irq, IRQF_SHARED); |
786 | if (err) { | 479 | if (err) { |
787 | dev_err(&pdev->dev, "Failed to add USB HCD\n"); | 480 | dev_err(&pdev->dev, "Failed to add USB HCD\n"); |
788 | goto fail; | 481 | goto cleanup_transceiver; |
789 | } | 482 | } |
790 | 483 | ||
791 | pm_runtime_set_active(&pdev->dev); | ||
792 | pm_runtime_get_noresume(&pdev->dev); | ||
793 | |||
794 | /* Don't skip the pm_runtime_forbid call if wakeup isn't working */ | ||
795 | /* if (!pdata->power_down_on_bus_suspend) */ | ||
796 | pm_runtime_forbid(&pdev->dev); | ||
797 | pm_runtime_enable(&pdev->dev); | ||
798 | pm_runtime_put_sync(&pdev->dev); | ||
799 | return err; | 484 | return err; |
800 | 485 | ||
801 | fail: | 486 | cleanup_transceiver: |
802 | if (!IS_ERR(tegra->transceiver)) | 487 | if (!IS_ERR(tegra->transceiver)) |
803 | otg_set_host(tegra->transceiver->otg, NULL); | 488 | otg_set_host(tegra->transceiver->otg, NULL); |
804 | fail_phy: | 489 | cleanup_phy: |
805 | usb_phy_shutdown(hcd->phy); | 490 | usb_phy_shutdown(hcd->phy); |
806 | fail_io: | 491 | cleanup_clk_en: |
807 | clk_disable_unprepare(tegra->clk); | 492 | clk_disable_unprepare(tegra->clk); |
808 | fail_clk: | 493 | cleanup_clk_get: |
494 | clk_put(tegra->clk); | ||
495 | cleanup_hcd_create: | ||
809 | usb_put_hcd(hcd); | 496 | usb_put_hcd(hcd); |
497 | cleanup_vbus_gpio: | ||
498 | /* FIXME: Undo setup_vbus_gpio() here */ | ||
810 | return err; | 499 | return err; |
811 | } | 500 | } |
812 | 501 | ||
813 | static int tegra_ehci_remove(struct platform_device *pdev) | 502 | static int tegra_ehci_remove(struct platform_device *pdev) |
814 | { | 503 | { |
815 | struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev); | 504 | struct usb_hcd *hcd = platform_get_drvdata(pdev); |
816 | struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci); | 505 | struct tegra_ehci_hcd *tegra = |
817 | 506 | (struct tegra_ehci_hcd *)hcd_to_ehci(hcd)->priv; | |
818 | pm_runtime_get_sync(&pdev->dev); | ||
819 | pm_runtime_disable(&pdev->dev); | ||
820 | pm_runtime_put_noidle(&pdev->dev); | ||
821 | 507 | ||
822 | if (!IS_ERR(tegra->transceiver)) | 508 | if (!IS_ERR(tegra->transceiver)) |
823 | otg_set_host(tegra->transceiver->otg, NULL); | 509 | otg_set_host(tegra->transceiver->otg, NULL); |
@@ -833,8 +519,7 @@ static int tegra_ehci_remove(struct platform_device *pdev) | |||
833 | 519 | ||
834 | static void tegra_ehci_hcd_shutdown(struct platform_device *pdev) | 520 | static void tegra_ehci_hcd_shutdown(struct platform_device *pdev) |
835 | { | 521 | { |
836 | struct tegra_ehci_hcd *tegra = platform_get_drvdata(pdev); | 522 | struct usb_hcd *hcd = platform_get_drvdata(pdev); |
837 | struct usb_hcd *hcd = ehci_to_hcd(tegra->ehci); | ||
838 | 523 | ||
839 | if (hcd->driver->shutdown) | 524 | if (hcd->driver->shutdown) |
840 | hcd->driver->shutdown(hcd); | 525 | hcd->driver->shutdown(hcd); |
@@ -850,10 +535,50 @@ static struct platform_driver tegra_ehci_driver = { | |||
850 | .remove = tegra_ehci_remove, | 535 | .remove = tegra_ehci_remove, |
851 | .shutdown = tegra_ehci_hcd_shutdown, | 536 | .shutdown = tegra_ehci_hcd_shutdown, |
852 | .driver = { | 537 | .driver = { |
853 | .name = "tegra-ehci", | 538 | .name = DRV_NAME, |
854 | .of_match_table = tegra_ehci_of_match, | 539 | .of_match_table = tegra_ehci_of_match, |
855 | #ifdef CONFIG_PM | ||
856 | .pm = &tegra_ehci_pm_ops, | ||
857 | #endif | ||
858 | } | 540 | } |
859 | }; | 541 | }; |
542 | |||
543 | static const struct ehci_driver_overrides tegra_overrides __initconst = { | ||
544 | .extra_priv_size = sizeof(struct tegra_ehci_hcd), | ||
545 | }; | ||
546 | |||
547 | static int __init ehci_tegra_init(void) | ||
548 | { | ||
549 | if (usb_disabled()) | ||
550 | return -ENODEV; | ||
551 | |||
552 | pr_info(DRV_NAME ": " DRIVER_DESC "\n"); | ||
553 | |||
554 | ehci_init_driver(&tegra_ehci_hc_driver, &tegra_overrides); | ||
555 | |||
556 | /* | ||
557 | * The Tegra HW has some unusual quirks, which require Tegra-specific | ||
558 | * workarounds. We override certain hc_driver functions here to | ||
559 | * achieve that. We explicitly do not enhance ehci_driver_overrides to | ||
560 | * allow this more easily, since this is an unusual case, and we don't | ||
561 | * want to encourage others to override these functions by making it | ||
562 | * too easy. | ||
563 | */ | ||
564 | |||
565 | orig_hub_control = tegra_ehci_hc_driver.hub_control; | ||
566 | |||
567 | tegra_ehci_hc_driver.map_urb_for_dma = tegra_ehci_map_urb_for_dma; | ||
568 | tegra_ehci_hc_driver.unmap_urb_for_dma = tegra_ehci_unmap_urb_for_dma; | ||
569 | tegra_ehci_hc_driver.hub_control = tegra_ehci_hub_control; | ||
570 | |||
571 | return platform_driver_register(&tegra_ehci_driver); | ||
572 | } | ||
573 | module_init(ehci_tegra_init); | ||
574 | |||
575 | static void __exit ehci_tegra_cleanup(void) | ||
576 | { | ||
577 | platform_driver_unregister(&tegra_ehci_driver); | ||
578 | } | ||
579 | module_exit(ehci_tegra_cleanup); | ||
580 | |||
581 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
582 | MODULE_LICENSE("GPL"); | ||
583 | MODULE_ALIAS("platform:" DRV_NAME); | ||
584 | MODULE_DEVICE_TABLE(of, tegra_ehci_of_match); | ||
diff --git a/drivers/usb/host/ehci-tilegx.c b/drivers/usb/host/ehci-tilegx.c index b083a350eea3..d72b2929c03d 100644 --- a/drivers/usb/host/ehci-tilegx.c +++ b/drivers/usb/host/ehci-tilegx.c | |||
@@ -193,7 +193,6 @@ static int ehci_hcd_tilegx_drv_remove(struct platform_device *pdev) | |||
193 | tilegx_stop_ehc(); | 193 | tilegx_stop_ehc(); |
194 | gxio_usb_host_destroy(&pdata->usb_ctx); | 194 | gxio_usb_host_destroy(&pdata->usb_ctx); |
195 | destroy_irq(pdata->irq); | 195 | destroy_irq(pdata->irq); |
196 | platform_set_drvdata(pdev, NULL); | ||
197 | 196 | ||
198 | return 0; | 197 | return 0; |
199 | } | 198 | } |
diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c index d845e3bcfaff..35c7f90384a6 100644 --- a/drivers/usb/host/ehci-xilinx-of.c +++ b/drivers/usb/host/ehci-xilinx-of.c | |||
@@ -209,8 +209,7 @@ err_irq: | |||
209 | */ | 209 | */ |
210 | static int ehci_hcd_xilinx_of_remove(struct platform_device *op) | 210 | static int ehci_hcd_xilinx_of_remove(struct platform_device *op) |
211 | { | 211 | { |
212 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); | 212 | struct usb_hcd *hcd = platform_get_drvdata(op); |
213 | dev_set_drvdata(&op->dev, NULL); | ||
214 | 213 | ||
215 | dev_dbg(&op->dev, "stopping XILINX-OF USB Controller\n"); | 214 | dev_dbg(&op->dev, "stopping XILINX-OF USB Controller\n"); |
216 | 215 | ||
@@ -229,7 +228,7 @@ static int ehci_hcd_xilinx_of_remove(struct platform_device *op) | |||
229 | */ | 228 | */ |
230 | static void ehci_hcd_xilinx_of_shutdown(struct platform_device *op) | 229 | static void ehci_hcd_xilinx_of_shutdown(struct platform_device *op) |
231 | { | 230 | { |
232 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); | 231 | struct usb_hcd *hcd = platform_get_drvdata(op); |
233 | 232 | ||
234 | if (hcd->driver->shutdown) | 233 | if (hcd->driver->shutdown) |
235 | hcd->driver->shutdown(hcd); | 234 | hcd->driver->shutdown(hcd); |
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 7c978b23520d..64f9a08e959c 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h | |||
@@ -800,6 +800,8 @@ struct ehci_driver_overrides { | |||
800 | extern void ehci_init_driver(struct hc_driver *drv, | 800 | extern void ehci_init_driver(struct hc_driver *drv, |
801 | const struct ehci_driver_overrides *over); | 801 | const struct ehci_driver_overrides *over); |
802 | extern int ehci_setup(struct usb_hcd *hcd); | 802 | extern int ehci_setup(struct usb_hcd *hcd); |
803 | extern int ehci_handshake(struct ehci_hcd *ehci, void __iomem *ptr, | ||
804 | u32 mask, u32 done, int usec); | ||
803 | 805 | ||
804 | #ifdef CONFIG_PM | 806 | #ifdef CONFIG_PM |
805 | extern int ehci_suspend(struct usb_hcd *hcd, bool do_wakeup); | 807 | extern int ehci_suspend(struct usb_hcd *hcd, bool do_wakeup); |
diff --git a/drivers/usb/host/fhci-sched.c b/drivers/usb/host/fhci-sched.c index 8f18538e0ff7..95ca5986e672 100644 --- a/drivers/usb/host/fhci-sched.c +++ b/drivers/usb/host/fhci-sched.c | |||
@@ -739,9 +739,13 @@ void fhci_queue_urb(struct fhci_hcd *fhci, struct urb *urb) | |||
739 | } | 739 | } |
740 | 740 | ||
741 | /* for ISO transfer calculate start frame index */ | 741 | /* for ISO transfer calculate start frame index */ |
742 | if (ed->mode == FHCI_TF_ISO && urb->transfer_flags & URB_ISO_ASAP) | 742 | if (ed->mode == FHCI_TF_ISO) { |
743 | urb->start_frame = ed->td_head ? ed->last_iso + 1 : | 743 | /* Ignore the possibility of underruns */ |
744 | urb->start_frame = ed->td_head ? ed->next_iso : | ||
744 | get_frame_num(fhci); | 745 | get_frame_num(fhci); |
746 | ed->next_iso = (urb->start_frame + urb->interval * | ||
747 | urb->number_of_packets) & 0x07ff; | ||
748 | } | ||
745 | 749 | ||
746 | /* | 750 | /* |
747 | * OHCI handles the DATA toggle itself,we just use the USB | 751 | * OHCI handles the DATA toggle itself,we just use the USB |
diff --git a/drivers/usb/host/fhci.h b/drivers/usb/host/fhci.h index 7cc1c32dc36c..154e6a007727 100644 --- a/drivers/usb/host/fhci.h +++ b/drivers/usb/host/fhci.h | |||
@@ -338,7 +338,7 @@ struct ed { | |||
338 | 338 | ||
339 | /* read only parameters, should be cleared upon initialization */ | 339 | /* read only parameters, should be cleared upon initialization */ |
340 | u8 toggle_carry; /* toggle carry from the last TD submitted */ | 340 | u8 toggle_carry; /* toggle carry from the last TD submitted */ |
341 | u32 last_iso; /* time stamp of last queued ISO transfer */ | 341 | u16 next_iso; /* time stamp of next queued ISO transfer */ |
342 | struct td *td_head; /* a pointer to the current TD handled */ | 342 | struct td *td_head; /* a pointer to the current TD handled */ |
343 | }; | 343 | }; |
344 | 344 | ||
diff --git a/drivers/usb/host/fusbh200-hcd.c b/drivers/usb/host/fusbh200-hcd.c new file mode 100644 index 000000000000..299253c826c7 --- /dev/null +++ b/drivers/usb/host/fusbh200-hcd.c | |||
@@ -0,0 +1,5972 @@ | |||
1 | /* | ||
2 | * Faraday FUSBH200 EHCI-like driver | ||
3 | * | ||
4 | * Copyright (c) 2013 Faraday Technology Corporation | ||
5 | * | ||
6 | * Author: Yuan-Hsin Chen <yhchen@faraday-tech.com> | ||
7 | * Feng-Hsin Chiang <john453@faraday-tech.com> | ||
8 | * Po-Yu Chuang <ratbert.chuang@gmail.com> | ||
9 | * | ||
10 | * Most of code borrowed from the Linux-3.7 EHCI driver | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, but | ||
18 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||
19 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
20 | * for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software Foundation, | ||
24 | * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #include <linux/module.h> | ||
28 | #include <linux/device.h> | ||
29 | #include <linux/dmapool.h> | ||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/delay.h> | ||
32 | #include <linux/ioport.h> | ||
33 | #include <linux/sched.h> | ||
34 | #include <linux/vmalloc.h> | ||
35 | #include <linux/errno.h> | ||
36 | #include <linux/init.h> | ||
37 | #include <linux/hrtimer.h> | ||
38 | #include <linux/list.h> | ||
39 | #include <linux/interrupt.h> | ||
40 | #include <linux/usb.h> | ||
41 | #include <linux/usb/hcd.h> | ||
42 | #include <linux/moduleparam.h> | ||
43 | #include <linux/dma-mapping.h> | ||
44 | #include <linux/debugfs.h> | ||
45 | #include <linux/slab.h> | ||
46 | #include <linux/uaccess.h> | ||
47 | #include <linux/platform_device.h> | ||
48 | |||
49 | #include <asm/byteorder.h> | ||
50 | #include <asm/io.h> | ||
51 | #include <asm/irq.h> | ||
52 | #include <asm/unaligned.h> | ||
53 | |||
54 | /*-------------------------------------------------------------------------*/ | ||
55 | #define DRIVER_AUTHOR "Yuan-Hsin Chen" | ||
56 | #define DRIVER_DESC "FUSBH200 Host Controller (EHCI) Driver" | ||
57 | |||
58 | static const char hcd_name [] = "fusbh200_hcd"; | ||
59 | |||
60 | #undef VERBOSE_DEBUG | ||
61 | #undef FUSBH200_URB_TRACE | ||
62 | |||
63 | #ifdef DEBUG | ||
64 | #define FUSBH200_STATS | ||
65 | #endif | ||
66 | |||
67 | /* magic numbers that can affect system performance */ | ||
68 | #define FUSBH200_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */ | ||
69 | #define FUSBH200_TUNE_RL_HS 4 /* nak throttle; see 4.9 */ | ||
70 | #define FUSBH200_TUNE_RL_TT 0 | ||
71 | #define FUSBH200_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */ | ||
72 | #define FUSBH200_TUNE_MULT_TT 1 | ||
73 | /* | ||
74 | * Some drivers think it's safe to schedule isochronous transfers more than | ||
75 | * 256 ms into the future (partly as a result of an old bug in the scheduling | ||
76 | * code). In an attempt to avoid trouble, we will use a minimum scheduling | ||
77 | * length of 512 frames instead of 256. | ||
78 | */ | ||
79 | #define FUSBH200_TUNE_FLS 1 /* (medium) 512-frame schedule */ | ||
80 | |||
81 | /* Initial IRQ latency: faster than hw default */ | ||
82 | static int log2_irq_thresh = 0; // 0 to 6 | ||
83 | module_param (log2_irq_thresh, int, S_IRUGO); | ||
84 | MODULE_PARM_DESC (log2_irq_thresh, "log2 IRQ latency, 1-64 microframes"); | ||
85 | |||
86 | /* initial park setting: slower than hw default */ | ||
87 | static unsigned park = 0; | ||
88 | module_param (park, uint, S_IRUGO); | ||
89 | MODULE_PARM_DESC (park, "park setting; 1-3 back-to-back async packets"); | ||
90 | |||
91 | /* for link power management(LPM) feature */ | ||
92 | static unsigned int hird; | ||
93 | module_param(hird, int, S_IRUGO); | ||
94 | MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us"); | ||
95 | |||
96 | #define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT) | ||
97 | |||
98 | #include "fusbh200.h" | ||
99 | |||
100 | /*-------------------------------------------------------------------------*/ | ||
101 | |||
102 | #define fusbh200_dbg(fusbh200, fmt, args...) \ | ||
103 | dev_dbg (fusbh200_to_hcd(fusbh200)->self.controller , fmt , ## args ) | ||
104 | #define fusbh200_err(fusbh200, fmt, args...) \ | ||
105 | dev_err (fusbh200_to_hcd(fusbh200)->self.controller , fmt , ## args ) | ||
106 | #define fusbh200_info(fusbh200, fmt, args...) \ | ||
107 | dev_info (fusbh200_to_hcd(fusbh200)->self.controller , fmt , ## args ) | ||
108 | #define fusbh200_warn(fusbh200, fmt, args...) \ | ||
109 | dev_warn (fusbh200_to_hcd(fusbh200)->self.controller , fmt , ## args ) | ||
110 | |||
111 | #ifdef VERBOSE_DEBUG | ||
112 | # define fusbh200_vdbg fusbh200_dbg | ||
113 | #else | ||
114 | static inline void fusbh200_vdbg(struct fusbh200_hcd *fusbh200, ...) {} | ||
115 | #endif | ||
116 | |||
117 | #ifdef DEBUG | ||
118 | |||
119 | /* check the values in the HCSPARAMS register | ||
120 | * (host controller _Structural_ parameters) | ||
121 | * see EHCI spec, Table 2-4 for each value | ||
122 | */ | ||
123 | static void dbg_hcs_params (struct fusbh200_hcd *fusbh200, char *label) | ||
124 | { | ||
125 | u32 params = fusbh200_readl(fusbh200, &fusbh200->caps->hcs_params); | ||
126 | |||
127 | fusbh200_dbg (fusbh200, | ||
128 | "%s hcs_params 0x%x ports=%d\n", | ||
129 | label, params, | ||
130 | HCS_N_PORTS (params) | ||
131 | ); | ||
132 | } | ||
133 | #else | ||
134 | |||
135 | static inline void dbg_hcs_params (struct fusbh200_hcd *fusbh200, char *label) {} | ||
136 | |||
137 | #endif | ||
138 | |||
139 | #ifdef DEBUG | ||
140 | |||
141 | /* check the values in the HCCPARAMS register | ||
142 | * (host controller _Capability_ parameters) | ||
143 | * see EHCI Spec, Table 2-5 for each value | ||
144 | * */ | ||
145 | static void dbg_hcc_params (struct fusbh200_hcd *fusbh200, char *label) | ||
146 | { | ||
147 | u32 params = fusbh200_readl(fusbh200, &fusbh200->caps->hcc_params); | ||
148 | |||
149 | fusbh200_dbg (fusbh200, | ||
150 | "%s hcc_params %04x uframes %s%s\n", | ||
151 | label, | ||
152 | params, | ||
153 | HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024", | ||
154 | HCC_CANPARK(params) ? " park" : ""); | ||
155 | } | ||
156 | #else | ||
157 | |||
158 | static inline void dbg_hcc_params (struct fusbh200_hcd *fusbh200, char *label) {} | ||
159 | |||
160 | #endif | ||
161 | |||
162 | #ifdef DEBUG | ||
163 | |||
164 | static void __maybe_unused | ||
165 | dbg_qtd (const char *label, struct fusbh200_hcd *fusbh200, struct fusbh200_qtd *qtd) | ||
166 | { | ||
167 | fusbh200_dbg(fusbh200, "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd, | ||
168 | hc32_to_cpup(fusbh200, &qtd->hw_next), | ||
169 | hc32_to_cpup(fusbh200, &qtd->hw_alt_next), | ||
170 | hc32_to_cpup(fusbh200, &qtd->hw_token), | ||
171 | hc32_to_cpup(fusbh200, &qtd->hw_buf [0])); | ||
172 | if (qtd->hw_buf [1]) | ||
173 | fusbh200_dbg(fusbh200, " p1=%08x p2=%08x p3=%08x p4=%08x\n", | ||
174 | hc32_to_cpup(fusbh200, &qtd->hw_buf[1]), | ||
175 | hc32_to_cpup(fusbh200, &qtd->hw_buf[2]), | ||
176 | hc32_to_cpup(fusbh200, &qtd->hw_buf[3]), | ||
177 | hc32_to_cpup(fusbh200, &qtd->hw_buf[4])); | ||
178 | } | ||
179 | |||
180 | static void __maybe_unused | ||
181 | dbg_qh (const char *label, struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh) | ||
182 | { | ||
183 | struct fusbh200_qh_hw *hw = qh->hw; | ||
184 | |||
185 | fusbh200_dbg (fusbh200, "%s qh %p n%08x info %x %x qtd %x\n", label, | ||
186 | qh, hw->hw_next, hw->hw_info1, hw->hw_info2, hw->hw_current); | ||
187 | dbg_qtd("overlay", fusbh200, (struct fusbh200_qtd *) &hw->hw_qtd_next); | ||
188 | } | ||
189 | |||
190 | static void __maybe_unused | ||
191 | dbg_itd (const char *label, struct fusbh200_hcd *fusbh200, struct fusbh200_itd *itd) | ||
192 | { | ||
193 | fusbh200_dbg (fusbh200, "%s [%d] itd %p, next %08x, urb %p\n", | ||
194 | label, itd->frame, itd, hc32_to_cpu(fusbh200, itd->hw_next), | ||
195 | itd->urb); | ||
196 | fusbh200_dbg (fusbh200, | ||
197 | " trans: %08x %08x %08x %08x %08x %08x %08x %08x\n", | ||
198 | hc32_to_cpu(fusbh200, itd->hw_transaction[0]), | ||
199 | hc32_to_cpu(fusbh200, itd->hw_transaction[1]), | ||
200 | hc32_to_cpu(fusbh200, itd->hw_transaction[2]), | ||
201 | hc32_to_cpu(fusbh200, itd->hw_transaction[3]), | ||
202 | hc32_to_cpu(fusbh200, itd->hw_transaction[4]), | ||
203 | hc32_to_cpu(fusbh200, itd->hw_transaction[5]), | ||
204 | hc32_to_cpu(fusbh200, itd->hw_transaction[6]), | ||
205 | hc32_to_cpu(fusbh200, itd->hw_transaction[7])); | ||
206 | fusbh200_dbg (fusbh200, | ||
207 | " buf: %08x %08x %08x %08x %08x %08x %08x\n", | ||
208 | hc32_to_cpu(fusbh200, itd->hw_bufp[0]), | ||
209 | hc32_to_cpu(fusbh200, itd->hw_bufp[1]), | ||
210 | hc32_to_cpu(fusbh200, itd->hw_bufp[2]), | ||
211 | hc32_to_cpu(fusbh200, itd->hw_bufp[3]), | ||
212 | hc32_to_cpu(fusbh200, itd->hw_bufp[4]), | ||
213 | hc32_to_cpu(fusbh200, itd->hw_bufp[5]), | ||
214 | hc32_to_cpu(fusbh200, itd->hw_bufp[6])); | ||
215 | fusbh200_dbg (fusbh200, " index: %d %d %d %d %d %d %d %d\n", | ||
216 | itd->index[0], itd->index[1], itd->index[2], | ||
217 | itd->index[3], itd->index[4], itd->index[5], | ||
218 | itd->index[6], itd->index[7]); | ||
219 | } | ||
220 | |||
221 | static int __maybe_unused | ||
222 | dbg_status_buf (char *buf, unsigned len, const char *label, u32 status) | ||
223 | { | ||
224 | return scnprintf (buf, len, | ||
225 | "%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s", | ||
226 | label, label [0] ? " " : "", status, | ||
227 | (status & STS_ASS) ? " Async" : "", | ||
228 | (status & STS_PSS) ? " Periodic" : "", | ||
229 | (status & STS_RECL) ? " Recl" : "", | ||
230 | (status & STS_HALT) ? " Halt" : "", | ||
231 | (status & STS_IAA) ? " IAA" : "", | ||
232 | (status & STS_FATAL) ? " FATAL" : "", | ||
233 | (status & STS_FLR) ? " FLR" : "", | ||
234 | (status & STS_PCD) ? " PCD" : "", | ||
235 | (status & STS_ERR) ? " ERR" : "", | ||
236 | (status & STS_INT) ? " INT" : "" | ||
237 | ); | ||
238 | } | ||
239 | |||
240 | static int __maybe_unused | ||
241 | dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable) | ||
242 | { | ||
243 | return scnprintf (buf, len, | ||
244 | "%s%sintrenable %02x%s%s%s%s%s%s", | ||
245 | label, label [0] ? " " : "", enable, | ||
246 | (enable & STS_IAA) ? " IAA" : "", | ||
247 | (enable & STS_FATAL) ? " FATAL" : "", | ||
248 | (enable & STS_FLR) ? " FLR" : "", | ||
249 | (enable & STS_PCD) ? " PCD" : "", | ||
250 | (enable & STS_ERR) ? " ERR" : "", | ||
251 | (enable & STS_INT) ? " INT" : "" | ||
252 | ); | ||
253 | } | ||
254 | |||
255 | static const char *const fls_strings [] = | ||
256 | { "1024", "512", "256", "??" }; | ||
257 | |||
258 | static int | ||
259 | dbg_command_buf (char *buf, unsigned len, const char *label, u32 command) | ||
260 | { | ||
261 | return scnprintf (buf, len, | ||
262 | "%s%scommand %07x %s=%d ithresh=%d%s%s%s " | ||
263 | "period=%s%s %s", | ||
264 | label, label [0] ? " " : "", command, | ||
265 | (command & CMD_PARK) ? " park" : "(park)", | ||
266 | CMD_PARK_CNT (command), | ||
267 | (command >> 16) & 0x3f, | ||
268 | (command & CMD_IAAD) ? " IAAD" : "", | ||
269 | (command & CMD_ASE) ? " Async" : "", | ||
270 | (command & CMD_PSE) ? " Periodic" : "", | ||
271 | fls_strings [(command >> 2) & 0x3], | ||
272 | (command & CMD_RESET) ? " Reset" : "", | ||
273 | (command & CMD_RUN) ? "RUN" : "HALT" | ||
274 | ); | ||
275 | } | ||
276 | |||
277 | static int | ||
278 | dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status) | ||
279 | { | ||
280 | char *sig; | ||
281 | |||
282 | /* signaling state */ | ||
283 | switch (status & (3 << 10)) { | ||
284 | case 0 << 10: sig = "se0"; break; | ||
285 | case 1 << 10: sig = "k"; break; /* low speed */ | ||
286 | case 2 << 10: sig = "j"; break; | ||
287 | default: sig = "?"; break; | ||
288 | } | ||
289 | |||
290 | return scnprintf (buf, len, | ||
291 | "%s%sport:%d status %06x %d " | ||
292 | "sig=%s%s%s%s%s%s%s%s", | ||
293 | label, label [0] ? " " : "", port, status, | ||
294 | status>>25,/*device address */ | ||
295 | sig, | ||
296 | (status & PORT_RESET) ? " RESET" : "", | ||
297 | (status & PORT_SUSPEND) ? " SUSPEND" : "", | ||
298 | (status & PORT_RESUME) ? " RESUME" : "", | ||
299 | (status & PORT_PEC) ? " PEC" : "", | ||
300 | (status & PORT_PE) ? " PE" : "", | ||
301 | (status & PORT_CSC) ? " CSC" : "", | ||
302 | (status & PORT_CONNECT) ? " CONNECT" : ""); | ||
303 | } | ||
304 | |||
305 | #else | ||
306 | static inline void __maybe_unused | ||
307 | dbg_qh (char *label, struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh) | ||
308 | {} | ||
309 | |||
310 | static inline int __maybe_unused | ||
311 | dbg_status_buf (char *buf, unsigned len, const char *label, u32 status) | ||
312 | { return 0; } | ||
313 | |||
314 | static inline int __maybe_unused | ||
315 | dbg_command_buf (char *buf, unsigned len, const char *label, u32 command) | ||
316 | { return 0; } | ||
317 | |||
318 | static inline int __maybe_unused | ||
319 | dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable) | ||
320 | { return 0; } | ||
321 | |||
322 | static inline int __maybe_unused | ||
323 | dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status) | ||
324 | { return 0; } | ||
325 | |||
326 | #endif /* DEBUG */ | ||
327 | |||
328 | /* functions have the "wrong" filename when they're output... */ | ||
329 | #define dbg_status(fusbh200, label, status) { \ | ||
330 | char _buf [80]; \ | ||
331 | dbg_status_buf (_buf, sizeof _buf, label, status); \ | ||
332 | fusbh200_dbg (fusbh200, "%s\n", _buf); \ | ||
333 | } | ||
334 | |||
335 | #define dbg_cmd(fusbh200, label, command) { \ | ||
336 | char _buf [80]; \ | ||
337 | dbg_command_buf (_buf, sizeof _buf, label, command); \ | ||
338 | fusbh200_dbg (fusbh200, "%s\n", _buf); \ | ||
339 | } | ||
340 | |||
341 | #define dbg_port(fusbh200, label, port, status) { \ | ||
342 | char _buf [80]; \ | ||
343 | dbg_port_buf (_buf, sizeof _buf, label, port, status); \ | ||
344 | fusbh200_dbg (fusbh200, "%s\n", _buf); \ | ||
345 | } | ||
346 | |||
347 | /*-------------------------------------------------------------------------*/ | ||
348 | |||
349 | #ifdef STUB_DEBUG_FILES | ||
350 | |||
351 | static inline void create_debug_files (struct fusbh200_hcd *bus) { } | ||
352 | static inline void remove_debug_files (struct fusbh200_hcd *bus) { } | ||
353 | |||
354 | #else | ||
355 | |||
356 | /* troubleshooting help: expose state in debugfs */ | ||
357 | |||
358 | static int debug_async_open(struct inode *, struct file *); | ||
359 | static int debug_periodic_open(struct inode *, struct file *); | ||
360 | static int debug_registers_open(struct inode *, struct file *); | ||
361 | static int debug_async_open(struct inode *, struct file *); | ||
362 | |||
363 | static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*); | ||
364 | static int debug_close(struct inode *, struct file *); | ||
365 | |||
366 | static const struct file_operations debug_async_fops = { | ||
367 | .owner = THIS_MODULE, | ||
368 | .open = debug_async_open, | ||
369 | .read = debug_output, | ||
370 | .release = debug_close, | ||
371 | .llseek = default_llseek, | ||
372 | }; | ||
373 | static const struct file_operations debug_periodic_fops = { | ||
374 | .owner = THIS_MODULE, | ||
375 | .open = debug_periodic_open, | ||
376 | .read = debug_output, | ||
377 | .release = debug_close, | ||
378 | .llseek = default_llseek, | ||
379 | }; | ||
380 | static const struct file_operations debug_registers_fops = { | ||
381 | .owner = THIS_MODULE, | ||
382 | .open = debug_registers_open, | ||
383 | .read = debug_output, | ||
384 | .release = debug_close, | ||
385 | .llseek = default_llseek, | ||
386 | }; | ||
387 | |||
388 | static struct dentry *fusbh200_debug_root; | ||
389 | |||
390 | struct debug_buffer { | ||
391 | ssize_t (*fill_func)(struct debug_buffer *); /* fill method */ | ||
392 | struct usb_bus *bus; | ||
393 | struct mutex mutex; /* protect filling of buffer */ | ||
394 | size_t count; /* number of characters filled into buffer */ | ||
395 | char *output_buf; | ||
396 | size_t alloc_size; | ||
397 | }; | ||
398 | |||
399 | #define speed_char(info1) ({ char tmp; \ | ||
400 | switch (info1 & (3 << 12)) { \ | ||
401 | case QH_FULL_SPEED: tmp = 'f'; break; \ | ||
402 | case QH_LOW_SPEED: tmp = 'l'; break; \ | ||
403 | case QH_HIGH_SPEED: tmp = 'h'; break; \ | ||
404 | default: tmp = '?'; break; \ | ||
405 | }; tmp; }) | ||
406 | |||
407 | static inline char token_mark(struct fusbh200_hcd *fusbh200, __hc32 token) | ||
408 | { | ||
409 | __u32 v = hc32_to_cpu(fusbh200, token); | ||
410 | |||
411 | if (v & QTD_STS_ACTIVE) | ||
412 | return '*'; | ||
413 | if (v & QTD_STS_HALT) | ||
414 | return '-'; | ||
415 | if (!IS_SHORT_READ (v)) | ||
416 | return ' '; | ||
417 | /* tries to advance through hw_alt_next */ | ||
418 | return '/'; | ||
419 | } | ||
420 | |||
421 | static void qh_lines ( | ||
422 | struct fusbh200_hcd *fusbh200, | ||
423 | struct fusbh200_qh *qh, | ||
424 | char **nextp, | ||
425 | unsigned *sizep | ||
426 | ) | ||
427 | { | ||
428 | u32 scratch; | ||
429 | u32 hw_curr; | ||
430 | struct fusbh200_qtd *td; | ||
431 | unsigned temp; | ||
432 | unsigned size = *sizep; | ||
433 | char *next = *nextp; | ||
434 | char mark; | ||
435 | __le32 list_end = FUSBH200_LIST_END(fusbh200); | ||
436 | struct fusbh200_qh_hw *hw = qh->hw; | ||
437 | |||
438 | if (hw->hw_qtd_next == list_end) /* NEC does this */ | ||
439 | mark = '@'; | ||
440 | else | ||
441 | mark = token_mark(fusbh200, hw->hw_token); | ||
442 | if (mark == '/') { /* qh_alt_next controls qh advance? */ | ||
443 | if ((hw->hw_alt_next & QTD_MASK(fusbh200)) | ||
444 | == fusbh200->async->hw->hw_alt_next) | ||
445 | mark = '#'; /* blocked */ | ||
446 | else if (hw->hw_alt_next == list_end) | ||
447 | mark = '.'; /* use hw_qtd_next */ | ||
448 | /* else alt_next points to some other qtd */ | ||
449 | } | ||
450 | scratch = hc32_to_cpup(fusbh200, &hw->hw_info1); | ||
451 | hw_curr = (mark == '*') ? hc32_to_cpup(fusbh200, &hw->hw_current) : 0; | ||
452 | temp = scnprintf (next, size, | ||
453 | "qh/%p dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)", | ||
454 | qh, scratch & 0x007f, | ||
455 | speed_char (scratch), | ||
456 | (scratch >> 8) & 0x000f, | ||
457 | scratch, hc32_to_cpup(fusbh200, &hw->hw_info2), | ||
458 | hc32_to_cpup(fusbh200, &hw->hw_token), mark, | ||
459 | (cpu_to_hc32(fusbh200, QTD_TOGGLE) & hw->hw_token) | ||
460 | ? "data1" : "data0", | ||
461 | (hc32_to_cpup(fusbh200, &hw->hw_alt_next) >> 1) & 0x0f); | ||
462 | size -= temp; | ||
463 | next += temp; | ||
464 | |||
465 | /* hc may be modifying the list as we read it ... */ | ||
466 | list_for_each_entry(td, &qh->qtd_list, qtd_list) { | ||
467 | scratch = hc32_to_cpup(fusbh200, &td->hw_token); | ||
468 | mark = ' '; | ||
469 | if (hw_curr == td->qtd_dma) | ||
470 | mark = '*'; | ||
471 | else if (hw->hw_qtd_next == cpu_to_hc32(fusbh200, td->qtd_dma)) | ||
472 | mark = '+'; | ||
473 | else if (QTD_LENGTH (scratch)) { | ||
474 | if (td->hw_alt_next == fusbh200->async->hw->hw_alt_next) | ||
475 | mark = '#'; | ||
476 | else if (td->hw_alt_next != list_end) | ||
477 | mark = '/'; | ||
478 | } | ||
479 | temp = snprintf (next, size, | ||
480 | "\n\t%p%c%s len=%d %08x urb %p", | ||
481 | td, mark, ({ char *tmp; | ||
482 | switch ((scratch>>8)&0x03) { | ||
483 | case 0: tmp = "out"; break; | ||
484 | case 1: tmp = "in"; break; | ||
485 | case 2: tmp = "setup"; break; | ||
486 | default: tmp = "?"; break; | ||
487 | } tmp;}), | ||
488 | (scratch >> 16) & 0x7fff, | ||
489 | scratch, | ||
490 | td->urb); | ||
491 | if (size < temp) | ||
492 | temp = size; | ||
493 | size -= temp; | ||
494 | next += temp; | ||
495 | if (temp == size) | ||
496 | goto done; | ||
497 | } | ||
498 | |||
499 | temp = snprintf (next, size, "\n"); | ||
500 | if (size < temp) | ||
501 | temp = size; | ||
502 | size -= temp; | ||
503 | next += temp; | ||
504 | |||
505 | done: | ||
506 | *sizep = size; | ||
507 | *nextp = next; | ||
508 | } | ||
509 | |||
510 | static ssize_t fill_async_buffer(struct debug_buffer *buf) | ||
511 | { | ||
512 | struct usb_hcd *hcd; | ||
513 | struct fusbh200_hcd *fusbh200; | ||
514 | unsigned long flags; | ||
515 | unsigned temp, size; | ||
516 | char *next; | ||
517 | struct fusbh200_qh *qh; | ||
518 | |||
519 | hcd = bus_to_hcd(buf->bus); | ||
520 | fusbh200 = hcd_to_fusbh200 (hcd); | ||
521 | next = buf->output_buf; | ||
522 | size = buf->alloc_size; | ||
523 | |||
524 | *next = 0; | ||
525 | |||
526 | /* dumps a snapshot of the async schedule. | ||
527 | * usually empty except for long-term bulk reads, or head. | ||
528 | * one QH per line, and TDs we know about | ||
529 | */ | ||
530 | spin_lock_irqsave (&fusbh200->lock, flags); | ||
531 | for (qh = fusbh200->async->qh_next.qh; size > 0 && qh; qh = qh->qh_next.qh) | ||
532 | qh_lines (fusbh200, qh, &next, &size); | ||
533 | if (fusbh200->async_unlink && size > 0) { | ||
534 | temp = scnprintf(next, size, "\nunlink =\n"); | ||
535 | size -= temp; | ||
536 | next += temp; | ||
537 | |||
538 | for (qh = fusbh200->async_unlink; size > 0 && qh; | ||
539 | qh = qh->unlink_next) | ||
540 | qh_lines (fusbh200, qh, &next, &size); | ||
541 | } | ||
542 | spin_unlock_irqrestore (&fusbh200->lock, flags); | ||
543 | |||
544 | return strlen(buf->output_buf); | ||
545 | } | ||
546 | |||
547 | #define DBG_SCHED_LIMIT 64 | ||
548 | static ssize_t fill_periodic_buffer(struct debug_buffer *buf) | ||
549 | { | ||
550 | struct usb_hcd *hcd; | ||
551 | struct fusbh200_hcd *fusbh200; | ||
552 | unsigned long flags; | ||
553 | union fusbh200_shadow p, *seen; | ||
554 | unsigned temp, size, seen_count; | ||
555 | char *next; | ||
556 | unsigned i; | ||
557 | __hc32 tag; | ||
558 | |||
559 | if (!(seen = kmalloc (DBG_SCHED_LIMIT * sizeof *seen, GFP_ATOMIC))) | ||
560 | return 0; | ||
561 | seen_count = 0; | ||
562 | |||
563 | hcd = bus_to_hcd(buf->bus); | ||
564 | fusbh200 = hcd_to_fusbh200 (hcd); | ||
565 | next = buf->output_buf; | ||
566 | size = buf->alloc_size; | ||
567 | |||
568 | temp = scnprintf (next, size, "size = %d\n", fusbh200->periodic_size); | ||
569 | size -= temp; | ||
570 | next += temp; | ||
571 | |||
572 | /* dump a snapshot of the periodic schedule. | ||
573 | * iso changes, interrupt usually doesn't. | ||
574 | */ | ||
575 | spin_lock_irqsave (&fusbh200->lock, flags); | ||
576 | for (i = 0; i < fusbh200->periodic_size; i++) { | ||
577 | p = fusbh200->pshadow [i]; | ||
578 | if (likely (!p.ptr)) | ||
579 | continue; | ||
580 | tag = Q_NEXT_TYPE(fusbh200, fusbh200->periodic [i]); | ||
581 | |||
582 | temp = scnprintf (next, size, "%4d: ", i); | ||
583 | size -= temp; | ||
584 | next += temp; | ||
585 | |||
586 | do { | ||
587 | struct fusbh200_qh_hw *hw; | ||
588 | |||
589 | switch (hc32_to_cpu(fusbh200, tag)) { | ||
590 | case Q_TYPE_QH: | ||
591 | hw = p.qh->hw; | ||
592 | temp = scnprintf (next, size, " qh%d-%04x/%p", | ||
593 | p.qh->period, | ||
594 | hc32_to_cpup(fusbh200, | ||
595 | &hw->hw_info2) | ||
596 | /* uframe masks */ | ||
597 | & (QH_CMASK | QH_SMASK), | ||
598 | p.qh); | ||
599 | size -= temp; | ||
600 | next += temp; | ||
601 | /* don't repeat what follows this qh */ | ||
602 | for (temp = 0; temp < seen_count; temp++) { | ||
603 | if (seen [temp].ptr != p.ptr) | ||
604 | continue; | ||
605 | if (p.qh->qh_next.ptr) { | ||
606 | temp = scnprintf (next, size, | ||
607 | " ..."); | ||
608 | size -= temp; | ||
609 | next += temp; | ||
610 | } | ||
611 | break; | ||
612 | } | ||
613 | /* show more info the first time around */ | ||
614 | if (temp == seen_count) { | ||
615 | u32 scratch = hc32_to_cpup(fusbh200, | ||
616 | &hw->hw_info1); | ||
617 | struct fusbh200_qtd *qtd; | ||
618 | char *type = ""; | ||
619 | |||
620 | /* count tds, get ep direction */ | ||
621 | temp = 0; | ||
622 | list_for_each_entry (qtd, | ||
623 | &p.qh->qtd_list, | ||
624 | qtd_list) { | ||
625 | temp++; | ||
626 | switch (0x03 & (hc32_to_cpu( | ||
627 | fusbh200, | ||
628 | qtd->hw_token) >> 8)) { | ||
629 | case 0: type = "out"; continue; | ||
630 | case 1: type = "in"; continue; | ||
631 | } | ||
632 | } | ||
633 | |||
634 | temp = scnprintf (next, size, | ||
635 | " (%c%d ep%d%s " | ||
636 | "[%d/%d] q%d p%d)", | ||
637 | speed_char (scratch), | ||
638 | scratch & 0x007f, | ||
639 | (scratch >> 8) & 0x000f, type, | ||
640 | p.qh->usecs, p.qh->c_usecs, | ||
641 | temp, | ||
642 | 0x7ff & (scratch >> 16)); | ||
643 | |||
644 | if (seen_count < DBG_SCHED_LIMIT) | ||
645 | seen [seen_count++].qh = p.qh; | ||
646 | } else | ||
647 | temp = 0; | ||
648 | tag = Q_NEXT_TYPE(fusbh200, hw->hw_next); | ||
649 | p = p.qh->qh_next; | ||
650 | break; | ||
651 | case Q_TYPE_FSTN: | ||
652 | temp = scnprintf (next, size, | ||
653 | " fstn-%8x/%p", p.fstn->hw_prev, | ||
654 | p.fstn); | ||
655 | tag = Q_NEXT_TYPE(fusbh200, p.fstn->hw_next); | ||
656 | p = p.fstn->fstn_next; | ||
657 | break; | ||
658 | case Q_TYPE_ITD: | ||
659 | temp = scnprintf (next, size, | ||
660 | " itd/%p", p.itd); | ||
661 | tag = Q_NEXT_TYPE(fusbh200, p.itd->hw_next); | ||
662 | p = p.itd->itd_next; | ||
663 | break; | ||
664 | } | ||
665 | size -= temp; | ||
666 | next += temp; | ||
667 | } while (p.ptr); | ||
668 | |||
669 | temp = scnprintf (next, size, "\n"); | ||
670 | size -= temp; | ||
671 | next += temp; | ||
672 | } | ||
673 | spin_unlock_irqrestore (&fusbh200->lock, flags); | ||
674 | kfree (seen); | ||
675 | |||
676 | return buf->alloc_size - size; | ||
677 | } | ||
678 | #undef DBG_SCHED_LIMIT | ||
679 | |||
680 | static const char *rh_state_string(struct fusbh200_hcd *fusbh200) | ||
681 | { | ||
682 | switch (fusbh200->rh_state) { | ||
683 | case FUSBH200_RH_HALTED: | ||
684 | return "halted"; | ||
685 | case FUSBH200_RH_SUSPENDED: | ||
686 | return "suspended"; | ||
687 | case FUSBH200_RH_RUNNING: | ||
688 | return "running"; | ||
689 | case FUSBH200_RH_STOPPING: | ||
690 | return "stopping"; | ||
691 | } | ||
692 | return "?"; | ||
693 | } | ||
694 | |||
695 | static ssize_t fill_registers_buffer(struct debug_buffer *buf) | ||
696 | { | ||
697 | struct usb_hcd *hcd; | ||
698 | struct fusbh200_hcd *fusbh200; | ||
699 | unsigned long flags; | ||
700 | unsigned temp, size, i; | ||
701 | char *next, scratch [80]; | ||
702 | static char fmt [] = "%*s\n"; | ||
703 | static char label [] = ""; | ||
704 | |||
705 | hcd = bus_to_hcd(buf->bus); | ||
706 | fusbh200 = hcd_to_fusbh200 (hcd); | ||
707 | next = buf->output_buf; | ||
708 | size = buf->alloc_size; | ||
709 | |||
710 | spin_lock_irqsave (&fusbh200->lock, flags); | ||
711 | |||
712 | if (!HCD_HW_ACCESSIBLE(hcd)) { | ||
713 | size = scnprintf (next, size, | ||
714 | "bus %s, device %s\n" | ||
715 | "%s\n" | ||
716 | "SUSPENDED (no register access)\n", | ||
717 | hcd->self.controller->bus->name, | ||
718 | dev_name(hcd->self.controller), | ||
719 | hcd->product_desc); | ||
720 | goto done; | ||
721 | } | ||
722 | |||
723 | /* Capability Registers */ | ||
724 | i = HC_VERSION(fusbh200, fusbh200_readl(fusbh200, &fusbh200->caps->hc_capbase)); | ||
725 | temp = scnprintf (next, size, | ||
726 | "bus %s, device %s\n" | ||
727 | "%s\n" | ||
728 | "EHCI %x.%02x, rh state %s\n", | ||
729 | hcd->self.controller->bus->name, | ||
730 | dev_name(hcd->self.controller), | ||
731 | hcd->product_desc, | ||
732 | i >> 8, i & 0x0ff, rh_state_string(fusbh200)); | ||
733 | size -= temp; | ||
734 | next += temp; | ||
735 | |||
736 | // FIXME interpret both types of params | ||
737 | i = fusbh200_readl(fusbh200, &fusbh200->caps->hcs_params); | ||
738 | temp = scnprintf (next, size, "structural params 0x%08x\n", i); | ||
739 | size -= temp; | ||
740 | next += temp; | ||
741 | |||
742 | i = fusbh200_readl(fusbh200, &fusbh200->caps->hcc_params); | ||
743 | temp = scnprintf (next, size, "capability params 0x%08x\n", i); | ||
744 | size -= temp; | ||
745 | next += temp; | ||
746 | |||
747 | /* Operational Registers */ | ||
748 | temp = dbg_status_buf (scratch, sizeof scratch, label, | ||
749 | fusbh200_readl(fusbh200, &fusbh200->regs->status)); | ||
750 | temp = scnprintf (next, size, fmt, temp, scratch); | ||
751 | size -= temp; | ||
752 | next += temp; | ||
753 | |||
754 | temp = dbg_command_buf (scratch, sizeof scratch, label, | ||
755 | fusbh200_readl(fusbh200, &fusbh200->regs->command)); | ||
756 | temp = scnprintf (next, size, fmt, temp, scratch); | ||
757 | size -= temp; | ||
758 | next += temp; | ||
759 | |||
760 | temp = dbg_intr_buf (scratch, sizeof scratch, label, | ||
761 | fusbh200_readl(fusbh200, &fusbh200->regs->intr_enable)); | ||
762 | temp = scnprintf (next, size, fmt, temp, scratch); | ||
763 | size -= temp; | ||
764 | next += temp; | ||
765 | |||
766 | temp = scnprintf (next, size, "uframe %04x\n", | ||
767 | fusbh200_read_frame_index(fusbh200)); | ||
768 | size -= temp; | ||
769 | next += temp; | ||
770 | |||
771 | if (fusbh200->async_unlink) { | ||
772 | temp = scnprintf(next, size, "async unlink qh %p\n", | ||
773 | fusbh200->async_unlink); | ||
774 | size -= temp; | ||
775 | next += temp; | ||
776 | } | ||
777 | |||
778 | #ifdef FUSBH200_STATS | ||
779 | temp = scnprintf (next, size, | ||
780 | "irq normal %ld err %ld iaa %ld (lost %ld)\n", | ||
781 | fusbh200->stats.normal, fusbh200->stats.error, fusbh200->stats.iaa, | ||
782 | fusbh200->stats.lost_iaa); | ||
783 | size -= temp; | ||
784 | next += temp; | ||
785 | |||
786 | temp = scnprintf (next, size, "complete %ld unlink %ld\n", | ||
787 | fusbh200->stats.complete, fusbh200->stats.unlink); | ||
788 | size -= temp; | ||
789 | next += temp; | ||
790 | #endif | ||
791 | |||
792 | done: | ||
793 | spin_unlock_irqrestore (&fusbh200->lock, flags); | ||
794 | |||
795 | return buf->alloc_size - size; | ||
796 | } | ||
797 | |||
798 | static struct debug_buffer *alloc_buffer(struct usb_bus *bus, | ||
799 | ssize_t (*fill_func)(struct debug_buffer *)) | ||
800 | { | ||
801 | struct debug_buffer *buf; | ||
802 | |||
803 | buf = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL); | ||
804 | |||
805 | if (buf) { | ||
806 | buf->bus = bus; | ||
807 | buf->fill_func = fill_func; | ||
808 | mutex_init(&buf->mutex); | ||
809 | buf->alloc_size = PAGE_SIZE; | ||
810 | } | ||
811 | |||
812 | return buf; | ||
813 | } | ||
814 | |||
815 | static int fill_buffer(struct debug_buffer *buf) | ||
816 | { | ||
817 | int ret = 0; | ||
818 | |||
819 | if (!buf->output_buf) | ||
820 | buf->output_buf = vmalloc(buf->alloc_size); | ||
821 | |||
822 | if (!buf->output_buf) { | ||
823 | ret = -ENOMEM; | ||
824 | goto out; | ||
825 | } | ||
826 | |||
827 | ret = buf->fill_func(buf); | ||
828 | |||
829 | if (ret >= 0) { | ||
830 | buf->count = ret; | ||
831 | ret = 0; | ||
832 | } | ||
833 | |||
834 | out: | ||
835 | return ret; | ||
836 | } | ||
837 | |||
838 | static ssize_t debug_output(struct file *file, char __user *user_buf, | ||
839 | size_t len, loff_t *offset) | ||
840 | { | ||
841 | struct debug_buffer *buf = file->private_data; | ||
842 | int ret = 0; | ||
843 | |||
844 | mutex_lock(&buf->mutex); | ||
845 | if (buf->count == 0) { | ||
846 | ret = fill_buffer(buf); | ||
847 | if (ret != 0) { | ||
848 | mutex_unlock(&buf->mutex); | ||
849 | goto out; | ||
850 | } | ||
851 | } | ||
852 | mutex_unlock(&buf->mutex); | ||
853 | |||
854 | ret = simple_read_from_buffer(user_buf, len, offset, | ||
855 | buf->output_buf, buf->count); | ||
856 | |||
857 | out: | ||
858 | return ret; | ||
859 | |||
860 | } | ||
861 | |||
862 | static int debug_close(struct inode *inode, struct file *file) | ||
863 | { | ||
864 | struct debug_buffer *buf = file->private_data; | ||
865 | |||
866 | if (buf) { | ||
867 | vfree(buf->output_buf); | ||
868 | kfree(buf); | ||
869 | } | ||
870 | |||
871 | return 0; | ||
872 | } | ||
873 | static int debug_async_open(struct inode *inode, struct file *file) | ||
874 | { | ||
875 | file->private_data = alloc_buffer(inode->i_private, fill_async_buffer); | ||
876 | |||
877 | return file->private_data ? 0 : -ENOMEM; | ||
878 | } | ||
879 | |||
880 | static int debug_periodic_open(struct inode *inode, struct file *file) | ||
881 | { | ||
882 | struct debug_buffer *buf; | ||
883 | buf = alloc_buffer(inode->i_private, fill_periodic_buffer); | ||
884 | if (!buf) | ||
885 | return -ENOMEM; | ||
886 | |||
887 | buf->alloc_size = (sizeof(void *) == 4 ? 6 : 8)*PAGE_SIZE; | ||
888 | file->private_data = buf; | ||
889 | return 0; | ||
890 | } | ||
891 | |||
892 | static int debug_registers_open(struct inode *inode, struct file *file) | ||
893 | { | ||
894 | file->private_data = alloc_buffer(inode->i_private, | ||
895 | fill_registers_buffer); | ||
896 | |||
897 | return file->private_data ? 0 : -ENOMEM; | ||
898 | } | ||
899 | |||
900 | static inline void create_debug_files (struct fusbh200_hcd *fusbh200) | ||
901 | { | ||
902 | struct usb_bus *bus = &fusbh200_to_hcd(fusbh200)->self; | ||
903 | |||
904 | fusbh200->debug_dir = debugfs_create_dir(bus->bus_name, fusbh200_debug_root); | ||
905 | if (!fusbh200->debug_dir) | ||
906 | return; | ||
907 | |||
908 | if (!debugfs_create_file("async", S_IRUGO, fusbh200->debug_dir, bus, | ||
909 | &debug_async_fops)) | ||
910 | goto file_error; | ||
911 | |||
912 | if (!debugfs_create_file("periodic", S_IRUGO, fusbh200->debug_dir, bus, | ||
913 | &debug_periodic_fops)) | ||
914 | goto file_error; | ||
915 | |||
916 | if (!debugfs_create_file("registers", S_IRUGO, fusbh200->debug_dir, bus, | ||
917 | &debug_registers_fops)) | ||
918 | goto file_error; | ||
919 | |||
920 | return; | ||
921 | |||
922 | file_error: | ||
923 | debugfs_remove_recursive(fusbh200->debug_dir); | ||
924 | } | ||
925 | |||
926 | static inline void remove_debug_files (struct fusbh200_hcd *fusbh200) | ||
927 | { | ||
928 | debugfs_remove_recursive(fusbh200->debug_dir); | ||
929 | } | ||
930 | |||
931 | #endif /* STUB_DEBUG_FILES */ | ||
932 | /*-------------------------------------------------------------------------*/ | ||
933 | |||
934 | /* | ||
935 | * handshake - spin reading hc until handshake completes or fails | ||
936 | * @ptr: address of hc register to be read | ||
937 | * @mask: bits to look at in result of read | ||
938 | * @done: value of those bits when handshake succeeds | ||
939 | * @usec: timeout in microseconds | ||
940 | * | ||
941 | * Returns negative errno, or zero on success | ||
942 | * | ||
943 | * Success happens when the "mask" bits have the specified value (hardware | ||
944 | * handshake done). There are two failure modes: "usec" have passed (major | ||
945 | * hardware flakeout), or the register reads as all-ones (hardware removed). | ||
946 | * | ||
947 | * That last failure should_only happen in cases like physical cardbus eject | ||
948 | * before driver shutdown. But it also seems to be caused by bugs in cardbus | ||
949 | * bridge shutdown: shutting down the bridge before the devices using it. | ||
950 | */ | ||
951 | static int handshake (struct fusbh200_hcd *fusbh200, void __iomem *ptr, | ||
952 | u32 mask, u32 done, int usec) | ||
953 | { | ||
954 | u32 result; | ||
955 | |||
956 | do { | ||
957 | result = fusbh200_readl(fusbh200, ptr); | ||
958 | if (result == ~(u32)0) /* card removed */ | ||
959 | return -ENODEV; | ||
960 | result &= mask; | ||
961 | if (result == done) | ||
962 | return 0; | ||
963 | udelay (1); | ||
964 | usec--; | ||
965 | } while (usec > 0); | ||
966 | return -ETIMEDOUT; | ||
967 | } | ||
968 | |||
969 | /* | ||
970 | * Force HC to halt state from unknown (EHCI spec section 2.3). | ||
971 | * Must be called with interrupts enabled and the lock not held. | ||
972 | */ | ||
973 | static int fusbh200_halt (struct fusbh200_hcd *fusbh200) | ||
974 | { | ||
975 | u32 temp; | ||
976 | |||
977 | spin_lock_irq(&fusbh200->lock); | ||
978 | |||
979 | /* disable any irqs left enabled by previous code */ | ||
980 | fusbh200_writel(fusbh200, 0, &fusbh200->regs->intr_enable); | ||
981 | |||
982 | /* | ||
983 | * This routine gets called during probe before fusbh200->command | ||
984 | * has been initialized, so we can't rely on its value. | ||
985 | */ | ||
986 | fusbh200->command &= ~CMD_RUN; | ||
987 | temp = fusbh200_readl(fusbh200, &fusbh200->regs->command); | ||
988 | temp &= ~(CMD_RUN | CMD_IAAD); | ||
989 | fusbh200_writel(fusbh200, temp, &fusbh200->regs->command); | ||
990 | |||
991 | spin_unlock_irq(&fusbh200->lock); | ||
992 | synchronize_irq(fusbh200_to_hcd(fusbh200)->irq); | ||
993 | |||
994 | return handshake(fusbh200, &fusbh200->regs->status, | ||
995 | STS_HALT, STS_HALT, 16 * 125); | ||
996 | } | ||
997 | |||
998 | /* | ||
999 | * Reset a non-running (STS_HALT == 1) controller. | ||
1000 | * Must be called with interrupts enabled and the lock not held. | ||
1001 | */ | ||
1002 | static int fusbh200_reset (struct fusbh200_hcd *fusbh200) | ||
1003 | { | ||
1004 | int retval; | ||
1005 | u32 command = fusbh200_readl(fusbh200, &fusbh200->regs->command); | ||
1006 | |||
1007 | /* If the EHCI debug controller is active, special care must be | ||
1008 | * taken before and after a host controller reset */ | ||
1009 | if (fusbh200->debug && !dbgp_reset_prep(fusbh200_to_hcd(fusbh200))) | ||
1010 | fusbh200->debug = NULL; | ||
1011 | |||
1012 | command |= CMD_RESET; | ||
1013 | dbg_cmd (fusbh200, "reset", command); | ||
1014 | fusbh200_writel(fusbh200, command, &fusbh200->regs->command); | ||
1015 | fusbh200->rh_state = FUSBH200_RH_HALTED; | ||
1016 | fusbh200->next_statechange = jiffies; | ||
1017 | retval = handshake (fusbh200, &fusbh200->regs->command, | ||
1018 | CMD_RESET, 0, 250 * 1000); | ||
1019 | |||
1020 | if (retval) | ||
1021 | return retval; | ||
1022 | |||
1023 | if (fusbh200->debug) | ||
1024 | dbgp_external_startup(fusbh200_to_hcd(fusbh200)); | ||
1025 | |||
1026 | fusbh200->port_c_suspend = fusbh200->suspended_ports = | ||
1027 | fusbh200->resuming_ports = 0; | ||
1028 | return retval; | ||
1029 | } | ||
1030 | |||
1031 | /* | ||
1032 | * Idle the controller (turn off the schedules). | ||
1033 | * Must be called with interrupts enabled and the lock not held. | ||
1034 | */ | ||
1035 | static void fusbh200_quiesce (struct fusbh200_hcd *fusbh200) | ||
1036 | { | ||
1037 | u32 temp; | ||
1038 | |||
1039 | if (fusbh200->rh_state != FUSBH200_RH_RUNNING) | ||
1040 | return; | ||
1041 | |||
1042 | /* wait for any schedule enables/disables to take effect */ | ||
1043 | temp = (fusbh200->command << 10) & (STS_ASS | STS_PSS); | ||
1044 | handshake(fusbh200, &fusbh200->regs->status, STS_ASS | STS_PSS, temp, 16 * 125); | ||
1045 | |||
1046 | /* then disable anything that's still active */ | ||
1047 | spin_lock_irq(&fusbh200->lock); | ||
1048 | fusbh200->command &= ~(CMD_ASE | CMD_PSE); | ||
1049 | fusbh200_writel(fusbh200, fusbh200->command, &fusbh200->regs->command); | ||
1050 | spin_unlock_irq(&fusbh200->lock); | ||
1051 | |||
1052 | /* hardware can take 16 microframes to turn off ... */ | ||
1053 | handshake(fusbh200, &fusbh200->regs->status, STS_ASS | STS_PSS, 0, 16 * 125); | ||
1054 | } | ||
1055 | |||
1056 | /*-------------------------------------------------------------------------*/ | ||
1057 | |||
1058 | static void end_unlink_async(struct fusbh200_hcd *fusbh200); | ||
1059 | static void unlink_empty_async(struct fusbh200_hcd *fusbh200); | ||
1060 | static void fusbh200_work(struct fusbh200_hcd *fusbh200); | ||
1061 | static void start_unlink_intr(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh); | ||
1062 | static void end_unlink_intr(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh); | ||
1063 | |||
1064 | /*-------------------------------------------------------------------------*/ | ||
1065 | |||
1066 | /* Set a bit in the USBCMD register */ | ||
1067 | static void fusbh200_set_command_bit(struct fusbh200_hcd *fusbh200, u32 bit) | ||
1068 | { | ||
1069 | fusbh200->command |= bit; | ||
1070 | fusbh200_writel(fusbh200, fusbh200->command, &fusbh200->regs->command); | ||
1071 | |||
1072 | /* unblock posted write */ | ||
1073 | fusbh200_readl(fusbh200, &fusbh200->regs->command); | ||
1074 | } | ||
1075 | |||
1076 | /* Clear a bit in the USBCMD register */ | ||
1077 | static void fusbh200_clear_command_bit(struct fusbh200_hcd *fusbh200, u32 bit) | ||
1078 | { | ||
1079 | fusbh200->command &= ~bit; | ||
1080 | fusbh200_writel(fusbh200, fusbh200->command, &fusbh200->regs->command); | ||
1081 | |||
1082 | /* unblock posted write */ | ||
1083 | fusbh200_readl(fusbh200, &fusbh200->regs->command); | ||
1084 | } | ||
1085 | |||
1086 | /*-------------------------------------------------------------------------*/ | ||
1087 | |||
1088 | /* | ||
1089 | * EHCI timer support... Now using hrtimers. | ||
1090 | * | ||
1091 | * Lots of different events are triggered from fusbh200->hrtimer. Whenever | ||
1092 | * the timer routine runs, it checks each possible event; events that are | ||
1093 | * currently enabled and whose expiration time has passed get handled. | ||
1094 | * The set of enabled events is stored as a collection of bitflags in | ||
1095 | * fusbh200->enabled_hrtimer_events, and they are numbered in order of | ||
1096 | * increasing delay values (ranging between 1 ms and 100 ms). | ||
1097 | * | ||
1098 | * Rather than implementing a sorted list or tree of all pending events, | ||
1099 | * we keep track only of the lowest-numbered pending event, in | ||
1100 | * fusbh200->next_hrtimer_event. Whenever fusbh200->hrtimer gets restarted, its | ||
1101 | * expiration time is set to the timeout value for this event. | ||
1102 | * | ||
1103 | * As a result, events might not get handled right away; the actual delay | ||
1104 | * could be anywhere up to twice the requested delay. This doesn't | ||
1105 | * matter, because none of the events are especially time-critical. The | ||
1106 | * ones that matter most all have a delay of 1 ms, so they will be | ||
1107 | * handled after 2 ms at most, which is okay. In addition to this, we | ||
1108 | * allow for an expiration range of 1 ms. | ||
1109 | */ | ||
1110 | |||
1111 | /* | ||
1112 | * Delay lengths for the hrtimer event types. | ||
1113 | * Keep this list sorted by delay length, in the same order as | ||
1114 | * the event types indexed by enum fusbh200_hrtimer_event in fusbh200.h. | ||
1115 | */ | ||
1116 | static unsigned event_delays_ns[] = { | ||
1117 | 1 * NSEC_PER_MSEC, /* FUSBH200_HRTIMER_POLL_ASS */ | ||
1118 | 1 * NSEC_PER_MSEC, /* FUSBH200_HRTIMER_POLL_PSS */ | ||
1119 | 1 * NSEC_PER_MSEC, /* FUSBH200_HRTIMER_POLL_DEAD */ | ||
1120 | 1125 * NSEC_PER_USEC, /* FUSBH200_HRTIMER_UNLINK_INTR */ | ||
1121 | 2 * NSEC_PER_MSEC, /* FUSBH200_HRTIMER_FREE_ITDS */ | ||
1122 | 6 * NSEC_PER_MSEC, /* FUSBH200_HRTIMER_ASYNC_UNLINKS */ | ||
1123 | 10 * NSEC_PER_MSEC, /* FUSBH200_HRTIMER_IAA_WATCHDOG */ | ||
1124 | 10 * NSEC_PER_MSEC, /* FUSBH200_HRTIMER_DISABLE_PERIODIC */ | ||
1125 | 15 * NSEC_PER_MSEC, /* FUSBH200_HRTIMER_DISABLE_ASYNC */ | ||
1126 | 100 * NSEC_PER_MSEC, /* FUSBH200_HRTIMER_IO_WATCHDOG */ | ||
1127 | }; | ||
1128 | |||
1129 | /* Enable a pending hrtimer event */ | ||
1130 | static void fusbh200_enable_event(struct fusbh200_hcd *fusbh200, unsigned event, | ||
1131 | bool resched) | ||
1132 | { | ||
1133 | ktime_t *timeout = &fusbh200->hr_timeouts[event]; | ||
1134 | |||
1135 | if (resched) | ||
1136 | *timeout = ktime_add(ktime_get(), | ||
1137 | ktime_set(0, event_delays_ns[event])); | ||
1138 | fusbh200->enabled_hrtimer_events |= (1 << event); | ||
1139 | |||
1140 | /* Track only the lowest-numbered pending event */ | ||
1141 | if (event < fusbh200->next_hrtimer_event) { | ||
1142 | fusbh200->next_hrtimer_event = event; | ||
1143 | hrtimer_start_range_ns(&fusbh200->hrtimer, *timeout, | ||
1144 | NSEC_PER_MSEC, HRTIMER_MODE_ABS); | ||
1145 | } | ||
1146 | } | ||
1147 | |||
1148 | |||
1149 | /* Poll the STS_ASS status bit; see when it agrees with CMD_ASE */ | ||
1150 | static void fusbh200_poll_ASS(struct fusbh200_hcd *fusbh200) | ||
1151 | { | ||
1152 | unsigned actual, want; | ||
1153 | |||
1154 | /* Don't enable anything if the controller isn't running (e.g., died) */ | ||
1155 | if (fusbh200->rh_state != FUSBH200_RH_RUNNING) | ||
1156 | return; | ||
1157 | |||
1158 | want = (fusbh200->command & CMD_ASE) ? STS_ASS : 0; | ||
1159 | actual = fusbh200_readl(fusbh200, &fusbh200->regs->status) & STS_ASS; | ||
1160 | |||
1161 | if (want != actual) { | ||
1162 | |||
1163 | /* Poll again later, but give up after about 20 ms */ | ||
1164 | if (fusbh200->ASS_poll_count++ < 20) { | ||
1165 | fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_POLL_ASS, true); | ||
1166 | return; | ||
1167 | } | ||
1168 | fusbh200_dbg(fusbh200, "Waited too long for the async schedule status (%x/%x), giving up\n", | ||
1169 | want, actual); | ||
1170 | } | ||
1171 | fusbh200->ASS_poll_count = 0; | ||
1172 | |||
1173 | /* The status is up-to-date; restart or stop the schedule as needed */ | ||
1174 | if (want == 0) { /* Stopped */ | ||
1175 | if (fusbh200->async_count > 0) | ||
1176 | fusbh200_set_command_bit(fusbh200, CMD_ASE); | ||
1177 | |||
1178 | } else { /* Running */ | ||
1179 | if (fusbh200->async_count == 0) { | ||
1180 | |||
1181 | /* Turn off the schedule after a while */ | ||
1182 | fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_DISABLE_ASYNC, | ||
1183 | true); | ||
1184 | } | ||
1185 | } | ||
1186 | } | ||
1187 | |||
1188 | /* Turn off the async schedule after a brief delay */ | ||
1189 | static void fusbh200_disable_ASE(struct fusbh200_hcd *fusbh200) | ||
1190 | { | ||
1191 | fusbh200_clear_command_bit(fusbh200, CMD_ASE); | ||
1192 | } | ||
1193 | |||
1194 | |||
1195 | /* Poll the STS_PSS status bit; see when it agrees with CMD_PSE */ | ||
1196 | static void fusbh200_poll_PSS(struct fusbh200_hcd *fusbh200) | ||
1197 | { | ||
1198 | unsigned actual, want; | ||
1199 | |||
1200 | /* Don't do anything if the controller isn't running (e.g., died) */ | ||
1201 | if (fusbh200->rh_state != FUSBH200_RH_RUNNING) | ||
1202 | return; | ||
1203 | |||
1204 | want = (fusbh200->command & CMD_PSE) ? STS_PSS : 0; | ||
1205 | actual = fusbh200_readl(fusbh200, &fusbh200->regs->status) & STS_PSS; | ||
1206 | |||
1207 | if (want != actual) { | ||
1208 | |||
1209 | /* Poll again later, but give up after about 20 ms */ | ||
1210 | if (fusbh200->PSS_poll_count++ < 20) { | ||
1211 | fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_POLL_PSS, true); | ||
1212 | return; | ||
1213 | } | ||
1214 | fusbh200_dbg(fusbh200, "Waited too long for the periodic schedule status (%x/%x), giving up\n", | ||
1215 | want, actual); | ||
1216 | } | ||
1217 | fusbh200->PSS_poll_count = 0; | ||
1218 | |||
1219 | /* The status is up-to-date; restart or stop the schedule as needed */ | ||
1220 | if (want == 0) { /* Stopped */ | ||
1221 | if (fusbh200->periodic_count > 0) | ||
1222 | fusbh200_set_command_bit(fusbh200, CMD_PSE); | ||
1223 | |||
1224 | } else { /* Running */ | ||
1225 | if (fusbh200->periodic_count == 0) { | ||
1226 | |||
1227 | /* Turn off the schedule after a while */ | ||
1228 | fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_DISABLE_PERIODIC, | ||
1229 | true); | ||
1230 | } | ||
1231 | } | ||
1232 | } | ||
1233 | |||
1234 | /* Turn off the periodic schedule after a brief delay */ | ||
1235 | static void fusbh200_disable_PSE(struct fusbh200_hcd *fusbh200) | ||
1236 | { | ||
1237 | fusbh200_clear_command_bit(fusbh200, CMD_PSE); | ||
1238 | } | ||
1239 | |||
1240 | |||
1241 | /* Poll the STS_HALT status bit; see when a dead controller stops */ | ||
1242 | static void fusbh200_handle_controller_death(struct fusbh200_hcd *fusbh200) | ||
1243 | { | ||
1244 | if (!(fusbh200_readl(fusbh200, &fusbh200->regs->status) & STS_HALT)) { | ||
1245 | |||
1246 | /* Give up after a few milliseconds */ | ||
1247 | if (fusbh200->died_poll_count++ < 5) { | ||
1248 | /* Try again later */ | ||
1249 | fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_POLL_DEAD, true); | ||
1250 | return; | ||
1251 | } | ||
1252 | fusbh200_warn(fusbh200, "Waited too long for the controller to stop, giving up\n"); | ||
1253 | } | ||
1254 | |||
1255 | /* Clean up the mess */ | ||
1256 | fusbh200->rh_state = FUSBH200_RH_HALTED; | ||
1257 | fusbh200_writel(fusbh200, 0, &fusbh200->regs->intr_enable); | ||
1258 | fusbh200_work(fusbh200); | ||
1259 | end_unlink_async(fusbh200); | ||
1260 | |||
1261 | /* Not in process context, so don't try to reset the controller */ | ||
1262 | } | ||
1263 | |||
1264 | |||
1265 | /* Handle unlinked interrupt QHs once they are gone from the hardware */ | ||
1266 | static void fusbh200_handle_intr_unlinks(struct fusbh200_hcd *fusbh200) | ||
1267 | { | ||
1268 | bool stopped = (fusbh200->rh_state < FUSBH200_RH_RUNNING); | ||
1269 | |||
1270 | /* | ||
1271 | * Process all the QHs on the intr_unlink list that were added | ||
1272 | * before the current unlink cycle began. The list is in | ||
1273 | * temporal order, so stop when we reach the first entry in the | ||
1274 | * current cycle. But if the root hub isn't running then | ||
1275 | * process all the QHs on the list. | ||
1276 | */ | ||
1277 | fusbh200->intr_unlinking = true; | ||
1278 | while (fusbh200->intr_unlink) { | ||
1279 | struct fusbh200_qh *qh = fusbh200->intr_unlink; | ||
1280 | |||
1281 | if (!stopped && qh->unlink_cycle == fusbh200->intr_unlink_cycle) | ||
1282 | break; | ||
1283 | fusbh200->intr_unlink = qh->unlink_next; | ||
1284 | qh->unlink_next = NULL; | ||
1285 | end_unlink_intr(fusbh200, qh); | ||
1286 | } | ||
1287 | |||
1288 | /* Handle remaining entries later */ | ||
1289 | if (fusbh200->intr_unlink) { | ||
1290 | fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_UNLINK_INTR, true); | ||
1291 | ++fusbh200->intr_unlink_cycle; | ||
1292 | } | ||
1293 | fusbh200->intr_unlinking = false; | ||
1294 | } | ||
1295 | |||
1296 | |||
1297 | /* Start another free-iTDs/siTDs cycle */ | ||
1298 | static void start_free_itds(struct fusbh200_hcd *fusbh200) | ||
1299 | { | ||
1300 | if (!(fusbh200->enabled_hrtimer_events & BIT(FUSBH200_HRTIMER_FREE_ITDS))) { | ||
1301 | fusbh200->last_itd_to_free = list_entry( | ||
1302 | fusbh200->cached_itd_list.prev, | ||
1303 | struct fusbh200_itd, itd_list); | ||
1304 | fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_FREE_ITDS, true); | ||
1305 | } | ||
1306 | } | ||
1307 | |||
1308 | /* Wait for controller to stop using old iTDs and siTDs */ | ||
1309 | static void end_free_itds(struct fusbh200_hcd *fusbh200) | ||
1310 | { | ||
1311 | struct fusbh200_itd *itd, *n; | ||
1312 | |||
1313 | if (fusbh200->rh_state < FUSBH200_RH_RUNNING) { | ||
1314 | fusbh200->last_itd_to_free = NULL; | ||
1315 | } | ||
1316 | |||
1317 | list_for_each_entry_safe(itd, n, &fusbh200->cached_itd_list, itd_list) { | ||
1318 | list_del(&itd->itd_list); | ||
1319 | dma_pool_free(fusbh200->itd_pool, itd, itd->itd_dma); | ||
1320 | if (itd == fusbh200->last_itd_to_free) | ||
1321 | break; | ||
1322 | } | ||
1323 | |||
1324 | if (!list_empty(&fusbh200->cached_itd_list)) | ||
1325 | start_free_itds(fusbh200); | ||
1326 | } | ||
1327 | |||
1328 | |||
1329 | /* Handle lost (or very late) IAA interrupts */ | ||
1330 | static void fusbh200_iaa_watchdog(struct fusbh200_hcd *fusbh200) | ||
1331 | { | ||
1332 | if (fusbh200->rh_state != FUSBH200_RH_RUNNING) | ||
1333 | return; | ||
1334 | |||
1335 | /* | ||
1336 | * Lost IAA irqs wedge things badly; seen first with a vt8235. | ||
1337 | * So we need this watchdog, but must protect it against both | ||
1338 | * (a) SMP races against real IAA firing and retriggering, and | ||
1339 | * (b) clean HC shutdown, when IAA watchdog was pending. | ||
1340 | */ | ||
1341 | if (fusbh200->async_iaa) { | ||
1342 | u32 cmd, status; | ||
1343 | |||
1344 | /* If we get here, IAA is *REALLY* late. It's barely | ||
1345 | * conceivable that the system is so busy that CMD_IAAD | ||
1346 | * is still legitimately set, so let's be sure it's | ||
1347 | * clear before we read STS_IAA. (The HC should clear | ||
1348 | * CMD_IAAD when it sets STS_IAA.) | ||
1349 | */ | ||
1350 | cmd = fusbh200_readl(fusbh200, &fusbh200->regs->command); | ||
1351 | |||
1352 | /* | ||
1353 | * If IAA is set here it either legitimately triggered | ||
1354 | * after the watchdog timer expired (_way_ late, so we'll | ||
1355 | * still count it as lost) ... or a silicon erratum: | ||
1356 | * - VIA seems to set IAA without triggering the IRQ; | ||
1357 | * - IAAD potentially cleared without setting IAA. | ||
1358 | */ | ||
1359 | status = fusbh200_readl(fusbh200, &fusbh200->regs->status); | ||
1360 | if ((status & STS_IAA) || !(cmd & CMD_IAAD)) { | ||
1361 | COUNT(fusbh200->stats.lost_iaa); | ||
1362 | fusbh200_writel(fusbh200, STS_IAA, &fusbh200->regs->status); | ||
1363 | } | ||
1364 | |||
1365 | fusbh200_vdbg(fusbh200, "IAA watchdog: status %x cmd %x\n", | ||
1366 | status, cmd); | ||
1367 | end_unlink_async(fusbh200); | ||
1368 | } | ||
1369 | } | ||
1370 | |||
1371 | |||
1372 | /* Enable the I/O watchdog, if appropriate */ | ||
1373 | static void turn_on_io_watchdog(struct fusbh200_hcd *fusbh200) | ||
1374 | { | ||
1375 | /* Not needed if the controller isn't running or it's already enabled */ | ||
1376 | if (fusbh200->rh_state != FUSBH200_RH_RUNNING || | ||
1377 | (fusbh200->enabled_hrtimer_events & | ||
1378 | BIT(FUSBH200_HRTIMER_IO_WATCHDOG))) | ||
1379 | return; | ||
1380 | |||
1381 | /* | ||
1382 | * Isochronous transfers always need the watchdog. | ||
1383 | * For other sorts we use it only if the flag is set. | ||
1384 | */ | ||
1385 | if (fusbh200->isoc_count > 0 || (fusbh200->need_io_watchdog && | ||
1386 | fusbh200->async_count + fusbh200->intr_count > 0)) | ||
1387 | fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_IO_WATCHDOG, true); | ||
1388 | } | ||
1389 | |||
1390 | |||
1391 | /* | ||
1392 | * Handler functions for the hrtimer event types. | ||
1393 | * Keep this array in the same order as the event types indexed by | ||
1394 | * enum fusbh200_hrtimer_event in fusbh200.h. | ||
1395 | */ | ||
1396 | static void (*event_handlers[])(struct fusbh200_hcd *) = { | ||
1397 | fusbh200_poll_ASS, /* FUSBH200_HRTIMER_POLL_ASS */ | ||
1398 | fusbh200_poll_PSS, /* FUSBH200_HRTIMER_POLL_PSS */ | ||
1399 | fusbh200_handle_controller_death, /* FUSBH200_HRTIMER_POLL_DEAD */ | ||
1400 | fusbh200_handle_intr_unlinks, /* FUSBH200_HRTIMER_UNLINK_INTR */ | ||
1401 | end_free_itds, /* FUSBH200_HRTIMER_FREE_ITDS */ | ||
1402 | unlink_empty_async, /* FUSBH200_HRTIMER_ASYNC_UNLINKS */ | ||
1403 | fusbh200_iaa_watchdog, /* FUSBH200_HRTIMER_IAA_WATCHDOG */ | ||
1404 | fusbh200_disable_PSE, /* FUSBH200_HRTIMER_DISABLE_PERIODIC */ | ||
1405 | fusbh200_disable_ASE, /* FUSBH200_HRTIMER_DISABLE_ASYNC */ | ||
1406 | fusbh200_work, /* FUSBH200_HRTIMER_IO_WATCHDOG */ | ||
1407 | }; | ||
1408 | |||
1409 | static enum hrtimer_restart fusbh200_hrtimer_func(struct hrtimer *t) | ||
1410 | { | ||
1411 | struct fusbh200_hcd *fusbh200 = container_of(t, struct fusbh200_hcd, hrtimer); | ||
1412 | ktime_t now; | ||
1413 | unsigned long events; | ||
1414 | unsigned long flags; | ||
1415 | unsigned e; | ||
1416 | |||
1417 | spin_lock_irqsave(&fusbh200->lock, flags); | ||
1418 | |||
1419 | events = fusbh200->enabled_hrtimer_events; | ||
1420 | fusbh200->enabled_hrtimer_events = 0; | ||
1421 | fusbh200->next_hrtimer_event = FUSBH200_HRTIMER_NO_EVENT; | ||
1422 | |||
1423 | /* | ||
1424 | * Check each pending event. If its time has expired, handle | ||
1425 | * the event; otherwise re-enable it. | ||
1426 | */ | ||
1427 | now = ktime_get(); | ||
1428 | for_each_set_bit(e, &events, FUSBH200_HRTIMER_NUM_EVENTS) { | ||
1429 | if (now.tv64 >= fusbh200->hr_timeouts[e].tv64) | ||
1430 | event_handlers[e](fusbh200); | ||
1431 | else | ||
1432 | fusbh200_enable_event(fusbh200, e, false); | ||
1433 | } | ||
1434 | |||
1435 | spin_unlock_irqrestore(&fusbh200->lock, flags); | ||
1436 | return HRTIMER_NORESTART; | ||
1437 | } | ||
1438 | |||
1439 | /*-------------------------------------------------------------------------*/ | ||
1440 | |||
1441 | #define fusbh200_bus_suspend NULL | ||
1442 | #define fusbh200_bus_resume NULL | ||
1443 | |||
1444 | /*-------------------------------------------------------------------------*/ | ||
1445 | |||
1446 | static int check_reset_complete ( | ||
1447 | struct fusbh200_hcd *fusbh200, | ||
1448 | int index, | ||
1449 | u32 __iomem *status_reg, | ||
1450 | int port_status | ||
1451 | ) { | ||
1452 | if (!(port_status & PORT_CONNECT)) | ||
1453 | return port_status; | ||
1454 | |||
1455 | /* if reset finished and it's still not enabled -- handoff */ | ||
1456 | if (!(port_status & PORT_PE)) { | ||
1457 | /* with integrated TT, there's nobody to hand it to! */ | ||
1458 | fusbh200_dbg (fusbh200, | ||
1459 | "Failed to enable port %d on root hub TT\n", | ||
1460 | index+1); | ||
1461 | return port_status; | ||
1462 | } else { | ||
1463 | fusbh200_dbg(fusbh200, "port %d reset complete, port enabled\n", | ||
1464 | index + 1); | ||
1465 | } | ||
1466 | |||
1467 | return port_status; | ||
1468 | } | ||
1469 | |||
1470 | /*-------------------------------------------------------------------------*/ | ||
1471 | |||
1472 | |||
1473 | /* build "status change" packet (one or two bytes) from HC registers */ | ||
1474 | |||
1475 | static int | ||
1476 | fusbh200_hub_status_data (struct usb_hcd *hcd, char *buf) | ||
1477 | { | ||
1478 | struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200 (hcd); | ||
1479 | u32 temp, status; | ||
1480 | u32 mask; | ||
1481 | int retval = 1; | ||
1482 | unsigned long flags; | ||
1483 | |||
1484 | /* init status to no-changes */ | ||
1485 | buf [0] = 0; | ||
1486 | |||
1487 | /* Inform the core about resumes-in-progress by returning | ||
1488 | * a non-zero value even if there are no status changes. | ||
1489 | */ | ||
1490 | status = fusbh200->resuming_ports; | ||
1491 | |||
1492 | mask = PORT_CSC | PORT_PEC; | ||
1493 | // PORT_RESUME from hardware ~= PORT_STAT_C_SUSPEND | ||
1494 | |||
1495 | /* no hub change reports (bit 0) for now (power, ...) */ | ||
1496 | |||
1497 | /* port N changes (bit N)? */ | ||
1498 | spin_lock_irqsave (&fusbh200->lock, flags); | ||
1499 | |||
1500 | temp = fusbh200_readl(fusbh200, &fusbh200->regs->port_status); | ||
1501 | |||
1502 | /* | ||
1503 | * Return status information even for ports with OWNER set. | ||
1504 | * Otherwise khubd wouldn't see the disconnect event when a | ||
1505 | * high-speed device is switched over to the companion | ||
1506 | * controller by the user. | ||
1507 | */ | ||
1508 | |||
1509 | if ((temp & mask) != 0 || test_bit(0, &fusbh200->port_c_suspend) | ||
1510 | || (fusbh200->reset_done[0] && time_after_eq( | ||
1511 | jiffies, fusbh200->reset_done[0]))) { | ||
1512 | buf [0] |= 1 << 1; | ||
1513 | status = STS_PCD; | ||
1514 | } | ||
1515 | /* FIXME autosuspend idle root hubs */ | ||
1516 | spin_unlock_irqrestore (&fusbh200->lock, flags); | ||
1517 | return status ? retval : 0; | ||
1518 | } | ||
1519 | |||
1520 | /*-------------------------------------------------------------------------*/ | ||
1521 | |||
1522 | static void | ||
1523 | fusbh200_hub_descriptor ( | ||
1524 | struct fusbh200_hcd *fusbh200, | ||
1525 | struct usb_hub_descriptor *desc | ||
1526 | ) { | ||
1527 | int ports = HCS_N_PORTS (fusbh200->hcs_params); | ||
1528 | u16 temp; | ||
1529 | |||
1530 | desc->bDescriptorType = 0x29; | ||
1531 | desc->bPwrOn2PwrGood = 10; /* fusbh200 1.0, 2.3.9 says 20ms max */ | ||
1532 | desc->bHubContrCurrent = 0; | ||
1533 | |||
1534 | desc->bNbrPorts = ports; | ||
1535 | temp = 1 + (ports / 8); | ||
1536 | desc->bDescLength = 7 + 2 * temp; | ||
1537 | |||
1538 | /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */ | ||
1539 | memset(&desc->u.hs.DeviceRemovable[0], 0, temp); | ||
1540 | memset(&desc->u.hs.DeviceRemovable[temp], 0xff, temp); | ||
1541 | |||
1542 | temp = 0x0008; /* per-port overcurrent reporting */ | ||
1543 | temp |= 0x0002; /* no power switching */ | ||
1544 | desc->wHubCharacteristics = cpu_to_le16(temp); | ||
1545 | } | ||
1546 | |||
1547 | /*-------------------------------------------------------------------------*/ | ||
1548 | |||
1549 | static int fusbh200_hub_control ( | ||
1550 | struct usb_hcd *hcd, | ||
1551 | u16 typeReq, | ||
1552 | u16 wValue, | ||
1553 | u16 wIndex, | ||
1554 | char *buf, | ||
1555 | u16 wLength | ||
1556 | ) { | ||
1557 | struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200 (hcd); | ||
1558 | int ports = HCS_N_PORTS (fusbh200->hcs_params); | ||
1559 | u32 __iomem *status_reg = &fusbh200->regs->port_status; | ||
1560 | u32 temp, temp1, status; | ||
1561 | unsigned long flags; | ||
1562 | int retval = 0; | ||
1563 | unsigned selector; | ||
1564 | |||
1565 | /* | ||
1566 | * FIXME: support SetPortFeatures USB_PORT_FEAT_INDICATOR. | ||
1567 | * HCS_INDICATOR may say we can change LEDs to off/amber/green. | ||
1568 | * (track current state ourselves) ... blink for diagnostics, | ||
1569 | * power, "this is the one", etc. EHCI spec supports this. | ||
1570 | */ | ||
1571 | |||
1572 | spin_lock_irqsave (&fusbh200->lock, flags); | ||
1573 | switch (typeReq) { | ||
1574 | case ClearHubFeature: | ||
1575 | switch (wValue) { | ||
1576 | case C_HUB_LOCAL_POWER: | ||
1577 | case C_HUB_OVER_CURRENT: | ||
1578 | /* no hub-wide feature/status flags */ | ||
1579 | break; | ||
1580 | default: | ||
1581 | goto error; | ||
1582 | } | ||
1583 | break; | ||
1584 | case ClearPortFeature: | ||
1585 | if (!wIndex || wIndex > ports) | ||
1586 | goto error; | ||
1587 | wIndex--; | ||
1588 | temp = fusbh200_readl(fusbh200, status_reg); | ||
1589 | temp &= ~PORT_RWC_BITS; | ||
1590 | |||
1591 | /* | ||
1592 | * Even if OWNER is set, so the port is owned by the | ||
1593 | * companion controller, khubd needs to be able to clear | ||
1594 | * the port-change status bits (especially | ||
1595 | * USB_PORT_STAT_C_CONNECTION). | ||
1596 | */ | ||
1597 | |||
1598 | switch (wValue) { | ||
1599 | case USB_PORT_FEAT_ENABLE: | ||
1600 | fusbh200_writel(fusbh200, temp & ~PORT_PE, status_reg); | ||
1601 | break; | ||
1602 | case USB_PORT_FEAT_C_ENABLE: | ||
1603 | fusbh200_writel(fusbh200, temp | PORT_PEC, status_reg); | ||
1604 | break; | ||
1605 | case USB_PORT_FEAT_SUSPEND: | ||
1606 | if (temp & PORT_RESET) | ||
1607 | goto error; | ||
1608 | if (!(temp & PORT_SUSPEND)) | ||
1609 | break; | ||
1610 | if ((temp & PORT_PE) == 0) | ||
1611 | goto error; | ||
1612 | |||
1613 | /* resume signaling for 20 msec */ | ||
1614 | fusbh200_writel(fusbh200, temp | PORT_RESUME, status_reg); | ||
1615 | fusbh200->reset_done[wIndex] = jiffies | ||
1616 | + msecs_to_jiffies(20); | ||
1617 | break; | ||
1618 | case USB_PORT_FEAT_C_SUSPEND: | ||
1619 | clear_bit(wIndex, &fusbh200->port_c_suspend); | ||
1620 | break; | ||
1621 | case USB_PORT_FEAT_C_CONNECTION: | ||
1622 | fusbh200_writel(fusbh200, temp | PORT_CSC, status_reg); | ||
1623 | break; | ||
1624 | case USB_PORT_FEAT_C_OVER_CURRENT: | ||
1625 | fusbh200_writel(fusbh200, temp | BMISR_OVC, &fusbh200->regs->bmisr); | ||
1626 | break; | ||
1627 | case USB_PORT_FEAT_C_RESET: | ||
1628 | /* GetPortStatus clears reset */ | ||
1629 | break; | ||
1630 | default: | ||
1631 | goto error; | ||
1632 | } | ||
1633 | fusbh200_readl(fusbh200, &fusbh200->regs->command); /* unblock posted write */ | ||
1634 | break; | ||
1635 | case GetHubDescriptor: | ||
1636 | fusbh200_hub_descriptor (fusbh200, (struct usb_hub_descriptor *) | ||
1637 | buf); | ||
1638 | break; | ||
1639 | case GetHubStatus: | ||
1640 | /* no hub-wide feature/status flags */ | ||
1641 | memset (buf, 0, 4); | ||
1642 | //cpu_to_le32s ((u32 *) buf); | ||
1643 | break; | ||
1644 | case GetPortStatus: | ||
1645 | if (!wIndex || wIndex > ports) | ||
1646 | goto error; | ||
1647 | wIndex--; | ||
1648 | status = 0; | ||
1649 | temp = fusbh200_readl(fusbh200, status_reg); | ||
1650 | |||
1651 | // wPortChange bits | ||
1652 | if (temp & PORT_CSC) | ||
1653 | status |= USB_PORT_STAT_C_CONNECTION << 16; | ||
1654 | if (temp & PORT_PEC) | ||
1655 | status |= USB_PORT_STAT_C_ENABLE << 16; | ||
1656 | |||
1657 | temp1 = fusbh200_readl(fusbh200, &fusbh200->regs->bmisr); | ||
1658 | if (temp1 & BMISR_OVC) | ||
1659 | status |= USB_PORT_STAT_C_OVERCURRENT << 16; | ||
1660 | |||
1661 | /* whoever resumes must GetPortStatus to complete it!! */ | ||
1662 | if (temp & PORT_RESUME) { | ||
1663 | |||
1664 | /* Remote Wakeup received? */ | ||
1665 | if (!fusbh200->reset_done[wIndex]) { | ||
1666 | /* resume signaling for 20 msec */ | ||
1667 | fusbh200->reset_done[wIndex] = jiffies | ||
1668 | + msecs_to_jiffies(20); | ||
1669 | /* check the port again */ | ||
1670 | mod_timer(&fusbh200_to_hcd(fusbh200)->rh_timer, | ||
1671 | fusbh200->reset_done[wIndex]); | ||
1672 | } | ||
1673 | |||
1674 | /* resume completed? */ | ||
1675 | else if (time_after_eq(jiffies, | ||
1676 | fusbh200->reset_done[wIndex])) { | ||
1677 | clear_bit(wIndex, &fusbh200->suspended_ports); | ||
1678 | set_bit(wIndex, &fusbh200->port_c_suspend); | ||
1679 | fusbh200->reset_done[wIndex] = 0; | ||
1680 | |||
1681 | /* stop resume signaling */ | ||
1682 | temp = fusbh200_readl(fusbh200, status_reg); | ||
1683 | fusbh200_writel(fusbh200, | ||
1684 | temp & ~(PORT_RWC_BITS | PORT_RESUME), | ||
1685 | status_reg); | ||
1686 | clear_bit(wIndex, &fusbh200->resuming_ports); | ||
1687 | retval = handshake(fusbh200, status_reg, | ||
1688 | PORT_RESUME, 0, 2000 /* 2msec */); | ||
1689 | if (retval != 0) { | ||
1690 | fusbh200_err(fusbh200, | ||
1691 | "port %d resume error %d\n", | ||
1692 | wIndex + 1, retval); | ||
1693 | goto error; | ||
1694 | } | ||
1695 | temp &= ~(PORT_SUSPEND|PORT_RESUME|(3<<10)); | ||
1696 | } | ||
1697 | } | ||
1698 | |||
1699 | /* whoever resets must GetPortStatus to complete it!! */ | ||
1700 | if ((temp & PORT_RESET) | ||
1701 | && time_after_eq(jiffies, | ||
1702 | fusbh200->reset_done[wIndex])) { | ||
1703 | status |= USB_PORT_STAT_C_RESET << 16; | ||
1704 | fusbh200->reset_done [wIndex] = 0; | ||
1705 | clear_bit(wIndex, &fusbh200->resuming_ports); | ||
1706 | |||
1707 | /* force reset to complete */ | ||
1708 | fusbh200_writel(fusbh200, temp & ~(PORT_RWC_BITS | PORT_RESET), | ||
1709 | status_reg); | ||
1710 | /* REVISIT: some hardware needs 550+ usec to clear | ||
1711 | * this bit; seems too long to spin routinely... | ||
1712 | */ | ||
1713 | retval = handshake(fusbh200, status_reg, | ||
1714 | PORT_RESET, 0, 1000); | ||
1715 | if (retval != 0) { | ||
1716 | fusbh200_err (fusbh200, "port %d reset error %d\n", | ||
1717 | wIndex + 1, retval); | ||
1718 | goto error; | ||
1719 | } | ||
1720 | |||
1721 | /* see what we found out */ | ||
1722 | temp = check_reset_complete (fusbh200, wIndex, status_reg, | ||
1723 | fusbh200_readl(fusbh200, status_reg)); | ||
1724 | } | ||
1725 | |||
1726 | if (!(temp & (PORT_RESUME|PORT_RESET))) { | ||
1727 | fusbh200->reset_done[wIndex] = 0; | ||
1728 | clear_bit(wIndex, &fusbh200->resuming_ports); | ||
1729 | } | ||
1730 | |||
1731 | /* transfer dedicated ports to the companion hc */ | ||
1732 | if ((temp & PORT_CONNECT) && | ||
1733 | test_bit(wIndex, &fusbh200->companion_ports)) { | ||
1734 | temp &= ~PORT_RWC_BITS; | ||
1735 | fusbh200_writel(fusbh200, temp, status_reg); | ||
1736 | fusbh200_dbg(fusbh200, "port %d --> companion\n", wIndex + 1); | ||
1737 | temp = fusbh200_readl(fusbh200, status_reg); | ||
1738 | } | ||
1739 | |||
1740 | /* | ||
1741 | * Even if OWNER is set, there's no harm letting khubd | ||
1742 | * see the wPortStatus values (they should all be 0 except | ||
1743 | * for PORT_POWER anyway). | ||
1744 | */ | ||
1745 | |||
1746 | if (temp & PORT_CONNECT) { | ||
1747 | status |= USB_PORT_STAT_CONNECTION; | ||
1748 | status |= fusbh200_port_speed(fusbh200, temp); | ||
1749 | } | ||
1750 | if (temp & PORT_PE) | ||
1751 | status |= USB_PORT_STAT_ENABLE; | ||
1752 | |||
1753 | /* maybe the port was unsuspended without our knowledge */ | ||
1754 | if (temp & (PORT_SUSPEND|PORT_RESUME)) { | ||
1755 | status |= USB_PORT_STAT_SUSPEND; | ||
1756 | } else if (test_bit(wIndex, &fusbh200->suspended_ports)) { | ||
1757 | clear_bit(wIndex, &fusbh200->suspended_ports); | ||
1758 | clear_bit(wIndex, &fusbh200->resuming_ports); | ||
1759 | fusbh200->reset_done[wIndex] = 0; | ||
1760 | if (temp & PORT_PE) | ||
1761 | set_bit(wIndex, &fusbh200->port_c_suspend); | ||
1762 | } | ||
1763 | |||
1764 | temp1 = fusbh200_readl(fusbh200, &fusbh200->regs->bmisr); | ||
1765 | if (temp1 & BMISR_OVC) | ||
1766 | status |= USB_PORT_STAT_OVERCURRENT; | ||
1767 | if (temp & PORT_RESET) | ||
1768 | status |= USB_PORT_STAT_RESET; | ||
1769 | if (test_bit(wIndex, &fusbh200->port_c_suspend)) | ||
1770 | status |= USB_PORT_STAT_C_SUSPEND << 16; | ||
1771 | |||
1772 | #ifndef VERBOSE_DEBUG | ||
1773 | if (status & ~0xffff) /* only if wPortChange is interesting */ | ||
1774 | #endif | ||
1775 | dbg_port (fusbh200, "GetStatus", wIndex + 1, temp); | ||
1776 | put_unaligned_le32(status, buf); | ||
1777 | break; | ||
1778 | case SetHubFeature: | ||
1779 | switch (wValue) { | ||
1780 | case C_HUB_LOCAL_POWER: | ||
1781 | case C_HUB_OVER_CURRENT: | ||
1782 | /* no hub-wide feature/status flags */ | ||
1783 | break; | ||
1784 | default: | ||
1785 | goto error; | ||
1786 | } | ||
1787 | break; | ||
1788 | case SetPortFeature: | ||
1789 | selector = wIndex >> 8; | ||
1790 | wIndex &= 0xff; | ||
1791 | |||
1792 | if (!wIndex || wIndex > ports) | ||
1793 | goto error; | ||
1794 | wIndex--; | ||
1795 | temp = fusbh200_readl(fusbh200, status_reg); | ||
1796 | temp &= ~PORT_RWC_BITS; | ||
1797 | switch (wValue) { | ||
1798 | case USB_PORT_FEAT_SUSPEND: | ||
1799 | if ((temp & PORT_PE) == 0 | ||
1800 | || (temp & PORT_RESET) != 0) | ||
1801 | goto error; | ||
1802 | |||
1803 | /* After above check the port must be connected. | ||
1804 | * Set appropriate bit thus could put phy into low power | ||
1805 | * mode if we have hostpc feature | ||
1806 | */ | ||
1807 | fusbh200_writel(fusbh200, temp | PORT_SUSPEND, status_reg); | ||
1808 | set_bit(wIndex, &fusbh200->suspended_ports); | ||
1809 | break; | ||
1810 | case USB_PORT_FEAT_RESET: | ||
1811 | if (temp & PORT_RESUME) | ||
1812 | goto error; | ||
1813 | /* line status bits may report this as low speed, | ||
1814 | * which can be fine if this root hub has a | ||
1815 | * transaction translator built in. | ||
1816 | */ | ||
1817 | fusbh200_vdbg (fusbh200, "port %d reset\n", wIndex + 1); | ||
1818 | temp |= PORT_RESET; | ||
1819 | temp &= ~PORT_PE; | ||
1820 | |||
1821 | /* | ||
1822 | * caller must wait, then call GetPortStatus | ||
1823 | * usb 2.0 spec says 50 ms resets on root | ||
1824 | */ | ||
1825 | fusbh200->reset_done [wIndex] = jiffies | ||
1826 | + msecs_to_jiffies (50); | ||
1827 | fusbh200_writel(fusbh200, temp, status_reg); | ||
1828 | break; | ||
1829 | |||
1830 | /* For downstream facing ports (these): one hub port is put | ||
1831 | * into test mode according to USB2 11.24.2.13, then the hub | ||
1832 | * must be reset (which for root hub now means rmmod+modprobe, | ||
1833 | * or else system reboot). See EHCI 2.3.9 and 4.14 for info | ||
1834 | * about the EHCI-specific stuff. | ||
1835 | */ | ||
1836 | case USB_PORT_FEAT_TEST: | ||
1837 | if (!selector || selector > 5) | ||
1838 | goto error; | ||
1839 | spin_unlock_irqrestore(&fusbh200->lock, flags); | ||
1840 | fusbh200_quiesce(fusbh200); | ||
1841 | spin_lock_irqsave(&fusbh200->lock, flags); | ||
1842 | |||
1843 | /* Put all enabled ports into suspend */ | ||
1844 | temp = fusbh200_readl(fusbh200, status_reg) & ~PORT_RWC_BITS; | ||
1845 | if (temp & PORT_PE) | ||
1846 | fusbh200_writel(fusbh200, temp | PORT_SUSPEND, | ||
1847 | status_reg); | ||
1848 | |||
1849 | spin_unlock_irqrestore(&fusbh200->lock, flags); | ||
1850 | fusbh200_halt(fusbh200); | ||
1851 | spin_lock_irqsave(&fusbh200->lock, flags); | ||
1852 | |||
1853 | temp = fusbh200_readl(fusbh200, status_reg); | ||
1854 | temp |= selector << 16; | ||
1855 | fusbh200_writel(fusbh200, temp, status_reg); | ||
1856 | break; | ||
1857 | |||
1858 | default: | ||
1859 | goto error; | ||
1860 | } | ||
1861 | fusbh200_readl(fusbh200, &fusbh200->regs->command); /* unblock posted writes */ | ||
1862 | break; | ||
1863 | |||
1864 | default: | ||
1865 | error: | ||
1866 | /* "stall" on error */ | ||
1867 | retval = -EPIPE; | ||
1868 | } | ||
1869 | spin_unlock_irqrestore (&fusbh200->lock, flags); | ||
1870 | return retval; | ||
1871 | } | ||
1872 | |||
1873 | static void __maybe_unused fusbh200_relinquish_port(struct usb_hcd *hcd, | ||
1874 | int portnum) | ||
1875 | { | ||
1876 | return; | ||
1877 | } | ||
1878 | |||
1879 | static int __maybe_unused fusbh200_port_handed_over(struct usb_hcd *hcd, | ||
1880 | int portnum) | ||
1881 | { | ||
1882 | return 0; | ||
1883 | } | ||
1884 | /*-------------------------------------------------------------------------*/ | ||
1885 | /* | ||
1886 | * There's basically three types of memory: | ||
1887 | * - data used only by the HCD ... kmalloc is fine | ||
1888 | * - async and periodic schedules, shared by HC and HCD ... these | ||
1889 | * need to use dma_pool or dma_alloc_coherent | ||
1890 | * - driver buffers, read/written by HC ... single shot DMA mapped | ||
1891 | * | ||
1892 | * There's also "register" data (e.g. PCI or SOC), which is memory mapped. | ||
1893 | * No memory seen by this driver is pageable. | ||
1894 | */ | ||
1895 | |||
1896 | /*-------------------------------------------------------------------------*/ | ||
1897 | |||
1898 | /* Allocate the key transfer structures from the previously allocated pool */ | ||
1899 | |||
1900 | static inline void fusbh200_qtd_init(struct fusbh200_hcd *fusbh200, struct fusbh200_qtd *qtd, | ||
1901 | dma_addr_t dma) | ||
1902 | { | ||
1903 | memset (qtd, 0, sizeof *qtd); | ||
1904 | qtd->qtd_dma = dma; | ||
1905 | qtd->hw_token = cpu_to_hc32(fusbh200, QTD_STS_HALT); | ||
1906 | qtd->hw_next = FUSBH200_LIST_END(fusbh200); | ||
1907 | qtd->hw_alt_next = FUSBH200_LIST_END(fusbh200); | ||
1908 | INIT_LIST_HEAD (&qtd->qtd_list); | ||
1909 | } | ||
1910 | |||
1911 | static struct fusbh200_qtd *fusbh200_qtd_alloc (struct fusbh200_hcd *fusbh200, gfp_t flags) | ||
1912 | { | ||
1913 | struct fusbh200_qtd *qtd; | ||
1914 | dma_addr_t dma; | ||
1915 | |||
1916 | qtd = dma_pool_alloc (fusbh200->qtd_pool, flags, &dma); | ||
1917 | if (qtd != NULL) { | ||
1918 | fusbh200_qtd_init(fusbh200, qtd, dma); | ||
1919 | } | ||
1920 | return qtd; | ||
1921 | } | ||
1922 | |||
1923 | static inline void fusbh200_qtd_free (struct fusbh200_hcd *fusbh200, struct fusbh200_qtd *qtd) | ||
1924 | { | ||
1925 | dma_pool_free (fusbh200->qtd_pool, qtd, qtd->qtd_dma); | ||
1926 | } | ||
1927 | |||
1928 | |||
1929 | static void qh_destroy(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh) | ||
1930 | { | ||
1931 | /* clean qtds first, and know this is not linked */ | ||
1932 | if (!list_empty (&qh->qtd_list) || qh->qh_next.ptr) { | ||
1933 | fusbh200_dbg (fusbh200, "unused qh not empty!\n"); | ||
1934 | BUG (); | ||
1935 | } | ||
1936 | if (qh->dummy) | ||
1937 | fusbh200_qtd_free (fusbh200, qh->dummy); | ||
1938 | dma_pool_free(fusbh200->qh_pool, qh->hw, qh->qh_dma); | ||
1939 | kfree(qh); | ||
1940 | } | ||
1941 | |||
1942 | static struct fusbh200_qh *fusbh200_qh_alloc (struct fusbh200_hcd *fusbh200, gfp_t flags) | ||
1943 | { | ||
1944 | struct fusbh200_qh *qh; | ||
1945 | dma_addr_t dma; | ||
1946 | |||
1947 | qh = kzalloc(sizeof *qh, GFP_ATOMIC); | ||
1948 | if (!qh) | ||
1949 | goto done; | ||
1950 | qh->hw = (struct fusbh200_qh_hw *) | ||
1951 | dma_pool_alloc(fusbh200->qh_pool, flags, &dma); | ||
1952 | if (!qh->hw) | ||
1953 | goto fail; | ||
1954 | memset(qh->hw, 0, sizeof *qh->hw); | ||
1955 | qh->qh_dma = dma; | ||
1956 | // INIT_LIST_HEAD (&qh->qh_list); | ||
1957 | INIT_LIST_HEAD (&qh->qtd_list); | ||
1958 | |||
1959 | /* dummy td enables safe urb queuing */ | ||
1960 | qh->dummy = fusbh200_qtd_alloc (fusbh200, flags); | ||
1961 | if (qh->dummy == NULL) { | ||
1962 | fusbh200_dbg (fusbh200, "no dummy td\n"); | ||
1963 | goto fail1; | ||
1964 | } | ||
1965 | done: | ||
1966 | return qh; | ||
1967 | fail1: | ||
1968 | dma_pool_free(fusbh200->qh_pool, qh->hw, qh->qh_dma); | ||
1969 | fail: | ||
1970 | kfree(qh); | ||
1971 | return NULL; | ||
1972 | } | ||
1973 | |||
1974 | /*-------------------------------------------------------------------------*/ | ||
1975 | |||
1976 | /* The queue heads and transfer descriptors are managed from pools tied | ||
1977 | * to each of the "per device" structures. | ||
1978 | * This is the initialisation and cleanup code. | ||
1979 | */ | ||
1980 | |||
1981 | static void fusbh200_mem_cleanup (struct fusbh200_hcd *fusbh200) | ||
1982 | { | ||
1983 | if (fusbh200->async) | ||
1984 | qh_destroy(fusbh200, fusbh200->async); | ||
1985 | fusbh200->async = NULL; | ||
1986 | |||
1987 | if (fusbh200->dummy) | ||
1988 | qh_destroy(fusbh200, fusbh200->dummy); | ||
1989 | fusbh200->dummy = NULL; | ||
1990 | |||
1991 | /* DMA consistent memory and pools */ | ||
1992 | if (fusbh200->qtd_pool) | ||
1993 | dma_pool_destroy (fusbh200->qtd_pool); | ||
1994 | fusbh200->qtd_pool = NULL; | ||
1995 | |||
1996 | if (fusbh200->qh_pool) { | ||
1997 | dma_pool_destroy (fusbh200->qh_pool); | ||
1998 | fusbh200->qh_pool = NULL; | ||
1999 | } | ||
2000 | |||
2001 | if (fusbh200->itd_pool) | ||
2002 | dma_pool_destroy (fusbh200->itd_pool); | ||
2003 | fusbh200->itd_pool = NULL; | ||
2004 | |||
2005 | if (fusbh200->periodic) | ||
2006 | dma_free_coherent (fusbh200_to_hcd(fusbh200)->self.controller, | ||
2007 | fusbh200->periodic_size * sizeof (u32), | ||
2008 | fusbh200->periodic, fusbh200->periodic_dma); | ||
2009 | fusbh200->periodic = NULL; | ||
2010 | |||
2011 | /* shadow periodic table */ | ||
2012 | kfree(fusbh200->pshadow); | ||
2013 | fusbh200->pshadow = NULL; | ||
2014 | } | ||
2015 | |||
2016 | /* remember to add cleanup code (above) if you add anything here */ | ||
2017 | static int fusbh200_mem_init (struct fusbh200_hcd *fusbh200, gfp_t flags) | ||
2018 | { | ||
2019 | int i; | ||
2020 | |||
2021 | /* QTDs for control/bulk/intr transfers */ | ||
2022 | fusbh200->qtd_pool = dma_pool_create ("fusbh200_qtd", | ||
2023 | fusbh200_to_hcd(fusbh200)->self.controller, | ||
2024 | sizeof (struct fusbh200_qtd), | ||
2025 | 32 /* byte alignment (for hw parts) */, | ||
2026 | 4096 /* can't cross 4K */); | ||
2027 | if (!fusbh200->qtd_pool) { | ||
2028 | goto fail; | ||
2029 | } | ||
2030 | |||
2031 | /* QHs for control/bulk/intr transfers */ | ||
2032 | fusbh200->qh_pool = dma_pool_create ("fusbh200_qh", | ||
2033 | fusbh200_to_hcd(fusbh200)->self.controller, | ||
2034 | sizeof(struct fusbh200_qh_hw), | ||
2035 | 32 /* byte alignment (for hw parts) */, | ||
2036 | 4096 /* can't cross 4K */); | ||
2037 | if (!fusbh200->qh_pool) { | ||
2038 | goto fail; | ||
2039 | } | ||
2040 | fusbh200->async = fusbh200_qh_alloc (fusbh200, flags); | ||
2041 | if (!fusbh200->async) { | ||
2042 | goto fail; | ||
2043 | } | ||
2044 | |||
2045 | /* ITD for high speed ISO transfers */ | ||
2046 | fusbh200->itd_pool = dma_pool_create ("fusbh200_itd", | ||
2047 | fusbh200_to_hcd(fusbh200)->self.controller, | ||
2048 | sizeof (struct fusbh200_itd), | ||
2049 | 64 /* byte alignment (for hw parts) */, | ||
2050 | 4096 /* can't cross 4K */); | ||
2051 | if (!fusbh200->itd_pool) { | ||
2052 | goto fail; | ||
2053 | } | ||
2054 | |||
2055 | /* Hardware periodic table */ | ||
2056 | fusbh200->periodic = (__le32 *) | ||
2057 | dma_alloc_coherent (fusbh200_to_hcd(fusbh200)->self.controller, | ||
2058 | fusbh200->periodic_size * sizeof(__le32), | ||
2059 | &fusbh200->periodic_dma, 0); | ||
2060 | if (fusbh200->periodic == NULL) { | ||
2061 | goto fail; | ||
2062 | } | ||
2063 | |||
2064 | for (i = 0; i < fusbh200->periodic_size; i++) | ||
2065 | fusbh200->periodic[i] = FUSBH200_LIST_END(fusbh200); | ||
2066 | |||
2067 | /* software shadow of hardware table */ | ||
2068 | fusbh200->pshadow = kcalloc(fusbh200->periodic_size, sizeof(void *), flags); | ||
2069 | if (fusbh200->pshadow != NULL) | ||
2070 | return 0; | ||
2071 | |||
2072 | fail: | ||
2073 | fusbh200_dbg (fusbh200, "couldn't init memory\n"); | ||
2074 | fusbh200_mem_cleanup (fusbh200); | ||
2075 | return -ENOMEM; | ||
2076 | } | ||
2077 | /*-------------------------------------------------------------------------*/ | ||
2078 | /* | ||
2079 | * EHCI hardware queue manipulation ... the core. QH/QTD manipulation. | ||
2080 | * | ||
2081 | * Control, bulk, and interrupt traffic all use "qh" lists. They list "qtd" | ||
2082 | * entries describing USB transactions, max 16-20kB/entry (with 4kB-aligned | ||
2083 | * buffers needed for the larger number). We use one QH per endpoint, queue | ||
2084 | * multiple urbs (all three types) per endpoint. URBs may need several qtds. | ||
2085 | * | ||
2086 | * ISO traffic uses "ISO TD" (itd) records, and (along with | ||
2087 | * interrupts) needs careful scheduling. Performance improvements can be | ||
2088 | * an ongoing challenge. That's in "ehci-sched.c". | ||
2089 | * | ||
2090 | * USB 1.1 devices are handled (a) by "companion" OHCI or UHCI root hubs, | ||
2091 | * or otherwise through transaction translators (TTs) in USB 2.0 hubs using | ||
2092 | * (b) special fields in qh entries or (c) split iso entries. TTs will | ||
2093 | * buffer low/full speed data so the host collects it at high speed. | ||
2094 | */ | ||
2095 | |||
2096 | /*-------------------------------------------------------------------------*/ | ||
2097 | |||
2098 | /* fill a qtd, returning how much of the buffer we were able to queue up */ | ||
2099 | |||
2100 | static int | ||
2101 | qtd_fill(struct fusbh200_hcd *fusbh200, struct fusbh200_qtd *qtd, dma_addr_t buf, | ||
2102 | size_t len, int token, int maxpacket) | ||
2103 | { | ||
2104 | int i, count; | ||
2105 | u64 addr = buf; | ||
2106 | |||
2107 | /* one buffer entry per 4K ... first might be short or unaligned */ | ||
2108 | qtd->hw_buf[0] = cpu_to_hc32(fusbh200, (u32)addr); | ||
2109 | qtd->hw_buf_hi[0] = cpu_to_hc32(fusbh200, (u32)(addr >> 32)); | ||
2110 | count = 0x1000 - (buf & 0x0fff); /* rest of that page */ | ||
2111 | if (likely (len < count)) /* ... iff needed */ | ||
2112 | count = len; | ||
2113 | else { | ||
2114 | buf += 0x1000; | ||
2115 | buf &= ~0x0fff; | ||
2116 | |||
2117 | /* per-qtd limit: from 16K to 20K (best alignment) */ | ||
2118 | for (i = 1; count < len && i < 5; i++) { | ||
2119 | addr = buf; | ||
2120 | qtd->hw_buf[i] = cpu_to_hc32(fusbh200, (u32)addr); | ||
2121 | qtd->hw_buf_hi[i] = cpu_to_hc32(fusbh200, | ||
2122 | (u32)(addr >> 32)); | ||
2123 | buf += 0x1000; | ||
2124 | if ((count + 0x1000) < len) | ||
2125 | count += 0x1000; | ||
2126 | else | ||
2127 | count = len; | ||
2128 | } | ||
2129 | |||
2130 | /* short packets may only terminate transfers */ | ||
2131 | if (count != len) | ||
2132 | count -= (count % maxpacket); | ||
2133 | } | ||
2134 | qtd->hw_token = cpu_to_hc32(fusbh200, (count << 16) | token); | ||
2135 | qtd->length = count; | ||
2136 | |||
2137 | return count; | ||
2138 | } | ||
2139 | |||
2140 | /*-------------------------------------------------------------------------*/ | ||
2141 | |||
2142 | static inline void | ||
2143 | qh_update (struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh, struct fusbh200_qtd *qtd) | ||
2144 | { | ||
2145 | struct fusbh200_qh_hw *hw = qh->hw; | ||
2146 | |||
2147 | /* writes to an active overlay are unsafe */ | ||
2148 | BUG_ON(qh->qh_state != QH_STATE_IDLE); | ||
2149 | |||
2150 | hw->hw_qtd_next = QTD_NEXT(fusbh200, qtd->qtd_dma); | ||
2151 | hw->hw_alt_next = FUSBH200_LIST_END(fusbh200); | ||
2152 | |||
2153 | /* Except for control endpoints, we make hardware maintain data | ||
2154 | * toggle (like OHCI) ... here (re)initialize the toggle in the QH, | ||
2155 | * and set the pseudo-toggle in udev. Only usb_clear_halt() will | ||
2156 | * ever clear it. | ||
2157 | */ | ||
2158 | if (!(hw->hw_info1 & cpu_to_hc32(fusbh200, QH_TOGGLE_CTL))) { | ||
2159 | unsigned is_out, epnum; | ||
2160 | |||
2161 | is_out = qh->is_out; | ||
2162 | epnum = (hc32_to_cpup(fusbh200, &hw->hw_info1) >> 8) & 0x0f; | ||
2163 | if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) { | ||
2164 | hw->hw_token &= ~cpu_to_hc32(fusbh200, QTD_TOGGLE); | ||
2165 | usb_settoggle (qh->dev, epnum, is_out, 1); | ||
2166 | } | ||
2167 | } | ||
2168 | |||
2169 | hw->hw_token &= cpu_to_hc32(fusbh200, QTD_TOGGLE | QTD_STS_PING); | ||
2170 | } | ||
2171 | |||
2172 | /* if it weren't for a common silicon quirk (writing the dummy into the qh | ||
2173 | * overlay, so qh->hw_token wrongly becomes inactive/halted), only fault | ||
2174 | * recovery (including urb dequeue) would need software changes to a QH... | ||
2175 | */ | ||
2176 | static void | ||
2177 | qh_refresh (struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh) | ||
2178 | { | ||
2179 | struct fusbh200_qtd *qtd; | ||
2180 | |||
2181 | if (list_empty (&qh->qtd_list)) | ||
2182 | qtd = qh->dummy; | ||
2183 | else { | ||
2184 | qtd = list_entry (qh->qtd_list.next, | ||
2185 | struct fusbh200_qtd, qtd_list); | ||
2186 | /* | ||
2187 | * first qtd may already be partially processed. | ||
2188 | * If we come here during unlink, the QH overlay region | ||
2189 | * might have reference to the just unlinked qtd. The | ||
2190 | * qtd is updated in qh_completions(). Update the QH | ||
2191 | * overlay here. | ||
2192 | */ | ||
2193 | if (cpu_to_hc32(fusbh200, qtd->qtd_dma) == qh->hw->hw_current) { | ||
2194 | qh->hw->hw_qtd_next = qtd->hw_next; | ||
2195 | qtd = NULL; | ||
2196 | } | ||
2197 | } | ||
2198 | |||
2199 | if (qtd) | ||
2200 | qh_update (fusbh200, qh, qtd); | ||
2201 | } | ||
2202 | |||
2203 | /*-------------------------------------------------------------------------*/ | ||
2204 | |||
2205 | static void qh_link_async(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh); | ||
2206 | |||
2207 | static void fusbh200_clear_tt_buffer_complete(struct usb_hcd *hcd, | ||
2208 | struct usb_host_endpoint *ep) | ||
2209 | { | ||
2210 | struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200(hcd); | ||
2211 | struct fusbh200_qh *qh = ep->hcpriv; | ||
2212 | unsigned long flags; | ||
2213 | |||
2214 | spin_lock_irqsave(&fusbh200->lock, flags); | ||
2215 | qh->clearing_tt = 0; | ||
2216 | if (qh->qh_state == QH_STATE_IDLE && !list_empty(&qh->qtd_list) | ||
2217 | && fusbh200->rh_state == FUSBH200_RH_RUNNING) | ||
2218 | qh_link_async(fusbh200, qh); | ||
2219 | spin_unlock_irqrestore(&fusbh200->lock, flags); | ||
2220 | } | ||
2221 | |||
2222 | static void fusbh200_clear_tt_buffer(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh, | ||
2223 | struct urb *urb, u32 token) | ||
2224 | { | ||
2225 | |||
2226 | /* If an async split transaction gets an error or is unlinked, | ||
2227 | * the TT buffer may be left in an indeterminate state. We | ||
2228 | * have to clear the TT buffer. | ||
2229 | * | ||
2230 | * Note: this routine is never called for Isochronous transfers. | ||
2231 | */ | ||
2232 | if (urb->dev->tt && !usb_pipeint(urb->pipe) && !qh->clearing_tt) { | ||
2233 | #ifdef DEBUG | ||
2234 | struct usb_device *tt = urb->dev->tt->hub; | ||
2235 | dev_dbg(&tt->dev, | ||
2236 | "clear tt buffer port %d, a%d ep%d t%08x\n", | ||
2237 | urb->dev->ttport, urb->dev->devnum, | ||
2238 | usb_pipeendpoint(urb->pipe), token); | ||
2239 | #endif /* DEBUG */ | ||
2240 | if (urb->dev->tt->hub != | ||
2241 | fusbh200_to_hcd(fusbh200)->self.root_hub) { | ||
2242 | if (usb_hub_clear_tt_buffer(urb) == 0) | ||
2243 | qh->clearing_tt = 1; | ||
2244 | } | ||
2245 | } | ||
2246 | } | ||
2247 | |||
2248 | static int qtd_copy_status ( | ||
2249 | struct fusbh200_hcd *fusbh200, | ||
2250 | struct urb *urb, | ||
2251 | size_t length, | ||
2252 | u32 token | ||
2253 | ) | ||
2254 | { | ||
2255 | int status = -EINPROGRESS; | ||
2256 | |||
2257 | /* count IN/OUT bytes, not SETUP (even short packets) */ | ||
2258 | if (likely (QTD_PID (token) != 2)) | ||
2259 | urb->actual_length += length - QTD_LENGTH (token); | ||
2260 | |||
2261 | /* don't modify error codes */ | ||
2262 | if (unlikely(urb->unlinked)) | ||
2263 | return status; | ||
2264 | |||
2265 | /* force cleanup after short read; not always an error */ | ||
2266 | if (unlikely (IS_SHORT_READ (token))) | ||
2267 | status = -EREMOTEIO; | ||
2268 | |||
2269 | /* serious "can't proceed" faults reported by the hardware */ | ||
2270 | if (token & QTD_STS_HALT) { | ||
2271 | if (token & QTD_STS_BABBLE) { | ||
2272 | /* FIXME "must" disable babbling device's port too */ | ||
2273 | status = -EOVERFLOW; | ||
2274 | /* CERR nonzero + halt --> stall */ | ||
2275 | } else if (QTD_CERR(token)) { | ||
2276 | status = -EPIPE; | ||
2277 | |||
2278 | /* In theory, more than one of the following bits can be set | ||
2279 | * since they are sticky and the transaction is retried. | ||
2280 | * Which to test first is rather arbitrary. | ||
2281 | */ | ||
2282 | } else if (token & QTD_STS_MMF) { | ||
2283 | /* fs/ls interrupt xfer missed the complete-split */ | ||
2284 | status = -EPROTO; | ||
2285 | } else if (token & QTD_STS_DBE) { | ||
2286 | status = (QTD_PID (token) == 1) /* IN ? */ | ||
2287 | ? -ENOSR /* hc couldn't read data */ | ||
2288 | : -ECOMM; /* hc couldn't write data */ | ||
2289 | } else if (token & QTD_STS_XACT) { | ||
2290 | /* timeout, bad CRC, wrong PID, etc */ | ||
2291 | fusbh200_dbg(fusbh200, "devpath %s ep%d%s 3strikes\n", | ||
2292 | urb->dev->devpath, | ||
2293 | usb_pipeendpoint(urb->pipe), | ||
2294 | usb_pipein(urb->pipe) ? "in" : "out"); | ||
2295 | status = -EPROTO; | ||
2296 | } else { /* unknown */ | ||
2297 | status = -EPROTO; | ||
2298 | } | ||
2299 | |||
2300 | fusbh200_vdbg (fusbh200, | ||
2301 | "dev%d ep%d%s qtd token %08x --> status %d\n", | ||
2302 | usb_pipedevice (urb->pipe), | ||
2303 | usb_pipeendpoint (urb->pipe), | ||
2304 | usb_pipein (urb->pipe) ? "in" : "out", | ||
2305 | token, status); | ||
2306 | } | ||
2307 | |||
2308 | return status; | ||
2309 | } | ||
2310 | |||
2311 | static void | ||
2312 | fusbh200_urb_done(struct fusbh200_hcd *fusbh200, struct urb *urb, int status) | ||
2313 | __releases(fusbh200->lock) | ||
2314 | __acquires(fusbh200->lock) | ||
2315 | { | ||
2316 | if (likely (urb->hcpriv != NULL)) { | ||
2317 | struct fusbh200_qh *qh = (struct fusbh200_qh *) urb->hcpriv; | ||
2318 | |||
2319 | /* S-mask in a QH means it's an interrupt urb */ | ||
2320 | if ((qh->hw->hw_info2 & cpu_to_hc32(fusbh200, QH_SMASK)) != 0) { | ||
2321 | |||
2322 | /* ... update hc-wide periodic stats (for usbfs) */ | ||
2323 | fusbh200_to_hcd(fusbh200)->self.bandwidth_int_reqs--; | ||
2324 | } | ||
2325 | } | ||
2326 | |||
2327 | if (unlikely(urb->unlinked)) { | ||
2328 | COUNT(fusbh200->stats.unlink); | ||
2329 | } else { | ||
2330 | /* report non-error and short read status as zero */ | ||
2331 | if (status == -EINPROGRESS || status == -EREMOTEIO) | ||
2332 | status = 0; | ||
2333 | COUNT(fusbh200->stats.complete); | ||
2334 | } | ||
2335 | |||
2336 | #ifdef FUSBH200_URB_TRACE | ||
2337 | fusbh200_dbg (fusbh200, | ||
2338 | "%s %s urb %p ep%d%s status %d len %d/%d\n", | ||
2339 | __func__, urb->dev->devpath, urb, | ||
2340 | usb_pipeendpoint (urb->pipe), | ||
2341 | usb_pipein (urb->pipe) ? "in" : "out", | ||
2342 | status, | ||
2343 | urb->actual_length, urb->transfer_buffer_length); | ||
2344 | #endif | ||
2345 | |||
2346 | /* complete() can reenter this HCD */ | ||
2347 | usb_hcd_unlink_urb_from_ep(fusbh200_to_hcd(fusbh200), urb); | ||
2348 | spin_unlock (&fusbh200->lock); | ||
2349 | usb_hcd_giveback_urb(fusbh200_to_hcd(fusbh200), urb, status); | ||
2350 | spin_lock (&fusbh200->lock); | ||
2351 | } | ||
2352 | |||
2353 | static int qh_schedule (struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh); | ||
2354 | |||
2355 | /* | ||
2356 | * Process and free completed qtds for a qh, returning URBs to drivers. | ||
2357 | * Chases up to qh->hw_current. Returns number of completions called, | ||
2358 | * indicating how much "real" work we did. | ||
2359 | */ | ||
2360 | static unsigned | ||
2361 | qh_completions (struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh) | ||
2362 | { | ||
2363 | struct fusbh200_qtd *last, *end = qh->dummy; | ||
2364 | struct list_head *entry, *tmp; | ||
2365 | int last_status; | ||
2366 | int stopped; | ||
2367 | unsigned count = 0; | ||
2368 | u8 state; | ||
2369 | struct fusbh200_qh_hw *hw = qh->hw; | ||
2370 | |||
2371 | if (unlikely (list_empty (&qh->qtd_list))) | ||
2372 | return count; | ||
2373 | |||
2374 | /* completions (or tasks on other cpus) must never clobber HALT | ||
2375 | * till we've gone through and cleaned everything up, even when | ||
2376 | * they add urbs to this qh's queue or mark them for unlinking. | ||
2377 | * | ||
2378 | * NOTE: unlinking expects to be done in queue order. | ||
2379 | * | ||
2380 | * It's a bug for qh->qh_state to be anything other than | ||
2381 | * QH_STATE_IDLE, unless our caller is scan_async() or | ||
2382 | * scan_intr(). | ||
2383 | */ | ||
2384 | state = qh->qh_state; | ||
2385 | qh->qh_state = QH_STATE_COMPLETING; | ||
2386 | stopped = (state == QH_STATE_IDLE); | ||
2387 | |||
2388 | rescan: | ||
2389 | last = NULL; | ||
2390 | last_status = -EINPROGRESS; | ||
2391 | qh->needs_rescan = 0; | ||
2392 | |||
2393 | /* remove de-activated QTDs from front of queue. | ||
2394 | * after faults (including short reads), cleanup this urb | ||
2395 | * then let the queue advance. | ||
2396 | * if queue is stopped, handles unlinks. | ||
2397 | */ | ||
2398 | list_for_each_safe (entry, tmp, &qh->qtd_list) { | ||
2399 | struct fusbh200_qtd *qtd; | ||
2400 | struct urb *urb; | ||
2401 | u32 token = 0; | ||
2402 | |||
2403 | qtd = list_entry (entry, struct fusbh200_qtd, qtd_list); | ||
2404 | urb = qtd->urb; | ||
2405 | |||
2406 | /* clean up any state from previous QTD ...*/ | ||
2407 | if (last) { | ||
2408 | if (likely (last->urb != urb)) { | ||
2409 | fusbh200_urb_done(fusbh200, last->urb, last_status); | ||
2410 | count++; | ||
2411 | last_status = -EINPROGRESS; | ||
2412 | } | ||
2413 | fusbh200_qtd_free (fusbh200, last); | ||
2414 | last = NULL; | ||
2415 | } | ||
2416 | |||
2417 | /* ignore urbs submitted during completions we reported */ | ||
2418 | if (qtd == end) | ||
2419 | break; | ||
2420 | |||
2421 | /* hardware copies qtd out of qh overlay */ | ||
2422 | rmb (); | ||
2423 | token = hc32_to_cpu(fusbh200, qtd->hw_token); | ||
2424 | |||
2425 | /* always clean up qtds the hc de-activated */ | ||
2426 | retry_xacterr: | ||
2427 | if ((token & QTD_STS_ACTIVE) == 0) { | ||
2428 | |||
2429 | /* Report Data Buffer Error: non-fatal but useful */ | ||
2430 | if (token & QTD_STS_DBE) | ||
2431 | fusbh200_dbg(fusbh200, | ||
2432 | "detected DataBufferErr for urb %p ep%d%s len %d, qtd %p [qh %p]\n", | ||
2433 | urb, | ||
2434 | usb_endpoint_num(&urb->ep->desc), | ||
2435 | usb_endpoint_dir_in(&urb->ep->desc) ? "in" : "out", | ||
2436 | urb->transfer_buffer_length, | ||
2437 | qtd, | ||
2438 | qh); | ||
2439 | |||
2440 | /* on STALL, error, and short reads this urb must | ||
2441 | * complete and all its qtds must be recycled. | ||
2442 | */ | ||
2443 | if ((token & QTD_STS_HALT) != 0) { | ||
2444 | |||
2445 | /* retry transaction errors until we | ||
2446 | * reach the software xacterr limit | ||
2447 | */ | ||
2448 | if ((token & QTD_STS_XACT) && | ||
2449 | QTD_CERR(token) == 0 && | ||
2450 | ++qh->xacterrs < QH_XACTERR_MAX && | ||
2451 | !urb->unlinked) { | ||
2452 | fusbh200_dbg(fusbh200, | ||
2453 | "detected XactErr len %zu/%zu retry %d\n", | ||
2454 | qtd->length - QTD_LENGTH(token), qtd->length, qh->xacterrs); | ||
2455 | |||
2456 | /* reset the token in the qtd and the | ||
2457 | * qh overlay (which still contains | ||
2458 | * the qtd) so that we pick up from | ||
2459 | * where we left off | ||
2460 | */ | ||
2461 | token &= ~QTD_STS_HALT; | ||
2462 | token |= QTD_STS_ACTIVE | | ||
2463 | (FUSBH200_TUNE_CERR << 10); | ||
2464 | qtd->hw_token = cpu_to_hc32(fusbh200, | ||
2465 | token); | ||
2466 | wmb(); | ||
2467 | hw->hw_token = cpu_to_hc32(fusbh200, | ||
2468 | token); | ||
2469 | goto retry_xacterr; | ||
2470 | } | ||
2471 | stopped = 1; | ||
2472 | |||
2473 | /* magic dummy for some short reads; qh won't advance. | ||
2474 | * that silicon quirk can kick in with this dummy too. | ||
2475 | * | ||
2476 | * other short reads won't stop the queue, including | ||
2477 | * control transfers (status stage handles that) or | ||
2478 | * most other single-qtd reads ... the queue stops if | ||
2479 | * URB_SHORT_NOT_OK was set so the driver submitting | ||
2480 | * the urbs could clean it up. | ||
2481 | */ | ||
2482 | } else if (IS_SHORT_READ (token) | ||
2483 | && !(qtd->hw_alt_next | ||
2484 | & FUSBH200_LIST_END(fusbh200))) { | ||
2485 | stopped = 1; | ||
2486 | } | ||
2487 | |||
2488 | /* stop scanning when we reach qtds the hc is using */ | ||
2489 | } else if (likely (!stopped | ||
2490 | && fusbh200->rh_state >= FUSBH200_RH_RUNNING)) { | ||
2491 | break; | ||
2492 | |||
2493 | /* scan the whole queue for unlinks whenever it stops */ | ||
2494 | } else { | ||
2495 | stopped = 1; | ||
2496 | |||
2497 | /* cancel everything if we halt, suspend, etc */ | ||
2498 | if (fusbh200->rh_state < FUSBH200_RH_RUNNING) | ||
2499 | last_status = -ESHUTDOWN; | ||
2500 | |||
2501 | /* this qtd is active; skip it unless a previous qtd | ||
2502 | * for its urb faulted, or its urb was canceled. | ||
2503 | */ | ||
2504 | else if (last_status == -EINPROGRESS && !urb->unlinked) | ||
2505 | continue; | ||
2506 | |||
2507 | /* qh unlinked; token in overlay may be most current */ | ||
2508 | if (state == QH_STATE_IDLE | ||
2509 | && cpu_to_hc32(fusbh200, qtd->qtd_dma) | ||
2510 | == hw->hw_current) { | ||
2511 | token = hc32_to_cpu(fusbh200, hw->hw_token); | ||
2512 | |||
2513 | /* An unlink may leave an incomplete | ||
2514 | * async transaction in the TT buffer. | ||
2515 | * We have to clear it. | ||
2516 | */ | ||
2517 | fusbh200_clear_tt_buffer(fusbh200, qh, urb, token); | ||
2518 | } | ||
2519 | } | ||
2520 | |||
2521 | /* unless we already know the urb's status, collect qtd status | ||
2522 | * and update count of bytes transferred. in common short read | ||
2523 | * cases with only one data qtd (including control transfers), | ||
2524 | * queue processing won't halt. but with two or more qtds (for | ||
2525 | * example, with a 32 KB transfer), when the first qtd gets a | ||
2526 | * short read the second must be removed by hand. | ||
2527 | */ | ||
2528 | if (last_status == -EINPROGRESS) { | ||
2529 | last_status = qtd_copy_status(fusbh200, urb, | ||
2530 | qtd->length, token); | ||
2531 | if (last_status == -EREMOTEIO | ||
2532 | && (qtd->hw_alt_next | ||
2533 | & FUSBH200_LIST_END(fusbh200))) | ||
2534 | last_status = -EINPROGRESS; | ||
2535 | |||
2536 | /* As part of low/full-speed endpoint-halt processing | ||
2537 | * we must clear the TT buffer (11.17.5). | ||
2538 | */ | ||
2539 | if (unlikely(last_status != -EINPROGRESS && | ||
2540 | last_status != -EREMOTEIO)) { | ||
2541 | /* The TT's in some hubs malfunction when they | ||
2542 | * receive this request following a STALL (they | ||
2543 | * stop sending isochronous packets). Since a | ||
2544 | * STALL can't leave the TT buffer in a busy | ||
2545 | * state (if you believe Figures 11-48 - 11-51 | ||
2546 | * in the USB 2.0 spec), we won't clear the TT | ||
2547 | * buffer in this case. Strictly speaking this | ||
2548 | * is a violation of the spec. | ||
2549 | */ | ||
2550 | if (last_status != -EPIPE) | ||
2551 | fusbh200_clear_tt_buffer(fusbh200, qh, urb, | ||
2552 | token); | ||
2553 | } | ||
2554 | } | ||
2555 | |||
2556 | /* if we're removing something not at the queue head, | ||
2557 | * patch the hardware queue pointer. | ||
2558 | */ | ||
2559 | if (stopped && qtd->qtd_list.prev != &qh->qtd_list) { | ||
2560 | last = list_entry (qtd->qtd_list.prev, | ||
2561 | struct fusbh200_qtd, qtd_list); | ||
2562 | last->hw_next = qtd->hw_next; | ||
2563 | } | ||
2564 | |||
2565 | /* remove qtd; it's recycled after possible urb completion */ | ||
2566 | list_del (&qtd->qtd_list); | ||
2567 | last = qtd; | ||
2568 | |||
2569 | /* reinit the xacterr counter for the next qtd */ | ||
2570 | qh->xacterrs = 0; | ||
2571 | } | ||
2572 | |||
2573 | /* last urb's completion might still need calling */ | ||
2574 | if (likely (last != NULL)) { | ||
2575 | fusbh200_urb_done(fusbh200, last->urb, last_status); | ||
2576 | count++; | ||
2577 | fusbh200_qtd_free (fusbh200, last); | ||
2578 | } | ||
2579 | |||
2580 | /* Do we need to rescan for URBs dequeued during a giveback? */ | ||
2581 | if (unlikely(qh->needs_rescan)) { | ||
2582 | /* If the QH is already unlinked, do the rescan now. */ | ||
2583 | if (state == QH_STATE_IDLE) | ||
2584 | goto rescan; | ||
2585 | |||
2586 | /* Otherwise we have to wait until the QH is fully unlinked. | ||
2587 | * Our caller will start an unlink if qh->needs_rescan is | ||
2588 | * set. But if an unlink has already started, nothing needs | ||
2589 | * to be done. | ||
2590 | */ | ||
2591 | if (state != QH_STATE_LINKED) | ||
2592 | qh->needs_rescan = 0; | ||
2593 | } | ||
2594 | |||
2595 | /* restore original state; caller must unlink or relink */ | ||
2596 | qh->qh_state = state; | ||
2597 | |||
2598 | /* be sure the hardware's done with the qh before refreshing | ||
2599 | * it after fault cleanup, or recovering from silicon wrongly | ||
2600 | * overlaying the dummy qtd (which reduces DMA chatter). | ||
2601 | */ | ||
2602 | if (stopped != 0 || hw->hw_qtd_next == FUSBH200_LIST_END(fusbh200)) { | ||
2603 | switch (state) { | ||
2604 | case QH_STATE_IDLE: | ||
2605 | qh_refresh(fusbh200, qh); | ||
2606 | break; | ||
2607 | case QH_STATE_LINKED: | ||
2608 | /* We won't refresh a QH that's linked (after the HC | ||
2609 | * stopped the queue). That avoids a race: | ||
2610 | * - HC reads first part of QH; | ||
2611 | * - CPU updates that first part and the token; | ||
2612 | * - HC reads rest of that QH, including token | ||
2613 | * Result: HC gets an inconsistent image, and then | ||
2614 | * DMAs to/from the wrong memory (corrupting it). | ||
2615 | * | ||
2616 | * That should be rare for interrupt transfers, | ||
2617 | * except maybe high bandwidth ... | ||
2618 | */ | ||
2619 | |||
2620 | /* Tell the caller to start an unlink */ | ||
2621 | qh->needs_rescan = 1; | ||
2622 | break; | ||
2623 | /* otherwise, unlink already started */ | ||
2624 | } | ||
2625 | } | ||
2626 | |||
2627 | return count; | ||
2628 | } | ||
2629 | |||
2630 | /*-------------------------------------------------------------------------*/ | ||
2631 | |||
2632 | // high bandwidth multiplier, as encoded in highspeed endpoint descriptors | ||
2633 | #define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) | ||
2634 | // ... and packet size, for any kind of endpoint descriptor | ||
2635 | #define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff) | ||
2636 | |||
2637 | /* | ||
2638 | * reverse of qh_urb_transaction: free a list of TDs. | ||
2639 | * used for cleanup after errors, before HC sees an URB's TDs. | ||
2640 | */ | ||
2641 | static void qtd_list_free ( | ||
2642 | struct fusbh200_hcd *fusbh200, | ||
2643 | struct urb *urb, | ||
2644 | struct list_head *qtd_list | ||
2645 | ) { | ||
2646 | struct list_head *entry, *temp; | ||
2647 | |||
2648 | list_for_each_safe (entry, temp, qtd_list) { | ||
2649 | struct fusbh200_qtd *qtd; | ||
2650 | |||
2651 | qtd = list_entry (entry, struct fusbh200_qtd, qtd_list); | ||
2652 | list_del (&qtd->qtd_list); | ||
2653 | fusbh200_qtd_free (fusbh200, qtd); | ||
2654 | } | ||
2655 | } | ||
2656 | |||
2657 | /* | ||
2658 | * create a list of filled qtds for this URB; won't link into qh. | ||
2659 | */ | ||
2660 | static struct list_head * | ||
2661 | qh_urb_transaction ( | ||
2662 | struct fusbh200_hcd *fusbh200, | ||
2663 | struct urb *urb, | ||
2664 | struct list_head *head, | ||
2665 | gfp_t flags | ||
2666 | ) { | ||
2667 | struct fusbh200_qtd *qtd, *qtd_prev; | ||
2668 | dma_addr_t buf; | ||
2669 | int len, this_sg_len, maxpacket; | ||
2670 | int is_input; | ||
2671 | u32 token; | ||
2672 | int i; | ||
2673 | struct scatterlist *sg; | ||
2674 | |||
2675 | /* | ||
2676 | * URBs map to sequences of QTDs: one logical transaction | ||
2677 | */ | ||
2678 | qtd = fusbh200_qtd_alloc (fusbh200, flags); | ||
2679 | if (unlikely (!qtd)) | ||
2680 | return NULL; | ||
2681 | list_add_tail (&qtd->qtd_list, head); | ||
2682 | qtd->urb = urb; | ||
2683 | |||
2684 | token = QTD_STS_ACTIVE; | ||
2685 | token |= (FUSBH200_TUNE_CERR << 10); | ||
2686 | /* for split transactions, SplitXState initialized to zero */ | ||
2687 | |||
2688 | len = urb->transfer_buffer_length; | ||
2689 | is_input = usb_pipein (urb->pipe); | ||
2690 | if (usb_pipecontrol (urb->pipe)) { | ||
2691 | /* SETUP pid */ | ||
2692 | qtd_fill(fusbh200, qtd, urb->setup_dma, | ||
2693 | sizeof (struct usb_ctrlrequest), | ||
2694 | token | (2 /* "setup" */ << 8), 8); | ||
2695 | |||
2696 | /* ... and always at least one more pid */ | ||
2697 | token ^= QTD_TOGGLE; | ||
2698 | qtd_prev = qtd; | ||
2699 | qtd = fusbh200_qtd_alloc (fusbh200, flags); | ||
2700 | if (unlikely (!qtd)) | ||
2701 | goto cleanup; | ||
2702 | qtd->urb = urb; | ||
2703 | qtd_prev->hw_next = QTD_NEXT(fusbh200, qtd->qtd_dma); | ||
2704 | list_add_tail (&qtd->qtd_list, head); | ||
2705 | |||
2706 | /* for zero length DATA stages, STATUS is always IN */ | ||
2707 | if (len == 0) | ||
2708 | token |= (1 /* "in" */ << 8); | ||
2709 | } | ||
2710 | |||
2711 | /* | ||
2712 | * data transfer stage: buffer setup | ||
2713 | */ | ||
2714 | i = urb->num_mapped_sgs; | ||
2715 | if (len > 0 && i > 0) { | ||
2716 | sg = urb->sg; | ||
2717 | buf = sg_dma_address(sg); | ||
2718 | |||
2719 | /* urb->transfer_buffer_length may be smaller than the | ||
2720 | * size of the scatterlist (or vice versa) | ||
2721 | */ | ||
2722 | this_sg_len = min_t(int, sg_dma_len(sg), len); | ||
2723 | } else { | ||
2724 | sg = NULL; | ||
2725 | buf = urb->transfer_dma; | ||
2726 | this_sg_len = len; | ||
2727 | } | ||
2728 | |||
2729 | if (is_input) | ||
2730 | token |= (1 /* "in" */ << 8); | ||
2731 | /* else it's already initted to "out" pid (0 << 8) */ | ||
2732 | |||
2733 | maxpacket = max_packet(usb_maxpacket(urb->dev, urb->pipe, !is_input)); | ||
2734 | |||
2735 | /* | ||
2736 | * buffer gets wrapped in one or more qtds; | ||
2737 | * last one may be "short" (including zero len) | ||
2738 | * and may serve as a control status ack | ||
2739 | */ | ||
2740 | for (;;) { | ||
2741 | int this_qtd_len; | ||
2742 | |||
2743 | this_qtd_len = qtd_fill(fusbh200, qtd, buf, this_sg_len, token, | ||
2744 | maxpacket); | ||
2745 | this_sg_len -= this_qtd_len; | ||
2746 | len -= this_qtd_len; | ||
2747 | buf += this_qtd_len; | ||
2748 | |||
2749 | /* | ||
2750 | * short reads advance to a "magic" dummy instead of the next | ||
2751 | * qtd ... that forces the queue to stop, for manual cleanup. | ||
2752 | * (this will usually be overridden later.) | ||
2753 | */ | ||
2754 | if (is_input) | ||
2755 | qtd->hw_alt_next = fusbh200->async->hw->hw_alt_next; | ||
2756 | |||
2757 | /* qh makes control packets use qtd toggle; maybe switch it */ | ||
2758 | if ((maxpacket & (this_qtd_len + (maxpacket - 1))) == 0) | ||
2759 | token ^= QTD_TOGGLE; | ||
2760 | |||
2761 | if (likely(this_sg_len <= 0)) { | ||
2762 | if (--i <= 0 || len <= 0) | ||
2763 | break; | ||
2764 | sg = sg_next(sg); | ||
2765 | buf = sg_dma_address(sg); | ||
2766 | this_sg_len = min_t(int, sg_dma_len(sg), len); | ||
2767 | } | ||
2768 | |||
2769 | qtd_prev = qtd; | ||
2770 | qtd = fusbh200_qtd_alloc (fusbh200, flags); | ||
2771 | if (unlikely (!qtd)) | ||
2772 | goto cleanup; | ||
2773 | qtd->urb = urb; | ||
2774 | qtd_prev->hw_next = QTD_NEXT(fusbh200, qtd->qtd_dma); | ||
2775 | list_add_tail (&qtd->qtd_list, head); | ||
2776 | } | ||
2777 | |||
2778 | /* | ||
2779 | * unless the caller requires manual cleanup after short reads, | ||
2780 | * have the alt_next mechanism keep the queue running after the | ||
2781 | * last data qtd (the only one, for control and most other cases). | ||
2782 | */ | ||
2783 | if (likely ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0 | ||
2784 | || usb_pipecontrol (urb->pipe))) | ||
2785 | qtd->hw_alt_next = FUSBH200_LIST_END(fusbh200); | ||
2786 | |||
2787 | /* | ||
2788 | * control requests may need a terminating data "status" ack; | ||
2789 | * other OUT ones may need a terminating short packet | ||
2790 | * (zero length). | ||
2791 | */ | ||
2792 | if (likely (urb->transfer_buffer_length != 0)) { | ||
2793 | int one_more = 0; | ||
2794 | |||
2795 | if (usb_pipecontrol (urb->pipe)) { | ||
2796 | one_more = 1; | ||
2797 | token ^= 0x0100; /* "in" <--> "out" */ | ||
2798 | token |= QTD_TOGGLE; /* force DATA1 */ | ||
2799 | } else if (usb_pipeout(urb->pipe) | ||
2800 | && (urb->transfer_flags & URB_ZERO_PACKET) | ||
2801 | && !(urb->transfer_buffer_length % maxpacket)) { | ||
2802 | one_more = 1; | ||
2803 | } | ||
2804 | if (one_more) { | ||
2805 | qtd_prev = qtd; | ||
2806 | qtd = fusbh200_qtd_alloc (fusbh200, flags); | ||
2807 | if (unlikely (!qtd)) | ||
2808 | goto cleanup; | ||
2809 | qtd->urb = urb; | ||
2810 | qtd_prev->hw_next = QTD_NEXT(fusbh200, qtd->qtd_dma); | ||
2811 | list_add_tail (&qtd->qtd_list, head); | ||
2812 | |||
2813 | /* never any data in such packets */ | ||
2814 | qtd_fill(fusbh200, qtd, 0, 0, token, 0); | ||
2815 | } | ||
2816 | } | ||
2817 | |||
2818 | /* by default, enable interrupt on urb completion */ | ||
2819 | if (likely (!(urb->transfer_flags & URB_NO_INTERRUPT))) | ||
2820 | qtd->hw_token |= cpu_to_hc32(fusbh200, QTD_IOC); | ||
2821 | return head; | ||
2822 | |||
2823 | cleanup: | ||
2824 | qtd_list_free (fusbh200, urb, head); | ||
2825 | return NULL; | ||
2826 | } | ||
2827 | |||
2828 | /*-------------------------------------------------------------------------*/ | ||
2829 | |||
2830 | // Would be best to create all qh's from config descriptors, | ||
2831 | // when each interface/altsetting is established. Unlink | ||
2832 | // any previous qh and cancel its urbs first; endpoints are | ||
2833 | // implicitly reset then (data toggle too). | ||
2834 | // That'd mean updating how usbcore talks to HCDs. (2.7?) | ||
2835 | |||
2836 | |||
2837 | /* | ||
2838 | * Each QH holds a qtd list; a QH is used for everything except iso. | ||
2839 | * | ||
2840 | * For interrupt urbs, the scheduler must set the microframe scheduling | ||
2841 | * mask(s) each time the QH gets scheduled. For highspeed, that's | ||
2842 | * just one microframe in the s-mask. For split interrupt transactions | ||
2843 | * there are additional complications: c-mask, maybe FSTNs. | ||
2844 | */ | ||
2845 | static struct fusbh200_qh * | ||
2846 | qh_make ( | ||
2847 | struct fusbh200_hcd *fusbh200, | ||
2848 | struct urb *urb, | ||
2849 | gfp_t flags | ||
2850 | ) { | ||
2851 | struct fusbh200_qh *qh = fusbh200_qh_alloc (fusbh200, flags); | ||
2852 | u32 info1 = 0, info2 = 0; | ||
2853 | int is_input, type; | ||
2854 | int maxp = 0; | ||
2855 | struct usb_tt *tt = urb->dev->tt; | ||
2856 | struct fusbh200_qh_hw *hw; | ||
2857 | |||
2858 | if (!qh) | ||
2859 | return qh; | ||
2860 | |||
2861 | /* | ||
2862 | * init endpoint/device data for this QH | ||
2863 | */ | ||
2864 | info1 |= usb_pipeendpoint (urb->pipe) << 8; | ||
2865 | info1 |= usb_pipedevice (urb->pipe) << 0; | ||
2866 | |||
2867 | is_input = usb_pipein (urb->pipe); | ||
2868 | type = usb_pipetype (urb->pipe); | ||
2869 | maxp = usb_maxpacket (urb->dev, urb->pipe, !is_input); | ||
2870 | |||
2871 | /* 1024 byte maxpacket is a hardware ceiling. High bandwidth | ||
2872 | * acts like up to 3KB, but is built from smaller packets. | ||
2873 | */ | ||
2874 | if (max_packet(maxp) > 1024) { | ||
2875 | fusbh200_dbg(fusbh200, "bogus qh maxpacket %d\n", max_packet(maxp)); | ||
2876 | goto done; | ||
2877 | } | ||
2878 | |||
2879 | /* Compute interrupt scheduling parameters just once, and save. | ||
2880 | * - allowing for high bandwidth, how many nsec/uframe are used? | ||
2881 | * - split transactions need a second CSPLIT uframe; same question | ||
2882 | * - splits also need a schedule gap (for full/low speed I/O) | ||
2883 | * - qh has a polling interval | ||
2884 | * | ||
2885 | * For control/bulk requests, the HC or TT handles these. | ||
2886 | */ | ||
2887 | if (type == PIPE_INTERRUPT) { | ||
2888 | qh->usecs = NS_TO_US(usb_calc_bus_time(USB_SPEED_HIGH, | ||
2889 | is_input, 0, | ||
2890 | hb_mult(maxp) * max_packet(maxp))); | ||
2891 | qh->start = NO_FRAME; | ||
2892 | |||
2893 | if (urb->dev->speed == USB_SPEED_HIGH) { | ||
2894 | qh->c_usecs = 0; | ||
2895 | qh->gap_uf = 0; | ||
2896 | |||
2897 | qh->period = urb->interval >> 3; | ||
2898 | if (qh->period == 0 && urb->interval != 1) { | ||
2899 | /* NOTE interval 2 or 4 uframes could work. | ||
2900 | * But interval 1 scheduling is simpler, and | ||
2901 | * includes high bandwidth. | ||
2902 | */ | ||
2903 | urb->interval = 1; | ||
2904 | } else if (qh->period > fusbh200->periodic_size) { | ||
2905 | qh->period = fusbh200->periodic_size; | ||
2906 | urb->interval = qh->period << 3; | ||
2907 | } | ||
2908 | } else { | ||
2909 | int think_time; | ||
2910 | |||
2911 | /* gap is f(FS/LS transfer times) */ | ||
2912 | qh->gap_uf = 1 + usb_calc_bus_time (urb->dev->speed, | ||
2913 | is_input, 0, maxp) / (125 * 1000); | ||
2914 | |||
2915 | /* FIXME this just approximates SPLIT/CSPLIT times */ | ||
2916 | if (is_input) { // SPLIT, gap, CSPLIT+DATA | ||
2917 | qh->c_usecs = qh->usecs + HS_USECS (0); | ||
2918 | qh->usecs = HS_USECS (1); | ||
2919 | } else { // SPLIT+DATA, gap, CSPLIT | ||
2920 | qh->usecs += HS_USECS (1); | ||
2921 | qh->c_usecs = HS_USECS (0); | ||
2922 | } | ||
2923 | |||
2924 | think_time = tt ? tt->think_time : 0; | ||
2925 | qh->tt_usecs = NS_TO_US (think_time + | ||
2926 | usb_calc_bus_time (urb->dev->speed, | ||
2927 | is_input, 0, max_packet (maxp))); | ||
2928 | qh->period = urb->interval; | ||
2929 | if (qh->period > fusbh200->periodic_size) { | ||
2930 | qh->period = fusbh200->periodic_size; | ||
2931 | urb->interval = qh->period; | ||
2932 | } | ||
2933 | } | ||
2934 | } | ||
2935 | |||
2936 | /* support for tt scheduling, and access to toggles */ | ||
2937 | qh->dev = urb->dev; | ||
2938 | |||
2939 | /* using TT? */ | ||
2940 | switch (urb->dev->speed) { | ||
2941 | case USB_SPEED_LOW: | ||
2942 | info1 |= QH_LOW_SPEED; | ||
2943 | /* FALL THROUGH */ | ||
2944 | |||
2945 | case USB_SPEED_FULL: | ||
2946 | /* EPS 0 means "full" */ | ||
2947 | if (type != PIPE_INTERRUPT) | ||
2948 | info1 |= (FUSBH200_TUNE_RL_TT << 28); | ||
2949 | if (type == PIPE_CONTROL) { | ||
2950 | info1 |= QH_CONTROL_EP; /* for TT */ | ||
2951 | info1 |= QH_TOGGLE_CTL; /* toggle from qtd */ | ||
2952 | } | ||
2953 | info1 |= maxp << 16; | ||
2954 | |||
2955 | info2 |= (FUSBH200_TUNE_MULT_TT << 30); | ||
2956 | |||
2957 | /* Some Freescale processors have an erratum in which the | ||
2958 | * port number in the queue head was 0..N-1 instead of 1..N. | ||
2959 | */ | ||
2960 | if (fusbh200_has_fsl_portno_bug(fusbh200)) | ||
2961 | info2 |= (urb->dev->ttport-1) << 23; | ||
2962 | else | ||
2963 | info2 |= urb->dev->ttport << 23; | ||
2964 | |||
2965 | /* set the address of the TT; for TDI's integrated | ||
2966 | * root hub tt, leave it zeroed. | ||
2967 | */ | ||
2968 | if (tt && tt->hub != fusbh200_to_hcd(fusbh200)->self.root_hub) | ||
2969 | info2 |= tt->hub->devnum << 16; | ||
2970 | |||
2971 | /* NOTE: if (PIPE_INTERRUPT) { scheduler sets c-mask } */ | ||
2972 | |||
2973 | break; | ||
2974 | |||
2975 | case USB_SPEED_HIGH: /* no TT involved */ | ||
2976 | info1 |= QH_HIGH_SPEED; | ||
2977 | if (type == PIPE_CONTROL) { | ||
2978 | info1 |= (FUSBH200_TUNE_RL_HS << 28); | ||
2979 | info1 |= 64 << 16; /* usb2 fixed maxpacket */ | ||
2980 | info1 |= QH_TOGGLE_CTL; /* toggle from qtd */ | ||
2981 | info2 |= (FUSBH200_TUNE_MULT_HS << 30); | ||
2982 | } else if (type == PIPE_BULK) { | ||
2983 | info1 |= (FUSBH200_TUNE_RL_HS << 28); | ||
2984 | /* The USB spec says that high speed bulk endpoints | ||
2985 | * always use 512 byte maxpacket. But some device | ||
2986 | * vendors decided to ignore that, and MSFT is happy | ||
2987 | * to help them do so. So now people expect to use | ||
2988 | * such nonconformant devices with Linux too; sigh. | ||
2989 | */ | ||
2990 | info1 |= max_packet(maxp) << 16; | ||
2991 | info2 |= (FUSBH200_TUNE_MULT_HS << 30); | ||
2992 | } else { /* PIPE_INTERRUPT */ | ||
2993 | info1 |= max_packet (maxp) << 16; | ||
2994 | info2 |= hb_mult (maxp) << 30; | ||
2995 | } | ||
2996 | break; | ||
2997 | default: | ||
2998 | fusbh200_dbg(fusbh200, "bogus dev %p speed %d\n", urb->dev, | ||
2999 | urb->dev->speed); | ||
3000 | done: | ||
3001 | qh_destroy(fusbh200, qh); | ||
3002 | return NULL; | ||
3003 | } | ||
3004 | |||
3005 | /* NOTE: if (PIPE_INTERRUPT) { scheduler sets s-mask } */ | ||
3006 | |||
3007 | /* init as live, toggle clear, advance to dummy */ | ||
3008 | qh->qh_state = QH_STATE_IDLE; | ||
3009 | hw = qh->hw; | ||
3010 | hw->hw_info1 = cpu_to_hc32(fusbh200, info1); | ||
3011 | hw->hw_info2 = cpu_to_hc32(fusbh200, info2); | ||
3012 | qh->is_out = !is_input; | ||
3013 | usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1); | ||
3014 | qh_refresh (fusbh200, qh); | ||
3015 | return qh; | ||
3016 | } | ||
3017 | |||
3018 | /*-------------------------------------------------------------------------*/ | ||
3019 | |||
3020 | static void enable_async(struct fusbh200_hcd *fusbh200) | ||
3021 | { | ||
3022 | if (fusbh200->async_count++) | ||
3023 | return; | ||
3024 | |||
3025 | /* Stop waiting to turn off the async schedule */ | ||
3026 | fusbh200->enabled_hrtimer_events &= ~BIT(FUSBH200_HRTIMER_DISABLE_ASYNC); | ||
3027 | |||
3028 | /* Don't start the schedule until ASS is 0 */ | ||
3029 | fusbh200_poll_ASS(fusbh200); | ||
3030 | turn_on_io_watchdog(fusbh200); | ||
3031 | } | ||
3032 | |||
3033 | static void disable_async(struct fusbh200_hcd *fusbh200) | ||
3034 | { | ||
3035 | if (--fusbh200->async_count) | ||
3036 | return; | ||
3037 | |||
3038 | /* The async schedule and async_unlink list are supposed to be empty */ | ||
3039 | WARN_ON(fusbh200->async->qh_next.qh || fusbh200->async_unlink); | ||
3040 | |||
3041 | /* Don't turn off the schedule until ASS is 1 */ | ||
3042 | fusbh200_poll_ASS(fusbh200); | ||
3043 | } | ||
3044 | |||
3045 | /* move qh (and its qtds) onto async queue; maybe enable queue. */ | ||
3046 | |||
3047 | static void qh_link_async (struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh) | ||
3048 | { | ||
3049 | __hc32 dma = QH_NEXT(fusbh200, qh->qh_dma); | ||
3050 | struct fusbh200_qh *head; | ||
3051 | |||
3052 | /* Don't link a QH if there's a Clear-TT-Buffer pending */ | ||
3053 | if (unlikely(qh->clearing_tt)) | ||
3054 | return; | ||
3055 | |||
3056 | WARN_ON(qh->qh_state != QH_STATE_IDLE); | ||
3057 | |||
3058 | /* clear halt and/or toggle; and maybe recover from silicon quirk */ | ||
3059 | qh_refresh(fusbh200, qh); | ||
3060 | |||
3061 | /* splice right after start */ | ||
3062 | head = fusbh200->async; | ||
3063 | qh->qh_next = head->qh_next; | ||
3064 | qh->hw->hw_next = head->hw->hw_next; | ||
3065 | wmb (); | ||
3066 | |||
3067 | head->qh_next.qh = qh; | ||
3068 | head->hw->hw_next = dma; | ||
3069 | |||
3070 | qh->xacterrs = 0; | ||
3071 | qh->qh_state = QH_STATE_LINKED; | ||
3072 | /* qtd completions reported later by interrupt */ | ||
3073 | |||
3074 | enable_async(fusbh200); | ||
3075 | } | ||
3076 | |||
3077 | /*-------------------------------------------------------------------------*/ | ||
3078 | |||
3079 | /* | ||
3080 | * For control/bulk/interrupt, return QH with these TDs appended. | ||
3081 | * Allocates and initializes the QH if necessary. | ||
3082 | * Returns null if it can't allocate a QH it needs to. | ||
3083 | * If the QH has TDs (urbs) already, that's great. | ||
3084 | */ | ||
3085 | static struct fusbh200_qh *qh_append_tds ( | ||
3086 | struct fusbh200_hcd *fusbh200, | ||
3087 | struct urb *urb, | ||
3088 | struct list_head *qtd_list, | ||
3089 | int epnum, | ||
3090 | void **ptr | ||
3091 | ) | ||
3092 | { | ||
3093 | struct fusbh200_qh *qh = NULL; | ||
3094 | __hc32 qh_addr_mask = cpu_to_hc32(fusbh200, 0x7f); | ||
3095 | |||
3096 | qh = (struct fusbh200_qh *) *ptr; | ||
3097 | if (unlikely (qh == NULL)) { | ||
3098 | /* can't sleep here, we have fusbh200->lock... */ | ||
3099 | qh = qh_make (fusbh200, urb, GFP_ATOMIC); | ||
3100 | *ptr = qh; | ||
3101 | } | ||
3102 | if (likely (qh != NULL)) { | ||
3103 | struct fusbh200_qtd *qtd; | ||
3104 | |||
3105 | if (unlikely (list_empty (qtd_list))) | ||
3106 | qtd = NULL; | ||
3107 | else | ||
3108 | qtd = list_entry (qtd_list->next, struct fusbh200_qtd, | ||
3109 | qtd_list); | ||
3110 | |||
3111 | /* control qh may need patching ... */ | ||
3112 | if (unlikely (epnum == 0)) { | ||
3113 | |||
3114 | /* usb_reset_device() briefly reverts to address 0 */ | ||
3115 | if (usb_pipedevice (urb->pipe) == 0) | ||
3116 | qh->hw->hw_info1 &= ~qh_addr_mask; | ||
3117 | } | ||
3118 | |||
3119 | /* just one way to queue requests: swap with the dummy qtd. | ||
3120 | * only hc or qh_refresh() ever modify the overlay. | ||
3121 | */ | ||
3122 | if (likely (qtd != NULL)) { | ||
3123 | struct fusbh200_qtd *dummy; | ||
3124 | dma_addr_t dma; | ||
3125 | __hc32 token; | ||
3126 | |||
3127 | /* to avoid racing the HC, use the dummy td instead of | ||
3128 | * the first td of our list (becomes new dummy). both | ||
3129 | * tds stay deactivated until we're done, when the | ||
3130 | * HC is allowed to fetch the old dummy (4.10.2). | ||
3131 | */ | ||
3132 | token = qtd->hw_token; | ||
3133 | qtd->hw_token = HALT_BIT(fusbh200); | ||
3134 | |||
3135 | dummy = qh->dummy; | ||
3136 | |||
3137 | dma = dummy->qtd_dma; | ||
3138 | *dummy = *qtd; | ||
3139 | dummy->qtd_dma = dma; | ||
3140 | |||
3141 | list_del (&qtd->qtd_list); | ||
3142 | list_add (&dummy->qtd_list, qtd_list); | ||
3143 | list_splice_tail(qtd_list, &qh->qtd_list); | ||
3144 | |||
3145 | fusbh200_qtd_init(fusbh200, qtd, qtd->qtd_dma); | ||
3146 | qh->dummy = qtd; | ||
3147 | |||
3148 | /* hc must see the new dummy at list end */ | ||
3149 | dma = qtd->qtd_dma; | ||
3150 | qtd = list_entry (qh->qtd_list.prev, | ||
3151 | struct fusbh200_qtd, qtd_list); | ||
3152 | qtd->hw_next = QTD_NEXT(fusbh200, dma); | ||
3153 | |||
3154 | /* let the hc process these next qtds */ | ||
3155 | wmb (); | ||
3156 | dummy->hw_token = token; | ||
3157 | |||
3158 | urb->hcpriv = qh; | ||
3159 | } | ||
3160 | } | ||
3161 | return qh; | ||
3162 | } | ||
3163 | |||
3164 | /*-------------------------------------------------------------------------*/ | ||
3165 | |||
3166 | static int | ||
3167 | submit_async ( | ||
3168 | struct fusbh200_hcd *fusbh200, | ||
3169 | struct urb *urb, | ||
3170 | struct list_head *qtd_list, | ||
3171 | gfp_t mem_flags | ||
3172 | ) { | ||
3173 | int epnum; | ||
3174 | unsigned long flags; | ||
3175 | struct fusbh200_qh *qh = NULL; | ||
3176 | int rc; | ||
3177 | |||
3178 | epnum = urb->ep->desc.bEndpointAddress; | ||
3179 | |||
3180 | #ifdef FUSBH200_URB_TRACE | ||
3181 | { | ||
3182 | struct fusbh200_qtd *qtd; | ||
3183 | qtd = list_entry(qtd_list->next, struct fusbh200_qtd, qtd_list); | ||
3184 | fusbh200_dbg(fusbh200, | ||
3185 | "%s %s urb %p ep%d%s len %d, qtd %p [qh %p]\n", | ||
3186 | __func__, urb->dev->devpath, urb, | ||
3187 | epnum & 0x0f, (epnum & USB_DIR_IN) ? "in" : "out", | ||
3188 | urb->transfer_buffer_length, | ||
3189 | qtd, urb->ep->hcpriv); | ||
3190 | } | ||
3191 | #endif | ||
3192 | |||
3193 | spin_lock_irqsave (&fusbh200->lock, flags); | ||
3194 | if (unlikely(!HCD_HW_ACCESSIBLE(fusbh200_to_hcd(fusbh200)))) { | ||
3195 | rc = -ESHUTDOWN; | ||
3196 | goto done; | ||
3197 | } | ||
3198 | rc = usb_hcd_link_urb_to_ep(fusbh200_to_hcd(fusbh200), urb); | ||
3199 | if (unlikely(rc)) | ||
3200 | goto done; | ||
3201 | |||
3202 | qh = qh_append_tds(fusbh200, urb, qtd_list, epnum, &urb->ep->hcpriv); | ||
3203 | if (unlikely(qh == NULL)) { | ||
3204 | usb_hcd_unlink_urb_from_ep(fusbh200_to_hcd(fusbh200), urb); | ||
3205 | rc = -ENOMEM; | ||
3206 | goto done; | ||
3207 | } | ||
3208 | |||
3209 | /* Control/bulk operations through TTs don't need scheduling, | ||
3210 | * the HC and TT handle it when the TT has a buffer ready. | ||
3211 | */ | ||
3212 | if (likely (qh->qh_state == QH_STATE_IDLE)) | ||
3213 | qh_link_async(fusbh200, qh); | ||
3214 | done: | ||
3215 | spin_unlock_irqrestore (&fusbh200->lock, flags); | ||
3216 | if (unlikely (qh == NULL)) | ||
3217 | qtd_list_free (fusbh200, urb, qtd_list); | ||
3218 | return rc; | ||
3219 | } | ||
3220 | |||
3221 | /*-------------------------------------------------------------------------*/ | ||
3222 | |||
3223 | static void single_unlink_async(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh) | ||
3224 | { | ||
3225 | struct fusbh200_qh *prev; | ||
3226 | |||
3227 | /* Add to the end of the list of QHs waiting for the next IAAD */ | ||
3228 | qh->qh_state = QH_STATE_UNLINK; | ||
3229 | if (fusbh200->async_unlink) | ||
3230 | fusbh200->async_unlink_last->unlink_next = qh; | ||
3231 | else | ||
3232 | fusbh200->async_unlink = qh; | ||
3233 | fusbh200->async_unlink_last = qh; | ||
3234 | |||
3235 | /* Unlink it from the schedule */ | ||
3236 | prev = fusbh200->async; | ||
3237 | while (prev->qh_next.qh != qh) | ||
3238 | prev = prev->qh_next.qh; | ||
3239 | |||
3240 | prev->hw->hw_next = qh->hw->hw_next; | ||
3241 | prev->qh_next = qh->qh_next; | ||
3242 | if (fusbh200->qh_scan_next == qh) | ||
3243 | fusbh200->qh_scan_next = qh->qh_next.qh; | ||
3244 | } | ||
3245 | |||
3246 | static void start_iaa_cycle(struct fusbh200_hcd *fusbh200, bool nested) | ||
3247 | { | ||
3248 | /* | ||
3249 | * Do nothing if an IAA cycle is already running or | ||
3250 | * if one will be started shortly. | ||
3251 | */ | ||
3252 | if (fusbh200->async_iaa || fusbh200->async_unlinking) | ||
3253 | return; | ||
3254 | |||
3255 | /* Do all the waiting QHs at once */ | ||
3256 | fusbh200->async_iaa = fusbh200->async_unlink; | ||
3257 | fusbh200->async_unlink = NULL; | ||
3258 | |||
3259 | /* If the controller isn't running, we don't have to wait for it */ | ||
3260 | if (unlikely(fusbh200->rh_state < FUSBH200_RH_RUNNING)) { | ||
3261 | if (!nested) /* Avoid recursion */ | ||
3262 | end_unlink_async(fusbh200); | ||
3263 | |||
3264 | /* Otherwise start a new IAA cycle */ | ||
3265 | } else if (likely(fusbh200->rh_state == FUSBH200_RH_RUNNING)) { | ||
3266 | /* Make sure the unlinks are all visible to the hardware */ | ||
3267 | wmb(); | ||
3268 | |||
3269 | fusbh200_writel(fusbh200, fusbh200->command | CMD_IAAD, | ||
3270 | &fusbh200->regs->command); | ||
3271 | fusbh200_readl(fusbh200, &fusbh200->regs->command); | ||
3272 | fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_IAA_WATCHDOG, true); | ||
3273 | } | ||
3274 | } | ||
3275 | |||
3276 | /* the async qh for the qtds being unlinked are now gone from the HC */ | ||
3277 | |||
3278 | static void end_unlink_async(struct fusbh200_hcd *fusbh200) | ||
3279 | { | ||
3280 | struct fusbh200_qh *qh; | ||
3281 | |||
3282 | /* Process the idle QHs */ | ||
3283 | restart: | ||
3284 | fusbh200->async_unlinking = true; | ||
3285 | while (fusbh200->async_iaa) { | ||
3286 | qh = fusbh200->async_iaa; | ||
3287 | fusbh200->async_iaa = qh->unlink_next; | ||
3288 | qh->unlink_next = NULL; | ||
3289 | |||
3290 | qh->qh_state = QH_STATE_IDLE; | ||
3291 | qh->qh_next.qh = NULL; | ||
3292 | |||
3293 | qh_completions(fusbh200, qh); | ||
3294 | if (!list_empty(&qh->qtd_list) && | ||
3295 | fusbh200->rh_state == FUSBH200_RH_RUNNING) | ||
3296 | qh_link_async(fusbh200, qh); | ||
3297 | disable_async(fusbh200); | ||
3298 | } | ||
3299 | fusbh200->async_unlinking = false; | ||
3300 | |||
3301 | /* Start a new IAA cycle if any QHs are waiting for it */ | ||
3302 | if (fusbh200->async_unlink) { | ||
3303 | start_iaa_cycle(fusbh200, true); | ||
3304 | if (unlikely(fusbh200->rh_state < FUSBH200_RH_RUNNING)) | ||
3305 | goto restart; | ||
3306 | } | ||
3307 | } | ||
3308 | |||
3309 | static void unlink_empty_async(struct fusbh200_hcd *fusbh200) | ||
3310 | { | ||
3311 | struct fusbh200_qh *qh, *next; | ||
3312 | bool stopped = (fusbh200->rh_state < FUSBH200_RH_RUNNING); | ||
3313 | bool check_unlinks_later = false; | ||
3314 | |||
3315 | /* Unlink all the async QHs that have been empty for a timer cycle */ | ||
3316 | next = fusbh200->async->qh_next.qh; | ||
3317 | while (next) { | ||
3318 | qh = next; | ||
3319 | next = qh->qh_next.qh; | ||
3320 | |||
3321 | if (list_empty(&qh->qtd_list) && | ||
3322 | qh->qh_state == QH_STATE_LINKED) { | ||
3323 | if (!stopped && qh->unlink_cycle == | ||
3324 | fusbh200->async_unlink_cycle) | ||
3325 | check_unlinks_later = true; | ||
3326 | else | ||
3327 | single_unlink_async(fusbh200, qh); | ||
3328 | } | ||
3329 | } | ||
3330 | |||
3331 | /* Start a new IAA cycle if any QHs are waiting for it */ | ||
3332 | if (fusbh200->async_unlink) | ||
3333 | start_iaa_cycle(fusbh200, false); | ||
3334 | |||
3335 | /* QHs that haven't been empty for long enough will be handled later */ | ||
3336 | if (check_unlinks_later) { | ||
3337 | fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_ASYNC_UNLINKS, true); | ||
3338 | ++fusbh200->async_unlink_cycle; | ||
3339 | } | ||
3340 | } | ||
3341 | |||
3342 | /* makes sure the async qh will become idle */ | ||
3343 | /* caller must own fusbh200->lock */ | ||
3344 | |||
3345 | static void start_unlink_async(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh) | ||
3346 | { | ||
3347 | /* | ||
3348 | * If the QH isn't linked then there's nothing we can do | ||
3349 | * unless we were called during a giveback, in which case | ||
3350 | * qh_completions() has to deal with it. | ||
3351 | */ | ||
3352 | if (qh->qh_state != QH_STATE_LINKED) { | ||
3353 | if (qh->qh_state == QH_STATE_COMPLETING) | ||
3354 | qh->needs_rescan = 1; | ||
3355 | return; | ||
3356 | } | ||
3357 | |||
3358 | single_unlink_async(fusbh200, qh); | ||
3359 | start_iaa_cycle(fusbh200, false); | ||
3360 | } | ||
3361 | |||
3362 | /*-------------------------------------------------------------------------*/ | ||
3363 | |||
3364 | static void scan_async (struct fusbh200_hcd *fusbh200) | ||
3365 | { | ||
3366 | struct fusbh200_qh *qh; | ||
3367 | bool check_unlinks_later = false; | ||
3368 | |||
3369 | fusbh200->qh_scan_next = fusbh200->async->qh_next.qh; | ||
3370 | while (fusbh200->qh_scan_next) { | ||
3371 | qh = fusbh200->qh_scan_next; | ||
3372 | fusbh200->qh_scan_next = qh->qh_next.qh; | ||
3373 | rescan: | ||
3374 | /* clean any finished work for this qh */ | ||
3375 | if (!list_empty(&qh->qtd_list)) { | ||
3376 | int temp; | ||
3377 | |||
3378 | /* | ||
3379 | * Unlinks could happen here; completion reporting | ||
3380 | * drops the lock. That's why fusbh200->qh_scan_next | ||
3381 | * always holds the next qh to scan; if the next qh | ||
3382 | * gets unlinked then fusbh200->qh_scan_next is adjusted | ||
3383 | * in single_unlink_async(). | ||
3384 | */ | ||
3385 | temp = qh_completions(fusbh200, qh); | ||
3386 | if (qh->needs_rescan) { | ||
3387 | start_unlink_async(fusbh200, qh); | ||
3388 | } else if (list_empty(&qh->qtd_list) | ||
3389 | && qh->qh_state == QH_STATE_LINKED) { | ||
3390 | qh->unlink_cycle = fusbh200->async_unlink_cycle; | ||
3391 | check_unlinks_later = true; | ||
3392 | } else if (temp != 0) | ||
3393 | goto rescan; | ||
3394 | } | ||
3395 | } | ||
3396 | |||
3397 | /* | ||
3398 | * Unlink empty entries, reducing DMA usage as well | ||
3399 | * as HCD schedule-scanning costs. Delay for any qh | ||
3400 | * we just scanned, there's a not-unusual case that it | ||
3401 | * doesn't stay idle for long. | ||
3402 | */ | ||
3403 | if (check_unlinks_later && fusbh200->rh_state == FUSBH200_RH_RUNNING && | ||
3404 | !(fusbh200->enabled_hrtimer_events & | ||
3405 | BIT(FUSBH200_HRTIMER_ASYNC_UNLINKS))) { | ||
3406 | fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_ASYNC_UNLINKS, true); | ||
3407 | ++fusbh200->async_unlink_cycle; | ||
3408 | } | ||
3409 | } | ||
3410 | /*-------------------------------------------------------------------------*/ | ||
3411 | /* | ||
3412 | * EHCI scheduled transaction support: interrupt, iso, split iso | ||
3413 | * These are called "periodic" transactions in the EHCI spec. | ||
3414 | * | ||
3415 | * Note that for interrupt transfers, the QH/QTD manipulation is shared | ||
3416 | * with the "asynchronous" transaction support (control/bulk transfers). | ||
3417 | * The only real difference is in how interrupt transfers are scheduled. | ||
3418 | * | ||
3419 | * For ISO, we make an "iso_stream" head to serve the same role as a QH. | ||
3420 | * It keeps track of every ITD (or SITD) that's linked, and holds enough | ||
3421 | * pre-calculated schedule data to make appending to the queue be quick. | ||
3422 | */ | ||
3423 | |||
3424 | static int fusbh200_get_frame (struct usb_hcd *hcd); | ||
3425 | |||
3426 | /*-------------------------------------------------------------------------*/ | ||
3427 | |||
3428 | /* | ||
3429 | * periodic_next_shadow - return "next" pointer on shadow list | ||
3430 | * @periodic: host pointer to qh/itd | ||
3431 | * @tag: hardware tag for type of this record | ||
3432 | */ | ||
3433 | static union fusbh200_shadow * | ||
3434 | periodic_next_shadow(struct fusbh200_hcd *fusbh200, union fusbh200_shadow *periodic, | ||
3435 | __hc32 tag) | ||
3436 | { | ||
3437 | switch (hc32_to_cpu(fusbh200, tag)) { | ||
3438 | case Q_TYPE_QH: | ||
3439 | return &periodic->qh->qh_next; | ||
3440 | case Q_TYPE_FSTN: | ||
3441 | return &periodic->fstn->fstn_next; | ||
3442 | default: | ||
3443 | return &periodic->itd->itd_next; | ||
3444 | } | ||
3445 | } | ||
3446 | |||
3447 | static __hc32 * | ||
3448 | shadow_next_periodic(struct fusbh200_hcd *fusbh200, union fusbh200_shadow *periodic, | ||
3449 | __hc32 tag) | ||
3450 | { | ||
3451 | switch (hc32_to_cpu(fusbh200, tag)) { | ||
3452 | /* our fusbh200_shadow.qh is actually software part */ | ||
3453 | case Q_TYPE_QH: | ||
3454 | return &periodic->qh->hw->hw_next; | ||
3455 | /* others are hw parts */ | ||
3456 | default: | ||
3457 | return periodic->hw_next; | ||
3458 | } | ||
3459 | } | ||
3460 | |||
3461 | /* caller must hold fusbh200->lock */ | ||
3462 | static void periodic_unlink (struct fusbh200_hcd *fusbh200, unsigned frame, void *ptr) | ||
3463 | { | ||
3464 | union fusbh200_shadow *prev_p = &fusbh200->pshadow[frame]; | ||
3465 | __hc32 *hw_p = &fusbh200->periodic[frame]; | ||
3466 | union fusbh200_shadow here = *prev_p; | ||
3467 | |||
3468 | /* find predecessor of "ptr"; hw and shadow lists are in sync */ | ||
3469 | while (here.ptr && here.ptr != ptr) { | ||
3470 | prev_p = periodic_next_shadow(fusbh200, prev_p, | ||
3471 | Q_NEXT_TYPE(fusbh200, *hw_p)); | ||
3472 | hw_p = shadow_next_periodic(fusbh200, &here, | ||
3473 | Q_NEXT_TYPE(fusbh200, *hw_p)); | ||
3474 | here = *prev_p; | ||
3475 | } | ||
3476 | /* an interrupt entry (at list end) could have been shared */ | ||
3477 | if (!here.ptr) | ||
3478 | return; | ||
3479 | |||
3480 | /* update shadow and hardware lists ... the old "next" pointers | ||
3481 | * from ptr may still be in use, the caller updates them. | ||
3482 | */ | ||
3483 | *prev_p = *periodic_next_shadow(fusbh200, &here, | ||
3484 | Q_NEXT_TYPE(fusbh200, *hw_p)); | ||
3485 | |||
3486 | *hw_p = *shadow_next_periodic(fusbh200, &here, | ||
3487 | Q_NEXT_TYPE(fusbh200, *hw_p)); | ||
3488 | } | ||
3489 | |||
3490 | /* how many of the uframe's 125 usecs are allocated? */ | ||
3491 | static unsigned short | ||
3492 | periodic_usecs (struct fusbh200_hcd *fusbh200, unsigned frame, unsigned uframe) | ||
3493 | { | ||
3494 | __hc32 *hw_p = &fusbh200->periodic [frame]; | ||
3495 | union fusbh200_shadow *q = &fusbh200->pshadow [frame]; | ||
3496 | unsigned usecs = 0; | ||
3497 | struct fusbh200_qh_hw *hw; | ||
3498 | |||
3499 | while (q->ptr) { | ||
3500 | switch (hc32_to_cpu(fusbh200, Q_NEXT_TYPE(fusbh200, *hw_p))) { | ||
3501 | case Q_TYPE_QH: | ||
3502 | hw = q->qh->hw; | ||
3503 | /* is it in the S-mask? */ | ||
3504 | if (hw->hw_info2 & cpu_to_hc32(fusbh200, 1 << uframe)) | ||
3505 | usecs += q->qh->usecs; | ||
3506 | /* ... or C-mask? */ | ||
3507 | if (hw->hw_info2 & cpu_to_hc32(fusbh200, | ||
3508 | 1 << (8 + uframe))) | ||
3509 | usecs += q->qh->c_usecs; | ||
3510 | hw_p = &hw->hw_next; | ||
3511 | q = &q->qh->qh_next; | ||
3512 | break; | ||
3513 | // case Q_TYPE_FSTN: | ||
3514 | default: | ||
3515 | /* for "save place" FSTNs, count the relevant INTR | ||
3516 | * bandwidth from the previous frame | ||
3517 | */ | ||
3518 | if (q->fstn->hw_prev != FUSBH200_LIST_END(fusbh200)) { | ||
3519 | fusbh200_dbg (fusbh200, "ignoring FSTN cost ...\n"); | ||
3520 | } | ||
3521 | hw_p = &q->fstn->hw_next; | ||
3522 | q = &q->fstn->fstn_next; | ||
3523 | break; | ||
3524 | case Q_TYPE_ITD: | ||
3525 | if (q->itd->hw_transaction[uframe]) | ||
3526 | usecs += q->itd->stream->usecs; | ||
3527 | hw_p = &q->itd->hw_next; | ||
3528 | q = &q->itd->itd_next; | ||
3529 | break; | ||
3530 | } | ||
3531 | } | ||
3532 | #ifdef DEBUG | ||
3533 | if (usecs > fusbh200->uframe_periodic_max) | ||
3534 | fusbh200_err (fusbh200, "uframe %d sched overrun: %d usecs\n", | ||
3535 | frame * 8 + uframe, usecs); | ||
3536 | #endif | ||
3537 | return usecs; | ||
3538 | } | ||
3539 | |||
3540 | /*-------------------------------------------------------------------------*/ | ||
3541 | |||
3542 | static int same_tt (struct usb_device *dev1, struct usb_device *dev2) | ||
3543 | { | ||
3544 | if (!dev1->tt || !dev2->tt) | ||
3545 | return 0; | ||
3546 | if (dev1->tt != dev2->tt) | ||
3547 | return 0; | ||
3548 | if (dev1->tt->multi) | ||
3549 | return dev1->ttport == dev2->ttport; | ||
3550 | else | ||
3551 | return 1; | ||
3552 | } | ||
3553 | |||
3554 | /* return true iff the device's transaction translator is available | ||
3555 | * for a periodic transfer starting at the specified frame, using | ||
3556 | * all the uframes in the mask. | ||
3557 | */ | ||
3558 | static int tt_no_collision ( | ||
3559 | struct fusbh200_hcd *fusbh200, | ||
3560 | unsigned period, | ||
3561 | struct usb_device *dev, | ||
3562 | unsigned frame, | ||
3563 | u32 uf_mask | ||
3564 | ) | ||
3565 | { | ||
3566 | if (period == 0) /* error */ | ||
3567 | return 0; | ||
3568 | |||
3569 | /* note bandwidth wastage: split never follows csplit | ||
3570 | * (different dev or endpoint) until the next uframe. | ||
3571 | * calling convention doesn't make that distinction. | ||
3572 | */ | ||
3573 | for (; frame < fusbh200->periodic_size; frame += period) { | ||
3574 | union fusbh200_shadow here; | ||
3575 | __hc32 type; | ||
3576 | struct fusbh200_qh_hw *hw; | ||
3577 | |||
3578 | here = fusbh200->pshadow [frame]; | ||
3579 | type = Q_NEXT_TYPE(fusbh200, fusbh200->periodic [frame]); | ||
3580 | while (here.ptr) { | ||
3581 | switch (hc32_to_cpu(fusbh200, type)) { | ||
3582 | case Q_TYPE_ITD: | ||
3583 | type = Q_NEXT_TYPE(fusbh200, here.itd->hw_next); | ||
3584 | here = here.itd->itd_next; | ||
3585 | continue; | ||
3586 | case Q_TYPE_QH: | ||
3587 | hw = here.qh->hw; | ||
3588 | if (same_tt (dev, here.qh->dev)) { | ||
3589 | u32 mask; | ||
3590 | |||
3591 | mask = hc32_to_cpu(fusbh200, | ||
3592 | hw->hw_info2); | ||
3593 | /* "knows" no gap is needed */ | ||
3594 | mask |= mask >> 8; | ||
3595 | if (mask & uf_mask) | ||
3596 | break; | ||
3597 | } | ||
3598 | type = Q_NEXT_TYPE(fusbh200, hw->hw_next); | ||
3599 | here = here.qh->qh_next; | ||
3600 | continue; | ||
3601 | // case Q_TYPE_FSTN: | ||
3602 | default: | ||
3603 | fusbh200_dbg (fusbh200, | ||
3604 | "periodic frame %d bogus type %d\n", | ||
3605 | frame, type); | ||
3606 | } | ||
3607 | |||
3608 | /* collision or error */ | ||
3609 | return 0; | ||
3610 | } | ||
3611 | } | ||
3612 | |||
3613 | /* no collision */ | ||
3614 | return 1; | ||
3615 | } | ||
3616 | |||
3617 | /*-------------------------------------------------------------------------*/ | ||
3618 | |||
3619 | static void enable_periodic(struct fusbh200_hcd *fusbh200) | ||
3620 | { | ||
3621 | if (fusbh200->periodic_count++) | ||
3622 | return; | ||
3623 | |||
3624 | /* Stop waiting to turn off the periodic schedule */ | ||
3625 | fusbh200->enabled_hrtimer_events &= ~BIT(FUSBH200_HRTIMER_DISABLE_PERIODIC); | ||
3626 | |||
3627 | /* Don't start the schedule until PSS is 0 */ | ||
3628 | fusbh200_poll_PSS(fusbh200); | ||
3629 | turn_on_io_watchdog(fusbh200); | ||
3630 | } | ||
3631 | |||
3632 | static void disable_periodic(struct fusbh200_hcd *fusbh200) | ||
3633 | { | ||
3634 | if (--fusbh200->periodic_count) | ||
3635 | return; | ||
3636 | |||
3637 | /* Don't turn off the schedule until PSS is 1 */ | ||
3638 | fusbh200_poll_PSS(fusbh200); | ||
3639 | } | ||
3640 | |||
3641 | /*-------------------------------------------------------------------------*/ | ||
3642 | |||
3643 | /* periodic schedule slots have iso tds (normal or split) first, then a | ||
3644 | * sparse tree for active interrupt transfers. | ||
3645 | * | ||
3646 | * this just links in a qh; caller guarantees uframe masks are set right. | ||
3647 | * no FSTN support (yet; fusbh200 0.96+) | ||
3648 | */ | ||
3649 | static void qh_link_periodic(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh) | ||
3650 | { | ||
3651 | unsigned i; | ||
3652 | unsigned period = qh->period; | ||
3653 | |||
3654 | dev_dbg (&qh->dev->dev, | ||
3655 | "link qh%d-%04x/%p start %d [%d/%d us]\n", | ||
3656 | period, hc32_to_cpup(fusbh200, &qh->hw->hw_info2) | ||
3657 | & (QH_CMASK | QH_SMASK), | ||
3658 | qh, qh->start, qh->usecs, qh->c_usecs); | ||
3659 | |||
3660 | /* high bandwidth, or otherwise every microframe */ | ||
3661 | if (period == 0) | ||
3662 | period = 1; | ||
3663 | |||
3664 | for (i = qh->start; i < fusbh200->periodic_size; i += period) { | ||
3665 | union fusbh200_shadow *prev = &fusbh200->pshadow[i]; | ||
3666 | __hc32 *hw_p = &fusbh200->periodic[i]; | ||
3667 | union fusbh200_shadow here = *prev; | ||
3668 | __hc32 type = 0; | ||
3669 | |||
3670 | /* skip the iso nodes at list head */ | ||
3671 | while (here.ptr) { | ||
3672 | type = Q_NEXT_TYPE(fusbh200, *hw_p); | ||
3673 | if (type == cpu_to_hc32(fusbh200, Q_TYPE_QH)) | ||
3674 | break; | ||
3675 | prev = periodic_next_shadow(fusbh200, prev, type); | ||
3676 | hw_p = shadow_next_periodic(fusbh200, &here, type); | ||
3677 | here = *prev; | ||
3678 | } | ||
3679 | |||
3680 | /* sorting each branch by period (slow-->fast) | ||
3681 | * enables sharing interior tree nodes | ||
3682 | */ | ||
3683 | while (here.ptr && qh != here.qh) { | ||
3684 | if (qh->period > here.qh->period) | ||
3685 | break; | ||
3686 | prev = &here.qh->qh_next; | ||
3687 | hw_p = &here.qh->hw->hw_next; | ||
3688 | here = *prev; | ||
3689 | } | ||
3690 | /* link in this qh, unless some earlier pass did that */ | ||
3691 | if (qh != here.qh) { | ||
3692 | qh->qh_next = here; | ||
3693 | if (here.qh) | ||
3694 | qh->hw->hw_next = *hw_p; | ||
3695 | wmb (); | ||
3696 | prev->qh = qh; | ||
3697 | *hw_p = QH_NEXT (fusbh200, qh->qh_dma); | ||
3698 | } | ||
3699 | } | ||
3700 | qh->qh_state = QH_STATE_LINKED; | ||
3701 | qh->xacterrs = 0; | ||
3702 | |||
3703 | /* update per-qh bandwidth for usbfs */ | ||
3704 | fusbh200_to_hcd(fusbh200)->self.bandwidth_allocated += qh->period | ||
3705 | ? ((qh->usecs + qh->c_usecs) / qh->period) | ||
3706 | : (qh->usecs * 8); | ||
3707 | |||
3708 | list_add(&qh->intr_node, &fusbh200->intr_qh_list); | ||
3709 | |||
3710 | /* maybe enable periodic schedule processing */ | ||
3711 | ++fusbh200->intr_count; | ||
3712 | enable_periodic(fusbh200); | ||
3713 | } | ||
3714 | |||
3715 | static void qh_unlink_periodic(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh) | ||
3716 | { | ||
3717 | unsigned i; | ||
3718 | unsigned period; | ||
3719 | |||
3720 | /* | ||
3721 | * If qh is for a low/full-speed device, simply unlinking it | ||
3722 | * could interfere with an ongoing split transaction. To unlink | ||
3723 | * it safely would require setting the QH_INACTIVATE bit and | ||
3724 | * waiting at least one frame, as described in EHCI 4.12.2.5. | ||
3725 | * | ||
3726 | * We won't bother with any of this. Instead, we assume that the | ||
3727 | * only reason for unlinking an interrupt QH while the current URB | ||
3728 | * is still active is to dequeue all the URBs (flush the whole | ||
3729 | * endpoint queue). | ||
3730 | * | ||
3731 | * If rebalancing the periodic schedule is ever implemented, this | ||
3732 | * approach will no longer be valid. | ||
3733 | */ | ||
3734 | |||
3735 | /* high bandwidth, or otherwise part of every microframe */ | ||
3736 | if ((period = qh->period) == 0) | ||
3737 | period = 1; | ||
3738 | |||
3739 | for (i = qh->start; i < fusbh200->periodic_size; i += period) | ||
3740 | periodic_unlink (fusbh200, i, qh); | ||
3741 | |||
3742 | /* update per-qh bandwidth for usbfs */ | ||
3743 | fusbh200_to_hcd(fusbh200)->self.bandwidth_allocated -= qh->period | ||
3744 | ? ((qh->usecs + qh->c_usecs) / qh->period) | ||
3745 | : (qh->usecs * 8); | ||
3746 | |||
3747 | dev_dbg (&qh->dev->dev, | ||
3748 | "unlink qh%d-%04x/%p start %d [%d/%d us]\n", | ||
3749 | qh->period, | ||
3750 | hc32_to_cpup(fusbh200, &qh->hw->hw_info2) & (QH_CMASK | QH_SMASK), | ||
3751 | qh, qh->start, qh->usecs, qh->c_usecs); | ||
3752 | |||
3753 | /* qh->qh_next still "live" to HC */ | ||
3754 | qh->qh_state = QH_STATE_UNLINK; | ||
3755 | qh->qh_next.ptr = NULL; | ||
3756 | |||
3757 | if (fusbh200->qh_scan_next == qh) | ||
3758 | fusbh200->qh_scan_next = list_entry(qh->intr_node.next, | ||
3759 | struct fusbh200_qh, intr_node); | ||
3760 | list_del(&qh->intr_node); | ||
3761 | } | ||
3762 | |||
3763 | static void start_unlink_intr(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh) | ||
3764 | { | ||
3765 | /* If the QH isn't linked then there's nothing we can do | ||
3766 | * unless we were called during a giveback, in which case | ||
3767 | * qh_completions() has to deal with it. | ||
3768 | */ | ||
3769 | if (qh->qh_state != QH_STATE_LINKED) { | ||
3770 | if (qh->qh_state == QH_STATE_COMPLETING) | ||
3771 | qh->needs_rescan = 1; | ||
3772 | return; | ||
3773 | } | ||
3774 | |||
3775 | qh_unlink_periodic (fusbh200, qh); | ||
3776 | |||
3777 | /* Make sure the unlinks are visible before starting the timer */ | ||
3778 | wmb(); | ||
3779 | |||
3780 | /* | ||
3781 | * The EHCI spec doesn't say how long it takes the controller to | ||
3782 | * stop accessing an unlinked interrupt QH. The timer delay is | ||
3783 | * 9 uframes; presumably that will be long enough. | ||
3784 | */ | ||
3785 | qh->unlink_cycle = fusbh200->intr_unlink_cycle; | ||
3786 | |||
3787 | /* New entries go at the end of the intr_unlink list */ | ||
3788 | if (fusbh200->intr_unlink) | ||
3789 | fusbh200->intr_unlink_last->unlink_next = qh; | ||
3790 | else | ||
3791 | fusbh200->intr_unlink = qh; | ||
3792 | fusbh200->intr_unlink_last = qh; | ||
3793 | |||
3794 | if (fusbh200->intr_unlinking) | ||
3795 | ; /* Avoid recursive calls */ | ||
3796 | else if (fusbh200->rh_state < FUSBH200_RH_RUNNING) | ||
3797 | fusbh200_handle_intr_unlinks(fusbh200); | ||
3798 | else if (fusbh200->intr_unlink == qh) { | ||
3799 | fusbh200_enable_event(fusbh200, FUSBH200_HRTIMER_UNLINK_INTR, true); | ||
3800 | ++fusbh200->intr_unlink_cycle; | ||
3801 | } | ||
3802 | } | ||
3803 | |||
3804 | static void end_unlink_intr(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh) | ||
3805 | { | ||
3806 | struct fusbh200_qh_hw *hw = qh->hw; | ||
3807 | int rc; | ||
3808 | |||
3809 | qh->qh_state = QH_STATE_IDLE; | ||
3810 | hw->hw_next = FUSBH200_LIST_END(fusbh200); | ||
3811 | |||
3812 | qh_completions(fusbh200, qh); | ||
3813 | |||
3814 | /* reschedule QH iff another request is queued */ | ||
3815 | if (!list_empty(&qh->qtd_list) && fusbh200->rh_state == FUSBH200_RH_RUNNING) { | ||
3816 | rc = qh_schedule(fusbh200, qh); | ||
3817 | |||
3818 | /* An error here likely indicates handshake failure | ||
3819 | * or no space left in the schedule. Neither fault | ||
3820 | * should happen often ... | ||
3821 | * | ||
3822 | * FIXME kill the now-dysfunctional queued urbs | ||
3823 | */ | ||
3824 | if (rc != 0) | ||
3825 | fusbh200_err(fusbh200, "can't reschedule qh %p, err %d\n", | ||
3826 | qh, rc); | ||
3827 | } | ||
3828 | |||
3829 | /* maybe turn off periodic schedule */ | ||
3830 | --fusbh200->intr_count; | ||
3831 | disable_periodic(fusbh200); | ||
3832 | } | ||
3833 | |||
3834 | /*-------------------------------------------------------------------------*/ | ||
3835 | |||
3836 | static int check_period ( | ||
3837 | struct fusbh200_hcd *fusbh200, | ||
3838 | unsigned frame, | ||
3839 | unsigned uframe, | ||
3840 | unsigned period, | ||
3841 | unsigned usecs | ||
3842 | ) { | ||
3843 | int claimed; | ||
3844 | |||
3845 | /* complete split running into next frame? | ||
3846 | * given FSTN support, we could sometimes check... | ||
3847 | */ | ||
3848 | if (uframe >= 8) | ||
3849 | return 0; | ||
3850 | |||
3851 | /* convert "usecs we need" to "max already claimed" */ | ||
3852 | usecs = fusbh200->uframe_periodic_max - usecs; | ||
3853 | |||
3854 | /* we "know" 2 and 4 uframe intervals were rejected; so | ||
3855 | * for period 0, check _every_ microframe in the schedule. | ||
3856 | */ | ||
3857 | if (unlikely (period == 0)) { | ||
3858 | do { | ||
3859 | for (uframe = 0; uframe < 7; uframe++) { | ||
3860 | claimed = periodic_usecs (fusbh200, frame, uframe); | ||
3861 | if (claimed > usecs) | ||
3862 | return 0; | ||
3863 | } | ||
3864 | } while ((frame += 1) < fusbh200->periodic_size); | ||
3865 | |||
3866 | /* just check the specified uframe, at that period */ | ||
3867 | } else { | ||
3868 | do { | ||
3869 | claimed = periodic_usecs (fusbh200, frame, uframe); | ||
3870 | if (claimed > usecs) | ||
3871 | return 0; | ||
3872 | } while ((frame += period) < fusbh200->periodic_size); | ||
3873 | } | ||
3874 | |||
3875 | // success! | ||
3876 | return 1; | ||
3877 | } | ||
3878 | |||
3879 | static int check_intr_schedule ( | ||
3880 | struct fusbh200_hcd *fusbh200, | ||
3881 | unsigned frame, | ||
3882 | unsigned uframe, | ||
3883 | const struct fusbh200_qh *qh, | ||
3884 | __hc32 *c_maskp | ||
3885 | ) | ||
3886 | { | ||
3887 | int retval = -ENOSPC; | ||
3888 | u8 mask = 0; | ||
3889 | |||
3890 | if (qh->c_usecs && uframe >= 6) /* FSTN territory? */ | ||
3891 | goto done; | ||
3892 | |||
3893 | if (!check_period (fusbh200, frame, uframe, qh->period, qh->usecs)) | ||
3894 | goto done; | ||
3895 | if (!qh->c_usecs) { | ||
3896 | retval = 0; | ||
3897 | *c_maskp = 0; | ||
3898 | goto done; | ||
3899 | } | ||
3900 | |||
3901 | /* Make sure this tt's buffer is also available for CSPLITs. | ||
3902 | * We pessimize a bit; probably the typical full speed case | ||
3903 | * doesn't need the second CSPLIT. | ||
3904 | * | ||
3905 | * NOTE: both SPLIT and CSPLIT could be checked in just | ||
3906 | * one smart pass... | ||
3907 | */ | ||
3908 | mask = 0x03 << (uframe + qh->gap_uf); | ||
3909 | *c_maskp = cpu_to_hc32(fusbh200, mask << 8); | ||
3910 | |||
3911 | mask |= 1 << uframe; | ||
3912 | if (tt_no_collision (fusbh200, qh->period, qh->dev, frame, mask)) { | ||
3913 | if (!check_period (fusbh200, frame, uframe + qh->gap_uf + 1, | ||
3914 | qh->period, qh->c_usecs)) | ||
3915 | goto done; | ||
3916 | if (!check_period (fusbh200, frame, uframe + qh->gap_uf, | ||
3917 | qh->period, qh->c_usecs)) | ||
3918 | goto done; | ||
3919 | retval = 0; | ||
3920 | } | ||
3921 | done: | ||
3922 | return retval; | ||
3923 | } | ||
3924 | |||
3925 | /* "first fit" scheduling policy used the first time through, | ||
3926 | * or when the previous schedule slot can't be re-used. | ||
3927 | */ | ||
3928 | static int qh_schedule(struct fusbh200_hcd *fusbh200, struct fusbh200_qh *qh) | ||
3929 | { | ||
3930 | int status; | ||
3931 | unsigned uframe; | ||
3932 | __hc32 c_mask; | ||
3933 | unsigned frame; /* 0..(qh->period - 1), or NO_FRAME */ | ||
3934 | struct fusbh200_qh_hw *hw = qh->hw; | ||
3935 | |||
3936 | qh_refresh(fusbh200, qh); | ||
3937 | hw->hw_next = FUSBH200_LIST_END(fusbh200); | ||
3938 | frame = qh->start; | ||
3939 | |||
3940 | /* reuse the previous schedule slots, if we can */ | ||
3941 | if (frame < qh->period) { | ||
3942 | uframe = ffs(hc32_to_cpup(fusbh200, &hw->hw_info2) & QH_SMASK); | ||
3943 | status = check_intr_schedule (fusbh200, frame, --uframe, | ||
3944 | qh, &c_mask); | ||
3945 | } else { | ||
3946 | uframe = 0; | ||
3947 | c_mask = 0; | ||
3948 | status = -ENOSPC; | ||
3949 | } | ||
3950 | |||
3951 | /* else scan the schedule to find a group of slots such that all | ||
3952 | * uframes have enough periodic bandwidth available. | ||
3953 | */ | ||
3954 | if (status) { | ||
3955 | /* "normal" case, uframing flexible except with splits */ | ||
3956 | if (qh->period) { | ||
3957 | int i; | ||
3958 | |||
3959 | for (i = qh->period; status && i > 0; --i) { | ||
3960 | frame = ++fusbh200->random_frame % qh->period; | ||
3961 | for (uframe = 0; uframe < 8; uframe++) { | ||
3962 | status = check_intr_schedule (fusbh200, | ||
3963 | frame, uframe, qh, | ||
3964 | &c_mask); | ||
3965 | if (status == 0) | ||
3966 | break; | ||
3967 | } | ||
3968 | } | ||
3969 | |||
3970 | /* qh->period == 0 means every uframe */ | ||
3971 | } else { | ||
3972 | frame = 0; | ||
3973 | status = check_intr_schedule (fusbh200, 0, 0, qh, &c_mask); | ||
3974 | } | ||
3975 | if (status) | ||
3976 | goto done; | ||
3977 | qh->start = frame; | ||
3978 | |||
3979 | /* reset S-frame and (maybe) C-frame masks */ | ||
3980 | hw->hw_info2 &= cpu_to_hc32(fusbh200, ~(QH_CMASK | QH_SMASK)); | ||
3981 | hw->hw_info2 |= qh->period | ||
3982 | ? cpu_to_hc32(fusbh200, 1 << uframe) | ||
3983 | : cpu_to_hc32(fusbh200, QH_SMASK); | ||
3984 | hw->hw_info2 |= c_mask; | ||
3985 | } else | ||
3986 | fusbh200_dbg (fusbh200, "reused qh %p schedule\n", qh); | ||
3987 | |||
3988 | /* stuff into the periodic schedule */ | ||
3989 | qh_link_periodic(fusbh200, qh); | ||
3990 | done: | ||
3991 | return status; | ||
3992 | } | ||
3993 | |||
3994 | static int intr_submit ( | ||
3995 | struct fusbh200_hcd *fusbh200, | ||
3996 | struct urb *urb, | ||
3997 | struct list_head *qtd_list, | ||
3998 | gfp_t mem_flags | ||
3999 | ) { | ||
4000 | unsigned epnum; | ||
4001 | unsigned long flags; | ||
4002 | struct fusbh200_qh *qh; | ||
4003 | int status; | ||
4004 | struct list_head empty; | ||
4005 | |||
4006 | /* get endpoint and transfer/schedule data */ | ||
4007 | epnum = urb->ep->desc.bEndpointAddress; | ||
4008 | |||
4009 | spin_lock_irqsave (&fusbh200->lock, flags); | ||
4010 | |||
4011 | if (unlikely(!HCD_HW_ACCESSIBLE(fusbh200_to_hcd(fusbh200)))) { | ||
4012 | status = -ESHUTDOWN; | ||
4013 | goto done_not_linked; | ||
4014 | } | ||
4015 | status = usb_hcd_link_urb_to_ep(fusbh200_to_hcd(fusbh200), urb); | ||
4016 | if (unlikely(status)) | ||
4017 | goto done_not_linked; | ||
4018 | |||
4019 | /* get qh and force any scheduling errors */ | ||
4020 | INIT_LIST_HEAD (&empty); | ||
4021 | qh = qh_append_tds(fusbh200, urb, &empty, epnum, &urb->ep->hcpriv); | ||
4022 | if (qh == NULL) { | ||
4023 | status = -ENOMEM; | ||
4024 | goto done; | ||
4025 | } | ||
4026 | if (qh->qh_state == QH_STATE_IDLE) { | ||
4027 | if ((status = qh_schedule (fusbh200, qh)) != 0) | ||
4028 | goto done; | ||
4029 | } | ||
4030 | |||
4031 | /* then queue the urb's tds to the qh */ | ||
4032 | qh = qh_append_tds(fusbh200, urb, qtd_list, epnum, &urb->ep->hcpriv); | ||
4033 | BUG_ON (qh == NULL); | ||
4034 | |||
4035 | /* ... update usbfs periodic stats */ | ||
4036 | fusbh200_to_hcd(fusbh200)->self.bandwidth_int_reqs++; | ||
4037 | |||
4038 | done: | ||
4039 | if (unlikely(status)) | ||
4040 | usb_hcd_unlink_urb_from_ep(fusbh200_to_hcd(fusbh200), urb); | ||
4041 | done_not_linked: | ||
4042 | spin_unlock_irqrestore (&fusbh200->lock, flags); | ||
4043 | if (status) | ||
4044 | qtd_list_free (fusbh200, urb, qtd_list); | ||
4045 | |||
4046 | return status; | ||
4047 | } | ||
4048 | |||
4049 | static void scan_intr(struct fusbh200_hcd *fusbh200) | ||
4050 | { | ||
4051 | struct fusbh200_qh *qh; | ||
4052 | |||
4053 | list_for_each_entry_safe(qh, fusbh200->qh_scan_next, &fusbh200->intr_qh_list, | ||
4054 | intr_node) { | ||
4055 | rescan: | ||
4056 | /* clean any finished work for this qh */ | ||
4057 | if (!list_empty(&qh->qtd_list)) { | ||
4058 | int temp; | ||
4059 | |||
4060 | /* | ||
4061 | * Unlinks could happen here; completion reporting | ||
4062 | * drops the lock. That's why fusbh200->qh_scan_next | ||
4063 | * always holds the next qh to scan; if the next qh | ||
4064 | * gets unlinked then fusbh200->qh_scan_next is adjusted | ||
4065 | * in qh_unlink_periodic(). | ||
4066 | */ | ||
4067 | temp = qh_completions(fusbh200, qh); | ||
4068 | if (unlikely(qh->needs_rescan || | ||
4069 | (list_empty(&qh->qtd_list) && | ||
4070 | qh->qh_state == QH_STATE_LINKED))) | ||
4071 | start_unlink_intr(fusbh200, qh); | ||
4072 | else if (temp != 0) | ||
4073 | goto rescan; | ||
4074 | } | ||
4075 | } | ||
4076 | } | ||
4077 | |||
4078 | /*-------------------------------------------------------------------------*/ | ||
4079 | |||
4080 | /* fusbh200_iso_stream ops work with both ITD and SITD */ | ||
4081 | |||
4082 | static struct fusbh200_iso_stream * | ||
4083 | iso_stream_alloc (gfp_t mem_flags) | ||
4084 | { | ||
4085 | struct fusbh200_iso_stream *stream; | ||
4086 | |||
4087 | stream = kzalloc(sizeof *stream, mem_flags); | ||
4088 | if (likely (stream != NULL)) { | ||
4089 | INIT_LIST_HEAD(&stream->td_list); | ||
4090 | INIT_LIST_HEAD(&stream->free_list); | ||
4091 | stream->next_uframe = -1; | ||
4092 | } | ||
4093 | return stream; | ||
4094 | } | ||
4095 | |||
4096 | static void | ||
4097 | iso_stream_init ( | ||
4098 | struct fusbh200_hcd *fusbh200, | ||
4099 | struct fusbh200_iso_stream *stream, | ||
4100 | struct usb_device *dev, | ||
4101 | int pipe, | ||
4102 | unsigned interval | ||
4103 | ) | ||
4104 | { | ||
4105 | u32 buf1; | ||
4106 | unsigned epnum, maxp; | ||
4107 | int is_input; | ||
4108 | long bandwidth; | ||
4109 | unsigned multi; | ||
4110 | |||
4111 | /* | ||
4112 | * this might be a "high bandwidth" highspeed endpoint, | ||
4113 | * as encoded in the ep descriptor's wMaxPacket field | ||
4114 | */ | ||
4115 | epnum = usb_pipeendpoint (pipe); | ||
4116 | is_input = usb_pipein (pipe) ? USB_DIR_IN : 0; | ||
4117 | maxp = usb_maxpacket(dev, pipe, !is_input); | ||
4118 | if (is_input) { | ||
4119 | buf1 = (1 << 11); | ||
4120 | } else { | ||
4121 | buf1 = 0; | ||
4122 | } | ||
4123 | |||
4124 | maxp = max_packet(maxp); | ||
4125 | multi = hb_mult(maxp); | ||
4126 | buf1 |= maxp; | ||
4127 | maxp *= multi; | ||
4128 | |||
4129 | stream->buf0 = cpu_to_hc32(fusbh200, (epnum << 8) | dev->devnum); | ||
4130 | stream->buf1 = cpu_to_hc32(fusbh200, buf1); | ||
4131 | stream->buf2 = cpu_to_hc32(fusbh200, multi); | ||
4132 | |||
4133 | /* usbfs wants to report the average usecs per frame tied up | ||
4134 | * when transfers on this endpoint are scheduled ... | ||
4135 | */ | ||
4136 | if (dev->speed == USB_SPEED_FULL) { | ||
4137 | interval <<= 3; | ||
4138 | stream->usecs = NS_TO_US(usb_calc_bus_time(dev->speed, | ||
4139 | is_input, 1, maxp)); | ||
4140 | stream->usecs /= 8; | ||
4141 | } else { | ||
4142 | stream->highspeed = 1; | ||
4143 | stream->usecs = HS_USECS_ISO (maxp); | ||
4144 | } | ||
4145 | bandwidth = stream->usecs * 8; | ||
4146 | bandwidth /= interval; | ||
4147 | |||
4148 | stream->bandwidth = bandwidth; | ||
4149 | stream->udev = dev; | ||
4150 | stream->bEndpointAddress = is_input | epnum; | ||
4151 | stream->interval = interval; | ||
4152 | stream->maxp = maxp; | ||
4153 | } | ||
4154 | |||
4155 | static struct fusbh200_iso_stream * | ||
4156 | iso_stream_find (struct fusbh200_hcd *fusbh200, struct urb *urb) | ||
4157 | { | ||
4158 | unsigned epnum; | ||
4159 | struct fusbh200_iso_stream *stream; | ||
4160 | struct usb_host_endpoint *ep; | ||
4161 | unsigned long flags; | ||
4162 | |||
4163 | epnum = usb_pipeendpoint (urb->pipe); | ||
4164 | if (usb_pipein(urb->pipe)) | ||
4165 | ep = urb->dev->ep_in[epnum]; | ||
4166 | else | ||
4167 | ep = urb->dev->ep_out[epnum]; | ||
4168 | |||
4169 | spin_lock_irqsave (&fusbh200->lock, flags); | ||
4170 | stream = ep->hcpriv; | ||
4171 | |||
4172 | if (unlikely (stream == NULL)) { | ||
4173 | stream = iso_stream_alloc(GFP_ATOMIC); | ||
4174 | if (likely (stream != NULL)) { | ||
4175 | ep->hcpriv = stream; | ||
4176 | stream->ep = ep; | ||
4177 | iso_stream_init(fusbh200, stream, urb->dev, urb->pipe, | ||
4178 | urb->interval); | ||
4179 | } | ||
4180 | |||
4181 | /* if dev->ep [epnum] is a QH, hw is set */ | ||
4182 | } else if (unlikely (stream->hw != NULL)) { | ||
4183 | fusbh200_dbg (fusbh200, "dev %s ep%d%s, not iso??\n", | ||
4184 | urb->dev->devpath, epnum, | ||
4185 | usb_pipein(urb->pipe) ? "in" : "out"); | ||
4186 | stream = NULL; | ||
4187 | } | ||
4188 | |||
4189 | spin_unlock_irqrestore (&fusbh200->lock, flags); | ||
4190 | return stream; | ||
4191 | } | ||
4192 | |||
4193 | /*-------------------------------------------------------------------------*/ | ||
4194 | |||
4195 | /* fusbh200_iso_sched ops can be ITD-only or SITD-only */ | ||
4196 | |||
4197 | static struct fusbh200_iso_sched * | ||
4198 | iso_sched_alloc (unsigned packets, gfp_t mem_flags) | ||
4199 | { | ||
4200 | struct fusbh200_iso_sched *iso_sched; | ||
4201 | int size = sizeof *iso_sched; | ||
4202 | |||
4203 | size += packets * sizeof (struct fusbh200_iso_packet); | ||
4204 | iso_sched = kzalloc(size, mem_flags); | ||
4205 | if (likely (iso_sched != NULL)) { | ||
4206 | INIT_LIST_HEAD (&iso_sched->td_list); | ||
4207 | } | ||
4208 | return iso_sched; | ||
4209 | } | ||
4210 | |||
4211 | static inline void | ||
4212 | itd_sched_init( | ||
4213 | struct fusbh200_hcd *fusbh200, | ||
4214 | struct fusbh200_iso_sched *iso_sched, | ||
4215 | struct fusbh200_iso_stream *stream, | ||
4216 | struct urb *urb | ||
4217 | ) | ||
4218 | { | ||
4219 | unsigned i; | ||
4220 | dma_addr_t dma = urb->transfer_dma; | ||
4221 | |||
4222 | /* how many uframes are needed for these transfers */ | ||
4223 | iso_sched->span = urb->number_of_packets * stream->interval; | ||
4224 | |||
4225 | /* figure out per-uframe itd fields that we'll need later | ||
4226 | * when we fit new itds into the schedule. | ||
4227 | */ | ||
4228 | for (i = 0; i < urb->number_of_packets; i++) { | ||
4229 | struct fusbh200_iso_packet *uframe = &iso_sched->packet [i]; | ||
4230 | unsigned length; | ||
4231 | dma_addr_t buf; | ||
4232 | u32 trans; | ||
4233 | |||
4234 | length = urb->iso_frame_desc [i].length; | ||
4235 | buf = dma + urb->iso_frame_desc [i].offset; | ||
4236 | |||
4237 | trans = FUSBH200_ISOC_ACTIVE; | ||
4238 | trans |= buf & 0x0fff; | ||
4239 | if (unlikely (((i + 1) == urb->number_of_packets)) | ||
4240 | && !(urb->transfer_flags & URB_NO_INTERRUPT)) | ||
4241 | trans |= FUSBH200_ITD_IOC; | ||
4242 | trans |= length << 16; | ||
4243 | uframe->transaction = cpu_to_hc32(fusbh200, trans); | ||
4244 | |||
4245 | /* might need to cross a buffer page within a uframe */ | ||
4246 | uframe->bufp = (buf & ~(u64)0x0fff); | ||
4247 | buf += length; | ||
4248 | if (unlikely ((uframe->bufp != (buf & ~(u64)0x0fff)))) | ||
4249 | uframe->cross = 1; | ||
4250 | } | ||
4251 | } | ||
4252 | |||
4253 | static void | ||
4254 | iso_sched_free ( | ||
4255 | struct fusbh200_iso_stream *stream, | ||
4256 | struct fusbh200_iso_sched *iso_sched | ||
4257 | ) | ||
4258 | { | ||
4259 | if (!iso_sched) | ||
4260 | return; | ||
4261 | // caller must hold fusbh200->lock! | ||
4262 | list_splice (&iso_sched->td_list, &stream->free_list); | ||
4263 | kfree (iso_sched); | ||
4264 | } | ||
4265 | |||
4266 | static int | ||
4267 | itd_urb_transaction ( | ||
4268 | struct fusbh200_iso_stream *stream, | ||
4269 | struct fusbh200_hcd *fusbh200, | ||
4270 | struct urb *urb, | ||
4271 | gfp_t mem_flags | ||
4272 | ) | ||
4273 | { | ||
4274 | struct fusbh200_itd *itd; | ||
4275 | dma_addr_t itd_dma; | ||
4276 | int i; | ||
4277 | unsigned num_itds; | ||
4278 | struct fusbh200_iso_sched *sched; | ||
4279 | unsigned long flags; | ||
4280 | |||
4281 | sched = iso_sched_alloc (urb->number_of_packets, mem_flags); | ||
4282 | if (unlikely (sched == NULL)) | ||
4283 | return -ENOMEM; | ||
4284 | |||
4285 | itd_sched_init(fusbh200, sched, stream, urb); | ||
4286 | |||
4287 | if (urb->interval < 8) | ||
4288 | num_itds = 1 + (sched->span + 7) / 8; | ||
4289 | else | ||
4290 | num_itds = urb->number_of_packets; | ||
4291 | |||
4292 | /* allocate/init ITDs */ | ||
4293 | spin_lock_irqsave (&fusbh200->lock, flags); | ||
4294 | for (i = 0; i < num_itds; i++) { | ||
4295 | |||
4296 | /* | ||
4297 | * Use iTDs from the free list, but not iTDs that may | ||
4298 | * still be in use by the hardware. | ||
4299 | */ | ||
4300 | if (likely(!list_empty(&stream->free_list))) { | ||
4301 | itd = list_first_entry(&stream->free_list, | ||
4302 | struct fusbh200_itd, itd_list); | ||
4303 | if (itd->frame == fusbh200->now_frame) | ||
4304 | goto alloc_itd; | ||
4305 | list_del (&itd->itd_list); | ||
4306 | itd_dma = itd->itd_dma; | ||
4307 | } else { | ||
4308 | alloc_itd: | ||
4309 | spin_unlock_irqrestore (&fusbh200->lock, flags); | ||
4310 | itd = dma_pool_alloc (fusbh200->itd_pool, mem_flags, | ||
4311 | &itd_dma); | ||
4312 | spin_lock_irqsave (&fusbh200->lock, flags); | ||
4313 | if (!itd) { | ||
4314 | iso_sched_free(stream, sched); | ||
4315 | spin_unlock_irqrestore(&fusbh200->lock, flags); | ||
4316 | return -ENOMEM; | ||
4317 | } | ||
4318 | } | ||
4319 | |||
4320 | memset (itd, 0, sizeof *itd); | ||
4321 | itd->itd_dma = itd_dma; | ||
4322 | list_add (&itd->itd_list, &sched->td_list); | ||
4323 | } | ||
4324 | spin_unlock_irqrestore (&fusbh200->lock, flags); | ||
4325 | |||
4326 | /* temporarily store schedule info in hcpriv */ | ||
4327 | urb->hcpriv = sched; | ||
4328 | urb->error_count = 0; | ||
4329 | return 0; | ||
4330 | } | ||
4331 | |||
4332 | /*-------------------------------------------------------------------------*/ | ||
4333 | |||
4334 | static inline int | ||
4335 | itd_slot_ok ( | ||
4336 | struct fusbh200_hcd *fusbh200, | ||
4337 | u32 mod, | ||
4338 | u32 uframe, | ||
4339 | u8 usecs, | ||
4340 | u32 period | ||
4341 | ) | ||
4342 | { | ||
4343 | uframe %= period; | ||
4344 | do { | ||
4345 | /* can't commit more than uframe_periodic_max usec */ | ||
4346 | if (periodic_usecs (fusbh200, uframe >> 3, uframe & 0x7) | ||
4347 | > (fusbh200->uframe_periodic_max - usecs)) | ||
4348 | return 0; | ||
4349 | |||
4350 | /* we know urb->interval is 2^N uframes */ | ||
4351 | uframe += period; | ||
4352 | } while (uframe < mod); | ||
4353 | return 1; | ||
4354 | } | ||
4355 | |||
4356 | /* | ||
4357 | * This scheduler plans almost as far into the future as it has actual | ||
4358 | * periodic schedule slots. (Affected by TUNE_FLS, which defaults to | ||
4359 | * "as small as possible" to be cache-friendlier.) That limits the size | ||
4360 | * transfers you can stream reliably; avoid more than 64 msec per urb. | ||
4361 | * Also avoid queue depths of less than fusbh200's worst irq latency (affected | ||
4362 | * by the per-urb URB_NO_INTERRUPT hint, the log2_irq_thresh module parameter, | ||
4363 | * and other factors); or more than about 230 msec total (for portability, | ||
4364 | * given FUSBH200_TUNE_FLS and the slop). Or, write a smarter scheduler! | ||
4365 | */ | ||
4366 | |||
4367 | #define SCHEDULE_SLOP 80 /* microframes */ | ||
4368 | |||
4369 | static int | ||
4370 | iso_stream_schedule ( | ||
4371 | struct fusbh200_hcd *fusbh200, | ||
4372 | struct urb *urb, | ||
4373 | struct fusbh200_iso_stream *stream | ||
4374 | ) | ||
4375 | { | ||
4376 | u32 now, next, start, period, span; | ||
4377 | int status; | ||
4378 | unsigned mod = fusbh200->periodic_size << 3; | ||
4379 | struct fusbh200_iso_sched *sched = urb->hcpriv; | ||
4380 | |||
4381 | period = urb->interval; | ||
4382 | span = sched->span; | ||
4383 | |||
4384 | if (span > mod - SCHEDULE_SLOP) { | ||
4385 | fusbh200_dbg (fusbh200, "iso request %p too long\n", urb); | ||
4386 | status = -EFBIG; | ||
4387 | goto fail; | ||
4388 | } | ||
4389 | |||
4390 | now = fusbh200_read_frame_index(fusbh200) & (mod - 1); | ||
4391 | |||
4392 | /* Typical case: reuse current schedule, stream is still active. | ||
4393 | * Hopefully there are no gaps from the host falling behind | ||
4394 | * (irq delays etc), but if there are we'll take the next | ||
4395 | * slot in the schedule, implicitly assuming URB_ISO_ASAP. | ||
4396 | */ | ||
4397 | if (likely (!list_empty (&stream->td_list))) { | ||
4398 | u32 excess; | ||
4399 | |||
4400 | /* For high speed devices, allow scheduling within the | ||
4401 | * isochronous scheduling threshold. For full speed devices | ||
4402 | * and Intel PCI-based controllers, don't (work around for | ||
4403 | * Intel ICH9 bug). | ||
4404 | */ | ||
4405 | if (!stream->highspeed && fusbh200->fs_i_thresh) | ||
4406 | next = now + fusbh200->i_thresh; | ||
4407 | else | ||
4408 | next = now; | ||
4409 | |||
4410 | /* Fell behind (by up to twice the slop amount)? | ||
4411 | * We decide based on the time of the last currently-scheduled | ||
4412 | * slot, not the time of the next available slot. | ||
4413 | */ | ||
4414 | excess = (stream->next_uframe - period - next) & (mod - 1); | ||
4415 | if (excess >= mod - 2 * SCHEDULE_SLOP) | ||
4416 | start = next + excess - mod + period * | ||
4417 | DIV_ROUND_UP(mod - excess, period); | ||
4418 | else | ||
4419 | start = next + excess + period; | ||
4420 | if (start - now >= mod) { | ||
4421 | fusbh200_dbg(fusbh200, "request %p would overflow (%d+%d >= %d)\n", | ||
4422 | urb, start - now - period, period, | ||
4423 | mod); | ||
4424 | status = -EFBIG; | ||
4425 | goto fail; | ||
4426 | } | ||
4427 | } | ||
4428 | |||
4429 | /* need to schedule; when's the next (u)frame we could start? | ||
4430 | * this is bigger than fusbh200->i_thresh allows; scheduling itself | ||
4431 | * isn't free, the slop should handle reasonably slow cpus. it | ||
4432 | * can also help high bandwidth if the dma and irq loads don't | ||
4433 | * jump until after the queue is primed. | ||
4434 | */ | ||
4435 | else { | ||
4436 | int done = 0; | ||
4437 | start = SCHEDULE_SLOP + (now & ~0x07); | ||
4438 | |||
4439 | /* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */ | ||
4440 | |||
4441 | /* find a uframe slot with enough bandwidth. | ||
4442 | * Early uframes are more precious because full-speed | ||
4443 | * iso IN transfers can't use late uframes, | ||
4444 | * and therefore they should be allocated last. | ||
4445 | */ | ||
4446 | next = start; | ||
4447 | start += period; | ||
4448 | do { | ||
4449 | start--; | ||
4450 | /* check schedule: enough space? */ | ||
4451 | if (itd_slot_ok(fusbh200, mod, start, | ||
4452 | stream->usecs, period)) | ||
4453 | done = 1; | ||
4454 | } while (start > next && !done); | ||
4455 | |||
4456 | /* no room in the schedule */ | ||
4457 | if (!done) { | ||
4458 | fusbh200_dbg(fusbh200, "iso resched full %p (now %d max %d)\n", | ||
4459 | urb, now, now + mod); | ||
4460 | status = -ENOSPC; | ||
4461 | goto fail; | ||
4462 | } | ||
4463 | } | ||
4464 | |||
4465 | /* Tried to schedule too far into the future? */ | ||
4466 | if (unlikely(start - now + span - period | ||
4467 | >= mod - 2 * SCHEDULE_SLOP)) { | ||
4468 | fusbh200_dbg(fusbh200, "request %p would overflow (%d+%d >= %d)\n", | ||
4469 | urb, start - now, span - period, | ||
4470 | mod - 2 * SCHEDULE_SLOP); | ||
4471 | status = -EFBIG; | ||
4472 | goto fail; | ||
4473 | } | ||
4474 | |||
4475 | stream->next_uframe = start & (mod - 1); | ||
4476 | |||
4477 | /* report high speed start in uframes; full speed, in frames */ | ||
4478 | urb->start_frame = stream->next_uframe; | ||
4479 | if (!stream->highspeed) | ||
4480 | urb->start_frame >>= 3; | ||
4481 | |||
4482 | /* Make sure scan_isoc() sees these */ | ||
4483 | if (fusbh200->isoc_count == 0) | ||
4484 | fusbh200->next_frame = now >> 3; | ||
4485 | return 0; | ||
4486 | |||
4487 | fail: | ||
4488 | iso_sched_free(stream, sched); | ||
4489 | urb->hcpriv = NULL; | ||
4490 | return status; | ||
4491 | } | ||
4492 | |||
4493 | /*-------------------------------------------------------------------------*/ | ||
4494 | |||
4495 | static inline void | ||
4496 | itd_init(struct fusbh200_hcd *fusbh200, struct fusbh200_iso_stream *stream, | ||
4497 | struct fusbh200_itd *itd) | ||
4498 | { | ||
4499 | int i; | ||
4500 | |||
4501 | /* it's been recently zeroed */ | ||
4502 | itd->hw_next = FUSBH200_LIST_END(fusbh200); | ||
4503 | itd->hw_bufp [0] = stream->buf0; | ||
4504 | itd->hw_bufp [1] = stream->buf1; | ||
4505 | itd->hw_bufp [2] = stream->buf2; | ||
4506 | |||
4507 | for (i = 0; i < 8; i++) | ||
4508 | itd->index[i] = -1; | ||
4509 | |||
4510 | /* All other fields are filled when scheduling */ | ||
4511 | } | ||
4512 | |||
4513 | static inline void | ||
4514 | itd_patch( | ||
4515 | struct fusbh200_hcd *fusbh200, | ||
4516 | struct fusbh200_itd *itd, | ||
4517 | struct fusbh200_iso_sched *iso_sched, | ||
4518 | unsigned index, | ||
4519 | u16 uframe | ||
4520 | ) | ||
4521 | { | ||
4522 | struct fusbh200_iso_packet *uf = &iso_sched->packet [index]; | ||
4523 | unsigned pg = itd->pg; | ||
4524 | |||
4525 | // BUG_ON (pg == 6 && uf->cross); | ||
4526 | |||
4527 | uframe &= 0x07; | ||
4528 | itd->index [uframe] = index; | ||
4529 | |||
4530 | itd->hw_transaction[uframe] = uf->transaction; | ||
4531 | itd->hw_transaction[uframe] |= cpu_to_hc32(fusbh200, pg << 12); | ||
4532 | itd->hw_bufp[pg] |= cpu_to_hc32(fusbh200, uf->bufp & ~(u32)0); | ||
4533 | itd->hw_bufp_hi[pg] |= cpu_to_hc32(fusbh200, (u32)(uf->bufp >> 32)); | ||
4534 | |||
4535 | /* iso_frame_desc[].offset must be strictly increasing */ | ||
4536 | if (unlikely (uf->cross)) { | ||
4537 | u64 bufp = uf->bufp + 4096; | ||
4538 | |||
4539 | itd->pg = ++pg; | ||
4540 | itd->hw_bufp[pg] |= cpu_to_hc32(fusbh200, bufp & ~(u32)0); | ||
4541 | itd->hw_bufp_hi[pg] |= cpu_to_hc32(fusbh200, (u32)(bufp >> 32)); | ||
4542 | } | ||
4543 | } | ||
4544 | |||
4545 | static inline void | ||
4546 | itd_link (struct fusbh200_hcd *fusbh200, unsigned frame, struct fusbh200_itd *itd) | ||
4547 | { | ||
4548 | union fusbh200_shadow *prev = &fusbh200->pshadow[frame]; | ||
4549 | __hc32 *hw_p = &fusbh200->periodic[frame]; | ||
4550 | union fusbh200_shadow here = *prev; | ||
4551 | __hc32 type = 0; | ||
4552 | |||
4553 | /* skip any iso nodes which might belong to previous microframes */ | ||
4554 | while (here.ptr) { | ||
4555 | type = Q_NEXT_TYPE(fusbh200, *hw_p); | ||
4556 | if (type == cpu_to_hc32(fusbh200, Q_TYPE_QH)) | ||
4557 | break; | ||
4558 | prev = periodic_next_shadow(fusbh200, prev, type); | ||
4559 | hw_p = shadow_next_periodic(fusbh200, &here, type); | ||
4560 | here = *prev; | ||
4561 | } | ||
4562 | |||
4563 | itd->itd_next = here; | ||
4564 | itd->hw_next = *hw_p; | ||
4565 | prev->itd = itd; | ||
4566 | itd->frame = frame; | ||
4567 | wmb (); | ||
4568 | *hw_p = cpu_to_hc32(fusbh200, itd->itd_dma | Q_TYPE_ITD); | ||
4569 | } | ||
4570 | |||
4571 | /* fit urb's itds into the selected schedule slot; activate as needed */ | ||
4572 | static void itd_link_urb( | ||
4573 | struct fusbh200_hcd *fusbh200, | ||
4574 | struct urb *urb, | ||
4575 | unsigned mod, | ||
4576 | struct fusbh200_iso_stream *stream | ||
4577 | ) | ||
4578 | { | ||
4579 | int packet; | ||
4580 | unsigned next_uframe, uframe, frame; | ||
4581 | struct fusbh200_iso_sched *iso_sched = urb->hcpriv; | ||
4582 | struct fusbh200_itd *itd; | ||
4583 | |||
4584 | next_uframe = stream->next_uframe & (mod - 1); | ||
4585 | |||
4586 | if (unlikely (list_empty(&stream->td_list))) { | ||
4587 | fusbh200_to_hcd(fusbh200)->self.bandwidth_allocated | ||
4588 | += stream->bandwidth; | ||
4589 | fusbh200_vdbg (fusbh200, | ||
4590 | "schedule devp %s ep%d%s-iso period %d start %d.%d\n", | ||
4591 | urb->dev->devpath, stream->bEndpointAddress & 0x0f, | ||
4592 | (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out", | ||
4593 | urb->interval, | ||
4594 | next_uframe >> 3, next_uframe & 0x7); | ||
4595 | } | ||
4596 | |||
4597 | /* fill iTDs uframe by uframe */ | ||
4598 | for (packet = 0, itd = NULL; packet < urb->number_of_packets; ) { | ||
4599 | if (itd == NULL) { | ||
4600 | /* ASSERT: we have all necessary itds */ | ||
4601 | // BUG_ON (list_empty (&iso_sched->td_list)); | ||
4602 | |||
4603 | /* ASSERT: no itds for this endpoint in this uframe */ | ||
4604 | |||
4605 | itd = list_entry (iso_sched->td_list.next, | ||
4606 | struct fusbh200_itd, itd_list); | ||
4607 | list_move_tail (&itd->itd_list, &stream->td_list); | ||
4608 | itd->stream = stream; | ||
4609 | itd->urb = urb; | ||
4610 | itd_init (fusbh200, stream, itd); | ||
4611 | } | ||
4612 | |||
4613 | uframe = next_uframe & 0x07; | ||
4614 | frame = next_uframe >> 3; | ||
4615 | |||
4616 | itd_patch(fusbh200, itd, iso_sched, packet, uframe); | ||
4617 | |||
4618 | next_uframe += stream->interval; | ||
4619 | next_uframe &= mod - 1; | ||
4620 | packet++; | ||
4621 | |||
4622 | /* link completed itds into the schedule */ | ||
4623 | if (((next_uframe >> 3) != frame) | ||
4624 | || packet == urb->number_of_packets) { | ||
4625 | itd_link(fusbh200, frame & (fusbh200->periodic_size - 1), itd); | ||
4626 | itd = NULL; | ||
4627 | } | ||
4628 | } | ||
4629 | stream->next_uframe = next_uframe; | ||
4630 | |||
4631 | /* don't need that schedule data any more */ | ||
4632 | iso_sched_free (stream, iso_sched); | ||
4633 | urb->hcpriv = NULL; | ||
4634 | |||
4635 | ++fusbh200->isoc_count; | ||
4636 | enable_periodic(fusbh200); | ||
4637 | } | ||
4638 | |||
4639 | #define ISO_ERRS (FUSBH200_ISOC_BUF_ERR | FUSBH200_ISOC_BABBLE | FUSBH200_ISOC_XACTERR) | ||
4640 | |||
4641 | /* Process and recycle a completed ITD. Return true iff its urb completed, | ||
4642 | * and hence its completion callback probably added things to the hardware | ||
4643 | * schedule. | ||
4644 | * | ||
4645 | * Note that we carefully avoid recycling this descriptor until after any | ||
4646 | * completion callback runs, so that it won't be reused quickly. That is, | ||
4647 | * assuming (a) no more than two urbs per frame on this endpoint, and also | ||
4648 | * (b) only this endpoint's completions submit URBs. It seems some silicon | ||
4649 | * corrupts things if you reuse completed descriptors very quickly... | ||
4650 | */ | ||
4651 | static bool itd_complete(struct fusbh200_hcd *fusbh200, struct fusbh200_itd *itd) | ||
4652 | { | ||
4653 | struct urb *urb = itd->urb; | ||
4654 | struct usb_iso_packet_descriptor *desc; | ||
4655 | u32 t; | ||
4656 | unsigned uframe; | ||
4657 | int urb_index = -1; | ||
4658 | struct fusbh200_iso_stream *stream = itd->stream; | ||
4659 | struct usb_device *dev; | ||
4660 | bool retval = false; | ||
4661 | |||
4662 | /* for each uframe with a packet */ | ||
4663 | for (uframe = 0; uframe < 8; uframe++) { | ||
4664 | if (likely (itd->index[uframe] == -1)) | ||
4665 | continue; | ||
4666 | urb_index = itd->index[uframe]; | ||
4667 | desc = &urb->iso_frame_desc [urb_index]; | ||
4668 | |||
4669 | t = hc32_to_cpup(fusbh200, &itd->hw_transaction [uframe]); | ||
4670 | itd->hw_transaction [uframe] = 0; | ||
4671 | |||
4672 | /* report transfer status */ | ||
4673 | if (unlikely (t & ISO_ERRS)) { | ||
4674 | urb->error_count++; | ||
4675 | if (t & FUSBH200_ISOC_BUF_ERR) | ||
4676 | desc->status = usb_pipein (urb->pipe) | ||
4677 | ? -ENOSR /* hc couldn't read */ | ||
4678 | : -ECOMM; /* hc couldn't write */ | ||
4679 | else if (t & FUSBH200_ISOC_BABBLE) | ||
4680 | desc->status = -EOVERFLOW; | ||
4681 | else /* (t & FUSBH200_ISOC_XACTERR) */ | ||
4682 | desc->status = -EPROTO; | ||
4683 | |||
4684 | /* HC need not update length with this error */ | ||
4685 | if (!(t & FUSBH200_ISOC_BABBLE)) { | ||
4686 | desc->actual_length = fusbh200_itdlen(urb, desc, t); | ||
4687 | urb->actual_length += desc->actual_length; | ||
4688 | } | ||
4689 | } else if (likely ((t & FUSBH200_ISOC_ACTIVE) == 0)) { | ||
4690 | desc->status = 0; | ||
4691 | desc->actual_length = fusbh200_itdlen(urb, desc, t); | ||
4692 | urb->actual_length += desc->actual_length; | ||
4693 | } else { | ||
4694 | /* URB was too late */ | ||
4695 | desc->status = -EXDEV; | ||
4696 | } | ||
4697 | } | ||
4698 | |||
4699 | /* handle completion now? */ | ||
4700 | if (likely ((urb_index + 1) != urb->number_of_packets)) | ||
4701 | goto done; | ||
4702 | |||
4703 | /* ASSERT: it's really the last itd for this urb | ||
4704 | list_for_each_entry (itd, &stream->td_list, itd_list) | ||
4705 | BUG_ON (itd->urb == urb); | ||
4706 | */ | ||
4707 | |||
4708 | /* give urb back to the driver; completion often (re)submits */ | ||
4709 | dev = urb->dev; | ||
4710 | fusbh200_urb_done(fusbh200, urb, 0); | ||
4711 | retval = true; | ||
4712 | urb = NULL; | ||
4713 | |||
4714 | --fusbh200->isoc_count; | ||
4715 | disable_periodic(fusbh200); | ||
4716 | |||
4717 | if (unlikely(list_is_singular(&stream->td_list))) { | ||
4718 | fusbh200_to_hcd(fusbh200)->self.bandwidth_allocated | ||
4719 | -= stream->bandwidth; | ||
4720 | fusbh200_vdbg (fusbh200, | ||
4721 | "deschedule devp %s ep%d%s-iso\n", | ||
4722 | dev->devpath, stream->bEndpointAddress & 0x0f, | ||
4723 | (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); | ||
4724 | } | ||
4725 | |||
4726 | done: | ||
4727 | itd->urb = NULL; | ||
4728 | |||
4729 | /* Add to the end of the free list for later reuse */ | ||
4730 | list_move_tail(&itd->itd_list, &stream->free_list); | ||
4731 | |||
4732 | /* Recycle the iTDs when the pipeline is empty (ep no longer in use) */ | ||
4733 | if (list_empty(&stream->td_list)) { | ||
4734 | list_splice_tail_init(&stream->free_list, | ||
4735 | &fusbh200->cached_itd_list); | ||
4736 | start_free_itds(fusbh200); | ||
4737 | } | ||
4738 | |||
4739 | return retval; | ||
4740 | } | ||
4741 | |||
4742 | /*-------------------------------------------------------------------------*/ | ||
4743 | |||
4744 | static int itd_submit (struct fusbh200_hcd *fusbh200, struct urb *urb, | ||
4745 | gfp_t mem_flags) | ||
4746 | { | ||
4747 | int status = -EINVAL; | ||
4748 | unsigned long flags; | ||
4749 | struct fusbh200_iso_stream *stream; | ||
4750 | |||
4751 | /* Get iso_stream head */ | ||
4752 | stream = iso_stream_find (fusbh200, urb); | ||
4753 | if (unlikely (stream == NULL)) { | ||
4754 | fusbh200_dbg (fusbh200, "can't get iso stream\n"); | ||
4755 | return -ENOMEM; | ||
4756 | } | ||
4757 | if (unlikely (urb->interval != stream->interval && | ||
4758 | fusbh200_port_speed(fusbh200, 0) == USB_PORT_STAT_HIGH_SPEED)) { | ||
4759 | fusbh200_dbg (fusbh200, "can't change iso interval %d --> %d\n", | ||
4760 | stream->interval, urb->interval); | ||
4761 | goto done; | ||
4762 | } | ||
4763 | |||
4764 | #ifdef FUSBH200_URB_TRACE | ||
4765 | fusbh200_dbg (fusbh200, | ||
4766 | "%s %s urb %p ep%d%s len %d, %d pkts %d uframes [%p]\n", | ||
4767 | __func__, urb->dev->devpath, urb, | ||
4768 | usb_pipeendpoint (urb->pipe), | ||
4769 | usb_pipein (urb->pipe) ? "in" : "out", | ||
4770 | urb->transfer_buffer_length, | ||
4771 | urb->number_of_packets, urb->interval, | ||
4772 | stream); | ||
4773 | #endif | ||
4774 | |||
4775 | /* allocate ITDs w/o locking anything */ | ||
4776 | status = itd_urb_transaction (stream, fusbh200, urb, mem_flags); | ||
4777 | if (unlikely (status < 0)) { | ||
4778 | fusbh200_dbg (fusbh200, "can't init itds\n"); | ||
4779 | goto done; | ||
4780 | } | ||
4781 | |||
4782 | /* schedule ... need to lock */ | ||
4783 | spin_lock_irqsave (&fusbh200->lock, flags); | ||
4784 | if (unlikely(!HCD_HW_ACCESSIBLE(fusbh200_to_hcd(fusbh200)))) { | ||
4785 | status = -ESHUTDOWN; | ||
4786 | goto done_not_linked; | ||
4787 | } | ||
4788 | status = usb_hcd_link_urb_to_ep(fusbh200_to_hcd(fusbh200), urb); | ||
4789 | if (unlikely(status)) | ||
4790 | goto done_not_linked; | ||
4791 | status = iso_stream_schedule(fusbh200, urb, stream); | ||
4792 | if (likely (status == 0)) | ||
4793 | itd_link_urb (fusbh200, urb, fusbh200->periodic_size << 3, stream); | ||
4794 | else | ||
4795 | usb_hcd_unlink_urb_from_ep(fusbh200_to_hcd(fusbh200), urb); | ||
4796 | done_not_linked: | ||
4797 | spin_unlock_irqrestore (&fusbh200->lock, flags); | ||
4798 | done: | ||
4799 | return status; | ||
4800 | } | ||
4801 | |||
4802 | /*-------------------------------------------------------------------------*/ | ||
4803 | |||
4804 | static void scan_isoc(struct fusbh200_hcd *fusbh200) | ||
4805 | { | ||
4806 | unsigned uf, now_frame, frame; | ||
4807 | unsigned fmask = fusbh200->periodic_size - 1; | ||
4808 | bool modified, live; | ||
4809 | |||
4810 | /* | ||
4811 | * When running, scan from last scan point up to "now" | ||
4812 | * else clean up by scanning everything that's left. | ||
4813 | * Touches as few pages as possible: cache-friendly. | ||
4814 | */ | ||
4815 | if (fusbh200->rh_state >= FUSBH200_RH_RUNNING) { | ||
4816 | uf = fusbh200_read_frame_index(fusbh200); | ||
4817 | now_frame = (uf >> 3) & fmask; | ||
4818 | live = true; | ||
4819 | } else { | ||
4820 | now_frame = (fusbh200->next_frame - 1) & fmask; | ||
4821 | live = false; | ||
4822 | } | ||
4823 | fusbh200->now_frame = now_frame; | ||
4824 | |||
4825 | frame = fusbh200->next_frame; | ||
4826 | for (;;) { | ||
4827 | union fusbh200_shadow q, *q_p; | ||
4828 | __hc32 type, *hw_p; | ||
4829 | |||
4830 | restart: | ||
4831 | /* scan each element in frame's queue for completions */ | ||
4832 | q_p = &fusbh200->pshadow [frame]; | ||
4833 | hw_p = &fusbh200->periodic [frame]; | ||
4834 | q.ptr = q_p->ptr; | ||
4835 | type = Q_NEXT_TYPE(fusbh200, *hw_p); | ||
4836 | modified = false; | ||
4837 | |||
4838 | while (q.ptr != NULL) { | ||
4839 | switch (hc32_to_cpu(fusbh200, type)) { | ||
4840 | case Q_TYPE_ITD: | ||
4841 | /* If this ITD is still active, leave it for | ||
4842 | * later processing ... check the next entry. | ||
4843 | * No need to check for activity unless the | ||
4844 | * frame is current. | ||
4845 | */ | ||
4846 | if (frame == now_frame && live) { | ||
4847 | rmb(); | ||
4848 | for (uf = 0; uf < 8; uf++) { | ||
4849 | if (q.itd->hw_transaction[uf] & | ||
4850 | ITD_ACTIVE(fusbh200)) | ||
4851 | break; | ||
4852 | } | ||
4853 | if (uf < 8) { | ||
4854 | q_p = &q.itd->itd_next; | ||
4855 | hw_p = &q.itd->hw_next; | ||
4856 | type = Q_NEXT_TYPE(fusbh200, | ||
4857 | q.itd->hw_next); | ||
4858 | q = *q_p; | ||
4859 | break; | ||
4860 | } | ||
4861 | } | ||
4862 | |||
4863 | /* Take finished ITDs out of the schedule | ||
4864 | * and process them: recycle, maybe report | ||
4865 | * URB completion. HC won't cache the | ||
4866 | * pointer for much longer, if at all. | ||
4867 | */ | ||
4868 | *q_p = q.itd->itd_next; | ||
4869 | *hw_p = q.itd->hw_next; | ||
4870 | type = Q_NEXT_TYPE(fusbh200, q.itd->hw_next); | ||
4871 | wmb(); | ||
4872 | modified = itd_complete (fusbh200, q.itd); | ||
4873 | q = *q_p; | ||
4874 | break; | ||
4875 | default: | ||
4876 | fusbh200_dbg(fusbh200, "corrupt type %d frame %d shadow %p\n", | ||
4877 | type, frame, q.ptr); | ||
4878 | // BUG (); | ||
4879 | /* FALL THROUGH */ | ||
4880 | case Q_TYPE_QH: | ||
4881 | case Q_TYPE_FSTN: | ||
4882 | /* End of the iTDs and siTDs */ | ||
4883 | q.ptr = NULL; | ||
4884 | break; | ||
4885 | } | ||
4886 | |||
4887 | /* assume completion callbacks modify the queue */ | ||
4888 | if (unlikely(modified && fusbh200->isoc_count > 0)) | ||
4889 | goto restart; | ||
4890 | } | ||
4891 | |||
4892 | /* Stop when we have reached the current frame */ | ||
4893 | if (frame == now_frame) | ||
4894 | break; | ||
4895 | frame = (frame + 1) & fmask; | ||
4896 | } | ||
4897 | fusbh200->next_frame = now_frame; | ||
4898 | } | ||
4899 | /*-------------------------------------------------------------------------*/ | ||
4900 | /* | ||
4901 | * Display / Set uframe_periodic_max | ||
4902 | */ | ||
4903 | static ssize_t show_uframe_periodic_max(struct device *dev, | ||
4904 | struct device_attribute *attr, | ||
4905 | char *buf) | ||
4906 | { | ||
4907 | struct fusbh200_hcd *fusbh200; | ||
4908 | int n; | ||
4909 | |||
4910 | fusbh200 = hcd_to_fusbh200(bus_to_hcd(dev_get_drvdata(dev))); | ||
4911 | n = scnprintf(buf, PAGE_SIZE, "%d\n", fusbh200->uframe_periodic_max); | ||
4912 | return n; | ||
4913 | } | ||
4914 | |||
4915 | |||
4916 | static ssize_t store_uframe_periodic_max(struct device *dev, | ||
4917 | struct device_attribute *attr, | ||
4918 | const char *buf, size_t count) | ||
4919 | { | ||
4920 | struct fusbh200_hcd *fusbh200; | ||
4921 | unsigned uframe_periodic_max; | ||
4922 | unsigned frame, uframe; | ||
4923 | unsigned short allocated_max; | ||
4924 | unsigned long flags; | ||
4925 | ssize_t ret; | ||
4926 | |||
4927 | fusbh200 = hcd_to_fusbh200(bus_to_hcd(dev_get_drvdata(dev))); | ||
4928 | if (kstrtouint(buf, 0, &uframe_periodic_max) < 0) | ||
4929 | return -EINVAL; | ||
4930 | |||
4931 | if (uframe_periodic_max < 100 || uframe_periodic_max >= 125) { | ||
4932 | fusbh200_info(fusbh200, "rejecting invalid request for " | ||
4933 | "uframe_periodic_max=%u\n", uframe_periodic_max); | ||
4934 | return -EINVAL; | ||
4935 | } | ||
4936 | |||
4937 | ret = -EINVAL; | ||
4938 | |||
4939 | /* | ||
4940 | * lock, so that our checking does not race with possible periodic | ||
4941 | * bandwidth allocation through submitting new urbs. | ||
4942 | */ | ||
4943 | spin_lock_irqsave (&fusbh200->lock, flags); | ||
4944 | |||
4945 | /* | ||
4946 | * for request to decrease max periodic bandwidth, we have to check | ||
4947 | * every microframe in the schedule to see whether the decrease is | ||
4948 | * possible. | ||
4949 | */ | ||
4950 | if (uframe_periodic_max < fusbh200->uframe_periodic_max) { | ||
4951 | allocated_max = 0; | ||
4952 | |||
4953 | for (frame = 0; frame < fusbh200->periodic_size; ++frame) | ||
4954 | for (uframe = 0; uframe < 7; ++uframe) | ||
4955 | allocated_max = max(allocated_max, | ||
4956 | periodic_usecs (fusbh200, frame, uframe)); | ||
4957 | |||
4958 | if (allocated_max > uframe_periodic_max) { | ||
4959 | fusbh200_info(fusbh200, | ||
4960 | "cannot decrease uframe_periodic_max becase " | ||
4961 | "periodic bandwidth is already allocated " | ||
4962 | "(%u > %u)\n", | ||
4963 | allocated_max, uframe_periodic_max); | ||
4964 | goto out_unlock; | ||
4965 | } | ||
4966 | } | ||
4967 | |||
4968 | /* increasing is always ok */ | ||
4969 | |||
4970 | fusbh200_info(fusbh200, "setting max periodic bandwidth to %u%% " | ||
4971 | "(== %u usec/uframe)\n", | ||
4972 | 100*uframe_periodic_max/125, uframe_periodic_max); | ||
4973 | |||
4974 | if (uframe_periodic_max != 100) | ||
4975 | fusbh200_warn(fusbh200, "max periodic bandwidth set is non-standard\n"); | ||
4976 | |||
4977 | fusbh200->uframe_periodic_max = uframe_periodic_max; | ||
4978 | ret = count; | ||
4979 | |||
4980 | out_unlock: | ||
4981 | spin_unlock_irqrestore (&fusbh200->lock, flags); | ||
4982 | return ret; | ||
4983 | } | ||
4984 | static DEVICE_ATTR(uframe_periodic_max, 0644, show_uframe_periodic_max, store_uframe_periodic_max); | ||
4985 | |||
4986 | |||
4987 | static inline int create_sysfs_files(struct fusbh200_hcd *fusbh200) | ||
4988 | { | ||
4989 | struct device *controller = fusbh200_to_hcd(fusbh200)->self.controller; | ||
4990 | int i = 0; | ||
4991 | |||
4992 | if (i) | ||
4993 | goto out; | ||
4994 | |||
4995 | i = device_create_file(controller, &dev_attr_uframe_periodic_max); | ||
4996 | out: | ||
4997 | return i; | ||
4998 | } | ||
4999 | |||
5000 | static inline void remove_sysfs_files(struct fusbh200_hcd *fusbh200) | ||
5001 | { | ||
5002 | struct device *controller = fusbh200_to_hcd(fusbh200)->self.controller; | ||
5003 | |||
5004 | device_remove_file(controller, &dev_attr_uframe_periodic_max); | ||
5005 | } | ||
5006 | /*-------------------------------------------------------------------------*/ | ||
5007 | |||
5008 | /* On some systems, leaving remote wakeup enabled prevents system shutdown. | ||
5009 | * The firmware seems to think that powering off is a wakeup event! | ||
5010 | * This routine turns off remote wakeup and everything else, on all ports. | ||
5011 | */ | ||
5012 | static void fusbh200_turn_off_all_ports(struct fusbh200_hcd *fusbh200) | ||
5013 | { | ||
5014 | u32 __iomem *status_reg = &fusbh200->regs->port_status; | ||
5015 | |||
5016 | fusbh200_writel(fusbh200, PORT_RWC_BITS, status_reg); | ||
5017 | } | ||
5018 | |||
5019 | /* | ||
5020 | * Halt HC, turn off all ports, and let the BIOS use the companion controllers. | ||
5021 | * Must be called with interrupts enabled and the lock not held. | ||
5022 | */ | ||
5023 | static void fusbh200_silence_controller(struct fusbh200_hcd *fusbh200) | ||
5024 | { | ||
5025 | fusbh200_halt(fusbh200); | ||
5026 | |||
5027 | spin_lock_irq(&fusbh200->lock); | ||
5028 | fusbh200->rh_state = FUSBH200_RH_HALTED; | ||
5029 | fusbh200_turn_off_all_ports(fusbh200); | ||
5030 | spin_unlock_irq(&fusbh200->lock); | ||
5031 | } | ||
5032 | |||
5033 | /* fusbh200_shutdown kick in for silicon on any bus (not just pci, etc). | ||
5034 | * This forcibly disables dma and IRQs, helping kexec and other cases | ||
5035 | * where the next system software may expect clean state. | ||
5036 | */ | ||
5037 | static void fusbh200_shutdown(struct usb_hcd *hcd) | ||
5038 | { | ||
5039 | struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200(hcd); | ||
5040 | |||
5041 | spin_lock_irq(&fusbh200->lock); | ||
5042 | fusbh200->shutdown = true; | ||
5043 | fusbh200->rh_state = FUSBH200_RH_STOPPING; | ||
5044 | fusbh200->enabled_hrtimer_events = 0; | ||
5045 | spin_unlock_irq(&fusbh200->lock); | ||
5046 | |||
5047 | fusbh200_silence_controller(fusbh200); | ||
5048 | |||
5049 | hrtimer_cancel(&fusbh200->hrtimer); | ||
5050 | } | ||
5051 | |||
5052 | /*-------------------------------------------------------------------------*/ | ||
5053 | |||
5054 | /* | ||
5055 | * fusbh200_work is called from some interrupts, timers, and so on. | ||
5056 | * it calls driver completion functions, after dropping fusbh200->lock. | ||
5057 | */ | ||
5058 | static void fusbh200_work (struct fusbh200_hcd *fusbh200) | ||
5059 | { | ||
5060 | /* another CPU may drop fusbh200->lock during a schedule scan while | ||
5061 | * it reports urb completions. this flag guards against bogus | ||
5062 | * attempts at re-entrant schedule scanning. | ||
5063 | */ | ||
5064 | if (fusbh200->scanning) { | ||
5065 | fusbh200->need_rescan = true; | ||
5066 | return; | ||
5067 | } | ||
5068 | fusbh200->scanning = true; | ||
5069 | |||
5070 | rescan: | ||
5071 | fusbh200->need_rescan = false; | ||
5072 | if (fusbh200->async_count) | ||
5073 | scan_async(fusbh200); | ||
5074 | if (fusbh200->intr_count > 0) | ||
5075 | scan_intr(fusbh200); | ||
5076 | if (fusbh200->isoc_count > 0) | ||
5077 | scan_isoc(fusbh200); | ||
5078 | if (fusbh200->need_rescan) | ||
5079 | goto rescan; | ||
5080 | fusbh200->scanning = false; | ||
5081 | |||
5082 | /* the IO watchdog guards against hardware or driver bugs that | ||
5083 | * misplace IRQs, and should let us run completely without IRQs. | ||
5084 | * such lossage has been observed on both VT6202 and VT8235. | ||
5085 | */ | ||
5086 | turn_on_io_watchdog(fusbh200); | ||
5087 | } | ||
5088 | |||
5089 | /* | ||
5090 | * Called when the fusbh200_hcd module is removed. | ||
5091 | */ | ||
5092 | static void fusbh200_stop (struct usb_hcd *hcd) | ||
5093 | { | ||
5094 | struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200 (hcd); | ||
5095 | |||
5096 | fusbh200_dbg (fusbh200, "stop\n"); | ||
5097 | |||
5098 | /* no more interrupts ... */ | ||
5099 | |||
5100 | spin_lock_irq(&fusbh200->lock); | ||
5101 | fusbh200->enabled_hrtimer_events = 0; | ||
5102 | spin_unlock_irq(&fusbh200->lock); | ||
5103 | |||
5104 | fusbh200_quiesce(fusbh200); | ||
5105 | fusbh200_silence_controller(fusbh200); | ||
5106 | fusbh200_reset (fusbh200); | ||
5107 | |||
5108 | hrtimer_cancel(&fusbh200->hrtimer); | ||
5109 | remove_sysfs_files(fusbh200); | ||
5110 | remove_debug_files (fusbh200); | ||
5111 | |||
5112 | /* root hub is shut down separately (first, when possible) */ | ||
5113 | spin_lock_irq (&fusbh200->lock); | ||
5114 | end_free_itds(fusbh200); | ||
5115 | spin_unlock_irq (&fusbh200->lock); | ||
5116 | fusbh200_mem_cleanup (fusbh200); | ||
5117 | |||
5118 | #ifdef FUSBH200_STATS | ||
5119 | fusbh200_dbg(fusbh200, "irq normal %ld err %ld iaa %ld (lost %ld)\n", | ||
5120 | fusbh200->stats.normal, fusbh200->stats.error, fusbh200->stats.iaa, | ||
5121 | fusbh200->stats.lost_iaa); | ||
5122 | fusbh200_dbg (fusbh200, "complete %ld unlink %ld\n", | ||
5123 | fusbh200->stats.complete, fusbh200->stats.unlink); | ||
5124 | #endif | ||
5125 | |||
5126 | dbg_status (fusbh200, "fusbh200_stop completed", | ||
5127 | fusbh200_readl(fusbh200, &fusbh200->regs->status)); | ||
5128 | } | ||
5129 | |||
5130 | /* one-time init, only for memory state */ | ||
5131 | static int hcd_fusbh200_init(struct usb_hcd *hcd) | ||
5132 | { | ||
5133 | struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200(hcd); | ||
5134 | u32 temp; | ||
5135 | int retval; | ||
5136 | u32 hcc_params; | ||
5137 | struct fusbh200_qh_hw *hw; | ||
5138 | |||
5139 | spin_lock_init(&fusbh200->lock); | ||
5140 | |||
5141 | /* | ||
5142 | * keep io watchdog by default, those good HCDs could turn off it later | ||
5143 | */ | ||
5144 | fusbh200->need_io_watchdog = 1; | ||
5145 | |||
5146 | hrtimer_init(&fusbh200->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); | ||
5147 | fusbh200->hrtimer.function = fusbh200_hrtimer_func; | ||
5148 | fusbh200->next_hrtimer_event = FUSBH200_HRTIMER_NO_EVENT; | ||
5149 | |||
5150 | hcc_params = fusbh200_readl(fusbh200, &fusbh200->caps->hcc_params); | ||
5151 | |||
5152 | /* | ||
5153 | * by default set standard 80% (== 100 usec/uframe) max periodic | ||
5154 | * bandwidth as required by USB 2.0 | ||
5155 | */ | ||
5156 | fusbh200->uframe_periodic_max = 100; | ||
5157 | |||
5158 | /* | ||
5159 | * hw default: 1K periodic list heads, one per frame. | ||
5160 | * periodic_size can shrink by USBCMD update if hcc_params allows. | ||
5161 | */ | ||
5162 | fusbh200->periodic_size = DEFAULT_I_TDPS; | ||
5163 | INIT_LIST_HEAD(&fusbh200->intr_qh_list); | ||
5164 | INIT_LIST_HEAD(&fusbh200->cached_itd_list); | ||
5165 | |||
5166 | if (HCC_PGM_FRAMELISTLEN(hcc_params)) { | ||
5167 | /* periodic schedule size can be smaller than default */ | ||
5168 | switch (FUSBH200_TUNE_FLS) { | ||
5169 | case 0: fusbh200->periodic_size = 1024; break; | ||
5170 | case 1: fusbh200->periodic_size = 512; break; | ||
5171 | case 2: fusbh200->periodic_size = 256; break; | ||
5172 | default: BUG(); | ||
5173 | } | ||
5174 | } | ||
5175 | if ((retval = fusbh200_mem_init(fusbh200, GFP_KERNEL)) < 0) | ||
5176 | return retval; | ||
5177 | |||
5178 | /* controllers may cache some of the periodic schedule ... */ | ||
5179 | fusbh200->i_thresh = 2; | ||
5180 | |||
5181 | /* | ||
5182 | * dedicate a qh for the async ring head, since we couldn't unlink | ||
5183 | * a 'real' qh without stopping the async schedule [4.8]. use it | ||
5184 | * as the 'reclamation list head' too. | ||
5185 | * its dummy is used in hw_alt_next of many tds, to prevent the qh | ||
5186 | * from automatically advancing to the next td after short reads. | ||
5187 | */ | ||
5188 | fusbh200->async->qh_next.qh = NULL; | ||
5189 | hw = fusbh200->async->hw; | ||
5190 | hw->hw_next = QH_NEXT(fusbh200, fusbh200->async->qh_dma); | ||
5191 | hw->hw_info1 = cpu_to_hc32(fusbh200, QH_HEAD); | ||
5192 | hw->hw_token = cpu_to_hc32(fusbh200, QTD_STS_HALT); | ||
5193 | hw->hw_qtd_next = FUSBH200_LIST_END(fusbh200); | ||
5194 | fusbh200->async->qh_state = QH_STATE_LINKED; | ||
5195 | hw->hw_alt_next = QTD_NEXT(fusbh200, fusbh200->async->dummy->qtd_dma); | ||
5196 | |||
5197 | /* clear interrupt enables, set irq latency */ | ||
5198 | if (log2_irq_thresh < 0 || log2_irq_thresh > 6) | ||
5199 | log2_irq_thresh = 0; | ||
5200 | temp = 1 << (16 + log2_irq_thresh); | ||
5201 | if (HCC_CANPARK(hcc_params)) { | ||
5202 | /* HW default park == 3, on hardware that supports it (like | ||
5203 | * NVidia and ALI silicon), maximizes throughput on the async | ||
5204 | * schedule by avoiding QH fetches between transfers. | ||
5205 | * | ||
5206 | * With fast usb storage devices and NForce2, "park" seems to | ||
5207 | * make problems: throughput reduction (!), data errors... | ||
5208 | */ | ||
5209 | if (park) { | ||
5210 | park = min(park, (unsigned) 3); | ||
5211 | temp |= CMD_PARK; | ||
5212 | temp |= park << 8; | ||
5213 | } | ||
5214 | fusbh200_dbg(fusbh200, "park %d\n", park); | ||
5215 | } | ||
5216 | if (HCC_PGM_FRAMELISTLEN(hcc_params)) { | ||
5217 | /* periodic schedule size can be smaller than default */ | ||
5218 | temp &= ~(3 << 2); | ||
5219 | temp |= (FUSBH200_TUNE_FLS << 2); | ||
5220 | } | ||
5221 | fusbh200->command = temp; | ||
5222 | |||
5223 | /* Accept arbitrarily long scatter-gather lists */ | ||
5224 | if (!(hcd->driver->flags & HCD_LOCAL_MEM)) | ||
5225 | hcd->self.sg_tablesize = ~0; | ||
5226 | return 0; | ||
5227 | } | ||
5228 | |||
5229 | /* start HC running; it's halted, hcd_fusbh200_init() has been run (once) */ | ||
5230 | static int fusbh200_run (struct usb_hcd *hcd) | ||
5231 | { | ||
5232 | struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200 (hcd); | ||
5233 | u32 temp; | ||
5234 | u32 hcc_params; | ||
5235 | |||
5236 | hcd->uses_new_polling = 1; | ||
5237 | |||
5238 | /* EHCI spec section 4.1 */ | ||
5239 | |||
5240 | fusbh200_writel(fusbh200, fusbh200->periodic_dma, &fusbh200->regs->frame_list); | ||
5241 | fusbh200_writel(fusbh200, (u32)fusbh200->async->qh_dma, &fusbh200->regs->async_next); | ||
5242 | |||
5243 | /* | ||
5244 | * hcc_params controls whether fusbh200->regs->segment must (!!!) | ||
5245 | * be used; it constrains QH/ITD/SITD and QTD locations. | ||
5246 | * pci_pool consistent memory always uses segment zero. | ||
5247 | * streaming mappings for I/O buffers, like pci_map_single(), | ||
5248 | * can return segments above 4GB, if the device allows. | ||
5249 | * | ||
5250 | * NOTE: the dma mask is visible through dma_supported(), so | ||
5251 | * drivers can pass this info along ... like NETIF_F_HIGHDMA, | ||
5252 | * Scsi_Host.highmem_io, and so forth. It's readonly to all | ||
5253 | * host side drivers though. | ||
5254 | */ | ||
5255 | hcc_params = fusbh200_readl(fusbh200, &fusbh200->caps->hcc_params); | ||
5256 | |||
5257 | // Philips, Intel, and maybe others need CMD_RUN before the | ||
5258 | // root hub will detect new devices (why?); NEC doesn't | ||
5259 | fusbh200->command &= ~(CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET); | ||
5260 | fusbh200->command |= CMD_RUN; | ||
5261 | fusbh200_writel(fusbh200, fusbh200->command, &fusbh200->regs->command); | ||
5262 | dbg_cmd (fusbh200, "init", fusbh200->command); | ||
5263 | |||
5264 | /* | ||
5265 | * Start, enabling full USB 2.0 functionality ... usb 1.1 devices | ||
5266 | * are explicitly handed to companion controller(s), so no TT is | ||
5267 | * involved with the root hub. (Except where one is integrated, | ||
5268 | * and there's no companion controller unless maybe for USB OTG.) | ||
5269 | * | ||
5270 | * Turning on the CF flag will transfer ownership of all ports | ||
5271 | * from the companions to the EHCI controller. If any of the | ||
5272 | * companions are in the middle of a port reset at the time, it | ||
5273 | * could cause trouble. Write-locking ehci_cf_port_reset_rwsem | ||
5274 | * guarantees that no resets are in progress. After we set CF, | ||
5275 | * a short delay lets the hardware catch up; new resets shouldn't | ||
5276 | * be started before the port switching actions could complete. | ||
5277 | */ | ||
5278 | down_write(&ehci_cf_port_reset_rwsem); | ||
5279 | fusbh200->rh_state = FUSBH200_RH_RUNNING; | ||
5280 | fusbh200_readl(fusbh200, &fusbh200->regs->command); /* unblock posted writes */ | ||
5281 | msleep(5); | ||
5282 | up_write(&ehci_cf_port_reset_rwsem); | ||
5283 | fusbh200->last_periodic_enable = ktime_get_real(); | ||
5284 | |||
5285 | temp = HC_VERSION(fusbh200, fusbh200_readl(fusbh200, &fusbh200->caps->hc_capbase)); | ||
5286 | fusbh200_info (fusbh200, | ||
5287 | "USB %x.%x started, EHCI %x.%02x\n", | ||
5288 | ((fusbh200->sbrn & 0xf0)>>4), (fusbh200->sbrn & 0x0f), | ||
5289 | temp >> 8, temp & 0xff); | ||
5290 | |||
5291 | fusbh200_writel(fusbh200, INTR_MASK, | ||
5292 | &fusbh200->regs->intr_enable); /* Turn On Interrupts */ | ||
5293 | |||
5294 | /* GRR this is run-once init(), being done every time the HC starts. | ||
5295 | * So long as they're part of class devices, we can't do it init() | ||
5296 | * since the class device isn't created that early. | ||
5297 | */ | ||
5298 | create_debug_files(fusbh200); | ||
5299 | create_sysfs_files(fusbh200); | ||
5300 | |||
5301 | return 0; | ||
5302 | } | ||
5303 | |||
5304 | static int fusbh200_setup(struct usb_hcd *hcd) | ||
5305 | { | ||
5306 | struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200(hcd); | ||
5307 | int retval; | ||
5308 | |||
5309 | fusbh200->regs = (void __iomem *)fusbh200->caps + | ||
5310 | HC_LENGTH(fusbh200, fusbh200_readl(fusbh200, &fusbh200->caps->hc_capbase)); | ||
5311 | dbg_hcs_params(fusbh200, "reset"); | ||
5312 | dbg_hcc_params(fusbh200, "reset"); | ||
5313 | |||
5314 | /* cache this readonly data; minimize chip reads */ | ||
5315 | fusbh200->hcs_params = fusbh200_readl(fusbh200, &fusbh200->caps->hcs_params); | ||
5316 | |||
5317 | fusbh200->sbrn = HCD_USB2; | ||
5318 | |||
5319 | /* data structure init */ | ||
5320 | retval = hcd_fusbh200_init(hcd); | ||
5321 | if (retval) | ||
5322 | return retval; | ||
5323 | |||
5324 | retval = fusbh200_halt(fusbh200); | ||
5325 | if (retval) | ||
5326 | return retval; | ||
5327 | |||
5328 | fusbh200_reset(fusbh200); | ||
5329 | |||
5330 | return 0; | ||
5331 | } | ||
5332 | |||
5333 | /*-------------------------------------------------------------------------*/ | ||
5334 | |||
5335 | static irqreturn_t fusbh200_irq (struct usb_hcd *hcd) | ||
5336 | { | ||
5337 | struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200 (hcd); | ||
5338 | u32 status, masked_status, pcd_status = 0, cmd; | ||
5339 | int bh; | ||
5340 | |||
5341 | spin_lock (&fusbh200->lock); | ||
5342 | |||
5343 | status = fusbh200_readl(fusbh200, &fusbh200->regs->status); | ||
5344 | |||
5345 | /* e.g. cardbus physical eject */ | ||
5346 | if (status == ~(u32) 0) { | ||
5347 | fusbh200_dbg (fusbh200, "device removed\n"); | ||
5348 | goto dead; | ||
5349 | } | ||
5350 | |||
5351 | /* | ||
5352 | * We don't use STS_FLR, but some controllers don't like it to | ||
5353 | * remain on, so mask it out along with the other status bits. | ||
5354 | */ | ||
5355 | masked_status = status & (INTR_MASK | STS_FLR); | ||
5356 | |||
5357 | /* Shared IRQ? */ | ||
5358 | if (!masked_status || unlikely(fusbh200->rh_state == FUSBH200_RH_HALTED)) { | ||
5359 | spin_unlock(&fusbh200->lock); | ||
5360 | return IRQ_NONE; | ||
5361 | } | ||
5362 | |||
5363 | /* clear (just) interrupts */ | ||
5364 | fusbh200_writel(fusbh200, masked_status, &fusbh200->regs->status); | ||
5365 | cmd = fusbh200_readl(fusbh200, &fusbh200->regs->command); | ||
5366 | bh = 0; | ||
5367 | |||
5368 | #ifdef VERBOSE_DEBUG | ||
5369 | /* unrequested/ignored: Frame List Rollover */ | ||
5370 | dbg_status (fusbh200, "irq", status); | ||
5371 | #endif | ||
5372 | |||
5373 | /* INT, ERR, and IAA interrupt rates can be throttled */ | ||
5374 | |||
5375 | /* normal [4.15.1.2] or error [4.15.1.1] completion */ | ||
5376 | if (likely ((status & (STS_INT|STS_ERR)) != 0)) { | ||
5377 | if (likely ((status & STS_ERR) == 0)) | ||
5378 | COUNT (fusbh200->stats.normal); | ||
5379 | else | ||
5380 | COUNT (fusbh200->stats.error); | ||
5381 | bh = 1; | ||
5382 | } | ||
5383 | |||
5384 | /* complete the unlinking of some qh [4.15.2.3] */ | ||
5385 | if (status & STS_IAA) { | ||
5386 | |||
5387 | /* Turn off the IAA watchdog */ | ||
5388 | fusbh200->enabled_hrtimer_events &= ~BIT(FUSBH200_HRTIMER_IAA_WATCHDOG); | ||
5389 | |||
5390 | /* | ||
5391 | * Mild optimization: Allow another IAAD to reset the | ||
5392 | * hrtimer, if one occurs before the next expiration. | ||
5393 | * In theory we could always cancel the hrtimer, but | ||
5394 | * tests show that about half the time it will be reset | ||
5395 | * for some other event anyway. | ||
5396 | */ | ||
5397 | if (fusbh200->next_hrtimer_event == FUSBH200_HRTIMER_IAA_WATCHDOG) | ||
5398 | ++fusbh200->next_hrtimer_event; | ||
5399 | |||
5400 | /* guard against (alleged) silicon errata */ | ||
5401 | if (cmd & CMD_IAAD) | ||
5402 | fusbh200_dbg(fusbh200, "IAA with IAAD still set?\n"); | ||
5403 | if (fusbh200->async_iaa) { | ||
5404 | COUNT(fusbh200->stats.iaa); | ||
5405 | end_unlink_async(fusbh200); | ||
5406 | } else | ||
5407 | fusbh200_dbg(fusbh200, "IAA with nothing unlinked?\n"); | ||
5408 | } | ||
5409 | |||
5410 | /* remote wakeup [4.3.1] */ | ||
5411 | if (status & STS_PCD) { | ||
5412 | int pstatus; | ||
5413 | u32 __iomem *status_reg = &fusbh200->regs->port_status; | ||
5414 | |||
5415 | /* kick root hub later */ | ||
5416 | pcd_status = status; | ||
5417 | |||
5418 | /* resume root hub? */ | ||
5419 | if (fusbh200->rh_state == FUSBH200_RH_SUSPENDED) | ||
5420 | usb_hcd_resume_root_hub(hcd); | ||
5421 | |||
5422 | pstatus = fusbh200_readl(fusbh200, status_reg); | ||
5423 | |||
5424 | if (test_bit(0, &fusbh200->suspended_ports) && | ||
5425 | ((pstatus & PORT_RESUME) || | ||
5426 | !(pstatus & PORT_SUSPEND)) && | ||
5427 | (pstatus & PORT_PE) && | ||
5428 | fusbh200->reset_done[0] == 0) { | ||
5429 | |||
5430 | /* start 20 msec resume signaling from this port, | ||
5431 | * and make khubd collect PORT_STAT_C_SUSPEND to | ||
5432 | * stop that signaling. Use 5 ms extra for safety, | ||
5433 | * like usb_port_resume() does. | ||
5434 | */ | ||
5435 | fusbh200->reset_done[0] = jiffies + msecs_to_jiffies(25); | ||
5436 | set_bit(0, &fusbh200->resuming_ports); | ||
5437 | fusbh200_dbg (fusbh200, "port 1 remote wakeup\n"); | ||
5438 | mod_timer(&hcd->rh_timer, fusbh200->reset_done[0]); | ||
5439 | } | ||
5440 | } | ||
5441 | |||
5442 | /* PCI errors [4.15.2.4] */ | ||
5443 | if (unlikely ((status & STS_FATAL) != 0)) { | ||
5444 | fusbh200_err(fusbh200, "fatal error\n"); | ||
5445 | dbg_cmd(fusbh200, "fatal", cmd); | ||
5446 | dbg_status(fusbh200, "fatal", status); | ||
5447 | dead: | ||
5448 | usb_hc_died(hcd); | ||
5449 | |||
5450 | /* Don't let the controller do anything more */ | ||
5451 | fusbh200->shutdown = true; | ||
5452 | fusbh200->rh_state = FUSBH200_RH_STOPPING; | ||
5453 | fusbh200->command &= ~(CMD_RUN | CMD_ASE | CMD_PSE); | ||
5454 | fusbh200_writel(fusbh200, fusbh200->command, &fusbh200->regs->command); | ||
5455 | fusbh200_writel(fusbh200, 0, &fusbh200->regs->intr_enable); | ||
5456 | fusbh200_handle_controller_death(fusbh200); | ||
5457 | |||
5458 | /* Handle completions when the controller stops */ | ||
5459 | bh = 0; | ||
5460 | } | ||
5461 | |||
5462 | if (bh) | ||
5463 | fusbh200_work (fusbh200); | ||
5464 | spin_unlock (&fusbh200->lock); | ||
5465 | if (pcd_status) | ||
5466 | usb_hcd_poll_rh_status(hcd); | ||
5467 | return IRQ_HANDLED; | ||
5468 | } | ||
5469 | |||
5470 | /*-------------------------------------------------------------------------*/ | ||
5471 | |||
5472 | /* | ||
5473 | * non-error returns are a promise to giveback() the urb later | ||
5474 | * we drop ownership so next owner (or urb unlink) can get it | ||
5475 | * | ||
5476 | * urb + dev is in hcd.self.controller.urb_list | ||
5477 | * we're queueing TDs onto software and hardware lists | ||
5478 | * | ||
5479 | * hcd-specific init for hcpriv hasn't been done yet | ||
5480 | * | ||
5481 | * NOTE: control, bulk, and interrupt share the same code to append TDs | ||
5482 | * to a (possibly active) QH, and the same QH scanning code. | ||
5483 | */ | ||
5484 | static int fusbh200_urb_enqueue ( | ||
5485 | struct usb_hcd *hcd, | ||
5486 | struct urb *urb, | ||
5487 | gfp_t mem_flags | ||
5488 | ) { | ||
5489 | struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200 (hcd); | ||
5490 | struct list_head qtd_list; | ||
5491 | |||
5492 | INIT_LIST_HEAD (&qtd_list); | ||
5493 | |||
5494 | switch (usb_pipetype (urb->pipe)) { | ||
5495 | case PIPE_CONTROL: | ||
5496 | /* qh_completions() code doesn't handle all the fault cases | ||
5497 | * in multi-TD control transfers. Even 1KB is rare anyway. | ||
5498 | */ | ||
5499 | if (urb->transfer_buffer_length > (16 * 1024)) | ||
5500 | return -EMSGSIZE; | ||
5501 | /* FALLTHROUGH */ | ||
5502 | /* case PIPE_BULK: */ | ||
5503 | default: | ||
5504 | if (!qh_urb_transaction (fusbh200, urb, &qtd_list, mem_flags)) | ||
5505 | return -ENOMEM; | ||
5506 | return submit_async(fusbh200, urb, &qtd_list, mem_flags); | ||
5507 | |||
5508 | case PIPE_INTERRUPT: | ||
5509 | if (!qh_urb_transaction (fusbh200, urb, &qtd_list, mem_flags)) | ||
5510 | return -ENOMEM; | ||
5511 | return intr_submit(fusbh200, urb, &qtd_list, mem_flags); | ||
5512 | |||
5513 | case PIPE_ISOCHRONOUS: | ||
5514 | return itd_submit (fusbh200, urb, mem_flags); | ||
5515 | } | ||
5516 | } | ||
5517 | |||
5518 | /* remove from hardware lists | ||
5519 | * completions normally happen asynchronously | ||
5520 | */ | ||
5521 | |||
5522 | static int fusbh200_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) | ||
5523 | { | ||
5524 | struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200 (hcd); | ||
5525 | struct fusbh200_qh *qh; | ||
5526 | unsigned long flags; | ||
5527 | int rc; | ||
5528 | |||
5529 | spin_lock_irqsave (&fusbh200->lock, flags); | ||
5530 | rc = usb_hcd_check_unlink_urb(hcd, urb, status); | ||
5531 | if (rc) | ||
5532 | goto done; | ||
5533 | |||
5534 | switch (usb_pipetype (urb->pipe)) { | ||
5535 | // case PIPE_CONTROL: | ||
5536 | // case PIPE_BULK: | ||
5537 | default: | ||
5538 | qh = (struct fusbh200_qh *) urb->hcpriv; | ||
5539 | if (!qh) | ||
5540 | break; | ||
5541 | switch (qh->qh_state) { | ||
5542 | case QH_STATE_LINKED: | ||
5543 | case QH_STATE_COMPLETING: | ||
5544 | start_unlink_async(fusbh200, qh); | ||
5545 | break; | ||
5546 | case QH_STATE_UNLINK: | ||
5547 | case QH_STATE_UNLINK_WAIT: | ||
5548 | /* already started */ | ||
5549 | break; | ||
5550 | case QH_STATE_IDLE: | ||
5551 | /* QH might be waiting for a Clear-TT-Buffer */ | ||
5552 | qh_completions(fusbh200, qh); | ||
5553 | break; | ||
5554 | } | ||
5555 | break; | ||
5556 | |||
5557 | case PIPE_INTERRUPT: | ||
5558 | qh = (struct fusbh200_qh *) urb->hcpriv; | ||
5559 | if (!qh) | ||
5560 | break; | ||
5561 | switch (qh->qh_state) { | ||
5562 | case QH_STATE_LINKED: | ||
5563 | case QH_STATE_COMPLETING: | ||
5564 | start_unlink_intr(fusbh200, qh); | ||
5565 | break; | ||
5566 | case QH_STATE_IDLE: | ||
5567 | qh_completions (fusbh200, qh); | ||
5568 | break; | ||
5569 | default: | ||
5570 | fusbh200_dbg (fusbh200, "bogus qh %p state %d\n", | ||
5571 | qh, qh->qh_state); | ||
5572 | goto done; | ||
5573 | } | ||
5574 | break; | ||
5575 | |||
5576 | case PIPE_ISOCHRONOUS: | ||
5577 | // itd... | ||
5578 | |||
5579 | // wait till next completion, do it then. | ||
5580 | // completion irqs can wait up to 1024 msec, | ||
5581 | break; | ||
5582 | } | ||
5583 | done: | ||
5584 | spin_unlock_irqrestore (&fusbh200->lock, flags); | ||
5585 | return rc; | ||
5586 | } | ||
5587 | |||
5588 | /*-------------------------------------------------------------------------*/ | ||
5589 | |||
5590 | // bulk qh holds the data toggle | ||
5591 | |||
5592 | static void | ||
5593 | fusbh200_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep) | ||
5594 | { | ||
5595 | struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200 (hcd); | ||
5596 | unsigned long flags; | ||
5597 | struct fusbh200_qh *qh, *tmp; | ||
5598 | |||
5599 | /* ASSERT: any requests/urbs are being unlinked */ | ||
5600 | /* ASSERT: nobody can be submitting urbs for this any more */ | ||
5601 | |||
5602 | rescan: | ||
5603 | spin_lock_irqsave (&fusbh200->lock, flags); | ||
5604 | qh = ep->hcpriv; | ||
5605 | if (!qh) | ||
5606 | goto done; | ||
5607 | |||
5608 | /* endpoints can be iso streams. for now, we don't | ||
5609 | * accelerate iso completions ... so spin a while. | ||
5610 | */ | ||
5611 | if (qh->hw == NULL) { | ||
5612 | struct fusbh200_iso_stream *stream = ep->hcpriv; | ||
5613 | |||
5614 | if (!list_empty(&stream->td_list)) | ||
5615 | goto idle_timeout; | ||
5616 | |||
5617 | /* BUG_ON(!list_empty(&stream->free_list)); */ | ||
5618 | kfree(stream); | ||
5619 | goto done; | ||
5620 | } | ||
5621 | |||
5622 | if (fusbh200->rh_state < FUSBH200_RH_RUNNING) | ||
5623 | qh->qh_state = QH_STATE_IDLE; | ||
5624 | switch (qh->qh_state) { | ||
5625 | case QH_STATE_LINKED: | ||
5626 | case QH_STATE_COMPLETING: | ||
5627 | for (tmp = fusbh200->async->qh_next.qh; | ||
5628 | tmp && tmp != qh; | ||
5629 | tmp = tmp->qh_next.qh) | ||
5630 | continue; | ||
5631 | /* periodic qh self-unlinks on empty, and a COMPLETING qh | ||
5632 | * may already be unlinked. | ||
5633 | */ | ||
5634 | if (tmp) | ||
5635 | start_unlink_async(fusbh200, qh); | ||
5636 | /* FALL THROUGH */ | ||
5637 | case QH_STATE_UNLINK: /* wait for hw to finish? */ | ||
5638 | case QH_STATE_UNLINK_WAIT: | ||
5639 | idle_timeout: | ||
5640 | spin_unlock_irqrestore (&fusbh200->lock, flags); | ||
5641 | schedule_timeout_uninterruptible(1); | ||
5642 | goto rescan; | ||
5643 | case QH_STATE_IDLE: /* fully unlinked */ | ||
5644 | if (qh->clearing_tt) | ||
5645 | goto idle_timeout; | ||
5646 | if (list_empty (&qh->qtd_list)) { | ||
5647 | qh_destroy(fusbh200, qh); | ||
5648 | break; | ||
5649 | } | ||
5650 | /* else FALL THROUGH */ | ||
5651 | default: | ||
5652 | /* caller was supposed to have unlinked any requests; | ||
5653 | * that's not our job. just leak this memory. | ||
5654 | */ | ||
5655 | fusbh200_err (fusbh200, "qh %p (#%02x) state %d%s\n", | ||
5656 | qh, ep->desc.bEndpointAddress, qh->qh_state, | ||
5657 | list_empty (&qh->qtd_list) ? "" : "(has tds)"); | ||
5658 | break; | ||
5659 | } | ||
5660 | done: | ||
5661 | ep->hcpriv = NULL; | ||
5662 | spin_unlock_irqrestore (&fusbh200->lock, flags); | ||
5663 | } | ||
5664 | |||
5665 | static void | ||
5666 | fusbh200_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) | ||
5667 | { | ||
5668 | struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200(hcd); | ||
5669 | struct fusbh200_qh *qh; | ||
5670 | int eptype = usb_endpoint_type(&ep->desc); | ||
5671 | int epnum = usb_endpoint_num(&ep->desc); | ||
5672 | int is_out = usb_endpoint_dir_out(&ep->desc); | ||
5673 | unsigned long flags; | ||
5674 | |||
5675 | if (eptype != USB_ENDPOINT_XFER_BULK && eptype != USB_ENDPOINT_XFER_INT) | ||
5676 | return; | ||
5677 | |||
5678 | spin_lock_irqsave(&fusbh200->lock, flags); | ||
5679 | qh = ep->hcpriv; | ||
5680 | |||
5681 | /* For Bulk and Interrupt endpoints we maintain the toggle state | ||
5682 | * in the hardware; the toggle bits in udev aren't used at all. | ||
5683 | * When an endpoint is reset by usb_clear_halt() we must reset | ||
5684 | * the toggle bit in the QH. | ||
5685 | */ | ||
5686 | if (qh) { | ||
5687 | usb_settoggle(qh->dev, epnum, is_out, 0); | ||
5688 | if (!list_empty(&qh->qtd_list)) { | ||
5689 | WARN_ONCE(1, "clear_halt for a busy endpoint\n"); | ||
5690 | } else if (qh->qh_state == QH_STATE_LINKED || | ||
5691 | qh->qh_state == QH_STATE_COMPLETING) { | ||
5692 | |||
5693 | /* The toggle value in the QH can't be updated | ||
5694 | * while the QH is active. Unlink it now; | ||
5695 | * re-linking will call qh_refresh(). | ||
5696 | */ | ||
5697 | if (eptype == USB_ENDPOINT_XFER_BULK) | ||
5698 | start_unlink_async(fusbh200, qh); | ||
5699 | else | ||
5700 | start_unlink_intr(fusbh200, qh); | ||
5701 | } | ||
5702 | } | ||
5703 | spin_unlock_irqrestore(&fusbh200->lock, flags); | ||
5704 | } | ||
5705 | |||
5706 | static int fusbh200_get_frame (struct usb_hcd *hcd) | ||
5707 | { | ||
5708 | struct fusbh200_hcd *fusbh200 = hcd_to_fusbh200 (hcd); | ||
5709 | return (fusbh200_read_frame_index(fusbh200) >> 3) % fusbh200->periodic_size; | ||
5710 | } | ||
5711 | |||
5712 | /*-------------------------------------------------------------------------*/ | ||
5713 | |||
5714 | /* | ||
5715 | * The EHCI in ChipIdea HDRC cannot be a separate module or device, | ||
5716 | * because its registers (and irq) are shared between host/gadget/otg | ||
5717 | * functions and in order to facilitate role switching we cannot | ||
5718 | * give the fusbh200 driver exclusive access to those. | ||
5719 | */ | ||
5720 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
5721 | MODULE_AUTHOR (DRIVER_AUTHOR); | ||
5722 | MODULE_LICENSE ("GPL"); | ||
5723 | |||
5724 | static const struct hc_driver fusbh200_fusbh200_hc_driver = { | ||
5725 | .description = hcd_name, | ||
5726 | .product_desc = "Faraday USB2.0 Host Controller", | ||
5727 | .hcd_priv_size = sizeof(struct fusbh200_hcd), | ||
5728 | |||
5729 | /* | ||
5730 | * generic hardware linkage | ||
5731 | */ | ||
5732 | .irq = fusbh200_irq, | ||
5733 | .flags = HCD_MEMORY | HCD_USB2, | ||
5734 | |||
5735 | /* | ||
5736 | * basic lifecycle operations | ||
5737 | */ | ||
5738 | .reset = hcd_fusbh200_init, | ||
5739 | .start = fusbh200_run, | ||
5740 | .stop = fusbh200_stop, | ||
5741 | .shutdown = fusbh200_shutdown, | ||
5742 | |||
5743 | /* | ||
5744 | * managing i/o requests and associated device resources | ||
5745 | */ | ||
5746 | .urb_enqueue = fusbh200_urb_enqueue, | ||
5747 | .urb_dequeue = fusbh200_urb_dequeue, | ||
5748 | .endpoint_disable = fusbh200_endpoint_disable, | ||
5749 | .endpoint_reset = fusbh200_endpoint_reset, | ||
5750 | |||
5751 | /* | ||
5752 | * scheduling support | ||
5753 | */ | ||
5754 | .get_frame_number = fusbh200_get_frame, | ||
5755 | |||
5756 | /* | ||
5757 | * root hub support | ||
5758 | */ | ||
5759 | .hub_status_data = fusbh200_hub_status_data, | ||
5760 | .hub_control = fusbh200_hub_control, | ||
5761 | .bus_suspend = fusbh200_bus_suspend, | ||
5762 | .bus_resume = fusbh200_bus_resume, | ||
5763 | |||
5764 | .relinquish_port = fusbh200_relinquish_port, | ||
5765 | .port_handed_over = fusbh200_port_handed_over, | ||
5766 | |||
5767 | .clear_tt_buffer_complete = fusbh200_clear_tt_buffer_complete, | ||
5768 | }; | ||
5769 | |||
5770 | static void fusbh200_init(struct fusbh200_hcd *fusbh200) | ||
5771 | { | ||
5772 | u32 reg; | ||
5773 | |||
5774 | reg = fusbh200_readl(fusbh200, &fusbh200->regs->bmcsr); | ||
5775 | reg |= BMCSR_INT_POLARITY; | ||
5776 | reg &= ~BMCSR_VBUS_OFF; | ||
5777 | fusbh200_writel(fusbh200, reg, &fusbh200->regs->bmcsr); | ||
5778 | |||
5779 | reg = fusbh200_readl(fusbh200, &fusbh200->regs->bmier); | ||
5780 | fusbh200_writel(fusbh200, reg | BMIER_OVC_EN | BMIER_VBUS_ERR_EN, | ||
5781 | &fusbh200->regs->bmier); | ||
5782 | } | ||
5783 | |||
5784 | /** | ||
5785 | * fusbh200_hcd_probe - initialize faraday FUSBH200 HCDs | ||
5786 | * | ||
5787 | * Allocates basic resources for this USB host controller, and | ||
5788 | * then invokes the start() method for the HCD associated with it | ||
5789 | * through the hotplug entry's driver_data. | ||
5790 | */ | ||
5791 | static int fusbh200_hcd_probe(struct platform_device *pdev) | ||
5792 | { | ||
5793 | struct device *dev = &pdev->dev; | ||
5794 | struct usb_hcd *hcd; | ||
5795 | struct resource *res; | ||
5796 | int irq; | ||
5797 | int retval = -ENODEV; | ||
5798 | struct fusbh200_hcd *fusbh200; | ||
5799 | |||
5800 | if (usb_disabled()) | ||
5801 | return -ENODEV; | ||
5802 | |||
5803 | pdev->dev.power.power_state = PMSG_ON; | ||
5804 | |||
5805 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
5806 | if (!res) { | ||
5807 | dev_err(dev, | ||
5808 | "Found HC with no IRQ. Check %s setup!\n", | ||
5809 | dev_name(dev)); | ||
5810 | return -ENODEV; | ||
5811 | } | ||
5812 | |||
5813 | irq = res->start; | ||
5814 | |||
5815 | hcd = usb_create_hcd(&fusbh200_fusbh200_hc_driver, dev, | ||
5816 | dev_name(dev)); | ||
5817 | if (!hcd) { | ||
5818 | dev_err(dev, "failed to create hcd with err %d\n", retval); | ||
5819 | retval = -ENOMEM; | ||
5820 | goto fail_create_hcd; | ||
5821 | } | ||
5822 | |||
5823 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
5824 | if (!res) { | ||
5825 | dev_err(dev, | ||
5826 | "Found HC with no register addr. Check %s setup!\n", | ||
5827 | dev_name(dev)); | ||
5828 | retval = -ENODEV; | ||
5829 | goto fail_request_resource; | ||
5830 | } | ||
5831 | |||
5832 | hcd->rsrc_start = res->start; | ||
5833 | hcd->rsrc_len = resource_size(res); | ||
5834 | hcd->has_tt = 1; | ||
5835 | |||
5836 | if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, | ||
5837 | fusbh200_fusbh200_hc_driver.description)) { | ||
5838 | dev_dbg(dev, "controller already in use\n"); | ||
5839 | retval = -EBUSY; | ||
5840 | goto fail_request_resource; | ||
5841 | } | ||
5842 | |||
5843 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
5844 | if (!res) { | ||
5845 | dev_err(dev, | ||
5846 | "Found HC with no register addr. Check %s setup!\n", | ||
5847 | dev_name(dev)); | ||
5848 | retval = -ENODEV; | ||
5849 | goto fail_request_resource; | ||
5850 | } | ||
5851 | |||
5852 | hcd->regs = ioremap_nocache(res->start, resource_size(res)); | ||
5853 | if (hcd->regs == NULL) { | ||
5854 | dev_dbg(dev, "error mapping memory\n"); | ||
5855 | retval = -EFAULT; | ||
5856 | goto fail_ioremap; | ||
5857 | } | ||
5858 | |||
5859 | fusbh200 = hcd_to_fusbh200(hcd); | ||
5860 | |||
5861 | fusbh200->caps = hcd->regs; | ||
5862 | |||
5863 | retval = fusbh200_setup(hcd); | ||
5864 | if (retval) | ||
5865 | goto fail_add_hcd; | ||
5866 | |||
5867 | fusbh200_init(fusbh200); | ||
5868 | |||
5869 | retval = usb_add_hcd(hcd, irq, IRQF_SHARED); | ||
5870 | if (retval) { | ||
5871 | dev_err(dev, "failed to add hcd with err %d\n", retval); | ||
5872 | goto fail_add_hcd; | ||
5873 | } | ||
5874 | |||
5875 | return retval; | ||
5876 | |||
5877 | fail_add_hcd: | ||
5878 | iounmap(hcd->regs); | ||
5879 | fail_ioremap: | ||
5880 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
5881 | fail_request_resource: | ||
5882 | usb_put_hcd(hcd); | ||
5883 | fail_create_hcd: | ||
5884 | dev_err(dev, "init %s fail, %d\n", dev_name(dev), retval); | ||
5885 | return retval; | ||
5886 | } | ||
5887 | |||
5888 | /** | ||
5889 | * fusbh200_hcd_remove - shutdown processing for EHCI HCDs | ||
5890 | * @dev: USB Host Controller being removed | ||
5891 | * | ||
5892 | * Reverses the effect of fotg2xx_usb_hcd_probe(), first invoking | ||
5893 | * the HCD's stop() method. It is always called from a thread | ||
5894 | * context, normally "rmmod", "apmd", or something similar. | ||
5895 | */ | ||
5896 | static int fusbh200_hcd_remove(struct platform_device *pdev) | ||
5897 | { | ||
5898 | struct device *dev = &pdev->dev; | ||
5899 | struct usb_hcd *hcd = dev_get_drvdata(dev); | ||
5900 | |||
5901 | if (!hcd) | ||
5902 | return 0; | ||
5903 | |||
5904 | usb_remove_hcd(hcd); | ||
5905 | iounmap(hcd->regs); | ||
5906 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
5907 | usb_put_hcd(hcd); | ||
5908 | |||
5909 | return 0; | ||
5910 | } | ||
5911 | |||
5912 | static struct platform_driver fusbh200_hcd_fusbh200_driver = { | ||
5913 | .driver = { | ||
5914 | .name = "fusbh200", | ||
5915 | }, | ||
5916 | .probe = fusbh200_hcd_probe, | ||
5917 | .remove = fusbh200_hcd_remove, | ||
5918 | }; | ||
5919 | |||
5920 | static int __init fusbh200_hcd_init(void) | ||
5921 | { | ||
5922 | int retval = 0; | ||
5923 | |||
5924 | if (usb_disabled()) | ||
5925 | return -ENODEV; | ||
5926 | |||
5927 | printk(KERN_INFO "%s: " DRIVER_DESC "\n", hcd_name); | ||
5928 | set_bit(USB_EHCI_LOADED, &usb_hcds_loaded); | ||
5929 | if (test_bit(USB_UHCI_LOADED, &usb_hcds_loaded) || | ||
5930 | test_bit(USB_OHCI_LOADED, &usb_hcds_loaded)) | ||
5931 | printk(KERN_WARNING "Warning! fusbh200_hcd should always be loaded" | ||
5932 | " before uhci_hcd and ohci_hcd, not after\n"); | ||
5933 | |||
5934 | pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd\n", | ||
5935 | hcd_name, | ||
5936 | sizeof(struct fusbh200_qh), sizeof(struct fusbh200_qtd), | ||
5937 | sizeof(struct fusbh200_itd)); | ||
5938 | |||
5939 | #ifdef DEBUG | ||
5940 | fusbh200_debug_root = debugfs_create_dir("fusbh200", usb_debug_root); | ||
5941 | if (!fusbh200_debug_root) { | ||
5942 | retval = -ENOENT; | ||
5943 | goto err_debug; | ||
5944 | } | ||
5945 | #endif | ||
5946 | |||
5947 | retval = platform_driver_register(&fusbh200_hcd_fusbh200_driver); | ||
5948 | if (retval < 0) | ||
5949 | goto clean; | ||
5950 | return retval; | ||
5951 | |||
5952 | platform_driver_unregister(&fusbh200_hcd_fusbh200_driver); | ||
5953 | clean: | ||
5954 | #ifdef DEBUG | ||
5955 | debugfs_remove(fusbh200_debug_root); | ||
5956 | fusbh200_debug_root = NULL; | ||
5957 | err_debug: | ||
5958 | #endif | ||
5959 | clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); | ||
5960 | return retval; | ||
5961 | } | ||
5962 | module_init(fusbh200_hcd_init); | ||
5963 | |||
5964 | static void __exit fusbh200_hcd_cleanup(void) | ||
5965 | { | ||
5966 | platform_driver_unregister(&fusbh200_hcd_fusbh200_driver); | ||
5967 | #ifdef DEBUG | ||
5968 | debugfs_remove(fusbh200_debug_root); | ||
5969 | #endif | ||
5970 | clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); | ||
5971 | } | ||
5972 | module_exit(fusbh200_hcd_cleanup); | ||
diff --git a/drivers/usb/host/fusbh200.h b/drivers/usb/host/fusbh200.h new file mode 100644 index 000000000000..797c9e855270 --- /dev/null +++ b/drivers/usb/host/fusbh200.h | |||
@@ -0,0 +1,743 @@ | |||
1 | #ifndef __LINUX_FUSBH200_H | ||
2 | #define __LINUX_FUSBH200_H | ||
3 | |||
4 | /* definitions used for the EHCI driver */ | ||
5 | |||
6 | /* | ||
7 | * __hc32 and __hc16 are "Host Controller" types, they may be equivalent to | ||
8 | * __leXX (normally) or __beXX (given FUSBH200_BIG_ENDIAN_DESC), depending on | ||
9 | * the host controller implementation. | ||
10 | * | ||
11 | * To facilitate the strongest possible byte-order checking from "sparse" | ||
12 | * and so on, we use __leXX unless that's not practical. | ||
13 | */ | ||
14 | #define __hc32 __le32 | ||
15 | #define __hc16 __le16 | ||
16 | |||
17 | /* statistics can be kept for tuning/monitoring */ | ||
18 | struct fusbh200_stats { | ||
19 | /* irq usage */ | ||
20 | unsigned long normal; | ||
21 | unsigned long error; | ||
22 | unsigned long iaa; | ||
23 | unsigned long lost_iaa; | ||
24 | |||
25 | /* termination of urbs from core */ | ||
26 | unsigned long complete; | ||
27 | unsigned long unlink; | ||
28 | }; | ||
29 | |||
30 | /* fusbh200_hcd->lock guards shared data against other CPUs: | ||
31 | * fusbh200_hcd: async, unlink, periodic (and shadow), ... | ||
32 | * usb_host_endpoint: hcpriv | ||
33 | * fusbh200_qh: qh_next, qtd_list | ||
34 | * fusbh200_qtd: qtd_list | ||
35 | * | ||
36 | * Also, hold this lock when talking to HC registers or | ||
37 | * when updating hw_* fields in shared qh/qtd/... structures. | ||
38 | */ | ||
39 | |||
40 | #define FUSBH200_MAX_ROOT_PORTS 1 /* see HCS_N_PORTS */ | ||
41 | |||
42 | /* | ||
43 | * fusbh200_rh_state values of FUSBH200_RH_RUNNING or above mean that the | ||
44 | * controller may be doing DMA. Lower values mean there's no DMA. | ||
45 | */ | ||
46 | enum fusbh200_rh_state { | ||
47 | FUSBH200_RH_HALTED, | ||
48 | FUSBH200_RH_SUSPENDED, | ||
49 | FUSBH200_RH_RUNNING, | ||
50 | FUSBH200_RH_STOPPING | ||
51 | }; | ||
52 | |||
53 | /* | ||
54 | * Timer events, ordered by increasing delay length. | ||
55 | * Always update event_delays_ns[] and event_handlers[] (defined in | ||
56 | * ehci-timer.c) in parallel with this list. | ||
57 | */ | ||
58 | enum fusbh200_hrtimer_event { | ||
59 | FUSBH200_HRTIMER_POLL_ASS, /* Poll for async schedule off */ | ||
60 | FUSBH200_HRTIMER_POLL_PSS, /* Poll for periodic schedule off */ | ||
61 | FUSBH200_HRTIMER_POLL_DEAD, /* Wait for dead controller to stop */ | ||
62 | FUSBH200_HRTIMER_UNLINK_INTR, /* Wait for interrupt QH unlink */ | ||
63 | FUSBH200_HRTIMER_FREE_ITDS, /* Wait for unused iTDs and siTDs */ | ||
64 | FUSBH200_HRTIMER_ASYNC_UNLINKS, /* Unlink empty async QHs */ | ||
65 | FUSBH200_HRTIMER_IAA_WATCHDOG, /* Handle lost IAA interrupts */ | ||
66 | FUSBH200_HRTIMER_DISABLE_PERIODIC, /* Wait to disable periodic sched */ | ||
67 | FUSBH200_HRTIMER_DISABLE_ASYNC, /* Wait to disable async sched */ | ||
68 | FUSBH200_HRTIMER_IO_WATCHDOG, /* Check for missing IRQs */ | ||
69 | FUSBH200_HRTIMER_NUM_EVENTS /* Must come last */ | ||
70 | }; | ||
71 | #define FUSBH200_HRTIMER_NO_EVENT 99 | ||
72 | |||
73 | struct fusbh200_hcd { /* one per controller */ | ||
74 | /* timing support */ | ||
75 | enum fusbh200_hrtimer_event next_hrtimer_event; | ||
76 | unsigned enabled_hrtimer_events; | ||
77 | ktime_t hr_timeouts[FUSBH200_HRTIMER_NUM_EVENTS]; | ||
78 | struct hrtimer hrtimer; | ||
79 | |||
80 | int PSS_poll_count; | ||
81 | int ASS_poll_count; | ||
82 | int died_poll_count; | ||
83 | |||
84 | /* glue to PCI and HCD framework */ | ||
85 | struct fusbh200_caps __iomem *caps; | ||
86 | struct fusbh200_regs __iomem *regs; | ||
87 | struct fusbh200_dbg_port __iomem *debug; | ||
88 | |||
89 | __u32 hcs_params; /* cached register copy */ | ||
90 | spinlock_t lock; | ||
91 | enum fusbh200_rh_state rh_state; | ||
92 | |||
93 | /* general schedule support */ | ||
94 | bool scanning:1; | ||
95 | bool need_rescan:1; | ||
96 | bool intr_unlinking:1; | ||
97 | bool async_unlinking:1; | ||
98 | bool shutdown:1; | ||
99 | struct fusbh200_qh *qh_scan_next; | ||
100 | |||
101 | /* async schedule support */ | ||
102 | struct fusbh200_qh *async; | ||
103 | struct fusbh200_qh *dummy; /* For AMD quirk use */ | ||
104 | struct fusbh200_qh *async_unlink; | ||
105 | struct fusbh200_qh *async_unlink_last; | ||
106 | struct fusbh200_qh *async_iaa; | ||
107 | unsigned async_unlink_cycle; | ||
108 | unsigned async_count; /* async activity count */ | ||
109 | |||
110 | /* periodic schedule support */ | ||
111 | #define DEFAULT_I_TDPS 1024 /* some HCs can do less */ | ||
112 | unsigned periodic_size; | ||
113 | __hc32 *periodic; /* hw periodic table */ | ||
114 | dma_addr_t periodic_dma; | ||
115 | struct list_head intr_qh_list; | ||
116 | unsigned i_thresh; /* uframes HC might cache */ | ||
117 | |||
118 | union fusbh200_shadow *pshadow; /* mirror hw periodic table */ | ||
119 | struct fusbh200_qh *intr_unlink; | ||
120 | struct fusbh200_qh *intr_unlink_last; | ||
121 | unsigned intr_unlink_cycle; | ||
122 | unsigned now_frame; /* frame from HC hardware */ | ||
123 | unsigned next_frame; /* scan periodic, start here */ | ||
124 | unsigned intr_count; /* intr activity count */ | ||
125 | unsigned isoc_count; /* isoc activity count */ | ||
126 | unsigned periodic_count; /* periodic activity count */ | ||
127 | unsigned uframe_periodic_max; /* max periodic time per uframe */ | ||
128 | |||
129 | |||
130 | /* list of itds completed while now_frame was still active */ | ||
131 | struct list_head cached_itd_list; | ||
132 | struct fusbh200_itd *last_itd_to_free; | ||
133 | |||
134 | /* per root hub port */ | ||
135 | unsigned long reset_done [FUSBH200_MAX_ROOT_PORTS]; | ||
136 | |||
137 | /* bit vectors (one bit per port) */ | ||
138 | unsigned long bus_suspended; /* which ports were | ||
139 | already suspended at the start of a bus suspend */ | ||
140 | unsigned long companion_ports; /* which ports are | ||
141 | dedicated to the companion controller */ | ||
142 | unsigned long owned_ports; /* which ports are | ||
143 | owned by the companion during a bus suspend */ | ||
144 | unsigned long port_c_suspend; /* which ports have | ||
145 | the change-suspend feature turned on */ | ||
146 | unsigned long suspended_ports; /* which ports are | ||
147 | suspended */ | ||
148 | unsigned long resuming_ports; /* which ports have | ||
149 | started to resume */ | ||
150 | |||
151 | /* per-HC memory pools (could be per-bus, but ...) */ | ||
152 | struct dma_pool *qh_pool; /* qh per active urb */ | ||
153 | struct dma_pool *qtd_pool; /* one or more per qh */ | ||
154 | struct dma_pool *itd_pool; /* itd per iso urb */ | ||
155 | |||
156 | unsigned random_frame; | ||
157 | unsigned long next_statechange; | ||
158 | ktime_t last_periodic_enable; | ||
159 | u32 command; | ||
160 | |||
161 | /* SILICON QUIRKS */ | ||
162 | unsigned need_io_watchdog:1; | ||
163 | unsigned fs_i_thresh:1; /* Intel iso scheduling */ | ||
164 | |||
165 | u8 sbrn; /* packed release number */ | ||
166 | |||
167 | /* irq statistics */ | ||
168 | #ifdef FUSBH200_STATS | ||
169 | struct fusbh200_stats stats; | ||
170 | # define COUNT(x) do { (x)++; } while (0) | ||
171 | #else | ||
172 | # define COUNT(x) do {} while (0) | ||
173 | #endif | ||
174 | |||
175 | /* debug files */ | ||
176 | #ifdef DEBUG | ||
177 | struct dentry *debug_dir; | ||
178 | #endif | ||
179 | }; | ||
180 | |||
181 | /* convert between an HCD pointer and the corresponding FUSBH200_HCD */ | ||
182 | static inline struct fusbh200_hcd *hcd_to_fusbh200 (struct usb_hcd *hcd) | ||
183 | { | ||
184 | return (struct fusbh200_hcd *) (hcd->hcd_priv); | ||
185 | } | ||
186 | static inline struct usb_hcd *fusbh200_to_hcd (struct fusbh200_hcd *fusbh200) | ||
187 | { | ||
188 | return container_of ((void *) fusbh200, struct usb_hcd, hcd_priv); | ||
189 | } | ||
190 | |||
191 | /*-------------------------------------------------------------------------*/ | ||
192 | |||
193 | /* EHCI register interface, corresponds to EHCI Revision 0.95 specification */ | ||
194 | |||
195 | /* Section 2.2 Host Controller Capability Registers */ | ||
196 | struct fusbh200_caps { | ||
197 | /* these fields are specified as 8 and 16 bit registers, | ||
198 | * but some hosts can't perform 8 or 16 bit PCI accesses. | ||
199 | * some hosts treat caplength and hciversion as parts of a 32-bit | ||
200 | * register, others treat them as two separate registers, this | ||
201 | * affects the memory map for big endian controllers. | ||
202 | */ | ||
203 | u32 hc_capbase; | ||
204 | #define HC_LENGTH(fusbh200, p) (0x00ff&((p) >> /* bits 7:0 / offset 00h */ \ | ||
205 | (fusbh200_big_endian_capbase(fusbh200) ? 24 : 0))) | ||
206 | #define HC_VERSION(fusbh200, p) (0xffff&((p) >> /* bits 31:16 / offset 02h */ \ | ||
207 | (fusbh200_big_endian_capbase(fusbh200) ? 0 : 16))) | ||
208 | u32 hcs_params; /* HCSPARAMS - offset 0x4 */ | ||
209 | #define HCS_N_PORTS(p) (((p)>>0)&0xf) /* bits 3:0, ports on HC */ | ||
210 | |||
211 | u32 hcc_params; /* HCCPARAMS - offset 0x8 */ | ||
212 | #define HCC_CANPARK(p) ((p)&(1 << 2)) /* true: can park on async qh */ | ||
213 | #define HCC_PGM_FRAMELISTLEN(p) ((p)&(1 << 1)) /* true: periodic_size changes*/ | ||
214 | u8 portroute[8]; /* nibbles for routing - offset 0xC */ | ||
215 | }; | ||
216 | |||
217 | |||
218 | /* Section 2.3 Host Controller Operational Registers */ | ||
219 | struct fusbh200_regs { | ||
220 | |||
221 | /* USBCMD: offset 0x00 */ | ||
222 | u32 command; | ||
223 | |||
224 | /* EHCI 1.1 addendum */ | ||
225 | /* 23:16 is r/w intr rate, in microframes; default "8" == 1/msec */ | ||
226 | #define CMD_PARK (1<<11) /* enable "park" on async qh */ | ||
227 | #define CMD_PARK_CNT(c) (((c)>>8)&3) /* how many transfers to park for */ | ||
228 | #define CMD_IAAD (1<<6) /* "doorbell" interrupt async advance */ | ||
229 | #define CMD_ASE (1<<5) /* async schedule enable */ | ||
230 | #define CMD_PSE (1<<4) /* periodic schedule enable */ | ||
231 | /* 3:2 is periodic frame list size */ | ||
232 | #define CMD_RESET (1<<1) /* reset HC not bus */ | ||
233 | #define CMD_RUN (1<<0) /* start/stop HC */ | ||
234 | |||
235 | /* USBSTS: offset 0x04 */ | ||
236 | u32 status; | ||
237 | #define STS_ASS (1<<15) /* Async Schedule Status */ | ||
238 | #define STS_PSS (1<<14) /* Periodic Schedule Status */ | ||
239 | #define STS_RECL (1<<13) /* Reclamation */ | ||
240 | #define STS_HALT (1<<12) /* Not running (any reason) */ | ||
241 | /* some bits reserved */ | ||
242 | /* these STS_* flags are also intr_enable bits (USBINTR) */ | ||
243 | #define STS_IAA (1<<5) /* Interrupted on async advance */ | ||
244 | #define STS_FATAL (1<<4) /* such as some PCI access errors */ | ||
245 | #define STS_FLR (1<<3) /* frame list rolled over */ | ||
246 | #define STS_PCD (1<<2) /* port change detect */ | ||
247 | #define STS_ERR (1<<1) /* "error" completion (overflow, ...) */ | ||
248 | #define STS_INT (1<<0) /* "normal" completion (short, ...) */ | ||
249 | |||
250 | /* USBINTR: offset 0x08 */ | ||
251 | u32 intr_enable; | ||
252 | |||
253 | /* FRINDEX: offset 0x0C */ | ||
254 | u32 frame_index; /* current microframe number */ | ||
255 | /* CTRLDSSEGMENT: offset 0x10 */ | ||
256 | u32 segment; /* address bits 63:32 if needed */ | ||
257 | /* PERIODICLISTBASE: offset 0x14 */ | ||
258 | u32 frame_list; /* points to periodic list */ | ||
259 | /* ASYNCLISTADDR: offset 0x18 */ | ||
260 | u32 async_next; /* address of next async queue head */ | ||
261 | |||
262 | u32 reserved1; | ||
263 | /* PORTSC: offset 0x20 */ | ||
264 | u32 port_status; | ||
265 | /* 31:23 reserved */ | ||
266 | #define PORT_USB11(x) (((x)&(3<<10)) == (1<<10)) /* USB 1.1 device */ | ||
267 | #define PORT_RESET (1<<8) /* reset port */ | ||
268 | #define PORT_SUSPEND (1<<7) /* suspend port */ | ||
269 | #define PORT_RESUME (1<<6) /* resume it */ | ||
270 | #define PORT_PEC (1<<3) /* port enable change */ | ||
271 | #define PORT_PE (1<<2) /* port enable */ | ||
272 | #define PORT_CSC (1<<1) /* connect status change */ | ||
273 | #define PORT_CONNECT (1<<0) /* device connected */ | ||
274 | #define PORT_RWC_BITS (PORT_CSC | PORT_PEC) | ||
275 | |||
276 | u32 reserved2[3]; | ||
277 | |||
278 | /* BMCSR: offset 0x30 */ | ||
279 | u32 bmcsr; /* Bus Moniter Control/Status Register */ | ||
280 | #define BMCSR_HOST_SPD_TYP (3<<9) | ||
281 | #define BMCSR_VBUS_OFF (1<<4) | ||
282 | #define BMCSR_INT_POLARITY (1<<3) | ||
283 | |||
284 | /* BMISR: offset 0x34 */ | ||
285 | u32 bmisr; /* Bus Moniter Interrupt Status Register*/ | ||
286 | #define BMISR_OVC (1<<1) | ||
287 | |||
288 | /* BMIER: offset 0x38 */ | ||
289 | u32 bmier; /* Bus Moniter Interrupt Enable Register */ | ||
290 | #define BMIER_OVC_EN (1<<1) | ||
291 | #define BMIER_VBUS_ERR_EN (1<<0) | ||
292 | }; | ||
293 | |||
294 | /* Appendix C, Debug port ... intended for use with special "debug devices" | ||
295 | * that can help if there's no serial console. (nonstandard enumeration.) | ||
296 | */ | ||
297 | struct fusbh200_dbg_port { | ||
298 | u32 control; | ||
299 | #define DBGP_OWNER (1<<30) | ||
300 | #define DBGP_ENABLED (1<<28) | ||
301 | #define DBGP_DONE (1<<16) | ||
302 | #define DBGP_INUSE (1<<10) | ||
303 | #define DBGP_ERRCODE(x) (((x)>>7)&0x07) | ||
304 | # define DBGP_ERR_BAD 1 | ||
305 | # define DBGP_ERR_SIGNAL 2 | ||
306 | #define DBGP_ERROR (1<<6) | ||
307 | #define DBGP_GO (1<<5) | ||
308 | #define DBGP_OUT (1<<4) | ||
309 | #define DBGP_LEN(x) (((x)>>0)&0x0f) | ||
310 | u32 pids; | ||
311 | #define DBGP_PID_GET(x) (((x)>>16)&0xff) | ||
312 | #define DBGP_PID_SET(data, tok) (((data)<<8)|(tok)) | ||
313 | u32 data03; | ||
314 | u32 data47; | ||
315 | u32 address; | ||
316 | #define DBGP_EPADDR(dev, ep) (((dev)<<8)|(ep)) | ||
317 | }; | ||
318 | |||
319 | #ifdef CONFIG_EARLY_PRINTK_DBGP | ||
320 | #include <linux/init.h> | ||
321 | extern int __init early_dbgp_init(char *s); | ||
322 | extern struct console early_dbgp_console; | ||
323 | #endif /* CONFIG_EARLY_PRINTK_DBGP */ | ||
324 | |||
325 | struct usb_hcd; | ||
326 | |||
327 | static inline int xen_dbgp_reset_prep(struct usb_hcd *hcd) | ||
328 | { | ||
329 | return 1; /* Shouldn't this be 0? */ | ||
330 | } | ||
331 | |||
332 | static inline int xen_dbgp_external_startup(struct usb_hcd *hcd) | ||
333 | { | ||
334 | return -1; | ||
335 | } | ||
336 | |||
337 | #ifdef CONFIG_EARLY_PRINTK_DBGP | ||
338 | /* Call backs from fusbh200 host driver to fusbh200 debug driver */ | ||
339 | extern int dbgp_external_startup(struct usb_hcd *); | ||
340 | extern int dbgp_reset_prep(struct usb_hcd *hcd); | ||
341 | #else | ||
342 | static inline int dbgp_reset_prep(struct usb_hcd *hcd) | ||
343 | { | ||
344 | return xen_dbgp_reset_prep(hcd); | ||
345 | } | ||
346 | static inline int dbgp_external_startup(struct usb_hcd *hcd) | ||
347 | { | ||
348 | return xen_dbgp_external_startup(hcd); | ||
349 | } | ||
350 | #endif | ||
351 | |||
352 | /*-------------------------------------------------------------------------*/ | ||
353 | |||
354 | #define QTD_NEXT(fusbh200, dma) cpu_to_hc32(fusbh200, (u32)dma) | ||
355 | |||
356 | /* | ||
357 | * EHCI Specification 0.95 Section 3.5 | ||
358 | * QTD: describe data transfer components (buffer, direction, ...) | ||
359 | * See Fig 3-6 "Queue Element Transfer Descriptor Block Diagram". | ||
360 | * | ||
361 | * These are associated only with "QH" (Queue Head) structures, | ||
362 | * used with control, bulk, and interrupt transfers. | ||
363 | */ | ||
364 | struct fusbh200_qtd { | ||
365 | /* first part defined by EHCI spec */ | ||
366 | __hc32 hw_next; /* see EHCI 3.5.1 */ | ||
367 | __hc32 hw_alt_next; /* see EHCI 3.5.2 */ | ||
368 | __hc32 hw_token; /* see EHCI 3.5.3 */ | ||
369 | #define QTD_TOGGLE (1 << 31) /* data toggle */ | ||
370 | #define QTD_LENGTH(tok) (((tok)>>16) & 0x7fff) | ||
371 | #define QTD_IOC (1 << 15) /* interrupt on complete */ | ||
372 | #define QTD_CERR(tok) (((tok)>>10) & 0x3) | ||
373 | #define QTD_PID(tok) (((tok)>>8) & 0x3) | ||
374 | #define QTD_STS_ACTIVE (1 << 7) /* HC may execute this */ | ||
375 | #define QTD_STS_HALT (1 << 6) /* halted on error */ | ||
376 | #define QTD_STS_DBE (1 << 5) /* data buffer error (in HC) */ | ||
377 | #define QTD_STS_BABBLE (1 << 4) /* device was babbling (qtd halted) */ | ||
378 | #define QTD_STS_XACT (1 << 3) /* device gave illegal response */ | ||
379 | #define QTD_STS_MMF (1 << 2) /* incomplete split transaction */ | ||
380 | #define QTD_STS_STS (1 << 1) /* split transaction state */ | ||
381 | #define QTD_STS_PING (1 << 0) /* issue PING? */ | ||
382 | |||
383 | #define ACTIVE_BIT(fusbh200) cpu_to_hc32(fusbh200, QTD_STS_ACTIVE) | ||
384 | #define HALT_BIT(fusbh200) cpu_to_hc32(fusbh200, QTD_STS_HALT) | ||
385 | #define STATUS_BIT(fusbh200) cpu_to_hc32(fusbh200, QTD_STS_STS) | ||
386 | |||
387 | __hc32 hw_buf [5]; /* see EHCI 3.5.4 */ | ||
388 | __hc32 hw_buf_hi [5]; /* Appendix B */ | ||
389 | |||
390 | /* the rest is HCD-private */ | ||
391 | dma_addr_t qtd_dma; /* qtd address */ | ||
392 | struct list_head qtd_list; /* sw qtd list */ | ||
393 | struct urb *urb; /* qtd's urb */ | ||
394 | size_t length; /* length of buffer */ | ||
395 | } __attribute__ ((aligned (32))); | ||
396 | |||
397 | /* mask NakCnt+T in qh->hw_alt_next */ | ||
398 | #define QTD_MASK(fusbh200) cpu_to_hc32 (fusbh200, ~0x1f) | ||
399 | |||
400 | #define IS_SHORT_READ(token) (QTD_LENGTH (token) != 0 && QTD_PID (token) == 1) | ||
401 | |||
402 | /*-------------------------------------------------------------------------*/ | ||
403 | |||
404 | /* type tag from {qh,itd,fstn}->hw_next */ | ||
405 | #define Q_NEXT_TYPE(fusbh200,dma) ((dma) & cpu_to_hc32(fusbh200, 3 << 1)) | ||
406 | |||
407 | /* | ||
408 | * Now the following defines are not converted using the | ||
409 | * cpu_to_le32() macro anymore, since we have to support | ||
410 | * "dynamic" switching between be and le support, so that the driver | ||
411 | * can be used on one system with SoC EHCI controller using big-endian | ||
412 | * descriptors as well as a normal little-endian PCI EHCI controller. | ||
413 | */ | ||
414 | /* values for that type tag */ | ||
415 | #define Q_TYPE_ITD (0 << 1) | ||
416 | #define Q_TYPE_QH (1 << 1) | ||
417 | #define Q_TYPE_SITD (2 << 1) | ||
418 | #define Q_TYPE_FSTN (3 << 1) | ||
419 | |||
420 | /* next async queue entry, or pointer to interrupt/periodic QH */ | ||
421 | #define QH_NEXT(fusbh200,dma) (cpu_to_hc32(fusbh200, (((u32)dma)&~0x01f)|Q_TYPE_QH)) | ||
422 | |||
423 | /* for periodic/async schedules and qtd lists, mark end of list */ | ||
424 | #define FUSBH200_LIST_END(fusbh200) cpu_to_hc32(fusbh200, 1) /* "null pointer" to hw */ | ||
425 | |||
426 | /* | ||
427 | * Entries in periodic shadow table are pointers to one of four kinds | ||
428 | * of data structure. That's dictated by the hardware; a type tag is | ||
429 | * encoded in the low bits of the hardware's periodic schedule. Use | ||
430 | * Q_NEXT_TYPE to get the tag. | ||
431 | * | ||
432 | * For entries in the async schedule, the type tag always says "qh". | ||
433 | */ | ||
434 | union fusbh200_shadow { | ||
435 | struct fusbh200_qh *qh; /* Q_TYPE_QH */ | ||
436 | struct fusbh200_itd *itd; /* Q_TYPE_ITD */ | ||
437 | struct fusbh200_fstn *fstn; /* Q_TYPE_FSTN */ | ||
438 | __hc32 *hw_next; /* (all types) */ | ||
439 | void *ptr; | ||
440 | }; | ||
441 | |||
442 | /*-------------------------------------------------------------------------*/ | ||
443 | |||
444 | /* | ||
445 | * EHCI Specification 0.95 Section 3.6 | ||
446 | * QH: describes control/bulk/interrupt endpoints | ||
447 | * See Fig 3-7 "Queue Head Structure Layout". | ||
448 | * | ||
449 | * These appear in both the async and (for interrupt) periodic schedules. | ||
450 | */ | ||
451 | |||
452 | /* first part defined by EHCI spec */ | ||
453 | struct fusbh200_qh_hw { | ||
454 | __hc32 hw_next; /* see EHCI 3.6.1 */ | ||
455 | __hc32 hw_info1; /* see EHCI 3.6.2 */ | ||
456 | #define QH_CONTROL_EP (1 << 27) /* FS/LS control endpoint */ | ||
457 | #define QH_HEAD (1 << 15) /* Head of async reclamation list */ | ||
458 | #define QH_TOGGLE_CTL (1 << 14) /* Data toggle control */ | ||
459 | #define QH_HIGH_SPEED (2 << 12) /* Endpoint speed */ | ||
460 | #define QH_LOW_SPEED (1 << 12) | ||
461 | #define QH_FULL_SPEED (0 << 12) | ||
462 | #define QH_INACTIVATE (1 << 7) /* Inactivate on next transaction */ | ||
463 | __hc32 hw_info2; /* see EHCI 3.6.2 */ | ||
464 | #define QH_SMASK 0x000000ff | ||
465 | #define QH_CMASK 0x0000ff00 | ||
466 | #define QH_HUBADDR 0x007f0000 | ||
467 | #define QH_HUBPORT 0x3f800000 | ||
468 | #define QH_MULT 0xc0000000 | ||
469 | __hc32 hw_current; /* qtd list - see EHCI 3.6.4 */ | ||
470 | |||
471 | /* qtd overlay (hardware parts of a struct fusbh200_qtd) */ | ||
472 | __hc32 hw_qtd_next; | ||
473 | __hc32 hw_alt_next; | ||
474 | __hc32 hw_token; | ||
475 | __hc32 hw_buf [5]; | ||
476 | __hc32 hw_buf_hi [5]; | ||
477 | } __attribute__ ((aligned(32))); | ||
478 | |||
479 | struct fusbh200_qh { | ||
480 | struct fusbh200_qh_hw *hw; /* Must come first */ | ||
481 | /* the rest is HCD-private */ | ||
482 | dma_addr_t qh_dma; /* address of qh */ | ||
483 | union fusbh200_shadow qh_next; /* ptr to qh; or periodic */ | ||
484 | struct list_head qtd_list; /* sw qtd list */ | ||
485 | struct list_head intr_node; /* list of intr QHs */ | ||
486 | struct fusbh200_qtd *dummy; | ||
487 | struct fusbh200_qh *unlink_next; /* next on unlink list */ | ||
488 | |||
489 | unsigned unlink_cycle; | ||
490 | |||
491 | u8 needs_rescan; /* Dequeue during giveback */ | ||
492 | u8 qh_state; | ||
493 | #define QH_STATE_LINKED 1 /* HC sees this */ | ||
494 | #define QH_STATE_UNLINK 2 /* HC may still see this */ | ||
495 | #define QH_STATE_IDLE 3 /* HC doesn't see this */ | ||
496 | #define QH_STATE_UNLINK_WAIT 4 /* LINKED and on unlink q */ | ||
497 | #define QH_STATE_COMPLETING 5 /* don't touch token.HALT */ | ||
498 | |||
499 | u8 xacterrs; /* XactErr retry counter */ | ||
500 | #define QH_XACTERR_MAX 32 /* XactErr retry limit */ | ||
501 | |||
502 | /* periodic schedule info */ | ||
503 | u8 usecs; /* intr bandwidth */ | ||
504 | u8 gap_uf; /* uframes split/csplit gap */ | ||
505 | u8 c_usecs; /* ... split completion bw */ | ||
506 | u16 tt_usecs; /* tt downstream bandwidth */ | ||
507 | unsigned short period; /* polling interval */ | ||
508 | unsigned short start; /* where polling starts */ | ||
509 | #define NO_FRAME ((unsigned short)~0) /* pick new start */ | ||
510 | |||
511 | struct usb_device *dev; /* access to TT */ | ||
512 | unsigned is_out:1; /* bulk or intr OUT */ | ||
513 | unsigned clearing_tt:1; /* Clear-TT-Buf in progress */ | ||
514 | }; | ||
515 | |||
516 | /*-------------------------------------------------------------------------*/ | ||
517 | |||
518 | /* description of one iso transaction (up to 3 KB data if highspeed) */ | ||
519 | struct fusbh200_iso_packet { | ||
520 | /* These will be copied to iTD when scheduling */ | ||
521 | u64 bufp; /* itd->hw_bufp{,_hi}[pg] |= */ | ||
522 | __hc32 transaction; /* itd->hw_transaction[i] |= */ | ||
523 | u8 cross; /* buf crosses pages */ | ||
524 | /* for full speed OUT splits */ | ||
525 | u32 buf1; | ||
526 | }; | ||
527 | |||
528 | /* temporary schedule data for packets from iso urbs (both speeds) | ||
529 | * each packet is one logical usb transaction to the device (not TT), | ||
530 | * beginning at stream->next_uframe | ||
531 | */ | ||
532 | struct fusbh200_iso_sched { | ||
533 | struct list_head td_list; | ||
534 | unsigned span; | ||
535 | struct fusbh200_iso_packet packet [0]; | ||
536 | }; | ||
537 | |||
538 | /* | ||
539 | * fusbh200_iso_stream - groups all (s)itds for this endpoint. | ||
540 | * acts like a qh would, if EHCI had them for ISO. | ||
541 | */ | ||
542 | struct fusbh200_iso_stream { | ||
543 | /* first field matches fusbh200_hq, but is NULL */ | ||
544 | struct fusbh200_qh_hw *hw; | ||
545 | |||
546 | u8 bEndpointAddress; | ||
547 | u8 highspeed; | ||
548 | struct list_head td_list; /* queued itds */ | ||
549 | struct list_head free_list; /* list of unused itds */ | ||
550 | struct usb_device *udev; | ||
551 | struct usb_host_endpoint *ep; | ||
552 | |||
553 | /* output of (re)scheduling */ | ||
554 | int next_uframe; | ||
555 | __hc32 splits; | ||
556 | |||
557 | /* the rest is derived from the endpoint descriptor, | ||
558 | * trusting urb->interval == f(epdesc->bInterval) and | ||
559 | * including the extra info for hw_bufp[0..2] | ||
560 | */ | ||
561 | u8 usecs, c_usecs; | ||
562 | u16 interval; | ||
563 | u16 tt_usecs; | ||
564 | u16 maxp; | ||
565 | u16 raw_mask; | ||
566 | unsigned bandwidth; | ||
567 | |||
568 | /* This is used to initialize iTD's hw_bufp fields */ | ||
569 | __hc32 buf0; | ||
570 | __hc32 buf1; | ||
571 | __hc32 buf2; | ||
572 | |||
573 | /* this is used to initialize sITD's tt info */ | ||
574 | __hc32 address; | ||
575 | }; | ||
576 | |||
577 | /*-------------------------------------------------------------------------*/ | ||
578 | |||
579 | /* | ||
580 | * EHCI Specification 0.95 Section 3.3 | ||
581 | * Fig 3-4 "Isochronous Transaction Descriptor (iTD)" | ||
582 | * | ||
583 | * Schedule records for high speed iso xfers | ||
584 | */ | ||
585 | struct fusbh200_itd { | ||
586 | /* first part defined by EHCI spec */ | ||
587 | __hc32 hw_next; /* see EHCI 3.3.1 */ | ||
588 | __hc32 hw_transaction [8]; /* see EHCI 3.3.2 */ | ||
589 | #define FUSBH200_ISOC_ACTIVE (1<<31) /* activate transfer this slot */ | ||
590 | #define FUSBH200_ISOC_BUF_ERR (1<<30) /* Data buffer error */ | ||
591 | #define FUSBH200_ISOC_BABBLE (1<<29) /* babble detected */ | ||
592 | #define FUSBH200_ISOC_XACTERR (1<<28) /* XactErr - transaction error */ | ||
593 | #define FUSBH200_ITD_LENGTH(tok) (((tok)>>16) & 0x0fff) | ||
594 | #define FUSBH200_ITD_IOC (1 << 15) /* interrupt on complete */ | ||
595 | |||
596 | #define ITD_ACTIVE(fusbh200) cpu_to_hc32(fusbh200, FUSBH200_ISOC_ACTIVE) | ||
597 | |||
598 | __hc32 hw_bufp [7]; /* see EHCI 3.3.3 */ | ||
599 | __hc32 hw_bufp_hi [7]; /* Appendix B */ | ||
600 | |||
601 | /* the rest is HCD-private */ | ||
602 | dma_addr_t itd_dma; /* for this itd */ | ||
603 | union fusbh200_shadow itd_next; /* ptr to periodic q entry */ | ||
604 | |||
605 | struct urb *urb; | ||
606 | struct fusbh200_iso_stream *stream; /* endpoint's queue */ | ||
607 | struct list_head itd_list; /* list of stream's itds */ | ||
608 | |||
609 | /* any/all hw_transactions here may be used by that urb */ | ||
610 | unsigned frame; /* where scheduled */ | ||
611 | unsigned pg; | ||
612 | unsigned index[8]; /* in urb->iso_frame_desc */ | ||
613 | } __attribute__ ((aligned (32))); | ||
614 | |||
615 | /*-------------------------------------------------------------------------*/ | ||
616 | |||
617 | /* | ||
618 | * EHCI Specification 0.96 Section 3.7 | ||
619 | * Periodic Frame Span Traversal Node (FSTN) | ||
620 | * | ||
621 | * Manages split interrupt transactions (using TT) that span frame boundaries | ||
622 | * into uframes 0/1; see 4.12.2.2. In those uframes, a "save place" FSTN | ||
623 | * makes the HC jump (back) to a QH to scan for fs/ls QH completions until | ||
624 | * it hits a "restore" FSTN; then it returns to finish other uframe 0/1 work. | ||
625 | */ | ||
626 | struct fusbh200_fstn { | ||
627 | __hc32 hw_next; /* any periodic q entry */ | ||
628 | __hc32 hw_prev; /* qh or FUSBH200_LIST_END */ | ||
629 | |||
630 | /* the rest is HCD-private */ | ||
631 | dma_addr_t fstn_dma; | ||
632 | union fusbh200_shadow fstn_next; /* ptr to periodic q entry */ | ||
633 | } __attribute__ ((aligned (32))); | ||
634 | |||
635 | /*-------------------------------------------------------------------------*/ | ||
636 | |||
637 | /* Prepare the PORTSC wakeup flags during controller suspend/resume */ | ||
638 | |||
639 | #define fusbh200_prepare_ports_for_controller_suspend(fusbh200, do_wakeup) \ | ||
640 | fusbh200_adjust_port_wakeup_flags(fusbh200, true, do_wakeup); | ||
641 | |||
642 | #define fusbh200_prepare_ports_for_controller_resume(fusbh200) \ | ||
643 | fusbh200_adjust_port_wakeup_flags(fusbh200, false, false); | ||
644 | |||
645 | /*-------------------------------------------------------------------------*/ | ||
646 | |||
647 | /* | ||
648 | * Some EHCI controllers have a Transaction Translator built into the | ||
649 | * root hub. This is a non-standard feature. Each controller will need | ||
650 | * to add code to the following inline functions, and call them as | ||
651 | * needed (mostly in root hub code). | ||
652 | */ | ||
653 | |||
654 | static inline unsigned int | ||
655 | fusbh200_get_speed(struct fusbh200_hcd *fusbh200, unsigned int portsc) | ||
656 | { | ||
657 | return (readl(&fusbh200->regs->bmcsr) | ||
658 | & BMCSR_HOST_SPD_TYP) >> 9; | ||
659 | } | ||
660 | |||
661 | /* Returns the speed of a device attached to a port on the root hub. */ | ||
662 | static inline unsigned int | ||
663 | fusbh200_port_speed(struct fusbh200_hcd *fusbh200, unsigned int portsc) | ||
664 | { | ||
665 | switch (fusbh200_get_speed(fusbh200, portsc)) { | ||
666 | case 0: | ||
667 | return 0; | ||
668 | case 1: | ||
669 | return USB_PORT_STAT_LOW_SPEED; | ||
670 | case 2: | ||
671 | default: | ||
672 | return USB_PORT_STAT_HIGH_SPEED; | ||
673 | } | ||
674 | } | ||
675 | |||
676 | /*-------------------------------------------------------------------------*/ | ||
677 | |||
678 | #define fusbh200_has_fsl_portno_bug(e) (0) | ||
679 | |||
680 | /* | ||
681 | * While most USB host controllers implement their registers in | ||
682 | * little-endian format, a minority (celleb companion chip) implement | ||
683 | * them in big endian format. | ||
684 | * | ||
685 | * This attempts to support either format at compile time without a | ||
686 | * runtime penalty, or both formats with the additional overhead | ||
687 | * of checking a flag bit. | ||
688 | * | ||
689 | */ | ||
690 | |||
691 | #define fusbh200_big_endian_mmio(e) 0 | ||
692 | #define fusbh200_big_endian_capbase(e) 0 | ||
693 | |||
694 | static inline unsigned int fusbh200_readl(const struct fusbh200_hcd *fusbh200, | ||
695 | __u32 __iomem * regs) | ||
696 | { | ||
697 | return readl(regs); | ||
698 | } | ||
699 | |||
700 | static inline void fusbh200_writel(const struct fusbh200_hcd *fusbh200, | ||
701 | const unsigned int val, __u32 __iomem *regs) | ||
702 | { | ||
703 | writel(val, regs); | ||
704 | } | ||
705 | |||
706 | /* cpu to fusbh200 */ | ||
707 | static inline __hc32 cpu_to_hc32 (const struct fusbh200_hcd *fusbh200, const u32 x) | ||
708 | { | ||
709 | return cpu_to_le32(x); | ||
710 | } | ||
711 | |||
712 | /* fusbh200 to cpu */ | ||
713 | static inline u32 hc32_to_cpu (const struct fusbh200_hcd *fusbh200, const __hc32 x) | ||
714 | { | ||
715 | return le32_to_cpu(x); | ||
716 | } | ||
717 | |||
718 | static inline u32 hc32_to_cpup (const struct fusbh200_hcd *fusbh200, const __hc32 *x) | ||
719 | { | ||
720 | return le32_to_cpup(x); | ||
721 | } | ||
722 | |||
723 | /*-------------------------------------------------------------------------*/ | ||
724 | |||
725 | static inline unsigned fusbh200_read_frame_index(struct fusbh200_hcd *fusbh200) | ||
726 | { | ||
727 | return fusbh200_readl(fusbh200, &fusbh200->regs->frame_index); | ||
728 | } | ||
729 | |||
730 | #define fusbh200_itdlen(urb, desc, t) ({ \ | ||
731 | usb_pipein((urb)->pipe) ? \ | ||
732 | (desc)->length - FUSBH200_ITD_LENGTH(t) : \ | ||
733 | FUSBH200_ITD_LENGTH(t); \ | ||
734 | }) | ||
735 | /*-------------------------------------------------------------------------*/ | ||
736 | |||
737 | #ifndef DEBUG | ||
738 | #define STUB_DEBUG_FILES | ||
739 | #endif /* DEBUG */ | ||
740 | |||
741 | /*-------------------------------------------------------------------------*/ | ||
742 | |||
743 | #endif /* __LINUX_FUSBH200_H */ | ||
diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c index 104730dabd2d..483990c716aa 100644 --- a/drivers/usb/host/hwa-hc.c +++ b/drivers/usb/host/hwa-hc.c | |||
@@ -577,7 +577,7 @@ static struct hc_driver hwahc_hc_driver = { | |||
577 | .product_desc = "Wireless USB HWA host controller", | 577 | .product_desc = "Wireless USB HWA host controller", |
578 | .hcd_priv_size = sizeof(struct hwahc) - sizeof(struct usb_hcd), | 578 | .hcd_priv_size = sizeof(struct hwahc) - sizeof(struct usb_hcd), |
579 | .irq = NULL, /* FIXME */ | 579 | .irq = NULL, /* FIXME */ |
580 | .flags = HCD_USB2, /* FIXME */ | 580 | .flags = HCD_USB25, |
581 | .reset = hwahc_op_reset, | 581 | .reset = hwahc_op_reset, |
582 | .start = hwahc_op_start, | 582 | .start = hwahc_op_start, |
583 | .stop = hwahc_op_stop, | 583 | .stop = hwahc_op_stop, |
@@ -588,8 +588,6 @@ static struct hc_driver hwahc_hc_driver = { | |||
588 | 588 | ||
589 | .hub_status_data = wusbhc_rh_status_data, | 589 | .hub_status_data = wusbhc_rh_status_data, |
590 | .hub_control = wusbhc_rh_control, | 590 | .hub_control = wusbhc_rh_control, |
591 | .bus_suspend = wusbhc_rh_suspend, | ||
592 | .bus_resume = wusbhc_rh_resume, | ||
593 | .start_port_reset = wusbhc_rh_start_port_reset, | 591 | .start_port_reset = wusbhc_rh_start_port_reset, |
594 | }; | 592 | }; |
595 | 593 | ||
@@ -685,12 +683,9 @@ static int hwahc_create(struct hwahc *hwahc, struct usb_interface *iface) | |||
685 | wa->usb_dev = usb_get_dev(usb_dev); /* bind the USB device */ | 683 | wa->usb_dev = usb_get_dev(usb_dev); /* bind the USB device */ |
686 | wa->usb_iface = usb_get_intf(iface); | 684 | wa->usb_iface = usb_get_intf(iface); |
687 | wusbhc->dev = dev; | 685 | wusbhc->dev = dev; |
688 | wusbhc->uwb_rc = uwb_rc_get_by_grandpa(iface->dev.parent); | 686 | /* defer getting the uwb_rc handle until it is needed since it |
689 | if (wusbhc->uwb_rc == NULL) { | 687 | * may not have been registered by the hwa_rc driver yet. */ |
690 | result = -ENODEV; | 688 | wusbhc->uwb_rc = NULL; |
691 | dev_err(dev, "Cannot get associated UWB Host Controller\n"); | ||
692 | goto error_rc_get; | ||
693 | } | ||
694 | result = wa_fill_descr(wa); /* Get the device descriptor */ | 689 | result = wa_fill_descr(wa); /* Get the device descriptor */ |
695 | if (result < 0) | 690 | if (result < 0) |
696 | goto error_fill_descriptor; | 691 | goto error_fill_descriptor; |
@@ -733,8 +728,6 @@ error_wusbhc_create: | |||
733 | /* WA Descr fill allocs no resources */ | 728 | /* WA Descr fill allocs no resources */ |
734 | error_security_create: | 729 | error_security_create: |
735 | error_fill_descriptor: | 730 | error_fill_descriptor: |
736 | uwb_rc_put(wusbhc->uwb_rc); | ||
737 | error_rc_get: | ||
738 | usb_put_intf(iface); | 731 | usb_put_intf(iface); |
739 | usb_put_dev(usb_dev); | 732 | usb_put_dev(usb_dev); |
740 | return result; | 733 | return result; |
@@ -776,6 +769,7 @@ static int hwahc_probe(struct usb_interface *usb_iface, | |||
776 | goto error_alloc; | 769 | goto error_alloc; |
777 | } | 770 | } |
778 | usb_hcd->wireless = 1; | 771 | usb_hcd->wireless = 1; |
772 | usb_hcd->self.sg_tablesize = ~0; | ||
779 | wusbhc = usb_hcd_to_wusbhc(usb_hcd); | 773 | wusbhc = usb_hcd_to_wusbhc(usb_hcd); |
780 | hwahc = container_of(wusbhc, struct hwahc, wusbhc); | 774 | hwahc = container_of(wusbhc, struct hwahc, wusbhc); |
781 | hwahc_init(hwahc); | 775 | hwahc_init(hwahc); |
diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c index f0ebe8e7c58b..03dc4d9cbeca 100644 --- a/drivers/usb/host/imx21-hcd.c +++ b/drivers/usb/host/imx21-hcd.c | |||
@@ -809,26 +809,36 @@ static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd, | |||
809 | 809 | ||
810 | /* calculate frame */ | 810 | /* calculate frame */ |
811 | cur_frame = imx21_hc_get_frame(hcd); | 811 | cur_frame = imx21_hc_get_frame(hcd); |
812 | if (urb->transfer_flags & URB_ISO_ASAP) { | 812 | i = 0; |
813 | if (list_empty(&ep_priv->td_list)) | 813 | if (list_empty(&ep_priv->td_list)) { |
814 | urb->start_frame = cur_frame + 5; | 814 | urb->start_frame = wrap_frame(cur_frame + 5); |
815 | else | 815 | } else { |
816 | urb->start_frame = list_entry( | 816 | urb->start_frame = wrap_frame(list_entry(ep_priv->td_list.prev, |
817 | ep_priv->td_list.prev, | 817 | struct td, list)->frame + urb->interval); |
818 | struct td, list)->frame + urb->interval; | 818 | |
819 | } | 819 | if (frame_after(cur_frame, urb->start_frame)) { |
820 | urb->start_frame = wrap_frame(urb->start_frame); | 820 | dev_dbg(imx21->dev, |
821 | if (frame_after(cur_frame, urb->start_frame)) { | 821 | "enqueue: adjusting iso start %d (cur=%d) asap=%d\n", |
822 | dev_dbg(imx21->dev, | 822 | urb->start_frame, cur_frame, |
823 | "enqueue: adjusting iso start %d (cur=%d) asap=%d\n", | 823 | (urb->transfer_flags & URB_ISO_ASAP) != 0); |
824 | urb->start_frame, cur_frame, | 824 | i = DIV_ROUND_UP(wrap_frame( |
825 | (urb->transfer_flags & URB_ISO_ASAP) != 0); | 825 | cur_frame - urb->start_frame), |
826 | urb->start_frame = wrap_frame(cur_frame + 1); | 826 | urb->interval); |
827 | if (urb->transfer_flags & URB_ISO_ASAP) { | ||
828 | urb->start_frame = wrap_frame(urb->start_frame | ||
829 | + i * urb->interval); | ||
830 | i = 0; | ||
831 | } else if (i >= urb->number_of_packets) { | ||
832 | ret = -EXDEV; | ||
833 | goto alloc_dmem_failed; | ||
834 | } | ||
835 | } | ||
827 | } | 836 | } |
828 | 837 | ||
829 | /* set up transfers */ | 838 | /* set up transfers */ |
839 | urb_priv->isoc_remaining = urb->number_of_packets - i; | ||
830 | td = urb_priv->isoc_td; | 840 | td = urb_priv->isoc_td; |
831 | for (i = 0; i < urb->number_of_packets; i++, td++) { | 841 | for (; i < urb->number_of_packets; i++, td++) { |
832 | unsigned int offset = urb->iso_frame_desc[i].offset; | 842 | unsigned int offset = urb->iso_frame_desc[i].offset; |
833 | td->ep = ep; | 843 | td->ep = ep; |
834 | td->urb = urb; | 844 | td->urb = urb; |
@@ -840,7 +850,6 @@ static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd, | |||
840 | list_add_tail(&td->list, &ep_priv->td_list); | 850 | list_add_tail(&td->list, &ep_priv->td_list); |
841 | } | 851 | } |
842 | 852 | ||
843 | urb_priv->isoc_remaining = urb->number_of_packets; | ||
844 | dev_vdbg(imx21->dev, "setup %d packets for iso frame %d->%d\n", | 853 | dev_vdbg(imx21->dev, "setup %d packets for iso frame %d->%d\n", |
845 | urb->number_of_packets, urb->start_frame, td->frame); | 854 | urb->number_of_packets, urb->start_frame, td->frame); |
846 | 855 | ||
diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index a13709ee4e5d..3df49b169b53 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c | |||
@@ -118,7 +118,7 @@ static int of_isp1760_probe(struct platform_device *dev) | |||
118 | goto free_gpio; | 118 | goto free_gpio; |
119 | } | 119 | } |
120 | 120 | ||
121 | dev_set_drvdata(&dev->dev, drvdata); | 121 | platform_set_drvdata(dev, drvdata); |
122 | return ret; | 122 | return ret; |
123 | 123 | ||
124 | free_gpio: | 124 | free_gpio: |
@@ -133,9 +133,7 @@ free_data: | |||
133 | 133 | ||
134 | static int of_isp1760_remove(struct platform_device *dev) | 134 | static int of_isp1760_remove(struct platform_device *dev) |
135 | { | 135 | { |
136 | struct isp1760 *drvdata = dev_get_drvdata(&dev->dev); | 136 | struct isp1760 *drvdata = platform_get_drvdata(dev); |
137 | |||
138 | dev_set_drvdata(&dev->dev, NULL); | ||
139 | 137 | ||
140 | usb_remove_hcd(drvdata->hcd); | 138 | usb_remove_hcd(drvdata->hcd); |
141 | iounmap(drvdata->hcd->regs); | 139 | iounmap(drvdata->hcd->regs); |
@@ -398,7 +396,7 @@ static int isp1760_plat_probe(struct platform_device *pdev) | |||
398 | irqflags, -ENOENT, | 396 | irqflags, -ENOENT, |
399 | &pdev->dev, dev_name(&pdev->dev), devflags); | 397 | &pdev->dev, dev_name(&pdev->dev), devflags); |
400 | 398 | ||
401 | dev_set_drvdata(&pdev->dev, hcd); | 399 | platform_set_drvdata(pdev, hcd); |
402 | 400 | ||
403 | if (IS_ERR(hcd)) { | 401 | if (IS_ERR(hcd)) { |
404 | pr_warning("isp1760: Failed to register the HCD device\n"); | 402 | pr_warning("isp1760: Failed to register the HCD device\n"); |
@@ -419,7 +417,7 @@ static int isp1760_plat_remove(struct platform_device *pdev) | |||
419 | { | 417 | { |
420 | struct resource *mem_res; | 418 | struct resource *mem_res; |
421 | resource_size_t mem_size; | 419 | resource_size_t mem_size; |
422 | struct usb_hcd *hcd = dev_get_drvdata(&pdev->dev); | 420 | struct usb_hcd *hcd = platform_get_drvdata(pdev); |
423 | 421 | ||
424 | usb_remove_hcd(hcd); | 422 | usb_remove_hcd(hcd); |
425 | 423 | ||
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 2ee1496dbc1d..9677f6831209 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c | |||
@@ -41,17 +41,17 @@ extern int usb_disabled(void); | |||
41 | 41 | ||
42 | static void at91_start_clock(void) | 42 | static void at91_start_clock(void) |
43 | { | 43 | { |
44 | clk_enable(hclk); | 44 | clk_prepare_enable(hclk); |
45 | clk_enable(iclk); | 45 | clk_prepare_enable(iclk); |
46 | clk_enable(fclk); | 46 | clk_prepare_enable(fclk); |
47 | clocked = 1; | 47 | clocked = 1; |
48 | } | 48 | } |
49 | 49 | ||
50 | static void at91_stop_clock(void) | 50 | static void at91_stop_clock(void) |
51 | { | 51 | { |
52 | clk_disable(fclk); | 52 | clk_disable_unprepare(fclk); |
53 | clk_disable(iclk); | 53 | clk_disable_unprepare(iclk); |
54 | clk_disable(hclk); | 54 | clk_disable_unprepare(hclk); |
55 | clocked = 0; | 55 | clocked = 0; |
56 | } | 56 | } |
57 | 57 | ||
diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c index 0b815a856811..6aaa9c9c8eb0 100644 --- a/drivers/usb/host/ohci-da8xx.c +++ b/drivers/usb/host/ohci-da8xx.c | |||
@@ -401,7 +401,6 @@ static int ohci_hcd_da8xx_drv_remove(struct platform_device *dev) | |||
401 | struct usb_hcd *hcd = platform_get_drvdata(dev); | 401 | struct usb_hcd *hcd = platform_get_drvdata(dev); |
402 | 402 | ||
403 | usb_hcd_da8xx_remove(hcd, dev); | 403 | usb_hcd_da8xx_remove(hcd, dev); |
404 | platform_set_drvdata(dev, NULL); | ||
405 | 404 | ||
406 | return 0; | 405 | return 0; |
407 | } | 406 | } |
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index fc627fd54116..a9d3437da220 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c | |||
@@ -79,23 +79,8 @@ static const char hcd_name [] = "ohci_hcd"; | |||
79 | #include "pci-quirks.h" | 79 | #include "pci-quirks.h" |
80 | 80 | ||
81 | static void ohci_dump (struct ohci_hcd *ohci, int verbose); | 81 | static void ohci_dump (struct ohci_hcd *ohci, int verbose); |
82 | static int ohci_init (struct ohci_hcd *ohci); | ||
83 | static void ohci_stop (struct usb_hcd *hcd); | 82 | static void ohci_stop (struct usb_hcd *hcd); |
84 | 83 | ||
85 | #if defined(CONFIG_PM) || defined(CONFIG_PCI) | ||
86 | static int ohci_restart (struct ohci_hcd *ohci); | ||
87 | #endif | ||
88 | |||
89 | #ifdef CONFIG_PCI | ||
90 | static void sb800_prefetch(struct ohci_hcd *ohci, int on); | ||
91 | #else | ||
92 | static inline void sb800_prefetch(struct ohci_hcd *ohci, int on) | ||
93 | { | ||
94 | return; | ||
95 | } | ||
96 | #endif | ||
97 | |||
98 | |||
99 | #include "ohci-hub.c" | 84 | #include "ohci-hub.c" |
100 | #include "ohci-dbg.c" | 85 | #include "ohci-dbg.c" |
101 | #include "ohci-mem.c" | 86 | #include "ohci-mem.c" |
@@ -772,6 +757,32 @@ retry: | |||
772 | return 0; | 757 | return 0; |
773 | } | 758 | } |
774 | 759 | ||
760 | /* ohci_setup routine for generic controller initialization */ | ||
761 | |||
762 | int ohci_setup(struct usb_hcd *hcd) | ||
763 | { | ||
764 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); | ||
765 | |||
766 | ohci_hcd_init(ohci); | ||
767 | |||
768 | return ohci_init(ohci); | ||
769 | } | ||
770 | EXPORT_SYMBOL_GPL(ohci_setup); | ||
771 | |||
772 | /* ohci_start routine for generic controller start of all OHCI bus glue */ | ||
773 | static int ohci_start(struct usb_hcd *hcd) | ||
774 | { | ||
775 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); | ||
776 | int ret; | ||
777 | |||
778 | ret = ohci_run(ohci); | ||
779 | if (ret < 0) { | ||
780 | ohci_err(ohci, "can't start\n"); | ||
781 | ohci_stop(hcd); | ||
782 | } | ||
783 | return ret; | ||
784 | } | ||
785 | |||
775 | /*-------------------------------------------------------------------------*/ | 786 | /*-------------------------------------------------------------------------*/ |
776 | 787 | ||
777 | /* an interrupt happens */ | 788 | /* an interrupt happens */ |
@@ -953,12 +964,13 @@ static void ohci_stop (struct usb_hcd *hcd) | |||
953 | #if defined(CONFIG_PM) || defined(CONFIG_PCI) | 964 | #if defined(CONFIG_PM) || defined(CONFIG_PCI) |
954 | 965 | ||
955 | /* must not be called from interrupt context */ | 966 | /* must not be called from interrupt context */ |
956 | static int ohci_restart (struct ohci_hcd *ohci) | 967 | int ohci_restart(struct ohci_hcd *ohci) |
957 | { | 968 | { |
958 | int temp; | 969 | int temp; |
959 | int i; | 970 | int i; |
960 | struct urb_priv *priv; | 971 | struct urb_priv *priv; |
961 | 972 | ||
973 | ohci_init(ohci); | ||
962 | spin_lock_irq(&ohci->lock); | 974 | spin_lock_irq(&ohci->lock); |
963 | ohci->rh_state = OHCI_RH_HALTED; | 975 | ohci->rh_state = OHCI_RH_HALTED; |
964 | 976 | ||
@@ -1012,12 +1024,13 @@ static int ohci_restart (struct ohci_hcd *ohci) | |||
1012 | ohci_dbg(ohci, "restart complete\n"); | 1024 | ohci_dbg(ohci, "restart complete\n"); |
1013 | return 0; | 1025 | return 0; |
1014 | } | 1026 | } |
1027 | EXPORT_SYMBOL_GPL(ohci_restart); | ||
1015 | 1028 | ||
1016 | #endif | 1029 | #endif |
1017 | 1030 | ||
1018 | #ifdef CONFIG_PM | 1031 | #ifdef CONFIG_PM |
1019 | 1032 | ||
1020 | static int __maybe_unused ohci_suspend(struct usb_hcd *hcd, bool do_wakeup) | 1033 | int ohci_suspend(struct usb_hcd *hcd, bool do_wakeup) |
1021 | { | 1034 | { |
1022 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | 1035 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
1023 | unsigned long flags; | 1036 | unsigned long flags; |
@@ -1035,9 +1048,10 @@ static int __maybe_unused ohci_suspend(struct usb_hcd *hcd, bool do_wakeup) | |||
1035 | 1048 | ||
1036 | return 0; | 1049 | return 0; |
1037 | } | 1050 | } |
1051 | EXPORT_SYMBOL_GPL(ohci_suspend); | ||
1038 | 1052 | ||
1039 | 1053 | ||
1040 | static int __maybe_unused ohci_resume(struct usb_hcd *hcd, bool hibernated) | 1054 | int ohci_resume(struct usb_hcd *hcd, bool hibernated) |
1041 | { | 1055 | { |
1042 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); | 1056 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); |
1043 | int port; | 1057 | int port; |
@@ -1085,20 +1099,79 @@ static int __maybe_unused ohci_resume(struct usb_hcd *hcd, bool hibernated) | |||
1085 | 1099 | ||
1086 | return 0; | 1100 | return 0; |
1087 | } | 1101 | } |
1102 | EXPORT_SYMBOL_GPL(ohci_resume); | ||
1088 | 1103 | ||
1089 | #endif | 1104 | #endif |
1090 | 1105 | ||
1091 | /*-------------------------------------------------------------------------*/ | 1106 | /*-------------------------------------------------------------------------*/ |
1092 | 1107 | ||
1108 | /* | ||
1109 | * Generic structure: This gets copied for platform drivers so that | ||
1110 | * individual entries can be overridden as needed. | ||
1111 | */ | ||
1112 | |||
1113 | static const struct hc_driver ohci_hc_driver = { | ||
1114 | .description = hcd_name, | ||
1115 | .product_desc = "OHCI Host Controller", | ||
1116 | .hcd_priv_size = sizeof(struct ohci_hcd), | ||
1117 | |||
1118 | /* | ||
1119 | * generic hardware linkage | ||
1120 | */ | ||
1121 | .irq = ohci_irq, | ||
1122 | .flags = HCD_MEMORY | HCD_USB11, | ||
1123 | |||
1124 | /* | ||
1125 | * basic lifecycle operations | ||
1126 | */ | ||
1127 | .reset = ohci_setup, | ||
1128 | .start = ohci_start, | ||
1129 | .stop = ohci_stop, | ||
1130 | .shutdown = ohci_shutdown, | ||
1131 | |||
1132 | /* | ||
1133 | * managing i/o requests and associated device resources | ||
1134 | */ | ||
1135 | .urb_enqueue = ohci_urb_enqueue, | ||
1136 | .urb_dequeue = ohci_urb_dequeue, | ||
1137 | .endpoint_disable = ohci_endpoint_disable, | ||
1138 | |||
1139 | /* | ||
1140 | * scheduling support | ||
1141 | */ | ||
1142 | .get_frame_number = ohci_get_frame, | ||
1143 | |||
1144 | /* | ||
1145 | * root hub support | ||
1146 | */ | ||
1147 | .hub_status_data = ohci_hub_status_data, | ||
1148 | .hub_control = ohci_hub_control, | ||
1149 | #ifdef CONFIG_PM | ||
1150 | .bus_suspend = ohci_bus_suspend, | ||
1151 | .bus_resume = ohci_bus_resume, | ||
1152 | #endif | ||
1153 | .start_port_reset = ohci_start_port_reset, | ||
1154 | }; | ||
1155 | |||
1156 | void ohci_init_driver(struct hc_driver *drv, | ||
1157 | const struct ohci_driver_overrides *over) | ||
1158 | { | ||
1159 | /* Copy the generic table to drv and then apply the overrides */ | ||
1160 | *drv = ohci_hc_driver; | ||
1161 | |||
1162 | drv->product_desc = over->product_desc; | ||
1163 | drv->hcd_priv_size += over->extra_priv_size; | ||
1164 | if (over->reset) | ||
1165 | drv->reset = over->reset; | ||
1166 | } | ||
1167 | EXPORT_SYMBOL_GPL(ohci_init_driver); | ||
1168 | |||
1169 | /*-------------------------------------------------------------------------*/ | ||
1170 | |||
1093 | MODULE_AUTHOR (DRIVER_AUTHOR); | 1171 | MODULE_AUTHOR (DRIVER_AUTHOR); |
1094 | MODULE_DESCRIPTION(DRIVER_DESC); | 1172 | MODULE_DESCRIPTION(DRIVER_DESC); |
1095 | MODULE_LICENSE ("GPL"); | 1173 | MODULE_LICENSE ("GPL"); |
1096 | 1174 | ||
1097 | #ifdef CONFIG_PCI | ||
1098 | #include "ohci-pci.c" | ||
1099 | #define PCI_DRIVER ohci_pci_driver | ||
1100 | #endif | ||
1101 | |||
1102 | #if defined(CONFIG_ARCH_SA1100) && defined(CONFIG_SA1111) | 1175 | #if defined(CONFIG_ARCH_SA1100) && defined(CONFIG_SA1111) |
1103 | #include "ohci-sa1111.c" | 1176 | #include "ohci-sa1111.c" |
1104 | #define SA1111_DRIVER ohci_hcd_sa1111_driver | 1177 | #define SA1111_DRIVER ohci_hcd_sa1111_driver |
@@ -1189,30 +1262,6 @@ MODULE_LICENSE ("GPL"); | |||
1189 | #define PLATFORM_DRIVER ohci_hcd_tilegx_driver | 1262 | #define PLATFORM_DRIVER ohci_hcd_tilegx_driver |
1190 | #endif | 1263 | #endif |
1191 | 1264 | ||
1192 | #ifdef CONFIG_USB_OHCI_HCD_PLATFORM | ||
1193 | #include "ohci-platform.c" | ||
1194 | #define PLATFORM_DRIVER ohci_platform_driver | ||
1195 | #endif | ||
1196 | |||
1197 | #if !defined(PCI_DRIVER) && \ | ||
1198 | !defined(PLATFORM_DRIVER) && \ | ||
1199 | !defined(OMAP1_PLATFORM_DRIVER) && \ | ||
1200 | !defined(OMAP3_PLATFORM_DRIVER) && \ | ||
1201 | !defined(OF_PLATFORM_DRIVER) && \ | ||
1202 | !defined(SA1111_DRIVER) && \ | ||
1203 | !defined(PS3_SYSTEM_BUS_DRIVER) && \ | ||
1204 | !defined(SM501_OHCI_DRIVER) && \ | ||
1205 | !defined(TMIO_OHCI_DRIVER) && \ | ||
1206 | !defined(S3C2410_PLATFORM_DRIVER) && \ | ||
1207 | !defined(EXYNOS_PLATFORM_DRIVER) && \ | ||
1208 | !defined(EP93XX_PLATFORM_DRIVER) && \ | ||
1209 | !defined(AT91_PLATFORM_DRIVER) && \ | ||
1210 | !defined(NXP_PLATFORM_DRIVER) && \ | ||
1211 | !defined(DAVINCI_PLATFORM_DRIVER) && \ | ||
1212 | !defined(SPEAR_PLATFORM_DRIVER) | ||
1213 | #error "missing bus glue for ohci-hcd" | ||
1214 | #endif | ||
1215 | |||
1216 | static int __init ohci_hcd_mod_init(void) | 1265 | static int __init ohci_hcd_mod_init(void) |
1217 | { | 1266 | { |
1218 | int retval = 0; | 1267 | int retval = 0; |
@@ -1269,12 +1318,6 @@ static int __init ohci_hcd_mod_init(void) | |||
1269 | goto error_sa1111; | 1318 | goto error_sa1111; |
1270 | #endif | 1319 | #endif |
1271 | 1320 | ||
1272 | #ifdef PCI_DRIVER | ||
1273 | retval = pci_register_driver(&PCI_DRIVER); | ||
1274 | if (retval < 0) | ||
1275 | goto error_pci; | ||
1276 | #endif | ||
1277 | |||
1278 | #ifdef SM501_OHCI_DRIVER | 1321 | #ifdef SM501_OHCI_DRIVER |
1279 | retval = platform_driver_register(&SM501_OHCI_DRIVER); | 1322 | retval = platform_driver_register(&SM501_OHCI_DRIVER); |
1280 | if (retval < 0) | 1323 | if (retval < 0) |
@@ -1368,10 +1411,6 @@ static int __init ohci_hcd_mod_init(void) | |||
1368 | platform_driver_unregister(&SM501_OHCI_DRIVER); | 1411 | platform_driver_unregister(&SM501_OHCI_DRIVER); |
1369 | error_sm501: | 1412 | error_sm501: |
1370 | #endif | 1413 | #endif |
1371 | #ifdef PCI_DRIVER | ||
1372 | pci_unregister_driver(&PCI_DRIVER); | ||
1373 | error_pci: | ||
1374 | #endif | ||
1375 | #ifdef SA1111_DRIVER | 1414 | #ifdef SA1111_DRIVER |
1376 | sa1111_driver_unregister(&SA1111_DRIVER); | 1415 | sa1111_driver_unregister(&SA1111_DRIVER); |
1377 | error_sa1111: | 1416 | error_sa1111: |
@@ -1436,9 +1475,6 @@ static void __exit ohci_hcd_mod_exit(void) | |||
1436 | #ifdef SM501_OHCI_DRIVER | 1475 | #ifdef SM501_OHCI_DRIVER |
1437 | platform_driver_unregister(&SM501_OHCI_DRIVER); | 1476 | platform_driver_unregister(&SM501_OHCI_DRIVER); |
1438 | #endif | 1477 | #endif |
1439 | #ifdef PCI_DRIVER | ||
1440 | pci_unregister_driver(&PCI_DRIVER); | ||
1441 | #endif | ||
1442 | #ifdef SA1111_DRIVER | 1478 | #ifdef SA1111_DRIVER |
1443 | sa1111_driver_unregister(&SA1111_DRIVER); | 1479 | sa1111_driver_unregister(&SA1111_DRIVER); |
1444 | #endif | 1480 | #endif |
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 60ff4220e8b4..2347ab83f046 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c | |||
@@ -176,7 +176,6 @@ __acquires(ohci->lock) | |||
176 | if (status == -EBUSY) { | 176 | if (status == -EBUSY) { |
177 | if (!autostopped) { | 177 | if (!autostopped) { |
178 | spin_unlock_irq (&ohci->lock); | 178 | spin_unlock_irq (&ohci->lock); |
179 | (void) ohci_init (ohci); | ||
180 | status = ohci_restart (ohci); | 179 | status = ohci_restart (ohci); |
181 | 180 | ||
182 | usb_root_hub_lost_power(hcd->self.root_hub); | 181 | usb_root_hub_lost_power(hcd->self.root_hub); |
diff --git a/drivers/usb/host/ohci-jz4740.c b/drivers/usb/host/ohci-jz4740.c index 8062bb9dea16..d4ef53990d73 100644 --- a/drivers/usb/host/ohci-jz4740.c +++ b/drivers/usb/host/ohci-jz4740.c | |||
@@ -221,7 +221,6 @@ static int jz4740_ohci_probe(struct platform_device *pdev) | |||
221 | return 0; | 221 | return 0; |
222 | 222 | ||
223 | err_disable: | 223 | err_disable: |
224 | platform_set_drvdata(pdev, NULL); | ||
225 | if (jz4740_ohci->vbus) { | 224 | if (jz4740_ohci->vbus) { |
226 | regulator_disable(jz4740_ohci->vbus); | 225 | regulator_disable(jz4740_ohci->vbus); |
227 | regulator_put(jz4740_ohci->vbus); | 226 | regulator_put(jz4740_ohci->vbus); |
@@ -246,8 +245,6 @@ static int jz4740_ohci_remove(struct platform_device *pdev) | |||
246 | 245 | ||
247 | usb_remove_hcd(hcd); | 246 | usb_remove_hcd(hcd); |
248 | 247 | ||
249 | platform_set_drvdata(pdev, NULL); | ||
250 | |||
251 | if (jz4740_ohci->vbus) { | 248 | if (jz4740_ohci->vbus) { |
252 | regulator_disable(jz4740_ohci->vbus); | 249 | regulator_disable(jz4740_ohci->vbus); |
253 | regulator_put(jz4740_ohci->vbus); | 250 | regulator_put(jz4740_ohci->vbus); |
diff --git a/drivers/usb/host/ohci-nxp.c b/drivers/usb/host/ohci-nxp.c index 5d7eb72c5064..7d7d507d54e8 100644 --- a/drivers/usb/host/ohci-nxp.c +++ b/drivers/usb/host/ohci-nxp.c | |||
@@ -351,7 +351,6 @@ static int usb_hcd_nxp_remove(struct platform_device *pdev) | |||
351 | 351 | ||
352 | usb_remove_hcd(hcd); | 352 | usb_remove_hcd(hcd); |
353 | nxp_stop_hc(); | 353 | nxp_stop_hc(); |
354 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
355 | usb_put_hcd(hcd); | 354 | usb_put_hcd(hcd); |
356 | clk_disable(usb_pll_clk); | 355 | clk_disable(usb_pll_clk); |
357 | clk_put(usb_pll_clk); | 356 | clk_put(usb_pll_clk); |
@@ -360,8 +359,6 @@ static int usb_hcd_nxp_remove(struct platform_device *pdev) | |||
360 | i2c_unregister_device(isp1301_i2c_client); | 359 | i2c_unregister_device(isp1301_i2c_client); |
361 | isp1301_i2c_client = NULL; | 360 | isp1301_i2c_client = NULL; |
362 | 361 | ||
363 | platform_set_drvdata(pdev, NULL); | ||
364 | |||
365 | return 0; | 362 | return 0; |
366 | } | 363 | } |
367 | 364 | ||
diff --git a/drivers/usb/host/ohci-octeon.c b/drivers/usb/host/ohci-octeon.c index d44430d009f8..342dc7e543b8 100644 --- a/drivers/usb/host/ohci-octeon.c +++ b/drivers/usb/host/ohci-octeon.c | |||
@@ -196,8 +196,6 @@ static int ohci_octeon_drv_remove(struct platform_device *pdev) | |||
196 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | 196 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
197 | usb_put_hcd(hcd); | 197 | usb_put_hcd(hcd); |
198 | 198 | ||
199 | platform_set_drvdata(pdev, NULL); | ||
200 | |||
201 | return 0; | 199 | return 0; |
202 | } | 200 | } |
203 | 201 | ||
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index b1d32fb4a7ae..8747fa6a51b7 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c | |||
@@ -498,7 +498,6 @@ static int ohci_hcd_omap_drv_remove(struct platform_device *dev) | |||
498 | struct usb_hcd *hcd = platform_get_drvdata(dev); | 498 | struct usb_hcd *hcd = platform_get_drvdata(dev); |
499 | 499 | ||
500 | usb_hcd_omap_remove(hcd, dev); | 500 | usb_hcd_omap_remove(hcd, dev); |
501 | platform_set_drvdata(dev, NULL); | ||
502 | 501 | ||
503 | return 0; | 502 | return 0; |
504 | } | 503 | } |
diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c index 8663851c8d8e..8f713571a0b7 100644 --- a/drivers/usb/host/ohci-omap3.c +++ b/drivers/usb/host/ohci-omap3.c | |||
@@ -252,7 +252,7 @@ static struct platform_driver ohci_hcd_omap3_driver = { | |||
252 | .shutdown = ohci_hcd_omap3_shutdown, | 252 | .shutdown = ohci_hcd_omap3_shutdown, |
253 | .driver = { | 253 | .driver = { |
254 | .name = "ohci-omap3", | 254 | .name = "ohci-omap3", |
255 | .of_match_table = of_match_ptr(omap_ohci_dt_ids), | 255 | .of_match_table = omap_ohci_dt_ids, |
256 | }, | 256 | }, |
257 | }; | 257 | }; |
258 | 258 | ||
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 951514ef446d..08613e241894 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c | |||
@@ -14,12 +14,19 @@ | |||
14 | * This file is licenced under the GPL. | 14 | * This file is licenced under the GPL. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #ifndef CONFIG_PCI | ||
18 | #error "This file is PCI bus glue. CONFIG_PCI must be defined." | ||
19 | #endif | ||
20 | |||
21 | #include <linux/pci.h> | ||
22 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | #include <linux/kernel.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/pci.h> | ||
21 | #include <linux/usb.h> | ||
22 | #include <linux/usb/hcd.h> | ||
23 | |||
24 | #include "ohci.h" | ||
25 | #include "pci-quirks.h" | ||
26 | |||
27 | #define DRIVER_DESC "OHCI PCI platform driver" | ||
28 | |||
29 | static const char hcd_name[] = "ohci-pci"; | ||
23 | 30 | ||
24 | 31 | ||
25 | /*-------------------------------------------------------------------------*/ | 32 | /*-------------------------------------------------------------------------*/ |
@@ -123,13 +130,6 @@ static void ohci_quirk_nec_worker(struct work_struct *work) | |||
123 | struct ohci_hcd *ohci = container_of(work, struct ohci_hcd, nec_work); | 130 | struct ohci_hcd *ohci = container_of(work, struct ohci_hcd, nec_work); |
124 | int status; | 131 | int status; |
125 | 132 | ||
126 | status = ohci_init(ohci); | ||
127 | if (status != 0) { | ||
128 | ohci_err(ohci, "Restarting NEC controller failed in %s, %d\n", | ||
129 | "ohci_init", status); | ||
130 | return; | ||
131 | } | ||
132 | |||
133 | status = ohci_restart(ohci); | 133 | status = ohci_restart(ohci); |
134 | if (status != 0) | 134 | if (status != 0) |
135 | ohci_err(ohci, "Restarting NEC controller failed in %s, %d\n", | 135 | ohci_err(ohci, "Restarting NEC controller failed in %s, %d\n", |
@@ -175,19 +175,6 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd) | |||
175 | return 0; | 175 | return 0; |
176 | } | 176 | } |
177 | 177 | ||
178 | static void sb800_prefetch(struct ohci_hcd *ohci, int on) | ||
179 | { | ||
180 | struct pci_dev *pdev; | ||
181 | u16 misc; | ||
182 | |||
183 | pdev = to_pci_dev(ohci_to_hcd(ohci)->self.controller); | ||
184 | pci_read_config_word(pdev, 0x50, &misc); | ||
185 | if (on == 0) | ||
186 | pci_write_config_word(pdev, 0x50, misc & 0xfcff); | ||
187 | else | ||
188 | pci_write_config_word(pdev, 0x50, misc | 0x0300); | ||
189 | } | ||
190 | |||
191 | /* List of quirks for OHCI */ | 178 | /* List of quirks for OHCI */ |
192 | static const struct pci_device_id ohci_pci_quirks[] = { | 179 | static const struct pci_device_id ohci_pci_quirks[] = { |
193 | { | 180 | { |
@@ -249,10 +236,10 @@ static const struct pci_device_id ohci_pci_quirks[] = { | |||
249 | static int ohci_pci_reset (struct usb_hcd *hcd) | 236 | static int ohci_pci_reset (struct usb_hcd *hcd) |
250 | { | 237 | { |
251 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | 238 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
239 | struct pci_dev *pdev = to_pci_dev(hcd->self.controller); | ||
252 | int ret = 0; | 240 | int ret = 0; |
253 | 241 | ||
254 | if (hcd->self.controller) { | 242 | if (hcd->self.controller) { |
255 | struct pci_dev *pdev = to_pci_dev(hcd->self.controller); | ||
256 | const struct pci_device_id *quirk_id; | 243 | const struct pci_device_id *quirk_id; |
257 | 244 | ||
258 | quirk_id = pci_match_id(ohci_pci_quirks, pdev); | 245 | quirk_id = pci_match_id(ohci_pci_quirks, pdev); |
@@ -262,94 +249,25 @@ static int ohci_pci_reset (struct usb_hcd *hcd) | |||
262 | ret = quirk(hcd); | 249 | ret = quirk(hcd); |
263 | } | 250 | } |
264 | } | 251 | } |
265 | if (ret == 0) { | ||
266 | ohci_hcd_init (ohci); | ||
267 | return ohci_init (ohci); | ||
268 | } | ||
269 | return ret; | ||
270 | } | ||
271 | |||
272 | |||
273 | static int ohci_pci_start (struct usb_hcd *hcd) | ||
274 | { | ||
275 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | ||
276 | int ret; | ||
277 | |||
278 | #ifdef CONFIG_PM /* avoid warnings about unused pdev */ | ||
279 | if (hcd->self.controller) { | ||
280 | struct pci_dev *pdev = to_pci_dev(hcd->self.controller); | ||
281 | |||
282 | /* RWC may not be set for add-in PCI cards, since boot | ||
283 | * firmware probably ignored them. This transfers PCI | ||
284 | * PM wakeup capabilities. | ||
285 | */ | ||
286 | if (device_can_wakeup(&pdev->dev)) | ||
287 | ohci->hc_control |= OHCI_CTRL_RWC; | ||
288 | } | ||
289 | #endif /* CONFIG_PM */ | ||
290 | 252 | ||
291 | ret = ohci_run (ohci); | 253 | if (ret == 0) |
292 | if (ret < 0) { | 254 | ret = ohci_setup(hcd); |
293 | ohci_err (ohci, "can't start\n"); | 255 | /* |
294 | ohci_stop (hcd); | 256 | * After ohci setup RWC may not be set for add-in PCI cards. |
295 | } | 257 | * This transfers PCI PM wakeup capabilities. |
258 | */ | ||
259 | if (device_can_wakeup(&pdev->dev)) | ||
260 | ohci->hc_control |= OHCI_CTRL_RWC; | ||
296 | return ret; | 261 | return ret; |
297 | } | 262 | } |
298 | 263 | ||
264 | static struct hc_driver __read_mostly ohci_pci_hc_driver; | ||
299 | 265 | ||
300 | /*-------------------------------------------------------------------------*/ | 266 | static const struct ohci_driver_overrides pci_overrides __initconst = { |
301 | 267 | .product_desc = "OHCI PCI host controller", | |
302 | static const struct hc_driver ohci_pci_hc_driver = { | ||
303 | .description = hcd_name, | ||
304 | .product_desc = "OHCI Host Controller", | ||
305 | .hcd_priv_size = sizeof(struct ohci_hcd), | ||
306 | |||
307 | /* | ||
308 | * generic hardware linkage | ||
309 | */ | ||
310 | .irq = ohci_irq, | ||
311 | .flags = HCD_MEMORY | HCD_USB11, | ||
312 | |||
313 | /* | ||
314 | * basic lifecycle operations | ||
315 | */ | ||
316 | .reset = ohci_pci_reset, | 268 | .reset = ohci_pci_reset, |
317 | .start = ohci_pci_start, | ||
318 | .stop = ohci_stop, | ||
319 | .shutdown = ohci_shutdown, | ||
320 | |||
321 | #ifdef CONFIG_PM | ||
322 | .pci_suspend = ohci_suspend, | ||
323 | .pci_resume = ohci_resume, | ||
324 | #endif | ||
325 | |||
326 | /* | ||
327 | * managing i/o requests and associated device resources | ||
328 | */ | ||
329 | .urb_enqueue = ohci_urb_enqueue, | ||
330 | .urb_dequeue = ohci_urb_dequeue, | ||
331 | .endpoint_disable = ohci_endpoint_disable, | ||
332 | |||
333 | /* | ||
334 | * scheduling support | ||
335 | */ | ||
336 | .get_frame_number = ohci_get_frame, | ||
337 | |||
338 | /* | ||
339 | * root hub support | ||
340 | */ | ||
341 | .hub_status_data = ohci_hub_status_data, | ||
342 | .hub_control = ohci_hub_control, | ||
343 | #ifdef CONFIG_PM | ||
344 | .bus_suspend = ohci_bus_suspend, | ||
345 | .bus_resume = ohci_bus_resume, | ||
346 | #endif | ||
347 | .start_port_reset = ohci_start_port_reset, | ||
348 | }; | 269 | }; |
349 | 270 | ||
350 | /*-------------------------------------------------------------------------*/ | ||
351 | |||
352 | |||
353 | static const struct pci_device_id pci_ids [] = { { | 271 | static const struct pci_device_id pci_ids [] = { { |
354 | /* handle any USB OHCI controller */ | 272 | /* handle any USB OHCI controller */ |
355 | PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_OHCI, ~0), | 273 | PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_OHCI, ~0), |
@@ -377,3 +295,24 @@ static struct pci_driver ohci_pci_driver = { | |||
377 | }, | 295 | }, |
378 | #endif | 296 | #endif |
379 | }; | 297 | }; |
298 | |||
299 | static int __init ohci_pci_init(void) | ||
300 | { | ||
301 | if (usb_disabled()) | ||
302 | return -ENODEV; | ||
303 | |||
304 | pr_info("%s: " DRIVER_DESC "\n", hcd_name); | ||
305 | |||
306 | ohci_init_driver(&ohci_pci_hc_driver, &pci_overrides); | ||
307 | return pci_register_driver(&ohci_pci_driver); | ||
308 | } | ||
309 | module_init(ohci_pci_init); | ||
310 | |||
311 | static void __exit ohci_pci_cleanup(void) | ||
312 | { | ||
313 | pci_unregister_driver(&ohci_pci_driver); | ||
314 | } | ||
315 | module_exit(ohci_pci_cleanup); | ||
316 | |||
317 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
318 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c index c3e7287f7921..bc30475c3a23 100644 --- a/drivers/usb/host/ohci-platform.c +++ b/drivers/usb/host/ohci-platform.c | |||
@@ -13,16 +13,28 @@ | |||
13 | * | 13 | * |
14 | * Licensed under the GNU/GPL. See COPYING for details. | 14 | * Licensed under the GNU/GPL. See COPYING for details. |
15 | */ | 15 | */ |
16 | |||
17 | #include <linux/hrtimer.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/module.h> | ||
16 | #include <linux/err.h> | 21 | #include <linux/err.h> |
17 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
18 | #include <linux/usb/ohci_pdriver.h> | 23 | #include <linux/usb/ohci_pdriver.h> |
24 | #include <linux/usb.h> | ||
25 | #include <linux/usb/hcd.h> | ||
26 | |||
27 | #include "ohci.h" | ||
28 | |||
29 | #define DRIVER_DESC "OHCI generic platform driver" | ||
30 | |||
31 | static const char hcd_name[] = "ohci-platform"; | ||
19 | 32 | ||
20 | static int ohci_platform_reset(struct usb_hcd *hcd) | 33 | static int ohci_platform_reset(struct usb_hcd *hcd) |
21 | { | 34 | { |
22 | struct platform_device *pdev = to_platform_device(hcd->self.controller); | 35 | struct platform_device *pdev = to_platform_device(hcd->self.controller); |
23 | struct usb_ohci_pdata *pdata = pdev->dev.platform_data; | 36 | struct usb_ohci_pdata *pdata = pdev->dev.platform_data; |
24 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); | 37 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); |
25 | int err; | ||
26 | 38 | ||
27 | if (pdata->big_endian_desc) | 39 | if (pdata->big_endian_desc) |
28 | ohci->flags |= OHCI_QUIRK_BE_DESC; | 40 | ohci->flags |= OHCI_QUIRK_BE_DESC; |
@@ -30,58 +42,17 @@ static int ohci_platform_reset(struct usb_hcd *hcd) | |||
30 | ohci->flags |= OHCI_QUIRK_BE_MMIO; | 42 | ohci->flags |= OHCI_QUIRK_BE_MMIO; |
31 | if (pdata->no_big_frame_no) | 43 | if (pdata->no_big_frame_no) |
32 | ohci->flags |= OHCI_QUIRK_FRAME_NO; | 44 | ohci->flags |= OHCI_QUIRK_FRAME_NO; |
33 | |||
34 | ohci_hcd_init(ohci); | ||
35 | |||
36 | if (pdata->num_ports) | 45 | if (pdata->num_ports) |
37 | ohci->num_ports = pdata->num_ports; | 46 | ohci->num_ports = pdata->num_ports; |
38 | 47 | ||
39 | err = ohci_init(ohci); | 48 | return ohci_setup(hcd); |
40 | |||
41 | return err; | ||
42 | } | ||
43 | |||
44 | static int ohci_platform_start(struct usb_hcd *hcd) | ||
45 | { | ||
46 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); | ||
47 | int err; | ||
48 | |||
49 | err = ohci_run(ohci); | ||
50 | if (err < 0) { | ||
51 | ohci_err(ohci, "can't start\n"); | ||
52 | ohci_stop(hcd); | ||
53 | } | ||
54 | |||
55 | return err; | ||
56 | } | 49 | } |
57 | 50 | ||
58 | static const struct hc_driver ohci_platform_hc_driver = { | 51 | static struct hc_driver __read_mostly ohci_platform_hc_driver; |
59 | .description = hcd_name, | ||
60 | .product_desc = "Generic Platform OHCI Controller", | ||
61 | .hcd_priv_size = sizeof(struct ohci_hcd), | ||
62 | 52 | ||
63 | .irq = ohci_irq, | 53 | static const struct ohci_driver_overrides platform_overrides __initconst = { |
64 | .flags = HCD_MEMORY | HCD_USB11, | 54 | .product_desc = "Generic Platform OHCI controller", |
65 | 55 | .reset = ohci_platform_reset, | |
66 | .reset = ohci_platform_reset, | ||
67 | .start = ohci_platform_start, | ||
68 | .stop = ohci_stop, | ||
69 | .shutdown = ohci_shutdown, | ||
70 | |||
71 | .urb_enqueue = ohci_urb_enqueue, | ||
72 | .urb_dequeue = ohci_urb_dequeue, | ||
73 | .endpoint_disable = ohci_endpoint_disable, | ||
74 | |||
75 | .get_frame_number = ohci_get_frame, | ||
76 | |||
77 | .hub_status_data = ohci_hub_status_data, | ||
78 | .hub_control = ohci_hub_control, | ||
79 | #ifdef CONFIG_PM | ||
80 | .bus_suspend = ohci_bus_suspend, | ||
81 | .bus_resume = ohci_bus_resume, | ||
82 | #endif | ||
83 | |||
84 | .start_port_reset = ohci_start_port_reset, | ||
85 | }; | 56 | }; |
86 | 57 | ||
87 | static int ohci_platform_probe(struct platform_device *dev) | 58 | static int ohci_platform_probe(struct platform_device *dev) |
@@ -157,7 +128,6 @@ static int ohci_platform_remove(struct platform_device *dev) | |||
157 | 128 | ||
158 | usb_remove_hcd(hcd); | 129 | usb_remove_hcd(hcd); |
159 | usb_put_hcd(hcd); | 130 | usb_put_hcd(hcd); |
160 | platform_set_drvdata(dev, NULL); | ||
161 | 131 | ||
162 | if (pdata->power_off) | 132 | if (pdata->power_off) |
163 | pdata->power_off(dev); | 133 | pdata->power_off(dev); |
@@ -223,3 +193,26 @@ static struct platform_driver ohci_platform_driver = { | |||
223 | .pm = &ohci_platform_pm_ops, | 193 | .pm = &ohci_platform_pm_ops, |
224 | } | 194 | } |
225 | }; | 195 | }; |
196 | |||
197 | static int __init ohci_platform_init(void) | ||
198 | { | ||
199 | if (usb_disabled()) | ||
200 | return -ENODEV; | ||
201 | |||
202 | pr_info("%s: " DRIVER_DESC "\n", hcd_name); | ||
203 | |||
204 | ohci_init_driver(&ohci_platform_hc_driver, &platform_overrides); | ||
205 | return platform_driver_register(&ohci_platform_driver); | ||
206 | } | ||
207 | module_init(ohci_platform_init); | ||
208 | |||
209 | static void __exit ohci_platform_cleanup(void) | ||
210 | { | ||
211 | platform_driver_unregister(&ohci_platform_driver); | ||
212 | } | ||
213 | module_exit(ohci_platform_cleanup); | ||
214 | |||
215 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
216 | MODULE_AUTHOR("Hauke Mehrtens"); | ||
217 | MODULE_AUTHOR("Alan Stern"); | ||
218 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c index 64c2ed9ff95e..8294e2fcc2f6 100644 --- a/drivers/usb/host/ohci-ppc-of.c +++ b/drivers/usb/host/ohci-ppc-of.c | |||
@@ -185,8 +185,7 @@ err_rmr: | |||
185 | 185 | ||
186 | static int ohci_hcd_ppc_of_remove(struct platform_device *op) | 186 | static int ohci_hcd_ppc_of_remove(struct platform_device *op) |
187 | { | 187 | { |
188 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); | 188 | struct usb_hcd *hcd = platform_get_drvdata(op); |
189 | dev_set_drvdata(&op->dev, NULL); | ||
190 | 189 | ||
191 | dev_dbg(&op->dev, "stopping PPC-OF USB Controller\n"); | 190 | dev_dbg(&op->dev, "stopping PPC-OF USB Controller\n"); |
192 | 191 | ||
@@ -203,7 +202,7 @@ static int ohci_hcd_ppc_of_remove(struct platform_device *op) | |||
203 | 202 | ||
204 | static void ohci_hcd_ppc_of_shutdown(struct platform_device *op) | 203 | static void ohci_hcd_ppc_of_shutdown(struct platform_device *op) |
205 | { | 204 | { |
206 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); | 205 | struct usb_hcd *hcd = platform_get_drvdata(op); |
207 | 206 | ||
208 | if (hcd->driver->shutdown) | 207 | if (hcd->driver->shutdown) |
209 | hcd->driver->shutdown(hcd); | 208 | hcd->driver->shutdown(hcd); |
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index 279b2ef17411..3a9c01d8b79c 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c | |||
@@ -556,7 +556,6 @@ static int ohci_hcd_pxa27x_drv_remove(struct platform_device *pdev) | |||
556 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | 556 | struct usb_hcd *hcd = platform_get_drvdata(pdev); |
557 | 557 | ||
558 | usb_hcd_pxa27x_remove(hcd, pdev); | 558 | usb_hcd_pxa27x_remove(hcd, pdev); |
559 | platform_set_drvdata(pdev, NULL); | ||
560 | return 0; | 559 | return 0; |
561 | } | 560 | } |
562 | 561 | ||
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index 88731b7c5f42..df4a6707322d 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c | |||
@@ -41,6 +41,7 @@ finish_urb(struct ohci_hcd *ohci, struct urb *urb, int status) | |||
41 | __releases(ohci->lock) | 41 | __releases(ohci->lock) |
42 | __acquires(ohci->lock) | 42 | __acquires(ohci->lock) |
43 | { | 43 | { |
44 | struct device *dev = ohci_to_hcd(ohci)->self.controller; | ||
44 | // ASSERT (urb->hcpriv != 0); | 45 | // ASSERT (urb->hcpriv != 0); |
45 | 46 | ||
46 | urb_free_priv (ohci, urb->hcpriv); | 47 | urb_free_priv (ohci, urb->hcpriv); |
@@ -55,7 +56,7 @@ __acquires(ohci->lock) | |||
55 | if (quirk_amdiso(ohci)) | 56 | if (quirk_amdiso(ohci)) |
56 | usb_amd_quirk_pll_enable(); | 57 | usb_amd_quirk_pll_enable(); |
57 | if (quirk_amdprefetch(ohci)) | 58 | if (quirk_amdprefetch(ohci)) |
58 | sb800_prefetch(ohci, 0); | 59 | sb800_prefetch(dev, 0); |
59 | } | 60 | } |
60 | break; | 61 | break; |
61 | case PIPE_INTERRUPT: | 62 | case PIPE_INTERRUPT: |
@@ -580,6 +581,7 @@ static void td_submit_urb ( | |||
580 | struct urb *urb | 581 | struct urb *urb |
581 | ) { | 582 | ) { |
582 | struct urb_priv *urb_priv = urb->hcpriv; | 583 | struct urb_priv *urb_priv = urb->hcpriv; |
584 | struct device *dev = ohci_to_hcd(ohci)->self.controller; | ||
583 | dma_addr_t data; | 585 | dma_addr_t data; |
584 | int data_len = urb->transfer_buffer_length; | 586 | int data_len = urb->transfer_buffer_length; |
585 | int cnt = 0; | 587 | int cnt = 0; |
@@ -689,7 +691,7 @@ static void td_submit_urb ( | |||
689 | if (quirk_amdiso(ohci)) | 691 | if (quirk_amdiso(ohci)) |
690 | usb_amd_quirk_pll_disable(); | 692 | usb_amd_quirk_pll_disable(); |
691 | if (quirk_amdprefetch(ohci)) | 693 | if (quirk_amdprefetch(ohci)) |
692 | sb800_prefetch(ohci, 1); | 694 | sb800_prefetch(dev, 1); |
693 | } | 695 | } |
694 | periodic = ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs++ == 0 | 696 | periodic = ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs++ == 0 |
695 | && ohci_to_hcd(ohci)->self.bandwidth_int_reqs == 0; | 697 | && ohci_to_hcd(ohci)->self.bandwidth_int_reqs == 0; |
diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c index 3b5b908fd47b..d479d5ddab88 100644 --- a/drivers/usb/host/ohci-sm501.c +++ b/drivers/usb/host/ohci-sm501.c | |||
@@ -207,7 +207,6 @@ static int ohci_hcd_sm501_drv_remove(struct platform_device *pdev) | |||
207 | sm501_modify_reg(pdev->dev.parent, SM501_IRQ_MASK, 0, 1 << 6); | 207 | sm501_modify_reg(pdev->dev.parent, SM501_IRQ_MASK, 0, 1 << 6); |
208 | sm501_unit_power(pdev->dev.parent, SM501_GATE_USB_HOST, 0); | 208 | sm501_unit_power(pdev->dev.parent, SM501_GATE_USB_HOST, 0); |
209 | 209 | ||
210 | platform_set_drvdata(pdev, NULL); | ||
211 | return 0; | 210 | return 0; |
212 | } | 211 | } |
213 | 212 | ||
diff --git a/drivers/usb/host/ohci-spear.c b/drivers/usb/host/ohci-spear.c index 3e19e0170d11..cc9dd9e4f05e 100644 --- a/drivers/usb/host/ohci-spear.c +++ b/drivers/usb/host/ohci-spear.c | |||
@@ -179,8 +179,6 @@ static int spear_ohci_hcd_drv_remove(struct platform_device *pdev) | |||
179 | spear_stop_ohci(ohci_p); | 179 | spear_stop_ohci(ohci_p); |
180 | 180 | ||
181 | usb_put_hcd(hcd); | 181 | usb_put_hcd(hcd); |
182 | |||
183 | platform_set_drvdata(pdev, NULL); | ||
184 | return 0; | 182 | return 0; |
185 | } | 183 | } |
186 | 184 | ||
@@ -232,7 +230,7 @@ static struct platform_driver spear_ohci_hcd_driver = { | |||
232 | .driver = { | 230 | .driver = { |
233 | .owner = THIS_MODULE, | 231 | .owner = THIS_MODULE, |
234 | .name = "spear-ohci", | 232 | .name = "spear-ohci", |
235 | .of_match_table = of_match_ptr(spear_ohci_id_table), | 233 | .of_match_table = spear_ohci_id_table, |
236 | }, | 234 | }, |
237 | }; | 235 | }; |
238 | 236 | ||
diff --git a/drivers/usb/host/ohci-tilegx.c b/drivers/usb/host/ohci-tilegx.c index ea73009de623..197d514fe0d1 100644 --- a/drivers/usb/host/ohci-tilegx.c +++ b/drivers/usb/host/ohci-tilegx.c | |||
@@ -182,7 +182,6 @@ static int ohci_hcd_tilegx_drv_remove(struct platform_device *pdev) | |||
182 | tilegx_stop_ohc(); | 182 | tilegx_stop_ohc(); |
183 | gxio_usb_host_destroy(&pdata->usb_ctx); | 183 | gxio_usb_host_destroy(&pdata->usb_ctx); |
184 | destroy_irq(pdata->irq); | 184 | destroy_irq(pdata->irq); |
185 | platform_set_drvdata(pdev, NULL); | ||
186 | 185 | ||
187 | return 0; | 186 | return 0; |
188 | } | 187 | } |
diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c index 5e3a6deb62b1..ecb09a5ada9c 100644 --- a/drivers/usb/host/ohci-tmio.c +++ b/drivers/usb/host/ohci-tmio.c | |||
@@ -287,8 +287,6 @@ static int ohci_hcd_tmio_drv_remove(struct platform_device *dev) | |||
287 | iounmap(tmio->ccr); | 287 | iounmap(tmio->ccr); |
288 | usb_put_hcd(hcd); | 288 | usb_put_hcd(hcd); |
289 | 289 | ||
290 | platform_set_drvdata(dev, NULL); | ||
291 | |||
292 | return 0; | 290 | return 0; |
293 | } | 291 | } |
294 | 292 | ||
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index d3299143d9e2..e2e5faa5a402 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h | |||
@@ -421,6 +421,9 @@ struct ohci_hcd { | |||
421 | struct dentry *debug_periodic; | 421 | struct dentry *debug_periodic; |
422 | struct dentry *debug_registers; | 422 | struct dentry *debug_registers; |
423 | #endif | 423 | #endif |
424 | /* platform-specific data -- must come last */ | ||
425 | unsigned long priv[0] __aligned(sizeof(s64)); | ||
426 | |||
424 | }; | 427 | }; |
425 | 428 | ||
426 | #ifdef CONFIG_PCI | 429 | #ifdef CONFIG_PCI |
@@ -718,3 +721,20 @@ static inline u32 roothub_status (struct ohci_hcd *hc) | |||
718 | { return ohci_readl (hc, &hc->regs->roothub.status); } | 721 | { return ohci_readl (hc, &hc->regs->roothub.status); } |
719 | static inline u32 roothub_portstatus (struct ohci_hcd *hc, int i) | 722 | static inline u32 roothub_portstatus (struct ohci_hcd *hc, int i) |
720 | { return read_roothub (hc, portstatus [i], 0xffe0fce0); } | 723 | { return read_roothub (hc, portstatus [i], 0xffe0fce0); } |
724 | |||
725 | /* Declarations of things exported for use by ohci platform drivers */ | ||
726 | |||
727 | struct ohci_driver_overrides { | ||
728 | const char *product_desc; | ||
729 | size_t extra_priv_size; | ||
730 | int (*reset)(struct usb_hcd *hcd); | ||
731 | }; | ||
732 | |||
733 | extern void ohci_init_driver(struct hc_driver *drv, | ||
734 | const struct ohci_driver_overrides *over); | ||
735 | extern int ohci_restart(struct ohci_hcd *ohci); | ||
736 | extern int ohci_setup(struct usb_hcd *hcd); | ||
737 | #ifdef CONFIG_PM | ||
738 | extern int ohci_suspend(struct usb_hcd *hcd, bool do_wakeup); | ||
739 | extern int ohci_resume(struct usb_hcd *hcd, bool hibernated); | ||
740 | #endif | ||
diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index 0f401dbfaf07..4a6df2d8f902 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c | |||
@@ -3874,7 +3874,6 @@ static int oxu_drv_probe(struct platform_device *pdev) | |||
3874 | 3874 | ||
3875 | error_init: | 3875 | error_init: |
3876 | kfree(info); | 3876 | kfree(info); |
3877 | platform_set_drvdata(pdev, NULL); | ||
3878 | 3877 | ||
3879 | error_alloc: | 3878 | error_alloc: |
3880 | iounmap(base); | 3879 | iounmap(base); |
@@ -3907,7 +3906,6 @@ static int oxu_drv_remove(struct platform_device *pdev) | |||
3907 | release_mem_region(memstart, memlen); | 3906 | release_mem_region(memstart, memlen); |
3908 | 3907 | ||
3909 | kfree(info); | 3908 | kfree(info); |
3910 | platform_set_drvdata(pdev, NULL); | ||
3911 | 3909 | ||
3912 | return 0; | 3910 | return 0; |
3913 | } | 3911 | } |
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 4c338ec03a07..b9848e4d3d44 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c | |||
@@ -91,6 +91,19 @@ static struct amd_chipset_info { | |||
91 | 91 | ||
92 | static DEFINE_SPINLOCK(amd_lock); | 92 | static DEFINE_SPINLOCK(amd_lock); |
93 | 93 | ||
94 | void sb800_prefetch(struct device *dev, int on) | ||
95 | { | ||
96 | u16 misc; | ||
97 | struct pci_dev *pdev = to_pci_dev(dev); | ||
98 | |||
99 | pci_read_config_word(pdev, 0x50, &misc); | ||
100 | if (on == 0) | ||
101 | pci_write_config_word(pdev, 0x50, misc & 0xfcff); | ||
102 | else | ||
103 | pci_write_config_word(pdev, 0x50, misc | 0x0300); | ||
104 | } | ||
105 | EXPORT_SYMBOL_GPL(sb800_prefetch); | ||
106 | |||
94 | int usb_amd_find_chipset_info(void) | 107 | int usb_amd_find_chipset_info(void) |
95 | { | 108 | { |
96 | u8 rev = 0; | 109 | u8 rev = 0; |
diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h index 7f69a39163ce..4b8a2092432f 100644 --- a/drivers/usb/host/pci-quirks.h +++ b/drivers/usb/host/pci-quirks.h | |||
@@ -11,11 +11,13 @@ void usb_amd_quirk_pll_enable(void); | |||
11 | bool usb_is_intel_switchable_xhci(struct pci_dev *pdev); | 11 | bool usb_is_intel_switchable_xhci(struct pci_dev *pdev); |
12 | void usb_enable_xhci_ports(struct pci_dev *xhci_pdev); | 12 | void usb_enable_xhci_ports(struct pci_dev *xhci_pdev); |
13 | void usb_disable_xhci_ports(struct pci_dev *xhci_pdev); | 13 | void usb_disable_xhci_ports(struct pci_dev *xhci_pdev); |
14 | void sb800_prefetch(struct device *dev, int on); | ||
14 | #else | 15 | #else |
15 | static inline void usb_amd_quirk_pll_disable(void) {} | 16 | static inline void usb_amd_quirk_pll_disable(void) {} |
16 | static inline void usb_amd_quirk_pll_enable(void) {} | 17 | static inline void usb_amd_quirk_pll_enable(void) {} |
17 | static inline void usb_amd_dev_put(void) {} | 18 | static inline void usb_amd_dev_put(void) {} |
18 | static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {} | 19 | static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {} |
20 | static inline void sb800_prefetch(struct device *dev, int on) {} | ||
19 | #endif /* CONFIG_PCI */ | 21 | #endif /* CONFIG_PCI */ |
20 | 22 | ||
21 | #endif /* __LINUX_USB_PCI_QUIRKS_H */ | 23 | #endif /* __LINUX_USB_PCI_QUIRKS_H */ |
diff --git a/drivers/usb/host/uhci-grlib.c b/drivers/usb/host/uhci-grlib.c index 511bfc46dd78..53c23ff7d685 100644 --- a/drivers/usb/host/uhci-grlib.c +++ b/drivers/usb/host/uhci-grlib.c | |||
@@ -157,9 +157,7 @@ err_rmr: | |||
157 | 157 | ||
158 | static int uhci_hcd_grlib_remove(struct platform_device *op) | 158 | static int uhci_hcd_grlib_remove(struct platform_device *op) |
159 | { | 159 | { |
160 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); | 160 | struct usb_hcd *hcd = platform_get_drvdata(op); |
161 | |||
162 | dev_set_drvdata(&op->dev, NULL); | ||
163 | 161 | ||
164 | dev_dbg(&op->dev, "stopping GRLIB GRUSBHC UHCI USB Controller\n"); | 162 | dev_dbg(&op->dev, "stopping GRLIB GRUSBHC UHCI USB Controller\n"); |
165 | 163 | ||
@@ -183,7 +181,7 @@ static int uhci_hcd_grlib_remove(struct platform_device *op) | |||
183 | */ | 181 | */ |
184 | static void uhci_hcd_grlib_shutdown(struct platform_device *op) | 182 | static void uhci_hcd_grlib_shutdown(struct platform_device *op) |
185 | { | 183 | { |
186 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); | 184 | struct usb_hcd *hcd = platform_get_drvdata(op); |
187 | 185 | ||
188 | uhci_hc_died(hcd_to_uhci(hcd)); | 186 | uhci_hc_died(hcd_to_uhci(hcd)); |
189 | } | 187 | } |
diff --git a/drivers/usb/host/uhci-platform.c b/drivers/usb/host/uhci-platform.c index f1db61ada6a8..d033a0ec7f0d 100644 --- a/drivers/usb/host/uhci-platform.c +++ b/drivers/usb/host/uhci-platform.c | |||
@@ -130,7 +130,6 @@ static int uhci_hcd_platform_remove(struct platform_device *pdev) | |||
130 | iounmap(hcd->regs); | 130 | iounmap(hcd->regs); |
131 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | 131 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
132 | usb_put_hcd(hcd); | 132 | usb_put_hcd(hcd); |
133 | platform_set_drvdata(pdev, NULL); | ||
134 | 133 | ||
135 | return 0; | 134 | return 0; |
136 | } | 135 | } |
@@ -144,7 +143,7 @@ static int uhci_hcd_platform_remove(struct platform_device *pdev) | |||
144 | */ | 143 | */ |
145 | static void uhci_hcd_platform_shutdown(struct platform_device *op) | 144 | static void uhci_hcd_platform_shutdown(struct platform_device *op) |
146 | { | 145 | { |
147 | struct usb_hcd *hcd = dev_get_drvdata(&op->dev); | 146 | struct usb_hcd *hcd = platform_get_drvdata(op); |
148 | 147 | ||
149 | uhci_hc_died(hcd_to_uhci(hcd)); | 148 | uhci_hc_died(hcd_to_uhci(hcd)); |
150 | } | 149 | } |
@@ -161,6 +160,6 @@ static struct platform_driver uhci_platform_driver = { | |||
161 | .driver = { | 160 | .driver = { |
162 | .name = "platform-uhci", | 161 | .name = "platform-uhci", |
163 | .owner = THIS_MODULE, | 162 | .owner = THIS_MODULE, |
164 | .of_match_table = of_match_ptr(platform_uhci_ids), | 163 | .of_match_table = platform_uhci_ids, |
165 | }, | 164 | }, |
166 | }; | 165 | }; |
diff --git a/drivers/usb/host/whci/hcd.c b/drivers/usb/host/whci/hcd.c index c3a647816af0..ecc88db804e0 100644 --- a/drivers/usb/host/whci/hcd.c +++ b/drivers/usb/host/whci/hcd.c | |||
@@ -231,8 +231,6 @@ static struct hc_driver whc_hc_driver = { | |||
231 | 231 | ||
232 | .hub_status_data = wusbhc_rh_status_data, | 232 | .hub_status_data = wusbhc_rh_status_data, |
233 | .hub_control = wusbhc_rh_control, | 233 | .hub_control = wusbhc_rh_control, |
234 | .bus_suspend = wusbhc_rh_suspend, | ||
235 | .bus_resume = wusbhc_rh_resume, | ||
236 | .start_port_reset = wusbhc_rh_start_port_reset, | 234 | .start_port_reset = wusbhc_rh_start_port_reset, |
237 | }; | 235 | }; |
238 | 236 | ||
diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c index 5f3a7c74aa8d..5d5e58fdeccc 100644 --- a/drivers/usb/host/xhci-dbg.c +++ b/drivers/usb/host/xhci-dbg.c | |||
@@ -503,11 +503,14 @@ static void xhci_dbg_ep_ctx(struct xhci_hcd *xhci, | |||
503 | if (last_ep < 31) | 503 | if (last_ep < 31) |
504 | last_ep_ctx = last_ep + 1; | 504 | last_ep_ctx = last_ep + 1; |
505 | for (i = 0; i < last_ep_ctx; ++i) { | 505 | for (i = 0; i < last_ep_ctx; ++i) { |
506 | unsigned int epaddr = xhci_get_endpoint_address(i); | ||
506 | struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, ctx, i); | 507 | struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, ctx, i); |
507 | dma_addr_t dma = ctx->dma + | 508 | dma_addr_t dma = ctx->dma + |
508 | ((unsigned long)ep_ctx - (unsigned long)ctx->bytes); | 509 | ((unsigned long)ep_ctx - (unsigned long)ctx->bytes); |
509 | 510 | ||
510 | xhci_dbg(xhci, "Endpoint %02d Context:\n", i); | 511 | xhci_dbg(xhci, "%s Endpoint %02d Context (ep_index %02d):\n", |
512 | usb_endpoint_out(epaddr) ? "OUT" : "IN", | ||
513 | epaddr & USB_ENDPOINT_NUMBER_MASK, i); | ||
511 | xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - ep_info\n", | 514 | xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - ep_info\n", |
512 | &ep_ctx->ep_info, | 515 | &ep_ctx->ep_info, |
513 | (unsigned long long)dma, ep_ctx->ep_info); | 516 | (unsigned long long)dma, ep_ctx->ep_info); |
@@ -550,6 +553,11 @@ void xhci_dbg_ctx(struct xhci_hcd *xhci, | |||
550 | if (ctx->type == XHCI_CTX_TYPE_INPUT) { | 553 | if (ctx->type == XHCI_CTX_TYPE_INPUT) { |
551 | struct xhci_input_control_ctx *ctrl_ctx = | 554 | struct xhci_input_control_ctx *ctrl_ctx = |
552 | xhci_get_input_control_ctx(xhci, ctx); | 555 | xhci_get_input_control_ctx(xhci, ctx); |
556 | if (!ctrl_ctx) { | ||
557 | xhci_warn(xhci, "Could not get input context, bad type.\n"); | ||
558 | return; | ||
559 | } | ||
560 | |||
553 | xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - drop flags\n", | 561 | xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - drop flags\n", |
554 | &ctrl_ctx->drop_flags, (unsigned long long)dma, | 562 | &ctrl_ctx->drop_flags, (unsigned long long)dma, |
555 | ctrl_ctx->drop_flags); | 563 | ctrl_ctx->drop_flags); |
diff --git a/drivers/usb/host/xhci-ext-caps.h b/drivers/usb/host/xhci-ext-caps.h index 377f4242dabb..8d7a1324e2f3 100644 --- a/drivers/usb/host/xhci-ext-caps.h +++ b/drivers/usb/host/xhci-ext-caps.h | |||
@@ -71,6 +71,7 @@ | |||
71 | 71 | ||
72 | /* USB 2.0 xHCI 1.0 hardware LMP capability - section 7.2.2.1.3.2 */ | 72 | /* USB 2.0 xHCI 1.0 hardware LMP capability - section 7.2.2.1.3.2 */ |
73 | #define XHCI_HLC (1 << 19) | 73 | #define XHCI_HLC (1 << 19) |
74 | #define XHCI_BLC (1 << 19) | ||
74 | 75 | ||
75 | /* command register values to disable interrupts and halt the HC */ | 76 | /* command register values to disable interrupts and halt the HC */ |
76 | /* start/stop HC execution - do not write unless HC is halted*/ | 77 | /* start/stop HC execution - do not write unless HC is halted*/ |
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 187a3ec1069a..1d3545943c50 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c | |||
@@ -867,18 +867,18 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
867 | case USB_PORT_FEAT_U1_TIMEOUT: | 867 | case USB_PORT_FEAT_U1_TIMEOUT: |
868 | if (hcd->speed != HCD_USB3) | 868 | if (hcd->speed != HCD_USB3) |
869 | goto error; | 869 | goto error; |
870 | temp = xhci_readl(xhci, port_array[wIndex] + 1); | 870 | temp = xhci_readl(xhci, port_array[wIndex] + PORTPMSC); |
871 | temp &= ~PORT_U1_TIMEOUT_MASK; | 871 | temp &= ~PORT_U1_TIMEOUT_MASK; |
872 | temp |= PORT_U1_TIMEOUT(timeout); | 872 | temp |= PORT_U1_TIMEOUT(timeout); |
873 | xhci_writel(xhci, temp, port_array[wIndex] + 1); | 873 | xhci_writel(xhci, temp, port_array[wIndex] + PORTPMSC); |
874 | break; | 874 | break; |
875 | case USB_PORT_FEAT_U2_TIMEOUT: | 875 | case USB_PORT_FEAT_U2_TIMEOUT: |
876 | if (hcd->speed != HCD_USB3) | 876 | if (hcd->speed != HCD_USB3) |
877 | goto error; | 877 | goto error; |
878 | temp = xhci_readl(xhci, port_array[wIndex] + 1); | 878 | temp = xhci_readl(xhci, port_array[wIndex] + PORTPMSC); |
879 | temp &= ~PORT_U2_TIMEOUT_MASK; | 879 | temp &= ~PORT_U2_TIMEOUT_MASK; |
880 | temp |= PORT_U2_TIMEOUT(timeout); | 880 | temp |= PORT_U2_TIMEOUT(timeout); |
881 | xhci_writel(xhci, temp, port_array[wIndex] + 1); | 881 | xhci_writel(xhci, temp, port_array[wIndex] + PORTPMSC); |
882 | break; | 882 | break; |
883 | default: | 883 | default: |
884 | goto error; | 884 | goto error; |
@@ -1098,10 +1098,8 @@ int xhci_bus_suspend(struct usb_hcd *hcd) | |||
1098 | __le32 __iomem *addr; | 1098 | __le32 __iomem *addr; |
1099 | u32 tmp; | 1099 | u32 tmp; |
1100 | 1100 | ||
1101 | /* Add one to the port status register address to get | 1101 | /* Get the port power control register address. */ |
1102 | * the port power control register address. | 1102 | addr = port_array[port_index] + PORTPMSC; |
1103 | */ | ||
1104 | addr = port_array[port_index] + 1; | ||
1105 | tmp = xhci_readl(xhci, addr); | 1103 | tmp = xhci_readl(xhci, addr); |
1106 | tmp |= PORT_RWE; | 1104 | tmp |= PORT_RWE; |
1107 | xhci_writel(xhci, tmp, addr); | 1105 | xhci_writel(xhci, tmp, addr); |
@@ -1193,7 +1191,7 @@ int xhci_bus_resume(struct usb_hcd *hcd) | |||
1193 | /* Add one to the port status register address to get | 1191 | /* Add one to the port status register address to get |
1194 | * the port power control register address. | 1192 | * the port power control register address. |
1195 | */ | 1193 | */ |
1196 | addr = port_array[port_index] + 1; | 1194 | addr = port_array[port_index] + PORTPMSC; |
1197 | tmp = xhci_readl(xhci, addr); | 1195 | tmp = xhci_readl(xhci, addr); |
1198 | tmp &= ~PORT_RWE; | 1196 | tmp &= ~PORT_RWE; |
1199 | xhci_writel(xhci, tmp, addr); | 1197 | xhci_writel(xhci, tmp, addr); |
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index fbf75e57628b..df6978abd7e6 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c | |||
@@ -358,17 +358,25 @@ int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring, | |||
358 | static struct xhci_container_ctx *xhci_alloc_container_ctx(struct xhci_hcd *xhci, | 358 | static struct xhci_container_ctx *xhci_alloc_container_ctx(struct xhci_hcd *xhci, |
359 | int type, gfp_t flags) | 359 | int type, gfp_t flags) |
360 | { | 360 | { |
361 | struct xhci_container_ctx *ctx = kzalloc(sizeof(*ctx), flags); | 361 | struct xhci_container_ctx *ctx; |
362 | |||
363 | if ((type != XHCI_CTX_TYPE_DEVICE) && (type != XHCI_CTX_TYPE_INPUT)) | ||
364 | return NULL; | ||
365 | |||
366 | ctx = kzalloc(sizeof(*ctx), flags); | ||
362 | if (!ctx) | 367 | if (!ctx) |
363 | return NULL; | 368 | return NULL; |
364 | 369 | ||
365 | BUG_ON((type != XHCI_CTX_TYPE_DEVICE) && (type != XHCI_CTX_TYPE_INPUT)); | ||
366 | ctx->type = type; | 370 | ctx->type = type; |
367 | ctx->size = HCC_64BYTE_CONTEXT(xhci->hcc_params) ? 2048 : 1024; | 371 | ctx->size = HCC_64BYTE_CONTEXT(xhci->hcc_params) ? 2048 : 1024; |
368 | if (type == XHCI_CTX_TYPE_INPUT) | 372 | if (type == XHCI_CTX_TYPE_INPUT) |
369 | ctx->size += CTX_SIZE(xhci->hcc_params); | 373 | ctx->size += CTX_SIZE(xhci->hcc_params); |
370 | 374 | ||
371 | ctx->bytes = dma_pool_alloc(xhci->device_pool, flags, &ctx->dma); | 375 | ctx->bytes = dma_pool_alloc(xhci->device_pool, flags, &ctx->dma); |
376 | if (!ctx->bytes) { | ||
377 | kfree(ctx); | ||
378 | return NULL; | ||
379 | } | ||
372 | memset(ctx->bytes, 0, ctx->size); | 380 | memset(ctx->bytes, 0, ctx->size); |
373 | return ctx; | 381 | return ctx; |
374 | } | 382 | } |
@@ -385,7 +393,9 @@ static void xhci_free_container_ctx(struct xhci_hcd *xhci, | |||
385 | struct xhci_input_control_ctx *xhci_get_input_control_ctx(struct xhci_hcd *xhci, | 393 | struct xhci_input_control_ctx *xhci_get_input_control_ctx(struct xhci_hcd *xhci, |
386 | struct xhci_container_ctx *ctx) | 394 | struct xhci_container_ctx *ctx) |
387 | { | 395 | { |
388 | BUG_ON(ctx->type != XHCI_CTX_TYPE_INPUT); | 396 | if (ctx->type != XHCI_CTX_TYPE_INPUT) |
397 | return NULL; | ||
398 | |||
389 | return (struct xhci_input_control_ctx *)ctx->bytes; | 399 | return (struct xhci_input_control_ctx *)ctx->bytes; |
390 | } | 400 | } |
391 | 401 | ||
@@ -1049,6 +1059,7 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud | |||
1049 | struct xhci_ep_ctx *ep0_ctx; | 1059 | struct xhci_ep_ctx *ep0_ctx; |
1050 | struct xhci_slot_ctx *slot_ctx; | 1060 | struct xhci_slot_ctx *slot_ctx; |
1051 | u32 port_num; | 1061 | u32 port_num; |
1062 | u32 max_packets; | ||
1052 | struct usb_device *top_dev; | 1063 | struct usb_device *top_dev; |
1053 | 1064 | ||
1054 | dev = xhci->devs[udev->slot_id]; | 1065 | dev = xhci->devs[udev->slot_id]; |
@@ -1066,15 +1077,20 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud | |||
1066 | switch (udev->speed) { | 1077 | switch (udev->speed) { |
1067 | case USB_SPEED_SUPER: | 1078 | case USB_SPEED_SUPER: |
1068 | slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_SS); | 1079 | slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_SS); |
1080 | max_packets = MAX_PACKET(512); | ||
1069 | break; | 1081 | break; |
1070 | case USB_SPEED_HIGH: | 1082 | case USB_SPEED_HIGH: |
1071 | slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_HS); | 1083 | slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_HS); |
1084 | max_packets = MAX_PACKET(64); | ||
1072 | break; | 1085 | break; |
1086 | /* USB core guesses at a 64-byte max packet first for FS devices */ | ||
1073 | case USB_SPEED_FULL: | 1087 | case USB_SPEED_FULL: |
1074 | slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_FS); | 1088 | slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_FS); |
1089 | max_packets = MAX_PACKET(64); | ||
1075 | break; | 1090 | break; |
1076 | case USB_SPEED_LOW: | 1091 | case USB_SPEED_LOW: |
1077 | slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_LS); | 1092 | slot_ctx->dev_info |= cpu_to_le32(SLOT_SPEED_LS); |
1093 | max_packets = MAX_PACKET(8); | ||
1078 | break; | 1094 | break; |
1079 | case USB_SPEED_WIRELESS: | 1095 | case USB_SPEED_WIRELESS: |
1080 | xhci_dbg(xhci, "FIXME xHCI doesn't support wireless speeds\n"); | 1096 | xhci_dbg(xhci, "FIXME xHCI doesn't support wireless speeds\n"); |
@@ -1082,7 +1098,7 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud | |||
1082 | break; | 1098 | break; |
1083 | default: | 1099 | default: |
1084 | /* Speed was set earlier, this shouldn't happen. */ | 1100 | /* Speed was set earlier, this shouldn't happen. */ |
1085 | BUG(); | 1101 | return -EINVAL; |
1086 | } | 1102 | } |
1087 | /* Find the root hub port this device is under */ | 1103 | /* Find the root hub port this device is under */ |
1088 | port_num = xhci_find_real_port_number(xhci, udev); | 1104 | port_num = xhci_find_real_port_number(xhci, udev); |
@@ -1141,31 +1157,10 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud | |||
1141 | /* Step 4 - ring already allocated */ | 1157 | /* Step 4 - ring already allocated */ |
1142 | /* Step 5 */ | 1158 | /* Step 5 */ |
1143 | ep0_ctx->ep_info2 = cpu_to_le32(EP_TYPE(CTRL_EP)); | 1159 | ep0_ctx->ep_info2 = cpu_to_le32(EP_TYPE(CTRL_EP)); |
1144 | /* | 1160 | |
1145 | * XXX: Not sure about wireless USB devices. | ||
1146 | */ | ||
1147 | switch (udev->speed) { | ||
1148 | case USB_SPEED_SUPER: | ||
1149 | ep0_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(512)); | ||
1150 | break; | ||
1151 | case USB_SPEED_HIGH: | ||
1152 | /* USB core guesses at a 64-byte max packet first for FS devices */ | ||
1153 | case USB_SPEED_FULL: | ||
1154 | ep0_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(64)); | ||
1155 | break; | ||
1156 | case USB_SPEED_LOW: | ||
1157 | ep0_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(8)); | ||
1158 | break; | ||
1159 | case USB_SPEED_WIRELESS: | ||
1160 | xhci_dbg(xhci, "FIXME xHCI doesn't support wireless speeds\n"); | ||
1161 | return -EINVAL; | ||
1162 | break; | ||
1163 | default: | ||
1164 | /* New speed? */ | ||
1165 | BUG(); | ||
1166 | } | ||
1167 | /* EP 0 can handle "burst" sizes of 1, so Max Burst Size field is 0 */ | 1161 | /* EP 0 can handle "burst" sizes of 1, so Max Burst Size field is 0 */ |
1168 | ep0_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(0) | ERROR_COUNT(3)); | 1162 | ep0_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(0) | ERROR_COUNT(3) | |
1163 | max_packets); | ||
1169 | 1164 | ||
1170 | ep0_ctx->deq = cpu_to_le64(dev->eps[0].ring->first_seg->dma | | 1165 | ep0_ctx->deq = cpu_to_le64(dev->eps[0].ring->first_seg->dma | |
1171 | dev->eps[0].ring->cycle_state); | 1166 | dev->eps[0].ring->cycle_state); |
@@ -1338,7 +1333,7 @@ static u32 xhci_get_endpoint_type(struct usb_device *udev, | |||
1338 | else | 1333 | else |
1339 | type = EP_TYPE(INT_OUT_EP); | 1334 | type = EP_TYPE(INT_OUT_EP); |
1340 | } else { | 1335 | } else { |
1341 | BUG(); | 1336 | type = 0; |
1342 | } | 1337 | } |
1343 | return type; | 1338 | return type; |
1344 | } | 1339 | } |
@@ -1384,10 +1379,16 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, | |||
1384 | unsigned int max_burst; | 1379 | unsigned int max_burst; |
1385 | enum xhci_ring_type type; | 1380 | enum xhci_ring_type type; |
1386 | u32 max_esit_payload; | 1381 | u32 max_esit_payload; |
1382 | u32 endpoint_type; | ||
1387 | 1383 | ||
1388 | ep_index = xhci_get_endpoint_index(&ep->desc); | 1384 | ep_index = xhci_get_endpoint_index(&ep->desc); |
1389 | ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index); | 1385 | ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index); |
1390 | 1386 | ||
1387 | endpoint_type = xhci_get_endpoint_type(udev, ep); | ||
1388 | if (!endpoint_type) | ||
1389 | return -EINVAL; | ||
1390 | ep_ctx->ep_info2 = cpu_to_le32(endpoint_type); | ||
1391 | |||
1391 | type = usb_endpoint_type(&ep->desc); | 1392 | type = usb_endpoint_type(&ep->desc); |
1392 | /* Set up the endpoint ring */ | 1393 | /* Set up the endpoint ring */ |
1393 | virt_dev->eps[ep_index].new_ring = | 1394 | virt_dev->eps[ep_index].new_ring = |
@@ -1416,11 +1417,9 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, | |||
1416 | * CErr shall be set to 0 for Isoch endpoints. | 1417 | * CErr shall be set to 0 for Isoch endpoints. |
1417 | */ | 1418 | */ |
1418 | if (!usb_endpoint_xfer_isoc(&ep->desc)) | 1419 | if (!usb_endpoint_xfer_isoc(&ep->desc)) |
1419 | ep_ctx->ep_info2 = cpu_to_le32(ERROR_COUNT(3)); | 1420 | ep_ctx->ep_info2 |= cpu_to_le32(ERROR_COUNT(3)); |
1420 | else | 1421 | else |
1421 | ep_ctx->ep_info2 = cpu_to_le32(ERROR_COUNT(0)); | 1422 | ep_ctx->ep_info2 |= cpu_to_le32(ERROR_COUNT(0)); |
1422 | |||
1423 | ep_ctx->ep_info2 |= cpu_to_le32(xhci_get_endpoint_type(udev, ep)); | ||
1424 | 1423 | ||
1425 | /* Set the max packet size and max burst */ | 1424 | /* Set the max packet size and max burst */ |
1426 | max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)); | 1425 | max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)); |
@@ -1856,6 +1855,7 @@ no_bw: | |||
1856 | kfree(xhci->usb3_ports); | 1855 | kfree(xhci->usb3_ports); |
1857 | kfree(xhci->port_array); | 1856 | kfree(xhci->port_array); |
1858 | kfree(xhci->rh_bw); | 1857 | kfree(xhci->rh_bw); |
1858 | kfree(xhci->ext_caps); | ||
1859 | 1859 | ||
1860 | xhci->page_size = 0; | 1860 | xhci->page_size = 0; |
1861 | xhci->page_shift = 0; | 1861 | xhci->page_shift = 0; |
@@ -2043,7 +2043,7 @@ static void xhci_set_hc_event_deq(struct xhci_hcd *xhci) | |||
2043 | } | 2043 | } |
2044 | 2044 | ||
2045 | static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, | 2045 | static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, |
2046 | __le32 __iomem *addr, u8 major_revision) | 2046 | __le32 __iomem *addr, u8 major_revision, int max_caps) |
2047 | { | 2047 | { |
2048 | u32 temp, port_offset, port_count; | 2048 | u32 temp, port_offset, port_count; |
2049 | int i; | 2049 | int i; |
@@ -2068,6 +2068,10 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, | |||
2068 | /* WTF? "Valid values are ‘1’ to MaxPorts" */ | 2068 | /* WTF? "Valid values are ‘1’ to MaxPorts" */ |
2069 | return; | 2069 | return; |
2070 | 2070 | ||
2071 | /* cache usb2 port capabilities */ | ||
2072 | if (major_revision < 0x03 && xhci->num_ext_caps < max_caps) | ||
2073 | xhci->ext_caps[xhci->num_ext_caps++] = temp; | ||
2074 | |||
2071 | /* Check the host's USB2 LPM capability */ | 2075 | /* Check the host's USB2 LPM capability */ |
2072 | if ((xhci->hci_version == 0x96) && (major_revision != 0x03) && | 2076 | if ((xhci->hci_version == 0x96) && (major_revision != 0x03) && |
2073 | (temp & XHCI_L1C)) { | 2077 | (temp & XHCI_L1C)) { |
@@ -2125,10 +2129,11 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, | |||
2125 | */ | 2129 | */ |
2126 | static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags) | 2130 | static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags) |
2127 | { | 2131 | { |
2128 | __le32 __iomem *addr; | 2132 | __le32 __iomem *addr, *tmp_addr; |
2129 | u32 offset; | 2133 | u32 offset, tmp_offset; |
2130 | unsigned int num_ports; | 2134 | unsigned int num_ports; |
2131 | int i, j, port_index; | 2135 | int i, j, port_index; |
2136 | int cap_count = 0; | ||
2132 | 2137 | ||
2133 | addr = &xhci->cap_regs->hcc_params; | 2138 | addr = &xhci->cap_regs->hcc_params; |
2134 | offset = XHCI_HCC_EXT_CAPS(xhci_readl(xhci, addr)); | 2139 | offset = XHCI_HCC_EXT_CAPS(xhci_readl(xhci, addr)); |
@@ -2161,13 +2166,32 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags) | |||
2161 | * See section 5.3.6 for offset calculation. | 2166 | * See section 5.3.6 for offset calculation. |
2162 | */ | 2167 | */ |
2163 | addr = &xhci->cap_regs->hc_capbase + offset; | 2168 | addr = &xhci->cap_regs->hc_capbase + offset; |
2169 | |||
2170 | tmp_addr = addr; | ||
2171 | tmp_offset = offset; | ||
2172 | |||
2173 | /* count extended protocol capability entries for later caching */ | ||
2174 | do { | ||
2175 | u32 cap_id; | ||
2176 | cap_id = xhci_readl(xhci, tmp_addr); | ||
2177 | if (XHCI_EXT_CAPS_ID(cap_id) == XHCI_EXT_CAPS_PROTOCOL) | ||
2178 | cap_count++; | ||
2179 | tmp_offset = XHCI_EXT_CAPS_NEXT(cap_id); | ||
2180 | tmp_addr += tmp_offset; | ||
2181 | } while (tmp_offset); | ||
2182 | |||
2183 | xhci->ext_caps = kzalloc(sizeof(*xhci->ext_caps) * cap_count, flags); | ||
2184 | if (!xhci->ext_caps) | ||
2185 | return -ENOMEM; | ||
2186 | |||
2164 | while (1) { | 2187 | while (1) { |
2165 | u32 cap_id; | 2188 | u32 cap_id; |
2166 | 2189 | ||
2167 | cap_id = xhci_readl(xhci, addr); | 2190 | cap_id = xhci_readl(xhci, addr); |
2168 | if (XHCI_EXT_CAPS_ID(cap_id) == XHCI_EXT_CAPS_PROTOCOL) | 2191 | if (XHCI_EXT_CAPS_ID(cap_id) == XHCI_EXT_CAPS_PROTOCOL) |
2169 | xhci_add_in_port(xhci, num_ports, addr, | 2192 | xhci_add_in_port(xhci, num_ports, addr, |
2170 | (u8) XHCI_EXT_PORT_MAJOR(cap_id)); | 2193 | (u8) XHCI_EXT_PORT_MAJOR(cap_id), |
2194 | cap_count); | ||
2171 | offset = XHCI_EXT_CAPS_NEXT(cap_id); | 2195 | offset = XHCI_EXT_CAPS_NEXT(cap_id); |
2172 | if (!offset || (xhci->num_usb2_ports + xhci->num_usb3_ports) | 2196 | if (!offset || (xhci->num_usb2_ports + xhci->num_usb3_ports) |
2173 | == num_ports) | 2197 | == num_ports) |
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index df90fe51b4aa..51e22bf89505 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c | |||
@@ -130,7 +130,7 @@ static int xhci_plat_probe(struct platform_device *pdev) | |||
130 | goto unmap_registers; | 130 | goto unmap_registers; |
131 | 131 | ||
132 | /* USB 2.0 roothub is stored in the platform_device now. */ | 132 | /* USB 2.0 roothub is stored in the platform_device now. */ |
133 | hcd = dev_get_drvdata(&pdev->dev); | 133 | hcd = platform_get_drvdata(pdev); |
134 | xhci = hcd_to_xhci(hcd); | 134 | xhci = hcd_to_xhci(hcd); |
135 | xhci->shared_hcd = usb_create_shared_hcd(driver, &pdev->dev, | 135 | xhci->shared_hcd = usb_create_shared_hcd(driver, &pdev->dev, |
136 | dev_name(&pdev->dev), hcd); | 136 | dev_name(&pdev->dev), hcd); |
@@ -179,6 +179,7 @@ static int xhci_plat_remove(struct platform_device *dev) | |||
179 | 179 | ||
180 | usb_remove_hcd(hcd); | 180 | usb_remove_hcd(hcd); |
181 | iounmap(hcd->regs); | 181 | iounmap(hcd->regs); |
182 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
182 | usb_put_hcd(hcd); | 183 | usb_put_hcd(hcd); |
183 | kfree(xhci); | 184 | kfree(xhci); |
184 | 185 | ||
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 1969c001b3f9..1e57eafa6910 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c | |||
@@ -1424,6 +1424,10 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, | |||
1424 | */ | 1424 | */ |
1425 | ctrl_ctx = xhci_get_input_control_ctx(xhci, | 1425 | ctrl_ctx = xhci_get_input_control_ctx(xhci, |
1426 | virt_dev->in_ctx); | 1426 | virt_dev->in_ctx); |
1427 | if (!ctrl_ctx) { | ||
1428 | xhci_warn(xhci, "Could not get input context, bad type.\n"); | ||
1429 | break; | ||
1430 | } | ||
1427 | /* Input ctx add_flags are the endpoint index plus one */ | 1431 | /* Input ctx add_flags are the endpoint index plus one */ |
1428 | ep_index = xhci_last_valid_endpoint(le32_to_cpu(ctrl_ctx->add_flags)) - 1; | 1432 | ep_index = xhci_last_valid_endpoint(le32_to_cpu(ctrl_ctx->add_flags)) - 1; |
1429 | /* A usb_set_interface() call directly after clearing a halted | 1433 | /* A usb_set_interface() call directly after clearing a halted |
@@ -2799,7 +2803,7 @@ hw_died: | |||
2799 | return IRQ_HANDLED; | 2803 | return IRQ_HANDLED; |
2800 | } | 2804 | } |
2801 | 2805 | ||
2802 | irqreturn_t xhci_msi_irq(int irq, struct usb_hcd *hcd) | 2806 | irqreturn_t xhci_msi_irq(int irq, void *hcd) |
2803 | { | 2807 | { |
2804 | return xhci_irq(hcd); | 2808 | return xhci_irq(hcd); |
2805 | } | 2809 | } |
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index d8f640b12dd9..2c49f00260ca 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c | |||
@@ -218,7 +218,7 @@ static int xhci_setup_msi(struct xhci_hcd *xhci) | |||
218 | return ret; | 218 | return ret; |
219 | } | 219 | } |
220 | 220 | ||
221 | ret = request_irq(pdev->irq, (irq_handler_t)xhci_msi_irq, | 221 | ret = request_irq(pdev->irq, xhci_msi_irq, |
222 | 0, "xhci_hcd", xhci_to_hcd(xhci)); | 222 | 0, "xhci_hcd", xhci_to_hcd(xhci)); |
223 | if (ret) { | 223 | if (ret) { |
224 | xhci_dbg(xhci, "disable MSI interrupt\n"); | 224 | xhci_dbg(xhci, "disable MSI interrupt\n"); |
@@ -290,7 +290,7 @@ static int xhci_setup_msix(struct xhci_hcd *xhci) | |||
290 | 290 | ||
291 | for (i = 0; i < xhci->msix_count; i++) { | 291 | for (i = 0; i < xhci->msix_count; i++) { |
292 | ret = request_irq(xhci->msix_entries[i].vector, | 292 | ret = request_irq(xhci->msix_entries[i].vector, |
293 | (irq_handler_t)xhci_msi_irq, | 293 | xhci_msi_irq, |
294 | 0, "xhci_hcd", xhci_to_hcd(xhci)); | 294 | 0, "xhci_hcd", xhci_to_hcd(xhci)); |
295 | if (ret) | 295 | if (ret) |
296 | goto disable_msix; | 296 | goto disable_msix; |
@@ -1121,6 +1121,16 @@ unsigned int xhci_get_endpoint_index(struct usb_endpoint_descriptor *desc) | |||
1121 | return index; | 1121 | return index; |
1122 | } | 1122 | } |
1123 | 1123 | ||
1124 | /* The reverse operation to xhci_get_endpoint_index. Calculate the USB endpoint | ||
1125 | * address from the XHCI endpoint index. | ||
1126 | */ | ||
1127 | unsigned int xhci_get_endpoint_address(unsigned int ep_index) | ||
1128 | { | ||
1129 | unsigned int number = DIV_ROUND_UP(ep_index, 2); | ||
1130 | unsigned int direction = ep_index % 2 ? USB_DIR_OUT : USB_DIR_IN; | ||
1131 | return direction | number; | ||
1132 | } | ||
1133 | |||
1124 | /* Find the flag for this endpoint (for use in the control context). Use the | 1134 | /* Find the flag for this endpoint (for use in the control context). Use the |
1125 | * endpoint index to create a bitmask. The slot context is bit 0, endpoint 0 is | 1135 | * endpoint index to create a bitmask. The slot context is bit 0, endpoint 0 is |
1126 | * bit 1, etc. | 1136 | * bit 1, etc. |
@@ -1225,19 +1235,25 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id, | |||
1225 | hw_max_packet_size); | 1235 | hw_max_packet_size); |
1226 | xhci_dbg(xhci, "Issuing evaluate context command.\n"); | 1236 | xhci_dbg(xhci, "Issuing evaluate context command.\n"); |
1227 | 1237 | ||
1238 | /* Set up the input context flags for the command */ | ||
1239 | /* FIXME: This won't work if a non-default control endpoint | ||
1240 | * changes max packet sizes. | ||
1241 | */ | ||
1242 | in_ctx = xhci->devs[slot_id]->in_ctx; | ||
1243 | ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); | ||
1244 | if (!ctrl_ctx) { | ||
1245 | xhci_warn(xhci, "%s: Could not get input context, bad type.\n", | ||
1246 | __func__); | ||
1247 | return -ENOMEM; | ||
1248 | } | ||
1228 | /* Set up the modified control endpoint 0 */ | 1249 | /* Set up the modified control endpoint 0 */ |
1229 | xhci_endpoint_copy(xhci, xhci->devs[slot_id]->in_ctx, | 1250 | xhci_endpoint_copy(xhci, xhci->devs[slot_id]->in_ctx, |
1230 | xhci->devs[slot_id]->out_ctx, ep_index); | 1251 | xhci->devs[slot_id]->out_ctx, ep_index); |
1231 | in_ctx = xhci->devs[slot_id]->in_ctx; | 1252 | |
1232 | ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, ep_index); | 1253 | ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, ep_index); |
1233 | ep_ctx->ep_info2 &= cpu_to_le32(~MAX_PACKET_MASK); | 1254 | ep_ctx->ep_info2 &= cpu_to_le32(~MAX_PACKET_MASK); |
1234 | ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet_size)); | 1255 | ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet_size)); |
1235 | 1256 | ||
1236 | /* Set up the input context flags for the command */ | ||
1237 | /* FIXME: This won't work if a non-default control endpoint | ||
1238 | * changes max packet sizes. | ||
1239 | */ | ||
1240 | ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); | ||
1241 | ctrl_ctx->add_flags = cpu_to_le32(EP0_FLAG); | 1257 | ctrl_ctx->add_flags = cpu_to_le32(EP0_FLAG); |
1242 | ctrl_ctx->drop_flags = 0; | 1258 | ctrl_ctx->drop_flags = 0; |
1243 | 1259 | ||
@@ -1597,6 +1613,12 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, | |||
1597 | in_ctx = xhci->devs[udev->slot_id]->in_ctx; | 1613 | in_ctx = xhci->devs[udev->slot_id]->in_ctx; |
1598 | out_ctx = xhci->devs[udev->slot_id]->out_ctx; | 1614 | out_ctx = xhci->devs[udev->slot_id]->out_ctx; |
1599 | ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); | 1615 | ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); |
1616 | if (!ctrl_ctx) { | ||
1617 | xhci_warn(xhci, "%s: Could not get input context, bad type.\n", | ||
1618 | __func__); | ||
1619 | return 0; | ||
1620 | } | ||
1621 | |||
1600 | ep_index = xhci_get_endpoint_index(&ep->desc); | 1622 | ep_index = xhci_get_endpoint_index(&ep->desc); |
1601 | ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index); | 1623 | ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index); |
1602 | /* If the HC already knows the endpoint is disabled, | 1624 | /* If the HC already knows the endpoint is disabled, |
@@ -1691,8 +1713,13 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, | |||
1691 | in_ctx = virt_dev->in_ctx; | 1713 | in_ctx = virt_dev->in_ctx; |
1692 | out_ctx = virt_dev->out_ctx; | 1714 | out_ctx = virt_dev->out_ctx; |
1693 | ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); | 1715 | ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); |
1694 | ep_index = xhci_get_endpoint_index(&ep->desc); | 1716 | if (!ctrl_ctx) { |
1717 | xhci_warn(xhci, "%s: Could not get input context, bad type.\n", | ||
1718 | __func__); | ||
1719 | return 0; | ||
1720 | } | ||
1695 | 1721 | ||
1722 | ep_index = xhci_get_endpoint_index(&ep->desc); | ||
1696 | /* If this endpoint is already in use, and the upper layers are trying | 1723 | /* If this endpoint is already in use, and the upper layers are trying |
1697 | * to add it again without dropping it, reject the addition. | 1724 | * to add it again without dropping it, reject the addition. |
1698 | */ | 1725 | */ |
@@ -1765,12 +1792,18 @@ static void xhci_zero_in_ctx(struct xhci_hcd *xhci, struct xhci_virt_device *vir | |||
1765 | struct xhci_slot_ctx *slot_ctx; | 1792 | struct xhci_slot_ctx *slot_ctx; |
1766 | int i; | 1793 | int i; |
1767 | 1794 | ||
1795 | ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx); | ||
1796 | if (!ctrl_ctx) { | ||
1797 | xhci_warn(xhci, "%s: Could not get input context, bad type.\n", | ||
1798 | __func__); | ||
1799 | return; | ||
1800 | } | ||
1801 | |||
1768 | /* When a device's add flag and drop flag are zero, any subsequent | 1802 | /* When a device's add flag and drop flag are zero, any subsequent |
1769 | * configure endpoint command will leave that endpoint's state | 1803 | * configure endpoint command will leave that endpoint's state |
1770 | * untouched. Make sure we don't leave any old state in the input | 1804 | * untouched. Make sure we don't leave any old state in the input |
1771 | * endpoint contexts. | 1805 | * endpoint contexts. |
1772 | */ | 1806 | */ |
1773 | ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx); | ||
1774 | ctrl_ctx->drop_flags = 0; | 1807 | ctrl_ctx->drop_flags = 0; |
1775 | ctrl_ctx->add_flags = 0; | 1808 | ctrl_ctx->add_flags = 0; |
1776 | slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx); | 1809 | slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx); |
@@ -1877,13 +1910,11 @@ static int xhci_evaluate_context_result(struct xhci_hcd *xhci, | |||
1877 | } | 1910 | } |
1878 | 1911 | ||
1879 | static u32 xhci_count_num_new_endpoints(struct xhci_hcd *xhci, | 1912 | static u32 xhci_count_num_new_endpoints(struct xhci_hcd *xhci, |
1880 | struct xhci_container_ctx *in_ctx) | 1913 | struct xhci_input_control_ctx *ctrl_ctx) |
1881 | { | 1914 | { |
1882 | struct xhci_input_control_ctx *ctrl_ctx; | ||
1883 | u32 valid_add_flags; | 1915 | u32 valid_add_flags; |
1884 | u32 valid_drop_flags; | 1916 | u32 valid_drop_flags; |
1885 | 1917 | ||
1886 | ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); | ||
1887 | /* Ignore the slot flag (bit 0), and the default control endpoint flag | 1918 | /* Ignore the slot flag (bit 0), and the default control endpoint flag |
1888 | * (bit 1). The default control endpoint is added during the Address | 1919 | * (bit 1). The default control endpoint is added during the Address |
1889 | * Device command and is never removed until the slot is disabled. | 1920 | * Device command and is never removed until the slot is disabled. |
@@ -1900,13 +1931,11 @@ static u32 xhci_count_num_new_endpoints(struct xhci_hcd *xhci, | |||
1900 | } | 1931 | } |
1901 | 1932 | ||
1902 | static unsigned int xhci_count_num_dropped_endpoints(struct xhci_hcd *xhci, | 1933 | static unsigned int xhci_count_num_dropped_endpoints(struct xhci_hcd *xhci, |
1903 | struct xhci_container_ctx *in_ctx) | 1934 | struct xhci_input_control_ctx *ctrl_ctx) |
1904 | { | 1935 | { |
1905 | struct xhci_input_control_ctx *ctrl_ctx; | ||
1906 | u32 valid_add_flags; | 1936 | u32 valid_add_flags; |
1907 | u32 valid_drop_flags; | 1937 | u32 valid_drop_flags; |
1908 | 1938 | ||
1909 | ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); | ||
1910 | valid_add_flags = ctrl_ctx->add_flags >> 2; | 1939 | valid_add_flags = ctrl_ctx->add_flags >> 2; |
1911 | valid_drop_flags = ctrl_ctx->drop_flags >> 2; | 1940 | valid_drop_flags = ctrl_ctx->drop_flags >> 2; |
1912 | 1941 | ||
@@ -1928,11 +1957,11 @@ static unsigned int xhci_count_num_dropped_endpoints(struct xhci_hcd *xhci, | |||
1928 | * Must be called with xhci->lock held. | 1957 | * Must be called with xhci->lock held. |
1929 | */ | 1958 | */ |
1930 | static int xhci_reserve_host_resources(struct xhci_hcd *xhci, | 1959 | static int xhci_reserve_host_resources(struct xhci_hcd *xhci, |
1931 | struct xhci_container_ctx *in_ctx) | 1960 | struct xhci_input_control_ctx *ctrl_ctx) |
1932 | { | 1961 | { |
1933 | u32 added_eps; | 1962 | u32 added_eps; |
1934 | 1963 | ||
1935 | added_eps = xhci_count_num_new_endpoints(xhci, in_ctx); | 1964 | added_eps = xhci_count_num_new_endpoints(xhci, ctrl_ctx); |
1936 | if (xhci->num_active_eps + added_eps > xhci->limit_active_eps) { | 1965 | if (xhci->num_active_eps + added_eps > xhci->limit_active_eps) { |
1937 | xhci_dbg(xhci, "Not enough ep ctxs: " | 1966 | xhci_dbg(xhci, "Not enough ep ctxs: " |
1938 | "%u active, need to add %u, limit is %u.\n", | 1967 | "%u active, need to add %u, limit is %u.\n", |
@@ -1953,11 +1982,11 @@ static int xhci_reserve_host_resources(struct xhci_hcd *xhci, | |||
1953 | * Must be called with xhci->lock held. | 1982 | * Must be called with xhci->lock held. |
1954 | */ | 1983 | */ |
1955 | static void xhci_free_host_resources(struct xhci_hcd *xhci, | 1984 | static void xhci_free_host_resources(struct xhci_hcd *xhci, |
1956 | struct xhci_container_ctx *in_ctx) | 1985 | struct xhci_input_control_ctx *ctrl_ctx) |
1957 | { | 1986 | { |
1958 | u32 num_failed_eps; | 1987 | u32 num_failed_eps; |
1959 | 1988 | ||
1960 | num_failed_eps = xhci_count_num_new_endpoints(xhci, in_ctx); | 1989 | num_failed_eps = xhci_count_num_new_endpoints(xhci, ctrl_ctx); |
1961 | xhci->num_active_eps -= num_failed_eps; | 1990 | xhci->num_active_eps -= num_failed_eps; |
1962 | xhci_dbg(xhci, "Removing %u failed ep ctxs, %u now active.\n", | 1991 | xhci_dbg(xhci, "Removing %u failed ep ctxs, %u now active.\n", |
1963 | num_failed_eps, | 1992 | num_failed_eps, |
@@ -1971,11 +2000,11 @@ static void xhci_free_host_resources(struct xhci_hcd *xhci, | |||
1971 | * Must be called with xhci->lock held. | 2000 | * Must be called with xhci->lock held. |
1972 | */ | 2001 | */ |
1973 | static void xhci_finish_resource_reservation(struct xhci_hcd *xhci, | 2002 | static void xhci_finish_resource_reservation(struct xhci_hcd *xhci, |
1974 | struct xhci_container_ctx *in_ctx) | 2003 | struct xhci_input_control_ctx *ctrl_ctx) |
1975 | { | 2004 | { |
1976 | u32 num_dropped_eps; | 2005 | u32 num_dropped_eps; |
1977 | 2006 | ||
1978 | num_dropped_eps = xhci_count_num_dropped_endpoints(xhci, in_ctx); | 2007 | num_dropped_eps = xhci_count_num_dropped_endpoints(xhci, ctrl_ctx); |
1979 | xhci->num_active_eps -= num_dropped_eps; | 2008 | xhci->num_active_eps -= num_dropped_eps; |
1980 | if (num_dropped_eps) | 2009 | if (num_dropped_eps) |
1981 | xhci_dbg(xhci, "Removing %u dropped ep ctxs, %u now active.\n", | 2010 | xhci_dbg(xhci, "Removing %u dropped ep ctxs, %u now active.\n", |
@@ -2470,6 +2499,11 @@ static int xhci_reserve_bandwidth(struct xhci_hcd *xhci, | |||
2470 | old_active_eps = virt_dev->tt_info->active_eps; | 2499 | old_active_eps = virt_dev->tt_info->active_eps; |
2471 | 2500 | ||
2472 | ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); | 2501 | ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); |
2502 | if (!ctrl_ctx) { | ||
2503 | xhci_warn(xhci, "%s: Could not get input context, bad type.\n", | ||
2504 | __func__); | ||
2505 | return -ENOMEM; | ||
2506 | } | ||
2473 | 2507 | ||
2474 | for (i = 0; i < 31; i++) { | 2508 | for (i = 0; i < 31; i++) { |
2475 | if (!EP_IS_ADDED(ctrl_ctx, i) && !EP_IS_DROPPED(ctrl_ctx, i)) | 2509 | if (!EP_IS_ADDED(ctrl_ctx, i) && !EP_IS_DROPPED(ctrl_ctx, i)) |
@@ -2554,6 +2588,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, | |||
2554 | int timeleft; | 2588 | int timeleft; |
2555 | unsigned long flags; | 2589 | unsigned long flags; |
2556 | struct xhci_container_ctx *in_ctx; | 2590 | struct xhci_container_ctx *in_ctx; |
2591 | struct xhci_input_control_ctx *ctrl_ctx; | ||
2557 | struct completion *cmd_completion; | 2592 | struct completion *cmd_completion; |
2558 | u32 *cmd_status; | 2593 | u32 *cmd_status; |
2559 | struct xhci_virt_device *virt_dev; | 2594 | struct xhci_virt_device *virt_dev; |
@@ -2566,9 +2601,16 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, | |||
2566 | in_ctx = command->in_ctx; | 2601 | in_ctx = command->in_ctx; |
2567 | else | 2602 | else |
2568 | in_ctx = virt_dev->in_ctx; | 2603 | in_ctx = virt_dev->in_ctx; |
2604 | ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); | ||
2605 | if (!ctrl_ctx) { | ||
2606 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
2607 | xhci_warn(xhci, "%s: Could not get input context, bad type.\n", | ||
2608 | __func__); | ||
2609 | return -ENOMEM; | ||
2610 | } | ||
2569 | 2611 | ||
2570 | if ((xhci->quirks & XHCI_EP_LIMIT_QUIRK) && | 2612 | if ((xhci->quirks & XHCI_EP_LIMIT_QUIRK) && |
2571 | xhci_reserve_host_resources(xhci, in_ctx)) { | 2613 | xhci_reserve_host_resources(xhci, ctrl_ctx)) { |
2572 | spin_unlock_irqrestore(&xhci->lock, flags); | 2614 | spin_unlock_irqrestore(&xhci->lock, flags); |
2573 | xhci_warn(xhci, "Not enough host resources, " | 2615 | xhci_warn(xhci, "Not enough host resources, " |
2574 | "active endpoint contexts = %u\n", | 2616 | "active endpoint contexts = %u\n", |
@@ -2578,7 +2620,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, | |||
2578 | if ((xhci->quirks & XHCI_SW_BW_CHECKING) && | 2620 | if ((xhci->quirks & XHCI_SW_BW_CHECKING) && |
2579 | xhci_reserve_bandwidth(xhci, virt_dev, in_ctx)) { | 2621 | xhci_reserve_bandwidth(xhci, virt_dev, in_ctx)) { |
2580 | if ((xhci->quirks & XHCI_EP_LIMIT_QUIRK)) | 2622 | if ((xhci->quirks & XHCI_EP_LIMIT_QUIRK)) |
2581 | xhci_free_host_resources(xhci, in_ctx); | 2623 | xhci_free_host_resources(xhci, ctrl_ctx); |
2582 | spin_unlock_irqrestore(&xhci->lock, flags); | 2624 | spin_unlock_irqrestore(&xhci->lock, flags); |
2583 | xhci_warn(xhci, "Not enough bandwidth\n"); | 2625 | xhci_warn(xhci, "Not enough bandwidth\n"); |
2584 | return -ENOMEM; | 2626 | return -ENOMEM; |
@@ -2614,7 +2656,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, | |||
2614 | if (command) | 2656 | if (command) |
2615 | list_del(&command->cmd_list); | 2657 | list_del(&command->cmd_list); |
2616 | if ((xhci->quirks & XHCI_EP_LIMIT_QUIRK)) | 2658 | if ((xhci->quirks & XHCI_EP_LIMIT_QUIRK)) |
2617 | xhci_free_host_resources(xhci, in_ctx); | 2659 | xhci_free_host_resources(xhci, ctrl_ctx); |
2618 | spin_unlock_irqrestore(&xhci->lock, flags); | 2660 | spin_unlock_irqrestore(&xhci->lock, flags); |
2619 | xhci_dbg(xhci, "FIXME allocate a new ring segment\n"); | 2661 | xhci_dbg(xhci, "FIXME allocate a new ring segment\n"); |
2620 | return -ENOMEM; | 2662 | return -ENOMEM; |
@@ -2650,9 +2692,9 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, | |||
2650 | * Otherwise, clean up the estimate to include dropped eps. | 2692 | * Otherwise, clean up the estimate to include dropped eps. |
2651 | */ | 2693 | */ |
2652 | if (ret) | 2694 | if (ret) |
2653 | xhci_free_host_resources(xhci, in_ctx); | 2695 | xhci_free_host_resources(xhci, ctrl_ctx); |
2654 | else | 2696 | else |
2655 | xhci_finish_resource_reservation(xhci, in_ctx); | 2697 | xhci_finish_resource_reservation(xhci, ctrl_ctx); |
2656 | spin_unlock_irqrestore(&xhci->lock, flags); | 2698 | spin_unlock_irqrestore(&xhci->lock, flags); |
2657 | } | 2699 | } |
2658 | return ret; | 2700 | return ret; |
@@ -2689,6 +2731,11 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) | |||
2689 | 2731 | ||
2690 | /* See section 4.6.6 - A0 = 1; A1 = D0 = D1 = 0 */ | 2732 | /* See section 4.6.6 - A0 = 1; A1 = D0 = D1 = 0 */ |
2691 | ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx); | 2733 | ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx); |
2734 | if (!ctrl_ctx) { | ||
2735 | xhci_warn(xhci, "%s: Could not get input context, bad type.\n", | ||
2736 | __func__); | ||
2737 | return -ENOMEM; | ||
2738 | } | ||
2692 | ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG); | 2739 | ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG); |
2693 | ctrl_ctx->add_flags &= cpu_to_le32(~EP0_FLAG); | 2740 | ctrl_ctx->add_flags &= cpu_to_le32(~EP0_FLAG); |
2694 | ctrl_ctx->drop_flags &= cpu_to_le32(~(SLOT_FLAG | EP0_FLAG)); | 2741 | ctrl_ctx->drop_flags &= cpu_to_le32(~(SLOT_FLAG | EP0_FLAG)); |
@@ -2767,10 +2814,9 @@ void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) | |||
2767 | static void xhci_setup_input_ctx_for_config_ep(struct xhci_hcd *xhci, | 2814 | static void xhci_setup_input_ctx_for_config_ep(struct xhci_hcd *xhci, |
2768 | struct xhci_container_ctx *in_ctx, | 2815 | struct xhci_container_ctx *in_ctx, |
2769 | struct xhci_container_ctx *out_ctx, | 2816 | struct xhci_container_ctx *out_ctx, |
2817 | struct xhci_input_control_ctx *ctrl_ctx, | ||
2770 | u32 add_flags, u32 drop_flags) | 2818 | u32 add_flags, u32 drop_flags) |
2771 | { | 2819 | { |
2772 | struct xhci_input_control_ctx *ctrl_ctx; | ||
2773 | ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); | ||
2774 | ctrl_ctx->add_flags = cpu_to_le32(add_flags); | 2820 | ctrl_ctx->add_flags = cpu_to_le32(add_flags); |
2775 | ctrl_ctx->drop_flags = cpu_to_le32(drop_flags); | 2821 | ctrl_ctx->drop_flags = cpu_to_le32(drop_flags); |
2776 | xhci_slot_copy(xhci, in_ctx, out_ctx); | 2822 | xhci_slot_copy(xhci, in_ctx, out_ctx); |
@@ -2784,14 +2830,22 @@ static void xhci_setup_input_ctx_for_quirk(struct xhci_hcd *xhci, | |||
2784 | unsigned int slot_id, unsigned int ep_index, | 2830 | unsigned int slot_id, unsigned int ep_index, |
2785 | struct xhci_dequeue_state *deq_state) | 2831 | struct xhci_dequeue_state *deq_state) |
2786 | { | 2832 | { |
2833 | struct xhci_input_control_ctx *ctrl_ctx; | ||
2787 | struct xhci_container_ctx *in_ctx; | 2834 | struct xhci_container_ctx *in_ctx; |
2788 | struct xhci_ep_ctx *ep_ctx; | 2835 | struct xhci_ep_ctx *ep_ctx; |
2789 | u32 added_ctxs; | 2836 | u32 added_ctxs; |
2790 | dma_addr_t addr; | 2837 | dma_addr_t addr; |
2791 | 2838 | ||
2839 | in_ctx = xhci->devs[slot_id]->in_ctx; | ||
2840 | ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); | ||
2841 | if (!ctrl_ctx) { | ||
2842 | xhci_warn(xhci, "%s: Could not get input context, bad type.\n", | ||
2843 | __func__); | ||
2844 | return; | ||
2845 | } | ||
2846 | |||
2792 | xhci_endpoint_copy(xhci, xhci->devs[slot_id]->in_ctx, | 2847 | xhci_endpoint_copy(xhci, xhci->devs[slot_id]->in_ctx, |
2793 | xhci->devs[slot_id]->out_ctx, ep_index); | 2848 | xhci->devs[slot_id]->out_ctx, ep_index); |
2794 | in_ctx = xhci->devs[slot_id]->in_ctx; | ||
2795 | ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, ep_index); | 2849 | ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, ep_index); |
2796 | addr = xhci_trb_virt_to_dma(deq_state->new_deq_seg, | 2850 | addr = xhci_trb_virt_to_dma(deq_state->new_deq_seg, |
2797 | deq_state->new_deq_ptr); | 2851 | deq_state->new_deq_ptr); |
@@ -2807,7 +2861,8 @@ static void xhci_setup_input_ctx_for_quirk(struct xhci_hcd *xhci, | |||
2807 | 2861 | ||
2808 | added_ctxs = xhci_get_endpoint_flag_from_index(ep_index); | 2862 | added_ctxs = xhci_get_endpoint_flag_from_index(ep_index); |
2809 | xhci_setup_input_ctx_for_config_ep(xhci, xhci->devs[slot_id]->in_ctx, | 2863 | xhci_setup_input_ctx_for_config_ep(xhci, xhci->devs[slot_id]->in_ctx, |
2810 | xhci->devs[slot_id]->out_ctx, added_ctxs, added_ctxs); | 2864 | xhci->devs[slot_id]->out_ctx, ctrl_ctx, |
2865 | added_ctxs, added_ctxs); | ||
2811 | } | 2866 | } |
2812 | 2867 | ||
2813 | void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, | 2868 | void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, |
@@ -3065,6 +3120,7 @@ int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev, | |||
3065 | struct xhci_hcd *xhci; | 3120 | struct xhci_hcd *xhci; |
3066 | struct xhci_virt_device *vdev; | 3121 | struct xhci_virt_device *vdev; |
3067 | struct xhci_command *config_cmd; | 3122 | struct xhci_command *config_cmd; |
3123 | struct xhci_input_control_ctx *ctrl_ctx; | ||
3068 | unsigned int ep_index; | 3124 | unsigned int ep_index; |
3069 | unsigned int num_stream_ctxs; | 3125 | unsigned int num_stream_ctxs; |
3070 | unsigned long flags; | 3126 | unsigned long flags; |
@@ -3086,6 +3142,13 @@ int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev, | |||
3086 | xhci_dbg(xhci, "Could not allocate xHCI command structure.\n"); | 3142 | xhci_dbg(xhci, "Could not allocate xHCI command structure.\n"); |
3087 | return -ENOMEM; | 3143 | return -ENOMEM; |
3088 | } | 3144 | } |
3145 | ctrl_ctx = xhci_get_input_control_ctx(xhci, config_cmd->in_ctx); | ||
3146 | if (!ctrl_ctx) { | ||
3147 | xhci_warn(xhci, "%s: Could not get input context, bad type.\n", | ||
3148 | __func__); | ||
3149 | xhci_free_command(xhci, config_cmd); | ||
3150 | return -ENOMEM; | ||
3151 | } | ||
3089 | 3152 | ||
3090 | /* Check to make sure all endpoints are not already configured for | 3153 | /* Check to make sure all endpoints are not already configured for |
3091 | * streams. While we're at it, find the maximum number of streams that | 3154 | * streams. While we're at it, find the maximum number of streams that |
@@ -3152,7 +3215,8 @@ int xhci_alloc_streams(struct usb_hcd *hcd, struct usb_device *udev, | |||
3152 | * and add the updated copy from the input context. | 3215 | * and add the updated copy from the input context. |
3153 | */ | 3216 | */ |
3154 | xhci_setup_input_ctx_for_config_ep(xhci, config_cmd->in_ctx, | 3217 | xhci_setup_input_ctx_for_config_ep(xhci, config_cmd->in_ctx, |
3155 | vdev->out_ctx, changed_ep_bitmask, changed_ep_bitmask); | 3218 | vdev->out_ctx, ctrl_ctx, |
3219 | changed_ep_bitmask, changed_ep_bitmask); | ||
3156 | 3220 | ||
3157 | /* Issue and wait for the configure endpoint command */ | 3221 | /* Issue and wait for the configure endpoint command */ |
3158 | ret = xhci_configure_endpoint(xhci, udev, config_cmd, | 3222 | ret = xhci_configure_endpoint(xhci, udev, config_cmd, |
@@ -3210,6 +3274,7 @@ int xhci_free_streams(struct usb_hcd *hcd, struct usb_device *udev, | |||
3210 | struct xhci_hcd *xhci; | 3274 | struct xhci_hcd *xhci; |
3211 | struct xhci_virt_device *vdev; | 3275 | struct xhci_virt_device *vdev; |
3212 | struct xhci_command *command; | 3276 | struct xhci_command *command; |
3277 | struct xhci_input_control_ctx *ctrl_ctx; | ||
3213 | unsigned int ep_index; | 3278 | unsigned int ep_index; |
3214 | unsigned long flags; | 3279 | unsigned long flags; |
3215 | u32 changed_ep_bitmask; | 3280 | u32 changed_ep_bitmask; |
@@ -3232,6 +3297,14 @@ int xhci_free_streams(struct usb_hcd *hcd, struct usb_device *udev, | |||
3232 | */ | 3297 | */ |
3233 | ep_index = xhci_get_endpoint_index(&eps[0]->desc); | 3298 | ep_index = xhci_get_endpoint_index(&eps[0]->desc); |
3234 | command = vdev->eps[ep_index].stream_info->free_streams_command; | 3299 | command = vdev->eps[ep_index].stream_info->free_streams_command; |
3300 | ctrl_ctx = xhci_get_input_control_ctx(xhci, command->in_ctx); | ||
3301 | if (!ctrl_ctx) { | ||
3302 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
3303 | xhci_warn(xhci, "%s: Could not get input context, bad type.\n", | ||
3304 | __func__); | ||
3305 | return -EINVAL; | ||
3306 | } | ||
3307 | |||
3235 | for (i = 0; i < num_eps; i++) { | 3308 | for (i = 0; i < num_eps; i++) { |
3236 | struct xhci_ep_ctx *ep_ctx; | 3309 | struct xhci_ep_ctx *ep_ctx; |
3237 | 3310 | ||
@@ -3246,7 +3319,8 @@ int xhci_free_streams(struct usb_hcd *hcd, struct usb_device *udev, | |||
3246 | &vdev->eps[ep_index]); | 3319 | &vdev->eps[ep_index]); |
3247 | } | 3320 | } |
3248 | xhci_setup_input_ctx_for_config_ep(xhci, command->in_ctx, | 3321 | xhci_setup_input_ctx_for_config_ep(xhci, command->in_ctx, |
3249 | vdev->out_ctx, changed_ep_bitmask, changed_ep_bitmask); | 3322 | vdev->out_ctx, ctrl_ctx, |
3323 | changed_ep_bitmask, changed_ep_bitmask); | ||
3250 | spin_unlock_irqrestore(&xhci->lock, flags); | 3324 | spin_unlock_irqrestore(&xhci->lock, flags); |
3251 | 3325 | ||
3252 | /* Issue and wait for the configure endpoint command, | 3326 | /* Issue and wait for the configure endpoint command, |
@@ -3686,6 +3760,12 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) | |||
3686 | } | 3760 | } |
3687 | 3761 | ||
3688 | slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx); | 3762 | slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx); |
3763 | ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx); | ||
3764 | if (!ctrl_ctx) { | ||
3765 | xhci_warn(xhci, "%s: Could not get input context, bad type.\n", | ||
3766 | __func__); | ||
3767 | return -EINVAL; | ||
3768 | } | ||
3689 | /* | 3769 | /* |
3690 | * If this is the first Set Address since device plug-in or | 3770 | * If this is the first Set Address since device plug-in or |
3691 | * virt_device realloaction after a resume with an xHCI power loss, | 3771 | * virt_device realloaction after a resume with an xHCI power loss, |
@@ -3696,7 +3776,6 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) | |||
3696 | /* Otherwise, update the control endpoint ring enqueue pointer. */ | 3776 | /* Otherwise, update the control endpoint ring enqueue pointer. */ |
3697 | else | 3777 | else |
3698 | xhci_copy_ep0_dequeue_into_input_ctx(xhci, udev); | 3778 | xhci_copy_ep0_dequeue_into_input_ctx(xhci, udev); |
3699 | ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx); | ||
3700 | ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG); | 3779 | ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG); |
3701 | ctrl_ctx->drop_flags = 0; | 3780 | ctrl_ctx->drop_flags = 0; |
3702 | 3781 | ||
@@ -3815,6 +3894,63 @@ int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1) | |||
3815 | return raw_port; | 3894 | return raw_port; |
3816 | } | 3895 | } |
3817 | 3896 | ||
3897 | /* | ||
3898 | * Issue an Evaluate Context command to change the Maximum Exit Latency in the | ||
3899 | * slot context. If that succeeds, store the new MEL in the xhci_virt_device. | ||
3900 | */ | ||
3901 | static int xhci_change_max_exit_latency(struct xhci_hcd *xhci, | ||
3902 | struct usb_device *udev, u16 max_exit_latency) | ||
3903 | { | ||
3904 | struct xhci_virt_device *virt_dev; | ||
3905 | struct xhci_command *command; | ||
3906 | struct xhci_input_control_ctx *ctrl_ctx; | ||
3907 | struct xhci_slot_ctx *slot_ctx; | ||
3908 | unsigned long flags; | ||
3909 | int ret; | ||
3910 | |||
3911 | spin_lock_irqsave(&xhci->lock, flags); | ||
3912 | if (max_exit_latency == xhci->devs[udev->slot_id]->current_mel) { | ||
3913 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
3914 | return 0; | ||
3915 | } | ||
3916 | |||
3917 | /* Attempt to issue an Evaluate Context command to change the MEL. */ | ||
3918 | virt_dev = xhci->devs[udev->slot_id]; | ||
3919 | command = xhci->lpm_command; | ||
3920 | ctrl_ctx = xhci_get_input_control_ctx(xhci, command->in_ctx); | ||
3921 | if (!ctrl_ctx) { | ||
3922 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
3923 | xhci_warn(xhci, "%s: Could not get input context, bad type.\n", | ||
3924 | __func__); | ||
3925 | return -ENOMEM; | ||
3926 | } | ||
3927 | |||
3928 | xhci_slot_copy(xhci, command->in_ctx, virt_dev->out_ctx); | ||
3929 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
3930 | |||
3931 | ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG); | ||
3932 | slot_ctx = xhci_get_slot_ctx(xhci, command->in_ctx); | ||
3933 | slot_ctx->dev_info2 &= cpu_to_le32(~((u32) MAX_EXIT)); | ||
3934 | slot_ctx->dev_info2 |= cpu_to_le32(max_exit_latency); | ||
3935 | |||
3936 | xhci_dbg(xhci, "Set up evaluate context for LPM MEL change.\n"); | ||
3937 | xhci_dbg(xhci, "Slot %u Input Context:\n", udev->slot_id); | ||
3938 | xhci_dbg_ctx(xhci, command->in_ctx, 0); | ||
3939 | |||
3940 | /* Issue and wait for the evaluate context command. */ | ||
3941 | ret = xhci_configure_endpoint(xhci, udev, command, | ||
3942 | true, true); | ||
3943 | xhci_dbg(xhci, "Slot %u Output Context:\n", udev->slot_id); | ||
3944 | xhci_dbg_ctx(xhci, virt_dev->out_ctx, 0); | ||
3945 | |||
3946 | if (!ret) { | ||
3947 | spin_lock_irqsave(&xhci->lock, flags); | ||
3948 | virt_dev->current_mel = max_exit_latency; | ||
3949 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
3950 | } | ||
3951 | return ret; | ||
3952 | } | ||
3953 | |||
3818 | #ifdef CONFIG_PM_RUNTIME | 3954 | #ifdef CONFIG_PM_RUNTIME |
3819 | 3955 | ||
3820 | /* BESL to HIRD Encoding array for USB2 LPM */ | 3956 | /* BESL to HIRD Encoding array for USB2 LPM */ |
@@ -3856,6 +3992,28 @@ static int xhci_calculate_hird_besl(struct xhci_hcd *xhci, | |||
3856 | return besl; | 3992 | return besl; |
3857 | } | 3993 | } |
3858 | 3994 | ||
3995 | /* Calculate BESLD, L1 timeout and HIRDM for USB2 PORTHLPMC */ | ||
3996 | static int xhci_calculate_usb2_hw_lpm_params(struct usb_device *udev) | ||
3997 | { | ||
3998 | u32 field; | ||
3999 | int l1; | ||
4000 | int besld = 0; | ||
4001 | int hirdm = 0; | ||
4002 | |||
4003 | field = le32_to_cpu(udev->bos->ext_cap->bmAttributes); | ||
4004 | |||
4005 | /* xHCI l1 is set in steps of 256us, xHCI 1.0 section 5.4.11.2 */ | ||
4006 | l1 = udev->l1_params.timeout / 256; | ||
4007 | |||
4008 | /* device has preferred BESLD */ | ||
4009 | if (field & USB_BESL_DEEP_VALID) { | ||
4010 | besld = USB_GET_BESL_DEEP(field); | ||
4011 | hirdm = 1; | ||
4012 | } | ||
4013 | |||
4014 | return PORT_BESLD(besld) | PORT_L1_TIMEOUT(l1) | PORT_HIRDM(hirdm); | ||
4015 | } | ||
4016 | |||
3859 | static int xhci_usb2_software_lpm_test(struct usb_hcd *hcd, | 4017 | static int xhci_usb2_software_lpm_test(struct usb_hcd *hcd, |
3860 | struct usb_device *udev) | 4018 | struct usb_device *udev) |
3861 | { | 4019 | { |
@@ -3911,7 +4069,7 @@ static int xhci_usb2_software_lpm_test(struct usb_hcd *hcd, | |||
3911 | * Check device's USB 2.0 extension descriptor to determine whether | 4069 | * Check device's USB 2.0 extension descriptor to determine whether |
3912 | * HIRD or BESL shoule be used. See USB2.0 LPM errata. | 4070 | * HIRD or BESL shoule be used. See USB2.0 LPM errata. |
3913 | */ | 4071 | */ |
3914 | pm_addr = port_array[port_num] + 1; | 4072 | pm_addr = port_array[port_num] + PORTPMSC; |
3915 | hird = xhci_calculate_hird_besl(xhci, udev); | 4073 | hird = xhci_calculate_hird_besl(xhci, udev); |
3916 | temp = PORT_L1DS(udev->slot_id) | PORT_HIRD(hird); | 4074 | temp = PORT_L1DS(udev->slot_id) | PORT_HIRD(hird); |
3917 | xhci_writel(xhci, temp, pm_addr); | 4075 | xhci_writel(xhci, temp, pm_addr); |
@@ -3988,11 +4146,12 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, | |||
3988 | { | 4146 | { |
3989 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 4147 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
3990 | __le32 __iomem **port_array; | 4148 | __le32 __iomem **port_array; |
3991 | __le32 __iomem *pm_addr; | 4149 | __le32 __iomem *pm_addr, *hlpm_addr; |
3992 | u32 temp; | 4150 | u32 pm_val, hlpm_val, field; |
3993 | unsigned int port_num; | 4151 | unsigned int port_num; |
3994 | unsigned long flags; | 4152 | unsigned long flags; |
3995 | int hird; | 4153 | int hird, exit_latency; |
4154 | int ret; | ||
3996 | 4155 | ||
3997 | if (hcd->speed == HCD_USB3 || !xhci->hw_lpm_support || | 4156 | if (hcd->speed == HCD_USB3 || !xhci->hw_lpm_support || |
3998 | !udev->lpm_capable) | 4157 | !udev->lpm_capable) |
@@ -4009,40 +4168,120 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, | |||
4009 | 4168 | ||
4010 | port_array = xhci->usb2_ports; | 4169 | port_array = xhci->usb2_ports; |
4011 | port_num = udev->portnum - 1; | 4170 | port_num = udev->portnum - 1; |
4012 | pm_addr = port_array[port_num] + 1; | 4171 | pm_addr = port_array[port_num] + PORTPMSC; |
4013 | temp = xhci_readl(xhci, pm_addr); | 4172 | pm_val = xhci_readl(xhci, pm_addr); |
4173 | hlpm_addr = port_array[port_num] + PORTHLPMC; | ||
4174 | field = le32_to_cpu(udev->bos->ext_cap->bmAttributes); | ||
4014 | 4175 | ||
4015 | xhci_dbg(xhci, "%s port %d USB2 hardware LPM\n", | 4176 | xhci_dbg(xhci, "%s port %d USB2 hardware LPM\n", |
4016 | enable ? "enable" : "disable", port_num); | 4177 | enable ? "enable" : "disable", port_num); |
4017 | 4178 | ||
4018 | hird = xhci_calculate_hird_besl(xhci, udev); | ||
4019 | |||
4020 | if (enable) { | 4179 | if (enable) { |
4021 | temp &= ~PORT_HIRD_MASK; | 4180 | /* Host supports BESL timeout instead of HIRD */ |
4022 | temp |= PORT_HIRD(hird) | PORT_RWE; | 4181 | if (udev->usb2_hw_lpm_besl_capable) { |
4023 | xhci_writel(xhci, temp, pm_addr); | 4182 | /* if device doesn't have a preferred BESL value use a |
4024 | temp = xhci_readl(xhci, pm_addr); | 4183 | * default one which works with mixed HIRD and BESL |
4025 | temp |= PORT_HLE; | 4184 | * systems. See XHCI_DEFAULT_BESL definition in xhci.h |
4026 | xhci_writel(xhci, temp, pm_addr); | 4185 | */ |
4186 | if ((field & USB_BESL_SUPPORT) && | ||
4187 | (field & USB_BESL_BASELINE_VALID)) | ||
4188 | hird = USB_GET_BESL_BASELINE(field); | ||
4189 | else | ||
4190 | hird = udev->l1_params.besl; | ||
4191 | |||
4192 | exit_latency = xhci_besl_encoding[hird]; | ||
4193 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
4194 | |||
4195 | /* USB 3.0 code dedicate one xhci->lpm_command->in_ctx | ||
4196 | * input context for link powermanagement evaluate | ||
4197 | * context commands. It is protected by hcd->bandwidth | ||
4198 | * mutex and is shared by all devices. We need to set | ||
4199 | * the max ext latency in USB 2 BESL LPM as well, so | ||
4200 | * use the same mutex and xhci_change_max_exit_latency() | ||
4201 | */ | ||
4202 | mutex_lock(hcd->bandwidth_mutex); | ||
4203 | ret = xhci_change_max_exit_latency(xhci, udev, | ||
4204 | exit_latency); | ||
4205 | mutex_unlock(hcd->bandwidth_mutex); | ||
4206 | |||
4207 | if (ret < 0) | ||
4208 | return ret; | ||
4209 | spin_lock_irqsave(&xhci->lock, flags); | ||
4210 | |||
4211 | hlpm_val = xhci_calculate_usb2_hw_lpm_params(udev); | ||
4212 | xhci_writel(xhci, hlpm_val, hlpm_addr); | ||
4213 | /* flush write */ | ||
4214 | xhci_readl(xhci, hlpm_addr); | ||
4215 | } else { | ||
4216 | hird = xhci_calculate_hird_besl(xhci, udev); | ||
4217 | } | ||
4218 | |||
4219 | pm_val &= ~PORT_HIRD_MASK; | ||
4220 | pm_val |= PORT_HIRD(hird) | PORT_RWE; | ||
4221 | xhci_writel(xhci, pm_val, pm_addr); | ||
4222 | pm_val = xhci_readl(xhci, pm_addr); | ||
4223 | pm_val |= PORT_HLE; | ||
4224 | xhci_writel(xhci, pm_val, pm_addr); | ||
4225 | /* flush write */ | ||
4226 | xhci_readl(xhci, pm_addr); | ||
4027 | } else { | 4227 | } else { |
4028 | temp &= ~(PORT_HLE | PORT_RWE | PORT_HIRD_MASK); | 4228 | pm_val &= ~(PORT_HLE | PORT_RWE | PORT_HIRD_MASK); |
4029 | xhci_writel(xhci, temp, pm_addr); | 4229 | xhci_writel(xhci, pm_val, pm_addr); |
4230 | /* flush write */ | ||
4231 | xhci_readl(xhci, pm_addr); | ||
4232 | if (udev->usb2_hw_lpm_besl_capable) { | ||
4233 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
4234 | mutex_lock(hcd->bandwidth_mutex); | ||
4235 | xhci_change_max_exit_latency(xhci, udev, 0); | ||
4236 | mutex_unlock(hcd->bandwidth_mutex); | ||
4237 | return 0; | ||
4238 | } | ||
4030 | } | 4239 | } |
4031 | 4240 | ||
4032 | spin_unlock_irqrestore(&xhci->lock, flags); | 4241 | spin_unlock_irqrestore(&xhci->lock, flags); |
4033 | return 0; | 4242 | return 0; |
4034 | } | 4243 | } |
4035 | 4244 | ||
4245 | /* check if a usb2 port supports a given extened capability protocol | ||
4246 | * only USB2 ports extended protocol capability values are cached. | ||
4247 | * Return 1 if capability is supported | ||
4248 | */ | ||
4249 | static int xhci_check_usb2_port_capability(struct xhci_hcd *xhci, int port, | ||
4250 | unsigned capability) | ||
4251 | { | ||
4252 | u32 port_offset, port_count; | ||
4253 | int i; | ||
4254 | |||
4255 | for (i = 0; i < xhci->num_ext_caps; i++) { | ||
4256 | if (xhci->ext_caps[i] & capability) { | ||
4257 | /* port offsets starts at 1 */ | ||
4258 | port_offset = XHCI_EXT_PORT_OFF(xhci->ext_caps[i]) - 1; | ||
4259 | port_count = XHCI_EXT_PORT_COUNT(xhci->ext_caps[i]); | ||
4260 | if (port >= port_offset && | ||
4261 | port < port_offset + port_count) | ||
4262 | return 1; | ||
4263 | } | ||
4264 | } | ||
4265 | return 0; | ||
4266 | } | ||
4267 | |||
4036 | int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev) | 4268 | int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev) |
4037 | { | 4269 | { |
4038 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 4270 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
4039 | int ret; | 4271 | int ret; |
4272 | int portnum = udev->portnum - 1; | ||
4040 | 4273 | ||
4041 | ret = xhci_usb2_software_lpm_test(hcd, udev); | 4274 | ret = xhci_usb2_software_lpm_test(hcd, udev); |
4042 | if (!ret) { | 4275 | if (!ret) { |
4043 | xhci_dbg(xhci, "software LPM test succeed\n"); | 4276 | xhci_dbg(xhci, "software LPM test succeed\n"); |
4044 | if (xhci->hw_lpm_support == 1) { | 4277 | if (xhci->hw_lpm_support == 1 && |
4278 | xhci_check_usb2_port_capability(xhci, portnum, XHCI_HLC)) { | ||
4045 | udev->usb2_hw_lpm_capable = 1; | 4279 | udev->usb2_hw_lpm_capable = 1; |
4280 | udev->l1_params.timeout = XHCI_L1_TIMEOUT; | ||
4281 | udev->l1_params.besl = XHCI_DEFAULT_BESL; | ||
4282 | if (xhci_check_usb2_port_capability(xhci, portnum, | ||
4283 | XHCI_BLC)) | ||
4284 | udev->usb2_hw_lpm_besl_capable = 1; | ||
4046 | ret = xhci_set_usb2_hardware_lpm(hcd, udev, 1); | 4285 | ret = xhci_set_usb2_hardware_lpm(hcd, udev, 1); |
4047 | if (!ret) | 4286 | if (!ret) |
4048 | udev->usb2_hw_lpm_enabled = 1; | 4287 | udev->usb2_hw_lpm_enabled = 1; |
@@ -4373,56 +4612,6 @@ static u16 xhci_calculate_lpm_timeout(struct usb_hcd *hcd, | |||
4373 | return timeout; | 4612 | return timeout; |
4374 | } | 4613 | } |
4375 | 4614 | ||
4376 | /* | ||
4377 | * Issue an Evaluate Context command to change the Maximum Exit Latency in the | ||
4378 | * slot context. If that succeeds, store the new MEL in the xhci_virt_device. | ||
4379 | */ | ||
4380 | static int xhci_change_max_exit_latency(struct xhci_hcd *xhci, | ||
4381 | struct usb_device *udev, u16 max_exit_latency) | ||
4382 | { | ||
4383 | struct xhci_virt_device *virt_dev; | ||
4384 | struct xhci_command *command; | ||
4385 | struct xhci_input_control_ctx *ctrl_ctx; | ||
4386 | struct xhci_slot_ctx *slot_ctx; | ||
4387 | unsigned long flags; | ||
4388 | int ret; | ||
4389 | |||
4390 | spin_lock_irqsave(&xhci->lock, flags); | ||
4391 | if (max_exit_latency == xhci->devs[udev->slot_id]->current_mel) { | ||
4392 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
4393 | return 0; | ||
4394 | } | ||
4395 | |||
4396 | /* Attempt to issue an Evaluate Context command to change the MEL. */ | ||
4397 | virt_dev = xhci->devs[udev->slot_id]; | ||
4398 | command = xhci->lpm_command; | ||
4399 | xhci_slot_copy(xhci, command->in_ctx, virt_dev->out_ctx); | ||
4400 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
4401 | |||
4402 | ctrl_ctx = xhci_get_input_control_ctx(xhci, command->in_ctx); | ||
4403 | ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG); | ||
4404 | slot_ctx = xhci_get_slot_ctx(xhci, command->in_ctx); | ||
4405 | slot_ctx->dev_info2 &= cpu_to_le32(~((u32) MAX_EXIT)); | ||
4406 | slot_ctx->dev_info2 |= cpu_to_le32(max_exit_latency); | ||
4407 | |||
4408 | xhci_dbg(xhci, "Set up evaluate context for LPM MEL change.\n"); | ||
4409 | xhci_dbg(xhci, "Slot %u Input Context:\n", udev->slot_id); | ||
4410 | xhci_dbg_ctx(xhci, command->in_ctx, 0); | ||
4411 | |||
4412 | /* Issue and wait for the evaluate context command. */ | ||
4413 | ret = xhci_configure_endpoint(xhci, udev, command, | ||
4414 | true, true); | ||
4415 | xhci_dbg(xhci, "Slot %u Output Context:\n", udev->slot_id); | ||
4416 | xhci_dbg_ctx(xhci, virt_dev->out_ctx, 0); | ||
4417 | |||
4418 | if (!ret) { | ||
4419 | spin_lock_irqsave(&xhci->lock, flags); | ||
4420 | virt_dev->current_mel = max_exit_latency; | ||
4421 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
4422 | } | ||
4423 | return ret; | ||
4424 | } | ||
4425 | |||
4426 | static int calculate_max_exit_latency(struct usb_device *udev, | 4615 | static int calculate_max_exit_latency(struct usb_device *udev, |
4427 | enum usb3_link_state state_changed, | 4616 | enum usb3_link_state state_changed, |
4428 | u16 hub_encoded_timeout) | 4617 | u16 hub_encoded_timeout) |
@@ -4564,6 +4753,13 @@ int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev, | |||
4564 | xhci_dbg(xhci, "Could not allocate xHCI command structure.\n"); | 4753 | xhci_dbg(xhci, "Could not allocate xHCI command structure.\n"); |
4565 | return -ENOMEM; | 4754 | return -ENOMEM; |
4566 | } | 4755 | } |
4756 | ctrl_ctx = xhci_get_input_control_ctx(xhci, config_cmd->in_ctx); | ||
4757 | if (!ctrl_ctx) { | ||
4758 | xhci_warn(xhci, "%s: Could not get input context, bad type.\n", | ||
4759 | __func__); | ||
4760 | xhci_free_command(xhci, config_cmd); | ||
4761 | return -ENOMEM; | ||
4762 | } | ||
4567 | 4763 | ||
4568 | spin_lock_irqsave(&xhci->lock, flags); | 4764 | spin_lock_irqsave(&xhci->lock, flags); |
4569 | if (hdev->speed == USB_SPEED_HIGH && | 4765 | if (hdev->speed == USB_SPEED_HIGH && |
@@ -4575,7 +4771,6 @@ int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev, | |||
4575 | } | 4771 | } |
4576 | 4772 | ||
4577 | xhci_slot_copy(xhci, config_cmd->in_ctx, vdev->out_ctx); | 4773 | xhci_slot_copy(xhci, config_cmd->in_ctx, vdev->out_ctx); |
4578 | ctrl_ctx = xhci_get_input_control_ctx(xhci, config_cmd->in_ctx); | ||
4579 | ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG); | 4774 | ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG); |
4580 | slot_ctx = xhci_get_slot_ctx(xhci, config_cmd->in_ctx); | 4775 | slot_ctx = xhci_get_slot_ctx(xhci, config_cmd->in_ctx); |
4581 | slot_ctx->dev_info |= cpu_to_le32(DEV_HUB); | 4776 | slot_ctx->dev_info |= cpu_to_le32(DEV_HUB); |
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 77600cefcaf1..c338741a675d 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h | |||
@@ -132,6 +132,11 @@ struct xhci_cap_regs { | |||
132 | /* Number of registers per port */ | 132 | /* Number of registers per port */ |
133 | #define NUM_PORT_REGS 4 | 133 | #define NUM_PORT_REGS 4 |
134 | 134 | ||
135 | #define PORTSC 0 | ||
136 | #define PORTPMSC 1 | ||
137 | #define PORTLI 2 | ||
138 | #define PORTHLPMC 3 | ||
139 | |||
135 | /** | 140 | /** |
136 | * struct xhci_op_regs - xHCI Host Controller Operational Registers. | 141 | * struct xhci_op_regs - xHCI Host Controller Operational Registers. |
137 | * @command: USBCMD - xHC command register | 142 | * @command: USBCMD - xHC command register |
@@ -381,6 +386,27 @@ struct xhci_op_regs { | |||
381 | #define PORT_L1DS(p) (((p) & 0xff) << 8) | 386 | #define PORT_L1DS(p) (((p) & 0xff) << 8) |
382 | #define PORT_HLE (1 << 16) | 387 | #define PORT_HLE (1 << 16) |
383 | 388 | ||
389 | |||
390 | /* USB2 Protocol PORTHLPMC */ | ||
391 | #define PORT_HIRDM(p)((p) & 3) | ||
392 | #define PORT_L1_TIMEOUT(p)(((p) & 0xff) << 2) | ||
393 | #define PORT_BESLD(p)(((p) & 0xf) << 10) | ||
394 | |||
395 | /* use 512 microseconds as USB2 LPM L1 default timeout. */ | ||
396 | #define XHCI_L1_TIMEOUT 512 | ||
397 | |||
398 | /* Set default HIRD/BESL value to 4 (350/400us) for USB2 L1 LPM resume latency. | ||
399 | * Safe to use with mixed HIRD and BESL systems (host and device) and is used | ||
400 | * by other operating systems. | ||
401 | * | ||
402 | * XHCI 1.0 errata 8/14/12 Table 13 notes: | ||
403 | * "Software should choose xHC BESL/BESLD field values that do not violate a | ||
404 | * device's resume latency requirements, | ||
405 | * e.g. not program values > '4' if BLC = '1' and a HIRD device is attached, | ||
406 | * or not program values < '4' if BLC = '0' and a BESL device is attached. | ||
407 | */ | ||
408 | #define XHCI_DEFAULT_BESL 4 | ||
409 | |||
384 | /** | 410 | /** |
385 | * struct xhci_intr_reg - Interrupt Register Set | 411 | * struct xhci_intr_reg - Interrupt Register Set |
386 | * @irq_pending: IMAN - Interrupt Management Register. Used to enable | 412 | * @irq_pending: IMAN - Interrupt Management Register. Used to enable |
@@ -1532,6 +1558,9 @@ struct xhci_hcd { | |||
1532 | unsigned sw_lpm_support:1; | 1558 | unsigned sw_lpm_support:1; |
1533 | /* support xHCI 1.0 spec USB2 hardware LPM */ | 1559 | /* support xHCI 1.0 spec USB2 hardware LPM */ |
1534 | unsigned hw_lpm_support:1; | 1560 | unsigned hw_lpm_support:1; |
1561 | /* cached usb2 extened protocol capabilites */ | ||
1562 | u32 *ext_caps; | ||
1563 | unsigned int num_ext_caps; | ||
1535 | /* Compliance Mode Recovery Data */ | 1564 | /* Compliance Mode Recovery Data */ |
1536 | struct timer_list comp_mode_recovery_timer; | 1565 | struct timer_list comp_mode_recovery_timer; |
1537 | u32 port_status_u0; | 1566 | u32 port_status_u0; |
@@ -1641,6 +1670,7 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud | |||
1641 | void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci, | 1670 | void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci, |
1642 | struct usb_device *udev); | 1671 | struct usb_device *udev); |
1643 | unsigned int xhci_get_endpoint_index(struct usb_endpoint_descriptor *desc); | 1672 | unsigned int xhci_get_endpoint_index(struct usb_endpoint_descriptor *desc); |
1673 | unsigned int xhci_get_endpoint_address(unsigned int ep_index); | ||
1644 | unsigned int xhci_get_endpoint_flag(struct usb_endpoint_descriptor *desc); | 1674 | unsigned int xhci_get_endpoint_flag(struct usb_endpoint_descriptor *desc); |
1645 | unsigned int xhci_get_endpoint_flag_from_index(unsigned int ep_index); | 1675 | unsigned int xhci_get_endpoint_flag_from_index(unsigned int ep_index); |
1646 | unsigned int xhci_last_valid_endpoint(u32 added_ctxs); | 1676 | unsigned int xhci_last_valid_endpoint(u32 added_ctxs); |
@@ -1745,7 +1775,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated); | |||
1745 | 1775 | ||
1746 | int xhci_get_frame(struct usb_hcd *hcd); | 1776 | int xhci_get_frame(struct usb_hcd *hcd); |
1747 | irqreturn_t xhci_irq(struct usb_hcd *hcd); | 1777 | irqreturn_t xhci_irq(struct usb_hcd *hcd); |
1748 | irqreturn_t xhci_msi_irq(int irq, struct usb_hcd *hcd); | 1778 | irqreturn_t xhci_msi_irq(int irq, void *hcd); |
1749 | int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev); | 1779 | int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev); |
1750 | void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev); | 1780 | void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev); |
1751 | int xhci_alloc_tt_info(struct xhci_hcd *xhci, | 1781 | int xhci_alloc_tt_info(struct xhci_hcd *xhci, |
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index 284b85461410..eb3c8c142fa9 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/usb.h> | 26 | #include <linux/usb.h> |
27 | #include <linux/mutex.h> | 27 | #include <linux/mutex.h> |
28 | #include <asm/uaccess.h> | 28 | #include <linux/uaccess.h> |
29 | 29 | ||
30 | #ifdef CONFIG_USB_DEBUG | 30 | #ifdef CONFIG_USB_DEBUG |
31 | static int debug = 5; | 31 | static int debug = 5; |
@@ -35,8 +35,8 @@ static int debug = 1; | |||
35 | 35 | ||
36 | /* Use our own dbg macro */ | 36 | /* Use our own dbg macro */ |
37 | #undef dbg | 37 | #undef dbg |
38 | #define dbg(lvl, format, arg...) \ | 38 | #define dbg(lvl, format, arg...) \ |
39 | do { \ | 39 | do { \ |
40 | if (debug >= lvl) \ | 40 | if (debug >= lvl) \ |
41 | printk(KERN_DEBUG "%s: " format "\n", __FILE__, ##arg); \ | 41 | printk(KERN_DEBUG "%s: " format "\n", __FILE__, ##arg); \ |
42 | } while (0) | 42 | } while (0) |
@@ -58,12 +58,12 @@ MODULE_PARM_DESC(debug, "Debug enabled or not"); | |||
58 | /* table of devices that work with this driver */ | 58 | /* table of devices that work with this driver */ |
59 | static const struct usb_device_id device_table[] = { | 59 | static const struct usb_device_id device_table[] = { |
60 | { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID) }, /* ADU100 */ | 60 | { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID) }, /* ADU100 */ |
61 | { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+20) }, /* ADU120 */ | 61 | { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+20) }, /* ADU120 */ |
62 | { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+30) }, /* ADU130 */ | 62 | { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+30) }, /* ADU130 */ |
63 | { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+100) }, /* ADU200 */ | 63 | { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+100) }, /* ADU200 */ |
64 | { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+108) }, /* ADU208 */ | 64 | { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+108) }, /* ADU208 */ |
65 | { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+118) }, /* ADU218 */ | 65 | { USB_DEVICE(ADU_VENDOR_ID, ADU_PRODUCT_ID+118) }, /* ADU218 */ |
66 | { }/* Terminating entry */ | 66 | { } /* Terminating entry */ |
67 | }; | 67 | }; |
68 | 68 | ||
69 | MODULE_DEVICE_TABLE(usb, device_table); | 69 | MODULE_DEVICE_TABLE(usb, device_table); |
@@ -92,16 +92,16 @@ MODULE_DEVICE_TABLE(usb, device_table); | |||
92 | /* Structure to hold all of our device specific stuff */ | 92 | /* Structure to hold all of our device specific stuff */ |
93 | struct adu_device { | 93 | struct adu_device { |
94 | struct mutex mtx; | 94 | struct mutex mtx; |
95 | struct usb_device* udev; /* save off the usb device pointer */ | 95 | struct usb_device *udev; /* save off the usb device pointer */ |
96 | struct usb_interface* interface; | 96 | struct usb_interface *interface; |
97 | unsigned int minor; /* the starting minor number for this device */ | 97 | unsigned int minor; /* the starting minor number for this device */ |
98 | char serial_number[8]; | 98 | char serial_number[8]; |
99 | 99 | ||
100 | int open_count; /* number of times this port has been opened */ | 100 | int open_count; /* number of times this port has been opened */ |
101 | 101 | ||
102 | char* read_buffer_primary; | 102 | char *read_buffer_primary; |
103 | int read_buffer_length; | 103 | int read_buffer_length; |
104 | char* read_buffer_secondary; | 104 | char *read_buffer_secondary; |
105 | int secondary_head; | 105 | int secondary_head; |
106 | int secondary_tail; | 106 | int secondary_tail; |
107 | spinlock_t buflock; | 107 | spinlock_t buflock; |
@@ -109,14 +109,14 @@ struct adu_device { | |||
109 | wait_queue_head_t read_wait; | 109 | wait_queue_head_t read_wait; |
110 | wait_queue_head_t write_wait; | 110 | wait_queue_head_t write_wait; |
111 | 111 | ||
112 | char* interrupt_in_buffer; | 112 | char *interrupt_in_buffer; |
113 | struct usb_endpoint_descriptor* interrupt_in_endpoint; | 113 | struct usb_endpoint_descriptor *interrupt_in_endpoint; |
114 | struct urb* interrupt_in_urb; | 114 | struct urb *interrupt_in_urb; |
115 | int read_urb_finished; | 115 | int read_urb_finished; |
116 | 116 | ||
117 | char* interrupt_out_buffer; | 117 | char *interrupt_out_buffer; |
118 | struct usb_endpoint_descriptor* interrupt_out_endpoint; | 118 | struct usb_endpoint_descriptor *interrupt_out_endpoint; |
119 | struct urb* interrupt_out_urb; | 119 | struct urb *interrupt_out_urb; |
120 | int out_urb_finished; | 120 | int out_urb_finished; |
121 | }; | 121 | }; |
122 | 122 | ||
@@ -147,10 +147,10 @@ static void adu_abort_transfers(struct adu_device *dev) | |||
147 | { | 147 | { |
148 | unsigned long flags; | 148 | unsigned long flags; |
149 | 149 | ||
150 | dbg(2," %s : enter", __func__); | 150 | dbg(2, " %s : enter", __func__); |
151 | 151 | ||
152 | if (dev->udev == NULL) { | 152 | if (dev->udev == NULL) { |
153 | dbg(1," %s : udev is null", __func__); | 153 | dbg(1, " %s : udev is null", __func__); |
154 | goto exit; | 154 | goto exit; |
155 | } | 155 | } |
156 | 156 | ||
@@ -172,7 +172,7 @@ static void adu_abort_transfers(struct adu_device *dev) | |||
172 | spin_unlock_irqrestore(&dev->buflock, flags); | 172 | spin_unlock_irqrestore(&dev->buflock, flags); |
173 | 173 | ||
174 | exit: | 174 | exit: |
175 | dbg(2," %s : leave", __func__); | 175 | dbg(2, " %s : leave", __func__); |
176 | } | 176 | } |
177 | 177 | ||
178 | static void adu_delete(struct adu_device *dev) | 178 | static void adu_delete(struct adu_device *dev) |
@@ -196,7 +196,7 @@ static void adu_interrupt_in_callback(struct urb *urb) | |||
196 | struct adu_device *dev = urb->context; | 196 | struct adu_device *dev = urb->context; |
197 | int status = urb->status; | 197 | int status = urb->status; |
198 | 198 | ||
199 | dbg(4," %s : enter, status %d", __func__, status); | 199 | dbg(4, " %s : enter, status %d", __func__, status); |
200 | adu_debug_data(5, __func__, urb->actual_length, | 200 | adu_debug_data(5, __func__, urb->actual_length, |
201 | urb->transfer_buffer); | 201 | urb->transfer_buffer); |
202 | 202 | ||
@@ -205,7 +205,7 @@ static void adu_interrupt_in_callback(struct urb *urb) | |||
205 | if (status != 0) { | 205 | if (status != 0) { |
206 | if ((status != -ENOENT) && (status != -ECONNRESET) && | 206 | if ((status != -ENOENT) && (status != -ECONNRESET) && |
207 | (status != -ESHUTDOWN)) { | 207 | (status != -ESHUTDOWN)) { |
208 | dbg(1," %s : nonzero status received: %d", | 208 | dbg(1, " %s : nonzero status received: %d", |
209 | __func__, status); | 209 | __func__, status); |
210 | } | 210 | } |
211 | goto exit; | 211 | goto exit; |
@@ -220,10 +220,10 @@ static void adu_interrupt_in_callback(struct urb *urb) | |||
220 | dev->interrupt_in_buffer, urb->actual_length); | 220 | dev->interrupt_in_buffer, urb->actual_length); |
221 | 221 | ||
222 | dev->read_buffer_length += urb->actual_length; | 222 | dev->read_buffer_length += urb->actual_length; |
223 | dbg(2," %s reading %d ", __func__, | 223 | dbg(2, " %s reading %d ", __func__, |
224 | urb->actual_length); | 224 | urb->actual_length); |
225 | } else { | 225 | } else { |
226 | dbg(1," %s : read_buffer overflow", __func__); | 226 | dbg(1, " %s : read_buffer overflow", __func__); |
227 | } | 227 | } |
228 | } | 228 | } |
229 | 229 | ||
@@ -234,7 +234,7 @@ exit: | |||
234 | wake_up_interruptible(&dev->read_wait); | 234 | wake_up_interruptible(&dev->read_wait); |
235 | adu_debug_data(5, __func__, urb->actual_length, | 235 | adu_debug_data(5, __func__, urb->actual_length, |
236 | urb->transfer_buffer); | 236 | urb->transfer_buffer); |
237 | dbg(4," %s : leave, status %d", __func__, status); | 237 | dbg(4, " %s : leave, status %d", __func__, status); |
238 | } | 238 | } |
239 | 239 | ||
240 | static void adu_interrupt_out_callback(struct urb *urb) | 240 | static void adu_interrupt_out_callback(struct urb *urb) |
@@ -242,8 +242,8 @@ static void adu_interrupt_out_callback(struct urb *urb) | |||
242 | struct adu_device *dev = urb->context; | 242 | struct adu_device *dev = urb->context; |
243 | int status = urb->status; | 243 | int status = urb->status; |
244 | 244 | ||
245 | dbg(4," %s : enter, status %d", __func__, status); | 245 | dbg(4, " %s : enter, status %d", __func__, status); |
246 | adu_debug_data(5,__func__, urb->actual_length, urb->transfer_buffer); | 246 | adu_debug_data(5, __func__, urb->actual_length, urb->transfer_buffer); |
247 | 247 | ||
248 | if (status != 0) { | 248 | if (status != 0) { |
249 | if ((status != -ENOENT) && | 249 | if ((status != -ENOENT) && |
@@ -262,7 +262,7 @@ exit: | |||
262 | 262 | ||
263 | adu_debug_data(5, __func__, urb->actual_length, | 263 | adu_debug_data(5, __func__, urb->actual_length, |
264 | urb->transfer_buffer); | 264 | urb->transfer_buffer); |
265 | dbg(4," %s : leave, status %d", __func__, status); | 265 | dbg(4, " %s : leave, status %d", __func__, status); |
266 | } | 266 | } |
267 | 267 | ||
268 | static int adu_open(struct inode *inode, struct file *file) | 268 | static int adu_open(struct inode *inode, struct file *file) |
@@ -272,11 +272,12 @@ static int adu_open(struct inode *inode, struct file *file) | |||
272 | int subminor; | 272 | int subminor; |
273 | int retval; | 273 | int retval; |
274 | 274 | ||
275 | dbg(2,"%s : enter", __func__); | 275 | dbg(2, "%s : enter", __func__); |
276 | 276 | ||
277 | subminor = iminor(inode); | 277 | subminor = iminor(inode); |
278 | 278 | ||
279 | if ((retval = mutex_lock_interruptible(&adutux_mutex))) { | 279 | retval = mutex_lock_interruptible(&adutux_mutex); |
280 | if (retval) { | ||
280 | dbg(2, "%s : mutex lock failed", __func__); | 281 | dbg(2, "%s : mutex lock failed", __func__); |
281 | goto exit_no_lock; | 282 | goto exit_no_lock; |
282 | } | 283 | } |
@@ -302,7 +303,7 @@ static int adu_open(struct inode *inode, struct file *file) | |||
302 | } | 303 | } |
303 | 304 | ||
304 | ++dev->open_count; | 305 | ++dev->open_count; |
305 | dbg(2,"%s : open count %d", __func__, dev->open_count); | 306 | dbg(2, "%s : open count %d", __func__, dev->open_count); |
306 | 307 | ||
307 | /* save device in the file's private structure */ | 308 | /* save device in the file's private structure */ |
308 | file->private_data = dev; | 309 | file->private_data = dev; |
@@ -311,7 +312,7 @@ static int adu_open(struct inode *inode, struct file *file) | |||
311 | dev->read_buffer_length = 0; | 312 | dev->read_buffer_length = 0; |
312 | 313 | ||
313 | /* fixup first read by having urb waiting for it */ | 314 | /* fixup first read by having urb waiting for it */ |
314 | usb_fill_int_urb(dev->interrupt_in_urb,dev->udev, | 315 | usb_fill_int_urb(dev->interrupt_in_urb, dev->udev, |
315 | usb_rcvintpipe(dev->udev, | 316 | usb_rcvintpipe(dev->udev, |
316 | dev->interrupt_in_endpoint->bEndpointAddress), | 317 | dev->interrupt_in_endpoint->bEndpointAddress), |
317 | dev->interrupt_in_buffer, | 318 | dev->interrupt_in_buffer, |
@@ -332,23 +333,23 @@ static int adu_open(struct inode *inode, struct file *file) | |||
332 | exit_no_device: | 333 | exit_no_device: |
333 | mutex_unlock(&adutux_mutex); | 334 | mutex_unlock(&adutux_mutex); |
334 | exit_no_lock: | 335 | exit_no_lock: |
335 | dbg(2,"%s : leave, return value %d ", __func__, retval); | 336 | dbg(2, "%s : leave, return value %d ", __func__, retval); |
336 | return retval; | 337 | return retval; |
337 | } | 338 | } |
338 | 339 | ||
339 | static void adu_release_internal(struct adu_device *dev) | 340 | static void adu_release_internal(struct adu_device *dev) |
340 | { | 341 | { |
341 | dbg(2," %s : enter", __func__); | 342 | dbg(2, " %s : enter", __func__); |
342 | 343 | ||
343 | /* decrement our usage count for the device */ | 344 | /* decrement our usage count for the device */ |
344 | --dev->open_count; | 345 | --dev->open_count; |
345 | dbg(2," %s : open count %d", __func__, dev->open_count); | 346 | dbg(2, " %s : open count %d", __func__, dev->open_count); |
346 | if (dev->open_count <= 0) { | 347 | if (dev->open_count <= 0) { |
347 | adu_abort_transfers(dev); | 348 | adu_abort_transfers(dev); |
348 | dev->open_count = 0; | 349 | dev->open_count = 0; |
349 | } | 350 | } |
350 | 351 | ||
351 | dbg(2," %s : leave", __func__); | 352 | dbg(2, " %s : leave", __func__); |
352 | } | 353 | } |
353 | 354 | ||
354 | static int adu_release(struct inode *inode, struct file *file) | 355 | static int adu_release(struct inode *inode, struct file *file) |
@@ -356,17 +357,17 @@ static int adu_release(struct inode *inode, struct file *file) | |||
356 | struct adu_device *dev; | 357 | struct adu_device *dev; |
357 | int retval = 0; | 358 | int retval = 0; |
358 | 359 | ||
359 | dbg(2," %s : enter", __func__); | 360 | dbg(2, " %s : enter", __func__); |
360 | 361 | ||
361 | if (file == NULL) { | 362 | if (file == NULL) { |
362 | dbg(1," %s : file is NULL", __func__); | 363 | dbg(1, " %s : file is NULL", __func__); |
363 | retval = -ENODEV; | 364 | retval = -ENODEV; |
364 | goto exit; | 365 | goto exit; |
365 | } | 366 | } |
366 | 367 | ||
367 | dev = file->private_data; | 368 | dev = file->private_data; |
368 | if (dev == NULL) { | 369 | if (dev == NULL) { |
369 | dbg(1," %s : object is NULL", __func__); | 370 | dbg(1, " %s : object is NULL", __func__); |
370 | retval = -ENODEV; | 371 | retval = -ENODEV; |
371 | goto exit; | 372 | goto exit; |
372 | } | 373 | } |
@@ -374,7 +375,7 @@ static int adu_release(struct inode *inode, struct file *file) | |||
374 | mutex_lock(&adutux_mutex); /* not interruptible */ | 375 | mutex_lock(&adutux_mutex); /* not interruptible */ |
375 | 376 | ||
376 | if (dev->open_count <= 0) { | 377 | if (dev->open_count <= 0) { |
377 | dbg(1," %s : device not opened", __func__); | 378 | dbg(1, " %s : device not opened", __func__); |
378 | retval = -ENODEV; | 379 | retval = -ENODEV; |
379 | goto unlock; | 380 | goto unlock; |
380 | } | 381 | } |
@@ -388,7 +389,7 @@ static int adu_release(struct inode *inode, struct file *file) | |||
388 | unlock: | 389 | unlock: |
389 | mutex_unlock(&adutux_mutex); | 390 | mutex_unlock(&adutux_mutex); |
390 | exit: | 391 | exit: |
391 | dbg(2," %s : leave, return value %d", __func__, retval); | 392 | dbg(2, " %s : leave, return value %d", __func__, retval); |
392 | return retval; | 393 | return retval; |
393 | } | 394 | } |
394 | 395 | ||
@@ -405,10 +406,10 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, | |||
405 | unsigned long flags; | 406 | unsigned long flags; |
406 | DECLARE_WAITQUEUE(wait, current); | 407 | DECLARE_WAITQUEUE(wait, current); |
407 | 408 | ||
408 | dbg(2," %s : enter, count = %Zd, file=%p", __func__, count, file); | 409 | dbg(2, " %s : enter, count = %Zd, file=%p", __func__, count, file); |
409 | 410 | ||
410 | dev = file->private_data; | 411 | dev = file->private_data; |
411 | dbg(2," %s : dev=%p", __func__, dev); | 412 | dbg(2, " %s : dev=%p", __func__, dev); |
412 | 413 | ||
413 | if (mutex_lock_interruptible(&dev->mtx)) | 414 | if (mutex_lock_interruptible(&dev->mtx)) |
414 | return -ERESTARTSYS; | 415 | return -ERESTARTSYS; |
@@ -423,15 +424,15 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, | |||
423 | 424 | ||
424 | /* verify that some data was requested */ | 425 | /* verify that some data was requested */ |
425 | if (count == 0) { | 426 | if (count == 0) { |
426 | dbg(1," %s : read request of 0 bytes", __func__); | 427 | dbg(1, " %s : read request of 0 bytes", __func__); |
427 | goto exit; | 428 | goto exit; |
428 | } | 429 | } |
429 | 430 | ||
430 | timeout = COMMAND_TIMEOUT; | 431 | timeout = COMMAND_TIMEOUT; |
431 | dbg(2," %s : about to start looping", __func__); | 432 | dbg(2, " %s : about to start looping", __func__); |
432 | while (bytes_to_read) { | 433 | while (bytes_to_read) { |
433 | int data_in_secondary = dev->secondary_tail - dev->secondary_head; | 434 | int data_in_secondary = dev->secondary_tail - dev->secondary_head; |
434 | dbg(2," %s : while, data_in_secondary=%d, status=%d", | 435 | dbg(2, " %s : while, data_in_secondary=%d, status=%d", |
435 | __func__, data_in_secondary, | 436 | __func__, data_in_secondary, |
436 | dev->interrupt_in_urb->status); | 437 | dev->interrupt_in_urb->status); |
437 | 438 | ||
@@ -456,7 +457,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, | |||
456 | if (dev->read_buffer_length) { | 457 | if (dev->read_buffer_length) { |
457 | /* we secure access to the primary */ | 458 | /* we secure access to the primary */ |
458 | char *tmp; | 459 | char *tmp; |
459 | dbg(2," %s : swap, read_buffer_length = %d", | 460 | dbg(2, " %s : swap, read_buffer_length = %d", |
460 | __func__, dev->read_buffer_length); | 461 | __func__, dev->read_buffer_length); |
461 | tmp = dev->read_buffer_secondary; | 462 | tmp = dev->read_buffer_secondary; |
462 | dev->read_buffer_secondary = dev->read_buffer_primary; | 463 | dev->read_buffer_secondary = dev->read_buffer_primary; |
@@ -472,16 +473,16 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, | |||
472 | if (!dev->read_urb_finished) { | 473 | if (!dev->read_urb_finished) { |
473 | /* somebody is doing IO */ | 474 | /* somebody is doing IO */ |
474 | spin_unlock_irqrestore(&dev->buflock, flags); | 475 | spin_unlock_irqrestore(&dev->buflock, flags); |
475 | dbg(2," %s : submitted already", __func__); | 476 | dbg(2, " %s : submitted already", __func__); |
476 | } else { | 477 | } else { |
477 | /* we must initiate input */ | 478 | /* we must initiate input */ |
478 | dbg(2," %s : initiate input", __func__); | 479 | dbg(2, " %s : initiate input", __func__); |
479 | dev->read_urb_finished = 0; | 480 | dev->read_urb_finished = 0; |
480 | spin_unlock_irqrestore(&dev->buflock, flags); | 481 | spin_unlock_irqrestore(&dev->buflock, flags); |
481 | 482 | ||
482 | usb_fill_int_urb(dev->interrupt_in_urb,dev->udev, | 483 | usb_fill_int_urb(dev->interrupt_in_urb, dev->udev, |
483 | usb_rcvintpipe(dev->udev, | 484 | usb_rcvintpipe(dev->udev, |
484 | dev->interrupt_in_endpoint->bEndpointAddress), | 485 | dev->interrupt_in_endpoint->bEndpointAddress), |
485 | dev->interrupt_in_buffer, | 486 | dev->interrupt_in_buffer, |
486 | usb_endpoint_maxp(dev->interrupt_in_endpoint), | 487 | usb_endpoint_maxp(dev->interrupt_in_endpoint), |
487 | adu_interrupt_in_callback, | 488 | adu_interrupt_in_callback, |
@@ -493,7 +494,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, | |||
493 | if (retval == -ENOMEM) { | 494 | if (retval == -ENOMEM) { |
494 | retval = bytes_read ? bytes_read : -ENOMEM; | 495 | retval = bytes_read ? bytes_read : -ENOMEM; |
495 | } | 496 | } |
496 | dbg(2," %s : submit failed", __func__); | 497 | dbg(2, " %s : submit failed", __func__); |
497 | goto exit; | 498 | goto exit; |
498 | } | 499 | } |
499 | } | 500 | } |
@@ -512,13 +513,13 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, | |||
512 | remove_wait_queue(&dev->read_wait, &wait); | 513 | remove_wait_queue(&dev->read_wait, &wait); |
513 | 514 | ||
514 | if (timeout <= 0) { | 515 | if (timeout <= 0) { |
515 | dbg(2," %s : timeout", __func__); | 516 | dbg(2, " %s : timeout", __func__); |
516 | retval = bytes_read ? bytes_read : -ETIMEDOUT; | 517 | retval = bytes_read ? bytes_read : -ETIMEDOUT; |
517 | goto exit; | 518 | goto exit; |
518 | } | 519 | } |
519 | 520 | ||
520 | if (signal_pending(current)) { | 521 | if (signal_pending(current)) { |
521 | dbg(2," %s : signal pending", __func__); | 522 | dbg(2, " %s : signal pending", __func__); |
522 | retval = bytes_read ? bytes_read : -EINTR; | 523 | retval = bytes_read ? bytes_read : -EINTR; |
523 | goto exit; | 524 | goto exit; |
524 | } | 525 | } |
@@ -532,9 +533,9 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, | |||
532 | if (should_submit && dev->read_urb_finished) { | 533 | if (should_submit && dev->read_urb_finished) { |
533 | dev->read_urb_finished = 0; | 534 | dev->read_urb_finished = 0; |
534 | spin_unlock_irqrestore(&dev->buflock, flags); | 535 | spin_unlock_irqrestore(&dev->buflock, flags); |
535 | usb_fill_int_urb(dev->interrupt_in_urb,dev->udev, | 536 | usb_fill_int_urb(dev->interrupt_in_urb, dev->udev, |
536 | usb_rcvintpipe(dev->udev, | 537 | usb_rcvintpipe(dev->udev, |
537 | dev->interrupt_in_endpoint->bEndpointAddress), | 538 | dev->interrupt_in_endpoint->bEndpointAddress), |
538 | dev->interrupt_in_buffer, | 539 | dev->interrupt_in_buffer, |
539 | usb_endpoint_maxp(dev->interrupt_in_endpoint), | 540 | usb_endpoint_maxp(dev->interrupt_in_endpoint), |
540 | adu_interrupt_in_callback, | 541 | adu_interrupt_in_callback, |
@@ -551,7 +552,7 @@ exit: | |||
551 | /* unlock the device */ | 552 | /* unlock the device */ |
552 | mutex_unlock(&dev->mtx); | 553 | mutex_unlock(&dev->mtx); |
553 | 554 | ||
554 | dbg(2," %s : leave, return value %d", __func__, retval); | 555 | dbg(2, " %s : leave, return value %d", __func__, retval); |
555 | return retval; | 556 | return retval; |
556 | } | 557 | } |
557 | 558 | ||
@@ -566,7 +567,7 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, | |||
566 | unsigned long flags; | 567 | unsigned long flags; |
567 | int retval; | 568 | int retval; |
568 | 569 | ||
569 | dbg(2," %s : enter, count = %Zd", __func__, count); | 570 | dbg(2, " %s : enter, count = %Zd", __func__, count); |
570 | 571 | ||
571 | dev = file->private_data; | 572 | dev = file->private_data; |
572 | 573 | ||
@@ -584,7 +585,7 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, | |||
584 | 585 | ||
585 | /* verify that we actually have some data to write */ | 586 | /* verify that we actually have some data to write */ |
586 | if (count == 0) { | 587 | if (count == 0) { |
587 | dbg(1," %s : write request of 0 bytes", __func__); | 588 | dbg(1, " %s : write request of 0 bytes", __func__); |
588 | goto exit; | 589 | goto exit; |
589 | } | 590 | } |
590 | 591 | ||
@@ -597,7 +598,7 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, | |||
597 | 598 | ||
598 | mutex_unlock(&dev->mtx); | 599 | mutex_unlock(&dev->mtx); |
599 | if (signal_pending(current)) { | 600 | if (signal_pending(current)) { |
600 | dbg(1," %s : interrupted", __func__); | 601 | dbg(1, " %s : interrupted", __func__); |
601 | set_current_state(TASK_RUNNING); | 602 | set_current_state(TASK_RUNNING); |
602 | retval = -EINTR; | 603 | retval = -EINTR; |
603 | goto exit_onqueue; | 604 | goto exit_onqueue; |
@@ -614,17 +615,17 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, | |||
614 | goto exit_nolock; | 615 | goto exit_nolock; |
615 | } | 616 | } |
616 | 617 | ||
617 | dbg(4," %s : in progress, count = %Zd", __func__, count); | 618 | dbg(4, " %s : in progress, count = %Zd", __func__, count); |
618 | } else { | 619 | } else { |
619 | spin_unlock_irqrestore(&dev->buflock, flags); | 620 | spin_unlock_irqrestore(&dev->buflock, flags); |
620 | set_current_state(TASK_RUNNING); | 621 | set_current_state(TASK_RUNNING); |
621 | remove_wait_queue(&dev->write_wait, &waita); | 622 | remove_wait_queue(&dev->write_wait, &waita); |
622 | dbg(4," %s : sending, count = %Zd", __func__, count); | 623 | dbg(4, " %s : sending, count = %Zd", __func__, count); |
623 | 624 | ||
624 | /* write the data into interrupt_out_buffer from userspace */ | 625 | /* write the data into interrupt_out_buffer from userspace */ |
625 | buffer_size = usb_endpoint_maxp(dev->interrupt_out_endpoint); | 626 | buffer_size = usb_endpoint_maxp(dev->interrupt_out_endpoint); |
626 | bytes_to_write = count > buffer_size ? buffer_size : count; | 627 | bytes_to_write = count > buffer_size ? buffer_size : count; |
627 | dbg(4," %s : buffer_size = %Zd, count = %Zd, bytes_to_write = %Zd", | 628 | dbg(4, " %s : buffer_size = %Zd, count = %Zd, bytes_to_write = %Zd", |
628 | __func__, buffer_size, count, bytes_to_write); | 629 | __func__, buffer_size, count, bytes_to_write); |
629 | 630 | ||
630 | if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write) != 0) { | 631 | if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write) != 0) { |
@@ -664,7 +665,7 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, | |||
664 | exit: | 665 | exit: |
665 | mutex_unlock(&dev->mtx); | 666 | mutex_unlock(&dev->mtx); |
666 | exit_nolock: | 667 | exit_nolock: |
667 | dbg(2," %s : leave, return value %d", __func__, retval); | 668 | dbg(2, " %s : leave, return value %d", __func__, retval); |
668 | return retval; | 669 | return retval; |
669 | 670 | ||
670 | exit_onqueue: | 671 | exit_onqueue: |
@@ -710,7 +711,7 @@ static int adu_probe(struct usb_interface *interface, | |||
710 | int out_end_size; | 711 | int out_end_size; |
711 | int i; | 712 | int i; |
712 | 713 | ||
713 | dbg(2," %s : enter", __func__); | 714 | dbg(2, " %s : enter", __func__); |
714 | 715 | ||
715 | if (udev == NULL) { | 716 | if (udev == NULL) { |
716 | dev_err(&interface->dev, "udev is NULL.\n"); | 717 | dev_err(&interface->dev, "udev is NULL.\n"); |
@@ -811,7 +812,7 @@ static int adu_probe(struct usb_interface *interface, | |||
811 | dev_err(&interface->dev, "Could not retrieve serial number\n"); | 812 | dev_err(&interface->dev, "Could not retrieve serial number\n"); |
812 | goto error; | 813 | goto error; |
813 | } | 814 | } |
814 | dbg(2," %s : serial_number=%s", __func__, dev->serial_number); | 815 | dbg(2, " %s : serial_number=%s", __func__, dev->serial_number); |
815 | 816 | ||
816 | /* we can register the device now, as it is ready */ | 817 | /* we can register the device now, as it is ready */ |
817 | usb_set_intfdata(interface, dev); | 818 | usb_set_intfdata(interface, dev); |
@@ -832,7 +833,7 @@ static int adu_probe(struct usb_interface *interface, | |||
832 | udev->descriptor.idProduct, dev->serial_number, | 833 | udev->descriptor.idProduct, dev->serial_number, |
833 | (dev->minor - ADU_MINOR_BASE)); | 834 | (dev->minor - ADU_MINOR_BASE)); |
834 | exit: | 835 | exit: |
835 | dbg(2," %s : leave, return value %p (dev)", __func__, dev); | 836 | dbg(2, " %s : leave, return value %p (dev)", __func__, dev); |
836 | 837 | ||
837 | return retval; | 838 | return retval; |
838 | 839 | ||
@@ -851,7 +852,7 @@ static void adu_disconnect(struct usb_interface *interface) | |||
851 | struct adu_device *dev; | 852 | struct adu_device *dev; |
852 | int minor; | 853 | int minor; |
853 | 854 | ||
854 | dbg(2," %s : enter", __func__); | 855 | dbg(2, " %s : enter", __func__); |
855 | 856 | ||
856 | dev = usb_get_intfdata(interface); | 857 | dev = usb_get_intfdata(interface); |
857 | 858 | ||
@@ -865,7 +866,7 @@ static void adu_disconnect(struct usb_interface *interface) | |||
865 | usb_set_intfdata(interface, NULL); | 866 | usb_set_intfdata(interface, NULL); |
866 | 867 | ||
867 | /* if the device is not opened, then we clean up right now */ | 868 | /* if the device is not opened, then we clean up right now */ |
868 | dbg(2," %s : open count %d", __func__, dev->open_count); | 869 | dbg(2, " %s : open count %d", __func__, dev->open_count); |
869 | if (!dev->open_count) | 870 | if (!dev->open_count) |
870 | adu_delete(dev); | 871 | adu_delete(dev); |
871 | 872 | ||
@@ -874,7 +875,7 @@ static void adu_disconnect(struct usb_interface *interface) | |||
874 | dev_info(&interface->dev, "ADU device adutux%d now disconnected\n", | 875 | dev_info(&interface->dev, "ADU device adutux%d now disconnected\n", |
875 | (minor - ADU_MINOR_BASE)); | 876 | (minor - ADU_MINOR_BASE)); |
876 | 877 | ||
877 | dbg(2," %s : leave", __func__); | 878 | dbg(2, " %s : leave", __func__); |
878 | } | 879 | } |
879 | 880 | ||
880 | /* usb specific object needed to register this driver with the usb subsystem */ | 881 | /* usb specific object needed to register this driver with the usb subsystem */ |
diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c index d3a1cce1bf9c..c3578393ddef 100644 --- a/drivers/usb/misc/usb3503.c +++ b/drivers/usb/misc/usb3503.c | |||
@@ -42,9 +42,6 @@ | |||
42 | #define USB3503_NRD 0x09 | 42 | #define USB3503_NRD 0x09 |
43 | 43 | ||
44 | #define USB3503_PDS 0x0a | 44 | #define USB3503_PDS 0x0a |
45 | #define USB3503_PORT1 (1 << 1) | ||
46 | #define USB3503_PORT2 (1 << 2) | ||
47 | #define USB3503_PORT3 (1 << 3) | ||
48 | 45 | ||
49 | #define USB3503_SP_ILOCK 0xe7 | 46 | #define USB3503_SP_ILOCK 0xe7 |
50 | #define USB3503_SPILOCK_CONNECT (1 << 1) | 47 | #define USB3503_SPILOCK_CONNECT (1 << 1) |
@@ -56,6 +53,7 @@ | |||
56 | struct usb3503 { | 53 | struct usb3503 { |
57 | enum usb3503_mode mode; | 54 | enum usb3503_mode mode; |
58 | struct i2c_client *client; | 55 | struct i2c_client *client; |
56 | u8 port_off_mask; | ||
59 | int gpio_intn; | 57 | int gpio_intn; |
60 | int gpio_reset; | 58 | int gpio_reset; |
61 | int gpio_connect; | 59 | int gpio_connect; |
@@ -107,11 +105,9 @@ static int usb3503_reset(int gpio_reset, int state) | |||
107 | if (gpio_is_valid(gpio_reset)) | 105 | if (gpio_is_valid(gpio_reset)) |
108 | gpio_set_value(gpio_reset, state); | 106 | gpio_set_value(gpio_reset, state); |
109 | 107 | ||
110 | /* Wait RefClk when RESET_N is released, otherwise Hub will | 108 | /* Wait T_HUBINIT == 4ms for hub logic to stabilize */ |
111 | * not transition to Hub Communication Stage. | ||
112 | */ | ||
113 | if (state) | 109 | if (state) |
114 | msleep(100); | 110 | usleep_range(4000, 10000); |
115 | 111 | ||
116 | return 0; | 112 | return 0; |
117 | } | 113 | } |
@@ -134,12 +130,14 @@ static int usb3503_switch_mode(struct usb3503 *hub, enum usb3503_mode mode) | |||
134 | goto err_hubmode; | 130 | goto err_hubmode; |
135 | } | 131 | } |
136 | 132 | ||
137 | /* PDS : Port2,3 Disable For Self Powered Operation */ | 133 | /* PDS : Disable For Self Powered Operation */ |
138 | err = usb3503_set_bits(i2c, USB3503_PDS, | 134 | if (hub->port_off_mask) { |
139 | (USB3503_PORT2 | USB3503_PORT3)); | 135 | err = usb3503_set_bits(i2c, USB3503_PDS, |
140 | if (err < 0) { | 136 | hub->port_off_mask); |
141 | dev_err(&i2c->dev, "PDS failed (%d)\n", err); | 137 | if (err < 0) { |
142 | goto err_hubmode; | 138 | dev_err(&i2c->dev, "PDS failed (%d)\n", err); |
139 | goto err_hubmode; | ||
140 | } | ||
143 | } | 141 | } |
144 | 142 | ||
145 | /* CFG1 : SELF_BUS_PWR -> Self-Powerd operation */ | 143 | /* CFG1 : SELF_BUS_PWR -> Self-Powerd operation */ |
@@ -186,6 +184,8 @@ static int usb3503_probe(struct i2c_client *i2c, const struct i2c_device_id *id) | |||
186 | struct usb3503 *hub; | 184 | struct usb3503 *hub; |
187 | int err = -ENOMEM; | 185 | int err = -ENOMEM; |
188 | u32 mode = USB3503_MODE_UNKNOWN; | 186 | u32 mode = USB3503_MODE_UNKNOWN; |
187 | const u32 *property; | ||
188 | int len; | ||
189 | 189 | ||
190 | hub = kzalloc(sizeof(struct usb3503), GFP_KERNEL); | 190 | hub = kzalloc(sizeof(struct usb3503), GFP_KERNEL); |
191 | if (!hub) { | 191 | if (!hub) { |
@@ -197,18 +197,31 @@ static int usb3503_probe(struct i2c_client *i2c, const struct i2c_device_id *id) | |||
197 | hub->client = i2c; | 197 | hub->client = i2c; |
198 | 198 | ||
199 | if (pdata) { | 199 | if (pdata) { |
200 | hub->port_off_mask = pdata->port_off_mask; | ||
200 | hub->gpio_intn = pdata->gpio_intn; | 201 | hub->gpio_intn = pdata->gpio_intn; |
201 | hub->gpio_connect = pdata->gpio_connect; | 202 | hub->gpio_connect = pdata->gpio_connect; |
202 | hub->gpio_reset = pdata->gpio_reset; | 203 | hub->gpio_reset = pdata->gpio_reset; |
203 | hub->mode = pdata->initial_mode; | 204 | hub->mode = pdata->initial_mode; |
204 | } else if (np) { | 205 | } else if (np) { |
206 | hub->port_off_mask = 0; | ||
207 | |||
208 | property = of_get_property(np, "disabled-ports", &len); | ||
209 | if (property && (len / sizeof(u32)) > 0) { | ||
210 | int i; | ||
211 | for (i = 0; i < len / sizeof(u32); i++) { | ||
212 | u32 port = be32_to_cpu(property[i]); | ||
213 | if ((1 <= port) && (port <= 3)) | ||
214 | hub->port_off_mask |= (1 << port); | ||
215 | } | ||
216 | } | ||
217 | |||
205 | hub->gpio_intn = of_get_named_gpio(np, "connect-gpios", 0); | 218 | hub->gpio_intn = of_get_named_gpio(np, "connect-gpios", 0); |
206 | if (hub->gpio_intn == -EPROBE_DEFER) | 219 | if (hub->gpio_intn == -EPROBE_DEFER) |
207 | return -EPROBE_DEFER; | 220 | return -EPROBE_DEFER; |
208 | hub->gpio_connect = of_get_named_gpio(np, "intn-gpios", 0); | 221 | hub->gpio_connect = of_get_named_gpio(np, "intn-gpios", 0); |
209 | if (hub->gpio_connect == -EPROBE_DEFER) | 222 | if (hub->gpio_connect == -EPROBE_DEFER) |
210 | return -EPROBE_DEFER; | 223 | return -EPROBE_DEFER; |
211 | hub->gpio_reset = of_get_named_gpio(np, "reset-gpios", 0); | 224 | hub->gpio_reset = of_get_named_gpio(np, "reset-gpios", 0); |
212 | if (hub->gpio_reset == -EPROBE_DEFER) | 225 | if (hub->gpio_reset == -EPROBE_DEFER) |
213 | return -EPROBE_DEFER; | 226 | return -EPROBE_DEFER; |
214 | of_property_read_u32(np, "initial-mode", &mode); | 227 | of_property_read_u32(np, "initial-mode", &mode); |
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 06f8d29af1ef..797e3fd45510 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig | |||
@@ -28,6 +28,35 @@ config USB_MUSB_HDRC | |||
28 | if USB_MUSB_HDRC | 28 | if USB_MUSB_HDRC |
29 | 29 | ||
30 | choice | 30 | choice |
31 | bool "MUSB Mode Selection" | ||
32 | default USB_MUSB_DUAL_ROLE if (USB && USB_GADGET) | ||
33 | default USB_MUSB_HOST if (USB && !USB_GADGET) | ||
34 | default USB_MUSB_GADGET if (!USB && USB_GADGET) | ||
35 | |||
36 | config USB_MUSB_HOST | ||
37 | bool "Host only mode" | ||
38 | depends on USB | ||
39 | help | ||
40 | Select this when you want to use MUSB in host mode only, | ||
41 | thereby the gadget feature will be regressed. | ||
42 | |||
43 | config USB_MUSB_GADGET | ||
44 | bool "Gadget only mode" | ||
45 | depends on USB_GADGET | ||
46 | help | ||
47 | Select this when you want to use MUSB in gadget mode only, | ||
48 | thereby the host feature will be regressed. | ||
49 | |||
50 | config USB_MUSB_DUAL_ROLE | ||
51 | bool "Dual Role mode" | ||
52 | depends on (USB && USB_GADGET) | ||
53 | help | ||
54 | This is the default mode of working of MUSB controller where | ||
55 | both host and gadget features are enabled. | ||
56 | |||
57 | endchoice | ||
58 | |||
59 | choice | ||
31 | prompt "Platform Glue Layer" | 60 | prompt "Platform Glue Layer" |
32 | 61 | ||
33 | config USB_MUSB_DAVINCI | 62 | config USB_MUSB_DAVINCI |
diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile index 3b858715b5ea..2b82ed7c85ca 100644 --- a/drivers/usb/musb/Makefile +++ b/drivers/usb/musb/Makefile | |||
@@ -6,8 +6,8 @@ obj-$(CONFIG_USB_MUSB_HDRC) += musb_hdrc.o | |||
6 | 6 | ||
7 | musb_hdrc-y := musb_core.o | 7 | musb_hdrc-y := musb_core.o |
8 | 8 | ||
9 | musb_hdrc-y += musb_gadget_ep0.o musb_gadget.o | 9 | musb_hdrc-$(CONFIG_USB_MUSB_HOST)$(CONFIG_USB_MUSB_DUAL_ROLE) += musb_virthub.o musb_host.o |
10 | musb_hdrc-y += musb_virthub.o musb_host.o | 10 | musb_hdrc-$(CONFIG_USB_MUSB_GADGET)$(CONFIG_USB_MUSB_DUAL_ROLE) += musb_gadget_ep0.o musb_gadget.o |
11 | musb_hdrc-$(CONFIG_DEBUG_FS) += musb_debugfs.o | 11 | musb_hdrc-$(CONFIG_DEBUG_FS) += musb_debugfs.o |
12 | 12 | ||
13 | # Hardware Glue Layer | 13 | # Hardware Glue Layer |
diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c index 5e63b160db0c..6ba8439bd5a6 100644 --- a/drivers/usb/musb/blackfin.c +++ b/drivers/usb/musb/blackfin.c | |||
@@ -450,6 +450,7 @@ static u64 bfin_dmamask = DMA_BIT_MASK(32); | |||
450 | 450 | ||
451 | static int bfin_probe(struct platform_device *pdev) | 451 | static int bfin_probe(struct platform_device *pdev) |
452 | { | 452 | { |
453 | struct resource musb_resources[2]; | ||
453 | struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; | 454 | struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; |
454 | struct platform_device *musb; | 455 | struct platform_device *musb; |
455 | struct bfin_glue *glue; | 456 | struct bfin_glue *glue; |
@@ -479,8 +480,21 @@ static int bfin_probe(struct platform_device *pdev) | |||
479 | 480 | ||
480 | platform_set_drvdata(pdev, glue); | 481 | platform_set_drvdata(pdev, glue); |
481 | 482 | ||
482 | ret = platform_device_add_resources(musb, pdev->resource, | 483 | memset(musb_resources, 0x00, sizeof(*musb_resources) * |
483 | pdev->num_resources); | 484 | ARRAY_SIZE(musb_resources)); |
485 | |||
486 | musb_resources[0].name = pdev->resource[0].name; | ||
487 | musb_resources[0].start = pdev->resource[0].start; | ||
488 | musb_resources[0].end = pdev->resource[0].end; | ||
489 | musb_resources[0].flags = pdev->resource[0].flags; | ||
490 | |||
491 | musb_resources[1].name = pdev->resource[1].name; | ||
492 | musb_resources[1].start = pdev->resource[1].start; | ||
493 | musb_resources[1].end = pdev->resource[1].end; | ||
494 | musb_resources[1].flags = pdev->resource[1].flags; | ||
495 | |||
496 | ret = platform_device_add_resources(musb, musb_resources, | ||
497 | ARRAY_SIZE(musb_resources)); | ||
484 | if (ret) { | 498 | if (ret) { |
485 | dev_err(&pdev->dev, "failed to add resources\n"); | 499 | dev_err(&pdev->dev, "failed to add resources\n"); |
486 | goto err3; | 500 | goto err3; |
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c index b903b744a224..0da6f648a9fe 100644 --- a/drivers/usb/musb/da8xx.c +++ b/drivers/usb/musb/da8xx.c | |||
@@ -476,6 +476,7 @@ static u64 da8xx_dmamask = DMA_BIT_MASK(32); | |||
476 | 476 | ||
477 | static int da8xx_probe(struct platform_device *pdev) | 477 | static int da8xx_probe(struct platform_device *pdev) |
478 | { | 478 | { |
479 | struct resource musb_resources[2]; | ||
479 | struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; | 480 | struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; |
480 | struct platform_device *musb; | 481 | struct platform_device *musb; |
481 | struct da8xx_glue *glue; | 482 | struct da8xx_glue *glue; |
@@ -521,8 +522,21 @@ static int da8xx_probe(struct platform_device *pdev) | |||
521 | 522 | ||
522 | platform_set_drvdata(pdev, glue); | 523 | platform_set_drvdata(pdev, glue); |
523 | 524 | ||
524 | ret = platform_device_add_resources(musb, pdev->resource, | 525 | memset(musb_resources, 0x00, sizeof(*musb_resources) * |
525 | pdev->num_resources); | 526 | ARRAY_SIZE(musb_resources)); |
527 | |||
528 | musb_resources[0].name = pdev->resource[0].name; | ||
529 | musb_resources[0].start = pdev->resource[0].start; | ||
530 | musb_resources[0].end = pdev->resource[0].end; | ||
531 | musb_resources[0].flags = pdev->resource[0].flags; | ||
532 | |||
533 | musb_resources[1].name = pdev->resource[1].name; | ||
534 | musb_resources[1].start = pdev->resource[1].start; | ||
535 | musb_resources[1].end = pdev->resource[1].end; | ||
536 | musb_resources[1].flags = pdev->resource[1].flags; | ||
537 | |||
538 | ret = platform_device_add_resources(musb, musb_resources, | ||
539 | ARRAY_SIZE(musb_resources)); | ||
526 | if (ret) { | 540 | if (ret) { |
527 | dev_err(&pdev->dev, "failed to add resources\n"); | 541 | dev_err(&pdev->dev, "failed to add resources\n"); |
528 | goto err5; | 542 | goto err5; |
diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index bea6cc35471c..f8aeaf2e2cd1 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c | |||
@@ -509,6 +509,7 @@ static u64 davinci_dmamask = DMA_BIT_MASK(32); | |||
509 | 509 | ||
510 | static int davinci_probe(struct platform_device *pdev) | 510 | static int davinci_probe(struct platform_device *pdev) |
511 | { | 511 | { |
512 | struct resource musb_resources[2]; | ||
512 | struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; | 513 | struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; |
513 | struct platform_device *musb; | 514 | struct platform_device *musb; |
514 | struct davinci_glue *glue; | 515 | struct davinci_glue *glue; |
@@ -553,8 +554,21 @@ static int davinci_probe(struct platform_device *pdev) | |||
553 | 554 | ||
554 | platform_set_drvdata(pdev, glue); | 555 | platform_set_drvdata(pdev, glue); |
555 | 556 | ||
556 | ret = platform_device_add_resources(musb, pdev->resource, | 557 | memset(musb_resources, 0x00, sizeof(*musb_resources) * |
557 | pdev->num_resources); | 558 | ARRAY_SIZE(musb_resources)); |
559 | |||
560 | musb_resources[0].name = pdev->resource[0].name; | ||
561 | musb_resources[0].start = pdev->resource[0].start; | ||
562 | musb_resources[0].end = pdev->resource[0].end; | ||
563 | musb_resources[0].flags = pdev->resource[0].flags; | ||
564 | |||
565 | musb_resources[1].name = pdev->resource[1].name; | ||
566 | musb_resources[1].start = pdev->resource[1].start; | ||
567 | musb_resources[1].end = pdev->resource[1].end; | ||
568 | musb_resources[1].flags = pdev->resource[1].flags; | ||
569 | |||
570 | ret = platform_device_add_resources(musb, musb_resources, | ||
571 | ARRAY_SIZE(musb_resources)); | ||
558 | if (ret) { | 572 | if (ret) { |
559 | dev_err(&pdev->dev, "failed to add resources\n"); | 573 | dev_err(&pdev->dev, "failed to add resources\n"); |
560 | goto err5; | 574 | goto err5; |
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 37a261a6bb6a..29a24ced6748 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c | |||
@@ -380,7 +380,6 @@ static void musb_otg_timer_func(unsigned long data) | |||
380 | dev_dbg(musb->controller, "HNP: Unhandled mode %s\n", | 380 | dev_dbg(musb->controller, "HNP: Unhandled mode %s\n", |
381 | usb_otg_state_string(musb->xceiv->state)); | 381 | usb_otg_state_string(musb->xceiv->state)); |
382 | } | 382 | } |
383 | musb->ignore_disconnect = 0; | ||
384 | spin_unlock_irqrestore(&musb->lock, flags); | 383 | spin_unlock_irqrestore(&musb->lock, flags); |
385 | } | 384 | } |
386 | 385 | ||
@@ -389,7 +388,7 @@ static void musb_otg_timer_func(unsigned long data) | |||
389 | */ | 388 | */ |
390 | void musb_hnp_stop(struct musb *musb) | 389 | void musb_hnp_stop(struct musb *musb) |
391 | { | 390 | { |
392 | struct usb_hcd *hcd = musb_to_hcd(musb); | 391 | struct usb_hcd *hcd = musb->hcd; |
393 | void __iomem *mbase = musb->mregs; | 392 | void __iomem *mbase = musb->mregs; |
394 | u8 reg; | 393 | u8 reg; |
395 | 394 | ||
@@ -404,7 +403,8 @@ void musb_hnp_stop(struct musb *musb) | |||
404 | break; | 403 | break; |
405 | case OTG_STATE_B_HOST: | 404 | case OTG_STATE_B_HOST: |
406 | dev_dbg(musb->controller, "HNP: Disabling HR\n"); | 405 | dev_dbg(musb->controller, "HNP: Disabling HR\n"); |
407 | hcd->self.is_b_host = 0; | 406 | if (hcd) |
407 | hcd->self.is_b_host = 0; | ||
408 | musb->xceiv->state = OTG_STATE_B_PERIPHERAL; | 408 | musb->xceiv->state = OTG_STATE_B_PERIPHERAL; |
409 | MUSB_DEV_MODE(musb); | 409 | MUSB_DEV_MODE(musb); |
410 | reg = musb_readb(mbase, MUSB_POWER); | 410 | reg = musb_readb(mbase, MUSB_POWER); |
@@ -484,7 +484,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, | |||
484 | 484 | ||
485 | musb->xceiv->state = OTG_STATE_A_HOST; | 485 | musb->xceiv->state = OTG_STATE_A_HOST; |
486 | musb->is_active = 1; | 486 | musb->is_active = 1; |
487 | usb_hcd_resume_root_hub(musb_to_hcd(musb)); | 487 | musb_host_resume_root_hub(musb); |
488 | break; | 488 | break; |
489 | case OTG_STATE_B_WAIT_ACON: | 489 | case OTG_STATE_B_WAIT_ACON: |
490 | musb->xceiv->state = OTG_STATE_B_PERIPHERAL; | 490 | musb->xceiv->state = OTG_STATE_B_PERIPHERAL; |
@@ -501,7 +501,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, | |||
501 | case OTG_STATE_A_SUSPEND: | 501 | case OTG_STATE_A_SUSPEND: |
502 | /* possibly DISCONNECT is upcoming */ | 502 | /* possibly DISCONNECT is upcoming */ |
503 | musb->xceiv->state = OTG_STATE_A_HOST; | 503 | musb->xceiv->state = OTG_STATE_A_HOST; |
504 | usb_hcd_resume_root_hub(musb_to_hcd(musb)); | 504 | musb_host_resume_root_hub(musb); |
505 | break; | 505 | break; |
506 | case OTG_STATE_B_WAIT_ACON: | 506 | case OTG_STATE_B_WAIT_ACON: |
507 | case OTG_STATE_B_PERIPHERAL: | 507 | case OTG_STATE_B_PERIPHERAL: |
@@ -643,7 +643,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, | |||
643 | * undesired detour through A_WAIT_BCON. | 643 | * undesired detour through A_WAIT_BCON. |
644 | */ | 644 | */ |
645 | musb_hnp_stop(musb); | 645 | musb_hnp_stop(musb); |
646 | usb_hcd_resume_root_hub(musb_to_hcd(musb)); | 646 | musb_host_resume_root_hub(musb); |
647 | musb_root_disconnect(musb); | 647 | musb_root_disconnect(musb); |
648 | musb_platform_try_idle(musb, jiffies | 648 | musb_platform_try_idle(musb, jiffies |
649 | + msecs_to_jiffies(musb->a_wait_bcon | 649 | + msecs_to_jiffies(musb->a_wait_bcon |
@@ -685,7 +685,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, | |||
685 | } | 685 | } |
686 | 686 | ||
687 | if (int_usb & MUSB_INTR_CONNECT) { | 687 | if (int_usb & MUSB_INTR_CONNECT) { |
688 | struct usb_hcd *hcd = musb_to_hcd(musb); | 688 | struct usb_hcd *hcd = musb->hcd; |
689 | 689 | ||
690 | handled = IRQ_HANDLED; | 690 | handled = IRQ_HANDLED; |
691 | musb->is_active = 1; | 691 | musb->is_active = 1; |
@@ -726,31 +726,27 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, | |||
726 | dev_dbg(musb->controller, "HNP: CONNECT, now b_host\n"); | 726 | dev_dbg(musb->controller, "HNP: CONNECT, now b_host\n"); |
727 | b_host: | 727 | b_host: |
728 | musb->xceiv->state = OTG_STATE_B_HOST; | 728 | musb->xceiv->state = OTG_STATE_B_HOST; |
729 | hcd->self.is_b_host = 1; | 729 | if (musb->hcd) |
730 | musb->ignore_disconnect = 0; | 730 | musb->hcd->self.is_b_host = 1; |
731 | del_timer(&musb->otg_timer); | 731 | del_timer(&musb->otg_timer); |
732 | break; | 732 | break; |
733 | default: | 733 | default: |
734 | if ((devctl & MUSB_DEVCTL_VBUS) | 734 | if ((devctl & MUSB_DEVCTL_VBUS) |
735 | == (3 << MUSB_DEVCTL_VBUS_SHIFT)) { | 735 | == (3 << MUSB_DEVCTL_VBUS_SHIFT)) { |
736 | musb->xceiv->state = OTG_STATE_A_HOST; | 736 | musb->xceiv->state = OTG_STATE_A_HOST; |
737 | hcd->self.is_b_host = 0; | 737 | if (hcd) |
738 | hcd->self.is_b_host = 0; | ||
738 | } | 739 | } |
739 | break; | 740 | break; |
740 | } | 741 | } |
741 | 742 | ||
742 | /* poke the root hub */ | 743 | musb_host_poke_root_hub(musb); |
743 | MUSB_HST_MODE(musb); | ||
744 | if (hcd->status_urb) | ||
745 | usb_hcd_poll_rh_status(hcd); | ||
746 | else | ||
747 | usb_hcd_resume_root_hub(hcd); | ||
748 | 744 | ||
749 | dev_dbg(musb->controller, "CONNECT (%s) devctl %02x\n", | 745 | dev_dbg(musb->controller, "CONNECT (%s) devctl %02x\n", |
750 | usb_otg_state_string(musb->xceiv->state), devctl); | 746 | usb_otg_state_string(musb->xceiv->state), devctl); |
751 | } | 747 | } |
752 | 748 | ||
753 | if ((int_usb & MUSB_INTR_DISCONNECT) && !musb->ignore_disconnect) { | 749 | if (int_usb & MUSB_INTR_DISCONNECT) { |
754 | dev_dbg(musb->controller, "DISCONNECT (%s) as %s, devctl %02x\n", | 750 | dev_dbg(musb->controller, "DISCONNECT (%s) as %s, devctl %02x\n", |
755 | usb_otg_state_string(musb->xceiv->state), | 751 | usb_otg_state_string(musb->xceiv->state), |
756 | MUSB_MODE(musb), devctl); | 752 | MUSB_MODE(musb), devctl); |
@@ -759,7 +755,7 @@ b_host: | |||
759 | switch (musb->xceiv->state) { | 755 | switch (musb->xceiv->state) { |
760 | case OTG_STATE_A_HOST: | 756 | case OTG_STATE_A_HOST: |
761 | case OTG_STATE_A_SUSPEND: | 757 | case OTG_STATE_A_SUSPEND: |
762 | usb_hcd_resume_root_hub(musb_to_hcd(musb)); | 758 | musb_host_resume_root_hub(musb); |
763 | musb_root_disconnect(musb); | 759 | musb_root_disconnect(musb); |
764 | if (musb->a_wait_bcon != 0) | 760 | if (musb->a_wait_bcon != 0) |
765 | musb_platform_try_idle(musb, jiffies | 761 | musb_platform_try_idle(musb, jiffies |
@@ -772,7 +768,8 @@ b_host: | |||
772 | * in hnp_stop() is currently not used... | 768 | * in hnp_stop() is currently not used... |
773 | */ | 769 | */ |
774 | musb_root_disconnect(musb); | 770 | musb_root_disconnect(musb); |
775 | musb_to_hcd(musb)->self.is_b_host = 0; | 771 | if (musb->hcd) |
772 | musb->hcd->self.is_b_host = 0; | ||
776 | musb->xceiv->state = OTG_STATE_B_PERIPHERAL; | 773 | musb->xceiv->state = OTG_STATE_B_PERIPHERAL; |
777 | MUSB_DEV_MODE(musb); | 774 | MUSB_DEV_MODE(musb); |
778 | musb_g_disconnect(musb); | 775 | musb_g_disconnect(musb); |
@@ -818,11 +815,6 @@ b_host: | |||
818 | usb_otg_state_string(musb->xceiv->state)); | 815 | usb_otg_state_string(musb->xceiv->state)); |
819 | switch (musb->xceiv->state) { | 816 | switch (musb->xceiv->state) { |
820 | case OTG_STATE_A_SUSPEND: | 817 | case OTG_STATE_A_SUSPEND: |
821 | /* We need to ignore disconnect on suspend | ||
822 | * otherwise tusb 2.0 won't reconnect after a | ||
823 | * power cycle, which breaks otg compliance. | ||
824 | */ | ||
825 | musb->ignore_disconnect = 1; | ||
826 | musb_g_reset(musb); | 818 | musb_g_reset(musb); |
827 | /* FALLTHROUGH */ | 819 | /* FALLTHROUGH */ |
828 | case OTG_STATE_A_WAIT_BCON: /* OPT TD.4.7-900ms */ | 820 | case OTG_STATE_A_WAIT_BCON: /* OPT TD.4.7-900ms */ |
@@ -834,7 +826,6 @@ b_host: | |||
834 | + msecs_to_jiffies(TA_WAIT_BCON(musb))); | 826 | + msecs_to_jiffies(TA_WAIT_BCON(musb))); |
835 | break; | 827 | break; |
836 | case OTG_STATE_A_PERIPHERAL: | 828 | case OTG_STATE_A_PERIPHERAL: |
837 | musb->ignore_disconnect = 0; | ||
838 | del_timer(&musb->otg_timer); | 829 | del_timer(&musb->otg_timer); |
839 | musb_g_reset(musb); | 830 | musb_g_reset(musb); |
840 | break; | 831 | break; |
@@ -909,51 +900,6 @@ b_host: | |||
909 | 900 | ||
910 | /*-------------------------------------------------------------------------*/ | 901 | /*-------------------------------------------------------------------------*/ |
911 | 902 | ||
912 | /* | ||
913 | * Program the HDRC to start (enable interrupts, dma, etc.). | ||
914 | */ | ||
915 | void musb_start(struct musb *musb) | ||
916 | { | ||
917 | void __iomem *regs = musb->mregs; | ||
918 | u8 devctl = musb_readb(regs, MUSB_DEVCTL); | ||
919 | |||
920 | dev_dbg(musb->controller, "<== devctl %02x\n", devctl); | ||
921 | |||
922 | /* Set INT enable registers, enable interrupts */ | ||
923 | musb->intrtxe = musb->epmask; | ||
924 | musb_writew(regs, MUSB_INTRTXE, musb->intrtxe); | ||
925 | musb->intrrxe = musb->epmask & 0xfffe; | ||
926 | musb_writew(regs, MUSB_INTRRXE, musb->intrrxe); | ||
927 | musb_writeb(regs, MUSB_INTRUSBE, 0xf7); | ||
928 | |||
929 | musb_writeb(regs, MUSB_TESTMODE, 0); | ||
930 | |||
931 | /* put into basic highspeed mode and start session */ | ||
932 | musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE | ||
933 | | MUSB_POWER_HSENAB | ||
934 | /* ENSUSPEND wedges tusb */ | ||
935 | /* | MUSB_POWER_ENSUSPEND */ | ||
936 | ); | ||
937 | |||
938 | musb->is_active = 0; | ||
939 | devctl = musb_readb(regs, MUSB_DEVCTL); | ||
940 | devctl &= ~MUSB_DEVCTL_SESSION; | ||
941 | |||
942 | /* session started after: | ||
943 | * (a) ID-grounded irq, host mode; | ||
944 | * (b) vbus present/connect IRQ, peripheral mode; | ||
945 | * (c) peripheral initiates, using SRP | ||
946 | */ | ||
947 | if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) | ||
948 | musb->is_active = 1; | ||
949 | else | ||
950 | devctl |= MUSB_DEVCTL_SESSION; | ||
951 | |||
952 | musb_platform_enable(musb); | ||
953 | musb_writeb(regs, MUSB_DEVCTL, devctl); | ||
954 | } | ||
955 | |||
956 | |||
957 | static void musb_generic_disable(struct musb *musb) | 903 | static void musb_generic_disable(struct musb *musb) |
958 | { | 904 | { |
959 | void __iomem *mbase = musb->mregs; | 905 | void __iomem *mbase = musb->mregs; |
@@ -1007,6 +953,7 @@ static void musb_shutdown(struct platform_device *pdev) | |||
1007 | 953 | ||
1008 | pm_runtime_get_sync(musb->controller); | 954 | pm_runtime_get_sync(musb->controller); |
1009 | 955 | ||
956 | musb_host_cleanup(musb); | ||
1010 | musb_gadget_cleanup(musb); | 957 | musb_gadget_cleanup(musb); |
1011 | 958 | ||
1012 | spin_lock_irqsave(&musb->lock, flags); | 959 | spin_lock_irqsave(&musb->lock, flags); |
@@ -1763,24 +1710,18 @@ static struct musb *allocate_instance(struct device *dev, | |||
1763 | struct musb *musb; | 1710 | struct musb *musb; |
1764 | struct musb_hw_ep *ep; | 1711 | struct musb_hw_ep *ep; |
1765 | int epnum; | 1712 | int epnum; |
1766 | struct usb_hcd *hcd; | 1713 | int ret; |
1767 | 1714 | ||
1768 | hcd = usb_create_hcd(&musb_hc_driver, dev, dev_name(dev)); | 1715 | musb = devm_kzalloc(dev, sizeof(*musb), GFP_KERNEL); |
1769 | if (!hcd) | 1716 | if (!musb) |
1770 | return NULL; | 1717 | return NULL; |
1771 | /* usbcore sets dev->driver_data to hcd, and sometimes uses that... */ | ||
1772 | 1718 | ||
1773 | musb = hcd_to_musb(hcd); | ||
1774 | INIT_LIST_HEAD(&musb->control); | 1719 | INIT_LIST_HEAD(&musb->control); |
1775 | INIT_LIST_HEAD(&musb->in_bulk); | 1720 | INIT_LIST_HEAD(&musb->in_bulk); |
1776 | INIT_LIST_HEAD(&musb->out_bulk); | 1721 | INIT_LIST_HEAD(&musb->out_bulk); |
1777 | 1722 | ||
1778 | hcd->uses_new_polling = 1; | ||
1779 | hcd->has_tt = 1; | ||
1780 | |||
1781 | musb->vbuserr_retry = VBUSERR_RETRY_COUNT; | 1723 | musb->vbuserr_retry = VBUSERR_RETRY_COUNT; |
1782 | musb->a_wait_bcon = OTG_TIME_A_WAIT_BCON; | 1724 | musb->a_wait_bcon = OTG_TIME_A_WAIT_BCON; |
1783 | dev_set_drvdata(dev, musb); | ||
1784 | musb->mregs = mbase; | 1725 | musb->mregs = mbase; |
1785 | musb->ctrl_base = mbase; | 1726 | musb->ctrl_base = mbase; |
1786 | musb->nIrq = -ENODEV; | 1727 | musb->nIrq = -ENODEV; |
@@ -1795,7 +1736,16 @@ static struct musb *allocate_instance(struct device *dev, | |||
1795 | 1736 | ||
1796 | musb->controller = dev; | 1737 | musb->controller = dev; |
1797 | 1738 | ||
1739 | ret = musb_host_alloc(musb); | ||
1740 | if (ret < 0) | ||
1741 | goto err_free; | ||
1742 | |||
1743 | dev_set_drvdata(dev, musb); | ||
1744 | |||
1798 | return musb; | 1745 | return musb; |
1746 | |||
1747 | err_free: | ||
1748 | return NULL; | ||
1799 | } | 1749 | } |
1800 | 1750 | ||
1801 | static void musb_free(struct musb *musb) | 1751 | static void musb_free(struct musb *musb) |
@@ -1821,7 +1771,7 @@ static void musb_free(struct musb *musb) | |||
1821 | dma_controller_destroy(c); | 1771 | dma_controller_destroy(c); |
1822 | } | 1772 | } |
1823 | 1773 | ||
1824 | usb_put_hcd(musb_to_hcd(musb)); | 1774 | musb_host_free(musb); |
1825 | } | 1775 | } |
1826 | 1776 | ||
1827 | /* | 1777 | /* |
@@ -1838,7 +1788,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) | |||
1838 | int status; | 1788 | int status; |
1839 | struct musb *musb; | 1789 | struct musb *musb; |
1840 | struct musb_hdrc_platform_data *plat = dev->platform_data; | 1790 | struct musb_hdrc_platform_data *plat = dev->platform_data; |
1841 | struct usb_hcd *hcd; | ||
1842 | 1791 | ||
1843 | /* The driver might handle more features than the board; OK. | 1792 | /* The driver might handle more features than the board; OK. |
1844 | * Fail when the board needs a feature that's not enabled. | 1793 | * Fail when the board needs a feature that's not enabled. |
@@ -1864,6 +1813,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) | |||
1864 | musb->board_set_power = plat->set_power; | 1813 | musb->board_set_power = plat->set_power; |
1865 | musb->min_power = plat->min_power; | 1814 | musb->min_power = plat->min_power; |
1866 | musb->ops = plat->platform_ops; | 1815 | musb->ops = plat->platform_ops; |
1816 | musb->port_mode = plat->mode; | ||
1867 | 1817 | ||
1868 | /* The musb_platform_init() call: | 1818 | /* The musb_platform_init() call: |
1869 | * - adjusts musb->mregs | 1819 | * - adjusts musb->mregs |
@@ -1939,13 +1889,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) | |||
1939 | musb->irq_wake = 0; | 1889 | musb->irq_wake = 0; |
1940 | } | 1890 | } |
1941 | 1891 | ||
1942 | /* host side needs more setup */ | ||
1943 | hcd = musb_to_hcd(musb); | ||
1944 | otg_set_host(musb->xceiv->otg, &hcd->self); | ||
1945 | hcd->self.otg_port = 1; | ||
1946 | musb->xceiv->otg->host = &hcd->self; | ||
1947 | hcd->power_budget = 2 * (plat->power ? : 250); | ||
1948 | |||
1949 | /* program PHY to use external vBus if required */ | 1892 | /* program PHY to use external vBus if required */ |
1950 | if (plat->extvbus) { | 1893 | if (plat->extvbus) { |
1951 | u8 busctl = musb_read_ulpi_buscontrol(musb->mregs); | 1894 | u8 busctl = musb_read_ulpi_buscontrol(musb->mregs); |
@@ -1961,7 +1904,23 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) | |||
1961 | musb->xceiv->state = OTG_STATE_B_IDLE; | 1904 | musb->xceiv->state = OTG_STATE_B_IDLE; |
1962 | } | 1905 | } |
1963 | 1906 | ||
1964 | status = musb_gadget_setup(musb); | 1907 | switch (musb->port_mode) { |
1908 | case MUSB_PORT_MODE_HOST: | ||
1909 | status = musb_host_setup(musb, plat->power); | ||
1910 | break; | ||
1911 | case MUSB_PORT_MODE_GADGET: | ||
1912 | status = musb_gadget_setup(musb); | ||
1913 | break; | ||
1914 | case MUSB_PORT_MODE_DUAL_ROLE: | ||
1915 | status = musb_host_setup(musb, plat->power); | ||
1916 | if (status < 0) | ||
1917 | goto fail3; | ||
1918 | status = musb_gadget_setup(musb); | ||
1919 | break; | ||
1920 | default: | ||
1921 | dev_err(dev, "unsupported port mode %d\n", musb->port_mode); | ||
1922 | break; | ||
1923 | } | ||
1965 | 1924 | ||
1966 | if (status < 0) | 1925 | if (status < 0) |
1967 | goto fail3; | 1926 | goto fail3; |
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 7fb4819a6f11..7d341c387eab 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h | |||
@@ -77,28 +77,17 @@ struct musb_ep; | |||
77 | #define is_peripheral_active(m) (!(m)->is_host) | 77 | #define is_peripheral_active(m) (!(m)->is_host) |
78 | #define is_host_active(m) ((m)->is_host) | 78 | #define is_host_active(m) ((m)->is_host) |
79 | 79 | ||
80 | enum { | ||
81 | MUSB_PORT_MODE_HOST = 1, | ||
82 | MUSB_PORT_MODE_GADGET, | ||
83 | MUSB_PORT_MODE_DUAL_ROLE, | ||
84 | }; | ||
85 | |||
80 | #ifdef CONFIG_PROC_FS | 86 | #ifdef CONFIG_PROC_FS |
81 | #include <linux/fs.h> | 87 | #include <linux/fs.h> |
82 | #define MUSB_CONFIG_PROC_FS | 88 | #define MUSB_CONFIG_PROC_FS |
83 | #endif | 89 | #endif |
84 | 90 | ||
85 | /****************************** PERIPHERAL ROLE *****************************/ | ||
86 | |||
87 | extern irqreturn_t musb_g_ep0_irq(struct musb *); | ||
88 | extern void musb_g_tx(struct musb *, u8); | ||
89 | extern void musb_g_rx(struct musb *, u8); | ||
90 | extern void musb_g_reset(struct musb *); | ||
91 | extern void musb_g_suspend(struct musb *); | ||
92 | extern void musb_g_resume(struct musb *); | ||
93 | extern void musb_g_wakeup(struct musb *); | ||
94 | extern void musb_g_disconnect(struct musb *); | ||
95 | |||
96 | /****************************** HOST ROLE ***********************************/ | ||
97 | |||
98 | extern irqreturn_t musb_h_ep0_irq(struct musb *); | ||
99 | extern void musb_host_tx(struct musb *, u8); | ||
100 | extern void musb_host_rx(struct musb *, u8); | ||
101 | |||
102 | /****************************** CONSTANTS ********************************/ | 91 | /****************************** CONSTANTS ********************************/ |
103 | 92 | ||
104 | #ifndef MUSB_C_NUM_EPS | 93 | #ifndef MUSB_C_NUM_EPS |
@@ -373,6 +362,7 @@ struct musb { | |||
373 | 362 | ||
374 | u8 min_power; /* vbus for periph, in mA/2 */ | 363 | u8 min_power; /* vbus for periph, in mA/2 */ |
375 | 364 | ||
365 | int port_mode; /* MUSB_PORT_MODE_* */ | ||
376 | bool is_host; | 366 | bool is_host; |
377 | 367 | ||
378 | int a_wait_bcon; /* VBUS timeout in msecs */ | 368 | int a_wait_bcon; /* VBUS timeout in msecs */ |
@@ -382,7 +372,6 @@ struct musb { | |||
382 | unsigned is_active:1; | 372 | unsigned is_active:1; |
383 | 373 | ||
384 | unsigned is_multipoint:1; | 374 | unsigned is_multipoint:1; |
385 | unsigned ignore_disconnect:1; /* during bus resets */ | ||
386 | 375 | ||
387 | unsigned hb_iso_rx:1; /* high bandwidth iso rx? */ | 376 | unsigned hb_iso_rx:1; /* high bandwidth iso rx? */ |
388 | unsigned hb_iso_tx:1; /* high bandwidth iso tx? */ | 377 | unsigned hb_iso_tx:1; /* high bandwidth iso tx? */ |
@@ -419,6 +408,7 @@ struct musb { | |||
419 | enum musb_g_ep0_state ep0_state; | 408 | enum musb_g_ep0_state ep0_state; |
420 | struct usb_gadget g; /* the gadget */ | 409 | struct usb_gadget g; /* the gadget */ |
421 | struct usb_gadget_driver *gadget_driver; /* its driver */ | 410 | struct usb_gadget_driver *gadget_driver; /* its driver */ |
411 | struct usb_hcd *hcd; /* the usb hcd */ | ||
422 | 412 | ||
423 | /* | 413 | /* |
424 | * FIXME: Remove this flag. | 414 | * FIXME: Remove this flag. |
@@ -520,7 +510,6 @@ static inline void musb_configure_ep0(struct musb *musb) | |||
520 | 510 | ||
521 | extern const char musb_driver_name[]; | 511 | extern const char musb_driver_name[]; |
522 | 512 | ||
523 | extern void musb_start(struct musb *musb); | ||
524 | extern void musb_stop(struct musb *musb); | 513 | extern void musb_stop(struct musb *musb); |
525 | 514 | ||
526 | extern void musb_write_fifo(struct musb_hw_ep *ep, u16 len, const u8 *src); | 515 | extern void musb_write_fifo(struct musb_hw_ep *ep, u16 len, const u8 *src); |
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index ba7092349fa9..0414bc19d009 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c | |||
@@ -1820,7 +1820,6 @@ static int musb_gadget_start(struct usb_gadget *g, | |||
1820 | { | 1820 | { |
1821 | struct musb *musb = gadget_to_musb(g); | 1821 | struct musb *musb = gadget_to_musb(g); |
1822 | struct usb_otg *otg = musb->xceiv->otg; | 1822 | struct usb_otg *otg = musb->xceiv->otg; |
1823 | struct usb_hcd *hcd = musb_to_hcd(musb); | ||
1824 | unsigned long flags; | 1823 | unsigned long flags; |
1825 | int retval = 0; | 1824 | int retval = 0; |
1826 | 1825 | ||
@@ -1847,17 +1846,9 @@ static int musb_gadget_start(struct usb_gadget *g, | |||
1847 | * handles power budgeting ... this way also | 1846 | * handles power budgeting ... this way also |
1848 | * ensures HdrcStart is indirectly called. | 1847 | * ensures HdrcStart is indirectly called. |
1849 | */ | 1848 | */ |
1850 | retval = usb_add_hcd(hcd, 0, 0); | ||
1851 | if (retval < 0) { | ||
1852 | dev_dbg(musb->controller, "add_hcd failed, %d\n", retval); | ||
1853 | goto err; | ||
1854 | } | ||
1855 | |||
1856 | if (musb->xceiv->last_event == USB_EVENT_ID) | 1849 | if (musb->xceiv->last_event == USB_EVENT_ID) |
1857 | musb_platform_set_vbus(musb, 1); | 1850 | musb_platform_set_vbus(musb, 1); |
1858 | 1851 | ||
1859 | hcd->self.uses_pio_for_control = 1; | ||
1860 | |||
1861 | if (musb->xceiv->last_event == USB_EVENT_NONE) | 1852 | if (musb->xceiv->last_event == USB_EVENT_NONE) |
1862 | pm_runtime_put(musb->controller); | 1853 | pm_runtime_put(musb->controller); |
1863 | 1854 | ||
@@ -1942,7 +1933,6 @@ static int musb_gadget_stop(struct usb_gadget *g, | |||
1942 | musb_platform_try_idle(musb, 0); | 1933 | musb_platform_try_idle(musb, 0); |
1943 | spin_unlock_irqrestore(&musb->lock, flags); | 1934 | spin_unlock_irqrestore(&musb->lock, flags); |
1944 | 1935 | ||
1945 | usb_remove_hcd(musb_to_hcd(musb)); | ||
1946 | /* | 1936 | /* |
1947 | * FIXME we need to be able to register another | 1937 | * FIXME we need to be able to register another |
1948 | * gadget driver here and have everything work; | 1938 | * gadget driver here and have everything work; |
diff --git a/drivers/usb/musb/musb_gadget.h b/drivers/usb/musb/musb_gadget.h index 66b7c5e0fb44..0314dfc770c7 100644 --- a/drivers/usb/musb/musb_gadget.h +++ b/drivers/usb/musb/musb_gadget.h | |||
@@ -37,6 +37,38 @@ | |||
37 | 37 | ||
38 | #include <linux/list.h> | 38 | #include <linux/list.h> |
39 | 39 | ||
40 | #if IS_ENABLED(CONFIG_USB_MUSB_GADGET) || IS_ENABLED(CONFIG_USB_MUSB_DUAL_ROLE) | ||
41 | extern irqreturn_t musb_g_ep0_irq(struct musb *); | ||
42 | extern void musb_g_tx(struct musb *, u8); | ||
43 | extern void musb_g_rx(struct musb *, u8); | ||
44 | extern void musb_g_reset(struct musb *); | ||
45 | extern void musb_g_suspend(struct musb *); | ||
46 | extern void musb_g_resume(struct musb *); | ||
47 | extern void musb_g_wakeup(struct musb *); | ||
48 | extern void musb_g_disconnect(struct musb *); | ||
49 | extern void musb_gadget_cleanup(struct musb *); | ||
50 | extern int musb_gadget_setup(struct musb *); | ||
51 | |||
52 | #else | ||
53 | static inline irqreturn_t musb_g_ep0_irq(struct musb *musb) | ||
54 | { | ||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | static inline void musb_g_tx(struct musb *musb, u8 epnum) {} | ||
59 | static inline void musb_g_rx(struct musb *musb, u8 epnum) {} | ||
60 | static inline void musb_g_reset(struct musb *musb) {} | ||
61 | static inline void musb_g_suspend(struct musb *musb) {} | ||
62 | static inline void musb_g_resume(struct musb *musb) {} | ||
63 | static inline void musb_g_wakeup(struct musb *musb) {} | ||
64 | static inline void musb_g_disconnect(struct musb *musb) {} | ||
65 | static inline void musb_gadget_cleanup(struct musb *musb) {} | ||
66 | static inline int musb_gadget_setup(struct musb *musb) | ||
67 | { | ||
68 | return 0; | ||
69 | } | ||
70 | #endif | ||
71 | |||
40 | enum buffer_map_state { | 72 | enum buffer_map_state { |
41 | UN_MAPPED = 0, | 73 | UN_MAPPED = 0, |
42 | PRE_MAPPED, | 74 | PRE_MAPPED, |
@@ -106,14 +138,8 @@ static inline struct musb_request *next_request(struct musb_ep *ep) | |||
106 | return container_of(queue->next, struct musb_request, list); | 138 | return container_of(queue->next, struct musb_request, list); |
107 | } | 139 | } |
108 | 140 | ||
109 | extern void musb_g_tx(struct musb *musb, u8 epnum); | ||
110 | extern void musb_g_rx(struct musb *musb, u8 epnum); | ||
111 | |||
112 | extern const struct usb_ep_ops musb_g_ep0_ops; | 141 | extern const struct usb_ep_ops musb_g_ep0_ops; |
113 | 142 | ||
114 | extern int musb_gadget_setup(struct musb *); | ||
115 | extern void musb_gadget_cleanup(struct musb *); | ||
116 | |||
117 | extern void musb_g_giveback(struct musb_ep *, struct usb_request *, int); | 143 | extern void musb_g_giveback(struct musb_ep *, struct usb_request *, int); |
118 | 144 | ||
119 | extern void musb_ep_restart(struct musb *, struct musb_request *); | 145 | extern void musb_ep_restart(struct musb *, struct musb_request *); |
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 9d3044bdebe5..a9695f5a92fb 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c | |||
@@ -46,7 +46,6 @@ | |||
46 | #include "musb_core.h" | 46 | #include "musb_core.h" |
47 | #include "musb_host.h" | 47 | #include "musb_host.h" |
48 | 48 | ||
49 | |||
50 | /* MUSB HOST status 22-mar-2006 | 49 | /* MUSB HOST status 22-mar-2006 |
51 | * | 50 | * |
52 | * - There's still lots of partial code duplication for fault paths, so | 51 | * - There's still lots of partial code duplication for fault paths, so |
@@ -96,6 +95,11 @@ | |||
96 | * of transfers between endpoints, or anything clever. | 95 | * of transfers between endpoints, or anything clever. |
97 | */ | 96 | */ |
98 | 97 | ||
98 | struct musb *hcd_to_musb(struct usb_hcd *hcd) | ||
99 | { | ||
100 | return *(struct musb **) hcd->hcd_priv; | ||
101 | } | ||
102 | |||
99 | 103 | ||
100 | static void musb_ep_program(struct musb *musb, u8 epnum, | 104 | static void musb_ep_program(struct musb *musb, u8 epnum, |
101 | struct urb *urb, int is_out, | 105 | struct urb *urb, int is_out, |
@@ -269,8 +273,7 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh) | |||
269 | /* FIXME this doesn't implement that scheduling policy ... | 273 | /* FIXME this doesn't implement that scheduling policy ... |
270 | * or handle framecounter wrapping | 274 | * or handle framecounter wrapping |
271 | */ | 275 | */ |
272 | if ((urb->transfer_flags & URB_ISO_ASAP) | 276 | if (1) { /* Always assume URB_ISO_ASAP */ |
273 | || (frame >= urb->start_frame)) { | ||
274 | /* REVISIT the SOF irq handler shouldn't duplicate | 277 | /* REVISIT the SOF irq handler shouldn't duplicate |
275 | * this code; and we don't init urb->start_frame... | 278 | * this code; and we don't init urb->start_frame... |
276 | */ | 279 | */ |
@@ -311,9 +314,9 @@ __acquires(musb->lock) | |||
311 | urb->actual_length, urb->transfer_buffer_length | 314 | urb->actual_length, urb->transfer_buffer_length |
312 | ); | 315 | ); |
313 | 316 | ||
314 | usb_hcd_unlink_urb_from_ep(musb_to_hcd(musb), urb); | 317 | usb_hcd_unlink_urb_from_ep(musb->hcd, urb); |
315 | spin_unlock(&musb->lock); | 318 | spin_unlock(&musb->lock); |
316 | usb_hcd_giveback_urb(musb_to_hcd(musb), urb, status); | 319 | usb_hcd_giveback_urb(musb->hcd, urb, status); |
317 | spin_lock(&musb->lock); | 320 | spin_lock(&musb->lock); |
318 | } | 321 | } |
319 | 322 | ||
@@ -625,7 +628,7 @@ static bool musb_tx_dma_program(struct dma_controller *dma, | |||
625 | u16 csr; | 628 | u16 csr; |
626 | u8 mode; | 629 | u8 mode; |
627 | 630 | ||
628 | #ifdef CONFIG_USB_INVENTRA_DMA | 631 | #if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_UX500_DMA) |
629 | if (length > channel->max_len) | 632 | if (length > channel->max_len) |
630 | length = channel->max_len; | 633 | length = channel->max_len; |
631 | 634 | ||
@@ -1455,7 +1458,7 @@ done: | |||
1455 | if (length > qh->maxpacket) | 1458 | if (length > qh->maxpacket) |
1456 | length = qh->maxpacket; | 1459 | length = qh->maxpacket; |
1457 | /* Unmap the buffer so that CPU can use it */ | 1460 | /* Unmap the buffer so that CPU can use it */ |
1458 | usb_hcd_unmap_urb_for_dma(musb_to_hcd(musb), urb); | 1461 | usb_hcd_unmap_urb_for_dma(musb->hcd, urb); |
1459 | 1462 | ||
1460 | /* | 1463 | /* |
1461 | * We need to map sg if the transfer_buffer is | 1464 | * We need to map sg if the transfer_buffer is |
@@ -1657,7 +1660,7 @@ void musb_host_rx(struct musb *musb, u8 epnum) | |||
1657 | 1660 | ||
1658 | /* FIXME this is _way_ too much in-line logic for Mentor DMA */ | 1661 | /* FIXME this is _way_ too much in-line logic for Mentor DMA */ |
1659 | 1662 | ||
1660 | #ifndef CONFIG_USB_INVENTRA_DMA | 1663 | #if !defined(CONFIG_USB_INVENTRA_DMA) && !defined(CONFIG_USB_UX500_DMA) |
1661 | if (rx_csr & MUSB_RXCSR_H_REQPKT) { | 1664 | if (rx_csr & MUSB_RXCSR_H_REQPKT) { |
1662 | /* REVISIT this happened for a while on some short reads... | 1665 | /* REVISIT this happened for a while on some short reads... |
1663 | * the cleanup still needs investigation... looks bad... | 1666 | * the cleanup still needs investigation... looks bad... |
@@ -1689,7 +1692,7 @@ void musb_host_rx(struct musb *musb, u8 epnum) | |||
1689 | | MUSB_RXCSR_RXPKTRDY); | 1692 | | MUSB_RXCSR_RXPKTRDY); |
1690 | musb_writew(hw_ep->regs, MUSB_RXCSR, val); | 1693 | musb_writew(hw_ep->regs, MUSB_RXCSR, val); |
1691 | 1694 | ||
1692 | #ifdef CONFIG_USB_INVENTRA_DMA | 1695 | #if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_UX500_DMA) |
1693 | if (usb_pipeisoc(pipe)) { | 1696 | if (usb_pipeisoc(pipe)) { |
1694 | struct usb_iso_packet_descriptor *d; | 1697 | struct usb_iso_packet_descriptor *d; |
1695 | 1698 | ||
@@ -1745,7 +1748,7 @@ void musb_host_rx(struct musb *musb, u8 epnum) | |||
1745 | } | 1748 | } |
1746 | 1749 | ||
1747 | /* we are expecting IN packets */ | 1750 | /* we are expecting IN packets */ |
1748 | #ifdef CONFIG_USB_INVENTRA_DMA | 1751 | #if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_UX500_DMA) |
1749 | if (dma) { | 1752 | if (dma) { |
1750 | struct dma_controller *c; | 1753 | struct dma_controller *c; |
1751 | u16 rx_count; | 1754 | u16 rx_count; |
@@ -1754,10 +1757,10 @@ void musb_host_rx(struct musb *musb, u8 epnum) | |||
1754 | 1757 | ||
1755 | rx_count = musb_readw(epio, MUSB_RXCOUNT); | 1758 | rx_count = musb_readw(epio, MUSB_RXCOUNT); |
1756 | 1759 | ||
1757 | dev_dbg(musb->controller, "RX%d count %d, buffer 0x%x len %d/%d\n", | 1760 | dev_dbg(musb->controller, "RX%d count %d, buffer 0x%llx len %d/%d\n", |
1758 | epnum, rx_count, | 1761 | epnum, rx_count, |
1759 | urb->transfer_dma | 1762 | (unsigned long long) urb->transfer_dma |
1760 | + urb->actual_length, | 1763 | + urb->actual_length, |
1761 | qh->offset, | 1764 | qh->offset, |
1762 | urb->transfer_buffer_length); | 1765 | urb->transfer_buffer_length); |
1763 | 1766 | ||
@@ -1869,7 +1872,7 @@ void musb_host_rx(struct musb *musb, u8 epnum) | |||
1869 | unsigned int received_len; | 1872 | unsigned int received_len; |
1870 | 1873 | ||
1871 | /* Unmap the buffer so that CPU can use it */ | 1874 | /* Unmap the buffer so that CPU can use it */ |
1872 | usb_hcd_unmap_urb_for_dma(musb_to_hcd(musb), urb); | 1875 | usb_hcd_unmap_urb_for_dma(musb->hcd, urb); |
1873 | 1876 | ||
1874 | /* | 1877 | /* |
1875 | * We need to map sg if the transfer_buffer is | 1878 | * We need to map sg if the transfer_buffer is |
@@ -2463,7 +2466,6 @@ static int musb_bus_resume(struct usb_hcd *hcd) | |||
2463 | return 0; | 2466 | return 0; |
2464 | } | 2467 | } |
2465 | 2468 | ||
2466 | |||
2467 | #ifndef CONFIG_MUSB_PIO_ONLY | 2469 | #ifndef CONFIG_MUSB_PIO_ONLY |
2468 | 2470 | ||
2469 | #define MUSB_USB_DMA_ALIGN 4 | 2471 | #define MUSB_USB_DMA_ALIGN 4 |
@@ -2575,10 +2577,10 @@ static void musb_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) | |||
2575 | } | 2577 | } |
2576 | #endif /* !CONFIG_MUSB_PIO_ONLY */ | 2578 | #endif /* !CONFIG_MUSB_PIO_ONLY */ |
2577 | 2579 | ||
2578 | const struct hc_driver musb_hc_driver = { | 2580 | static const struct hc_driver musb_hc_driver = { |
2579 | .description = "musb-hcd", | 2581 | .description = "musb-hcd", |
2580 | .product_desc = "MUSB HDRC host driver", | 2582 | .product_desc = "MUSB HDRC host driver", |
2581 | .hcd_priv_size = sizeof(struct musb), | 2583 | .hcd_priv_size = sizeof(struct musb *), |
2582 | .flags = HCD_USB2 | HCD_MEMORY, | 2584 | .flags = HCD_USB2 | HCD_MEMORY, |
2583 | 2585 | ||
2584 | /* not using irq handler or reset hooks from usbcore, since | 2586 | /* not using irq handler or reset hooks from usbcore, since |
@@ -2606,3 +2608,66 @@ const struct hc_driver musb_hc_driver = { | |||
2606 | /* .start_port_reset = NULL, */ | 2608 | /* .start_port_reset = NULL, */ |
2607 | /* .hub_irq_enable = NULL, */ | 2609 | /* .hub_irq_enable = NULL, */ |
2608 | }; | 2610 | }; |
2611 | |||
2612 | int musb_host_alloc(struct musb *musb) | ||
2613 | { | ||
2614 | struct device *dev = musb->controller; | ||
2615 | |||
2616 | /* usbcore sets dev->driver_data to hcd, and sometimes uses that... */ | ||
2617 | musb->hcd = usb_create_hcd(&musb_hc_driver, dev, dev_name(dev)); | ||
2618 | if (!musb->hcd) | ||
2619 | return -EINVAL; | ||
2620 | |||
2621 | *musb->hcd->hcd_priv = (unsigned long) musb; | ||
2622 | musb->hcd->self.uses_pio_for_control = 1; | ||
2623 | musb->hcd->uses_new_polling = 1; | ||
2624 | musb->hcd->has_tt = 1; | ||
2625 | |||
2626 | return 0; | ||
2627 | } | ||
2628 | |||
2629 | void musb_host_cleanup(struct musb *musb) | ||
2630 | { | ||
2631 | usb_remove_hcd(musb->hcd); | ||
2632 | musb->hcd = NULL; | ||
2633 | } | ||
2634 | |||
2635 | void musb_host_free(struct musb *musb) | ||
2636 | { | ||
2637 | usb_put_hcd(musb->hcd); | ||
2638 | } | ||
2639 | |||
2640 | int musb_host_setup(struct musb *musb, int power_budget) | ||
2641 | { | ||
2642 | int ret; | ||
2643 | struct usb_hcd *hcd = musb->hcd; | ||
2644 | |||
2645 | MUSB_HST_MODE(musb); | ||
2646 | musb->xceiv->otg->default_a = 1; | ||
2647 | musb->xceiv->state = OTG_STATE_A_IDLE; | ||
2648 | |||
2649 | otg_set_host(musb->xceiv->otg, &hcd->self); | ||
2650 | hcd->self.otg_port = 1; | ||
2651 | musb->xceiv->otg->host = &hcd->self; | ||
2652 | hcd->power_budget = 2 * (power_budget ? : 250); | ||
2653 | |||
2654 | ret = usb_add_hcd(hcd, 0, 0); | ||
2655 | if (ret < 0) | ||
2656 | return ret; | ||
2657 | |||
2658 | return 0; | ||
2659 | } | ||
2660 | |||
2661 | void musb_host_resume_root_hub(struct musb *musb) | ||
2662 | { | ||
2663 | usb_hcd_resume_root_hub(musb->hcd); | ||
2664 | } | ||
2665 | |||
2666 | void musb_host_poke_root_hub(struct musb *musb) | ||
2667 | { | ||
2668 | MUSB_HST_MODE(musb); | ||
2669 | if (musb->hcd->status_urb) | ||
2670 | usb_hcd_poll_rh_status(musb->hcd); | ||
2671 | else | ||
2672 | usb_hcd_resume_root_hub(musb->hcd); | ||
2673 | } | ||
diff --git a/drivers/usb/musb/musb_host.h b/drivers/usb/musb/musb_host.h index 738f7eb60df9..960d73570b2f 100644 --- a/drivers/usb/musb/musb_host.h +++ b/drivers/usb/musb/musb_host.h | |||
@@ -37,16 +37,6 @@ | |||
37 | 37 | ||
38 | #include <linux/scatterlist.h> | 38 | #include <linux/scatterlist.h> |
39 | 39 | ||
40 | static inline struct usb_hcd *musb_to_hcd(struct musb *musb) | ||
41 | { | ||
42 | return container_of((void *) musb, struct usb_hcd, hcd_priv); | ||
43 | } | ||
44 | |||
45 | static inline struct musb *hcd_to_musb(struct usb_hcd *hcd) | ||
46 | { | ||
47 | return (struct musb *) (hcd->hcd_priv); | ||
48 | } | ||
49 | |||
50 | /* stored in "usb_host_endpoint.hcpriv" for scheduled endpoints */ | 40 | /* stored in "usb_host_endpoint.hcpriv" for scheduled endpoints */ |
51 | struct musb_qh { | 41 | struct musb_qh { |
52 | struct usb_host_endpoint *hep; /* usbcore info */ | 42 | struct usb_host_endpoint *hep; /* usbcore info */ |
@@ -86,7 +76,52 @@ static inline struct musb_qh *first_qh(struct list_head *q) | |||
86 | } | 76 | } |
87 | 77 | ||
88 | 78 | ||
79 | #if IS_ENABLED(CONFIG_USB_MUSB_HOST) || IS_ENABLED(CONFIG_USB_MUSB_DUAL_ROLE) | ||
80 | extern struct musb *hcd_to_musb(struct usb_hcd *); | ||
81 | extern irqreturn_t musb_h_ep0_irq(struct musb *); | ||
82 | extern int musb_host_alloc(struct musb *); | ||
83 | extern int musb_host_setup(struct musb *, int); | ||
84 | extern void musb_host_cleanup(struct musb *); | ||
85 | extern void musb_host_tx(struct musb *, u8); | ||
86 | extern void musb_host_rx(struct musb *, u8); | ||
87 | extern void musb_root_disconnect(struct musb *musb); | ||
88 | extern void musb_host_free(struct musb *); | ||
89 | extern void musb_host_cleanup(struct musb *); | ||
90 | extern void musb_host_tx(struct musb *, u8); | ||
91 | extern void musb_host_rx(struct musb *, u8); | ||
89 | extern void musb_root_disconnect(struct musb *musb); | 92 | extern void musb_root_disconnect(struct musb *musb); |
93 | extern void musb_host_resume_root_hub(struct musb *musb); | ||
94 | extern void musb_host_poke_root_hub(struct musb *musb); | ||
95 | #else | ||
96 | static inline struct musb *hcd_to_musb(struct usb_hcd *hcd) | ||
97 | { | ||
98 | return NULL; | ||
99 | } | ||
100 | |||
101 | static inline irqreturn_t musb_h_ep0_irq(struct musb *musb) | ||
102 | { | ||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | static inline int musb_host_alloc(struct musb *musb) | ||
107 | { | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | static inline int musb_host_setup(struct musb *musb, int power_budget) | ||
112 | { | ||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | static inline void musb_host_cleanup(struct musb *musb) {} | ||
117 | static inline void musb_host_free(struct musb *musb) {} | ||
118 | static inline void musb_host_tx(struct musb *musb, u8 epnum) {} | ||
119 | static inline void musb_host_rx(struct musb *musb, u8 epnum) {} | ||
120 | static inline void musb_root_disconnect(struct musb *musb) {} | ||
121 | static inline void musb_host_resume_root_hub(struct musb *musb) {} | ||
122 | static inline void musb_host_poll_rh_status(struct musb *musb) {} | ||
123 | static inline void musb_host_poke_root_hub(struct musb *musb) {} | ||
124 | #endif | ||
90 | 125 | ||
91 | struct usb_hcd; | 126 | struct usb_hcd; |
92 | 127 | ||
@@ -95,8 +130,6 @@ extern int musb_hub_control(struct usb_hcd *hcd, | |||
95 | u16 typeReq, u16 wValue, u16 wIndex, | 130 | u16 typeReq, u16 wValue, u16 wIndex, |
96 | char *buf, u16 wLength); | 131 | char *buf, u16 wLength); |
97 | 132 | ||
98 | extern const struct hc_driver musb_hc_driver; | ||
99 | |||
100 | static inline struct urb *next_urb(struct musb_qh *qh) | 133 | static inline struct urb *next_urb(struct musb_qh *qh) |
101 | { | 134 | { |
102 | struct list_head *queue; | 135 | struct list_head *queue; |
diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index ef7d11045f56..a523950c2b32 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c | |||
@@ -44,6 +44,51 @@ | |||
44 | 44 | ||
45 | #include "musb_core.h" | 45 | #include "musb_core.h" |
46 | 46 | ||
47 | /* | ||
48 | * Program the HDRC to start (enable interrupts, dma, etc.). | ||
49 | */ | ||
50 | static void musb_start(struct musb *musb) | ||
51 | { | ||
52 | void __iomem *regs = musb->mregs; | ||
53 | u8 devctl = musb_readb(regs, MUSB_DEVCTL); | ||
54 | |||
55 | dev_dbg(musb->controller, "<== devctl %02x\n", devctl); | ||
56 | |||
57 | /* Set INT enable registers, enable interrupts */ | ||
58 | musb->intrtxe = musb->epmask; | ||
59 | musb_writew(regs, MUSB_INTRTXE, musb->intrtxe); | ||
60 | musb->intrrxe = musb->epmask & 0xfffe; | ||
61 | musb_writew(regs, MUSB_INTRRXE, musb->intrrxe); | ||
62 | musb_writeb(regs, MUSB_INTRUSBE, 0xf7); | ||
63 | |||
64 | musb_writeb(regs, MUSB_TESTMODE, 0); | ||
65 | |||
66 | /* put into basic highspeed mode and start session */ | ||
67 | musb_writeb(regs, MUSB_POWER, MUSB_POWER_ISOUPDATE | ||
68 | | MUSB_POWER_HSENAB | ||
69 | /* ENSUSPEND wedges tusb */ | ||
70 | /* | MUSB_POWER_ENSUSPEND */ | ||
71 | ); | ||
72 | |||
73 | musb->is_active = 0; | ||
74 | devctl = musb_readb(regs, MUSB_DEVCTL); | ||
75 | devctl &= ~MUSB_DEVCTL_SESSION; | ||
76 | |||
77 | /* session started after: | ||
78 | * (a) ID-grounded irq, host mode; | ||
79 | * (b) vbus present/connect IRQ, peripheral mode; | ||
80 | * (c) peripheral initiates, using SRP | ||
81 | */ | ||
82 | if (musb->port_mode != MUSB_PORT_MODE_HOST && | ||
83 | (devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) { | ||
84 | musb->is_active = 1; | ||
85 | } else { | ||
86 | devctl |= MUSB_DEVCTL_SESSION; | ||
87 | } | ||
88 | |||
89 | musb_platform_enable(musb); | ||
90 | musb_writeb(regs, MUSB_DEVCTL, devctl); | ||
91 | } | ||
47 | 92 | ||
48 | static void musb_port_suspend(struct musb *musb, bool do_suspend) | 93 | static void musb_port_suspend(struct musb *musb, bool do_suspend) |
49 | { | 94 | { |
@@ -145,7 +190,6 @@ static void musb_port_reset(struct musb *musb, bool do_reset) | |||
145 | msleep(1); | 190 | msleep(1); |
146 | } | 191 | } |
147 | 192 | ||
148 | musb->ignore_disconnect = true; | ||
149 | power &= 0xf0; | 193 | power &= 0xf0; |
150 | musb_writeb(mbase, MUSB_POWER, | 194 | musb_writeb(mbase, MUSB_POWER, |
151 | power | MUSB_POWER_RESET); | 195 | power | MUSB_POWER_RESET); |
@@ -158,8 +202,6 @@ static void musb_port_reset(struct musb *musb, bool do_reset) | |||
158 | musb_writeb(mbase, MUSB_POWER, | 202 | musb_writeb(mbase, MUSB_POWER, |
159 | power & ~MUSB_POWER_RESET); | 203 | power & ~MUSB_POWER_RESET); |
160 | 204 | ||
161 | musb->ignore_disconnect = false; | ||
162 | |||
163 | power = musb_readb(mbase, MUSB_POWER); | 205 | power = musb_readb(mbase, MUSB_POWER); |
164 | if (power & MUSB_POWER_HSMODE) { | 206 | if (power & MUSB_POWER_HSMODE) { |
165 | dev_dbg(musb->controller, "high-speed device connected\n"); | 207 | dev_dbg(musb->controller, "high-speed device connected\n"); |
@@ -170,7 +212,7 @@ static void musb_port_reset(struct musb *musb, bool do_reset) | |||
170 | musb->port1_status |= USB_PORT_STAT_ENABLE | 212 | musb->port1_status |= USB_PORT_STAT_ENABLE |
171 | | (USB_PORT_STAT_C_RESET << 16) | 213 | | (USB_PORT_STAT_C_RESET << 16) |
172 | | (USB_PORT_STAT_C_ENABLE << 16); | 214 | | (USB_PORT_STAT_C_ENABLE << 16); |
173 | usb_hcd_poll_rh_status(musb_to_hcd(musb)); | 215 | usb_hcd_poll_rh_status(musb->hcd); |
174 | 216 | ||
175 | musb->vbuserr_retry = VBUSERR_RETRY_COUNT; | 217 | musb->vbuserr_retry = VBUSERR_RETRY_COUNT; |
176 | } | 218 | } |
@@ -183,7 +225,7 @@ void musb_root_disconnect(struct musb *musb) | |||
183 | musb->port1_status = USB_PORT_STAT_POWER | 225 | musb->port1_status = USB_PORT_STAT_POWER |
184 | | (USB_PORT_STAT_C_CONNECTION << 16); | 226 | | (USB_PORT_STAT_C_CONNECTION << 16); |
185 | 227 | ||
186 | usb_hcd_poll_rh_status(musb_to_hcd(musb)); | 228 | usb_hcd_poll_rh_status(musb->hcd); |
187 | musb->is_active = 0; | 229 | musb->is_active = 0; |
188 | 230 | ||
189 | switch (musb->xceiv->state) { | 231 | switch (musb->xceiv->state) { |
@@ -337,7 +379,7 @@ int musb_hub_control( | |||
337 | musb->port1_status &= ~(USB_PORT_STAT_SUSPEND | 379 | musb->port1_status &= ~(USB_PORT_STAT_SUSPEND |
338 | | MUSB_PORT_STAT_RESUME); | 380 | | MUSB_PORT_STAT_RESUME); |
339 | musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16; | 381 | musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16; |
340 | usb_hcd_poll_rh_status(musb_to_hcd(musb)); | 382 | usb_hcd_poll_rh_status(musb->hcd); |
341 | /* NOTE: it might really be A_WAIT_BCON ... */ | 383 | /* NOTE: it might really be A_WAIT_BCON ... */ |
342 | musb->xceiv->state = OTG_STATE_A_HOST; | 384 | musb->xceiv->state = OTG_STATE_A_HOST; |
343 | } | 385 | } |
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 628b93fe5ccc..4315d351fc7d 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c | |||
@@ -87,7 +87,7 @@ static void musb_do_idle(unsigned long _musb) | |||
87 | musb->port1_status &= ~(USB_PORT_STAT_SUSPEND | 87 | musb->port1_status &= ~(USB_PORT_STAT_SUSPEND |
88 | | MUSB_PORT_STAT_RESUME); | 88 | | MUSB_PORT_STAT_RESUME); |
89 | musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16; | 89 | musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16; |
90 | usb_hcd_poll_rh_status(musb_to_hcd(musb)); | 90 | usb_hcd_poll_rh_status(musb->hcd); |
91 | /* NOTE: it might really be A_WAIT_BCON ... */ | 91 | /* NOTE: it might really be A_WAIT_BCON ... */ |
92 | musb->xceiv->state = OTG_STATE_A_HOST; | 92 | musb->xceiv->state = OTG_STATE_A_HOST; |
93 | } | 93 | } |
@@ -481,6 +481,7 @@ static u64 omap2430_dmamask = DMA_BIT_MASK(32); | |||
481 | 481 | ||
482 | static int omap2430_probe(struct platform_device *pdev) | 482 | static int omap2430_probe(struct platform_device *pdev) |
483 | { | 483 | { |
484 | struct resource musb_resources[2]; | ||
484 | struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; | 485 | struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; |
485 | struct omap_musb_board_data *data; | 486 | struct omap_musb_board_data *data; |
486 | struct platform_device *musb; | 487 | struct platform_device *musb; |
@@ -567,8 +568,21 @@ static int omap2430_probe(struct platform_device *pdev) | |||
567 | 568 | ||
568 | INIT_WORK(&glue->omap_musb_mailbox_work, omap_musb_mailbox_work); | 569 | INIT_WORK(&glue->omap_musb_mailbox_work, omap_musb_mailbox_work); |
569 | 570 | ||
570 | ret = platform_device_add_resources(musb, pdev->resource, | 571 | memset(musb_resources, 0x00, sizeof(*musb_resources) * |
571 | pdev->num_resources); | 572 | ARRAY_SIZE(musb_resources)); |
573 | |||
574 | musb_resources[0].name = pdev->resource[0].name; | ||
575 | musb_resources[0].start = pdev->resource[0].start; | ||
576 | musb_resources[0].end = pdev->resource[0].end; | ||
577 | musb_resources[0].flags = pdev->resource[0].flags; | ||
578 | |||
579 | musb_resources[1].name = pdev->resource[1].name; | ||
580 | musb_resources[1].start = pdev->resource[1].start; | ||
581 | musb_resources[1].end = pdev->resource[1].end; | ||
582 | musb_resources[1].flags = pdev->resource[1].flags; | ||
583 | |||
584 | ret = platform_device_add_resources(musb, musb_resources, | ||
585 | ARRAY_SIZE(musb_resources)); | ||
572 | if (ret) { | 586 | if (ret) { |
573 | dev_err(&pdev->dev, "failed to add resources\n"); | 587 | dev_err(&pdev->dev, "failed to add resources\n"); |
574 | goto err2; | 588 | goto err2; |
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 7369ba33c94f..2c06a8969a9f 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c | |||
@@ -1156,6 +1156,7 @@ static u64 tusb_dmamask = DMA_BIT_MASK(32); | |||
1156 | 1156 | ||
1157 | static int tusb_probe(struct platform_device *pdev) | 1157 | static int tusb_probe(struct platform_device *pdev) |
1158 | { | 1158 | { |
1159 | struct resource musb_resources[2]; | ||
1159 | struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; | 1160 | struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; |
1160 | struct platform_device *musb; | 1161 | struct platform_device *musb; |
1161 | struct tusb6010_glue *glue; | 1162 | struct tusb6010_glue *glue; |
@@ -1185,8 +1186,21 @@ static int tusb_probe(struct platform_device *pdev) | |||
1185 | 1186 | ||
1186 | platform_set_drvdata(pdev, glue); | 1187 | platform_set_drvdata(pdev, glue); |
1187 | 1188 | ||
1188 | ret = platform_device_add_resources(musb, pdev->resource, | 1189 | memset(musb_resources, 0x00, sizeof(*musb_resources) * |
1189 | pdev->num_resources); | 1190 | ARRAY_SIZE(musb_resources)); |
1191 | |||
1192 | musb_resources[0].name = pdev->resource[0].name; | ||
1193 | musb_resources[0].start = pdev->resource[0].start; | ||
1194 | musb_resources[0].end = pdev->resource[0].end; | ||
1195 | musb_resources[0].flags = pdev->resource[0].flags; | ||
1196 | |||
1197 | musb_resources[1].name = pdev->resource[1].name; | ||
1198 | musb_resources[1].start = pdev->resource[1].start; | ||
1199 | musb_resources[1].end = pdev->resource[1].end; | ||
1200 | musb_resources[1].flags = pdev->resource[1].flags; | ||
1201 | |||
1202 | ret = platform_device_add_resources(musb, musb_resources, | ||
1203 | ARRAY_SIZE(musb_resources)); | ||
1190 | if (ret) { | 1204 | if (ret) { |
1191 | dev_err(&pdev->dev, "failed to add resources\n"); | 1205 | dev_err(&pdev->dev, "failed to add resources\n"); |
1192 | goto err3; | 1206 | goto err3; |
diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c index 2c80004e0a83..028ff4d07dc7 100644 --- a/drivers/usb/musb/ux500.c +++ b/drivers/usb/musb/ux500.c | |||
@@ -189,6 +189,7 @@ static const struct musb_platform_ops ux500_ops = { | |||
189 | 189 | ||
190 | static int ux500_probe(struct platform_device *pdev) | 190 | static int ux500_probe(struct platform_device *pdev) |
191 | { | 191 | { |
192 | struct resource musb_resources[2]; | ||
192 | struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; | 193 | struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; |
193 | struct platform_device *musb; | 194 | struct platform_device *musb; |
194 | struct ux500_glue *glue; | 195 | struct ux500_glue *glue; |
@@ -232,8 +233,21 @@ static int ux500_probe(struct platform_device *pdev) | |||
232 | 233 | ||
233 | platform_set_drvdata(pdev, glue); | 234 | platform_set_drvdata(pdev, glue); |
234 | 235 | ||
235 | ret = platform_device_add_resources(musb, pdev->resource, | 236 | memset(musb_resources, 0x00, sizeof(*musb_resources) * |
236 | pdev->num_resources); | 237 | ARRAY_SIZE(musb_resources)); |
238 | |||
239 | musb_resources[0].name = pdev->resource[0].name; | ||
240 | musb_resources[0].start = pdev->resource[0].start; | ||
241 | musb_resources[0].end = pdev->resource[0].end; | ||
242 | musb_resources[0].flags = pdev->resource[0].flags; | ||
243 | |||
244 | musb_resources[1].name = pdev->resource[1].name; | ||
245 | musb_resources[1].start = pdev->resource[1].start; | ||
246 | musb_resources[1].end = pdev->resource[1].end; | ||
247 | musb_resources[1].flags = pdev->resource[1].flags; | ||
248 | |||
249 | ret = platform_device_add_resources(musb, musb_resources, | ||
250 | ARRAY_SIZE(musb_resources)); | ||
237 | if (ret) { | 251 | if (ret) { |
238 | dev_err(&pdev->dev, "failed to add resources\n"); | 252 | dev_err(&pdev->dev, "failed to add resources\n"); |
239 | goto err5; | 253 | goto err5; |
diff --git a/drivers/usb/musb/ux500_dma.c b/drivers/usb/musb/ux500_dma.c index 338120641145..63e7c8a6b125 100644 --- a/drivers/usb/musb/ux500_dma.c +++ b/drivers/usb/musb/ux500_dma.c | |||
@@ -71,8 +71,7 @@ static void ux500_dma_callback(void *private_data) | |||
71 | spin_lock_irqsave(&musb->lock, flags); | 71 | spin_lock_irqsave(&musb->lock, flags); |
72 | ux500_channel->channel.actual_len = ux500_channel->cur_len; | 72 | ux500_channel->channel.actual_len = ux500_channel->cur_len; |
73 | ux500_channel->channel.status = MUSB_DMA_STATUS_FREE; | 73 | ux500_channel->channel.status = MUSB_DMA_STATUS_FREE; |
74 | musb_dma_completion(musb, hw_ep->epnum, | 74 | musb_dma_completion(musb, hw_ep->epnum, ux500_channel->is_tx); |
75 | ux500_channel->is_tx); | ||
76 | spin_unlock_irqrestore(&musb->lock, flags); | 75 | spin_unlock_irqrestore(&musb->lock, flags); |
77 | 76 | ||
78 | } | 77 | } |
@@ -366,7 +365,8 @@ void dma_controller_destroy(struct dma_controller *c) | |||
366 | kfree(controller); | 365 | kfree(controller); |
367 | } | 366 | } |
368 | 367 | ||
369 | struct dma_controller *dma_controller_create(struct musb *musb, void __iomem *base) | 368 | struct dma_controller *dma_controller_create(struct musb *musb, |
369 | void __iomem *base) | ||
370 | { | 370 | { |
371 | struct ux500_dma_controller *controller; | 371 | struct ux500_dma_controller *controller; |
372 | struct platform_device *pdev = to_platform_device(musb->controller); | 372 | struct platform_device *pdev = to_platform_device(musb->controller); |
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 2311b1e4e43c..a5a9552c25a1 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig | |||
@@ -92,7 +92,7 @@ config OMAP_USB3 | |||
92 | on/off the PHY. | 92 | on/off the PHY. |
93 | 93 | ||
94 | config SAMSUNG_USBPHY | 94 | config SAMSUNG_USBPHY |
95 | tristate "Samsung USB PHY Driver" | 95 | tristate |
96 | help | 96 | help |
97 | Enable this to support Samsung USB phy helper driver for Samsung SoCs. | 97 | Enable this to support Samsung USB phy helper driver for Samsung SoCs. |
98 | This driver provides common interface to interact, for Samsung USB 2.0 PHY | 98 | This driver provides common interface to interact, for Samsung USB 2.0 PHY |
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index a9169cb1e6fc..070eca3af18b 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile | |||
@@ -5,6 +5,7 @@ | |||
5 | ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG | 5 | ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG |
6 | 6 | ||
7 | obj-$(CONFIG_USB_PHY) += phy.o | 7 | obj-$(CONFIG_USB_PHY) += phy.o |
8 | obj-$(CONFIG_OF) += of.o | ||
8 | 9 | ||
9 | # transceiver drivers, keep the list sorted | 10 | # transceiver drivers, keep the list sorted |
10 | 11 | ||
diff --git a/drivers/usb/phy/of.c b/drivers/usb/phy/of.c new file mode 100644 index 000000000000..7ea0154da9d5 --- /dev/null +++ b/drivers/usb/phy/of.c | |||
@@ -0,0 +1,47 @@ | |||
1 | /* | ||
2 | * USB of helper code | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/of.h> | ||
13 | #include <linux/usb/of.h> | ||
14 | #include <linux/usb/otg.h> | ||
15 | |||
16 | static const char *const usbphy_modes[] = { | ||
17 | [USBPHY_INTERFACE_MODE_UNKNOWN] = "", | ||
18 | [USBPHY_INTERFACE_MODE_UTMI] = "utmi", | ||
19 | [USBPHY_INTERFACE_MODE_UTMIW] = "utmi_wide", | ||
20 | [USBPHY_INTERFACE_MODE_ULPI] = "ulpi", | ||
21 | [USBPHY_INTERFACE_MODE_SERIAL] = "serial", | ||
22 | [USBPHY_INTERFACE_MODE_HSIC] = "hsic", | ||
23 | }; | ||
24 | |||
25 | /** | ||
26 | * of_usb_get_phy_mode - Get phy mode for given device_node | ||
27 | * @np: Pointer to the given device_node | ||
28 | * | ||
29 | * The function gets phy interface string from property 'phy_type', | ||
30 | * and returns the correspondig enum usb_phy_interface | ||
31 | */ | ||
32 | enum usb_phy_interface of_usb_get_phy_mode(struct device_node *np) | ||
33 | { | ||
34 | const char *phy_type; | ||
35 | int err, i; | ||
36 | |||
37 | err = of_property_read_string(np, "phy_type", &phy_type); | ||
38 | if (err < 0) | ||
39 | return USBPHY_INTERFACE_MODE_UNKNOWN; | ||
40 | |||
41 | for (i = 0; i < ARRAY_SIZE(usbphy_modes); i++) | ||
42 | if (!strcmp(phy_type, usbphy_modes[i])) | ||
43 | return i; | ||
44 | |||
45 | return USBPHY_INTERFACE_MODE_UNKNOWN; | ||
46 | } | ||
47 | EXPORT_SYMBOL_GPL(of_usb_get_phy_mode); | ||
diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c index e5eb1b5a04eb..087402350b6d 100644 --- a/drivers/usb/phy/phy-ab8500-usb.c +++ b/drivers/usb/phy/phy-ab8500-usb.c | |||
@@ -1,10 +1,12 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/usb/otg/ab8500_usb.c | 2 | * drivers/usb/otg/ab8500_usb.c |
3 | * | 3 | * |
4 | * USB transceiver driver for AB8500 chip | 4 | * USB transceiver driver for AB8500 family chips |
5 | * | 5 | * |
6 | * Copyright (C) 2010 ST-Ericsson AB | 6 | * Copyright (C) 2010-2013 ST-Ericsson AB |
7 | * Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com> | 7 | * Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com> |
8 | * Avinash Kumar <avinash.kumar@stericsson.com> | ||
9 | * Thirupathi Chippakurthy <thirupathi.chippakurthy@stericsson.com> | ||
8 | * | 10 | * |
9 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
10 | * it under the terms of the GNU General Public License as published by | 12 | * it under the terms of the GNU General Public License as published by |
@@ -29,6 +31,8 @@ | |||
29 | #include <linux/notifier.h> | 31 | #include <linux/notifier.h> |
30 | #include <linux/interrupt.h> | 32 | #include <linux/interrupt.h> |
31 | #include <linux/delay.h> | 33 | #include <linux/delay.h> |
34 | #include <linux/clk.h> | ||
35 | #include <linux/err.h> | ||
32 | #include <linux/mfd/abx500.h> | 36 | #include <linux/mfd/abx500.h> |
33 | #include <linux/mfd/abx500/ab8500.h> | 37 | #include <linux/mfd/abx500/ab8500.h> |
34 | #include <linux/usb/musb-ux500.h> | 38 | #include <linux/usb/musb-ux500.h> |
@@ -41,21 +45,34 @@ | |||
41 | /* Bank AB8500_USB */ | 45 | /* Bank AB8500_USB */ |
42 | #define AB8500_USB_LINE_STAT_REG 0x80 | 46 | #define AB8500_USB_LINE_STAT_REG 0x80 |
43 | #define AB8505_USB_LINE_STAT_REG 0x94 | 47 | #define AB8505_USB_LINE_STAT_REG 0x94 |
48 | #define AB8540_USB_LINK_STAT_REG 0x94 | ||
49 | #define AB9540_USB_LINK_STAT_REG 0x94 | ||
50 | #define AB8540_USB_OTG_CTL_REG 0x87 | ||
44 | #define AB8500_USB_PHY_CTRL_REG 0x8A | 51 | #define AB8500_USB_PHY_CTRL_REG 0x8A |
52 | #define AB8540_VBUS_CTRL_REG 0x82 | ||
45 | 53 | ||
46 | /* Bank AB8500_DEVELOPMENT */ | 54 | /* Bank AB8500_DEVELOPMENT */ |
47 | #define AB8500_BANK12_ACCESS 0x00 | 55 | #define AB8500_BANK12_ACCESS 0x00 |
48 | 56 | ||
49 | /* Bank AB8500_DEBUG */ | 57 | /* Bank AB8500_DEBUG */ |
58 | #define AB8540_DEBUG 0x32 | ||
50 | #define AB8500_USB_PHY_TUNE1 0x05 | 59 | #define AB8500_USB_PHY_TUNE1 0x05 |
51 | #define AB8500_USB_PHY_TUNE2 0x06 | 60 | #define AB8500_USB_PHY_TUNE2 0x06 |
52 | #define AB8500_USB_PHY_TUNE3 0x07 | 61 | #define AB8500_USB_PHY_TUNE3 0x07 |
53 | 62 | ||
63 | /* Bank AB8500_INTERRUPT */ | ||
64 | #define AB8500_IT_SOURCE2_REG 0x01 | ||
65 | |||
54 | #define AB8500_BIT_OTG_STAT_ID (1 << 0) | 66 | #define AB8500_BIT_OTG_STAT_ID (1 << 0) |
55 | #define AB8500_BIT_PHY_CTRL_HOST_EN (1 << 0) | 67 | #define AB8500_BIT_PHY_CTRL_HOST_EN (1 << 0) |
56 | #define AB8500_BIT_PHY_CTRL_DEVICE_EN (1 << 1) | 68 | #define AB8500_BIT_PHY_CTRL_DEVICE_EN (1 << 1) |
57 | #define AB8500_BIT_WD_CTRL_ENABLE (1 << 0) | 69 | #define AB8500_BIT_WD_CTRL_ENABLE (1 << 0) |
58 | #define AB8500_BIT_WD_CTRL_KICK (1 << 1) | 70 | #define AB8500_BIT_WD_CTRL_KICK (1 << 1) |
71 | #define AB8500_BIT_SOURCE2_VBUSDET (1 << 7) | ||
72 | #define AB8540_BIT_OTG_CTL_VBUS_VALID_ENA (1 << 0) | ||
73 | #define AB8540_BIT_OTG_CTL_ID_HOST_ENA (1 << 1) | ||
74 | #define AB8540_BIT_OTG_CTL_ID_DEV_ENA (1 << 5) | ||
75 | #define AB8540_BIT_VBUS_CTRL_CHARG_DET_ENA (1 << 0) | ||
59 | 76 | ||
60 | #define AB8500_WD_KICK_DELAY_US 100 /* usec */ | 77 | #define AB8500_WD_KICK_DELAY_US 100 /* usec */ |
61 | #define AB8500_WD_V11_DISABLE_DELAY_US 100 /* usec */ | 78 | #define AB8500_WD_V11_DISABLE_DELAY_US 100 /* usec */ |
@@ -112,6 +129,68 @@ enum ab8505_usb_link_status { | |||
112 | USB_LINK_MOTOROLA_FACTORY_CBL_PHY_EN_8505, | 129 | USB_LINK_MOTOROLA_FACTORY_CBL_PHY_EN_8505, |
113 | }; | 130 | }; |
114 | 131 | ||
132 | enum ab8540_usb_link_status { | ||
133 | USB_LINK_NOT_CONFIGURED_8540 = 0, | ||
134 | USB_LINK_STD_HOST_NC_8540, | ||
135 | USB_LINK_STD_HOST_C_NS_8540, | ||
136 | USB_LINK_STD_HOST_C_S_8540, | ||
137 | USB_LINK_CDP_8540, | ||
138 | USB_LINK_RESERVED0_8540, | ||
139 | USB_LINK_RESERVED1_8540, | ||
140 | USB_LINK_DEDICATED_CHG_8540, | ||
141 | USB_LINK_ACA_RID_A_8540, | ||
142 | USB_LINK_ACA_RID_B_8540, | ||
143 | USB_LINK_ACA_RID_C_NM_8540, | ||
144 | USB_LINK_RESERVED2_8540, | ||
145 | USB_LINK_RESERVED3_8540, | ||
146 | USB_LINK_HM_IDGND_8540, | ||
147 | USB_LINK_CHARGERPORT_NOT_OK_8540, | ||
148 | USB_LINK_CHARGER_DM_HIGH_8540, | ||
149 | USB_LINK_PHYEN_NO_VBUS_NO_IDGND_8540, | ||
150 | USB_LINK_STD_UPSTREAM_NO_IDGNG_VBUS_8540, | ||
151 | USB_LINK_STD_UPSTREAM_8540, | ||
152 | USB_LINK_CHARGER_SE1_8540, | ||
153 | USB_LINK_CARKIT_CHGR_1_8540, | ||
154 | USB_LINK_CARKIT_CHGR_2_8540, | ||
155 | USB_LINK_ACA_DOCK_CHGR_8540, | ||
156 | USB_LINK_SAMSUNG_BOOT_CBL_PHY_EN_8540, | ||
157 | USB_LINK_SAMSUNG_BOOT_CBL_PHY_DISB_8540, | ||
158 | USB_LINK_SAMSUNG_UART_CBL_PHY_EN_8540, | ||
159 | USB_LINK_SAMSUNG_UART_CBL_PHY_DISB_8540, | ||
160 | USB_LINK_MOTOROLA_FACTORY_CBL_PHY_EN_8540 | ||
161 | }; | ||
162 | |||
163 | enum ab9540_usb_link_status { | ||
164 | USB_LINK_NOT_CONFIGURED_9540 = 0, | ||
165 | USB_LINK_STD_HOST_NC_9540, | ||
166 | USB_LINK_STD_HOST_C_NS_9540, | ||
167 | USB_LINK_STD_HOST_C_S_9540, | ||
168 | USB_LINK_CDP_9540, | ||
169 | USB_LINK_RESERVED0_9540, | ||
170 | USB_LINK_RESERVED1_9540, | ||
171 | USB_LINK_DEDICATED_CHG_9540, | ||
172 | USB_LINK_ACA_RID_A_9540, | ||
173 | USB_LINK_ACA_RID_B_9540, | ||
174 | USB_LINK_ACA_RID_C_NM_9540, | ||
175 | USB_LINK_RESERVED2_9540, | ||
176 | USB_LINK_RESERVED3_9540, | ||
177 | USB_LINK_HM_IDGND_9540, | ||
178 | USB_LINK_CHARGERPORT_NOT_OK_9540, | ||
179 | USB_LINK_CHARGER_DM_HIGH_9540, | ||
180 | USB_LINK_PHYEN_NO_VBUS_NO_IDGND_9540, | ||
181 | USB_LINK_STD_UPSTREAM_NO_IDGNG_VBUS_9540, | ||
182 | USB_LINK_STD_UPSTREAM_9540, | ||
183 | USB_LINK_CHARGER_SE1_9540, | ||
184 | USB_LINK_CARKIT_CHGR_1_9540, | ||
185 | USB_LINK_CARKIT_CHGR_2_9540, | ||
186 | USB_LINK_ACA_DOCK_CHGR_9540, | ||
187 | USB_LINK_SAMSUNG_BOOT_CBL_PHY_EN_9540, | ||
188 | USB_LINK_SAMSUNG_BOOT_CBL_PHY_DISB_9540, | ||
189 | USB_LINK_SAMSUNG_UART_CBL_PHY_EN_9540, | ||
190 | USB_LINK_SAMSUNG_UART_CBL_PHY_DISB_9540, | ||
191 | USB_LINK_MOTOROLA_FACTORY_CBL_PHY_EN_9540 | ||
192 | }; | ||
193 | |||
115 | enum ab8500_usb_mode { | 194 | enum ab8500_usb_mode { |
116 | USB_IDLE = 0, | 195 | USB_IDLE = 0, |
117 | USB_PERIPHERAL, | 196 | USB_PERIPHERAL, |
@@ -119,13 +198,30 @@ enum ab8500_usb_mode { | |||
119 | USB_DEDICATED_CHG | 198 | USB_DEDICATED_CHG |
120 | }; | 199 | }; |
121 | 200 | ||
201 | /* Register USB_LINK_STATUS interrupt */ | ||
202 | #define AB8500_USB_FLAG_USE_LINK_STATUS_IRQ (1 << 0) | ||
203 | /* Register ID_WAKEUP_F interrupt */ | ||
204 | #define AB8500_USB_FLAG_USE_ID_WAKEUP_IRQ (1 << 1) | ||
205 | /* Register VBUS_DET_F interrupt */ | ||
206 | #define AB8500_USB_FLAG_USE_VBUS_DET_IRQ (1 << 2) | ||
207 | /* Driver is using the ab-iddet driver*/ | ||
208 | #define AB8500_USB_FLAG_USE_AB_IDDET (1 << 3) | ||
209 | /* Enable setting regulators voltage */ | ||
210 | #define AB8500_USB_FLAG_REGULATOR_SET_VOLTAGE (1 << 4) | ||
211 | /* Enable the check_vbus_status workaround */ | ||
212 | #define AB8500_USB_FLAG_USE_CHECK_VBUS_STATUS (1 << 5) | ||
213 | /* Enable the vbus host workaround */ | ||
214 | #define AB8500_USB_FLAG_USE_VBUS_HOST_QUIRK (1 << 6) | ||
215 | |||
122 | struct ab8500_usb { | 216 | struct ab8500_usb { |
123 | struct usb_phy phy; | 217 | struct usb_phy phy; |
124 | struct device *dev; | 218 | struct device *dev; |
125 | struct ab8500 *ab8500; | 219 | struct ab8500 *ab8500; |
126 | unsigned vbus_draw; | 220 | unsigned vbus_draw; |
127 | struct work_struct phy_dis_work; | 221 | struct work_struct phy_dis_work; |
222 | struct work_struct vbus_event_work; | ||
128 | enum ab8500_usb_mode mode; | 223 | enum ab8500_usb_mode mode; |
224 | struct clk *sysclk; | ||
129 | struct regulator *v_ape; | 225 | struct regulator *v_ape; |
130 | struct regulator *v_musb; | 226 | struct regulator *v_musb; |
131 | struct regulator *v_ulpi; | 227 | struct regulator *v_ulpi; |
@@ -133,6 +229,8 @@ struct ab8500_usb { | |||
133 | int previous_link_status_state; | 229 | int previous_link_status_state; |
134 | struct pinctrl *pinctrl; | 230 | struct pinctrl *pinctrl; |
135 | struct pinctrl_state *pins_sleep; | 231 | struct pinctrl_state *pins_sleep; |
232 | bool enabled_charging_detection; | ||
233 | unsigned int flags; | ||
136 | }; | 234 | }; |
137 | 235 | ||
138 | static inline struct ab8500_usb *phy_to_ab(struct usb_phy *x) | 236 | static inline struct ab8500_usb *phy_to_ab(struct usb_phy *x) |
@@ -171,7 +269,7 @@ static void ab8500_usb_regulator_enable(struct ab8500_usb *ab) | |||
171 | if (ret) | 269 | if (ret) |
172 | dev_err(ab->dev, "Failed to enable v-ape\n"); | 270 | dev_err(ab->dev, "Failed to enable v-ape\n"); |
173 | 271 | ||
174 | if (!is_ab8500_2p0_or_earlier(ab->ab8500)) { | 272 | if (ab->flags & AB8500_USB_FLAG_REGULATOR_SET_VOLTAGE) { |
175 | ab->saved_v_ulpi = regulator_get_voltage(ab->v_ulpi); | 273 | ab->saved_v_ulpi = regulator_get_voltage(ab->v_ulpi); |
176 | if (ab->saved_v_ulpi < 0) | 274 | if (ab->saved_v_ulpi < 0) |
177 | dev_err(ab->dev, "Failed to get v_ulpi voltage\n"); | 275 | dev_err(ab->dev, "Failed to get v_ulpi voltage\n"); |
@@ -191,7 +289,7 @@ static void ab8500_usb_regulator_enable(struct ab8500_usb *ab) | |||
191 | if (ret) | 289 | if (ret) |
192 | dev_err(ab->dev, "Failed to enable vddulpivio18\n"); | 290 | dev_err(ab->dev, "Failed to enable vddulpivio18\n"); |
193 | 291 | ||
194 | if (!is_ab8500_2p0_or_earlier(ab->ab8500)) { | 292 | if (ab->flags & AB8500_USB_FLAG_REGULATOR_SET_VOLTAGE) { |
195 | volt = regulator_get_voltage(ab->v_ulpi); | 293 | volt = regulator_get_voltage(ab->v_ulpi); |
196 | if ((volt != 1300000) && (volt != 1350000)) | 294 | if ((volt != 1300000) && (volt != 1350000)) |
197 | dev_err(ab->dev, "Vintcore is not set to 1.3V volt=%d\n", | 295 | dev_err(ab->dev, "Vintcore is not set to 1.3V volt=%d\n", |
@@ -212,7 +310,7 @@ static void ab8500_usb_regulator_disable(struct ab8500_usb *ab) | |||
212 | regulator_disable(ab->v_ulpi); | 310 | regulator_disable(ab->v_ulpi); |
213 | 311 | ||
214 | /* USB is not the only consumer of Vintcore, restore old settings */ | 312 | /* USB is not the only consumer of Vintcore, restore old settings */ |
215 | if (!is_ab8500_2p0_or_earlier(ab->ab8500)) { | 313 | if (ab->flags & AB8500_USB_FLAG_REGULATOR_SET_VOLTAGE) { |
216 | if (ab->saved_v_ulpi > 0) { | 314 | if (ab->saved_v_ulpi > 0) { |
217 | ret = regulator_set_voltage(ab->v_ulpi, | 315 | ret = regulator_set_voltage(ab->v_ulpi, |
218 | ab->saved_v_ulpi, ab->saved_v_ulpi); | 316 | ab->saved_v_ulpi, ab->saved_v_ulpi); |
@@ -252,11 +350,23 @@ static void ab8500_usb_phy_enable(struct ab8500_usb *ab, bool sel_host) | |||
252 | if (IS_ERR(ab->pinctrl)) | 350 | if (IS_ERR(ab->pinctrl)) |
253 | dev_err(ab->dev, "could not get/set default pinstate\n"); | 351 | dev_err(ab->dev, "could not get/set default pinstate\n"); |
254 | 352 | ||
353 | if (clk_prepare_enable(ab->sysclk)) | ||
354 | dev_err(ab->dev, "can't prepare/enable clock\n"); | ||
355 | |||
255 | ab8500_usb_regulator_enable(ab); | 356 | ab8500_usb_regulator_enable(ab); |
256 | 357 | ||
257 | abx500_mask_and_set_register_interruptible(ab->dev, | 358 | abx500_mask_and_set_register_interruptible(ab->dev, |
258 | AB8500_USB, AB8500_USB_PHY_CTRL_REG, | 359 | AB8500_USB, AB8500_USB_PHY_CTRL_REG, |
259 | bit, bit); | 360 | bit, bit); |
361 | |||
362 | if (ab->flags & AB8500_USB_FLAG_USE_VBUS_HOST_QUIRK) { | ||
363 | if (sel_host) | ||
364 | abx500_set_register_interruptible(ab->dev, | ||
365 | AB8500_USB, AB8540_USB_OTG_CTL_REG, | ||
366 | AB8540_BIT_OTG_CTL_VBUS_VALID_ENA | | ||
367 | AB8540_BIT_OTG_CTL_ID_HOST_ENA | | ||
368 | AB8540_BIT_OTG_CTL_ID_DEV_ENA); | ||
369 | } | ||
260 | } | 370 | } |
261 | 371 | ||
262 | static void ab8500_usb_phy_disable(struct ab8500_usb *ab, bool sel_host) | 372 | static void ab8500_usb_phy_disable(struct ab8500_usb *ab, bool sel_host) |
@@ -274,6 +384,8 @@ static void ab8500_usb_phy_disable(struct ab8500_usb *ab, bool sel_host) | |||
274 | /* Needed to disable the phy.*/ | 384 | /* Needed to disable the phy.*/ |
275 | ab8500_usb_wd_workaround(ab); | 385 | ab8500_usb_wd_workaround(ab); |
276 | 386 | ||
387 | clk_disable_unprepare(ab->sysclk); | ||
388 | |||
277 | ab8500_usb_regulator_disable(ab); | 389 | ab8500_usb_regulator_disable(ab); |
278 | 390 | ||
279 | if (!IS_ERR(ab->pinctrl)) { | 391 | if (!IS_ERR(ab->pinctrl)) { |
@@ -286,7 +398,8 @@ static void ab8500_usb_phy_disable(struct ab8500_usb *ab, bool sel_host) | |||
286 | else if (pinctrl_select_state(ab->pinctrl, ab->pins_sleep)) | 398 | else if (pinctrl_select_state(ab->pinctrl, ab->pins_sleep)) |
287 | dev_err(ab->dev, "could not set pins to sleep state\n"); | 399 | dev_err(ab->dev, "could not set pins to sleep state\n"); |
288 | 400 | ||
289 | /* as USB pins are shared with idddet, release them to allow | 401 | /* |
402 | * as USB pins are shared with iddet, release them to allow | ||
290 | * iddet to request them | 403 | * iddet to request them |
291 | */ | 404 | */ |
292 | pinctrl_put(ab->pinctrl); | 405 | pinctrl_put(ab->pinctrl); |
@@ -298,6 +411,254 @@ static void ab8500_usb_phy_disable(struct ab8500_usb *ab, bool sel_host) | |||
298 | #define ab8500_usb_peri_phy_en(ab) ab8500_usb_phy_enable(ab, false) | 411 | #define ab8500_usb_peri_phy_en(ab) ab8500_usb_phy_enable(ab, false) |
299 | #define ab8500_usb_peri_phy_dis(ab) ab8500_usb_phy_disable(ab, false) | 412 | #define ab8500_usb_peri_phy_dis(ab) ab8500_usb_phy_disable(ab, false) |
300 | 413 | ||
414 | static int ab9540_usb_link_status_update(struct ab8500_usb *ab, | ||
415 | enum ab9540_usb_link_status lsts) | ||
416 | { | ||
417 | enum ux500_musb_vbus_id_status event = 0; | ||
418 | |||
419 | dev_dbg(ab->dev, "ab9540_usb_link_status_update %d\n", lsts); | ||
420 | |||
421 | if (ab->previous_link_status_state == USB_LINK_HM_IDGND_9540 && | ||
422 | (lsts == USB_LINK_STD_HOST_C_NS_9540 || | ||
423 | lsts == USB_LINK_STD_HOST_NC_9540)) | ||
424 | return 0; | ||
425 | |||
426 | if (ab->previous_link_status_state == USB_LINK_ACA_RID_A_9540 && | ||
427 | (lsts == USB_LINK_STD_HOST_NC_9540)) | ||
428 | return 0; | ||
429 | |||
430 | ab->previous_link_status_state = lsts; | ||
431 | |||
432 | switch (lsts) { | ||
433 | case USB_LINK_ACA_RID_B_9540: | ||
434 | event = UX500_MUSB_RIDB; | ||
435 | case USB_LINK_NOT_CONFIGURED_9540: | ||
436 | case USB_LINK_RESERVED0_9540: | ||
437 | case USB_LINK_RESERVED1_9540: | ||
438 | case USB_LINK_RESERVED2_9540: | ||
439 | case USB_LINK_RESERVED3_9540: | ||
440 | if (ab->mode == USB_PERIPHERAL) | ||
441 | atomic_notifier_call_chain(&ab->phy.notifier, | ||
442 | UX500_MUSB_CLEAN, &ab->vbus_draw); | ||
443 | ab->mode = USB_IDLE; | ||
444 | ab->phy.otg->default_a = false; | ||
445 | ab->vbus_draw = 0; | ||
446 | if (event != UX500_MUSB_RIDB) | ||
447 | event = UX500_MUSB_NONE; | ||
448 | /* Fallback to default B_IDLE as nothing is connected. */ | ||
449 | ab->phy.state = OTG_STATE_B_IDLE; | ||
450 | break; | ||
451 | |||
452 | case USB_LINK_ACA_RID_C_NM_9540: | ||
453 | event = UX500_MUSB_RIDC; | ||
454 | case USB_LINK_STD_HOST_NC_9540: | ||
455 | case USB_LINK_STD_HOST_C_NS_9540: | ||
456 | case USB_LINK_STD_HOST_C_S_9540: | ||
457 | case USB_LINK_CDP_9540: | ||
458 | if (ab->mode == USB_HOST) { | ||
459 | ab->mode = USB_PERIPHERAL; | ||
460 | ab8500_usb_host_phy_dis(ab); | ||
461 | ab8500_usb_peri_phy_en(ab); | ||
462 | atomic_notifier_call_chain(&ab->phy.notifier, | ||
463 | UX500_MUSB_PREPARE, &ab->vbus_draw); | ||
464 | } | ||
465 | if (ab->mode == USB_IDLE) { | ||
466 | ab->mode = USB_PERIPHERAL; | ||
467 | ab8500_usb_peri_phy_en(ab); | ||
468 | atomic_notifier_call_chain(&ab->phy.notifier, | ||
469 | UX500_MUSB_PREPARE, &ab->vbus_draw); | ||
470 | } | ||
471 | if (event != UX500_MUSB_RIDC) | ||
472 | event = UX500_MUSB_VBUS; | ||
473 | break; | ||
474 | |||
475 | case USB_LINK_ACA_RID_A_9540: | ||
476 | event = UX500_MUSB_RIDA; | ||
477 | case USB_LINK_HM_IDGND_9540: | ||
478 | case USB_LINK_STD_UPSTREAM_9540: | ||
479 | if (ab->mode == USB_PERIPHERAL) { | ||
480 | ab->mode = USB_HOST; | ||
481 | ab8500_usb_peri_phy_dis(ab); | ||
482 | ab8500_usb_host_phy_en(ab); | ||
483 | atomic_notifier_call_chain(&ab->phy.notifier, | ||
484 | UX500_MUSB_PREPARE, &ab->vbus_draw); | ||
485 | } | ||
486 | if (ab->mode == USB_IDLE) { | ||
487 | ab->mode = USB_HOST; | ||
488 | ab8500_usb_host_phy_en(ab); | ||
489 | atomic_notifier_call_chain(&ab->phy.notifier, | ||
490 | UX500_MUSB_PREPARE, &ab->vbus_draw); | ||
491 | } | ||
492 | ab->phy.otg->default_a = true; | ||
493 | if (event != UX500_MUSB_RIDA) | ||
494 | event = UX500_MUSB_ID; | ||
495 | |||
496 | atomic_notifier_call_chain(&ab->phy.notifier, | ||
497 | event, &ab->vbus_draw); | ||
498 | break; | ||
499 | |||
500 | case USB_LINK_DEDICATED_CHG_9540: | ||
501 | ab->mode = USB_DEDICATED_CHG; | ||
502 | event = UX500_MUSB_CHARGER; | ||
503 | atomic_notifier_call_chain(&ab->phy.notifier, | ||
504 | event, &ab->vbus_draw); | ||
505 | break; | ||
506 | |||
507 | case USB_LINK_PHYEN_NO_VBUS_NO_IDGND_9540: | ||
508 | case USB_LINK_STD_UPSTREAM_NO_IDGNG_VBUS_9540: | ||
509 | if (!(is_ab9540_2p0_or_earlier(ab->ab8500))) { | ||
510 | event = UX500_MUSB_NONE; | ||
511 | if (ab->mode == USB_HOST) { | ||
512 | ab->phy.otg->default_a = false; | ||
513 | ab->vbus_draw = 0; | ||
514 | atomic_notifier_call_chain(&ab->phy.notifier, | ||
515 | event, &ab->vbus_draw); | ||
516 | ab8500_usb_host_phy_dis(ab); | ||
517 | ab->mode = USB_IDLE; | ||
518 | } | ||
519 | if (ab->mode == USB_PERIPHERAL) { | ||
520 | atomic_notifier_call_chain(&ab->phy.notifier, | ||
521 | event, &ab->vbus_draw); | ||
522 | ab8500_usb_peri_phy_dis(ab); | ||
523 | atomic_notifier_call_chain(&ab->phy.notifier, | ||
524 | UX500_MUSB_CLEAN, | ||
525 | &ab->vbus_draw); | ||
526 | ab->mode = USB_IDLE; | ||
527 | ab->phy.otg->default_a = false; | ||
528 | ab->vbus_draw = 0; | ||
529 | } | ||
530 | } | ||
531 | break; | ||
532 | |||
533 | default: | ||
534 | break; | ||
535 | } | ||
536 | |||
537 | return 0; | ||
538 | } | ||
539 | |||
540 | static int ab8540_usb_link_status_update(struct ab8500_usb *ab, | ||
541 | enum ab8540_usb_link_status lsts) | ||
542 | { | ||
543 | enum ux500_musb_vbus_id_status event = 0; | ||
544 | |||
545 | dev_dbg(ab->dev, "ab8540_usb_link_status_update %d\n", lsts); | ||
546 | |||
547 | if (ab->enabled_charging_detection) { | ||
548 | /* Disable USB Charger detection */ | ||
549 | abx500_mask_and_set_register_interruptible(ab->dev, | ||
550 | AB8500_USB, AB8540_VBUS_CTRL_REG, | ||
551 | AB8540_BIT_VBUS_CTRL_CHARG_DET_ENA, 0x00); | ||
552 | ab->enabled_charging_detection = false; | ||
553 | } | ||
554 | |||
555 | /* | ||
556 | * Spurious link_status interrupts are seen in case of a | ||
557 | * disconnection of a device in IDGND and RIDA stage | ||
558 | */ | ||
559 | if (ab->previous_link_status_state == USB_LINK_HM_IDGND_8540 && | ||
560 | (lsts == USB_LINK_STD_HOST_C_NS_8540 || | ||
561 | lsts == USB_LINK_STD_HOST_NC_8540)) | ||
562 | return 0; | ||
563 | |||
564 | if (ab->previous_link_status_state == USB_LINK_ACA_RID_A_8540 && | ||
565 | (lsts == USB_LINK_STD_HOST_NC_8540)) | ||
566 | return 0; | ||
567 | |||
568 | ab->previous_link_status_state = lsts; | ||
569 | |||
570 | switch (lsts) { | ||
571 | case USB_LINK_ACA_RID_B_8540: | ||
572 | event = UX500_MUSB_RIDB; | ||
573 | case USB_LINK_NOT_CONFIGURED_8540: | ||
574 | case USB_LINK_RESERVED0_8540: | ||
575 | case USB_LINK_RESERVED1_8540: | ||
576 | case USB_LINK_RESERVED2_8540: | ||
577 | case USB_LINK_RESERVED3_8540: | ||
578 | ab->mode = USB_IDLE; | ||
579 | ab->phy.otg->default_a = false; | ||
580 | ab->vbus_draw = 0; | ||
581 | if (event != UX500_MUSB_RIDB) | ||
582 | event = UX500_MUSB_NONE; | ||
583 | /* | ||
584 | * Fallback to default B_IDLE as nothing | ||
585 | * is connected | ||
586 | */ | ||
587 | ab->phy.state = OTG_STATE_B_IDLE; | ||
588 | break; | ||
589 | |||
590 | case USB_LINK_ACA_RID_C_NM_8540: | ||
591 | event = UX500_MUSB_RIDC; | ||
592 | case USB_LINK_STD_HOST_NC_8540: | ||
593 | case USB_LINK_STD_HOST_C_NS_8540: | ||
594 | case USB_LINK_STD_HOST_C_S_8540: | ||
595 | case USB_LINK_CDP_8540: | ||
596 | if (ab->mode == USB_IDLE) { | ||
597 | ab->mode = USB_PERIPHERAL; | ||
598 | ab8500_usb_peri_phy_en(ab); | ||
599 | atomic_notifier_call_chain(&ab->phy.notifier, | ||
600 | UX500_MUSB_PREPARE, &ab->vbus_draw); | ||
601 | } | ||
602 | if (event != UX500_MUSB_RIDC) | ||
603 | event = UX500_MUSB_VBUS; | ||
604 | break; | ||
605 | |||
606 | case USB_LINK_ACA_RID_A_8540: | ||
607 | case USB_LINK_ACA_DOCK_CHGR_8540: | ||
608 | event = UX500_MUSB_RIDA; | ||
609 | case USB_LINK_HM_IDGND_8540: | ||
610 | case USB_LINK_STD_UPSTREAM_8540: | ||
611 | if (ab->mode == USB_IDLE) { | ||
612 | ab->mode = USB_HOST; | ||
613 | ab8500_usb_host_phy_en(ab); | ||
614 | atomic_notifier_call_chain(&ab->phy.notifier, | ||
615 | UX500_MUSB_PREPARE, &ab->vbus_draw); | ||
616 | } | ||
617 | ab->phy.otg->default_a = true; | ||
618 | if (event != UX500_MUSB_RIDA) | ||
619 | event = UX500_MUSB_ID; | ||
620 | atomic_notifier_call_chain(&ab->phy.notifier, | ||
621 | event, &ab->vbus_draw); | ||
622 | break; | ||
623 | |||
624 | case USB_LINK_DEDICATED_CHG_8540: | ||
625 | ab->mode = USB_DEDICATED_CHG; | ||
626 | event = UX500_MUSB_CHARGER; | ||
627 | atomic_notifier_call_chain(&ab->phy.notifier, | ||
628 | event, &ab->vbus_draw); | ||
629 | break; | ||
630 | |||
631 | case USB_LINK_PHYEN_NO_VBUS_NO_IDGND_8540: | ||
632 | case USB_LINK_STD_UPSTREAM_NO_IDGNG_VBUS_8540: | ||
633 | event = UX500_MUSB_NONE; | ||
634 | if (ab->mode == USB_HOST) { | ||
635 | ab->phy.otg->default_a = false; | ||
636 | ab->vbus_draw = 0; | ||
637 | atomic_notifier_call_chain(&ab->phy.notifier, | ||
638 | event, &ab->vbus_draw); | ||
639 | ab8500_usb_host_phy_dis(ab); | ||
640 | ab->mode = USB_IDLE; | ||
641 | } | ||
642 | if (ab->mode == USB_PERIPHERAL) { | ||
643 | atomic_notifier_call_chain(&ab->phy.notifier, | ||
644 | event, &ab->vbus_draw); | ||
645 | ab8500_usb_peri_phy_dis(ab); | ||
646 | atomic_notifier_call_chain(&ab->phy.notifier, | ||
647 | UX500_MUSB_CLEAN, &ab->vbus_draw); | ||
648 | ab->mode = USB_IDLE; | ||
649 | ab->phy.otg->default_a = false; | ||
650 | ab->vbus_draw = 0; | ||
651 | } | ||
652 | break; | ||
653 | |||
654 | default: | ||
655 | event = UX500_MUSB_NONE; | ||
656 | break; | ||
657 | } | ||
658 | |||
659 | return 0; | ||
660 | } | ||
661 | |||
301 | static int ab8505_usb_link_status_update(struct ab8500_usb *ab, | 662 | static int ab8505_usb_link_status_update(struct ab8500_usb *ab, |
302 | enum ab8505_usb_link_status lsts) | 663 | enum ab8505_usb_link_status lsts) |
303 | { | 664 | { |
@@ -498,6 +859,20 @@ static int abx500_usb_link_status_update(struct ab8500_usb *ab) | |||
498 | AB8500_USB, AB8505_USB_LINE_STAT_REG, ®); | 859 | AB8500_USB, AB8505_USB_LINE_STAT_REG, ®); |
499 | lsts = (reg >> 3) & 0x1F; | 860 | lsts = (reg >> 3) & 0x1F; |
500 | ret = ab8505_usb_link_status_update(ab, lsts); | 861 | ret = ab8505_usb_link_status_update(ab, lsts); |
862 | } else if (is_ab8540(ab->ab8500)) { | ||
863 | enum ab8540_usb_link_status lsts; | ||
864 | |||
865 | abx500_get_register_interruptible(ab->dev, | ||
866 | AB8500_USB, AB8540_USB_LINK_STAT_REG, ®); | ||
867 | lsts = (reg >> 3) & 0xFF; | ||
868 | ret = ab8540_usb_link_status_update(ab, lsts); | ||
869 | } else if (is_ab9540(ab->ab8500)) { | ||
870 | enum ab9540_usb_link_status lsts; | ||
871 | |||
872 | abx500_get_register_interruptible(ab->dev, | ||
873 | AB8500_USB, AB9540_USB_LINK_STAT_REG, ®); | ||
874 | lsts = (reg >> 3) & 0xFF; | ||
875 | ret = ab9540_usb_link_status_update(ab, lsts); | ||
501 | } | 876 | } |
502 | 877 | ||
503 | return ret; | 878 | return ret; |
@@ -553,7 +928,7 @@ static irqreturn_t ab8500_usb_disconnect_irq(int irq, void *data) | |||
553 | 928 | ||
554 | static irqreturn_t ab8500_usb_link_status_irq(int irq, void *data) | 929 | static irqreturn_t ab8500_usb_link_status_irq(int irq, void *data) |
555 | { | 930 | { |
556 | struct ab8500_usb *ab = (struct ab8500_usb *) data; | 931 | struct ab8500_usb *ab = (struct ab8500_usb *)data; |
557 | 932 | ||
558 | abx500_usb_link_status_update(ab); | 933 | abx500_usb_link_status_update(ab); |
559 | 934 | ||
@@ -572,6 +947,69 @@ static void ab8500_usb_phy_disable_work(struct work_struct *work) | |||
572 | ab8500_usb_peri_phy_dis(ab); | 947 | ab8500_usb_peri_phy_dis(ab); |
573 | } | 948 | } |
574 | 949 | ||
950 | /* Check if VBUS is set and linkstatus has not detected a cable. */ | ||
951 | static bool ab8500_usb_check_vbus_status(struct ab8500_usb *ab) | ||
952 | { | ||
953 | u8 isource2; | ||
954 | u8 reg; | ||
955 | enum ab8540_usb_link_status lsts; | ||
956 | |||
957 | abx500_get_register_interruptible(ab->dev, | ||
958 | AB8500_INTERRUPT, AB8500_IT_SOURCE2_REG, | ||
959 | &isource2); | ||
960 | |||
961 | /* If Vbus is below 3.6V abort */ | ||
962 | if (!(isource2 & AB8500_BIT_SOURCE2_VBUSDET)) | ||
963 | return false; | ||
964 | |||
965 | abx500_get_register_interruptible(ab->dev, | ||
966 | AB8500_USB, AB8540_USB_LINK_STAT_REG, | ||
967 | ®); | ||
968 | |||
969 | lsts = (reg >> 3) & 0xFF; | ||
970 | |||
971 | /* Check if linkstatus has detected a cable */ | ||
972 | if (lsts) | ||
973 | return false; | ||
974 | |||
975 | return true; | ||
976 | } | ||
977 | |||
978 | /* re-trigger charger detection again with watchdog re-kick. */ | ||
979 | static void ab8500_usb_vbus_turn_on_event_work(struct work_struct *work) | ||
980 | { | ||
981 | struct ab8500_usb *ab = container_of(work, struct ab8500_usb, | ||
982 | vbus_event_work); | ||
983 | |||
984 | if (ab->mode != USB_IDLE) | ||
985 | return; | ||
986 | |||
987 | abx500_set_register_interruptible(ab->dev, | ||
988 | AB8500_SYS_CTRL2_BLOCK, AB8500_MAIN_WD_CTRL_REG, | ||
989 | AB8500_BIT_WD_CTRL_ENABLE); | ||
990 | |||
991 | udelay(100); | ||
992 | |||
993 | abx500_set_register_interruptible(ab->dev, | ||
994 | AB8500_SYS_CTRL2_BLOCK, AB8500_MAIN_WD_CTRL_REG, | ||
995 | AB8500_BIT_WD_CTRL_ENABLE | AB8500_BIT_WD_CTRL_KICK); | ||
996 | |||
997 | udelay(100); | ||
998 | |||
999 | /* Disable Main watchdog */ | ||
1000 | abx500_set_register_interruptible(ab->dev, | ||
1001 | AB8500_SYS_CTRL2_BLOCK, AB8500_MAIN_WD_CTRL_REG, | ||
1002 | 0x0); | ||
1003 | |||
1004 | /* Enable USB Charger detection */ | ||
1005 | abx500_mask_and_set_register_interruptible(ab->dev, | ||
1006 | AB8500_USB, AB8540_VBUS_CTRL_REG, | ||
1007 | AB8540_BIT_VBUS_CTRL_CHARG_DET_ENA, | ||
1008 | AB8540_BIT_VBUS_CTRL_CHARG_DET_ENA); | ||
1009 | |||
1010 | ab->enabled_charging_detection = true; | ||
1011 | } | ||
1012 | |||
575 | static unsigned ab8500_eyediagram_workaroud(struct ab8500_usb *ab, unsigned mA) | 1013 | static unsigned ab8500_eyediagram_workaroud(struct ab8500_usb *ab, unsigned mA) |
576 | { | 1014 | { |
577 | /* | 1015 | /* |
@@ -627,7 +1065,7 @@ static int ab8500_usb_set_peripheral(struct usb_otg *otg, | |||
627 | * is fixed. | 1065 | * is fixed. |
628 | */ | 1066 | */ |
629 | 1067 | ||
630 | if ((ab->mode != USB_IDLE) && (!gadget)) { | 1068 | if ((ab->mode != USB_IDLE) && !gadget) { |
631 | ab->mode = USB_IDLE; | 1069 | ab->mode = USB_IDLE; |
632 | schedule_work(&ab->phy_dis_work); | 1070 | schedule_work(&ab->phy_dis_work); |
633 | } | 1071 | } |
@@ -651,7 +1089,7 @@ static int ab8500_usb_set_host(struct usb_otg *otg, struct usb_bus *host) | |||
651 | * is fixed. | 1089 | * is fixed. |
652 | */ | 1090 | */ |
653 | 1091 | ||
654 | if ((ab->mode != USB_IDLE) && (!host)) { | 1092 | if ((ab->mode != USB_IDLE) && !host) { |
655 | ab->mode = USB_IDLE; | 1093 | ab->mode = USB_IDLE; |
656 | schedule_work(&ab->phy_dis_work); | 1094 | schedule_work(&ab->phy_dis_work); |
657 | } | 1095 | } |
@@ -659,6 +1097,33 @@ static int ab8500_usb_set_host(struct usb_otg *otg, struct usb_bus *host) | |||
659 | return 0; | 1097 | return 0; |
660 | } | 1098 | } |
661 | 1099 | ||
1100 | static void ab8500_usb_restart_phy(struct ab8500_usb *ab) | ||
1101 | { | ||
1102 | abx500_mask_and_set_register_interruptible(ab->dev, | ||
1103 | AB8500_USB, AB8500_USB_PHY_CTRL_REG, | ||
1104 | AB8500_BIT_PHY_CTRL_DEVICE_EN, | ||
1105 | AB8500_BIT_PHY_CTRL_DEVICE_EN); | ||
1106 | |||
1107 | udelay(100); | ||
1108 | |||
1109 | abx500_mask_and_set_register_interruptible(ab->dev, | ||
1110 | AB8500_USB, AB8500_USB_PHY_CTRL_REG, | ||
1111 | AB8500_BIT_PHY_CTRL_DEVICE_EN, | ||
1112 | 0); | ||
1113 | |||
1114 | abx500_mask_and_set_register_interruptible(ab->dev, | ||
1115 | AB8500_USB, AB8500_USB_PHY_CTRL_REG, | ||
1116 | AB8500_BIT_PHY_CTRL_HOST_EN, | ||
1117 | AB8500_BIT_PHY_CTRL_HOST_EN); | ||
1118 | |||
1119 | udelay(100); | ||
1120 | |||
1121 | abx500_mask_and_set_register_interruptible(ab->dev, | ||
1122 | AB8500_USB, AB8500_USB_PHY_CTRL_REG, | ||
1123 | AB8500_BIT_PHY_CTRL_HOST_EN, | ||
1124 | 0); | ||
1125 | } | ||
1126 | |||
662 | static int ab8500_usb_regulator_get(struct ab8500_usb *ab) | 1127 | static int ab8500_usb_regulator_get(struct ab8500_usb *ab) |
663 | { | 1128 | { |
664 | int err; | 1129 | int err; |
@@ -693,48 +1158,197 @@ static int ab8500_usb_irq_setup(struct platform_device *pdev, | |||
693 | int err; | 1158 | int err; |
694 | int irq; | 1159 | int irq; |
695 | 1160 | ||
696 | irq = platform_get_irq_byname(pdev, "USB_LINK_STATUS"); | 1161 | if (ab->flags & AB8500_USB_FLAG_USE_LINK_STATUS_IRQ) { |
697 | if (irq < 0) { | 1162 | irq = platform_get_irq_byname(pdev, "USB_LINK_STATUS"); |
698 | dev_err(&pdev->dev, "Link status irq not found\n"); | 1163 | if (irq < 0) { |
699 | return irq; | 1164 | dev_err(&pdev->dev, "Link status irq not found\n"); |
700 | } | 1165 | return irq; |
701 | err = devm_request_threaded_irq(&pdev->dev, irq, NULL, | 1166 | } |
702 | ab8500_usb_link_status_irq, | 1167 | err = devm_request_threaded_irq(&pdev->dev, irq, NULL, |
703 | IRQF_NO_SUSPEND | IRQF_SHARED, "usb-link-status", ab); | 1168 | ab8500_usb_link_status_irq, |
704 | if (err < 0) { | 1169 | IRQF_NO_SUSPEND | IRQF_SHARED, |
705 | dev_err(ab->dev, "request_irq failed for link status irq\n"); | 1170 | "usb-link-status", ab); |
706 | return err; | 1171 | if (err < 0) { |
1172 | dev_err(ab->dev, "request_irq failed for link status irq\n"); | ||
1173 | return err; | ||
1174 | } | ||
707 | } | 1175 | } |
708 | 1176 | ||
709 | irq = platform_get_irq_byname(pdev, "ID_WAKEUP_F"); | 1177 | if (ab->flags & AB8500_USB_FLAG_USE_ID_WAKEUP_IRQ) { |
710 | if (irq < 0) { | 1178 | irq = platform_get_irq_byname(pdev, "ID_WAKEUP_F"); |
711 | dev_err(&pdev->dev, "ID fall irq not found\n"); | 1179 | if (irq < 0) { |
712 | return irq; | 1180 | dev_err(&pdev->dev, "ID fall irq not found\n"); |
713 | } | 1181 | return irq; |
714 | err = devm_request_threaded_irq(&pdev->dev, irq, NULL, | 1182 | } |
715 | ab8500_usb_disconnect_irq, | 1183 | err = devm_request_threaded_irq(&pdev->dev, irq, NULL, |
716 | IRQF_NO_SUSPEND | IRQF_SHARED, "usb-id-fall", ab); | 1184 | ab8500_usb_disconnect_irq, |
717 | if (err < 0) { | 1185 | IRQF_NO_SUSPEND | IRQF_SHARED, |
718 | dev_err(ab->dev, "request_irq failed for ID fall irq\n"); | 1186 | "usb-id-fall", ab); |
719 | return err; | 1187 | if (err < 0) { |
1188 | dev_err(ab->dev, "request_irq failed for ID fall irq\n"); | ||
1189 | return err; | ||
1190 | } | ||
720 | } | 1191 | } |
721 | 1192 | ||
722 | irq = platform_get_irq_byname(pdev, "VBUS_DET_F"); | 1193 | if (ab->flags & AB8500_USB_FLAG_USE_VBUS_DET_IRQ) { |
723 | if (irq < 0) { | 1194 | irq = platform_get_irq_byname(pdev, "VBUS_DET_F"); |
724 | dev_err(&pdev->dev, "VBUS fall irq not found\n"); | 1195 | if (irq < 0) { |
725 | return irq; | 1196 | dev_err(&pdev->dev, "VBUS fall irq not found\n"); |
726 | } | 1197 | return irq; |
727 | err = devm_request_threaded_irq(&pdev->dev, irq, NULL, | 1198 | } |
728 | ab8500_usb_disconnect_irq, | 1199 | err = devm_request_threaded_irq(&pdev->dev, irq, NULL, |
729 | IRQF_NO_SUSPEND | IRQF_SHARED, "usb-vbus-fall", ab); | 1200 | ab8500_usb_disconnect_irq, |
730 | if (err < 0) { | 1201 | IRQF_NO_SUSPEND | IRQF_SHARED, |
731 | dev_err(ab->dev, "request_irq failed for Vbus fall irq\n"); | 1202 | "usb-vbus-fall", ab); |
732 | return err; | 1203 | if (err < 0) { |
1204 | dev_err(ab->dev, "request_irq failed for Vbus fall irq\n"); | ||
1205 | return err; | ||
1206 | } | ||
733 | } | 1207 | } |
734 | 1208 | ||
735 | return 0; | 1209 | return 0; |
736 | } | 1210 | } |
737 | 1211 | ||
1212 | static void ab8500_usb_set_ab8500_tuning_values(struct ab8500_usb *ab) | ||
1213 | { | ||
1214 | int err; | ||
1215 | |||
1216 | /* Enable the PBT/Bank 0x12 access */ | ||
1217 | err = abx500_set_register_interruptible(ab->dev, | ||
1218 | AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS, 0x01); | ||
1219 | if (err < 0) | ||
1220 | dev_err(ab->dev, "Failed to enable bank12 access err=%d\n", | ||
1221 | err); | ||
1222 | |||
1223 | err = abx500_set_register_interruptible(ab->dev, | ||
1224 | AB8500_DEBUG, AB8500_USB_PHY_TUNE1, 0xC8); | ||
1225 | if (err < 0) | ||
1226 | dev_err(ab->dev, "Failed to set PHY_TUNE1 register err=%d\n", | ||
1227 | err); | ||
1228 | |||
1229 | err = abx500_set_register_interruptible(ab->dev, | ||
1230 | AB8500_DEBUG, AB8500_USB_PHY_TUNE2, 0x00); | ||
1231 | if (err < 0) | ||
1232 | dev_err(ab->dev, "Failed to set PHY_TUNE2 register err=%d\n", | ||
1233 | err); | ||
1234 | |||
1235 | err = abx500_set_register_interruptible(ab->dev, | ||
1236 | AB8500_DEBUG, AB8500_USB_PHY_TUNE3, 0x78); | ||
1237 | if (err < 0) | ||
1238 | dev_err(ab->dev, "Failed to set PHY_TUNE3 regester err=%d\n", | ||
1239 | err); | ||
1240 | |||
1241 | /* Switch to normal mode/disable Bank 0x12 access */ | ||
1242 | err = abx500_set_register_interruptible(ab->dev, | ||
1243 | AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS, 0x00); | ||
1244 | if (err < 0) | ||
1245 | dev_err(ab->dev, "Failed to switch bank12 access err=%d\n", | ||
1246 | err); | ||
1247 | } | ||
1248 | |||
1249 | static void ab8500_usb_set_ab8505_tuning_values(struct ab8500_usb *ab) | ||
1250 | { | ||
1251 | int err; | ||
1252 | |||
1253 | /* Enable the PBT/Bank 0x12 access */ | ||
1254 | err = abx500_mask_and_set_register_interruptible(ab->dev, | ||
1255 | AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS, | ||
1256 | 0x01, 0x01); | ||
1257 | if (err < 0) | ||
1258 | dev_err(ab->dev, "Failed to enable bank12 access err=%d\n", | ||
1259 | err); | ||
1260 | |||
1261 | err = abx500_mask_and_set_register_interruptible(ab->dev, | ||
1262 | AB8500_DEBUG, AB8500_USB_PHY_TUNE1, | ||
1263 | 0xC8, 0xC8); | ||
1264 | if (err < 0) | ||
1265 | dev_err(ab->dev, "Failed to set PHY_TUNE1 register err=%d\n", | ||
1266 | err); | ||
1267 | |||
1268 | err = abx500_mask_and_set_register_interruptible(ab->dev, | ||
1269 | AB8500_DEBUG, AB8500_USB_PHY_TUNE2, | ||
1270 | 0x60, 0x60); | ||
1271 | if (err < 0) | ||
1272 | dev_err(ab->dev, "Failed to set PHY_TUNE2 register err=%d\n", | ||
1273 | err); | ||
1274 | |||
1275 | err = abx500_mask_and_set_register_interruptible(ab->dev, | ||
1276 | AB8500_DEBUG, AB8500_USB_PHY_TUNE3, | ||
1277 | 0xFC, 0x80); | ||
1278 | |||
1279 | if (err < 0) | ||
1280 | dev_err(ab->dev, "Failed to set PHY_TUNE3 regester err=%d\n", | ||
1281 | err); | ||
1282 | |||
1283 | /* Switch to normal mode/disable Bank 0x12 access */ | ||
1284 | err = abx500_mask_and_set_register_interruptible(ab->dev, | ||
1285 | AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS, | ||
1286 | 0x00, 0x00); | ||
1287 | if (err < 0) | ||
1288 | dev_err(ab->dev, "Failed to switch bank12 access err=%d\n", | ||
1289 | err); | ||
1290 | } | ||
1291 | |||
1292 | static void ab8500_usb_set_ab8540_tuning_values(struct ab8500_usb *ab) | ||
1293 | { | ||
1294 | int err; | ||
1295 | |||
1296 | err = abx500_set_register_interruptible(ab->dev, | ||
1297 | AB8540_DEBUG, AB8500_USB_PHY_TUNE1, 0xCC); | ||
1298 | if (err < 0) | ||
1299 | dev_err(ab->dev, "Failed to set PHY_TUNE1 register ret=%d\n", | ||
1300 | err); | ||
1301 | |||
1302 | err = abx500_set_register_interruptible(ab->dev, | ||
1303 | AB8540_DEBUG, AB8500_USB_PHY_TUNE2, 0x60); | ||
1304 | if (err < 0) | ||
1305 | dev_err(ab->dev, "Failed to set PHY_TUNE2 register ret=%d\n", | ||
1306 | err); | ||
1307 | |||
1308 | err = abx500_set_register_interruptible(ab->dev, | ||
1309 | AB8540_DEBUG, AB8500_USB_PHY_TUNE3, 0x90); | ||
1310 | if (err < 0) | ||
1311 | dev_err(ab->dev, "Failed to set PHY_TUNE3 regester ret=%d\n", | ||
1312 | err); | ||
1313 | } | ||
1314 | |||
1315 | static void ab8500_usb_set_ab9540_tuning_values(struct ab8500_usb *ab) | ||
1316 | { | ||
1317 | int err; | ||
1318 | |||
1319 | /* Enable the PBT/Bank 0x12 access */ | ||
1320 | err = abx500_set_register_interruptible(ab->dev, | ||
1321 | AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS, 0x01); | ||
1322 | if (err < 0) | ||
1323 | dev_err(ab->dev, "Failed to enable bank12 access err=%d\n", | ||
1324 | err); | ||
1325 | |||
1326 | err = abx500_set_register_interruptible(ab->dev, | ||
1327 | AB8500_DEBUG, AB8500_USB_PHY_TUNE1, 0xC8); | ||
1328 | if (err < 0) | ||
1329 | dev_err(ab->dev, "Failed to set PHY_TUNE1 register err=%d\n", | ||
1330 | err); | ||
1331 | |||
1332 | err = abx500_set_register_interruptible(ab->dev, | ||
1333 | AB8500_DEBUG, AB8500_USB_PHY_TUNE2, 0x60); | ||
1334 | if (err < 0) | ||
1335 | dev_err(ab->dev, "Failed to set PHY_TUNE2 register err=%d\n", | ||
1336 | err); | ||
1337 | |||
1338 | err = abx500_set_register_interruptible(ab->dev, | ||
1339 | AB8500_DEBUG, AB8500_USB_PHY_TUNE3, 0x80); | ||
1340 | if (err < 0) | ||
1341 | dev_err(ab->dev, "Failed to set PHY_TUNE3 regester err=%d\n", | ||
1342 | err); | ||
1343 | |||
1344 | /* Switch to normal mode/disable Bank 0x12 access */ | ||
1345 | err = abx500_set_register_interruptible(ab->dev, | ||
1346 | AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS, 0x00); | ||
1347 | if (err < 0) | ||
1348 | dev_err(ab->dev, "Failed to switch bank12 access err=%d\n", | ||
1349 | err); | ||
1350 | } | ||
1351 | |||
738 | static int ab8500_usb_probe(struct platform_device *pdev) | 1352 | static int ab8500_usb_probe(struct platform_device *pdev) |
739 | { | 1353 | { |
740 | struct ab8500_usb *ab; | 1354 | struct ab8500_usb *ab; |
@@ -772,6 +1386,33 @@ static int ab8500_usb_probe(struct platform_device *pdev) | |||
772 | otg->set_host = ab8500_usb_set_host; | 1386 | otg->set_host = ab8500_usb_set_host; |
773 | otg->set_peripheral = ab8500_usb_set_peripheral; | 1387 | otg->set_peripheral = ab8500_usb_set_peripheral; |
774 | 1388 | ||
1389 | if (is_ab8500(ab->ab8500)) { | ||
1390 | ab->flags |= AB8500_USB_FLAG_USE_LINK_STATUS_IRQ | | ||
1391 | AB8500_USB_FLAG_USE_ID_WAKEUP_IRQ | | ||
1392 | AB8500_USB_FLAG_USE_VBUS_DET_IRQ | | ||
1393 | AB8500_USB_FLAG_REGULATOR_SET_VOLTAGE; | ||
1394 | } else if (is_ab8505(ab->ab8500)) { | ||
1395 | ab->flags |= AB8500_USB_FLAG_USE_LINK_STATUS_IRQ | | ||
1396 | AB8500_USB_FLAG_USE_ID_WAKEUP_IRQ | | ||
1397 | AB8500_USB_FLAG_USE_VBUS_DET_IRQ | | ||
1398 | AB8500_USB_FLAG_REGULATOR_SET_VOLTAGE; | ||
1399 | } else if (is_ab8540(ab->ab8500)) { | ||
1400 | ab->flags |= AB8500_USB_FLAG_USE_LINK_STATUS_IRQ | | ||
1401 | AB8500_USB_FLAG_USE_CHECK_VBUS_STATUS | | ||
1402 | AB8500_USB_FLAG_USE_VBUS_HOST_QUIRK | | ||
1403 | AB8500_USB_FLAG_REGULATOR_SET_VOLTAGE; | ||
1404 | } else if (is_ab9540(ab->ab8500)) { | ||
1405 | ab->flags |= AB8500_USB_FLAG_USE_LINK_STATUS_IRQ | | ||
1406 | AB8500_USB_FLAG_REGULATOR_SET_VOLTAGE; | ||
1407 | if (is_ab9540_2p0_or_earlier(ab->ab8500)) | ||
1408 | ab->flags |= AB8500_USB_FLAG_USE_ID_WAKEUP_IRQ | | ||
1409 | AB8500_USB_FLAG_USE_VBUS_DET_IRQ; | ||
1410 | } | ||
1411 | |||
1412 | /* Disable regulator voltage setting for AB8500 <= v2.0 */ | ||
1413 | if (is_ab8500_2p0_or_earlier(ab->ab8500)) | ||
1414 | ab->flags &= ~AB8500_USB_FLAG_REGULATOR_SET_VOLTAGE; | ||
1415 | |||
775 | platform_set_drvdata(pdev, ab); | 1416 | platform_set_drvdata(pdev, ab); |
776 | 1417 | ||
777 | ATOMIC_INIT_NOTIFIER_HEAD(&ab->phy.notifier); | 1418 | ATOMIC_INIT_NOTIFIER_HEAD(&ab->phy.notifier); |
@@ -779,10 +1420,18 @@ static int ab8500_usb_probe(struct platform_device *pdev) | |||
779 | /* all: Disable phy when called from set_host and set_peripheral */ | 1420 | /* all: Disable phy when called from set_host and set_peripheral */ |
780 | INIT_WORK(&ab->phy_dis_work, ab8500_usb_phy_disable_work); | 1421 | INIT_WORK(&ab->phy_dis_work, ab8500_usb_phy_disable_work); |
781 | 1422 | ||
1423 | INIT_WORK(&ab->vbus_event_work, ab8500_usb_vbus_turn_on_event_work); | ||
1424 | |||
782 | err = ab8500_usb_regulator_get(ab); | 1425 | err = ab8500_usb_regulator_get(ab); |
783 | if (err) | 1426 | if (err) |
784 | return err; | 1427 | return err; |
785 | 1428 | ||
1429 | ab->sysclk = devm_clk_get(ab->dev, "sysclk"); | ||
1430 | if (IS_ERR(ab->sysclk)) { | ||
1431 | dev_err(ab->dev, "Could not get sysclk.\n"); | ||
1432 | return PTR_ERR(ab->sysclk); | ||
1433 | } | ||
1434 | |||
786 | err = ab8500_usb_irq_setup(pdev, ab); | 1435 | err = ab8500_usb_irq_setup(pdev, ab); |
787 | if (err < 0) | 1436 | if (err < 0) |
788 | return err; | 1437 | return err; |
@@ -793,85 +1442,33 @@ static int ab8500_usb_probe(struct platform_device *pdev) | |||
793 | return err; | 1442 | return err; |
794 | } | 1443 | } |
795 | 1444 | ||
796 | /* Phy tuning values for AB8500 */ | 1445 | if (is_ab8500(ab->ab8500) && !is_ab8500_2p0_or_earlier(ab->ab8500)) |
797 | if (!is_ab8500_2p0_or_earlier(ab->ab8500)) { | 1446 | /* Phy tuning values for AB8500 > v2.0 */ |
798 | /* Enable the PBT/Bank 0x12 access */ | 1447 | ab8500_usb_set_ab8500_tuning_values(ab); |
799 | err = abx500_set_register_interruptible(ab->dev, | 1448 | else if (is_ab8505(ab->ab8500)) |
800 | AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS, 0x01); | 1449 | /* Phy tuning values for AB8505 */ |
801 | if (err < 0) | 1450 | ab8500_usb_set_ab8505_tuning_values(ab); |
802 | dev_err(ab->dev, "Failed to enable bank12 access err=%d\n", | 1451 | else if (is_ab8540(ab->ab8500)) |
803 | err); | 1452 | /* Phy tuning values for AB8540 */ |
804 | 1453 | ab8500_usb_set_ab8540_tuning_values(ab); | |
805 | err = abx500_set_register_interruptible(ab->dev, | 1454 | else if (is_ab9540(ab->ab8500)) |
806 | AB8500_DEBUG, AB8500_USB_PHY_TUNE1, 0xC8); | 1455 | /* Phy tuning values for AB9540 */ |
807 | if (err < 0) | 1456 | ab8500_usb_set_ab9540_tuning_values(ab); |
808 | dev_err(ab->dev, "Failed to set PHY_TUNE1 register err=%d\n", | ||
809 | err); | ||
810 | |||
811 | err = abx500_set_register_interruptible(ab->dev, | ||
812 | AB8500_DEBUG, AB8500_USB_PHY_TUNE2, 0x00); | ||
813 | if (err < 0) | ||
814 | dev_err(ab->dev, "Failed to set PHY_TUNE2 register err=%d\n", | ||
815 | err); | ||
816 | |||
817 | err = abx500_set_register_interruptible(ab->dev, | ||
818 | AB8500_DEBUG, AB8500_USB_PHY_TUNE3, 0x78); | ||
819 | if (err < 0) | ||
820 | dev_err(ab->dev, "Failed to set PHY_TUNE3 regester err=%d\n", | ||
821 | err); | ||
822 | |||
823 | /* Switch to normal mode/disable Bank 0x12 access */ | ||
824 | err = abx500_set_register_interruptible(ab->dev, | ||
825 | AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS, 0x00); | ||
826 | if (err < 0) | ||
827 | dev_err(ab->dev, "Failed to switch bank12 access err=%d\n", | ||
828 | err); | ||
829 | } | ||
830 | |||
831 | /* Phy tuning values for AB8505 */ | ||
832 | if (is_ab8505(ab->ab8500)) { | ||
833 | /* Enable the PBT/Bank 0x12 access */ | ||
834 | err = abx500_mask_and_set_register_interruptible(ab->dev, | ||
835 | AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS, | ||
836 | 0x01, 0x01); | ||
837 | if (err < 0) | ||
838 | dev_err(ab->dev, "Failed to enable bank12 access err=%d\n", | ||
839 | err); | ||
840 | |||
841 | err = abx500_mask_and_set_register_interruptible(ab->dev, | ||
842 | AB8500_DEBUG, AB8500_USB_PHY_TUNE1, | ||
843 | 0xC8, 0xC8); | ||
844 | if (err < 0) | ||
845 | dev_err(ab->dev, "Failed to set PHY_TUNE1 register err=%d\n", | ||
846 | err); | ||
847 | |||
848 | err = abx500_mask_and_set_register_interruptible(ab->dev, | ||
849 | AB8500_DEBUG, AB8500_USB_PHY_TUNE2, | ||
850 | 0x60, 0x60); | ||
851 | if (err < 0) | ||
852 | dev_err(ab->dev, "Failed to set PHY_TUNE2 register err=%d\n", | ||
853 | err); | ||
854 | |||
855 | err = abx500_mask_and_set_register_interruptible(ab->dev, | ||
856 | AB8500_DEBUG, AB8500_USB_PHY_TUNE3, | ||
857 | 0xFC, 0x80); | ||
858 | |||
859 | if (err < 0) | ||
860 | dev_err(ab->dev, "Failed to set PHY_TUNE3 regester err=%d\n", | ||
861 | err); | ||
862 | |||
863 | /* Switch to normal mode/disable Bank 0x12 access */ | ||
864 | err = abx500_mask_and_set_register_interruptible(ab->dev, | ||
865 | AB8500_DEVELOPMENT, AB8500_BANK12_ACCESS, | ||
866 | 0x00, 0x00); | ||
867 | if (err < 0) | ||
868 | dev_err(ab->dev, "Failed to switch bank12 access err=%d\n", | ||
869 | err); | ||
870 | } | ||
871 | 1457 | ||
872 | /* Needed to enable ID detection. */ | 1458 | /* Needed to enable ID detection. */ |
873 | ab8500_usb_wd_workaround(ab); | 1459 | ab8500_usb_wd_workaround(ab); |
874 | 1460 | ||
1461 | /* | ||
1462 | * This is required for usb-link-status to work properly when a | ||
1463 | * cable is connected at boot time. | ||
1464 | */ | ||
1465 | ab8500_usb_restart_phy(ab); | ||
1466 | |||
1467 | if (ab->flags & AB8500_USB_FLAG_USE_CHECK_VBUS_STATUS) { | ||
1468 | if (ab8500_usb_check_vbus_status(ab)) | ||
1469 | schedule_work(&ab->vbus_event_work); | ||
1470 | } | ||
1471 | |||
875 | abx500_usb_link_status_update(ab); | 1472 | abx500_usb_link_status_update(ab); |
876 | 1473 | ||
877 | dev_info(&pdev->dev, "revision 0x%2x driver initialized\n", rev); | 1474 | dev_info(&pdev->dev, "revision 0x%2x driver initialized\n", rev); |
@@ -884,6 +1481,7 @@ static int ab8500_usb_remove(struct platform_device *pdev) | |||
884 | struct ab8500_usb *ab = platform_get_drvdata(pdev); | 1481 | struct ab8500_usb *ab = platform_get_drvdata(pdev); |
885 | 1482 | ||
886 | cancel_work_sync(&ab->phy_dis_work); | 1483 | cancel_work_sync(&ab->phy_dis_work); |
1484 | cancel_work_sync(&ab->vbus_event_work); | ||
887 | 1485 | ||
888 | usb_remove_phy(&ab->phy); | 1486 | usb_remove_phy(&ab->phy); |
889 | 1487 | ||
@@ -895,11 +1493,20 @@ static int ab8500_usb_remove(struct platform_device *pdev) | |||
895 | return 0; | 1493 | return 0; |
896 | } | 1494 | } |
897 | 1495 | ||
1496 | static struct platform_device_id ab8500_usb_devtype[] = { | ||
1497 | { .name = "ab8500-usb", }, | ||
1498 | { .name = "ab8540-usb", }, | ||
1499 | { .name = "ab9540-usb", }, | ||
1500 | { /* sentinel */ } | ||
1501 | }; | ||
1502 | MODULE_DEVICE_TABLE(platform, ab8500_usb_devtype); | ||
1503 | |||
898 | static struct platform_driver ab8500_usb_driver = { | 1504 | static struct platform_driver ab8500_usb_driver = { |
899 | .probe = ab8500_usb_probe, | 1505 | .probe = ab8500_usb_probe, |
900 | .remove = ab8500_usb_remove, | 1506 | .remove = ab8500_usb_remove, |
1507 | .id_table = ab8500_usb_devtype, | ||
901 | .driver = { | 1508 | .driver = { |
902 | .name = "ab8500-usb", | 1509 | .name = "abx5x0-usb", |
903 | .owner = THIS_MODULE, | 1510 | .owner = THIS_MODULE, |
904 | }, | 1511 | }, |
905 | }; | 1512 | }; |
@@ -916,7 +1523,6 @@ static void __exit ab8500_usb_exit(void) | |||
916 | } | 1523 | } |
917 | module_exit(ab8500_usb_exit); | 1524 | module_exit(ab8500_usb_exit); |
918 | 1525 | ||
919 | MODULE_ALIAS("platform:ab8500_usb"); | ||
920 | MODULE_AUTHOR("ST-Ericsson AB"); | 1526 | MODULE_AUTHOR("ST-Ericsson AB"); |
921 | MODULE_DESCRIPTION("AB8500 usb transceiver driver"); | 1527 | MODULE_DESCRIPTION("AB8500 family usb transceiver driver"); |
922 | MODULE_LICENSE("GPL"); | 1528 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/usb/phy/phy-nop.c b/drivers/usb/phy/phy-nop.c index 638cc5dade35..55445e5d72e5 100644 --- a/drivers/usb/phy/phy-nop.c +++ b/drivers/usb/phy/phy-nop.c | |||
@@ -270,7 +270,7 @@ static struct platform_driver nop_usb_xceiv_driver = { | |||
270 | .driver = { | 270 | .driver = { |
271 | .name = "nop_usb_xceiv", | 271 | .name = "nop_usb_xceiv", |
272 | .owner = THIS_MODULE, | 272 | .owner = THIS_MODULE, |
273 | .of_match_table = of_match_ptr(nop_xceiv_dt_ids), | 273 | .of_match_table = nop_xceiv_dt_ids, |
274 | }, | 274 | }, |
275 | }; | 275 | }; |
276 | 276 | ||
diff --git a/drivers/usb/phy/phy-omap-usb3.c b/drivers/usb/phy/phy-omap-usb3.c index a6e60b1e102e..efe6e1464f45 100644 --- a/drivers/usb/phy/phy-omap-usb3.c +++ b/drivers/usb/phy/phy-omap-usb3.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | #include <linux/usb/omap_control_usb.h> | 28 | #include <linux/usb/omap_control_usb.h> |
29 | 29 | ||
30 | #define NUM_SYS_CLKS 5 | 30 | #define NUM_SYS_CLKS 6 |
31 | #define PLL_STATUS 0x00000004 | 31 | #define PLL_STATUS 0x00000004 |
32 | #define PLL_GO 0x00000008 | 32 | #define PLL_GO 0x00000008 |
33 | #define PLL_CONFIGURATION1 0x0000000C | 33 | #define PLL_CONFIGURATION1 0x0000000C |
@@ -62,6 +62,7 @@ enum sys_clk_rate { | |||
62 | CLK_RATE_12MHZ, | 62 | CLK_RATE_12MHZ, |
63 | CLK_RATE_16MHZ, | 63 | CLK_RATE_16MHZ, |
64 | CLK_RATE_19MHZ, | 64 | CLK_RATE_19MHZ, |
65 | CLK_RATE_20MHZ, | ||
65 | CLK_RATE_26MHZ, | 66 | CLK_RATE_26MHZ, |
66 | CLK_RATE_38MHZ | 67 | CLK_RATE_38MHZ |
67 | }; | 68 | }; |
@@ -72,6 +73,8 @@ static struct usb_dpll_params omap_usb3_dpll_params[NUM_SYS_CLKS] = { | |||
72 | {1172, 8, 4, 20, 65537}, /* 19.2 MHz */ | 73 | {1172, 8, 4, 20, 65537}, /* 19.2 MHz */ |
73 | {1250, 12, 4, 20, 0}, /* 26 MHz */ | 74 | {1250, 12, 4, 20, 0}, /* 26 MHz */ |
74 | {3125, 47, 4, 20, 92843}, /* 38.4 MHz */ | 75 | {3125, 47, 4, 20, 92843}, /* 38.4 MHz */ |
76 | {1000, 7, 4, 10, 0}, /* 20 MHz */ | ||
77 | |||
75 | }; | 78 | }; |
76 | 79 | ||
77 | static int omap_usb3_suspend(struct usb_phy *x, int suspend) | 80 | static int omap_usb3_suspend(struct usb_phy *x, int suspend) |
@@ -122,6 +125,8 @@ static inline enum sys_clk_rate __get_sys_clk_index(unsigned long rate) | |||
122 | return CLK_RATE_16MHZ; | 125 | return CLK_RATE_16MHZ; |
123 | case 19200000: | 126 | case 19200000: |
124 | return CLK_RATE_19MHZ; | 127 | return CLK_RATE_19MHZ; |
128 | case 20000000: | ||
129 | return CLK_RATE_20MHZ; | ||
125 | case 26000000: | 130 | case 26000000: |
126 | return CLK_RATE_26MHZ; | 131 | return CLK_RATE_26MHZ; |
127 | case 38400000: | 132 | case 38400000: |
diff --git a/drivers/usb/phy/phy-rcar-usb.c b/drivers/usb/phy/phy-rcar-usb.c index a35681b0c501..23c3dd30b2f0 100644 --- a/drivers/usb/phy/phy-rcar-usb.c +++ b/drivers/usb/phy/phy-rcar-usb.c | |||
@@ -161,7 +161,7 @@ static int rcar_usb_phy_probe(struct platform_device *pdev) | |||
161 | * CAUTION | 161 | * CAUTION |
162 | * | 162 | * |
163 | * Because this phy address is also mapped under OHCI/EHCI address area, | 163 | * Because this phy address is also mapped under OHCI/EHCI address area, |
164 | * this driver can't use devm_request_and_ioremap(dev, res) here | 164 | * this driver can't use devm_ioremap_resource(dev, res) here |
165 | */ | 165 | */ |
166 | reg0 = devm_ioremap_nocache(dev, res0->start, resource_size(res0)); | 166 | reg0 = devm_ioremap_nocache(dev, res0->start, resource_size(res0)); |
167 | reg1 = devm_ioremap_nocache(dev, res1->start, resource_size(res1)); | 167 | reg1 = devm_ioremap_nocache(dev, res1->start, resource_size(res1)); |
diff --git a/drivers/usb/phy/phy-samsung-usb.c b/drivers/usb/phy/phy-samsung-usb.c index 7b118ee5f5e4..ac025ca08425 100644 --- a/drivers/usb/phy/phy-samsung-usb.c +++ b/drivers/usb/phy/phy-samsung-usb.c | |||
@@ -73,7 +73,7 @@ EXPORT_SYMBOL_GPL(samsung_usbphy_parse_dt); | |||
73 | * Here 'on = true' would mean USB PHY block is isolated, hence | 73 | * Here 'on = true' would mean USB PHY block is isolated, hence |
74 | * de-activated and vice-versa. | 74 | * de-activated and vice-versa. |
75 | */ | 75 | */ |
76 | void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on) | 76 | void samsung_usbphy_set_isolation_4210(struct samsung_usbphy *sphy, bool on) |
77 | { | 77 | { |
78 | void __iomem *reg = NULL; | 78 | void __iomem *reg = NULL; |
79 | u32 reg_val; | 79 | u32 reg_val; |
@@ -84,32 +84,12 @@ void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on) | |||
84 | return; | 84 | return; |
85 | } | 85 | } |
86 | 86 | ||
87 | switch (sphy->drv_data->cpu_type) { | 87 | if (sphy->phy_type == USB_PHY_TYPE_DEVICE) { |
88 | case TYPE_S3C64XX: | 88 | reg = sphy->pmuregs + sphy->drv_data->devphy_reg_offset; |
89 | /* | 89 | en_mask = sphy->drv_data->devphy_en_mask; |
90 | * Do nothing: We will add here once S3C64xx goes for DT support | 90 | } else if (sphy->phy_type == USB_PHY_TYPE_HOST) { |
91 | */ | 91 | reg = sphy->pmuregs + sphy->drv_data->hostphy_reg_offset; |
92 | break; | 92 | en_mask = sphy->drv_data->hostphy_en_mask; |
93 | case TYPE_EXYNOS4210: | ||
94 | /* | ||
95 | * Fall through since exynos4210 and exynos5250 have similar | ||
96 | * register architecture: two separate registers for host and | ||
97 | * device phy control with enable bit at position 0. | ||
98 | */ | ||
99 | case TYPE_EXYNOS5250: | ||
100 | if (sphy->phy_type == USB_PHY_TYPE_DEVICE) { | ||
101 | reg = sphy->pmuregs + | ||
102 | sphy->drv_data->devphy_reg_offset; | ||
103 | en_mask = sphy->drv_data->devphy_en_mask; | ||
104 | } else if (sphy->phy_type == USB_PHY_TYPE_HOST) { | ||
105 | reg = sphy->pmuregs + | ||
106 | sphy->drv_data->hostphy_reg_offset; | ||
107 | en_mask = sphy->drv_data->hostphy_en_mask; | ||
108 | } | ||
109 | break; | ||
110 | default: | ||
111 | dev_err(sphy->dev, "Invalid SoC type\n"); | ||
112 | return; | ||
113 | } | 93 | } |
114 | 94 | ||
115 | reg_val = readl(reg); | 95 | reg_val = readl(reg); |
@@ -120,8 +100,13 @@ void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on) | |||
120 | reg_val |= en_mask; | 100 | reg_val |= en_mask; |
121 | 101 | ||
122 | writel(reg_val, reg); | 102 | writel(reg_val, reg); |
103 | |||
104 | if (sphy->drv_data->cpu_type == TYPE_EXYNOS4X12) { | ||
105 | writel(reg_val, sphy->pmuregs + EXYNOS4X12_PHY_HSIC_CTRL0); | ||
106 | writel(reg_val, sphy->pmuregs + EXYNOS4X12_PHY_HSIC_CTRL1); | ||
107 | } | ||
123 | } | 108 | } |
124 | EXPORT_SYMBOL_GPL(samsung_usbphy_set_isolation); | 109 | EXPORT_SYMBOL_GPL(samsung_usbphy_set_isolation_4210); |
125 | 110 | ||
126 | /* | 111 | /* |
127 | * Configure the mode of working of usb-phy here: HOST/DEVICE. | 112 | * Configure the mode of working of usb-phy here: HOST/DEVICE. |
@@ -162,73 +147,93 @@ int samsung_usbphy_set_type(struct usb_phy *phy, | |||
162 | } | 147 | } |
163 | EXPORT_SYMBOL_GPL(samsung_usbphy_set_type); | 148 | EXPORT_SYMBOL_GPL(samsung_usbphy_set_type); |
164 | 149 | ||
150 | int samsung_usbphy_rate_to_clksel_64xx(struct samsung_usbphy *sphy, | ||
151 | unsigned long rate) | ||
152 | { | ||
153 | unsigned int clksel; | ||
154 | |||
155 | switch (rate) { | ||
156 | case 12 * MHZ: | ||
157 | clksel = PHYCLK_CLKSEL_12M; | ||
158 | break; | ||
159 | case 24 * MHZ: | ||
160 | clksel = PHYCLK_CLKSEL_24M; | ||
161 | break; | ||
162 | case 48 * MHZ: | ||
163 | clksel = PHYCLK_CLKSEL_48M; | ||
164 | break; | ||
165 | default: | ||
166 | dev_err(sphy->dev, | ||
167 | "Invalid reference clock frequency: %lu\n", rate); | ||
168 | return -EINVAL; | ||
169 | } | ||
170 | |||
171 | return clksel; | ||
172 | } | ||
173 | EXPORT_SYMBOL_GPL(samsung_usbphy_rate_to_clksel_64xx); | ||
174 | |||
175 | int samsung_usbphy_rate_to_clksel_4x12(struct samsung_usbphy *sphy, | ||
176 | unsigned long rate) | ||
177 | { | ||
178 | unsigned int clksel; | ||
179 | |||
180 | switch (rate) { | ||
181 | case 9600 * KHZ: | ||
182 | clksel = FSEL_CLKSEL_9600K; | ||
183 | break; | ||
184 | case 10 * MHZ: | ||
185 | clksel = FSEL_CLKSEL_10M; | ||
186 | break; | ||
187 | case 12 * MHZ: | ||
188 | clksel = FSEL_CLKSEL_12M; | ||
189 | break; | ||
190 | case 19200 * KHZ: | ||
191 | clksel = FSEL_CLKSEL_19200K; | ||
192 | break; | ||
193 | case 20 * MHZ: | ||
194 | clksel = FSEL_CLKSEL_20M; | ||
195 | break; | ||
196 | case 24 * MHZ: | ||
197 | clksel = FSEL_CLKSEL_24M; | ||
198 | break; | ||
199 | case 50 * MHZ: | ||
200 | clksel = FSEL_CLKSEL_50M; | ||
201 | break; | ||
202 | default: | ||
203 | dev_err(sphy->dev, | ||
204 | "Invalid reference clock frequency: %lu\n", rate); | ||
205 | return -EINVAL; | ||
206 | } | ||
207 | |||
208 | return clksel; | ||
209 | } | ||
210 | EXPORT_SYMBOL_GPL(samsung_usbphy_rate_to_clksel_4x12); | ||
211 | |||
165 | /* | 212 | /* |
166 | * Returns reference clock frequency selection value | 213 | * Returns reference clock frequency selection value |
167 | */ | 214 | */ |
168 | int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy) | 215 | int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy) |
169 | { | 216 | { |
170 | struct clk *ref_clk; | 217 | struct clk *ref_clk; |
171 | int refclk_freq = 0; | 218 | unsigned long rate; |
219 | int refclk_freq; | ||
172 | 220 | ||
173 | /* | 221 | /* |
174 | * In exynos5250 USB host and device PHY use | 222 | * In exynos5250 USB host and device PHY use |
175 | * external crystal clock XXTI | 223 | * external crystal clock XXTI |
176 | */ | 224 | */ |
177 | if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) | 225 | if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) |
178 | ref_clk = devm_clk_get(sphy->dev, "ext_xtal"); | 226 | ref_clk = clk_get(sphy->dev, "ext_xtal"); |
179 | else | 227 | else |
180 | ref_clk = devm_clk_get(sphy->dev, "xusbxti"); | 228 | ref_clk = clk_get(sphy->dev, "xusbxti"); |
181 | if (IS_ERR(ref_clk)) { | 229 | if (IS_ERR(ref_clk)) { |
182 | dev_err(sphy->dev, "Failed to get reference clock\n"); | 230 | dev_err(sphy->dev, "Failed to get reference clock\n"); |
183 | return PTR_ERR(ref_clk); | 231 | return PTR_ERR(ref_clk); |
184 | } | 232 | } |
185 | 233 | ||
186 | if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) { | 234 | rate = clk_get_rate(ref_clk); |
187 | /* set clock frequency for PLL */ | 235 | refclk_freq = sphy->drv_data->rate_to_clksel(sphy, rate); |
188 | switch (clk_get_rate(ref_clk)) { | 236 | |
189 | case 9600 * KHZ: | ||
190 | refclk_freq = FSEL_CLKSEL_9600K; | ||
191 | break; | ||
192 | case 10 * MHZ: | ||
193 | refclk_freq = FSEL_CLKSEL_10M; | ||
194 | break; | ||
195 | case 12 * MHZ: | ||
196 | refclk_freq = FSEL_CLKSEL_12M; | ||
197 | break; | ||
198 | case 19200 * KHZ: | ||
199 | refclk_freq = FSEL_CLKSEL_19200K; | ||
200 | break; | ||
201 | case 20 * MHZ: | ||
202 | refclk_freq = FSEL_CLKSEL_20M; | ||
203 | break; | ||
204 | case 50 * MHZ: | ||
205 | refclk_freq = FSEL_CLKSEL_50M; | ||
206 | break; | ||
207 | case 24 * MHZ: | ||
208 | default: | ||
209 | /* default reference clock */ | ||
210 | refclk_freq = FSEL_CLKSEL_24M; | ||
211 | break; | ||
212 | } | ||
213 | } else { | ||
214 | switch (clk_get_rate(ref_clk)) { | ||
215 | case 12 * MHZ: | ||
216 | refclk_freq = PHYCLK_CLKSEL_12M; | ||
217 | break; | ||
218 | case 24 * MHZ: | ||
219 | refclk_freq = PHYCLK_CLKSEL_24M; | ||
220 | break; | ||
221 | case 48 * MHZ: | ||
222 | refclk_freq = PHYCLK_CLKSEL_48M; | ||
223 | break; | ||
224 | default: | ||
225 | if (sphy->drv_data->cpu_type == TYPE_S3C64XX) | ||
226 | refclk_freq = PHYCLK_CLKSEL_48M; | ||
227 | else | ||
228 | refclk_freq = PHYCLK_CLKSEL_24M; | ||
229 | break; | ||
230 | } | ||
231 | } | ||
232 | clk_put(ref_clk); | 237 | clk_put(ref_clk); |
233 | 238 | ||
234 | return refclk_freq; | 239 | return refclk_freq; |
diff --git a/drivers/usb/phy/phy-samsung-usb.h b/drivers/usb/phy/phy-samsung-usb.h index 70a9cae5e37f..68771bfd1825 100644 --- a/drivers/usb/phy/phy-samsung-usb.h +++ b/drivers/usb/phy/phy-samsung-usb.h | |||
@@ -47,6 +47,16 @@ | |||
47 | #define RSTCON_HLINK_SWRST (0x1 << 1) | 47 | #define RSTCON_HLINK_SWRST (0x1 << 1) |
48 | #define RSTCON_SWRST (0x1 << 0) | 48 | #define RSTCON_SWRST (0x1 << 0) |
49 | 49 | ||
50 | /* EXYNOS4X12 */ | ||
51 | #define EXYNOS4X12_PHY_HSIC_CTRL0 (0x04) | ||
52 | #define EXYNOS4X12_PHY_HSIC_CTRL1 (0x08) | ||
53 | |||
54 | #define PHYPWR_NORMAL_MASK_HSIC1 (0x7 << 12) | ||
55 | #define PHYPWR_NORMAL_MASK_HSIC0 (0x7 << 9) | ||
56 | #define PHYPWR_NORMAL_MASK_PHY1 (0x7 << 6) | ||
57 | |||
58 | #define RSTCON_HOSTPHY_SWRST (0xf << 3) | ||
59 | |||
50 | /* EXYNOS5 */ | 60 | /* EXYNOS5 */ |
51 | #define EXYNOS5_PHY_HOST_CTRL0 (0x00) | 61 | #define EXYNOS5_PHY_HOST_CTRL0 (0x00) |
52 | 62 | ||
@@ -241,9 +251,12 @@ | |||
241 | enum samsung_cpu_type { | 251 | enum samsung_cpu_type { |
242 | TYPE_S3C64XX, | 252 | TYPE_S3C64XX, |
243 | TYPE_EXYNOS4210, | 253 | TYPE_EXYNOS4210, |
254 | TYPE_EXYNOS4X12, | ||
244 | TYPE_EXYNOS5250, | 255 | TYPE_EXYNOS5250, |
245 | }; | 256 | }; |
246 | 257 | ||
258 | struct samsung_usbphy; | ||
259 | |||
247 | /* | 260 | /* |
248 | * struct samsung_usbphy_drvdata - driver data for various SoC variants | 261 | * struct samsung_usbphy_drvdata - driver data for various SoC variants |
249 | * @cpu_type: machine identifier | 262 | * @cpu_type: machine identifier |
@@ -268,6 +281,10 @@ struct samsung_usbphy_drvdata { | |||
268 | int hostphy_en_mask; | 281 | int hostphy_en_mask; |
269 | u32 devphy_reg_offset; | 282 | u32 devphy_reg_offset; |
270 | u32 hostphy_reg_offset; | 283 | u32 hostphy_reg_offset; |
284 | int (*rate_to_clksel)(struct samsung_usbphy *, unsigned long); | ||
285 | void (*set_isolation)(struct samsung_usbphy *, bool); | ||
286 | void (*phy_enable)(struct samsung_usbphy *); | ||
287 | void (*phy_disable)(struct samsung_usbphy *); | ||
271 | }; | 288 | }; |
272 | 289 | ||
273 | /* | 290 | /* |
@@ -320,8 +337,13 @@ static inline const struct samsung_usbphy_drvdata | |||
320 | } | 337 | } |
321 | 338 | ||
322 | extern int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy); | 339 | extern int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy); |
323 | extern void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on); | 340 | extern void samsung_usbphy_set_isolation_4210(struct samsung_usbphy *sphy, |
341 | bool on); | ||
324 | extern void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy); | 342 | extern void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy); |
325 | extern int samsung_usbphy_set_type(struct usb_phy *phy, | 343 | extern int samsung_usbphy_set_type(struct usb_phy *phy, |
326 | enum samsung_usb_phy_type phy_type); | 344 | enum samsung_usb_phy_type phy_type); |
327 | extern int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy); | 345 | extern int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy); |
346 | extern int samsung_usbphy_rate_to_clksel_64xx(struct samsung_usbphy *sphy, | ||
347 | unsigned long rate); | ||
348 | extern int samsung_usbphy_rate_to_clksel_4x12(struct samsung_usbphy *sphy, | ||
349 | unsigned long rate); | ||
diff --git a/drivers/usb/phy/phy-samsung-usb2.c b/drivers/usb/phy/phy-samsung-usb2.c index 9d5e273abcc7..1011c16ade7e 100644 --- a/drivers/usb/phy/phy-samsung-usb2.c +++ b/drivers/usb/phy/phy-samsung-usb2.c | |||
@@ -176,6 +176,11 @@ static void samsung_usb2phy_enable(struct samsung_usbphy *sphy) | |||
176 | phypwr &= ~PHYPWR_NORMAL_MASK; | 176 | phypwr &= ~PHYPWR_NORMAL_MASK; |
177 | rstcon |= RSTCON_SWRST; | 177 | rstcon |= RSTCON_SWRST; |
178 | break; | 178 | break; |
179 | case TYPE_EXYNOS4X12: | ||
180 | phypwr &= ~(PHYPWR_NORMAL_MASK_HSIC0 | | ||
181 | PHYPWR_NORMAL_MASK_HSIC1 | | ||
182 | PHYPWR_NORMAL_MASK_PHY1); | ||
183 | rstcon |= RSTCON_HOSTPHY_SWRST; | ||
179 | case TYPE_EXYNOS4210: | 184 | case TYPE_EXYNOS4210: |
180 | phypwr &= ~PHYPWR_NORMAL_MASK_PHY0; | 185 | phypwr &= ~PHYPWR_NORMAL_MASK_PHY0; |
181 | rstcon |= RSTCON_SWRST; | 186 | rstcon |= RSTCON_SWRST; |
@@ -189,6 +194,8 @@ static void samsung_usb2phy_enable(struct samsung_usbphy *sphy) | |||
189 | /* reset all ports of PHY and Link */ | 194 | /* reset all ports of PHY and Link */ |
190 | writel(rstcon, regs + SAMSUNG_RSTCON); | 195 | writel(rstcon, regs + SAMSUNG_RSTCON); |
191 | udelay(10); | 196 | udelay(10); |
197 | if (sphy->drv_data->cpu_type == TYPE_EXYNOS4X12) | ||
198 | rstcon &= ~RSTCON_HOSTPHY_SWRST; | ||
192 | rstcon &= ~RSTCON_SWRST; | 199 | rstcon &= ~RSTCON_SWRST; |
193 | writel(rstcon, regs + SAMSUNG_RSTCON); | 200 | writel(rstcon, regs + SAMSUNG_RSTCON); |
194 | } | 201 | } |
@@ -239,6 +246,10 @@ static void samsung_usb2phy_disable(struct samsung_usbphy *sphy) | |||
239 | case TYPE_S3C64XX: | 246 | case TYPE_S3C64XX: |
240 | phypwr |= PHYPWR_NORMAL_MASK; | 247 | phypwr |= PHYPWR_NORMAL_MASK; |
241 | break; | 248 | break; |
249 | case TYPE_EXYNOS4X12: | ||
250 | phypwr |= (PHYPWR_NORMAL_MASK_HSIC0 | | ||
251 | PHYPWR_NORMAL_MASK_HSIC1 | | ||
252 | PHYPWR_NORMAL_MASK_PHY1); | ||
242 | case TYPE_EXYNOS4210: | 253 | case TYPE_EXYNOS4210: |
243 | phypwr |= PHYPWR_NORMAL_MASK_PHY0; | 254 | phypwr |= PHYPWR_NORMAL_MASK_PHY0; |
244 | default: | 255 | default: |
@@ -284,17 +295,14 @@ static int samsung_usb2phy_init(struct usb_phy *phy) | |||
284 | /* Disable phy isolation */ | 295 | /* Disable phy isolation */ |
285 | if (sphy->plat && sphy->plat->pmu_isolation) | 296 | if (sphy->plat && sphy->plat->pmu_isolation) |
286 | sphy->plat->pmu_isolation(false); | 297 | sphy->plat->pmu_isolation(false); |
287 | else | 298 | else if (sphy->drv_data->set_isolation) |
288 | samsung_usbphy_set_isolation(sphy, false); | 299 | sphy->drv_data->set_isolation(sphy, false); |
289 | 300 | ||
290 | /* Selecting Host/OTG mode; After reset USB2.0PHY_CFG: HOST */ | 301 | /* Selecting Host/OTG mode; After reset USB2.0PHY_CFG: HOST */ |
291 | samsung_usbphy_cfg_sel(sphy); | 302 | samsung_usbphy_cfg_sel(sphy); |
292 | 303 | ||
293 | /* Initialize usb phy registers */ | 304 | /* Initialize usb phy registers */ |
294 | if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) | 305 | sphy->drv_data->phy_enable(sphy); |
295 | samsung_exynos5_usb2phy_enable(sphy); | ||
296 | else | ||
297 | samsung_usb2phy_enable(sphy); | ||
298 | 306 | ||
299 | spin_unlock_irqrestore(&sphy->lock, flags); | 307 | spin_unlock_irqrestore(&sphy->lock, flags); |
300 | 308 | ||
@@ -334,16 +342,13 @@ static void samsung_usb2phy_shutdown(struct usb_phy *phy) | |||
334 | } | 342 | } |
335 | 343 | ||
336 | /* De-initialize usb phy registers */ | 344 | /* De-initialize usb phy registers */ |
337 | if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) | 345 | sphy->drv_data->phy_disable(sphy); |
338 | samsung_exynos5_usb2phy_disable(sphy); | ||
339 | else | ||
340 | samsung_usb2phy_disable(sphy); | ||
341 | 346 | ||
342 | /* Enable phy isolation */ | 347 | /* Enable phy isolation */ |
343 | if (sphy->plat && sphy->plat->pmu_isolation) | 348 | if (sphy->plat && sphy->plat->pmu_isolation) |
344 | sphy->plat->pmu_isolation(true); | 349 | sphy->plat->pmu_isolation(true); |
345 | else | 350 | else if (sphy->drv_data->set_isolation) |
346 | samsung_usbphy_set_isolation(sphy, true); | 351 | sphy->drv_data->set_isolation(sphy, true); |
347 | 352 | ||
348 | spin_unlock_irqrestore(&sphy->lock, flags); | 353 | spin_unlock_irqrestore(&sphy->lock, flags); |
349 | 354 | ||
@@ -408,7 +413,10 @@ static int samsung_usb2phy_probe(struct platform_device *pdev) | |||
408 | sphy->phy.label = "samsung-usb2phy"; | 413 | sphy->phy.label = "samsung-usb2phy"; |
409 | sphy->phy.init = samsung_usb2phy_init; | 414 | sphy->phy.init = samsung_usb2phy_init; |
410 | sphy->phy.shutdown = samsung_usb2phy_shutdown; | 415 | sphy->phy.shutdown = samsung_usb2phy_shutdown; |
411 | sphy->ref_clk_freq = samsung_usbphy_get_refclk_freq(sphy); | 416 | |
417 | sphy->ref_clk_freq = samsung_usbphy_get_refclk_freq(sphy); | ||
418 | if (sphy->ref_clk_freq < 0) | ||
419 | return -EINVAL; | ||
412 | 420 | ||
413 | sphy->phy.otg = otg; | 421 | sphy->phy.otg = otg; |
414 | sphy->phy.otg->phy = &sphy->phy; | 422 | sphy->phy.otg->phy = &sphy->phy; |
@@ -438,18 +446,40 @@ static int samsung_usb2phy_remove(struct platform_device *pdev) | |||
438 | static const struct samsung_usbphy_drvdata usb2phy_s3c64xx = { | 446 | static const struct samsung_usbphy_drvdata usb2phy_s3c64xx = { |
439 | .cpu_type = TYPE_S3C64XX, | 447 | .cpu_type = TYPE_S3C64XX, |
440 | .devphy_en_mask = S3C64XX_USBPHY_ENABLE, | 448 | .devphy_en_mask = S3C64XX_USBPHY_ENABLE, |
449 | .rate_to_clksel = samsung_usbphy_rate_to_clksel_64xx, | ||
450 | .set_isolation = NULL, /* TODO */ | ||
451 | .phy_enable = samsung_usb2phy_enable, | ||
452 | .phy_disable = samsung_usb2phy_disable, | ||
441 | }; | 453 | }; |
442 | 454 | ||
443 | static const struct samsung_usbphy_drvdata usb2phy_exynos4 = { | 455 | static const struct samsung_usbphy_drvdata usb2phy_exynos4 = { |
444 | .cpu_type = TYPE_EXYNOS4210, | 456 | .cpu_type = TYPE_EXYNOS4210, |
445 | .devphy_en_mask = EXYNOS_USBPHY_ENABLE, | 457 | .devphy_en_mask = EXYNOS_USBPHY_ENABLE, |
446 | .hostphy_en_mask = EXYNOS_USBPHY_ENABLE, | 458 | .hostphy_en_mask = EXYNOS_USBPHY_ENABLE, |
459 | .rate_to_clksel = samsung_usbphy_rate_to_clksel_64xx, | ||
460 | .set_isolation = samsung_usbphy_set_isolation_4210, | ||
461 | .phy_enable = samsung_usb2phy_enable, | ||
462 | .phy_disable = samsung_usb2phy_disable, | ||
463 | }; | ||
464 | |||
465 | static const struct samsung_usbphy_drvdata usb2phy_exynos4x12 = { | ||
466 | .cpu_type = TYPE_EXYNOS4X12, | ||
467 | .devphy_en_mask = EXYNOS_USBPHY_ENABLE, | ||
468 | .hostphy_en_mask = EXYNOS_USBPHY_ENABLE, | ||
469 | .rate_to_clksel = samsung_usbphy_rate_to_clksel_4x12, | ||
470 | .set_isolation = samsung_usbphy_set_isolation_4210, | ||
471 | .phy_enable = samsung_usb2phy_enable, | ||
472 | .phy_disable = samsung_usb2phy_disable, | ||
447 | }; | 473 | }; |
448 | 474 | ||
449 | static struct samsung_usbphy_drvdata usb2phy_exynos5 = { | 475 | static struct samsung_usbphy_drvdata usb2phy_exynos5 = { |
450 | .cpu_type = TYPE_EXYNOS5250, | 476 | .cpu_type = TYPE_EXYNOS5250, |
451 | .hostphy_en_mask = EXYNOS_USBPHY_ENABLE, | 477 | .hostphy_en_mask = EXYNOS_USBPHY_ENABLE, |
452 | .hostphy_reg_offset = EXYNOS_USBHOST_PHY_CTRL_OFFSET, | 478 | .hostphy_reg_offset = EXYNOS_USBHOST_PHY_CTRL_OFFSET, |
479 | .rate_to_clksel = samsung_usbphy_rate_to_clksel_4x12, | ||
480 | .set_isolation = samsung_usbphy_set_isolation_4210, | ||
481 | .phy_enable = samsung_exynos5_usb2phy_enable, | ||
482 | .phy_disable = samsung_exynos5_usb2phy_disable, | ||
453 | }; | 483 | }; |
454 | 484 | ||
455 | #ifdef CONFIG_OF | 485 | #ifdef CONFIG_OF |
@@ -461,6 +491,9 @@ static const struct of_device_id samsung_usbphy_dt_match[] = { | |||
461 | .compatible = "samsung,exynos4210-usb2phy", | 491 | .compatible = "samsung,exynos4210-usb2phy", |
462 | .data = &usb2phy_exynos4, | 492 | .data = &usb2phy_exynos4, |
463 | }, { | 493 | }, { |
494 | .compatible = "samsung,exynos4x12-usb2phy", | ||
495 | .data = &usb2phy_exynos4x12, | ||
496 | }, { | ||
464 | .compatible = "samsung,exynos5250-usb2phy", | 497 | .compatible = "samsung,exynos5250-usb2phy", |
465 | .data = &usb2phy_exynos5 | 498 | .data = &usb2phy_exynos5 |
466 | }, | 499 | }, |
@@ -477,6 +510,9 @@ static struct platform_device_id samsung_usbphy_driver_ids[] = { | |||
477 | .name = "exynos4210-usb2phy", | 510 | .name = "exynos4210-usb2phy", |
478 | .driver_data = (unsigned long)&usb2phy_exynos4, | 511 | .driver_data = (unsigned long)&usb2phy_exynos4, |
479 | }, { | 512 | }, { |
513 | .name = "exynos4x12-usb2phy", | ||
514 | .driver_data = (unsigned long)&usb2phy_exynos4x12, | ||
515 | }, { | ||
480 | .name = "exynos5250-usb2phy", | 516 | .name = "exynos5250-usb2phy", |
481 | .driver_data = (unsigned long)&usb2phy_exynos5, | 517 | .driver_data = (unsigned long)&usb2phy_exynos5, |
482 | }, | 518 | }, |
diff --git a/drivers/usb/phy/phy-samsung-usb3.c b/drivers/usb/phy/phy-samsung-usb3.c index 5a9efcbcb532..300e0cf5e31f 100644 --- a/drivers/usb/phy/phy-samsung-usb3.c +++ b/drivers/usb/phy/phy-samsung-usb3.c | |||
@@ -65,7 +65,7 @@ static u32 samsung_usb3phy_set_refclk(struct samsung_usbphy *sphy) | |||
65 | return reg; | 65 | return reg; |
66 | } | 66 | } |
67 | 67 | ||
68 | static int samsung_exynos5_usb3phy_enable(struct samsung_usbphy *sphy) | 68 | static void samsung_exynos5_usb3phy_enable(struct samsung_usbphy *sphy) |
69 | { | 69 | { |
70 | void __iomem *regs = sphy->regs; | 70 | void __iomem *regs = sphy->regs; |
71 | u32 phyparam0; | 71 | u32 phyparam0; |
@@ -133,8 +133,6 @@ static int samsung_exynos5_usb3phy_enable(struct samsung_usbphy *sphy) | |||
133 | 133 | ||
134 | phyclkrst &= ~(PHYCLKRST_PORTRESET); | 134 | phyclkrst &= ~(PHYCLKRST_PORTRESET); |
135 | writel(phyclkrst, regs + EXYNOS5_DRD_PHYCLKRST); | 135 | writel(phyclkrst, regs + EXYNOS5_DRD_PHYCLKRST); |
136 | |||
137 | return 0; | ||
138 | } | 136 | } |
139 | 137 | ||
140 | static void samsung_exynos5_usb3phy_disable(struct samsung_usbphy *sphy) | 138 | static void samsung_exynos5_usb3phy_disable(struct samsung_usbphy *sphy) |
@@ -184,10 +182,11 @@ static int samsung_usb3phy_init(struct usb_phy *phy) | |||
184 | samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE); | 182 | samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE); |
185 | 183 | ||
186 | /* Disable phy isolation */ | 184 | /* Disable phy isolation */ |
187 | samsung_usbphy_set_isolation(sphy, false); | 185 | if (sphy->drv_data->set_isolation) |
186 | sphy->drv_data->set_isolation(sphy, false); | ||
188 | 187 | ||
189 | /* Initialize usb phy registers */ | 188 | /* Initialize usb phy registers */ |
190 | samsung_exynos5_usb3phy_enable(sphy); | 189 | sphy->drv_data->phy_enable(sphy); |
191 | 190 | ||
192 | spin_unlock_irqrestore(&sphy->lock, flags); | 191 | spin_unlock_irqrestore(&sphy->lock, flags); |
193 | 192 | ||
@@ -218,10 +217,11 @@ static void samsung_usb3phy_shutdown(struct usb_phy *phy) | |||
218 | samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE); | 217 | samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE); |
219 | 218 | ||
220 | /* De-initialize usb phy registers */ | 219 | /* De-initialize usb phy registers */ |
221 | samsung_exynos5_usb3phy_disable(sphy); | 220 | sphy->drv_data->phy_disable(sphy); |
222 | 221 | ||
223 | /* Enable phy isolation */ | 222 | /* Enable phy isolation */ |
224 | samsung_usbphy_set_isolation(sphy, true); | 223 | if (sphy->drv_data->set_isolation) |
224 | sphy->drv_data->set_isolation(sphy, true); | ||
225 | 225 | ||
226 | spin_unlock_irqrestore(&sphy->lock, flags); | 226 | spin_unlock_irqrestore(&sphy->lock, flags); |
227 | 227 | ||
@@ -274,7 +274,10 @@ static int samsung_usb3phy_probe(struct platform_device *pdev) | |||
274 | sphy->phy.init = samsung_usb3phy_init; | 274 | sphy->phy.init = samsung_usb3phy_init; |
275 | sphy->phy.shutdown = samsung_usb3phy_shutdown; | 275 | sphy->phy.shutdown = samsung_usb3phy_shutdown; |
276 | sphy->drv_data = samsung_usbphy_get_driver_data(pdev); | 276 | sphy->drv_data = samsung_usbphy_get_driver_data(pdev); |
277 | sphy->ref_clk_freq = samsung_usbphy_get_refclk_freq(sphy); | 277 | |
278 | sphy->ref_clk_freq = samsung_usbphy_get_refclk_freq(sphy); | ||
279 | if (sphy->ref_clk_freq < 0) | ||
280 | return -EINVAL; | ||
278 | 281 | ||
279 | spin_lock_init(&sphy->lock); | 282 | spin_lock_init(&sphy->lock); |
280 | 283 | ||
@@ -300,6 +303,10 @@ static int samsung_usb3phy_remove(struct platform_device *pdev) | |||
300 | static struct samsung_usbphy_drvdata usb3phy_exynos5 = { | 303 | static struct samsung_usbphy_drvdata usb3phy_exynos5 = { |
301 | .cpu_type = TYPE_EXYNOS5250, | 304 | .cpu_type = TYPE_EXYNOS5250, |
302 | .devphy_en_mask = EXYNOS_USBPHY_ENABLE, | 305 | .devphy_en_mask = EXYNOS_USBPHY_ENABLE, |
306 | .rate_to_clksel = samsung_usbphy_rate_to_clksel_4x12, | ||
307 | .set_isolation = samsung_usbphy_set_isolation_4210, | ||
308 | .phy_enable = samsung_exynos5_usb3phy_enable, | ||
309 | .phy_disable = samsung_exynos5_usb3phy_disable, | ||
303 | }; | 310 | }; |
304 | 311 | ||
305 | #ifdef CONFIG_OF | 312 | #ifdef CONFIG_OF |
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c index 17d811292f3a..cec0855ed248 100644 --- a/drivers/usb/phy/phy-tegra-usb.c +++ b/drivers/usb/phy/phy-tegra-usb.c | |||
@@ -1,9 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2010 Google, Inc. | 2 | * Copyright (C) 2010 Google, Inc. |
3 | * Copyright (C) 2013 NVIDIA Corporation | ||
3 | * | 4 | * |
4 | * Author: | 5 | * Author: |
5 | * Erik Gilling <konkers@google.com> | 6 | * Erik Gilling <konkers@google.com> |
6 | * Benoit Goby <benoit@android.com> | 7 | * Benoit Goby <benoit@android.com> |
8 | * Venu Byravarasu <vbyravarasu@nvidia.com> | ||
7 | * | 9 | * |
8 | * This software is licensed under the terms of the GNU General Public | 10 | * This software is licensed under the terms of the GNU General Public |
9 | * License version 2, as published by the Free Software Foundation, and | 11 | * License version 2, as published by the Free Software Foundation, and |
@@ -21,6 +23,7 @@ | |||
21 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
22 | #include <linux/err.h> | 24 | #include <linux/err.h> |
23 | #include <linux/export.h> | 25 | #include <linux/export.h> |
26 | #include <linux/module.h> | ||
24 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
25 | #include <linux/io.h> | 28 | #include <linux/io.h> |
26 | #include <linux/gpio.h> | 29 | #include <linux/gpio.h> |
@@ -29,13 +32,19 @@ | |||
29 | #include <linux/usb/otg.h> | 32 | #include <linux/usb/otg.h> |
30 | #include <linux/usb/ulpi.h> | 33 | #include <linux/usb/ulpi.h> |
31 | #include <asm/mach-types.h> | 34 | #include <asm/mach-types.h> |
35 | #include <linux/usb/ehci_def.h> | ||
32 | #include <linux/usb/tegra_usb_phy.h> | 36 | #include <linux/usb/tegra_usb_phy.h> |
33 | 37 | ||
34 | #define TEGRA_USB_BASE 0xC5000000 | ||
35 | #define TEGRA_USB_SIZE SZ_16K | ||
36 | |||
37 | #define ULPI_VIEWPORT 0x170 | 38 | #define ULPI_VIEWPORT 0x170 |
38 | 39 | ||
40 | /* PORTSC registers */ | ||
41 | #define TEGRA_USB_PORTSC1 0x184 | ||
42 | #define TEGRA_USB_PORTSC1_PTS(x) (((x) & 0x3) << 30) | ||
43 | #define TEGRA_USB_PORTSC1_PHCD (1 << 23) | ||
44 | |||
45 | /* Bits of PORTSC1, which will get cleared by writing 1 into them */ | ||
46 | #define TEGRA_PORTSC1_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC) | ||
47 | |||
39 | #define USB_SUSP_CTRL 0x400 | 48 | #define USB_SUSP_CTRL 0x400 |
40 | #define USB_WAKE_ON_CNNT_EN_DEV (1 << 3) | 49 | #define USB_WAKE_ON_CNNT_EN_DEV (1 << 3) |
41 | #define USB_WAKE_ON_DISCON_EN_DEV (1 << 4) | 50 | #define USB_WAKE_ON_DISCON_EN_DEV (1 << 4) |
@@ -196,34 +205,41 @@ static struct tegra_utmip_config utmip_default[] = { | |||
196 | }, | 205 | }, |
197 | }; | 206 | }; |
198 | 207 | ||
208 | static void set_pts(struct tegra_usb_phy *phy, u8 pts_val) | ||
209 | { | ||
210 | void __iomem *base = phy->regs; | ||
211 | unsigned long val; | ||
212 | |||
213 | val = readl(base + TEGRA_USB_PORTSC1) & ~TEGRA_PORTSC1_RWC_BITS; | ||
214 | val &= ~TEGRA_USB_PORTSC1_PTS(3); | ||
215 | val |= TEGRA_USB_PORTSC1_PTS(pts_val & 3); | ||
216 | writel(val, base + TEGRA_USB_PORTSC1); | ||
217 | } | ||
218 | |||
219 | static void set_phcd(struct tegra_usb_phy *phy, bool enable) | ||
220 | { | ||
221 | void __iomem *base = phy->regs; | ||
222 | unsigned long val; | ||
223 | |||
224 | val = readl(base + TEGRA_USB_PORTSC1) & ~TEGRA_PORTSC1_RWC_BITS; | ||
225 | if (enable) | ||
226 | val |= TEGRA_USB_PORTSC1_PHCD; | ||
227 | else | ||
228 | val &= ~TEGRA_USB_PORTSC1_PHCD; | ||
229 | writel(val, base + TEGRA_USB_PORTSC1); | ||
230 | } | ||
231 | |||
199 | static int utmip_pad_open(struct tegra_usb_phy *phy) | 232 | static int utmip_pad_open(struct tegra_usb_phy *phy) |
200 | { | 233 | { |
201 | phy->pad_clk = clk_get_sys("utmip-pad", NULL); | 234 | phy->pad_clk = devm_clk_get(phy->dev, "utmi-pads"); |
202 | if (IS_ERR(phy->pad_clk)) { | 235 | if (IS_ERR(phy->pad_clk)) { |
203 | pr_err("%s: can't get utmip pad clock\n", __func__); | 236 | pr_err("%s: can't get utmip pad clock\n", __func__); |
204 | return PTR_ERR(phy->pad_clk); | 237 | return PTR_ERR(phy->pad_clk); |
205 | } | 238 | } |
206 | 239 | ||
207 | if (phy->is_legacy_phy) { | ||
208 | phy->pad_regs = phy->regs; | ||
209 | } else { | ||
210 | phy->pad_regs = ioremap(TEGRA_USB_BASE, TEGRA_USB_SIZE); | ||
211 | if (!phy->pad_regs) { | ||
212 | pr_err("%s: can't remap usb registers\n", __func__); | ||
213 | clk_put(phy->pad_clk); | ||
214 | return -ENOMEM; | ||
215 | } | ||
216 | } | ||
217 | return 0; | 240 | return 0; |
218 | } | 241 | } |
219 | 242 | ||
220 | static void utmip_pad_close(struct tegra_usb_phy *phy) | ||
221 | { | ||
222 | if (!phy->is_legacy_phy) | ||
223 | iounmap(phy->pad_regs); | ||
224 | clk_put(phy->pad_clk); | ||
225 | } | ||
226 | |||
227 | static void utmip_pad_power_on(struct tegra_usb_phy *phy) | 243 | static void utmip_pad_power_on(struct tegra_usb_phy *phy) |
228 | { | 244 | { |
229 | unsigned long val, flags; | 245 | unsigned long val, flags; |
@@ -299,7 +315,7 @@ static void utmi_phy_clk_disable(struct tegra_usb_phy *phy) | |||
299 | val &= ~USB_SUSP_SET; | 315 | val &= ~USB_SUSP_SET; |
300 | writel(val, base + USB_SUSP_CTRL); | 316 | writel(val, base + USB_SUSP_CTRL); |
301 | } else | 317 | } else |
302 | phy->set_phcd(&phy->u_phy, true); | 318 | set_phcd(phy, true); |
303 | 319 | ||
304 | if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0) | 320 | if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0) |
305 | pr_err("%s: timeout waiting for phy to stabilize\n", __func__); | 321 | pr_err("%s: timeout waiting for phy to stabilize\n", __func__); |
@@ -321,7 +337,7 @@ static void utmi_phy_clk_enable(struct tegra_usb_phy *phy) | |||
321 | val &= ~USB_SUSP_CLR; | 337 | val &= ~USB_SUSP_CLR; |
322 | writel(val, base + USB_SUSP_CTRL); | 338 | writel(val, base + USB_SUSP_CTRL); |
323 | } else | 339 | } else |
324 | phy->set_phcd(&phy->u_phy, false); | 340 | set_phcd(phy, false); |
325 | 341 | ||
326 | if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, | 342 | if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, |
327 | USB_PHY_CLK_VALID)) | 343 | USB_PHY_CLK_VALID)) |
@@ -444,7 +460,7 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy) | |||
444 | utmi_phy_clk_enable(phy); | 460 | utmi_phy_clk_enable(phy); |
445 | 461 | ||
446 | if (!phy->is_legacy_phy) | 462 | if (!phy->is_legacy_phy) |
447 | phy->set_pts(&phy->u_phy, 0); | 463 | set_pts(phy, 0); |
448 | 464 | ||
449 | return 0; | 465 | return 0; |
450 | } | 466 | } |
@@ -541,11 +557,18 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy) | |||
541 | int ret; | 557 | int ret; |
542 | unsigned long val; | 558 | unsigned long val; |
543 | void __iomem *base = phy->regs; | 559 | void __iomem *base = phy->regs; |
544 | struct tegra_ulpi_config *config = phy->config; | ||
545 | 560 | ||
546 | gpio_direction_output(config->reset_gpio, 0); | 561 | ret = gpio_direction_output(phy->reset_gpio, 0); |
562 | if (ret < 0) { | ||
563 | dev_err(phy->dev, "gpio %d not set to 0\n", phy->reset_gpio); | ||
564 | return ret; | ||
565 | } | ||
547 | msleep(5); | 566 | msleep(5); |
548 | gpio_direction_output(config->reset_gpio, 1); | 567 | ret = gpio_direction_output(phy->reset_gpio, 1); |
568 | if (ret < 0) { | ||
569 | dev_err(phy->dev, "gpio %d not set to 1\n", phy->reset_gpio); | ||
570 | return ret; | ||
571 | } | ||
549 | 572 | ||
550 | clk_prepare_enable(phy->clk); | 573 | clk_prepare_enable(phy->clk); |
551 | msleep(1); | 574 | msleep(1); |
@@ -603,63 +626,15 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy) | |||
603 | 626 | ||
604 | static int ulpi_phy_power_off(struct tegra_usb_phy *phy) | 627 | static int ulpi_phy_power_off(struct tegra_usb_phy *phy) |
605 | { | 628 | { |
606 | struct tegra_ulpi_config *config = phy->config; | ||
607 | |||
608 | clk_disable(phy->clk); | 629 | clk_disable(phy->clk); |
609 | return gpio_direction_output(config->reset_gpio, 0); | 630 | return gpio_direction_output(phy->reset_gpio, 0); |
610 | } | ||
611 | |||
612 | static int tegra_phy_init(struct usb_phy *x) | ||
613 | { | ||
614 | struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy); | ||
615 | struct tegra_ulpi_config *ulpi_config; | ||
616 | int err; | ||
617 | |||
618 | if (phy->is_ulpi_phy) { | ||
619 | ulpi_config = phy->config; | ||
620 | phy->clk = clk_get_sys(NULL, ulpi_config->clk); | ||
621 | if (IS_ERR(phy->clk)) { | ||
622 | pr_err("%s: can't get ulpi clock\n", __func__); | ||
623 | err = -ENXIO; | ||
624 | goto err1; | ||
625 | } | ||
626 | if (!gpio_is_valid(ulpi_config->reset_gpio)) | ||
627 | ulpi_config->reset_gpio = | ||
628 | of_get_named_gpio(phy->dev->of_node, | ||
629 | "nvidia,phy-reset-gpio", 0); | ||
630 | if (!gpio_is_valid(ulpi_config->reset_gpio)) { | ||
631 | pr_err("%s: invalid reset gpio: %d\n", __func__, | ||
632 | ulpi_config->reset_gpio); | ||
633 | err = -EINVAL; | ||
634 | goto err1; | ||
635 | } | ||
636 | gpio_request(ulpi_config->reset_gpio, "ulpi_phy_reset_b"); | ||
637 | gpio_direction_output(ulpi_config->reset_gpio, 0); | ||
638 | phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0); | ||
639 | phy->ulpi->io_priv = phy->regs + ULPI_VIEWPORT; | ||
640 | } else { | ||
641 | err = utmip_pad_open(phy); | ||
642 | if (err < 0) | ||
643 | goto err1; | ||
644 | } | ||
645 | return 0; | ||
646 | err1: | ||
647 | clk_disable_unprepare(phy->pll_u); | ||
648 | clk_put(phy->pll_u); | ||
649 | return err; | ||
650 | } | 631 | } |
651 | 632 | ||
652 | static void tegra_usb_phy_close(struct usb_phy *x) | 633 | static void tegra_usb_phy_close(struct usb_phy *x) |
653 | { | 634 | { |
654 | struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy); | 635 | struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy); |
655 | 636 | ||
656 | if (phy->is_ulpi_phy) | ||
657 | clk_put(phy->clk); | ||
658 | else | ||
659 | utmip_pad_close(phy); | ||
660 | clk_disable_unprepare(phy->pll_u); | 637 | clk_disable_unprepare(phy->pll_u); |
661 | clk_put(phy->pll_u); | ||
662 | kfree(phy); | ||
663 | } | 638 | } |
664 | 639 | ||
665 | static int tegra_usb_phy_power_on(struct tegra_usb_phy *phy) | 640 | static int tegra_usb_phy_power_on(struct tegra_usb_phy *phy) |
@@ -687,54 +662,63 @@ static int tegra_usb_phy_suspend(struct usb_phy *x, int suspend) | |||
687 | return tegra_usb_phy_power_on(phy); | 662 | return tegra_usb_phy_power_on(phy); |
688 | } | 663 | } |
689 | 664 | ||
690 | struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance, | 665 | static int ulpi_open(struct tegra_usb_phy *phy) |
691 | void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode, | 666 | { |
692 | void (*set_pts)(struct usb_phy *x, u8 pts_val), | 667 | int err; |
693 | void (*set_phcd)(struct usb_phy *x, bool enable)) | 668 | |
669 | phy->clk = devm_clk_get(phy->dev, "ulpi-link"); | ||
670 | if (IS_ERR(phy->clk)) { | ||
671 | pr_err("%s: can't get ulpi clock\n", __func__); | ||
672 | return PTR_ERR(phy->clk); | ||
673 | } | ||
674 | |||
675 | err = devm_gpio_request(phy->dev, phy->reset_gpio, "ulpi_phy_reset_b"); | ||
676 | if (err < 0) { | ||
677 | dev_err(phy->dev, "request failed for gpio: %d\n", | ||
678 | phy->reset_gpio); | ||
679 | return err; | ||
680 | } | ||
681 | |||
682 | err = gpio_direction_output(phy->reset_gpio, 0); | ||
683 | if (err < 0) { | ||
684 | dev_err(phy->dev, "gpio %d direction not set to output\n", | ||
685 | phy->reset_gpio); | ||
686 | return err; | ||
687 | } | ||
688 | |||
689 | phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0); | ||
690 | if (!phy->ulpi) { | ||
691 | dev_err(phy->dev, "otg_ulpi_create returned NULL\n"); | ||
692 | err = -ENOMEM; | ||
693 | return err; | ||
694 | } | ||
695 | |||
696 | phy->ulpi->io_priv = phy->regs + ULPI_VIEWPORT; | ||
697 | return 0; | ||
698 | } | ||
694 | 699 | ||
700 | static int tegra_usb_phy_init(struct tegra_usb_phy *phy) | ||
695 | { | 701 | { |
696 | struct tegra_usb_phy *phy; | ||
697 | unsigned long parent_rate; | 702 | unsigned long parent_rate; |
698 | int i; | 703 | int i; |
699 | int err; | 704 | int err; |
700 | struct device_node *np = dev->of_node; | 705 | |
701 | 706 | if (!phy->is_ulpi_phy) { | |
702 | phy = kzalloc(sizeof(struct tegra_usb_phy), GFP_KERNEL); | 707 | if (phy->is_legacy_phy) |
703 | if (!phy) | 708 | phy->config = &utmip_default[0]; |
704 | return ERR_PTR(-ENOMEM); | 709 | else |
705 | 710 | phy->config = &utmip_default[2]; | |
706 | phy->instance = instance; | ||
707 | phy->regs = regs; | ||
708 | phy->config = config; | ||
709 | phy->mode = phy_mode; | ||
710 | phy->dev = dev; | ||
711 | phy->is_legacy_phy = | ||
712 | of_property_read_bool(np, "nvidia,has-legacy-mode"); | ||
713 | phy->set_pts = set_pts; | ||
714 | phy->set_phcd = set_phcd; | ||
715 | err = of_property_match_string(np, "phy_type", "ulpi"); | ||
716 | if (err < 0) | ||
717 | phy->is_ulpi_phy = false; | ||
718 | else | ||
719 | phy->is_ulpi_phy = true; | ||
720 | |||
721 | if (!phy->config) { | ||
722 | if (phy->is_ulpi_phy) { | ||
723 | pr_err("%s: ulpi phy configuration missing", __func__); | ||
724 | err = -EINVAL; | ||
725 | goto err0; | ||
726 | } else { | ||
727 | phy->config = &utmip_default[instance]; | ||
728 | } | ||
729 | } | 711 | } |
730 | 712 | ||
731 | phy->pll_u = clk_get_sys(NULL, "pll_u"); | 713 | phy->pll_u = devm_clk_get(phy->dev, "pll_u"); |
732 | if (IS_ERR(phy->pll_u)) { | 714 | if (IS_ERR(phy->pll_u)) { |
733 | pr_err("Can't get pll_u clock\n"); | 715 | pr_err("Can't get pll_u clock\n"); |
734 | err = PTR_ERR(phy->pll_u); | 716 | return PTR_ERR(phy->pll_u); |
735 | goto err0; | ||
736 | } | 717 | } |
737 | clk_prepare_enable(phy->pll_u); | 718 | |
719 | err = clk_prepare_enable(phy->pll_u); | ||
720 | if (err) | ||
721 | return err; | ||
738 | 722 | ||
739 | parent_rate = clk_get_rate(clk_get_parent(phy->pll_u)); | 723 | parent_rate = clk_get_rate(clk_get_parent(phy->pll_u)); |
740 | for (i = 0; i < ARRAY_SIZE(tegra_freq_table); i++) { | 724 | for (i = 0; i < ARRAY_SIZE(tegra_freq_table); i++) { |
@@ -746,23 +730,22 @@ struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance, | |||
746 | if (!phy->freq) { | 730 | if (!phy->freq) { |
747 | pr_err("invalid pll_u parent rate %ld\n", parent_rate); | 731 | pr_err("invalid pll_u parent rate %ld\n", parent_rate); |
748 | err = -EINVAL; | 732 | err = -EINVAL; |
749 | goto err1; | 733 | goto fail; |
750 | } | 734 | } |
751 | 735 | ||
752 | phy->u_phy.init = tegra_phy_init; | 736 | if (phy->is_ulpi_phy) |
753 | phy->u_phy.shutdown = tegra_usb_phy_close; | 737 | err = ulpi_open(phy); |
754 | phy->u_phy.set_suspend = tegra_usb_phy_suspend; | 738 | else |
739 | err = utmip_pad_open(phy); | ||
740 | if (err < 0) | ||
741 | goto fail; | ||
755 | 742 | ||
756 | return phy; | 743 | return 0; |
757 | 744 | ||
758 | err1: | 745 | fail: |
759 | clk_disable_unprepare(phy->pll_u); | 746 | clk_disable_unprepare(phy->pll_u); |
760 | clk_put(phy->pll_u); | 747 | return err; |
761 | err0: | ||
762 | kfree(phy); | ||
763 | return ERR_PTR(err); | ||
764 | } | 748 | } |
765 | EXPORT_SYMBOL_GPL(tegra_usb_phy_open); | ||
766 | 749 | ||
767 | void tegra_usb_phy_preresume(struct usb_phy *x) | 750 | void tegra_usb_phy_preresume(struct usb_phy *x) |
768 | { | 751 | { |
@@ -801,3 +784,124 @@ void tegra_ehci_phy_restore_end(struct usb_phy *x) | |||
801 | } | 784 | } |
802 | EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_end); | 785 | EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_end); |
803 | 786 | ||
787 | static int tegra_usb_phy_probe(struct platform_device *pdev) | ||
788 | { | ||
789 | struct resource *res; | ||
790 | struct tegra_usb_phy *tegra_phy = NULL; | ||
791 | struct device_node *np = pdev->dev.of_node; | ||
792 | int err; | ||
793 | |||
794 | tegra_phy = devm_kzalloc(&pdev->dev, sizeof(*tegra_phy), GFP_KERNEL); | ||
795 | if (!tegra_phy) { | ||
796 | dev_err(&pdev->dev, "unable to allocate memory for USB2 PHY\n"); | ||
797 | return -ENOMEM; | ||
798 | } | ||
799 | |||
800 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
801 | if (!res) { | ||
802 | dev_err(&pdev->dev, "Failed to get I/O memory\n"); | ||
803 | return -ENXIO; | ||
804 | } | ||
805 | |||
806 | tegra_phy->regs = devm_ioremap(&pdev->dev, res->start, | ||
807 | resource_size(res)); | ||
808 | if (!tegra_phy->regs) { | ||
809 | dev_err(&pdev->dev, "Failed to remap I/O memory\n"); | ||
810 | return -ENOMEM; | ||
811 | } | ||
812 | |||
813 | tegra_phy->is_legacy_phy = | ||
814 | of_property_read_bool(np, "nvidia,has-legacy-mode"); | ||
815 | |||
816 | err = of_property_match_string(np, "phy_type", "ulpi"); | ||
817 | if (err < 0) { | ||
818 | tegra_phy->is_ulpi_phy = false; | ||
819 | |||
820 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
821 | if (!res) { | ||
822 | dev_err(&pdev->dev, "Failed to get UTMI Pad regs\n"); | ||
823 | return -ENXIO; | ||
824 | } | ||
825 | |||
826 | tegra_phy->pad_regs = devm_ioremap(&pdev->dev, res->start, | ||
827 | resource_size(res)); | ||
828 | if (!tegra_phy->regs) { | ||
829 | dev_err(&pdev->dev, "Failed to remap UTMI Pad regs\n"); | ||
830 | return -ENOMEM; | ||
831 | } | ||
832 | } else { | ||
833 | tegra_phy->is_ulpi_phy = true; | ||
834 | |||
835 | tegra_phy->reset_gpio = | ||
836 | of_get_named_gpio(np, "nvidia,phy-reset-gpio", 0); | ||
837 | if (!gpio_is_valid(tegra_phy->reset_gpio)) { | ||
838 | dev_err(&pdev->dev, "invalid gpio: %d\n", | ||
839 | tegra_phy->reset_gpio); | ||
840 | return tegra_phy->reset_gpio; | ||
841 | } | ||
842 | } | ||
843 | |||
844 | err = of_property_match_string(np, "dr_mode", "otg"); | ||
845 | if (err < 0) { | ||
846 | err = of_property_match_string(np, "dr_mode", "peripheral"); | ||
847 | if (err < 0) | ||
848 | tegra_phy->mode = TEGRA_USB_PHY_MODE_HOST; | ||
849 | else | ||
850 | tegra_phy->mode = TEGRA_USB_PHY_MODE_DEVICE; | ||
851 | } else | ||
852 | tegra_phy->mode = TEGRA_USB_PHY_MODE_OTG; | ||
853 | |||
854 | tegra_phy->dev = &pdev->dev; | ||
855 | err = tegra_usb_phy_init(tegra_phy); | ||
856 | if (err < 0) | ||
857 | return err; | ||
858 | |||
859 | tegra_phy->u_phy.shutdown = tegra_usb_phy_close; | ||
860 | tegra_phy->u_phy.set_suspend = tegra_usb_phy_suspend; | ||
861 | |||
862 | dev_set_drvdata(&pdev->dev, tegra_phy); | ||
863 | return 0; | ||
864 | } | ||
865 | |||
866 | static struct of_device_id tegra_usb_phy_id_table[] = { | ||
867 | { .compatible = "nvidia,tegra20-usb-phy", }, | ||
868 | { }, | ||
869 | }; | ||
870 | MODULE_DEVICE_TABLE(of, tegra_usb_phy_id_table); | ||
871 | |||
872 | static struct platform_driver tegra_usb_phy_driver = { | ||
873 | .probe = tegra_usb_phy_probe, | ||
874 | .driver = { | ||
875 | .name = "tegra-phy", | ||
876 | .owner = THIS_MODULE, | ||
877 | .of_match_table = of_match_ptr(tegra_usb_phy_id_table), | ||
878 | }, | ||
879 | }; | ||
880 | module_platform_driver(tegra_usb_phy_driver); | ||
881 | |||
882 | static int tegra_usb_phy_match(struct device *dev, void *data) | ||
883 | { | ||
884 | struct tegra_usb_phy *tegra_phy = dev_get_drvdata(dev); | ||
885 | struct device_node *dn = data; | ||
886 | |||
887 | return (tegra_phy->dev->of_node == dn) ? 1 : 0; | ||
888 | } | ||
889 | |||
890 | struct usb_phy *tegra_usb_get_phy(struct device_node *dn) | ||
891 | { | ||
892 | struct device *dev; | ||
893 | struct tegra_usb_phy *tegra_phy; | ||
894 | |||
895 | dev = driver_find_device(&tegra_usb_phy_driver.driver, NULL, dn, | ||
896 | tegra_usb_phy_match); | ||
897 | if (!dev) | ||
898 | return ERR_PTR(-EPROBE_DEFER); | ||
899 | |||
900 | tegra_phy = dev_get_drvdata(dev); | ||
901 | |||
902 | return &tegra_phy->u_phy; | ||
903 | } | ||
904 | EXPORT_SYMBOL_GPL(tegra_usb_get_phy); | ||
905 | |||
906 | MODULE_DESCRIPTION("Tegra USB PHY driver"); | ||
907 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/usb/phy/phy-ulpi-viewport.c b/drivers/usb/phy/phy-ulpi-viewport.c index c5ba7e5423fc..7c22a5390fc3 100644 --- a/drivers/usb/phy/phy-ulpi-viewport.c +++ b/drivers/usb/phy/phy-ulpi-viewport.c | |||
@@ -12,6 +12,7 @@ | |||
12 | * | 12 | * |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/export.h> | ||
15 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
16 | #include <linux/usb.h> | 17 | #include <linux/usb.h> |
17 | #include <linux/io.h> | 18 | #include <linux/io.h> |
@@ -78,3 +79,4 @@ struct usb_phy_io_ops ulpi_viewport_access_ops = { | |||
78 | .read = ulpi_viewport_read, | 79 | .read = ulpi_viewport_read, |
79 | .write = ulpi_viewport_write, | 80 | .write = ulpi_viewport_write, |
80 | }; | 81 | }; |
82 | EXPORT_SYMBOL_GPL(ulpi_viewport_access_ops); | ||
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 1d55762afbb1..8c3a42ea910c 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig | |||
@@ -710,6 +710,16 @@ config USB_SERIAL_QT2 | |||
710 | To compile this driver as a module, choose M here: the | 710 | To compile this driver as a module, choose M here: the |
711 | module will be called quatech-serial. | 711 | module will be called quatech-serial. |
712 | 712 | ||
713 | config USB_SERIAL_FLASHLOADER | ||
714 | tristate "Infineon Modem Flashloader USB interface driver" | ||
715 | help | ||
716 | Say Y here if you want to download Infineon Modem | ||
717 | via USB Flashloader serial driver. | ||
718 | |||
719 | To compile this driver as a module, choose M here: the | ||
720 | module will be called flashloader. | ||
721 | |||
722 | |||
713 | config USB_SERIAL_DEBUG | 723 | config USB_SERIAL_DEBUG |
714 | tristate "USB Debugging Device" | 724 | tristate "USB Debugging Device" |
715 | help | 725 | help |
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index cec63fa19104..f7130114488f 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile | |||
@@ -65,3 +65,4 @@ obj-$(CONFIG_USB_SERIAL_VIVOPAY_SERIAL) += vivopay-serial.o | |||
65 | obj-$(CONFIG_USB_SERIAL_XSENS_MT) += xsens_mt.o | 65 | obj-$(CONFIG_USB_SERIAL_XSENS_MT) += xsens_mt.o |
66 | obj-$(CONFIG_USB_SERIAL_ZIO) += zio.o | 66 | obj-$(CONFIG_USB_SERIAL_ZIO) += zio.o |
67 | obj-$(CONFIG_USB_SERIAL_ZTE) += zte_ev.o | 67 | obj-$(CONFIG_USB_SERIAL_ZTE) += zte_ev.o |
68 | obj-$(CONFIG_USB_SERIAL_FLASHLOADER) += flashloader.o | ||
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index 40e7fd94646f..bc77e955cbef 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c | |||
@@ -413,8 +413,8 @@ static int ark3116_ioctl(struct tty_struct *tty, | |||
413 | /* XXX: Some of these values are probably wrong. */ | 413 | /* XXX: Some of these values are probably wrong. */ |
414 | memset(&serstruct, 0, sizeof(serstruct)); | 414 | memset(&serstruct, 0, sizeof(serstruct)); |
415 | serstruct.type = PORT_16654; | 415 | serstruct.type = PORT_16654; |
416 | serstruct.line = port->serial->minor; | 416 | serstruct.line = port->minor; |
417 | serstruct.port = port->number; | 417 | serstruct.port = port->port_number; |
418 | serstruct.custom_divisor = 0; | 418 | serstruct.custom_divisor = 0; |
419 | serstruct.baud_base = 460800; | 419 | serstruct.baud_base = 460800; |
420 | 420 | ||
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c index 3c4db6d196c6..f053b302a00d 100644 --- a/drivers/usb/serial/bus.c +++ b/drivers/usb/serial/bus.c | |||
@@ -43,7 +43,7 @@ static ssize_t show_port_number(struct device *dev, | |||
43 | { | 43 | { |
44 | struct usb_serial_port *port = to_usb_serial_port(dev); | 44 | struct usb_serial_port *port = to_usb_serial_port(dev); |
45 | 45 | ||
46 | return sprintf(buf, "%d\n", port->number - port->serial->minor); | 46 | return sprintf(buf, "%d\n", port->port_number); |
47 | } | 47 | } |
48 | 48 | ||
49 | static DEVICE_ATTR(port_number, S_IRUGO, show_port_number, NULL); | 49 | static DEVICE_ATTR(port_number, S_IRUGO, show_port_number, NULL); |
@@ -80,7 +80,7 @@ static int usb_serial_device_probe(struct device *dev) | |||
80 | goto exit_with_autopm; | 80 | goto exit_with_autopm; |
81 | } | 81 | } |
82 | 82 | ||
83 | minor = port->number; | 83 | minor = port->minor; |
84 | tty_register_device(usb_serial_tty_driver, minor, dev); | 84 | tty_register_device(usb_serial_tty_driver, minor, dev); |
85 | dev_info(&port->serial->dev->dev, | 85 | dev_info(&port->serial->dev->dev, |
86 | "%s converter now attached to ttyUSB%d\n", | 86 | "%s converter now attached to ttyUSB%d\n", |
@@ -106,7 +106,7 @@ static int usb_serial_device_remove(struct device *dev) | |||
106 | /* make sure suspend/resume doesn't race against port_remove */ | 106 | /* make sure suspend/resume doesn't race against port_remove */ |
107 | usb_autopm_get_interface(port->serial->interface); | 107 | usb_autopm_get_interface(port->serial->interface); |
108 | 108 | ||
109 | minor = port->number; | 109 | minor = port->minor; |
110 | tty_unregister_device(usb_serial_tty_driver, minor); | 110 | tty_unregister_device(usb_serial_tty_driver, minor); |
111 | 111 | ||
112 | device_remove_file(&port->dev, &dev_attr_port_number); | 112 | device_remove_file(&port->dev, &dev_attr_port_number); |
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 5f3bcd31e204..afb50eab2049 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c | |||
@@ -108,18 +108,18 @@ static int usb_console_setup(struct console *co, char *options) | |||
108 | * no need to check the index here: if the index is wrong, console | 108 | * no need to check the index here: if the index is wrong, console |
109 | * code won't call us | 109 | * code won't call us |
110 | */ | 110 | */ |
111 | serial = usb_serial_get_by_index(co->index); | 111 | port = usb_serial_port_get_by_minor(co->index); |
112 | if (serial == NULL) { | 112 | if (port == NULL) { |
113 | /* no device is connected yet, sorry :( */ | 113 | /* no device is connected yet, sorry :( */ |
114 | pr_err("No USB device connected to ttyUSB%i\n", co->index); | 114 | pr_err("No USB device connected to ttyUSB%i\n", co->index); |
115 | return -ENODEV; | 115 | return -ENODEV; |
116 | } | 116 | } |
117 | serial = port->serial; | ||
117 | 118 | ||
118 | retval = usb_autopm_get_interface(serial->interface); | 119 | retval = usb_autopm_get_interface(serial->interface); |
119 | if (retval) | 120 | if (retval) |
120 | goto error_get_interface; | 121 | goto error_get_interface; |
121 | 122 | ||
122 | port = serial->port[co->index - serial->minor]; | ||
123 | tty_port_tty_set(&port->port, NULL); | 123 | tty_port_tty_set(&port->port, NULL); |
124 | 124 | ||
125 | info->port = port; | 125 | info->port = port; |
@@ -210,7 +210,7 @@ static void usb_console_write(struct console *co, | |||
210 | if (count == 0) | 210 | if (count == 0) |
211 | return; | 211 | return; |
212 | 212 | ||
213 | pr_debug("%s - port %d, %d byte(s)\n", __func__, port->number, count); | 213 | pr_debug("%s - minor %d, %d byte(s)\n", __func__, port->minor, count); |
214 | 214 | ||
215 | if (!port->port.console) { | 215 | if (!port->port.console) { |
216 | pr_debug("%s - port not opened\n", __func__); | 216 | pr_debug("%s - port not opened\n", __func__); |
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 2c659553c07c..d6ef2f8da37d 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c | |||
@@ -666,8 +666,6 @@ static void cp210x_set_termios(struct tty_struct *tty, | |||
666 | unsigned int bits; | 666 | unsigned int bits; |
667 | unsigned int modem_ctl[4]; | 667 | unsigned int modem_ctl[4]; |
668 | 668 | ||
669 | dev_dbg(dev, "%s - port %d\n", __func__, port->number); | ||
670 | |||
671 | if (!tty) | 669 | if (!tty) |
672 | return; | 670 | return; |
673 | 671 | ||
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 082120198f87..e948dc02795d 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c | |||
@@ -435,7 +435,7 @@ static void cypress_set_dead(struct usb_serial_port *port) | |||
435 | spin_unlock_irqrestore(&priv->lock, flags); | 435 | spin_unlock_irqrestore(&priv->lock, flags); |
436 | 436 | ||
437 | dev_err(&port->dev, "cypress_m8 suspending failing port %d - " | 437 | dev_err(&port->dev, "cypress_m8 suspending failing port %d - " |
438 | "interval might be too short\n", port->number); | 438 | "interval might be too short\n", port->port_number); |
439 | } | 439 | } |
440 | 440 | ||
441 | 441 | ||
@@ -667,7 +667,7 @@ static int cypress_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
667 | { | 667 | { |
668 | struct cypress_private *priv = usb_get_serial_port_data(port); | 668 | struct cypress_private *priv = usb_get_serial_port_data(port); |
669 | 669 | ||
670 | dev_dbg(&port->dev, "%s - port %d, %d bytes\n", __func__, port->number, count); | 670 | dev_dbg(&port->dev, "%s - %d bytes\n", __func__, count); |
671 | 671 | ||
672 | /* line control commands, which need to be executed immediately, | 672 | /* line control commands, which need to be executed immediately, |
673 | are not put into the buffer for obvious reasons. | 673 | are not put into the buffer for obvious reasons. |
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index 7b807d389527..19b467fe0388 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c | |||
@@ -1304,11 +1304,7 @@ static void digi_release(struct usb_serial *serial) | |||
1304 | 1304 | ||
1305 | static int digi_port_probe(struct usb_serial_port *port) | 1305 | static int digi_port_probe(struct usb_serial_port *port) |
1306 | { | 1306 | { |
1307 | unsigned port_num; | 1307 | return digi_port_init(port, port->port_number); |
1308 | |||
1309 | port_num = port->number - port->serial->minor; | ||
1310 | |||
1311 | return digi_port_init(port, port_num); | ||
1312 | } | 1308 | } |
1313 | 1309 | ||
1314 | static int digi_port_remove(struct usb_serial_port *port) | 1310 | static int digi_port_remove(struct usb_serial_port *port) |
diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c index 7d8dd5aad236..75e85cbf9e8b 100644 --- a/drivers/usb/serial/f81232.c +++ b/drivers/usb/serial/f81232.c | |||
@@ -288,15 +288,14 @@ static int f81232_ioctl(struct tty_struct *tty, | |||
288 | struct serial_struct ser; | 288 | struct serial_struct ser; |
289 | struct usb_serial_port *port = tty->driver_data; | 289 | struct usb_serial_port *port = tty->driver_data; |
290 | 290 | ||
291 | dev_dbg(&port->dev, "%s (%d) cmd = 0x%04x\n", __func__, | 291 | dev_dbg(&port->dev, "%s cmd = 0x%04x\n", __func__, cmd); |
292 | port->number, cmd); | ||
293 | 292 | ||
294 | switch (cmd) { | 293 | switch (cmd) { |
295 | case TIOCGSERIAL: | 294 | case TIOCGSERIAL: |
296 | memset(&ser, 0, sizeof ser); | 295 | memset(&ser, 0, sizeof ser); |
297 | ser.type = PORT_16654; | 296 | ser.type = PORT_16654; |
298 | ser.line = port->serial->minor; | 297 | ser.line = port->minor; |
299 | ser.port = port->number; | 298 | ser.port = port->port_number; |
300 | ser.baud_base = 460800; | 299 | ser.baud_base = 460800; |
301 | 300 | ||
302 | if (copy_to_user((void __user *)arg, &ser, sizeof ser)) | 301 | if (copy_to_user((void __user *)arg, &ser, sizeof ser)) |
diff --git a/drivers/usb/serial/flashloader.c b/drivers/usb/serial/flashloader.c new file mode 100644 index 000000000000..e6f5c10e891c --- /dev/null +++ b/drivers/usb/serial/flashloader.c | |||
@@ -0,0 +1,39 @@ | |||
1 | /* | ||
2 | * Infineon Flashloader driver | ||
3 | * | ||
4 | * Copyright (C) 2013 Wei Shuai <cpuwolf@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License version | ||
8 | * 2 as published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/tty.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/usb.h> | ||
16 | #include <linux/usb/serial.h> | ||
17 | #include <linux/uaccess.h> | ||
18 | |||
19 | static const struct usb_device_id id_table[] = { | ||
20 | { USB_DEVICE(0x8087, 0x0716) }, | ||
21 | { }, | ||
22 | }; | ||
23 | MODULE_DEVICE_TABLE(usb, id_table); | ||
24 | |||
25 | static struct usb_serial_driver flashloader_device = { | ||
26 | .driver = { | ||
27 | .owner = THIS_MODULE, | ||
28 | .name = "flashloader", | ||
29 | }, | ||
30 | .id_table = id_table, | ||
31 | .num_ports = 1, | ||
32 | }; | ||
33 | |||
34 | static struct usb_serial_driver * const serial_drivers[] = { | ||
35 | &flashloader_device, NULL | ||
36 | }; | ||
37 | |||
38 | module_usb_serial_driver(serial_drivers, id_table); | ||
39 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index b110c573ea85..04b5ed90ffb2 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c | |||
@@ -948,9 +948,9 @@ static void garmin_close(struct usb_serial_port *port) | |||
948 | { | 948 | { |
949 | struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); | 949 | struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); |
950 | 950 | ||
951 | dev_dbg(&port->dev, "%s - port %d - mode=%d state=%d flags=0x%X\n", | 951 | dev_dbg(&port->dev, "%s - mode=%d state=%d flags=0x%X\n", |
952 | __func__, port->number, garmin_data_p->mode, | 952 | __func__, garmin_data_p->mode, garmin_data_p->state, |
953 | garmin_data_p->state, garmin_data_p->flags); | 953 | garmin_data_p->flags); |
954 | 954 | ||
955 | garmin_clear(garmin_data_p); | 955 | garmin_clear(garmin_data_p); |
956 | 956 | ||
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index 1477e8593476..dc2803b5eb09 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c | |||
@@ -915,8 +915,8 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
915 | return -ENOMEM; | 915 | return -ENOMEM; |
916 | } | 916 | } |
917 | 917 | ||
918 | dev_dbg(dev, "%s(%d) - Initialize TX fifo to %d bytes\n", | 918 | dev_dbg(dev, "%s - Initialize TX fifo to %d bytes\n", |
919 | __func__, port->number, edge_port->maxTxCredits); | 919 | __func__, edge_port->maxTxCredits); |
920 | 920 | ||
921 | return 0; | 921 | return 0; |
922 | } | 922 | } |
@@ -1122,9 +1122,8 @@ static int edge_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
1122 | copySize = min((unsigned int)count, | 1122 | copySize = min((unsigned int)count, |
1123 | (edge_port->txCredits - fifo->count)); | 1123 | (edge_port->txCredits - fifo->count)); |
1124 | 1124 | ||
1125 | dev_dbg(&port->dev, "%s(%d) of %d byte(s) Fifo room %d -- will copy %d bytes\n", | 1125 | dev_dbg(&port->dev, "%s of %d byte(s) Fifo room %d -- will copy %d bytes\n", |
1126 | __func__, port->number, count, | 1126 | __func__, count, edge_port->txCredits - fifo->count, copySize); |
1127 | edge_port->txCredits - fifo->count, copySize); | ||
1128 | 1127 | ||
1129 | /* catch writes of 0 bytes which the tty driver likes to give us, | 1128 | /* catch writes of 0 bytes which the tty driver likes to give us, |
1130 | and when txCredits is empty */ | 1129 | and when txCredits is empty */ |
@@ -1216,9 +1215,8 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, | |||
1216 | if (edge_port->write_in_progress || | 1215 | if (edge_port->write_in_progress || |
1217 | !edge_port->open || | 1216 | !edge_port->open || |
1218 | (fifo->count == 0)) { | 1217 | (fifo->count == 0)) { |
1219 | dev_dbg(dev, "%s(%d) EXIT - fifo %d, PendingWrite = %d\n", | 1218 | dev_dbg(dev, "%s EXIT - fifo %d, PendingWrite = %d\n", |
1220 | __func__, edge_port->port->number, | 1219 | __func__, fifo->count, edge_port->write_in_progress); |
1221 | fifo->count, edge_port->write_in_progress); | ||
1222 | goto exit_send; | 1220 | goto exit_send; |
1223 | } | 1221 | } |
1224 | 1222 | ||
@@ -1230,9 +1228,8 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, | |||
1230 | * it's better to wait for more credits so we can do a larger write. | 1228 | * it's better to wait for more credits so we can do a larger write. |
1231 | */ | 1229 | */ |
1232 | if (edge_port->txCredits < EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(edge_port->maxTxCredits, EDGE_FW_BULK_MAX_PACKET_SIZE)) { | 1230 | if (edge_port->txCredits < EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(edge_port->maxTxCredits, EDGE_FW_BULK_MAX_PACKET_SIZE)) { |
1233 | dev_dbg(dev, "%s(%d) Not enough credit - fifo %d TxCredit %d\n", | 1231 | dev_dbg(dev, "%s Not enough credit - fifo %d TxCredit %d\n", |
1234 | __func__, edge_port->port->number, fifo->count, | 1232 | __func__, fifo->count, edge_port->txCredits); |
1235 | edge_port->txCredits); | ||
1236 | goto exit_send; | 1233 | goto exit_send; |
1237 | } | 1234 | } |
1238 | 1235 | ||
@@ -1256,10 +1253,8 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, | |||
1256 | edge_port->write_in_progress = false; | 1253 | edge_port->write_in_progress = false; |
1257 | goto exit_send; | 1254 | goto exit_send; |
1258 | } | 1255 | } |
1259 | buffer[0] = IOSP_BUILD_DATA_HDR1(edge_port->port->number | 1256 | buffer[0] = IOSP_BUILD_DATA_HDR1(edge_port->port->port_number, count); |
1260 | - edge_port->port->serial->minor, count); | 1257 | buffer[1] = IOSP_BUILD_DATA_HDR2(edge_port->port->port_number, count); |
1261 | buffer[1] = IOSP_BUILD_DATA_HDR2(edge_port->port->number | ||
1262 | - edge_port->port->serial->minor, count); | ||
1263 | 1258 | ||
1264 | /* now copy our data */ | 1259 | /* now copy our data */ |
1265 | bytesleft = fifo->size - fifo->tail; | 1260 | bytesleft = fifo->size - fifo->tail; |
@@ -1377,8 +1372,7 @@ static int edge_chars_in_buffer(struct tty_struct *tty) | |||
1377 | edge_port->txfifo.count; | 1372 | edge_port->txfifo.count; |
1378 | spin_unlock_irqrestore(&edge_port->ep_lock, flags); | 1373 | spin_unlock_irqrestore(&edge_port->ep_lock, flags); |
1379 | if (num_chars) { | 1374 | if (num_chars) { |
1380 | dev_dbg(&port->dev, "%s(port %d) - returns %d\n", __func__, | 1375 | dev_dbg(&port->dev, "%s - returns %d\n", __func__, num_chars); |
1381 | port->number, num_chars); | ||
1382 | } | 1376 | } |
1383 | 1377 | ||
1384 | return num_chars; | 1378 | return num_chars; |
@@ -1575,8 +1569,8 @@ static int get_serial_info(struct edgeport_port *edge_port, | |||
1575 | memset(&tmp, 0, sizeof(tmp)); | 1569 | memset(&tmp, 0, sizeof(tmp)); |
1576 | 1570 | ||
1577 | tmp.type = PORT_16550A; | 1571 | tmp.type = PORT_16550A; |
1578 | tmp.line = edge_port->port->serial->minor; | 1572 | tmp.line = edge_port->port->minor; |
1579 | tmp.port = edge_port->port->number; | 1573 | tmp.port = edge_port->port->port_number; |
1580 | tmp.irq = 0; | 1574 | tmp.irq = 0; |
1581 | tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; | 1575 | tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; |
1582 | tmp.xmit_fifo_size = edge_port->maxTxCredits; | 1576 | tmp.xmit_fifo_size = edge_port->maxTxCredits; |
@@ -1601,15 +1595,15 @@ static int edge_ioctl(struct tty_struct *tty, | |||
1601 | DEFINE_WAIT(wait); | 1595 | DEFINE_WAIT(wait); |
1602 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | 1596 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); |
1603 | 1597 | ||
1604 | dev_dbg(&port->dev, "%s - port %d, cmd = 0x%x\n", __func__, port->number, cmd); | 1598 | dev_dbg(&port->dev, "%s - cmd = 0x%x\n", __func__, cmd); |
1605 | 1599 | ||
1606 | switch (cmd) { | 1600 | switch (cmd) { |
1607 | case TIOCSERGETLSR: | 1601 | case TIOCSERGETLSR: |
1608 | dev_dbg(&port->dev, "%s (%d) TIOCSERGETLSR\n", __func__, port->number); | 1602 | dev_dbg(&port->dev, "%s TIOCSERGETLSR\n", __func__); |
1609 | return get_lsr_info(edge_port, (unsigned int __user *) arg); | 1603 | return get_lsr_info(edge_port, (unsigned int __user *) arg); |
1610 | 1604 | ||
1611 | case TIOCGSERIAL: | 1605 | case TIOCGSERIAL: |
1612 | dev_dbg(&port->dev, "%s (%d) TIOCGSERIAL\n", __func__, port->number); | 1606 | dev_dbg(&port->dev, "%s TIOCGSERIAL\n", __func__); |
1613 | return get_serial_info(edge_port, (struct serial_struct __user *) arg); | 1607 | return get_serial_info(edge_port, (struct serial_struct __user *) arg); |
1614 | } | 1608 | } |
1615 | return -ENOIOCTLCMD; | 1609 | return -ENOIOCTLCMD; |
@@ -2181,9 +2175,8 @@ static int send_iosp_ext_cmd(struct edgeport_port *edge_port, | |||
2181 | 2175 | ||
2182 | currentCommand = buffer; | 2176 | currentCommand = buffer; |
2183 | 2177 | ||
2184 | MAKE_CMD_EXT_CMD(¤tCommand, &length, | 2178 | MAKE_CMD_EXT_CMD(¤tCommand, &length, edge_port->port->port_number, |
2185 | edge_port->port->number - edge_port->port->serial->minor, | 2179 | command, param); |
2186 | command, param); | ||
2187 | 2180 | ||
2188 | status = write_cmd_usb(edge_port, buffer, length); | 2181 | status = write_cmd_usb(edge_port, buffer, length); |
2189 | if (status) { | 2182 | if (status) { |
@@ -2266,18 +2259,16 @@ static int send_cmd_write_baud_rate(struct edgeport_port *edge_port, | |||
2266 | int cmdLen = 0; | 2259 | int cmdLen = 0; |
2267 | int divisor; | 2260 | int divisor; |
2268 | int status; | 2261 | int status; |
2269 | unsigned char number = | 2262 | u32 number = edge_port->port->port_number; |
2270 | edge_port->port->number - edge_port->port->serial->minor; | ||
2271 | 2263 | ||
2272 | if (edge_serial->is_epic && | 2264 | if (edge_serial->is_epic && |
2273 | !edge_serial->epic_descriptor.Supports.IOSPSetBaudRate) { | 2265 | !edge_serial->epic_descriptor.Supports.IOSPSetBaudRate) { |
2274 | dev_dbg(dev, "SendCmdWriteBaudRate - NOT Setting baud rate for port = %d, baud = %d\n", | 2266 | dev_dbg(dev, "SendCmdWriteBaudRate - NOT Setting baud rate for port, baud = %d\n", |
2275 | edge_port->port->number, baudRate); | 2267 | baudRate); |
2276 | return 0; | 2268 | return 0; |
2277 | } | 2269 | } |
2278 | 2270 | ||
2279 | dev_dbg(dev, "%s - port = %d, baud = %d\n", __func__, | 2271 | dev_dbg(dev, "%s - baud = %d\n", __func__, baudRate); |
2280 | edge_port->port->number, baudRate); | ||
2281 | 2272 | ||
2282 | status = calc_baud_rate_divisor(dev, baudRate, &divisor); | 2273 | status = calc_baud_rate_divisor(dev, baudRate, &divisor); |
2283 | if (status) { | 2274 | if (status) { |
@@ -2388,9 +2379,8 @@ static int send_cmd_write_uart_register(struct edgeport_port *edge_port, | |||
2388 | currCmd = cmdBuffer; | 2379 | currCmd = cmdBuffer; |
2389 | 2380 | ||
2390 | /* Build a cmd in the buffer to write the given register */ | 2381 | /* Build a cmd in the buffer to write the given register */ |
2391 | MAKE_CMD_WRITE_REG(&currCmd, &cmdLen, | 2382 | MAKE_CMD_WRITE_REG(&currCmd, &cmdLen, edge_port->port->port_number, |
2392 | edge_port->port->number - edge_port->port->serial->minor, | 2383 | regNum, regValue); |
2393 | regNum, regValue); | ||
2394 | 2384 | ||
2395 | status = write_cmd_usb(edge_port, cmdBuffer, cmdLen); | 2385 | status = write_cmd_usb(edge_port, cmdBuffer, cmdLen); |
2396 | if (status) { | 2386 | if (status) { |
@@ -2424,8 +2414,6 @@ static void change_port_settings(struct tty_struct *tty, | |||
2424 | __u8 txFlow; | 2414 | __u8 txFlow; |
2425 | int status; | 2415 | int status; |
2426 | 2416 | ||
2427 | dev_dbg(dev, "%s - port %d\n", __func__, edge_port->port->number); | ||
2428 | |||
2429 | if (!edge_port->open && | 2417 | if (!edge_port->open && |
2430 | !edge_port->openPending) { | 2418 | !edge_port->openPending) { |
2431 | dev_dbg(dev, "%s - port not opened\n", __func__); | 2419 | dev_dbg(dev, "%s - port not opened\n", __func__); |
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 1be6ba7bee27..60054e72b75b 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c | |||
@@ -259,7 +259,7 @@ static int send_cmd(struct usb_device *dev, __u8 command, | |||
259 | /* clear tx/rx buffers and fifo in TI UMP */ | 259 | /* clear tx/rx buffers and fifo in TI UMP */ |
260 | static int purge_port(struct usb_serial_port *port, __u16 mask) | 260 | static int purge_port(struct usb_serial_port *port, __u16 mask) |
261 | { | 261 | { |
262 | int port_number = port->number - port->serial->minor; | 262 | int port_number = port->port_number; |
263 | 263 | ||
264 | dev_dbg(&port->dev, "%s - port %d, mask %x\n", __func__, port_number, mask); | 264 | dev_dbg(&port->dev, "%s - port %d, mask %x\n", __func__, port_number, mask); |
265 | 265 | ||
@@ -1392,7 +1392,8 @@ stayinbootmode: | |||
1392 | 1392 | ||
1393 | static int ti_do_config(struct edgeport_port *port, int feature, int on) | 1393 | static int ti_do_config(struct edgeport_port *port, int feature, int on) |
1394 | { | 1394 | { |
1395 | int port_number = port->port->number - port->port->serial->minor; | 1395 | int port_number = port->port->port_number; |
1396 | |||
1396 | on = !!on; /* 1 or 0 not bitmask */ | 1397 | on = !!on; /* 1 or 0 not bitmask */ |
1397 | return send_cmd(port->port->serial->dev, | 1398 | return send_cmd(port->port->serial->dev, |
1398 | feature, (__u8)(UMPM_UART1_PORT + port_number), | 1399 | feature, (__u8)(UMPM_UART1_PORT + port_number), |
@@ -1637,7 +1638,7 @@ static void edge_bulk_in_callback(struct urb *urb) | |||
1637 | return; | 1638 | return; |
1638 | } | 1639 | } |
1639 | 1640 | ||
1640 | port_number = edge_port->port->number - edge_port->port->serial->minor; | 1641 | port_number = edge_port->port->port_number; |
1641 | 1642 | ||
1642 | if (edge_port->lsr_event) { | 1643 | if (edge_port->lsr_event) { |
1643 | edge_port->lsr_event = 0; | 1644 | edge_port->lsr_event = 0; |
@@ -1730,7 +1731,7 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
1730 | if (edge_port == NULL) | 1731 | if (edge_port == NULL) |
1731 | return -ENODEV; | 1732 | return -ENODEV; |
1732 | 1733 | ||
1733 | port_number = port->number - port->serial->minor; | 1734 | port_number = port->port_number; |
1734 | switch (port_number) { | 1735 | switch (port_number) { |
1735 | case 0: | 1736 | case 0: |
1736 | edge_port->uart_base = UMPMEM_BASE_UART1; | 1737 | edge_port->uart_base = UMPMEM_BASE_UART1; |
@@ -1908,7 +1909,7 @@ static void edge_close(struct usb_serial_port *port) | |||
1908 | spin_unlock_irqrestore(&edge_port->ep_lock, flags); | 1909 | spin_unlock_irqrestore(&edge_port->ep_lock, flags); |
1909 | 1910 | ||
1910 | dev_dbg(&port->dev, "%s - send umpc_close_port\n", __func__); | 1911 | dev_dbg(&port->dev, "%s - send umpc_close_port\n", __func__); |
1911 | port_number = port->number - port->serial->minor; | 1912 | port_number = port->port_number; |
1912 | send_cmd(serial->dev, UMPC_CLOSE_PORT, | 1913 | send_cmd(serial->dev, UMPC_CLOSE_PORT, |
1913 | (__u8)(UMPM_UART1_PORT + port_number), 0, NULL, 0); | 1914 | (__u8)(UMPM_UART1_PORT + port_number), 0, NULL, 0); |
1914 | 1915 | ||
@@ -2137,10 +2138,7 @@ static void change_port_settings(struct tty_struct *tty, | |||
2137 | int baud; | 2138 | int baud; |
2138 | unsigned cflag; | 2139 | unsigned cflag; |
2139 | int status; | 2140 | int status; |
2140 | int port_number = edge_port->port->number - | 2141 | int port_number = edge_port->port->port_number; |
2141 | edge_port->port->serial->minor; | ||
2142 | |||
2143 | dev_dbg(dev, "%s - port %d\n", __func__, edge_port->port->number); | ||
2144 | 2142 | ||
2145 | config = kmalloc (sizeof (*config), GFP_KERNEL); | 2143 | config = kmalloc (sizeof (*config), GFP_KERNEL); |
2146 | if (!config) { | 2144 | if (!config) { |
@@ -2284,7 +2282,6 @@ static void edge_set_termios(struct tty_struct *tty, | |||
2284 | tty->termios.c_cflag, tty->termios.c_iflag); | 2282 | tty->termios.c_cflag, tty->termios.c_iflag); |
2285 | dev_dbg(&port->dev, "%s - old clfag %08x old iflag %08x\n", __func__, | 2283 | dev_dbg(&port->dev, "%s - old clfag %08x old iflag %08x\n", __func__, |
2286 | old_termios->c_cflag, old_termios->c_iflag); | 2284 | old_termios->c_cflag, old_termios->c_iflag); |
2287 | dev_dbg(&port->dev, "%s - port %d\n", __func__, port->number); | ||
2288 | 2285 | ||
2289 | if (edge_port == NULL) | 2286 | if (edge_port == NULL) |
2290 | return; | 2287 | return; |
@@ -2366,8 +2363,8 @@ static int get_serial_info(struct edgeport_port *edge_port, | |||
2366 | memset(&tmp, 0, sizeof(tmp)); | 2363 | memset(&tmp, 0, sizeof(tmp)); |
2367 | 2364 | ||
2368 | tmp.type = PORT_16550A; | 2365 | tmp.type = PORT_16550A; |
2369 | tmp.line = edge_port->port->serial->minor; | 2366 | tmp.line = edge_port->port->minor; |
2370 | tmp.port = edge_port->port->number; | 2367 | tmp.port = edge_port->port->port_number; |
2371 | tmp.irq = 0; | 2368 | tmp.irq = 0; |
2372 | tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; | 2369 | tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; |
2373 | tmp.xmit_fifo_size = edge_port->port->bulk_out_size; | 2370 | tmp.xmit_fifo_size = edge_port->port->bulk_out_size; |
@@ -2386,7 +2383,7 @@ static int edge_ioctl(struct tty_struct *tty, | |||
2386 | struct usb_serial_port *port = tty->driver_data; | 2383 | struct usb_serial_port *port = tty->driver_data; |
2387 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | 2384 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); |
2388 | 2385 | ||
2389 | dev_dbg(&port->dev, "%s - port %d, cmd = 0x%x\n", __func__, port->number, cmd); | 2386 | dev_dbg(&port->dev, "%s - cmd = 0x%x\n", __func__, cmd); |
2390 | 2387 | ||
2391 | switch (cmd) { | 2388 | switch (cmd) { |
2392 | case TIOCGSERIAL: | 2389 | case TIOCGSERIAL: |
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 3549d073df22..5a979729f8ec 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c | |||
@@ -152,7 +152,7 @@ static void keyspan_set_termios(struct tty_struct *tty, | |||
152 | p_priv = usb_get_serial_port_data(port); | 152 | p_priv = usb_get_serial_port_data(port); |
153 | d_details = p_priv->device_details; | 153 | d_details = p_priv->device_details; |
154 | cflag = tty->termios.c_cflag; | 154 | cflag = tty->termios.c_cflag; |
155 | device_port = port->number - port->serial->minor; | 155 | device_port = port->port_number; |
156 | 156 | ||
157 | /* Baud rate calculation takes baud rate as an integer | 157 | /* Baud rate calculation takes baud rate as an integer |
158 | so other rates can be generated if desired. */ | 158 | so other rates can be generated if desired. */ |
@@ -234,8 +234,8 @@ static int keyspan_write(struct tty_struct *tty, | |||
234 | dataOffset = 1; | 234 | dataOffset = 1; |
235 | } | 235 | } |
236 | 236 | ||
237 | dev_dbg(&port->dev, "%s - for port %d (%d chars), flip=%d\n", | 237 | dev_dbg(&port->dev, "%s - %d chars, flip=%d\n", __func__, count, |
238 | __func__, port->number, count, p_priv->out_flip); | 238 | p_priv->out_flip); |
239 | 239 | ||
240 | for (left = count; left > 0; left -= todo) { | 240 | for (left = count; left > 0; left -= todo) { |
241 | todo = left; | 241 | todo = left; |
@@ -520,12 +520,7 @@ static void usa28_instat_callback(struct urb *urb) | |||
520 | goto exit; | 520 | goto exit; |
521 | } | 521 | } |
522 | 522 | ||
523 | /* | 523 | /*dev_dbg(&urb->dev->dev, "%s %12ph", __func__, data);*/ |
524 | dev_dbg(&urb->dev->dev, | ||
525 | "%s %x %x %x %x %x %x %x %x %x %x %x %x", __func__, | ||
526 | data[0], data[1], data[2], data[3], data[4], data[5], | ||
527 | data[6], data[7], data[8], data[9], data[10], data[11]); | ||
528 | */ | ||
529 | 524 | ||
530 | /* Now do something useful with the data */ | 525 | /* Now do something useful with the data */ |
531 | msg = (struct keyspan_usa28_portStatusMessage *)data; | 526 | msg = (struct keyspan_usa28_portStatusMessage *)data; |
@@ -607,11 +602,7 @@ static void usa49_instat_callback(struct urb *urb) | |||
607 | goto exit; | 602 | goto exit; |
608 | } | 603 | } |
609 | 604 | ||
610 | /* | 605 | /*dev_dbg(&urb->dev->dev, "%s: %11ph", __func__, data);*/ |
611 | dev_dbg(&urb->dev->dev, "%s: %x %x %x %x %x %x %x %x %x %x %x", | ||
612 | __func__, data[0], data[1], data[2], data[3], data[4], | ||
613 | data[5], data[6], data[7], data[8], data[9], data[10]); | ||
614 | */ | ||
615 | 606 | ||
616 | /* Now do something useful with the data */ | 607 | /* Now do something useful with the data */ |
617 | msg = (struct keyspan_usa49_portStatusMessage *)data; | 608 | msg = (struct keyspan_usa49_portStatusMessage *)data; |
@@ -1050,7 +1041,7 @@ static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
1050 | /* get the terminal config for the setup message now so we don't | 1041 | /* get the terminal config for the setup message now so we don't |
1051 | * need to send 2 of them */ | 1042 | * need to send 2 of them */ |
1052 | 1043 | ||
1053 | device_port = port->number - port->serial->minor; | 1044 | device_port = port->port_number; |
1054 | if (tty) { | 1045 | if (tty) { |
1055 | cflag = tty->termios.c_cflag; | 1046 | cflag = tty->termios.c_cflag; |
1056 | /* Baud rate calculation takes baud rate as an integer | 1047 | /* Baud rate calculation takes baud rate as an integer |
@@ -1556,7 +1547,7 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial, | |||
1556 | s_priv = usb_get_serial_data(serial); | 1547 | s_priv = usb_get_serial_data(serial); |
1557 | p_priv = usb_get_serial_port_data(port); | 1548 | p_priv = usb_get_serial_port_data(port); |
1558 | d_details = s_priv->device_details; | 1549 | d_details = s_priv->device_details; |
1559 | device_port = port->number - port->serial->minor; | 1550 | device_port = port->port_number; |
1560 | 1551 | ||
1561 | this_urb = p_priv->outcont_urb; | 1552 | this_urb = p_priv->outcont_urb; |
1562 | 1553 | ||
@@ -1700,7 +1691,7 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial, | |||
1700 | s_priv = usb_get_serial_data(serial); | 1691 | s_priv = usb_get_serial_data(serial); |
1701 | p_priv = usb_get_serial_port_data(port); | 1692 | p_priv = usb_get_serial_port_data(port); |
1702 | d_details = s_priv->device_details; | 1693 | d_details = s_priv->device_details; |
1703 | device_port = port->number - port->serial->minor; | 1694 | device_port = port->port_number; |
1704 | 1695 | ||
1705 | /* only do something if we have a bulk out endpoint */ | 1696 | /* only do something if we have a bulk out endpoint */ |
1706 | this_urb = p_priv->outcont_urb; | 1697 | this_urb = p_priv->outcont_urb; |
@@ -1830,17 +1821,16 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial, | |||
1830 | this_urb = s_priv->glocont_urb; | 1821 | this_urb = s_priv->glocont_urb; |
1831 | 1822 | ||
1832 | /* Work out which port within the device is being setup */ | 1823 | /* Work out which port within the device is being setup */ |
1833 | device_port = port->number - port->serial->minor; | 1824 | device_port = port->port_number; |
1834 | 1825 | ||
1835 | /* Make sure we have an urb then send the message */ | 1826 | /* Make sure we have an urb then send the message */ |
1836 | if (this_urb == NULL) { | 1827 | if (this_urb == NULL) { |
1837 | dev_dbg(&port->dev, "%s - oops no urb for port %d.\n", __func__, port->number); | 1828 | dev_dbg(&port->dev, "%s - oops no urb for port.\n", __func__); |
1838 | return -1; | 1829 | return -1; |
1839 | } | 1830 | } |
1840 | 1831 | ||
1841 | dev_dbg(&port->dev, "%s - endpoint %d port %d (%d)\n", | 1832 | dev_dbg(&port->dev, "%s - endpoint %d (%d)\n", |
1842 | __func__, usb_pipeendpoint(this_urb->pipe), | 1833 | __func__, usb_pipeendpoint(this_urb->pipe), device_port); |
1843 | port->number, device_port); | ||
1844 | 1834 | ||
1845 | /* Save reset port val for resend. | 1835 | /* Save reset port val for resend. |
1846 | Don't overwrite resend for open/close condition. */ | 1836 | Don't overwrite resend for open/close condition. */ |
@@ -1855,7 +1845,6 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial, | |||
1855 | 1845 | ||
1856 | memset(&msg, 0, sizeof(struct keyspan_usa49_portControlMessage)); | 1846 | memset(&msg, 0, sizeof(struct keyspan_usa49_portControlMessage)); |
1857 | 1847 | ||
1858 | /*msg.portNumber = port->number;*/ | ||
1859 | msg.portNumber = device_port; | 1848 | msg.portNumber = device_port; |
1860 | 1849 | ||
1861 | /* Only set baud rate if it's changed */ | 1850 | /* Only set baud rate if it's changed */ |
@@ -2145,12 +2134,11 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial, | |||
2145 | this_urb = s_priv->glocont_urb; | 2134 | this_urb = s_priv->glocont_urb; |
2146 | 2135 | ||
2147 | /* Work out which port within the device is being setup */ | 2136 | /* Work out which port within the device is being setup */ |
2148 | device_port = port->number - port->serial->minor; | 2137 | device_port = port->port_number; |
2149 | 2138 | ||
2150 | /* Make sure we have an urb then send the message */ | 2139 | /* Make sure we have an urb then send the message */ |
2151 | if (this_urb == NULL) { | 2140 | if (this_urb == NULL) { |
2152 | dev_dbg(&port->dev, "%s - oops no urb for port %d.\n", __func__, | 2141 | dev_dbg(&port->dev, "%s - oops no urb for port.\n", __func__); |
2153 | port->number); | ||
2154 | return -1; | 2142 | return -1; |
2155 | } | 2143 | } |
2156 | 2144 | ||
@@ -2391,7 +2379,7 @@ static int keyspan_port_probe(struct usb_serial_port *port) | |||
2391 | /* Setup values for the various callback routines */ | 2379 | /* Setup values for the various callback routines */ |
2392 | cback = &keyspan_callbacks[d_details->msg_format]; | 2380 | cback = &keyspan_callbacks[d_details->msg_format]; |
2393 | 2381 | ||
2394 | port_num = port->number - port->serial->minor; | 2382 | port_num = port->port_number; |
2395 | 2383 | ||
2396 | /* Do indat endpoints first, once for each flip */ | 2384 | /* Do indat endpoints first, once for each flip */ |
2397 | endp = d_details->indat_endpoints[port_num]; | 2385 | endp = d_details->indat_endpoints[port_num]; |
diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index 47e247759eb0..40ccf6e5e318 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c | |||
@@ -224,8 +224,8 @@ static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
224 | result = metrousb_send_unidirectional_cmd(UNI_CMD_OPEN, port); | 224 | result = metrousb_send_unidirectional_cmd(UNI_CMD_OPEN, port); |
225 | if (result) { | 225 | if (result) { |
226 | dev_err(&port->dev, | 226 | dev_err(&port->dev, |
227 | "%s - failed to configure device for port number=%d, error code=%d\n", | 227 | "%s - failed to configure device, error code=%d\n", |
228 | __func__, port->number, result); | 228 | __func__, result); |
229 | goto exit; | 229 | goto exit; |
230 | } | 230 | } |
231 | 231 | ||
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index f27c621a9297..51da424327b0 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c | |||
@@ -1047,7 +1047,7 @@ static int mos7720_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
1047 | * | 1047 | * |
1048 | * 0x08 : SP1/2 Control Reg | 1048 | * 0x08 : SP1/2 Control Reg |
1049 | */ | 1049 | */ |
1050 | port_number = port->number - port->serial->minor; | 1050 | port_number = port->port_number; |
1051 | read_mos_reg(serial, port_number, LSR, &data); | 1051 | read_mos_reg(serial, port_number, LSR, &data); |
1052 | 1052 | ||
1053 | dev_dbg(&port->dev, "SS::%p LSR:%x\n", mos7720_port, data); | 1053 | dev_dbg(&port->dev, "SS::%p LSR:%x\n", mos7720_port, data); |
@@ -1066,7 +1066,7 @@ static int mos7720_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
1066 | 1066 | ||
1067 | write_mos_reg(serial, port_number, SP_CONTROL_REG, 0x00); | 1067 | write_mos_reg(serial, port_number, SP_CONTROL_REG, 0x00); |
1068 | read_mos_reg(serial, dummy, SP_CONTROL_REG, &data); | 1068 | read_mos_reg(serial, dummy, SP_CONTROL_REG, &data); |
1069 | data = data | (port->number - port->serial->minor + 1); | 1069 | data = data | (port->port_number + 1); |
1070 | write_mos_reg(serial, dummy, SP_CONTROL_REG, data); | 1070 | write_mos_reg(serial, dummy, SP_CONTROL_REG, data); |
1071 | mos7720_port->shadowLCR = 0x83; | 1071 | mos7720_port->shadowLCR = 0x83; |
1072 | write_mos_reg(serial, port_number, LCR, mos7720_port->shadowLCR); | 1072 | write_mos_reg(serial, port_number, LCR, mos7720_port->shadowLCR); |
@@ -1147,8 +1147,8 @@ static void mos7720_close(struct usb_serial_port *port) | |||
1147 | usb_kill_urb(port->write_urb); | 1147 | usb_kill_urb(port->write_urb); |
1148 | usb_kill_urb(port->read_urb); | 1148 | usb_kill_urb(port->read_urb); |
1149 | 1149 | ||
1150 | write_mos_reg(serial, port->number - port->serial->minor, MCR, 0x00); | 1150 | write_mos_reg(serial, port->port_number, MCR, 0x00); |
1151 | write_mos_reg(serial, port->number - port->serial->minor, IER, 0x00); | 1151 | write_mos_reg(serial, port->port_number, IER, 0x00); |
1152 | 1152 | ||
1153 | mos7720_port->open = 0; | 1153 | mos7720_port->open = 0; |
1154 | } | 1154 | } |
@@ -1172,8 +1172,7 @@ static void mos7720_break(struct tty_struct *tty, int break_state) | |||
1172 | data = mos7720_port->shadowLCR & ~UART_LCR_SBC; | 1172 | data = mos7720_port->shadowLCR & ~UART_LCR_SBC; |
1173 | 1173 | ||
1174 | mos7720_port->shadowLCR = data; | 1174 | mos7720_port->shadowLCR = data; |
1175 | write_mos_reg(serial, port->number - port->serial->minor, | 1175 | write_mos_reg(serial, port->port_number, LCR, mos7720_port->shadowLCR); |
1176 | LCR, mos7720_port->shadowLCR); | ||
1177 | } | 1176 | } |
1178 | 1177 | ||
1179 | /* | 1178 | /* |
@@ -1304,8 +1303,8 @@ static void mos7720_throttle(struct tty_struct *tty) | |||
1304 | /* if we are implementing RTS/CTS, toggle that line */ | 1303 | /* if we are implementing RTS/CTS, toggle that line */ |
1305 | if (tty->termios.c_cflag & CRTSCTS) { | 1304 | if (tty->termios.c_cflag & CRTSCTS) { |
1306 | mos7720_port->shadowMCR &= ~UART_MCR_RTS; | 1305 | mos7720_port->shadowMCR &= ~UART_MCR_RTS; |
1307 | write_mos_reg(port->serial, port->number - port->serial->minor, | 1306 | write_mos_reg(port->serial, port->port_number, MCR, |
1308 | MCR, mos7720_port->shadowMCR); | 1307 | mos7720_port->shadowMCR); |
1309 | if (status != 0) | 1308 | if (status != 0) |
1310 | return; | 1309 | return; |
1311 | } | 1310 | } |
@@ -1336,8 +1335,8 @@ static void mos7720_unthrottle(struct tty_struct *tty) | |||
1336 | /* if we are implementing RTS/CTS, toggle that line */ | 1335 | /* if we are implementing RTS/CTS, toggle that line */ |
1337 | if (tty->termios.c_cflag & CRTSCTS) { | 1336 | if (tty->termios.c_cflag & CRTSCTS) { |
1338 | mos7720_port->shadowMCR |= UART_MCR_RTS; | 1337 | mos7720_port->shadowMCR |= UART_MCR_RTS; |
1339 | write_mos_reg(port->serial, port->number - port->serial->minor, | 1338 | write_mos_reg(port->serial, port->port_number, MCR, |
1340 | MCR, mos7720_port->shadowMCR); | 1339 | mos7720_port->shadowMCR); |
1341 | if (status != 0) | 1340 | if (status != 0) |
1342 | return; | 1341 | return; |
1343 | } | 1342 | } |
@@ -1361,7 +1360,7 @@ static int set_higher_rates(struct moschip_port *mos7720_port, | |||
1361 | * Init Sequence for higher rates | 1360 | * Init Sequence for higher rates |
1362 | ***********************************************/ | 1361 | ***********************************************/ |
1363 | dev_dbg(&port->dev, "Sending Setting Commands ..........\n"); | 1362 | dev_dbg(&port->dev, "Sending Setting Commands ..........\n"); |
1364 | port_number = port->number - port->serial->minor; | 1363 | port_number = port->port_number; |
1365 | 1364 | ||
1366 | write_mos_reg(serial, port_number, IER, 0x00); | 1365 | write_mos_reg(serial, port_number, IER, 0x00); |
1367 | write_mos_reg(serial, port_number, FCR, 0x00); | 1366 | write_mos_reg(serial, port_number, FCR, 0x00); |
@@ -1487,7 +1486,7 @@ static int send_cmd_write_baud_rate(struct moschip_port *mos7720_port, | |||
1487 | port = mos7720_port->port; | 1486 | port = mos7720_port->port; |
1488 | serial = port->serial; | 1487 | serial = port->serial; |
1489 | 1488 | ||
1490 | number = port->number - port->serial->minor; | 1489 | number = port->port_number; |
1491 | dev_dbg(&port->dev, "%s - baud = %d\n", __func__, baudrate); | 1490 | dev_dbg(&port->dev, "%s - baud = %d\n", __func__, baudrate); |
1492 | 1491 | ||
1493 | /* Calculate the Divisor */ | 1492 | /* Calculate the Divisor */ |
@@ -1538,7 +1537,7 @@ static void change_port_settings(struct tty_struct *tty, | |||
1538 | 1537 | ||
1539 | port = mos7720_port->port; | 1538 | port = mos7720_port->port; |
1540 | serial = port->serial; | 1539 | serial = port->serial; |
1541 | port_number = port->number - port->serial->minor; | 1540 | port_number = port->port_number; |
1542 | 1541 | ||
1543 | if (!mos7720_port->open) { | 1542 | if (!mos7720_port->open) { |
1544 | dev_dbg(&port->dev, "%s - port not opened\n", __func__); | 1543 | dev_dbg(&port->dev, "%s - port not opened\n", __func__); |
@@ -1731,7 +1730,7 @@ static int get_lsr_info(struct tty_struct *tty, | |||
1731 | struct usb_serial_port *port = tty->driver_data; | 1730 | struct usb_serial_port *port = tty->driver_data; |
1732 | unsigned int result = 0; | 1731 | unsigned int result = 0; |
1733 | unsigned char data = 0; | 1732 | unsigned char data = 0; |
1734 | int port_number = port->number - port->serial->minor; | 1733 | int port_number = port->port_number; |
1735 | int count; | 1734 | int count; |
1736 | 1735 | ||
1737 | count = mos7720_chars_in_buffer(tty); | 1736 | count = mos7720_chars_in_buffer(tty); |
@@ -1793,8 +1792,8 @@ static int mos7720_tiocmset(struct tty_struct *tty, | |||
1793 | mcr &= ~UART_MCR_LOOP; | 1792 | mcr &= ~UART_MCR_LOOP; |
1794 | 1793 | ||
1795 | mos7720_port->shadowMCR = mcr; | 1794 | mos7720_port->shadowMCR = mcr; |
1796 | write_mos_reg(port->serial, port->number - port->serial->minor, | 1795 | write_mos_reg(port->serial, port->port_number, MCR, |
1797 | MCR, mos7720_port->shadowMCR); | 1796 | mos7720_port->shadowMCR); |
1798 | 1797 | ||
1799 | return 0; | 1798 | return 0; |
1800 | } | 1799 | } |
@@ -1838,8 +1837,8 @@ static int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd, | |||
1838 | } | 1837 | } |
1839 | 1838 | ||
1840 | mos7720_port->shadowMCR = mcr; | 1839 | mos7720_port->shadowMCR = mcr; |
1841 | write_mos_reg(port->serial, port->number - port->serial->minor, | 1840 | write_mos_reg(port->serial, port->port_number, MCR, |
1842 | MCR, mos7720_port->shadowMCR); | 1841 | mos7720_port->shadowMCR); |
1843 | 1842 | ||
1844 | return 0; | 1843 | return 0; |
1845 | } | 1844 | } |
@@ -1855,8 +1854,8 @@ static int get_serial_info(struct moschip_port *mos7720_port, | |||
1855 | memset(&tmp, 0, sizeof(tmp)); | 1854 | memset(&tmp, 0, sizeof(tmp)); |
1856 | 1855 | ||
1857 | tmp.type = PORT_16550A; | 1856 | tmp.type = PORT_16550A; |
1858 | tmp.line = mos7720_port->port->serial->minor; | 1857 | tmp.line = mos7720_port->port->minor; |
1859 | tmp.port = mos7720_port->port->number; | 1858 | tmp.port = mos7720_port->port->port_number; |
1860 | tmp.irq = 0; | 1859 | tmp.irq = 0; |
1861 | tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; | 1860 | tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; |
1862 | tmp.xmit_fifo_size = NUM_URBS * URB_TRANSFER_BUFFER_SIZE; | 1861 | tmp.xmit_fifo_size = NUM_URBS * URB_TRANSFER_BUFFER_SIZE; |
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 7e998081e1cd..0a818b238508 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c | |||
@@ -303,15 +303,12 @@ static int mos7840_set_uart_reg(struct usb_serial_port *port, __u16 reg, | |||
303 | /* For the UART control registers, the application number need | 303 | /* For the UART control registers, the application number need |
304 | to be Or'ed */ | 304 | to be Or'ed */ |
305 | if (port->serial->num_ports == 4) { | 305 | if (port->serial->num_ports == 4) { |
306 | val |= (((__u16) port->number - | 306 | val |= ((__u16)port->port_number + 1) << 8; |
307 | (__u16) (port->serial->minor)) + 1) << 8; | ||
308 | } else { | 307 | } else { |
309 | if (((__u16) port->number - (__u16) (port->serial->minor)) == 0) { | 308 | if (port->port_number == 0) { |
310 | val |= (((__u16) port->number - | 309 | val |= ((__u16)port->port_number + 1) << 8; |
311 | (__u16) (port->serial->minor)) + 1) << 8; | ||
312 | } else { | 310 | } else { |
313 | val |= (((__u16) port->number - | 311 | val |= ((__u16)port->port_number + 2) << 8; |
314 | (__u16) (port->serial->minor)) + 2) << 8; | ||
315 | } | 312 | } |
316 | } | 313 | } |
317 | dev_dbg(&port->dev, "%s application number is %x\n", __func__, val); | 314 | dev_dbg(&port->dev, "%s application number is %x\n", __func__, val); |
@@ -340,16 +337,12 @@ static int mos7840_get_uart_reg(struct usb_serial_port *port, __u16 reg, | |||
340 | 337 | ||
341 | /* Wval is same as application number */ | 338 | /* Wval is same as application number */ |
342 | if (port->serial->num_ports == 4) { | 339 | if (port->serial->num_ports == 4) { |
343 | Wval = | 340 | Wval = ((__u16)port->port_number + 1) << 8; |
344 | (((__u16) port->number - (__u16) (port->serial->minor)) + | ||
345 | 1) << 8; | ||
346 | } else { | 341 | } else { |
347 | if (((__u16) port->number - (__u16) (port->serial->minor)) == 0) { | 342 | if (port->port_number == 0) { |
348 | Wval = (((__u16) port->number - | 343 | Wval = ((__u16)port->port_number + 1) << 8; |
349 | (__u16) (port->serial->minor)) + 1) << 8; | ||
350 | } else { | 344 | } else { |
351 | Wval = (((__u16) port->number - | 345 | Wval = ((__u16)port->port_number + 2) << 8; |
352 | (__u16) (port->serial->minor)) + 2) << 8; | ||
353 | } | 346 | } |
354 | } | 347 | } |
355 | dev_dbg(&port->dev, "%s application number is %x\n", __func__, Wval); | 348 | dev_dbg(&port->dev, "%s application number is %x\n", __func__, Wval); |
@@ -631,9 +624,7 @@ static void mos7840_interrupt_callback(struct urb *urb) | |||
631 | 624 | ||
632 | for (i = 0; i < serial->num_ports; i++) { | 625 | for (i = 0; i < serial->num_ports; i++) { |
633 | mos7840_port = mos7840_get_port_private(serial->port[i]); | 626 | mos7840_port = mos7840_get_port_private(serial->port[i]); |
634 | wval = | 627 | wval = ((__u16)serial->port[i]->port_number + 1) << 8; |
635 | (((__u16) serial->port[i]->number - | ||
636 | (__u16) (serial->minor)) + 1) << 8; | ||
637 | if (mos7840_port->open) { | 628 | if (mos7840_port->open) { |
638 | if (sp[i] & 0x01) { | 629 | if (sp[i] & 0x01) { |
639 | dev_dbg(&urb->dev->dev, "SP%d No Interrupt !!!\n", i); | 630 | dev_dbg(&urb->dev->dev, "SP%d No Interrupt !!!\n", i); |
@@ -1065,8 +1056,8 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
1065 | * (can't set it up in mos7840_startup as the * | 1056 | * (can't set it up in mos7840_startup as the * |
1066 | * structures were not set up at that time.) */ | 1057 | * structures were not set up at that time.) */ |
1067 | 1058 | ||
1068 | dev_dbg(&port->dev, "port number is %d\n", port->number); | 1059 | dev_dbg(&port->dev, "port number is %d\n", port->port_number); |
1069 | dev_dbg(&port->dev, "serial number is %d\n", port->serial->minor); | 1060 | dev_dbg(&port->dev, "minor number is %d\n", port->minor); |
1070 | dev_dbg(&port->dev, "Bulkin endpoint is %d\n", port->bulk_in_endpointAddress); | 1061 | dev_dbg(&port->dev, "Bulkin endpoint is %d\n", port->bulk_in_endpointAddress); |
1071 | dev_dbg(&port->dev, "BulkOut endpoint is %d\n", port->bulk_out_endpointAddress); | 1062 | dev_dbg(&port->dev, "BulkOut endpoint is %d\n", port->bulk_out_endpointAddress); |
1072 | dev_dbg(&port->dev, "Interrupt endpoint is %d\n", port->interrupt_in_endpointAddress); | 1063 | dev_dbg(&port->dev, "Interrupt endpoint is %d\n", port->interrupt_in_endpointAddress); |
@@ -1074,9 +1065,7 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
1074 | mos7840_port->read_urb = port->read_urb; | 1065 | mos7840_port->read_urb = port->read_urb; |
1075 | 1066 | ||
1076 | /* set up our bulk in urb */ | 1067 | /* set up our bulk in urb */ |
1077 | if ((serial->num_ports == 2) | 1068 | if ((serial->num_ports == 2) && (((__u16)port->port_number % 2) != 0)) { |
1078 | && ((((__u16)port->number - | ||
1079 | (__u16)(port->serial->minor)) % 2) != 0)) { | ||
1080 | usb_fill_bulk_urb(mos7840_port->read_urb, | 1069 | usb_fill_bulk_urb(mos7840_port->read_urb, |
1081 | serial->dev, | 1070 | serial->dev, |
1082 | usb_rcvbulkpipe(serial->dev, | 1071 | usb_rcvbulkpipe(serial->dev, |
@@ -1199,7 +1188,7 @@ static void mos7840_close(struct usb_serial_port *port) | |||
1199 | mos7840_port->read_urb_busy = false; | 1188 | mos7840_port->read_urb_busy = false; |
1200 | 1189 | ||
1201 | port0->open_ports--; | 1190 | port0->open_ports--; |
1202 | dev_dbg(&port->dev, "%s in close%d:in port%d\n", __func__, port0->open_ports, port->number); | 1191 | dev_dbg(&port->dev, "%s in close%d\n", __func__, port0->open_ports); |
1203 | if (port0->open_ports == 0) { | 1192 | if (port0->open_ports == 0) { |
1204 | if (serial->port[0]->interrupt_in_urb) { | 1193 | if (serial->port[0]->interrupt_in_urb) { |
1205 | dev_dbg(&port->dev, "Shutdown interrupt_in_urb\n"); | 1194 | dev_dbg(&port->dev, "Shutdown interrupt_in_urb\n"); |
@@ -1435,9 +1424,7 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
1435 | memcpy(urb->transfer_buffer, current_position, transfer_size); | 1424 | memcpy(urb->transfer_buffer, current_position, transfer_size); |
1436 | 1425 | ||
1437 | /* fill urb with data and submit */ | 1426 | /* fill urb with data and submit */ |
1438 | if ((serial->num_ports == 2) | 1427 | if ((serial->num_ports == 2) && (((__u16)port->port_number % 2) != 0)) { |
1439 | && ((((__u16)port->number - | ||
1440 | (__u16)(port->serial->minor)) % 2) != 0)) { | ||
1441 | usb_fill_bulk_urb(urb, | 1428 | usb_fill_bulk_urb(urb, |
1442 | serial->dev, | 1429 | serial->dev, |
1443 | usb_sndbulkpipe(serial->dev, | 1430 | usb_sndbulkpipe(serial->dev, |
@@ -1732,10 +1719,9 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port, | |||
1732 | if (mos7840_serial_paranoia_check(port->serial, __func__)) | 1719 | if (mos7840_serial_paranoia_check(port->serial, __func__)) |
1733 | return -1; | 1720 | return -1; |
1734 | 1721 | ||
1735 | number = mos7840_port->port->number - mos7840_port->port->serial->minor; | 1722 | number = mos7840_port->port->port_number; |
1736 | 1723 | ||
1737 | dev_dbg(&port->dev, "%s - port = %d, baud = %d\n", __func__, | 1724 | dev_dbg(&port->dev, "%s - baud = %d\n", __func__, baudRate); |
1738 | mos7840_port->port->number, baudRate); | ||
1739 | /* reset clk_uart_sel in spregOffset */ | 1725 | /* reset clk_uart_sel in spregOffset */ |
1740 | if (baudRate > 115200) { | 1726 | if (baudRate > 115200) { |
1741 | #ifdef HW_flow_control | 1727 | #ifdef HW_flow_control |
@@ -2016,7 +2002,6 @@ static void mos7840_set_termios(struct tty_struct *tty, | |||
2016 | tty->termios.c_cflag, RELEVANT_IFLAG(tty->termios.c_iflag)); | 2002 | tty->termios.c_cflag, RELEVANT_IFLAG(tty->termios.c_iflag)); |
2017 | dev_dbg(&port->dev, "%s - old clfag %08x old iflag %08x\n", __func__, | 2003 | dev_dbg(&port->dev, "%s - old clfag %08x old iflag %08x\n", __func__, |
2018 | old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag)); | 2004 | old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag)); |
2019 | dev_dbg(&port->dev, "%s - port %d\n", __func__, port->number); | ||
2020 | 2005 | ||
2021 | /* change the port settings to the new ones specified */ | 2006 | /* change the port settings to the new ones specified */ |
2022 | 2007 | ||
@@ -2083,8 +2068,8 @@ static int mos7840_get_serial_info(struct moschip_port *mos7840_port, | |||
2083 | memset(&tmp, 0, sizeof(tmp)); | 2068 | memset(&tmp, 0, sizeof(tmp)); |
2084 | 2069 | ||
2085 | tmp.type = PORT_16550A; | 2070 | tmp.type = PORT_16550A; |
2086 | tmp.line = mos7840_port->port->serial->minor; | 2071 | tmp.line = mos7840_port->port->minor; |
2087 | tmp.port = mos7840_port->port->number; | 2072 | tmp.port = mos7840_port->port->port_number; |
2088 | tmp.irq = 0; | 2073 | tmp.irq = 0; |
2089 | tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; | 2074 | tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; |
2090 | tmp.xmit_fifo_size = NUM_URBS * URB_TRANSFER_BUFFER_SIZE; | 2075 | tmp.xmit_fifo_size = NUM_URBS * URB_TRANSFER_BUFFER_SIZE; |
@@ -2240,7 +2225,7 @@ static int mos7840_port_probe(struct usb_serial_port *port) | |||
2240 | /* we set up the pointers to the endpoints in the mos7840_open * | 2225 | /* we set up the pointers to the endpoints in the mos7840_open * |
2241 | * function, as the structures aren't created yet. */ | 2226 | * function, as the structures aren't created yet. */ |
2242 | 2227 | ||
2243 | pnum = port->number - serial->minor; | 2228 | pnum = port->port_number; |
2244 | 2229 | ||
2245 | dev_dbg(&port->dev, "mos7840_startup: configuring port %d\n", pnum); | 2230 | dev_dbg(&port->dev, "mos7840_startup: configuring port %d\n", pnum); |
2246 | mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); | 2231 | mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); |
@@ -2261,10 +2246,8 @@ static int mos7840_port_probe(struct usb_serial_port *port) | |||
2261 | * usb-serial.c:get_free_serial() and cannot therefore be used | 2246 | * usb-serial.c:get_free_serial() and cannot therefore be used |
2262 | * to index device instances */ | 2247 | * to index device instances */ |
2263 | mos7840_port->port_num = pnum + 1; | 2248 | mos7840_port->port_num = pnum + 1; |
2264 | dev_dbg(&port->dev, "port->number = %d\n", port->number); | 2249 | dev_dbg(&port->dev, "port->minor = %d\n", port->minor); |
2265 | dev_dbg(&port->dev, "port->serial->minor = %d\n", port->serial->minor); | ||
2266 | dev_dbg(&port->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num); | 2250 | dev_dbg(&port->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num); |
2267 | dev_dbg(&port->dev, "serial->minor = %d\n", serial->minor); | ||
2268 | 2251 | ||
2269 | if (mos7840_port->port_num == 1) { | 2252 | if (mos7840_port->port_num == 1) { |
2270 | mos7840_port->SpRegOffset = 0x0; | 2253 | mos7840_port->SpRegOffset = 0x0; |
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 5f4b0cd0f6e9..cbe779f578f9 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c | |||
@@ -348,7 +348,7 @@ static int get_serial_info(struct usb_serial_port *port, | |||
348 | 348 | ||
349 | /* fake emulate a 16550 uart to make userspace code happy */ | 349 | /* fake emulate a 16550 uart to make userspace code happy */ |
350 | tmp.type = PORT_16550A; | 350 | tmp.type = PORT_16550A; |
351 | tmp.line = port->serial->minor; | 351 | tmp.line = port->minor; |
352 | tmp.port = 0; | 352 | tmp.port = 0; |
353 | tmp.irq = 0; | 353 | tmp.irq = 0; |
354 | tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; | 354 | tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; |
@@ -367,7 +367,7 @@ static int opticon_ioctl(struct tty_struct *tty, | |||
367 | { | 367 | { |
368 | struct usb_serial_port *port = tty->driver_data; | 368 | struct usb_serial_port *port = tty->driver_data; |
369 | 369 | ||
370 | dev_dbg(&port->dev, "%s - port %d, cmd = 0x%x\n", __func__, port->number, cmd); | 370 | dev_dbg(&port->dev, "%s - cmd = 0x%x\n", __func__, cmd); |
371 | 371 | ||
372 | switch (cmd) { | 372 | switch (cmd) { |
373 | case TIOCGSERIAL: | 373 | case TIOCGSERIAL: |
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index bd4323ddae1a..5dd857de05b0 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c | |||
@@ -159,8 +159,6 @@ static void option_instat_callback(struct urb *urb); | |||
159 | #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED 0x9000 | 159 | #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED 0x9000 |
160 | #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED 0x9001 | 160 | #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED 0x9001 |
161 | #define NOVATELWIRELESS_PRODUCT_E362 0x9010 | 161 | #define NOVATELWIRELESS_PRODUCT_E362 0x9010 |
162 | #define NOVATELWIRELESS_PRODUCT_G1 0xA001 | ||
163 | #define NOVATELWIRELESS_PRODUCT_G1_M 0xA002 | ||
164 | #define NOVATELWIRELESS_PRODUCT_G2 0xA010 | 162 | #define NOVATELWIRELESS_PRODUCT_G2 0xA010 |
165 | #define NOVATELWIRELESS_PRODUCT_MC551 0xB001 | 163 | #define NOVATELWIRELESS_PRODUCT_MC551 0xB001 |
166 | 164 | ||
@@ -730,8 +728,6 @@ static const struct usb_device_id option_ids[] = { | |||
730 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC547) }, | 728 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC547) }, |
731 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED) }, | 729 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED) }, |
732 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED) }, | 730 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED) }, |
733 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G1) }, | ||
734 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G1_M) }, | ||
735 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G2) }, | 731 | { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G2) }, |
736 | /* Novatel Ovation MC551 a.k.a. Verizon USB551L */ | 732 | /* Novatel Ovation MC551 a.k.a. Verizon USB551L */ |
737 | { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC551, 0xff, 0xff, 0xff) }, | 733 | { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC551, 0xff, 0xff, 0xff) }, |
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 048cd44d51b1..cb6bbed374f2 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c | |||
@@ -275,7 +275,7 @@ static void pl2303_set_termios(struct tty_struct *tty, | |||
275 | u8 control; | 275 | u8 control; |
276 | const int baud_sup[] = { 75, 150, 300, 600, 1200, 1800, 2400, 3600, | 276 | const int baud_sup[] = { 75, 150, 300, 600, 1200, 1800, 2400, 3600, |
277 | 4800, 7200, 9600, 14400, 19200, 28800, 38400, | 277 | 4800, 7200, 9600, 14400, 19200, 28800, 38400, |
278 | 57600, 115200, 230400, 460800, 614400, | 278 | 57600, 115200, 230400, 460800, 500000, 614400, |
279 | 921600, 1228800, 2457600, 3000000, 6000000 }; | 279 | 921600, 1228800, 2457600, 3000000, 6000000 }; |
280 | int baud_floor, baud_ceil; | 280 | int baud_floor, baud_ceil; |
281 | int k; | 281 | int k; |
@@ -301,8 +301,7 @@ static void pl2303_set_termios(struct tty_struct *tty, | |||
301 | i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), | 301 | i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), |
302 | GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE, | 302 | GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE, |
303 | 0, 0, buf, 7, 100); | 303 | 0, 0, buf, 7, 100); |
304 | dev_dbg(&port->dev, "0xa1:0x21:0:0 %d - %x %x %x %x %x %x %x\n", i, | 304 | dev_dbg(&port->dev, "0xa1:0x21:0:0 %d - %7ph\n", i, buf); |
305 | buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); | ||
306 | 305 | ||
307 | if (cflag & CSIZE) { | 306 | if (cflag & CSIZE) { |
308 | switch (cflag & CSIZE) { | 307 | switch (cflag & CSIZE) { |
@@ -449,8 +448,7 @@ static void pl2303_set_termios(struct tty_struct *tty, | |||
449 | i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), | 448 | i = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), |
450 | GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE, | 449 | GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE, |
451 | 0, 0, buf, 7, 100); | 450 | 0, 0, buf, 7, 100); |
452 | dev_dbg(&port->dev, "0xa1:0x21:0:0 %d - %x %x %x %x %x %x %x\n", i, | 451 | dev_dbg(&port->dev, "0xa1:0x21:0:0 %d - %7ph\n", i, buf); |
453 | buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); | ||
454 | 452 | ||
455 | if (cflag & CRTSCTS) { | 453 | if (cflag & CRTSCTS) { |
456 | if (spriv->type == HX) | 454 | if (spriv->type == HX) |
@@ -641,8 +639,8 @@ static int pl2303_ioctl(struct tty_struct *tty, | |||
641 | case TIOCGSERIAL: | 639 | case TIOCGSERIAL: |
642 | memset(&ser, 0, sizeof ser); | 640 | memset(&ser, 0, sizeof ser); |
643 | ser.type = PORT_16654; | 641 | ser.type = PORT_16654; |
644 | ser.line = port->serial->minor; | 642 | ser.line = port->minor; |
645 | ser.port = port->number; | 643 | ser.port = port->port_number; |
646 | ser.baud_base = 460800; | 644 | ser.baud_base = 460800; |
647 | 645 | ||
648 | if (copy_to_user((void __user *)arg, &ser, sizeof ser)) | 646 | if (copy_to_user((void __user *)arg, &ser, sizeof ser)) |
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index bd794b43898c..c65437cfd4a2 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c | |||
@@ -35,7 +35,13 @@ static const struct usb_device_id id_table[] = { | |||
35 | {DEVICE_G1K(0x04da, 0x250c)}, /* Panasonic Gobi QDL device */ | 35 | {DEVICE_G1K(0x04da, 0x250c)}, /* Panasonic Gobi QDL device */ |
36 | {DEVICE_G1K(0x413c, 0x8172)}, /* Dell Gobi Modem device */ | 36 | {DEVICE_G1K(0x413c, 0x8172)}, /* Dell Gobi Modem device */ |
37 | {DEVICE_G1K(0x413c, 0x8171)}, /* Dell Gobi QDL device */ | 37 | {DEVICE_G1K(0x413c, 0x8171)}, /* Dell Gobi QDL device */ |
38 | {DEVICE_G1K(0x1410, 0xa001)}, /* Novatel Gobi Modem device */ | 38 | {DEVICE_G1K(0x1410, 0xa001)}, /* Novatel/Verizon USB-1000 */ |
39 | {DEVICE_G1K(0x1410, 0xa002)}, /* Novatel Gobi Modem device */ | ||
40 | {DEVICE_G1K(0x1410, 0xa003)}, /* Novatel Gobi Modem device */ | ||
41 | {DEVICE_G1K(0x1410, 0xa004)}, /* Novatel Gobi Modem device */ | ||
42 | {DEVICE_G1K(0x1410, 0xa005)}, /* Novatel Gobi Modem device */ | ||
43 | {DEVICE_G1K(0x1410, 0xa006)}, /* Novatel Gobi Modem device */ | ||
44 | {DEVICE_G1K(0x1410, 0xa007)}, /* Novatel Gobi Modem device */ | ||
39 | {DEVICE_G1K(0x1410, 0xa008)}, /* Novatel Gobi QDL device */ | 45 | {DEVICE_G1K(0x1410, 0xa008)}, /* Novatel Gobi QDL device */ |
40 | {DEVICE_G1K(0x0b05, 0x1776)}, /* Asus Gobi Modem device */ | 46 | {DEVICE_G1K(0x0b05, 0x1776)}, /* Asus Gobi Modem device */ |
41 | {DEVICE_G1K(0x0b05, 0x1774)}, /* Asus Gobi QDL device */ | 47 | {DEVICE_G1K(0x0b05, 0x1774)}, /* Asus Gobi QDL device */ |
diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index 02b0803425c5..d99743290fc1 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c | |||
@@ -343,7 +343,7 @@ static int qt2_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
343 | int status; | 343 | int status; |
344 | unsigned long flags; | 344 | unsigned long flags; |
345 | 345 | ||
346 | device_port = (u16) (port->number - port->serial->minor); | 346 | device_port = port->port_number; |
347 | 347 | ||
348 | serial = port->serial; | 348 | serial = port->serial; |
349 | 349 | ||
@@ -388,9 +388,8 @@ static int qt2_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
388 | status = qt2_set_port_config(serial->dev, device_port, | 388 | status = qt2_set_port_config(serial->dev, device_port, |
389 | DEFAULT_BAUD_RATE, UART_LCR_WLEN8); | 389 | DEFAULT_BAUD_RATE, UART_LCR_WLEN8); |
390 | if (status < 0) { | 390 | if (status < 0) { |
391 | dev_err(&port->dev, | 391 | dev_err(&port->dev, "%s - initial setup failed (%i)\n", |
392 | "%s - initial setup failed for port %i (%i)\n", | 392 | __func__, device_port); |
393 | __func__, port->number, device_port); | ||
394 | return status; | 393 | return status; |
395 | } | 394 | } |
396 | 395 | ||
@@ -466,7 +465,7 @@ static int get_serial_info(struct usb_serial_port *port, | |||
466 | return -EFAULT; | 465 | return -EFAULT; |
467 | 466 | ||
468 | memset(&tmp, 0, sizeof(tmp)); | 467 | memset(&tmp, 0, sizeof(tmp)); |
469 | tmp.line = port->serial->minor; | 468 | tmp.line = port->minor; |
470 | tmp.port = 0; | 469 | tmp.port = 0; |
471 | tmp.irq = 0; | 470 | tmp.irq = 0; |
472 | tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; | 471 | tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; |
@@ -523,7 +522,7 @@ static void qt2_process_flush(struct usb_serial_port *port, unsigned char *ch) | |||
523 | return; | 522 | return; |
524 | } | 523 | } |
525 | 524 | ||
526 | void qt2_process_read_urb(struct urb *urb) | 525 | static void qt2_process_read_urb(struct urb *urb) |
527 | { | 526 | { |
528 | struct usb_serial *serial; | 527 | struct usb_serial *serial; |
529 | struct qt2_serial_private *serial_priv; | 528 | struct qt2_serial_private *serial_priv; |
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 8894665cd610..de958c5b52e3 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c | |||
@@ -914,7 +914,7 @@ static int sierra_port_probe(struct usb_serial_port *port) | |||
914 | /* This is really the usb-serial port number of the interface | 914 | /* This is really the usb-serial port number of the interface |
915 | * rather than the interface number. | 915 | * rather than the interface number. |
916 | */ | 916 | */ |
917 | ifnum = port->number - serial->minor; | 917 | ifnum = port->port_number; |
918 | himemoryp = &typeA_interface_list; | 918 | himemoryp = &typeA_interface_list; |
919 | } | 919 | } |
920 | 920 | ||
diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index 5b62dbbdf996..e5750be49054 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c | |||
@@ -323,7 +323,7 @@ static int get_serial_info(struct usb_serial_port *port, | |||
323 | return -EFAULT; | 323 | return -EFAULT; |
324 | 324 | ||
325 | memset(&tmp, 0, sizeof(tmp)); | 325 | memset(&tmp, 0, sizeof(tmp)); |
326 | tmp.line = port->serial->minor; | 326 | tmp.line = port->minor; |
327 | tmp.port = 0; | 327 | tmp.port = 0; |
328 | tmp.irq = 0; | 328 | tmp.irq = 0; |
329 | tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; | 329 | tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; |
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index e581c2549a57..7182bb774b79 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c | |||
@@ -477,7 +477,7 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
477 | if (mutex_lock_interruptible(&tdev->td_open_close_lock)) | 477 | if (mutex_lock_interruptible(&tdev->td_open_close_lock)) |
478 | return -ERESTARTSYS; | 478 | return -ERESTARTSYS; |
479 | 479 | ||
480 | port_number = port->number - port->serial->minor; | 480 | port_number = port->port_number; |
481 | 481 | ||
482 | tport->tp_msr = 0; | 482 | tport->tp_msr = 0; |
483 | tport->tp_shadow_mcr |= (TI_MCR_RTS | TI_MCR_DTR); | 483 | tport->tp_shadow_mcr |= (TI_MCR_RTS | TI_MCR_DTR); |
@@ -619,7 +619,7 @@ static void ti_close(struct usb_serial_port *port) | |||
619 | kfifo_reset_out(&tport->write_fifo); | 619 | kfifo_reset_out(&tport->write_fifo); |
620 | spin_unlock_irqrestore(&tport->tp_lock, flags); | 620 | spin_unlock_irqrestore(&tport->tp_lock, flags); |
621 | 621 | ||
622 | port_number = port->number - port->serial->minor; | 622 | port_number = port->port_number; |
623 | 623 | ||
624 | dev_dbg(&port->dev, "%s - sending TI_CLOSE_PORT\n", __func__); | 624 | dev_dbg(&port->dev, "%s - sending TI_CLOSE_PORT\n", __func__); |
625 | status = ti_command_out_sync(tdev, TI_CLOSE_PORT, | 625 | status = ti_command_out_sync(tdev, TI_CLOSE_PORT, |
@@ -777,7 +777,7 @@ static void ti_set_termios(struct tty_struct *tty, | |||
777 | tcflag_t cflag, iflag; | 777 | tcflag_t cflag, iflag; |
778 | int baud; | 778 | int baud; |
779 | int status; | 779 | int status; |
780 | int port_number = port->number - port->serial->minor; | 780 | int port_number = port->port_number; |
781 | unsigned int mcr; | 781 | unsigned int mcr; |
782 | 782 | ||
783 | cflag = tty->termios.c_cflag; | 783 | cflag = tty->termios.c_cflag; |
@@ -1263,7 +1263,7 @@ static int ti_get_lsr(struct ti_port *tport, u8 *lsr) | |||
1263 | int size, status; | 1263 | int size, status; |
1264 | struct ti_device *tdev = tport->tp_tdev; | 1264 | struct ti_device *tdev = tport->tp_tdev; |
1265 | struct usb_serial_port *port = tport->tp_port; | 1265 | struct usb_serial_port *port = tport->tp_port; |
1266 | int port_number = port->number - port->serial->minor; | 1266 | int port_number = port->port_number; |
1267 | struct ti_port_status *data; | 1267 | struct ti_port_status *data; |
1268 | 1268 | ||
1269 | size = sizeof(struct ti_port_status); | 1269 | size = sizeof(struct ti_port_status); |
@@ -1309,8 +1309,8 @@ static int ti_get_serial_info(struct ti_port *tport, | |||
1309 | memset(&ret_serial, 0, sizeof(ret_serial)); | 1309 | memset(&ret_serial, 0, sizeof(ret_serial)); |
1310 | 1310 | ||
1311 | ret_serial.type = PORT_16550A; | 1311 | ret_serial.type = PORT_16550A; |
1312 | ret_serial.line = port->serial->minor; | 1312 | ret_serial.line = port->minor; |
1313 | ret_serial.port = port->number - port->serial->minor; | 1313 | ret_serial.port = port->port_number; |
1314 | ret_serial.flags = tport->tp_flags; | 1314 | ret_serial.flags = tport->tp_flags; |
1315 | ret_serial.xmit_fifo_size = TI_WRITE_BUF_SIZE; | 1315 | ret_serial.xmit_fifo_size = TI_WRITE_BUF_SIZE; |
1316 | ret_serial.baud_base = tport->tp_tdev->td_is_3410 ? 921600 : 460800; | 1316 | ret_serial.baud_base = tport->tp_tdev->td_is_3410 ? 921600 : 460800; |
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 5f6b1ff9d29e..cb27fcb2fc90 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -37,11 +37,15 @@ | |||
37 | #include <linux/usb.h> | 37 | #include <linux/usb.h> |
38 | #include <linux/usb/serial.h> | 38 | #include <linux/usb/serial.h> |
39 | #include <linux/kfifo.h> | 39 | #include <linux/kfifo.h> |
40 | #include <linux/idr.h> | ||
40 | #include "pl2303.h" | 41 | #include "pl2303.h" |
41 | 42 | ||
42 | #define DRIVER_AUTHOR "Greg Kroah-Hartman <gregkh@linuxfoundation.org>" | 43 | #define DRIVER_AUTHOR "Greg Kroah-Hartman <gregkh@linuxfoundation.org>" |
43 | #define DRIVER_DESC "USB Serial Driver core" | 44 | #define DRIVER_DESC "USB Serial Driver core" |
44 | 45 | ||
46 | #define USB_SERIAL_TTY_MAJOR 188 | ||
47 | #define USB_SERIAL_TTY_MINORS 512 /* should be enough for a while */ | ||
48 | |||
45 | /* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead | 49 | /* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead |
46 | the MODULE_DEVICE_TABLE declarations in each serial driver | 50 | the MODULE_DEVICE_TABLE declarations in each serial driver |
47 | cause the "hotplug" program to pull in whatever module is necessary | 51 | cause the "hotplug" program to pull in whatever module is necessary |
@@ -49,81 +53,75 @@ | |||
49 | drivers depend on it. | 53 | drivers depend on it. |
50 | */ | 54 | */ |
51 | 55 | ||
52 | static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; | 56 | static DEFINE_IDR(serial_minors); |
53 | static DEFINE_MUTEX(table_lock); | 57 | static DEFINE_MUTEX(table_lock); |
54 | static LIST_HEAD(usb_serial_driver_list); | 58 | static LIST_HEAD(usb_serial_driver_list); |
55 | 59 | ||
56 | /* | 60 | /* |
57 | * Look up the serial structure. If it is found and it hasn't been | 61 | * Look up the serial port structure. If it is found and it hasn't been |
58 | * disconnected, return with its disc_mutex held and its refcount | 62 | * disconnected, return with the parent usb_serial structure's disc_mutex held |
59 | * incremented. Otherwise return NULL. | 63 | * and its refcount incremented. Otherwise return NULL. |
60 | */ | 64 | */ |
61 | struct usb_serial *usb_serial_get_by_index(unsigned index) | 65 | struct usb_serial_port *usb_serial_port_get_by_minor(unsigned minor) |
62 | { | 66 | { |
63 | struct usb_serial *serial; | 67 | struct usb_serial *serial; |
68 | struct usb_serial_port *port; | ||
64 | 69 | ||
65 | mutex_lock(&table_lock); | 70 | mutex_lock(&table_lock); |
66 | serial = serial_table[index]; | 71 | port = idr_find(&serial_minors, minor); |
67 | 72 | if (!port) | |
68 | if (serial) { | 73 | goto exit; |
69 | mutex_lock(&serial->disc_mutex); | 74 | |
70 | if (serial->disconnected) { | 75 | serial = port->serial; |
71 | mutex_unlock(&serial->disc_mutex); | 76 | mutex_lock(&serial->disc_mutex); |
72 | serial = NULL; | 77 | if (serial->disconnected) { |
73 | } else { | 78 | mutex_unlock(&serial->disc_mutex); |
74 | kref_get(&serial->kref); | 79 | port = NULL; |
75 | } | 80 | } else { |
81 | kref_get(&serial->kref); | ||
76 | } | 82 | } |
83 | exit: | ||
77 | mutex_unlock(&table_lock); | 84 | mutex_unlock(&table_lock); |
78 | return serial; | 85 | return port; |
79 | } | 86 | } |
80 | 87 | ||
81 | static struct usb_serial *get_free_serial(struct usb_serial *serial, | 88 | static int allocate_minors(struct usb_serial *serial, int num_ports) |
82 | int num_ports, unsigned int *minor) | ||
83 | { | 89 | { |
90 | struct usb_serial_port *port; | ||
84 | unsigned int i, j; | 91 | unsigned int i, j; |
85 | int good_spot; | 92 | int minor; |
86 | 93 | ||
87 | dev_dbg(&serial->interface->dev, "%s %d\n", __func__, num_ports); | 94 | dev_dbg(&serial->interface->dev, "%s %d\n", __func__, num_ports); |
88 | 95 | ||
89 | *minor = 0; | ||
90 | mutex_lock(&table_lock); | 96 | mutex_lock(&table_lock); |
91 | for (i = 0; i < SERIAL_TTY_MINORS; ++i) { | 97 | for (i = 0; i < num_ports; ++i) { |
92 | if (serial_table[i]) | 98 | port = serial->port[i]; |
93 | continue; | 99 | minor = idr_alloc(&serial_minors, port, 0, 0, GFP_KERNEL); |
94 | 100 | if (minor < 0) | |
95 | good_spot = 1; | 101 | goto error; |
96 | for (j = 1; j <= num_ports-1; ++j) | 102 | port->minor = minor; |
97 | if ((i+j >= SERIAL_TTY_MINORS) || (serial_table[i+j])) { | 103 | port->port_number = i; |
98 | good_spot = 0; | ||
99 | i += j; | ||
100 | break; | ||
101 | } | ||
102 | if (good_spot == 0) | ||
103 | continue; | ||
104 | |||
105 | *minor = i; | ||
106 | j = 0; | ||
107 | dev_dbg(&serial->interface->dev, "%s - minor base = %d\n", __func__, *minor); | ||
108 | for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) { | ||
109 | serial_table[i] = serial; | ||
110 | serial->port[j++]->number = i; | ||
111 | } | ||
112 | mutex_unlock(&table_lock); | ||
113 | return serial; | ||
114 | } | 104 | } |
105 | serial->minors_reserved = 1; | ||
115 | mutex_unlock(&table_lock); | 106 | mutex_unlock(&table_lock); |
116 | return NULL; | 107 | return 0; |
108 | error: | ||
109 | /* unwind the already allocated minors */ | ||
110 | for (j = 0; j < i; ++j) | ||
111 | idr_remove(&serial_minors, serial->port[j]->minor); | ||
112 | mutex_unlock(&table_lock); | ||
113 | return minor; | ||
117 | } | 114 | } |
118 | 115 | ||
119 | static void return_serial(struct usb_serial *serial) | 116 | static void release_minors(struct usb_serial *serial) |
120 | { | 117 | { |
121 | int i; | 118 | int i; |
122 | 119 | ||
123 | mutex_lock(&table_lock); | 120 | mutex_lock(&table_lock); |
124 | for (i = 0; i < serial->num_ports; ++i) | 121 | for (i = 0; i < serial->num_ports; ++i) |
125 | serial_table[serial->minor + i] = NULL; | 122 | idr_remove(&serial_minors, serial->port[i]->minor); |
126 | mutex_unlock(&table_lock); | 123 | mutex_unlock(&table_lock); |
124 | serial->minors_reserved = 0; | ||
127 | } | 125 | } |
128 | 126 | ||
129 | static void destroy_serial(struct kref *kref) | 127 | static void destroy_serial(struct kref *kref) |
@@ -135,8 +133,8 @@ static void destroy_serial(struct kref *kref) | |||
135 | serial = to_usb_serial(kref); | 133 | serial = to_usb_serial(kref); |
136 | 134 | ||
137 | /* return the minor range that this device had */ | 135 | /* return the minor range that this device had */ |
138 | if (serial->minor != SERIAL_TTY_NO_MINOR) | 136 | if (serial->minors_reserved) |
139 | return_serial(serial); | 137 | release_minors(serial); |
140 | 138 | ||
141 | if (serial->attached && serial->type->release) | 139 | if (serial->attached && serial->type->release) |
142 | serial->type->release(serial); | 140 | serial->type->release(serial); |
@@ -185,13 +183,11 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty) | |||
185 | struct usb_serial_port *port; | 183 | struct usb_serial_port *port; |
186 | int retval = -ENODEV; | 184 | int retval = -ENODEV; |
187 | 185 | ||
188 | serial = usb_serial_get_by_index(idx); | 186 | port = usb_serial_port_get_by_minor(idx); |
189 | if (!serial) | 187 | if (!port) |
190 | return retval; | 188 | return retval; |
191 | 189 | ||
192 | port = serial->port[idx - serial->minor]; | 190 | serial = port->serial; |
193 | if (!port) | ||
194 | goto error_no_port; | ||
195 | if (!try_module_get(serial->type->driver.owner)) | 191 | if (!try_module_get(serial->type->driver.owner)) |
196 | goto error_module_get; | 192 | goto error_module_get; |
197 | 193 | ||
@@ -218,7 +214,6 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty) | |||
218 | error_get_interface: | 214 | error_get_interface: |
219 | module_put(serial->type->driver.owner); | 215 | module_put(serial->type->driver.owner); |
220 | error_module_get: | 216 | error_module_get: |
221 | error_no_port: | ||
222 | usb_serial_put(serial); | 217 | usb_serial_put(serial); |
223 | mutex_unlock(&serial->disc_mutex); | 218 | mutex_unlock(&serial->disc_mutex); |
224 | return retval; | 219 | return retval; |
@@ -452,14 +447,16 @@ static int serial_break(struct tty_struct *tty, int break_state) | |||
452 | static int serial_proc_show(struct seq_file *m, void *v) | 447 | static int serial_proc_show(struct seq_file *m, void *v) |
453 | { | 448 | { |
454 | struct usb_serial *serial; | 449 | struct usb_serial *serial; |
450 | struct usb_serial_port *port; | ||
455 | int i; | 451 | int i; |
456 | char tmp[40]; | 452 | char tmp[40]; |
457 | 453 | ||
458 | seq_puts(m, "usbserinfo:1.0 driver:2.0\n"); | 454 | seq_puts(m, "usbserinfo:1.0 driver:2.0\n"); |
459 | for (i = 0; i < SERIAL_TTY_MINORS; ++i) { | 455 | for (i = 0; i < USB_SERIAL_TTY_MINORS; ++i) { |
460 | serial = usb_serial_get_by_index(i); | 456 | port = usb_serial_port_get_by_minor(i); |
461 | if (serial == NULL) | 457 | if (port == NULL) |
462 | continue; | 458 | continue; |
459 | serial = port->serial; | ||
463 | 460 | ||
464 | seq_printf(m, "%d:", i); | 461 | seq_printf(m, "%d:", i); |
465 | if (serial->type->driver.owner) | 462 | if (serial->type->driver.owner) |
@@ -471,7 +468,7 @@ static int serial_proc_show(struct seq_file *m, void *v) | |||
471 | le16_to_cpu(serial->dev->descriptor.idVendor), | 468 | le16_to_cpu(serial->dev->descriptor.idVendor), |
472 | le16_to_cpu(serial->dev->descriptor.idProduct)); | 469 | le16_to_cpu(serial->dev->descriptor.idProduct)); |
473 | seq_printf(m, " num_ports:%d", serial->num_ports); | 470 | seq_printf(m, " num_ports:%d", serial->num_ports); |
474 | seq_printf(m, " port:%d", i - serial->minor + 1); | 471 | seq_printf(m, " port:%d", port->port_number); |
475 | usb_make_path(serial->dev, tmp, sizeof(tmp)); | 472 | usb_make_path(serial->dev, tmp, sizeof(tmp)); |
476 | seq_printf(m, " path:%s", tmp); | 473 | seq_printf(m, " path:%s", tmp); |
477 | 474 | ||
@@ -613,7 +610,7 @@ static struct usb_serial *create_serial(struct usb_device *dev, | |||
613 | serial->interface = usb_get_intf(interface); | 610 | serial->interface = usb_get_intf(interface); |
614 | kref_init(&serial->kref); | 611 | kref_init(&serial->kref); |
615 | mutex_init(&serial->disc_mutex); | 612 | mutex_init(&serial->disc_mutex); |
616 | serial->minor = SERIAL_TTY_NO_MINOR; | 613 | serial->minors_reserved = 0; |
617 | 614 | ||
618 | return serial; | 615 | return serial; |
619 | } | 616 | } |
@@ -722,7 +719,6 @@ static int usb_serial_probe(struct usb_interface *interface, | |||
722 | struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS]; | 719 | struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS]; |
723 | struct usb_serial_driver *type = NULL; | 720 | struct usb_serial_driver *type = NULL; |
724 | int retval; | 721 | int retval; |
725 | unsigned int minor; | ||
726 | int buffer_size; | 722 | int buffer_size; |
727 | int i; | 723 | int i; |
728 | int j; | 724 | int j; |
@@ -1039,16 +1035,15 @@ static int usb_serial_probe(struct usb_interface *interface, | |||
1039 | */ | 1035 | */ |
1040 | serial->disconnected = 1; | 1036 | serial->disconnected = 1; |
1041 | 1037 | ||
1042 | if (get_free_serial(serial, num_ports, &minor) == NULL) { | 1038 | if (allocate_minors(serial, num_ports)) { |
1043 | dev_err(ddev, "No more free serial devices\n"); | 1039 | dev_err(ddev, "No more free serial minor numbers\n"); |
1044 | goto probe_error; | 1040 | goto probe_error; |
1045 | } | 1041 | } |
1046 | serial->minor = minor; | ||
1047 | 1042 | ||
1048 | /* register all of the individual ports with the driver core */ | 1043 | /* register all of the individual ports with the driver core */ |
1049 | for (i = 0; i < num_ports; ++i) { | 1044 | for (i = 0; i < num_ports; ++i) { |
1050 | port = serial->port[i]; | 1045 | port = serial->port[i]; |
1051 | dev_set_name(&port->dev, "ttyUSB%d", port->number); | 1046 | dev_set_name(&port->dev, "ttyUSB%d", port->minor); |
1052 | dev_dbg(ddev, "registering %s", dev_name(&port->dev)); | 1047 | dev_dbg(ddev, "registering %s", dev_name(&port->dev)); |
1053 | device_enable_async_suspend(&port->dev); | 1048 | device_enable_async_suspend(&port->dev); |
1054 | 1049 | ||
@@ -1059,7 +1054,7 @@ static int usb_serial_probe(struct usb_interface *interface, | |||
1059 | 1054 | ||
1060 | serial->disconnected = 0; | 1055 | serial->disconnected = 0; |
1061 | 1056 | ||
1062 | usb_serial_console_init(minor); | 1057 | usb_serial_console_init(serial->port[0]->minor); |
1063 | exit: | 1058 | exit: |
1064 | module_put(type->driver.owner); | 1059 | module_put(type->driver.owner); |
1065 | return 0; | 1060 | return 0; |
@@ -1223,17 +1218,13 @@ static struct usb_driver usb_serial_driver = { | |||
1223 | 1218 | ||
1224 | static int __init usb_serial_init(void) | 1219 | static int __init usb_serial_init(void) |
1225 | { | 1220 | { |
1226 | int i; | ||
1227 | int result; | 1221 | int result; |
1228 | 1222 | ||
1229 | usb_serial_tty_driver = alloc_tty_driver(SERIAL_TTY_MINORS); | 1223 | usb_serial_tty_driver = alloc_tty_driver(USB_SERIAL_TTY_MINORS); |
1230 | if (!usb_serial_tty_driver) | 1224 | if (!usb_serial_tty_driver) |
1231 | return -ENOMEM; | 1225 | return -ENOMEM; |
1232 | 1226 | ||
1233 | /* Initialize our global data */ | 1227 | /* Initialize our global data */ |
1234 | for (i = 0; i < SERIAL_TTY_MINORS; ++i) | ||
1235 | serial_table[i] = NULL; | ||
1236 | |||
1237 | result = bus_register(&usb_serial_bus_type); | 1228 | result = bus_register(&usb_serial_bus_type); |
1238 | if (result) { | 1229 | if (result) { |
1239 | pr_err("%s - registering bus driver failed\n", __func__); | 1230 | pr_err("%s - registering bus driver failed\n", __func__); |
@@ -1242,7 +1233,7 @@ static int __init usb_serial_init(void) | |||
1242 | 1233 | ||
1243 | usb_serial_tty_driver->driver_name = "usbserial"; | 1234 | usb_serial_tty_driver->driver_name = "usbserial"; |
1244 | usb_serial_tty_driver->name = "ttyUSB"; | 1235 | usb_serial_tty_driver->name = "ttyUSB"; |
1245 | usb_serial_tty_driver->major = SERIAL_TTY_MAJOR; | 1236 | usb_serial_tty_driver->major = USB_SERIAL_TTY_MAJOR; |
1246 | usb_serial_tty_driver->minor_start = 0; | 1237 | usb_serial_tty_driver->minor_start = 0; |
1247 | usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; | 1238 | usb_serial_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; |
1248 | usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL; | 1239 | usb_serial_tty_driver->subtype = SERIAL_TYPE_NORMAL; |
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index ece326ef63a0..8257d30c4072 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c | |||
@@ -124,8 +124,8 @@ static int get_serial_info(struct usb_serial_port *port, | |||
124 | return -EFAULT; | 124 | return -EFAULT; |
125 | 125 | ||
126 | memset(&tmp, 0, sizeof(tmp)); | 126 | memset(&tmp, 0, sizeof(tmp)); |
127 | tmp.line = port->serial->minor; | 127 | tmp.line = port->minor; |
128 | tmp.port = port->number; | 128 | tmp.port = port->port_number; |
129 | tmp.baud_base = tty_get_baud_rate(port->port.tty); | 129 | tmp.baud_base = tty_get_baud_rate(port->port.tty); |
130 | tmp.close_delay = port->port.close_delay / 10; | 130 | tmp.close_delay = port->port.close_delay / 10; |
131 | tmp.closing_wait = port->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ? | 131 | tmp.closing_wait = port->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ? |
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 347caad47a12..36a7740e827c 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c | |||
@@ -461,8 +461,8 @@ static int whiteheat_ioctl(struct tty_struct *tty, | |||
461 | case TIOCGSERIAL: | 461 | case TIOCGSERIAL: |
462 | memset(&serstruct, 0, sizeof(serstruct)); | 462 | memset(&serstruct, 0, sizeof(serstruct)); |
463 | serstruct.type = PORT_16654; | 463 | serstruct.type = PORT_16654; |
464 | serstruct.line = port->serial->minor; | 464 | serstruct.line = port->minor; |
465 | serstruct.port = port->number; | 465 | serstruct.port = port->port_number; |
466 | serstruct.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; | 466 | serstruct.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; |
467 | serstruct.xmit_fifo_size = kfifo_size(&port->write_fifo); | 467 | serstruct.xmit_fifo_size = kfifo_size(&port->write_fifo); |
468 | serstruct.custom_divisor = 0; | 468 | serstruct.custom_divisor = 0; |
@@ -626,7 +626,7 @@ static int firm_open(struct usb_serial_port *port) | |||
626 | { | 626 | { |
627 | struct whiteheat_simple open_command; | 627 | struct whiteheat_simple open_command; |
628 | 628 | ||
629 | open_command.port = port->number - port->serial->minor + 1; | 629 | open_command.port = port->port_number + 1; |
630 | return firm_send_command(port, WHITEHEAT_OPEN, | 630 | return firm_send_command(port, WHITEHEAT_OPEN, |
631 | (__u8 *)&open_command, sizeof(open_command)); | 631 | (__u8 *)&open_command, sizeof(open_command)); |
632 | } | 632 | } |
@@ -636,7 +636,7 @@ static int firm_close(struct usb_serial_port *port) | |||
636 | { | 636 | { |
637 | struct whiteheat_simple close_command; | 637 | struct whiteheat_simple close_command; |
638 | 638 | ||
639 | close_command.port = port->number - port->serial->minor + 1; | 639 | close_command.port = port->port_number + 1; |
640 | return firm_send_command(port, WHITEHEAT_CLOSE, | 640 | return firm_send_command(port, WHITEHEAT_CLOSE, |
641 | (__u8 *)&close_command, sizeof(close_command)); | 641 | (__u8 *)&close_command, sizeof(close_command)); |
642 | } | 642 | } |
@@ -649,7 +649,7 @@ static void firm_setup_port(struct tty_struct *tty) | |||
649 | struct whiteheat_port_settings port_settings; | 649 | struct whiteheat_port_settings port_settings; |
650 | unsigned int cflag = tty->termios.c_cflag; | 650 | unsigned int cflag = tty->termios.c_cflag; |
651 | 651 | ||
652 | port_settings.port = port->number - port->serial->minor + 1; | 652 | port_settings.port = port->port_number + 1; |
653 | 653 | ||
654 | /* get the byte size */ | 654 | /* get the byte size */ |
655 | switch (cflag & CSIZE) { | 655 | switch (cflag & CSIZE) { |
@@ -726,7 +726,7 @@ static int firm_set_rts(struct usb_serial_port *port, __u8 onoff) | |||
726 | { | 726 | { |
727 | struct whiteheat_set_rdb rts_command; | 727 | struct whiteheat_set_rdb rts_command; |
728 | 728 | ||
729 | rts_command.port = port->number - port->serial->minor + 1; | 729 | rts_command.port = port->port_number + 1; |
730 | rts_command.state = onoff; | 730 | rts_command.state = onoff; |
731 | return firm_send_command(port, WHITEHEAT_SET_RTS, | 731 | return firm_send_command(port, WHITEHEAT_SET_RTS, |
732 | (__u8 *)&rts_command, sizeof(rts_command)); | 732 | (__u8 *)&rts_command, sizeof(rts_command)); |
@@ -737,7 +737,7 @@ static int firm_set_dtr(struct usb_serial_port *port, __u8 onoff) | |||
737 | { | 737 | { |
738 | struct whiteheat_set_rdb dtr_command; | 738 | struct whiteheat_set_rdb dtr_command; |
739 | 739 | ||
740 | dtr_command.port = port->number - port->serial->minor + 1; | 740 | dtr_command.port = port->port_number + 1; |
741 | dtr_command.state = onoff; | 741 | dtr_command.state = onoff; |
742 | return firm_send_command(port, WHITEHEAT_SET_DTR, | 742 | return firm_send_command(port, WHITEHEAT_SET_DTR, |
743 | (__u8 *)&dtr_command, sizeof(dtr_command)); | 743 | (__u8 *)&dtr_command, sizeof(dtr_command)); |
@@ -748,7 +748,7 @@ static int firm_set_break(struct usb_serial_port *port, __u8 onoff) | |||
748 | { | 748 | { |
749 | struct whiteheat_set_rdb break_command; | 749 | struct whiteheat_set_rdb break_command; |
750 | 750 | ||
751 | break_command.port = port->number - port->serial->minor + 1; | 751 | break_command.port = port->port_number + 1; |
752 | break_command.state = onoff; | 752 | break_command.state = onoff; |
753 | return firm_send_command(port, WHITEHEAT_SET_BREAK, | 753 | return firm_send_command(port, WHITEHEAT_SET_BREAK, |
754 | (__u8 *)&break_command, sizeof(break_command)); | 754 | (__u8 *)&break_command, sizeof(break_command)); |
@@ -759,7 +759,7 @@ static int firm_purge(struct usb_serial_port *port, __u8 rxtx) | |||
759 | { | 759 | { |
760 | struct whiteheat_purge purge_command; | 760 | struct whiteheat_purge purge_command; |
761 | 761 | ||
762 | purge_command.port = port->number - port->serial->minor + 1; | 762 | purge_command.port = port->port_number + 1; |
763 | purge_command.what = rxtx; | 763 | purge_command.what = rxtx; |
764 | return firm_send_command(port, WHITEHEAT_PURGE, | 764 | return firm_send_command(port, WHITEHEAT_PURGE, |
765 | (__u8 *)&purge_command, sizeof(purge_command)); | 765 | (__u8 *)&purge_command, sizeof(purge_command)); |
@@ -770,7 +770,7 @@ static int firm_get_dtr_rts(struct usb_serial_port *port) | |||
770 | { | 770 | { |
771 | struct whiteheat_simple get_dr_command; | 771 | struct whiteheat_simple get_dr_command; |
772 | 772 | ||
773 | get_dr_command.port = port->number - port->serial->minor + 1; | 773 | get_dr_command.port = port->port_number + 1; |
774 | return firm_send_command(port, WHITEHEAT_GET_DTR_RTS, | 774 | return firm_send_command(port, WHITEHEAT_GET_DTR_RTS, |
775 | (__u8 *)&get_dr_command, sizeof(get_dr_command)); | 775 | (__u8 *)&get_dr_command, sizeof(get_dr_command)); |
776 | } | 776 | } |
@@ -780,7 +780,7 @@ static int firm_report_tx_done(struct usb_serial_port *port) | |||
780 | { | 780 | { |
781 | struct whiteheat_simple close_command; | 781 | struct whiteheat_simple close_command; |
782 | 782 | ||
783 | close_command.port = port->number - port->serial->minor + 1; | 783 | close_command.port = port->port_number + 1; |
784 | return firm_send_command(port, WHITEHEAT_REPORT_TX_DONE, | 784 | return firm_send_command(port, WHITEHEAT_REPORT_TX_DONE, |
785 | (__u8 *)&close_command, sizeof(close_command)); | 785 | (__u8 *)&close_command, sizeof(close_command)); |
786 | } | 786 | } |
diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c index 77a2ddfe6487..6636a583da12 100644 --- a/drivers/usb/storage/alauda.c +++ b/drivers/usb/storage/alauda.c | |||
@@ -249,11 +249,7 @@ static void nand_init_ecc(void) { | |||
249 | /* compute 3-byte ecc on 256 bytes */ | 249 | /* compute 3-byte ecc on 256 bytes */ |
250 | static void nand_compute_ecc(unsigned char *data, unsigned char *ecc) { | 250 | static void nand_compute_ecc(unsigned char *data, unsigned char *ecc) { |
251 | int i, j, a; | 251 | int i, j, a; |
252 | unsigned char par, bit, bits[8]; | 252 | unsigned char par = 0, bit, bits[8] = {0}; |
253 | |||
254 | par = 0; | ||
255 | for (j = 0; j < 8; j++) | ||
256 | bits[j] = 0; | ||
257 | 253 | ||
258 | /* collect 16 checksum bits */ | 254 | /* collect 16 checksum bits */ |
259 | for (i = 0; i < 256; i++) { | 255 | for (i = 0; i < 256; i++) { |
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c index 732027f33200..073a2c32ccc4 100644 --- a/drivers/usb/storage/sddr09.c +++ b/drivers/usb/storage/sddr09.c | |||
@@ -219,11 +219,7 @@ static void nand_init_ecc(void) { | |||
219 | /* compute 3-byte ecc on 256 bytes */ | 219 | /* compute 3-byte ecc on 256 bytes */ |
220 | static void nand_compute_ecc(unsigned char *data, unsigned char *ecc) { | 220 | static void nand_compute_ecc(unsigned char *data, unsigned char *ecc) { |
221 | int i, j, a; | 221 | int i, j, a; |
222 | unsigned char par, bit, bits[8]; | 222 | unsigned char par = 0, bit, bits[8] = {0}; |
223 | |||
224 | par = 0; | ||
225 | for (j = 0; j < 8; j++) | ||
226 | bits[j] = 0; | ||
227 | 223 | ||
228 | /* collect 16 checksum bits */ | 224 | /* collect 16 checksum bits */ |
229 | for (i = 0; i < 256; i++) { | 225 | for (i = 0; i < 256; i++) { |
diff --git a/drivers/usb/usb-common.c b/drivers/usb/usb-common.c index 0db0a919d72b..675384dabfe9 100644 --- a/drivers/usb/usb-common.c +++ b/drivers/usb/usb-common.c | |||
@@ -13,7 +13,9 @@ | |||
13 | 13 | ||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/of.h> | ||
16 | #include <linux/usb/ch9.h> | 17 | #include <linux/usb/ch9.h> |
18 | #include <linux/usb/of.h> | ||
17 | #include <linux/usb/otg.h> | 19 | #include <linux/usb/otg.h> |
18 | 20 | ||
19 | const char *usb_otg_state_string(enum usb_otg_state state) | 21 | const char *usb_otg_state_string(enum usb_otg_state state) |
@@ -79,4 +81,37 @@ const char *usb_state_string(enum usb_device_state state) | |||
79 | } | 81 | } |
80 | EXPORT_SYMBOL_GPL(usb_state_string); | 82 | EXPORT_SYMBOL_GPL(usb_state_string); |
81 | 83 | ||
84 | #ifdef CONFIG_OF | ||
85 | static const char *const usb_dr_modes[] = { | ||
86 | [USB_DR_MODE_UNKNOWN] = "", | ||
87 | [USB_DR_MODE_HOST] = "host", | ||
88 | [USB_DR_MODE_PERIPHERAL] = "peripheral", | ||
89 | [USB_DR_MODE_OTG] = "otg", | ||
90 | }; | ||
91 | |||
92 | /** | ||
93 | * of_usb_get_dr_mode - Get dual role mode for given device_node | ||
94 | * @np: Pointer to the given device_node | ||
95 | * | ||
96 | * The function gets phy interface string from property 'dr_mode', | ||
97 | * and returns the correspondig enum usb_dr_mode | ||
98 | */ | ||
99 | enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np) | ||
100 | { | ||
101 | const char *dr_mode; | ||
102 | int err, i; | ||
103 | |||
104 | err = of_property_read_string(np, "dr_mode", &dr_mode); | ||
105 | if (err < 0) | ||
106 | return USB_DR_MODE_UNKNOWN; | ||
107 | |||
108 | for (i = 0; i < ARRAY_SIZE(usb_dr_modes); i++) | ||
109 | if (!strcmp(dr_mode, usb_dr_modes[i])) | ||
110 | return i; | ||
111 | |||
112 | return USB_DR_MODE_UNKNOWN; | ||
113 | } | ||
114 | EXPORT_SYMBOL_GPL(of_usb_get_dr_mode); | ||
115 | #endif | ||
116 | |||
82 | MODULE_LICENSE("GPL"); | 117 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/usb/wusbcore/devconnect.c b/drivers/usb/wusbcore/devconnect.c index 1d365316960c..33a12788f9ca 100644 --- a/drivers/usb/wusbcore/devconnect.c +++ b/drivers/usb/wusbcore/devconnect.c | |||
@@ -455,8 +455,8 @@ static void __wusbhc_keep_alive(struct wusbhc *wusbhc) | |||
455 | dev_err(dev, "KEEPALIVE: device %u timed out\n", | 455 | dev_err(dev, "KEEPALIVE: device %u timed out\n", |
456 | wusb_dev->addr); | 456 | wusb_dev->addr); |
457 | __wusbhc_dev_disconnect(wusbhc, wusb_port); | 457 | __wusbhc_dev_disconnect(wusbhc, wusb_port); |
458 | } else if (time_after(jiffies, wusb_dev->entry_ts + tt/2)) { | 458 | } else if (time_after(jiffies, wusb_dev->entry_ts + tt/3)) { |
459 | /* Approaching timeout cut out, need to refresh */ | 459 | /* Approaching timeout cut off, need to refresh */ |
460 | ie->bDeviceAddress[keep_alives++] = wusb_dev->addr; | 460 | ie->bDeviceAddress[keep_alives++] = wusb_dev->addr; |
461 | } | 461 | } |
462 | } | 462 | } |
@@ -1062,7 +1062,7 @@ int wusbhc_devconnect_start(struct wusbhc *wusbhc) | |||
1062 | wusbhc->wuie_host_info = hi; | 1062 | wusbhc->wuie_host_info = hi; |
1063 | 1063 | ||
1064 | queue_delayed_work(wusbd, &wusbhc->keep_alive_timer, | 1064 | queue_delayed_work(wusbd, &wusbhc->keep_alive_timer, |
1065 | (wusbhc->trust_timeout*CONFIG_HZ)/1000/2); | 1065 | msecs_to_jiffies(wusbhc->trust_timeout / 2)); |
1066 | 1066 | ||
1067 | return 0; | 1067 | return 0; |
1068 | 1068 | ||
diff --git a/drivers/usb/wusbcore/mmc.c b/drivers/usb/wusbcore/mmc.c index b8c72583c040..b71760c8d3ad 100644 --- a/drivers/usb/wusbcore/mmc.c +++ b/drivers/usb/wusbcore/mmc.c | |||
@@ -195,6 +195,7 @@ int wusbhc_start(struct wusbhc *wusbhc) | |||
195 | struct device *dev = wusbhc->dev; | 195 | struct device *dev = wusbhc->dev; |
196 | 196 | ||
197 | WARN_ON(wusbhc->wuie_host_info != NULL); | 197 | WARN_ON(wusbhc->wuie_host_info != NULL); |
198 | BUG_ON(wusbhc->uwb_rc == NULL); | ||
198 | 199 | ||
199 | result = wusbhc_rsv_establish(wusbhc); | 200 | result = wusbhc_rsv_establish(wusbhc); |
200 | if (result < 0) { | 201 | if (result < 0) { |
@@ -214,9 +215,9 @@ int wusbhc_start(struct wusbhc *wusbhc) | |||
214 | dev_err(dev, "error starting security in the HC: %d\n", result); | 215 | dev_err(dev, "error starting security in the HC: %d\n", result); |
215 | goto error_sec_start; | 216 | goto error_sec_start; |
216 | } | 217 | } |
217 | /* FIXME: the choice of the DNTS parameters is somewhat | 218 | |
218 | * arbitrary */ | 219 | result = wusbhc->set_num_dnts(wusbhc, wusbhc->dnts_interval, |
219 | result = wusbhc->set_num_dnts(wusbhc, 0, 15); | 220 | wusbhc->dnts_num_slots); |
220 | if (result < 0) { | 221 | if (result < 0) { |
221 | dev_err(dev, "Cannot set DNTS parameters: %d\n", result); | 222 | dev_err(dev, "Cannot set DNTS parameters: %d\n", result); |
222 | goto error_set_num_dnts; | 223 | goto error_set_num_dnts; |
@@ -276,12 +277,38 @@ int wusbhc_chid_set(struct wusbhc *wusbhc, const struct wusb_ckhdid *chid) | |||
276 | } | 277 | } |
277 | wusbhc->chid = *chid; | 278 | wusbhc->chid = *chid; |
278 | } | 279 | } |
280 | |||
281 | /* register with UWB if we haven't already since we are about to start | ||
282 | the radio. */ | ||
283 | if ((chid) && (wusbhc->uwb_rc == NULL)) { | ||
284 | wusbhc->uwb_rc = uwb_rc_get_by_grandpa(wusbhc->dev->parent); | ||
285 | if (wusbhc->uwb_rc == NULL) { | ||
286 | result = -ENODEV; | ||
287 | dev_err(wusbhc->dev, "Cannot get associated UWB Host Controller\n"); | ||
288 | goto error_rc_get; | ||
289 | } | ||
290 | |||
291 | result = wusbhc_pal_register(wusbhc); | ||
292 | if (result < 0) { | ||
293 | dev_err(wusbhc->dev, "Cannot register as a UWB PAL\n"); | ||
294 | goto error_pal_register; | ||
295 | } | ||
296 | } | ||
279 | mutex_unlock(&wusbhc->mutex); | 297 | mutex_unlock(&wusbhc->mutex); |
280 | 298 | ||
281 | if (chid) | 299 | if (chid) |
282 | result = uwb_radio_start(&wusbhc->pal); | 300 | result = uwb_radio_start(&wusbhc->pal); |
283 | else | 301 | else |
284 | uwb_radio_stop(&wusbhc->pal); | 302 | uwb_radio_stop(&wusbhc->pal); |
303 | |||
304 | return result; | ||
305 | |||
306 | error_pal_register: | ||
307 | uwb_rc_put(wusbhc->uwb_rc); | ||
308 | wusbhc->uwb_rc = NULL; | ||
309 | error_rc_get: | ||
310 | mutex_unlock(&wusbhc->mutex); | ||
311 | |||
285 | return result; | 312 | return result; |
286 | } | 313 | } |
287 | EXPORT_SYMBOL_GPL(wusbhc_chid_set); | 314 | EXPORT_SYMBOL_GPL(wusbhc_chid_set); |
diff --git a/drivers/usb/wusbcore/pal.c b/drivers/usb/wusbcore/pal.c index d0b172c5ecc7..59e100c2eb50 100644 --- a/drivers/usb/wusbcore/pal.c +++ b/drivers/usb/wusbcore/pal.c | |||
@@ -45,10 +45,11 @@ int wusbhc_pal_register(struct wusbhc *wusbhc) | |||
45 | } | 45 | } |
46 | 46 | ||
47 | /** | 47 | /** |
48 | * wusbhc_pal_register - unregister the WUSB HC as a UWB PAL | 48 | * wusbhc_pal_unregister - unregister the WUSB HC as a UWB PAL |
49 | * @wusbhc: the WUSB HC | 49 | * @wusbhc: the WUSB HC |
50 | */ | 50 | */ |
51 | void wusbhc_pal_unregister(struct wusbhc *wusbhc) | 51 | void wusbhc_pal_unregister(struct wusbhc *wusbhc) |
52 | { | 52 | { |
53 | uwb_pal_unregister(&wusbhc->pal); | 53 | if (wusbhc->uwb_rc) |
54 | uwb_pal_unregister(&wusbhc->pal); | ||
54 | } | 55 | } |
diff --git a/drivers/usb/wusbcore/reservation.c b/drivers/usb/wusbcore/reservation.c index 6f4fafdc2401..ead79f793927 100644 --- a/drivers/usb/wusbcore/reservation.c +++ b/drivers/usb/wusbcore/reservation.c | |||
@@ -80,6 +80,9 @@ int wusbhc_rsv_establish(struct wusbhc *wusbhc) | |||
80 | struct uwb_dev_addr bcid; | 80 | struct uwb_dev_addr bcid; |
81 | int ret; | 81 | int ret; |
82 | 82 | ||
83 | if (rc == NULL) | ||
84 | return -ENODEV; | ||
85 | |||
83 | rsv = uwb_rsv_create(rc, wusbhc_rsv_complete_cb, wusbhc); | 86 | rsv = uwb_rsv_create(rc, wusbhc_rsv_complete_cb, wusbhc); |
84 | if (rsv == NULL) | 87 | if (rsv == NULL) |
85 | return -ENOMEM; | 88 | return -ENOMEM; |
diff --git a/drivers/usb/wusbcore/rh.c b/drivers/usb/wusbcore/rh.c index 59ff254dfb6f..bdb0cc3046b5 100644 --- a/drivers/usb/wusbcore/rh.c +++ b/drivers/usb/wusbcore/rh.c | |||
@@ -393,26 +393,6 @@ int wusbhc_rh_control(struct usb_hcd *usb_hcd, u16 reqntype, u16 wValue, | |||
393 | } | 393 | } |
394 | EXPORT_SYMBOL_GPL(wusbhc_rh_control); | 394 | EXPORT_SYMBOL_GPL(wusbhc_rh_control); |
395 | 395 | ||
396 | int wusbhc_rh_suspend(struct usb_hcd *usb_hcd) | ||
397 | { | ||
398 | struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); | ||
399 | dev_err(wusbhc->dev, "%s (%p [%p]) UNIMPLEMENTED\n", __func__, | ||
400 | usb_hcd, wusbhc); | ||
401 | /* dump_stack(); */ | ||
402 | return -ENOSYS; | ||
403 | } | ||
404 | EXPORT_SYMBOL_GPL(wusbhc_rh_suspend); | ||
405 | |||
406 | int wusbhc_rh_resume(struct usb_hcd *usb_hcd) | ||
407 | { | ||
408 | struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); | ||
409 | dev_err(wusbhc->dev, "%s (%p [%p]) UNIMPLEMENTED\n", __func__, | ||
410 | usb_hcd, wusbhc); | ||
411 | /* dump_stack(); */ | ||
412 | return -ENOSYS; | ||
413 | } | ||
414 | EXPORT_SYMBOL_GPL(wusbhc_rh_resume); | ||
415 | |||
416 | int wusbhc_rh_start_port_reset(struct usb_hcd *usb_hcd, unsigned port_idx) | 396 | int wusbhc_rh_start_port_reset(struct usb_hcd *usb_hcd, unsigned port_idx) |
417 | { | 397 | { |
418 | struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); | 398 | struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); |
diff --git a/drivers/usb/wusbcore/wa-nep.c b/drivers/usb/wusbcore/wa-nep.c index f67f7f1e6df9..ada4e0870623 100644 --- a/drivers/usb/wusbcore/wa-nep.c +++ b/drivers/usb/wusbcore/wa-nep.c | |||
@@ -134,9 +134,10 @@ static void wa_notif_dispatch(struct work_struct *ws) | |||
134 | case WA_NOTIF_TRANSFER: | 134 | case WA_NOTIF_TRANSFER: |
135 | wa_handle_notif_xfer(wa, notif_hdr); | 135 | wa_handle_notif_xfer(wa, notif_hdr); |
136 | break; | 136 | break; |
137 | case HWA_NOTIF_BPST_ADJ: | ||
138 | break; /* no action needed for BPST ADJ. */ | ||
137 | case DWA_NOTIF_RWAKE: | 139 | case DWA_NOTIF_RWAKE: |
138 | case DWA_NOTIF_PORTSTATUS: | 140 | case DWA_NOTIF_PORTSTATUS: |
139 | case HWA_NOTIF_BPST_ADJ: | ||
140 | /* FIXME: unimplemented WA NOTIFs */ | 141 | /* FIXME: unimplemented WA NOTIFs */ |
141 | /* fallthru */ | 142 | /* fallthru */ |
142 | default: | 143 | default: |
diff --git a/drivers/usb/wusbcore/wa-rpipe.c b/drivers/usb/wusbcore/wa-rpipe.c index f0d546c5a089..9a595c1ed867 100644 --- a/drivers/usb/wusbcore/wa-rpipe.c +++ b/drivers/usb/wusbcore/wa-rpipe.c | |||
@@ -251,8 +251,8 @@ static int __rpipe_reset(struct wahc *wa, unsigned index) | |||
251 | static struct usb_wireless_ep_comp_descriptor epc0 = { | 251 | static struct usb_wireless_ep_comp_descriptor epc0 = { |
252 | .bLength = sizeof(epc0), | 252 | .bLength = sizeof(epc0), |
253 | .bDescriptorType = USB_DT_WIRELESS_ENDPOINT_COMP, | 253 | .bDescriptorType = USB_DT_WIRELESS_ENDPOINT_COMP, |
254 | /* .bMaxBurst = 1, */ | 254 | .bMaxBurst = 1, |
255 | .bMaxSequence = 31, | 255 | .bMaxSequence = 2, |
256 | }; | 256 | }; |
257 | 257 | ||
258 | /* | 258 | /* |
@@ -317,6 +317,7 @@ static int rpipe_aim(struct wa_rpipe *rpipe, struct wahc *wa, | |||
317 | struct device *dev = &wa->usb_iface->dev; | 317 | struct device *dev = &wa->usb_iface->dev; |
318 | struct usb_device *usb_dev = urb->dev; | 318 | struct usb_device *usb_dev = urb->dev; |
319 | struct usb_wireless_ep_comp_descriptor *epcd; | 319 | struct usb_wireless_ep_comp_descriptor *epcd; |
320 | u32 ack_window, epcd_max_sequence; | ||
320 | u8 unauth; | 321 | u8 unauth; |
321 | 322 | ||
322 | epcd = rpipe_epc_find(dev, ep); | 323 | epcd = rpipe_epc_find(dev, ep); |
@@ -333,8 +334,11 @@ static int rpipe_aim(struct wa_rpipe *rpipe, struct wahc *wa, | |||
333 | rpipe->descr.wBlocks = cpu_to_le16(16); /* given */ | 334 | rpipe->descr.wBlocks = cpu_to_le16(16); /* given */ |
334 | /* ep0 maxpktsize is 0x200 (WUSB1.0[4.8.1]) */ | 335 | /* ep0 maxpktsize is 0x200 (WUSB1.0[4.8.1]) */ |
335 | rpipe->descr.wMaxPacketSize = cpu_to_le16(ep->desc.wMaxPacketSize); | 336 | rpipe->descr.wMaxPacketSize = cpu_to_le16(ep->desc.wMaxPacketSize); |
336 | rpipe->descr.bHSHubAddress = 0; /* reserved: zero */ | 337 | |
337 | rpipe->descr.bHSHubPort = wusb_port_no_to_idx(urb->dev->portnum); | 338 | rpipe->descr.hwa_bMaxBurst = max(min_t(unsigned int, |
339 | epcd->bMaxBurst, 16U), 1U); | ||
340 | rpipe->descr.hwa_bDeviceInfoIndex = | ||
341 | wusb_port_no_to_idx(urb->dev->portnum); | ||
338 | /* FIXME: use maximum speed as supported or recommended by device */ | 342 | /* FIXME: use maximum speed as supported or recommended by device */ |
339 | rpipe->descr.bSpeed = usb_pipeendpoint(urb->pipe) == 0 ? | 343 | rpipe->descr.bSpeed = usb_pipeendpoint(urb->pipe) == 0 ? |
340 | UWB_PHY_RATE_53 : UWB_PHY_RATE_200; | 344 | UWB_PHY_RATE_53 : UWB_PHY_RATE_200; |
@@ -344,26 +348,26 @@ static int rpipe_aim(struct wa_rpipe *rpipe, struct wahc *wa, | |||
344 | le16_to_cpu(rpipe->descr.wRPipeIndex), | 348 | le16_to_cpu(rpipe->descr.wRPipeIndex), |
345 | usb_pipeendpoint(urb->pipe), rpipe->descr.bSpeed); | 349 | usb_pipeendpoint(urb->pipe), rpipe->descr.bSpeed); |
346 | 350 | ||
347 | /* see security.c:wusb_update_address() */ | 351 | rpipe->descr.hwa_reserved = 0; |
348 | if (unlikely(urb->dev->devnum == 0x80)) | 352 | |
349 | rpipe->descr.bDeviceAddress = 0; | ||
350 | else | ||
351 | rpipe->descr.bDeviceAddress = urb->dev->devnum | unauth; | ||
352 | rpipe->descr.bEndpointAddress = ep->desc.bEndpointAddress; | 353 | rpipe->descr.bEndpointAddress = ep->desc.bEndpointAddress; |
353 | /* FIXME: bDataSequence */ | 354 | /* FIXME: bDataSequence */ |
354 | rpipe->descr.bDataSequence = 0; | 355 | rpipe->descr.bDataSequence = 0; |
355 | /* FIXME: dwCurrentWindow */ | 356 | |
356 | rpipe->descr.dwCurrentWindow = cpu_to_le32(1); | 357 | /* start with base window of hwa_bMaxBurst bits starting at 0. */ |
357 | /* FIXME: bMaxDataSequence */ | 358 | ack_window = 0xFFFFFFFF >> (32 - rpipe->descr.hwa_bMaxBurst); |
358 | rpipe->descr.bMaxDataSequence = epcd->bMaxSequence - 1; | 359 | rpipe->descr.dwCurrentWindow = cpu_to_le32(ack_window); |
360 | epcd_max_sequence = max(min_t(unsigned int, | ||
361 | epcd->bMaxSequence, 32U), 2U); | ||
362 | rpipe->descr.bMaxDataSequence = epcd_max_sequence - 1; | ||
359 | rpipe->descr.bInterval = ep->desc.bInterval; | 363 | rpipe->descr.bInterval = ep->desc.bInterval; |
360 | /* FIXME: bOverTheAirInterval */ | 364 | /* FIXME: bOverTheAirInterval */ |
361 | rpipe->descr.bOverTheAirInterval = 0; /* 0 if not isoc */ | 365 | rpipe->descr.bOverTheAirInterval = 0; /* 0 if not isoc */ |
362 | /* FIXME: xmit power & preamble blah blah */ | 366 | /* FIXME: xmit power & preamble blah blah */ |
363 | rpipe->descr.bmAttribute = ep->desc.bmAttributes & 0x03; | 367 | rpipe->descr.bmAttribute = (ep->desc.bmAttributes & |
368 | USB_ENDPOINT_XFERTYPE_MASK); | ||
364 | /* rpipe->descr.bmCharacteristics RO */ | 369 | /* rpipe->descr.bmCharacteristics RO */ |
365 | /* FIXME: bmRetryOptions */ | 370 | rpipe->descr.bmRetryOptions = (wa->wusb->retry_count & 0xF); |
366 | rpipe->descr.bmRetryOptions = 15; | ||
367 | /* FIXME: use for assessing link quality? */ | 371 | /* FIXME: use for assessing link quality? */ |
368 | rpipe->descr.wNumTransactionErrors = 0; | 372 | rpipe->descr.wNumTransactionErrors = 0; |
369 | result = __rpipe_set_descr(wa, &rpipe->descr, | 373 | result = __rpipe_set_descr(wa, &rpipe->descr, |
@@ -387,10 +391,8 @@ static int rpipe_check_aim(const struct wa_rpipe *rpipe, const struct wahc *wa, | |||
387 | const struct usb_host_endpoint *ep, | 391 | const struct usb_host_endpoint *ep, |
388 | const struct urb *urb, gfp_t gfp) | 392 | const struct urb *urb, gfp_t gfp) |
389 | { | 393 | { |
390 | int result = 0; /* better code for lack of companion? */ | 394 | int result = 0; |
391 | struct device *dev = &wa->usb_iface->dev; | 395 | struct device *dev = &wa->usb_iface->dev; |
392 | struct usb_device *usb_dev = urb->dev; | ||
393 | u8 unauth = (usb_dev->wusb && !usb_dev->authenticated) ? 0x80 : 0; | ||
394 | u8 portnum = wusb_port_no_to_idx(urb->dev->portnum); | 396 | u8 portnum = wusb_port_no_to_idx(urb->dev->portnum); |
395 | 397 | ||
396 | #define AIM_CHECK(rdf, val, text) \ | 398 | #define AIM_CHECK(rdf, val, text) \ |
@@ -403,13 +405,10 @@ static int rpipe_check_aim(const struct wa_rpipe *rpipe, const struct wahc *wa, | |||
403 | WARN_ON(1); \ | 405 | WARN_ON(1); \ |
404 | } \ | 406 | } \ |
405 | } while (0) | 407 | } while (0) |
406 | AIM_CHECK(wMaxPacketSize, cpu_to_le16(ep->desc.wMaxPacketSize), | 408 | AIM_CHECK(hwa_bDeviceInfoIndex, portnum, "(%u vs %u)"); |
407 | "(%u vs %u)"); | ||
408 | AIM_CHECK(bHSHubPort, portnum, "(%u vs %u)"); | ||
409 | AIM_CHECK(bSpeed, usb_pipeendpoint(urb->pipe) == 0 ? | 409 | AIM_CHECK(bSpeed, usb_pipeendpoint(urb->pipe) == 0 ? |
410 | UWB_PHY_RATE_53 : UWB_PHY_RATE_200, | 410 | UWB_PHY_RATE_53 : UWB_PHY_RATE_200, |
411 | "(%u vs %u)"); | 411 | "(%u vs %u)"); |
412 | AIM_CHECK(bDeviceAddress, urb->dev->devnum | unauth, "(%u vs %u)"); | ||
413 | AIM_CHECK(bEndpointAddress, ep->desc.bEndpointAddress, "(%u vs %u)"); | 412 | AIM_CHECK(bEndpointAddress, ep->desc.bEndpointAddress, "(%u vs %u)"); |
414 | AIM_CHECK(bInterval, ep->desc.bInterval, "(%u vs %u)"); | 413 | AIM_CHECK(bInterval, ep->desc.bInterval, "(%u vs %u)"); |
415 | AIM_CHECK(bmAttribute, ep->desc.bmAttributes & 0x03, "(%u vs %u)"); | 414 | AIM_CHECK(bmAttribute, ep->desc.bmAttributes & 0x03, "(%u vs %u)"); |
diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c index 6ef94bce8c0d..16968c899493 100644 --- a/drivers/usb/wusbcore/wa-xfer.c +++ b/drivers/usb/wusbcore/wa-xfer.c | |||
@@ -85,6 +85,7 @@ | |||
85 | #include <linux/hash.h> | 85 | #include <linux/hash.h> |
86 | #include <linux/ratelimit.h> | 86 | #include <linux/ratelimit.h> |
87 | #include <linux/export.h> | 87 | #include <linux/export.h> |
88 | #include <linux/scatterlist.h> | ||
88 | 89 | ||
89 | #include "wa-hc.h" | 90 | #include "wa-hc.h" |
90 | #include "wusbhc.h" | 91 | #include "wusbhc.h" |
@@ -442,8 +443,7 @@ static ssize_t __wa_xfer_setup_sizes(struct wa_xfer *xfer, | |||
442 | goto error; | 443 | goto error; |
443 | } | 444 | } |
444 | xfer->seg_size = (xfer->seg_size / maxpktsize) * maxpktsize; | 445 | xfer->seg_size = (xfer->seg_size / maxpktsize) * maxpktsize; |
445 | xfer->segs = (urb->transfer_buffer_length + xfer->seg_size - 1) | 446 | xfer->segs = DIV_ROUND_UP(urb->transfer_buffer_length, xfer->seg_size); |
446 | / xfer->seg_size; | ||
447 | if (xfer->segs >= WA_SEGS_MAX) { | 447 | if (xfer->segs >= WA_SEGS_MAX) { |
448 | dev_err(dev, "BUG? ops, number of segments %d bigger than %d\n", | 448 | dev_err(dev, "BUG? ops, number of segments %d bigger than %d\n", |
449 | (int)(urb->transfer_buffer_length / xfer->seg_size), | 449 | (int)(urb->transfer_buffer_length / xfer->seg_size), |
@@ -627,6 +627,86 @@ static void wa_seg_cb(struct urb *urb) | |||
627 | } | 627 | } |
628 | } | 628 | } |
629 | 629 | ||
630 | /* allocate an SG list to store bytes_to_transfer bytes and copy the | ||
631 | * subset of the in_sg that matches the buffer subset | ||
632 | * we are about to transfer. */ | ||
633 | static struct scatterlist *wa_xfer_create_subset_sg(struct scatterlist *in_sg, | ||
634 | const unsigned int bytes_transferred, | ||
635 | const unsigned int bytes_to_transfer, unsigned int *out_num_sgs) | ||
636 | { | ||
637 | struct scatterlist *out_sg; | ||
638 | unsigned int bytes_processed = 0, offset_into_current_page_data = 0, | ||
639 | nents; | ||
640 | struct scatterlist *current_xfer_sg = in_sg; | ||
641 | struct scatterlist *current_seg_sg, *last_seg_sg; | ||
642 | |||
643 | /* skip previously transferred pages. */ | ||
644 | while ((current_xfer_sg) && | ||
645 | (bytes_processed < bytes_transferred)) { | ||
646 | bytes_processed += current_xfer_sg->length; | ||
647 | |||
648 | /* advance the sg if current segment starts on or past the | ||
649 | next page. */ | ||
650 | if (bytes_processed <= bytes_transferred) | ||
651 | current_xfer_sg = sg_next(current_xfer_sg); | ||
652 | } | ||
653 | |||
654 | /* the data for the current segment starts in current_xfer_sg. | ||
655 | calculate the offset. */ | ||
656 | if (bytes_processed > bytes_transferred) { | ||
657 | offset_into_current_page_data = current_xfer_sg->length - | ||
658 | (bytes_processed - bytes_transferred); | ||
659 | } | ||
660 | |||
661 | /* calculate the number of pages needed by this segment. */ | ||
662 | nents = DIV_ROUND_UP((bytes_to_transfer + | ||
663 | offset_into_current_page_data + | ||
664 | current_xfer_sg->offset), | ||
665 | PAGE_SIZE); | ||
666 | |||
667 | out_sg = kmalloc((sizeof(struct scatterlist) * nents), GFP_ATOMIC); | ||
668 | if (out_sg) { | ||
669 | sg_init_table(out_sg, nents); | ||
670 | |||
671 | /* copy the portion of the incoming SG that correlates to the | ||
672 | * data to be transferred by this segment to the segment SG. */ | ||
673 | last_seg_sg = current_seg_sg = out_sg; | ||
674 | bytes_processed = 0; | ||
675 | |||
676 | /* reset nents and calculate the actual number of sg entries | ||
677 | needed. */ | ||
678 | nents = 0; | ||
679 | while ((bytes_processed < bytes_to_transfer) && | ||
680 | current_seg_sg && current_xfer_sg) { | ||
681 | unsigned int page_len = min((current_xfer_sg->length - | ||
682 | offset_into_current_page_data), | ||
683 | (bytes_to_transfer - bytes_processed)); | ||
684 | |||
685 | sg_set_page(current_seg_sg, sg_page(current_xfer_sg), | ||
686 | page_len, | ||
687 | current_xfer_sg->offset + | ||
688 | offset_into_current_page_data); | ||
689 | |||
690 | bytes_processed += page_len; | ||
691 | |||
692 | last_seg_sg = current_seg_sg; | ||
693 | current_seg_sg = sg_next(current_seg_sg); | ||
694 | current_xfer_sg = sg_next(current_xfer_sg); | ||
695 | |||
696 | /* only the first page may require additional offset. */ | ||
697 | offset_into_current_page_data = 0; | ||
698 | nents++; | ||
699 | } | ||
700 | |||
701 | /* update num_sgs and terminate the list since we may have | ||
702 | * concatenated pages. */ | ||
703 | sg_mark_end(last_seg_sg); | ||
704 | *out_num_sgs = nents; | ||
705 | } | ||
706 | |||
707 | return out_sg; | ||
708 | } | ||
709 | |||
630 | /* | 710 | /* |
631 | * Allocate the segs array and initialize each of them | 711 | * Allocate the segs array and initialize each of them |
632 | * | 712 | * |
@@ -663,9 +743,9 @@ static int __wa_xfer_setup_segs(struct wa_xfer *xfer, size_t xfer_hdr_size) | |||
663 | dto_epd->bEndpointAddress), | 743 | dto_epd->bEndpointAddress), |
664 | &seg->xfer_hdr, xfer_hdr_size, | 744 | &seg->xfer_hdr, xfer_hdr_size, |
665 | wa_seg_cb, seg); | 745 | wa_seg_cb, seg); |
666 | buf_itr_size = buf_size > xfer->seg_size ? | 746 | buf_itr_size = min(buf_size, xfer->seg_size); |
667 | xfer->seg_size : buf_size; | ||
668 | if (xfer->is_inbound == 0 && buf_size > 0) { | 747 | if (xfer->is_inbound == 0 && buf_size > 0) { |
748 | /* outbound data. */ | ||
669 | seg->dto_urb = usb_alloc_urb(0, GFP_ATOMIC); | 749 | seg->dto_urb = usb_alloc_urb(0, GFP_ATOMIC); |
670 | if (seg->dto_urb == NULL) | 750 | if (seg->dto_urb == NULL) |
671 | goto error_dto_alloc; | 751 | goto error_dto_alloc; |
@@ -679,9 +759,42 @@ static int __wa_xfer_setup_segs(struct wa_xfer *xfer, size_t xfer_hdr_size) | |||
679 | xfer->urb->transfer_dma + buf_itr; | 759 | xfer->urb->transfer_dma + buf_itr; |
680 | seg->dto_urb->transfer_flags |= | 760 | seg->dto_urb->transfer_flags |= |
681 | URB_NO_TRANSFER_DMA_MAP; | 761 | URB_NO_TRANSFER_DMA_MAP; |
682 | } else | 762 | seg->dto_urb->transfer_buffer = NULL; |
683 | seg->dto_urb->transfer_buffer = | 763 | seg->dto_urb->sg = NULL; |
684 | xfer->urb->transfer_buffer + buf_itr; | 764 | seg->dto_urb->num_sgs = 0; |
765 | } else { | ||
766 | /* do buffer or SG processing. */ | ||
767 | seg->dto_urb->transfer_flags &= | ||
768 | ~URB_NO_TRANSFER_DMA_MAP; | ||
769 | /* this should always be 0 before a resubmit. */ | ||
770 | seg->dto_urb->num_mapped_sgs = 0; | ||
771 | |||
772 | if (xfer->urb->transfer_buffer) { | ||
773 | seg->dto_urb->transfer_buffer = | ||
774 | xfer->urb->transfer_buffer + | ||
775 | buf_itr; | ||
776 | seg->dto_urb->sg = NULL; | ||
777 | seg->dto_urb->num_sgs = 0; | ||
778 | } else { | ||
779 | /* allocate an SG list to store seg_size | ||
780 | bytes and copy the subset of the | ||
781 | xfer->urb->sg that matches the | ||
782 | buffer subset we are about to read. | ||
783 | */ | ||
784 | seg->dto_urb->sg = | ||
785 | wa_xfer_create_subset_sg( | ||
786 | xfer->urb->sg, | ||
787 | buf_itr, buf_itr_size, | ||
788 | &(seg->dto_urb->num_sgs)); | ||
789 | |||
790 | if (!(seg->dto_urb->sg)) { | ||
791 | seg->dto_urb->num_sgs = 0; | ||
792 | goto error_sg_alloc; | ||
793 | } | ||
794 | |||
795 | seg->dto_urb->transfer_buffer = NULL; | ||
796 | } | ||
797 | } | ||
685 | seg->dto_urb->transfer_buffer_length = buf_itr_size; | 798 | seg->dto_urb->transfer_buffer_length = buf_itr_size; |
686 | } | 799 | } |
687 | seg->status = WA_SEG_READY; | 800 | seg->status = WA_SEG_READY; |
@@ -690,6 +803,8 @@ static int __wa_xfer_setup_segs(struct wa_xfer *xfer, size_t xfer_hdr_size) | |||
690 | } | 803 | } |
691 | return 0; | 804 | return 0; |
692 | 805 | ||
806 | error_sg_alloc: | ||
807 | kfree(seg->dto_urb); | ||
693 | error_dto_alloc: | 808 | error_dto_alloc: |
694 | kfree(xfer->seg[cnt]); | 809 | kfree(xfer->seg[cnt]); |
695 | cnt--; | 810 | cnt--; |
@@ -1026,7 +1141,8 @@ int wa_urb_enqueue(struct wahc *wa, struct usb_host_endpoint *ep, | |||
1026 | unsigned long my_flags; | 1141 | unsigned long my_flags; |
1027 | unsigned cant_sleep = irqs_disabled() | in_atomic(); | 1142 | unsigned cant_sleep = irqs_disabled() | in_atomic(); |
1028 | 1143 | ||
1029 | if (urb->transfer_buffer == NULL | 1144 | if ((urb->transfer_buffer == NULL) |
1145 | && (urb->sg == NULL) | ||
1030 | && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) | 1146 | && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) |
1031 | && urb->transfer_buffer_length != 0) { | 1147 | && urb->transfer_buffer_length != 0) { |
1032 | dev_err(dev, "BUG? urb %p: NULL xfer buffer & NODMA\n", urb); | 1148 | dev_err(dev, "BUG? urb %p: NULL xfer buffer & NODMA\n", urb); |
@@ -1261,7 +1377,7 @@ static void wa_xfer_result_chew(struct wahc *wa, struct wa_xfer *xfer) | |||
1261 | seg = xfer->seg[seg_idx]; | 1377 | seg = xfer->seg[seg_idx]; |
1262 | rpipe = xfer->ep->hcpriv; | 1378 | rpipe = xfer->ep->hcpriv; |
1263 | usb_status = xfer_result->bTransferStatus; | 1379 | usb_status = xfer_result->bTransferStatus; |
1264 | dev_dbg(dev, "xfer %p#%u: bTransferStatus 0x%02x (seg %u)\n", | 1380 | dev_dbg(dev, "xfer %p#%u: bTransferStatus 0x%02x (seg status %u)\n", |
1265 | xfer, seg_idx, usb_status, seg->status); | 1381 | xfer, seg_idx, usb_status, seg->status); |
1266 | if (seg->status == WA_SEG_ABORTED | 1382 | if (seg->status == WA_SEG_ABORTED |
1267 | || seg->status == WA_SEG_ERROR) /* already handled */ | 1383 | || seg->status == WA_SEG_ERROR) /* already handled */ |
@@ -1276,8 +1392,8 @@ static void wa_xfer_result_chew(struct wahc *wa, struct wa_xfer *xfer) | |||
1276 | } | 1392 | } |
1277 | if (usb_status & 0x80) { | 1393 | if (usb_status & 0x80) { |
1278 | seg->result = wa_xfer_status_to_errno(usb_status); | 1394 | seg->result = wa_xfer_status_to_errno(usb_status); |
1279 | dev_err(dev, "DTI: xfer %p#%u failed (0x%02x)\n", | 1395 | dev_err(dev, "DTI: xfer %p#:%08X:%u failed (0x%02x)\n", |
1280 | xfer, seg->index, usb_status); | 1396 | xfer, xfer->id, seg->index, usb_status); |
1281 | goto error_complete; | 1397 | goto error_complete; |
1282 | } | 1398 | } |
1283 | /* FIXME: we ignore warnings, tally them for stats */ | 1399 | /* FIXME: we ignore warnings, tally them for stats */ |
@@ -1286,18 +1402,47 @@ static void wa_xfer_result_chew(struct wahc *wa, struct wa_xfer *xfer) | |||
1286 | if (xfer->is_inbound) { /* IN data phase: read to buffer */ | 1402 | if (xfer->is_inbound) { /* IN data phase: read to buffer */ |
1287 | seg->status = WA_SEG_DTI_PENDING; | 1403 | seg->status = WA_SEG_DTI_PENDING; |
1288 | BUG_ON(wa->buf_in_urb->status == -EINPROGRESS); | 1404 | BUG_ON(wa->buf_in_urb->status == -EINPROGRESS); |
1405 | /* this should always be 0 before a resubmit. */ | ||
1406 | wa->buf_in_urb->num_mapped_sgs = 0; | ||
1407 | |||
1289 | if (xfer->is_dma) { | 1408 | if (xfer->is_dma) { |
1290 | wa->buf_in_urb->transfer_dma = | 1409 | wa->buf_in_urb->transfer_dma = |
1291 | xfer->urb->transfer_dma | 1410 | xfer->urb->transfer_dma |
1292 | + seg_idx * xfer->seg_size; | 1411 | + (seg_idx * xfer->seg_size); |
1293 | wa->buf_in_urb->transfer_flags | 1412 | wa->buf_in_urb->transfer_flags |
1294 | |= URB_NO_TRANSFER_DMA_MAP; | 1413 | |= URB_NO_TRANSFER_DMA_MAP; |
1414 | wa->buf_in_urb->transfer_buffer = NULL; | ||
1415 | wa->buf_in_urb->sg = NULL; | ||
1416 | wa->buf_in_urb->num_sgs = 0; | ||
1295 | } else { | 1417 | } else { |
1296 | wa->buf_in_urb->transfer_buffer = | 1418 | /* do buffer or SG processing. */ |
1297 | xfer->urb->transfer_buffer | ||
1298 | + seg_idx * xfer->seg_size; | ||
1299 | wa->buf_in_urb->transfer_flags | 1419 | wa->buf_in_urb->transfer_flags |
1300 | &= ~URB_NO_TRANSFER_DMA_MAP; | 1420 | &= ~URB_NO_TRANSFER_DMA_MAP; |
1421 | |||
1422 | if (xfer->urb->transfer_buffer) { | ||
1423 | wa->buf_in_urb->transfer_buffer = | ||
1424 | xfer->urb->transfer_buffer | ||
1425 | + (seg_idx * xfer->seg_size); | ||
1426 | wa->buf_in_urb->sg = NULL; | ||
1427 | wa->buf_in_urb->num_sgs = 0; | ||
1428 | } else { | ||
1429 | /* allocate an SG list to store seg_size bytes | ||
1430 | and copy the subset of the xfer->urb->sg | ||
1431 | that matches the buffer subset we are | ||
1432 | about to read. */ | ||
1433 | wa->buf_in_urb->sg = wa_xfer_create_subset_sg( | ||
1434 | xfer->urb->sg, | ||
1435 | seg_idx * xfer->seg_size, | ||
1436 | le32_to_cpu( | ||
1437 | xfer_result->dwTransferLength), | ||
1438 | &(wa->buf_in_urb->num_sgs)); | ||
1439 | |||
1440 | if (!(wa->buf_in_urb->sg)) { | ||
1441 | wa->buf_in_urb->num_sgs = 0; | ||
1442 | goto error_sg_alloc; | ||
1443 | } | ||
1444 | wa->buf_in_urb->transfer_buffer = NULL; | ||
1445 | } | ||
1301 | } | 1446 | } |
1302 | wa->buf_in_urb->transfer_buffer_length = | 1447 | wa->buf_in_urb->transfer_buffer_length = |
1303 | le32_to_cpu(xfer_result->dwTransferLength); | 1448 | le32_to_cpu(xfer_result->dwTransferLength); |
@@ -1330,6 +1475,8 @@ error_submit_buf_in: | |||
1330 | dev_err(dev, "xfer %p#%u: can't submit DTI data phase: %d\n", | 1475 | dev_err(dev, "xfer %p#%u: can't submit DTI data phase: %d\n", |
1331 | xfer, seg_idx, result); | 1476 | xfer, seg_idx, result); |
1332 | seg->result = result; | 1477 | seg->result = result; |
1478 | kfree(wa->buf_in_urb->sg); | ||
1479 | error_sg_alloc: | ||
1333 | error_complete: | 1480 | error_complete: |
1334 | seg->status = WA_SEG_ERROR; | 1481 | seg->status = WA_SEG_ERROR; |
1335 | xfer->segs_done++; | 1482 | xfer->segs_done++; |
@@ -1381,6 +1528,10 @@ static void wa_buf_in_cb(struct urb *urb) | |||
1381 | unsigned long flags; | 1528 | unsigned long flags; |
1382 | u8 done = 0; | 1529 | u8 done = 0; |
1383 | 1530 | ||
1531 | /* free the sg if it was used. */ | ||
1532 | kfree(urb->sg); | ||
1533 | urb->sg = NULL; | ||
1534 | |||
1384 | switch (urb->status) { | 1535 | switch (urb->status) { |
1385 | case 0: | 1536 | case 0: |
1386 | spin_lock_irqsave(&xfer->lock, flags); | 1537 | spin_lock_irqsave(&xfer->lock, flags); |
diff --git a/drivers/usb/wusbcore/wusbhc.c b/drivers/usb/wusbcore/wusbhc.c index 0faca16df765..742c607d1fa3 100644 --- a/drivers/usb/wusbcore/wusbhc.c +++ b/drivers/usb/wusbcore/wusbhc.c | |||
@@ -75,12 +75,11 @@ static ssize_t wusb_trust_timeout_store(struct device *dev, | |||
75 | result = -EINVAL; | 75 | result = -EINVAL; |
76 | goto out; | 76 | goto out; |
77 | } | 77 | } |
78 | /* FIXME: maybe we should check for range validity? */ | 78 | wusbhc->trust_timeout = min_t(unsigned, trust_timeout, 500); |
79 | wusbhc->trust_timeout = trust_timeout; | ||
80 | cancel_delayed_work(&wusbhc->keep_alive_timer); | 79 | cancel_delayed_work(&wusbhc->keep_alive_timer); |
81 | flush_workqueue(wusbd); | 80 | flush_workqueue(wusbd); |
82 | queue_delayed_work(wusbd, &wusbhc->keep_alive_timer, | 81 | queue_delayed_work(wusbd, &wusbhc->keep_alive_timer, |
83 | (trust_timeout * CONFIG_HZ)/1000/2); | 82 | msecs_to_jiffies(wusbhc->trust_timeout / 2)); |
84 | out: | 83 | out: |
85 | return result < 0 ? result : size; | 84 | return result < 0 ? result : size; |
86 | } | 85 | } |
@@ -176,11 +175,72 @@ static ssize_t wusb_phy_rate_store(struct device *dev, | |||
176 | } | 175 | } |
177 | static DEVICE_ATTR(wusb_phy_rate, 0644, wusb_phy_rate_show, wusb_phy_rate_store); | 176 | static DEVICE_ATTR(wusb_phy_rate, 0644, wusb_phy_rate_show, wusb_phy_rate_store); |
178 | 177 | ||
178 | static ssize_t wusb_dnts_show(struct device *dev, | ||
179 | struct device_attribute *attr, | ||
180 | char *buf) | ||
181 | { | ||
182 | struct wusbhc *wusbhc = usbhc_dev_to_wusbhc(dev); | ||
183 | |||
184 | return sprintf(buf, "num slots: %d\ninterval: %dms\n", | ||
185 | wusbhc->dnts_num_slots, wusbhc->dnts_interval); | ||
186 | } | ||
187 | |||
188 | static ssize_t wusb_dnts_store(struct device *dev, | ||
189 | struct device_attribute *attr, | ||
190 | const char *buf, size_t size) | ||
191 | { | ||
192 | struct wusbhc *wusbhc = usbhc_dev_to_wusbhc(dev); | ||
193 | uint8_t num_slots, interval; | ||
194 | ssize_t result; | ||
195 | |||
196 | result = sscanf(buf, "%hhu %hhu", &num_slots, &interval); | ||
197 | |||
198 | if (result != 2) | ||
199 | return -EINVAL; | ||
200 | |||
201 | wusbhc->dnts_num_slots = num_slots; | ||
202 | wusbhc->dnts_interval = interval; | ||
203 | |||
204 | return size; | ||
205 | } | ||
206 | static DEVICE_ATTR(wusb_dnts, 0644, wusb_dnts_show, wusb_dnts_store); | ||
207 | |||
208 | static ssize_t wusb_retry_count_show(struct device *dev, | ||
209 | struct device_attribute *attr, | ||
210 | char *buf) | ||
211 | { | ||
212 | struct wusbhc *wusbhc = usbhc_dev_to_wusbhc(dev); | ||
213 | |||
214 | return sprintf(buf, "%d\n", wusbhc->retry_count); | ||
215 | } | ||
216 | |||
217 | static ssize_t wusb_retry_count_store(struct device *dev, | ||
218 | struct device_attribute *attr, | ||
219 | const char *buf, size_t size) | ||
220 | { | ||
221 | struct wusbhc *wusbhc = usbhc_dev_to_wusbhc(dev); | ||
222 | uint8_t retry_count; | ||
223 | ssize_t result; | ||
224 | |||
225 | result = sscanf(buf, "%hhu", &retry_count); | ||
226 | |||
227 | if (result != 1) | ||
228 | return -EINVAL; | ||
229 | |||
230 | wusbhc->retry_count = max_t(uint8_t, retry_count, WUSB_RETRY_COUNT_MAX); | ||
231 | |||
232 | return size; | ||
233 | } | ||
234 | static DEVICE_ATTR(wusb_retry_count, 0644, wusb_retry_count_show, | ||
235 | wusb_retry_count_store); | ||
236 | |||
179 | /* Group all the WUSBHC attributes */ | 237 | /* Group all the WUSBHC attributes */ |
180 | static struct attribute *wusbhc_attrs[] = { | 238 | static struct attribute *wusbhc_attrs[] = { |
181 | &dev_attr_wusb_trust_timeout.attr, | 239 | &dev_attr_wusb_trust_timeout.attr, |
182 | &dev_attr_wusb_chid.attr, | 240 | &dev_attr_wusb_chid.attr, |
183 | &dev_attr_wusb_phy_rate.attr, | 241 | &dev_attr_wusb_phy_rate.attr, |
242 | &dev_attr_wusb_dnts.attr, | ||
243 | &dev_attr_wusb_retry_count.attr, | ||
184 | NULL, | 244 | NULL, |
185 | }; | 245 | }; |
186 | 246 | ||
@@ -206,8 +266,12 @@ int wusbhc_create(struct wusbhc *wusbhc) | |||
206 | { | 266 | { |
207 | int result = 0; | 267 | int result = 0; |
208 | 268 | ||
269 | /* set defaults. These can be overwritten using sysfs attributes. */ | ||
209 | wusbhc->trust_timeout = WUSB_TRUST_TIMEOUT_MS; | 270 | wusbhc->trust_timeout = WUSB_TRUST_TIMEOUT_MS; |
210 | wusbhc->phy_rate = UWB_PHY_RATE_INVALID - 1; | 271 | wusbhc->phy_rate = UWB_PHY_RATE_INVALID - 1; |
272 | wusbhc->dnts_num_slots = 4; | ||
273 | wusbhc->dnts_interval = 2; | ||
274 | wusbhc->retry_count = WUSB_RETRY_COUNT_INFINITE; | ||
211 | 275 | ||
212 | mutex_init(&wusbhc->mutex); | 276 | mutex_init(&wusbhc->mutex); |
213 | result = wusbhc_mmcie_create(wusbhc); | 277 | result = wusbhc_mmcie_create(wusbhc); |
@@ -261,13 +325,7 @@ int wusbhc_b_create(struct wusbhc *wusbhc) | |||
261 | goto error_create_attr_group; | 325 | goto error_create_attr_group; |
262 | } | 326 | } |
263 | 327 | ||
264 | result = wusbhc_pal_register(wusbhc); | ||
265 | if (result < 0) | ||
266 | goto error_pal_register; | ||
267 | return 0; | 328 | return 0; |
268 | |||
269 | error_pal_register: | ||
270 | sysfs_remove_group(wusbhc_kobj(wusbhc), &wusbhc_attr_group); | ||
271 | error_create_attr_group: | 329 | error_create_attr_group: |
272 | return result; | 330 | return result; |
273 | } | 331 | } |
@@ -393,7 +451,8 @@ EXPORT_SYMBOL_GPL(wusbhc_giveback_urb); | |||
393 | */ | 451 | */ |
394 | void wusbhc_reset_all(struct wusbhc *wusbhc) | 452 | void wusbhc_reset_all(struct wusbhc *wusbhc) |
395 | { | 453 | { |
396 | uwb_rc_reset_all(wusbhc->uwb_rc); | 454 | if (wusbhc->uwb_rc) |
455 | uwb_rc_reset_all(wusbhc->uwb_rc); | ||
397 | } | 456 | } |
398 | EXPORT_SYMBOL_GPL(wusbhc_reset_all); | 457 | EXPORT_SYMBOL_GPL(wusbhc_reset_all); |
399 | 458 | ||
diff --git a/drivers/usb/wusbcore/wusbhc.h b/drivers/usb/wusbcore/wusbhc.h index 3a2d09162e70..711b1952b114 100644 --- a/drivers/usb/wusbcore/wusbhc.h +++ b/drivers/usb/wusbcore/wusbhc.h | |||
@@ -69,6 +69,8 @@ | |||
69 | * zone 0. | 69 | * zone 0. |
70 | */ | 70 | */ |
71 | #define WUSB_CHANNEL_STOP_DELAY_MS 8 | 71 | #define WUSB_CHANNEL_STOP_DELAY_MS 8 |
72 | #define WUSB_RETRY_COUNT_MAX 15 | ||
73 | #define WUSB_RETRY_COUNT_INFINITE 0 | ||
72 | 74 | ||
73 | /** | 75 | /** |
74 | * Wireless USB device | 76 | * Wireless USB device |
@@ -252,6 +254,9 @@ struct wusbhc { | |||
252 | unsigned trust_timeout; /* in jiffies */ | 254 | unsigned trust_timeout; /* in jiffies */ |
253 | struct wusb_ckhdid chid; | 255 | struct wusb_ckhdid chid; |
254 | uint8_t phy_rate; | 256 | uint8_t phy_rate; |
257 | uint8_t dnts_num_slots; | ||
258 | uint8_t dnts_interval; | ||
259 | uint8_t retry_count; | ||
255 | struct wuie_host_info *wuie_host_info; | 260 | struct wuie_host_info *wuie_host_info; |
256 | 261 | ||
257 | struct mutex mutex; /* locks everything else */ | 262 | struct mutex mutex; /* locks everything else */ |
@@ -399,8 +404,6 @@ extern void wusbhc_rh_destroy(struct wusbhc *); | |||
399 | 404 | ||
400 | extern int wusbhc_rh_status_data(struct usb_hcd *, char *); | 405 | extern int wusbhc_rh_status_data(struct usb_hcd *, char *); |
401 | extern int wusbhc_rh_control(struct usb_hcd *, u16, u16, u16, char *, u16); | 406 | extern int wusbhc_rh_control(struct usb_hcd *, u16, u16, u16, char *, u16); |
402 | extern int wusbhc_rh_suspend(struct usb_hcd *); | ||
403 | extern int wusbhc_rh_resume(struct usb_hcd *); | ||
404 | extern int wusbhc_rh_start_port_reset(struct usb_hcd *, unsigned); | 407 | extern int wusbhc_rh_start_port_reset(struct usb_hcd *, unsigned); |
405 | 408 | ||
406 | /* MMC handling */ | 409 | /* MMC handling */ |
diff --git a/drivers/uwb/drp.c b/drivers/uwb/drp.c index 3fbcf789dfaa..16ada8341c46 100644 --- a/drivers/uwb/drp.c +++ b/drivers/uwb/drp.c | |||
@@ -67,14 +67,14 @@ static void uwb_rc_set_drp_cmd_done(struct uwb_rc *rc, void *arg, | |||
67 | } else | 67 | } else |
68 | dev_err(&rc->uwb_dev.dev, "SET-DRP-IE: timeout\n"); | 68 | dev_err(&rc->uwb_dev.dev, "SET-DRP-IE: timeout\n"); |
69 | 69 | ||
70 | spin_lock_bh(&rc->rsvs_lock); | 70 | spin_lock_irq(&rc->rsvs_lock); |
71 | if (rc->set_drp_ie_pending > 1) { | 71 | if (rc->set_drp_ie_pending > 1) { |
72 | rc->set_drp_ie_pending = 0; | 72 | rc->set_drp_ie_pending = 0; |
73 | uwb_rsv_queue_update(rc); | 73 | uwb_rsv_queue_update(rc); |
74 | } else { | 74 | } else { |
75 | rc->set_drp_ie_pending = 0; | 75 | rc->set_drp_ie_pending = 0; |
76 | } | 76 | } |
77 | spin_unlock_bh(&rc->rsvs_lock); | 77 | spin_unlock_irq(&rc->rsvs_lock); |
78 | } | 78 | } |
79 | 79 | ||
80 | /** | 80 | /** |
diff --git a/drivers/uwb/est.c b/drivers/uwb/est.c index 86ed7e61e597..457f31d99bf4 100644 --- a/drivers/uwb/est.c +++ b/drivers/uwb/est.c | |||
@@ -436,7 +436,6 @@ ssize_t uwb_est_find_size(struct uwb_rc *rc, const struct uwb_rceb *rceb, | |||
436 | unsigned long flags; | 436 | unsigned long flags; |
437 | unsigned itr; | 437 | unsigned itr; |
438 | u16 type_event_high, event; | 438 | u16 type_event_high, event; |
439 | u8 *ptr = (u8 *) rceb; | ||
440 | 439 | ||
441 | read_lock_irqsave(&uwb_est_lock, flags); | 440 | read_lock_irqsave(&uwb_est_lock, flags); |
442 | size = -ENOSPC; | 441 | size = -ENOSPC; |
@@ -453,12 +452,12 @@ ssize_t uwb_est_find_size(struct uwb_rc *rc, const struct uwb_rceb *rceb, | |||
453 | if (size != -ENOENT) | 452 | if (size != -ENOENT) |
454 | goto out; | 453 | goto out; |
455 | } | 454 | } |
456 | dev_dbg(dev, "event 0x%02x/%04x/%02x: no handlers available; " | 455 | dev_dbg(dev, |
457 | "RCEB %02x %02x %02x %02x\n", | 456 | "event 0x%02x/%04x/%02x: no handlers available; RCEB %4ph\n", |
458 | (unsigned) rceb->bEventType, | 457 | (unsigned) rceb->bEventType, |
459 | (unsigned) le16_to_cpu(rceb->wEvent), | 458 | (unsigned) le16_to_cpu(rceb->wEvent), |
460 | (unsigned) rceb->bEventContext, | 459 | (unsigned) rceb->bEventContext, |
461 | ptr[0], ptr[1], ptr[2], ptr[3]); | 460 | rceb); |
462 | size = -ENOENT; | 461 | size = -ENOENT; |
463 | out: | 462 | out: |
464 | read_unlock_irqrestore(&uwb_est_lock, flags); | 463 | read_unlock_irqrestore(&uwb_est_lock, flags); |
diff --git a/drivers/uwb/hwa-rc.c b/drivers/uwb/hwa-rc.c index 810c90ae2c55..0621abef9b4a 100644 --- a/drivers/uwb/hwa-rc.c +++ b/drivers/uwb/hwa-rc.c | |||
@@ -900,6 +900,12 @@ static const struct usb_device_id hwarc_id_table[] = { | |||
900 | /* Intel i1480 (using firmware 1.3PA2-20070828) */ | 900 | /* Intel i1480 (using firmware 1.3PA2-20070828) */ |
901 | { USB_DEVICE_AND_INTERFACE_INFO(0x8086, 0x0c3b, 0xe0, 0x01, 0x02), | 901 | { USB_DEVICE_AND_INTERFACE_INFO(0x8086, 0x0c3b, 0xe0, 0x01, 0x02), |
902 | .driver_info = WUSB_QUIRK_WHCI_CMD_EVT }, | 902 | .driver_info = WUSB_QUIRK_WHCI_CMD_EVT }, |
903 | /* Alereon 5310 */ | ||
904 | { USB_DEVICE_AND_INTERFACE_INFO(0x13dc, 0x5310, 0xe0, 0x01, 0x02), | ||
905 | .driver_info = WUSB_QUIRK_WHCI_CMD_EVT }, | ||
906 | /* Alereon 5611 */ | ||
907 | { USB_DEVICE_AND_INTERFACE_INFO(0x13dc, 0x5611, 0xe0, 0x01, 0x02), | ||
908 | .driver_info = WUSB_QUIRK_WHCI_CMD_EVT }, | ||
903 | /* Generic match for the Radio Control interface */ | 909 | /* Generic match for the Radio Control interface */ |
904 | { USB_INTERFACE_INFO(0xe0, 0x01, 0x02), }, | 910 | { USB_INTERFACE_INFO(0xe0, 0x01, 0x02), }, |
905 | { }, | 911 | { }, |
diff --git a/drivers/uwb/pal.c b/drivers/uwb/pal.c index 8ee7d90a8c68..690577d2a35b 100644 --- a/drivers/uwb/pal.c +++ b/drivers/uwb/pal.c | |||
@@ -44,10 +44,12 @@ int uwb_pal_register(struct uwb_pal *pal) | |||
44 | int ret; | 44 | int ret; |
45 | 45 | ||
46 | if (pal->device) { | 46 | if (pal->device) { |
47 | /* create a link to the uwb_rc in the PAL device's directory. */ | ||
47 | ret = sysfs_create_link(&pal->device->kobj, | 48 | ret = sysfs_create_link(&pal->device->kobj, |
48 | &rc->uwb_dev.dev.kobj, "uwb_rc"); | 49 | &rc->uwb_dev.dev.kobj, "uwb_rc"); |
49 | if (ret < 0) | 50 | if (ret < 0) |
50 | return ret; | 51 | return ret; |
52 | /* create a link to the PAL in the UWB device's directory. */ | ||
51 | ret = sysfs_create_link(&rc->uwb_dev.dev.kobj, | 53 | ret = sysfs_create_link(&rc->uwb_dev.dev.kobj, |
52 | &pal->device->kobj, pal->name); | 54 | &pal->device->kobj, pal->name); |
53 | if (ret < 0) { | 55 | if (ret < 0) { |
diff --git a/drivers/uwb/rsv.c b/drivers/uwb/rsv.c index f4ae05f78c42..738e8a8cb811 100644 --- a/drivers/uwb/rsv.c +++ b/drivers/uwb/rsv.c | |||
@@ -872,7 +872,7 @@ void uwb_rsv_queue_update(struct uwb_rc *rc) | |||
872 | */ | 872 | */ |
873 | void uwb_rsv_sched_update(struct uwb_rc *rc) | 873 | void uwb_rsv_sched_update(struct uwb_rc *rc) |
874 | { | 874 | { |
875 | spin_lock_bh(&rc->rsvs_lock); | 875 | spin_lock_irq(&rc->rsvs_lock); |
876 | if (!delayed_work_pending(&rc->rsv_update_work)) { | 876 | if (!delayed_work_pending(&rc->rsv_update_work)) { |
877 | if (rc->set_drp_ie_pending > 0) { | 877 | if (rc->set_drp_ie_pending > 0) { |
878 | rc->set_drp_ie_pending++; | 878 | rc->set_drp_ie_pending++; |
@@ -881,7 +881,7 @@ void uwb_rsv_sched_update(struct uwb_rc *rc) | |||
881 | uwb_rsv_queue_update(rc); | 881 | uwb_rsv_queue_update(rc); |
882 | } | 882 | } |
883 | unlock: | 883 | unlock: |
884 | spin_unlock_bh(&rc->rsvs_lock); | 884 | spin_unlock_irq(&rc->rsvs_lock); |
885 | } | 885 | } |
886 | 886 | ||
887 | /* | 887 | /* |
diff --git a/drivers/uwb/uwb-internal.h b/drivers/uwb/uwb-internal.h index a7494bf10081..9a103b100f1e 100644 --- a/drivers/uwb/uwb-internal.h +++ b/drivers/uwb/uwb-internal.h | |||
@@ -55,7 +55,8 @@ static inline struct uwb_rc *__uwb_rc_get(struct uwb_rc *rc) | |||
55 | 55 | ||
56 | static inline void __uwb_rc_put(struct uwb_rc *rc) | 56 | static inline void __uwb_rc_put(struct uwb_rc *rc) |
57 | { | 57 | { |
58 | uwb_dev_put(&rc->uwb_dev); | 58 | if (rc) |
59 | uwb_dev_put(&rc->uwb_dev); | ||
59 | } | 60 | } |
60 | 61 | ||
61 | extern int uwb_rc_reset(struct uwb_rc *rc); | 62 | extern int uwb_rc_reset(struct uwb_rc *rc); |
diff --git a/drivers/uwb/whci.c b/drivers/uwb/whci.c index f48093e649e4..c9df8ba97dae 100644 --- a/drivers/uwb/whci.c +++ b/drivers/uwb/whci.c | |||
@@ -253,19 +253,7 @@ static struct pci_driver whci_driver = { | |||
253 | .remove = whci_remove, | 253 | .remove = whci_remove, |
254 | }; | 254 | }; |
255 | 255 | ||
256 | static int __init whci_init(void) | 256 | module_pci_driver(whci_driver); |
257 | { | ||
258 | return pci_register_driver(&whci_driver); | ||
259 | } | ||
260 | |||
261 | static void __exit whci_exit(void) | ||
262 | { | ||
263 | pci_unregister_driver(&whci_driver); | ||
264 | } | ||
265 | |||
266 | module_init(whci_init); | ||
267 | module_exit(whci_exit); | ||
268 | |||
269 | MODULE_DESCRIPTION("WHCI UWB Multi-interface Controller enumerator"); | 257 | MODULE_DESCRIPTION("WHCI UWB Multi-interface Controller enumerator"); |
270 | MODULE_AUTHOR("Cambridge Silicon Radio Ltd."); | 258 | MODULE_AUTHOR("Cambridge Silicon Radio Ltd."); |
271 | MODULE_LICENSE("GPL"); | 259 | MODULE_LICENSE("GPL"); |
diff --git a/include/linux/platform_data/usb3503.h b/include/linux/platform_data/usb3503.h index 85dcc709f7e9..1d1b6ef871f6 100644 --- a/include/linux/platform_data/usb3503.h +++ b/include/linux/platform_data/usb3503.h | |||
@@ -3,6 +3,10 @@ | |||
3 | 3 | ||
4 | #define USB3503_I2C_NAME "usb3503" | 4 | #define USB3503_I2C_NAME "usb3503" |
5 | 5 | ||
6 | #define USB3503_OFF_PORT1 (1 << 1) | ||
7 | #define USB3503_OFF_PORT2 (1 << 2) | ||
8 | #define USB3503_OFF_PORT3 (1 << 3) | ||
9 | |||
6 | enum usb3503_mode { | 10 | enum usb3503_mode { |
7 | USB3503_MODE_UNKNOWN, | 11 | USB3503_MODE_UNKNOWN, |
8 | USB3503_MODE_HUB, | 12 | USB3503_MODE_HUB, |
@@ -11,6 +15,7 @@ enum usb3503_mode { | |||
11 | 15 | ||
12 | struct usb3503_platform_data { | 16 | struct usb3503_platform_data { |
13 | enum usb3503_mode initial_mode; | 17 | enum usb3503_mode initial_mode; |
18 | u8 port_off_mask; | ||
14 | int gpio_intn; | 19 | int gpio_intn; |
15 | int gpio_connect; | 20 | int gpio_connect; |
16 | int gpio_reset; | 21 | int gpio_reset; |
diff --git a/include/linux/usb.h b/include/linux/usb.h index a0bee5a28d1a..a232b7ece1f6 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h | |||
@@ -394,6 +394,22 @@ enum usb_port_connect_type { | |||
394 | }; | 394 | }; |
395 | 395 | ||
396 | /* | 396 | /* |
397 | * USB 2.0 Link Power Management (LPM) parameters. | ||
398 | */ | ||
399 | struct usb2_lpm_parameters { | ||
400 | /* Best effort service latency indicate how long the host will drive | ||
401 | * resume on an exit from L1. | ||
402 | */ | ||
403 | unsigned int besl; | ||
404 | |||
405 | /* Timeout value in microseconds for the L1 inactivity (LPM) timer. | ||
406 | * When the timer counts to zero, the parent hub will initiate a LPM | ||
407 | * transition to L1. | ||
408 | */ | ||
409 | int timeout; | ||
410 | }; | ||
411 | |||
412 | /* | ||
397 | * USB 3.0 Link Power Management (LPM) parameters. | 413 | * USB 3.0 Link Power Management (LPM) parameters. |
398 | * | 414 | * |
399 | * PEL and SEL are USB 3.0 Link PM latencies for device-initiated LPM exit. | 415 | * PEL and SEL are USB 3.0 Link PM latencies for device-initiated LPM exit. |
@@ -468,6 +484,7 @@ struct usb3_lpm_parameters { | |||
468 | * @wusb: device is Wireless USB | 484 | * @wusb: device is Wireless USB |
469 | * @lpm_capable: device supports LPM | 485 | * @lpm_capable: device supports LPM |
470 | * @usb2_hw_lpm_capable: device can perform USB2 hardware LPM | 486 | * @usb2_hw_lpm_capable: device can perform USB2 hardware LPM |
487 | * @usb2_hw_lpm_besl_capable: device can perform USB2 hardware BESL LPM | ||
471 | * @usb2_hw_lpm_enabled: USB2 hardware LPM enabled | 488 | * @usb2_hw_lpm_enabled: USB2 hardware LPM enabled |
472 | * @usb3_lpm_enabled: USB3 hardware LPM enabled | 489 | * @usb3_lpm_enabled: USB3 hardware LPM enabled |
473 | * @string_langid: language ID for strings | 490 | * @string_langid: language ID for strings |
@@ -487,6 +504,7 @@ struct usb3_lpm_parameters { | |||
487 | * specific data for the device. | 504 | * specific data for the device. |
488 | * @slot_id: Slot ID assigned by xHCI | 505 | * @slot_id: Slot ID assigned by xHCI |
489 | * @removable: Device can be physically removed from this port | 506 | * @removable: Device can be physically removed from this port |
507 | * @l1_params: best effor service latency for USB2 L1 LPM state, and L1 timeout. | ||
490 | * @u1_params: exit latencies for USB3 U1 LPM state, and hub-initiated timeout. | 508 | * @u1_params: exit latencies for USB3 U1 LPM state, and hub-initiated timeout. |
491 | * @u2_params: exit latencies for USB3 U2 LPM state, and hub-initiated timeout. | 509 | * @u2_params: exit latencies for USB3 U2 LPM state, and hub-initiated timeout. |
492 | * @lpm_disable_count: Ref count used by usb_disable_lpm() and usb_enable_lpm() | 510 | * @lpm_disable_count: Ref count used by usb_disable_lpm() and usb_enable_lpm() |
@@ -538,6 +556,7 @@ struct usb_device { | |||
538 | unsigned wusb:1; | 556 | unsigned wusb:1; |
539 | unsigned lpm_capable:1; | 557 | unsigned lpm_capable:1; |
540 | unsigned usb2_hw_lpm_capable:1; | 558 | unsigned usb2_hw_lpm_capable:1; |
559 | unsigned usb2_hw_lpm_besl_capable:1; | ||
541 | unsigned usb2_hw_lpm_enabled:1; | 560 | unsigned usb2_hw_lpm_enabled:1; |
542 | unsigned usb3_lpm_enabled:1; | 561 | unsigned usb3_lpm_enabled:1; |
543 | int string_langid; | 562 | int string_langid; |
@@ -566,6 +585,7 @@ struct usb_device { | |||
566 | struct wusb_dev *wusb_dev; | 585 | struct wusb_dev *wusb_dev; |
567 | int slot_id; | 586 | int slot_id; |
568 | enum usb_device_removable removable; | 587 | enum usb_device_removable removable; |
588 | struct usb2_lpm_parameters l1_params; | ||
569 | struct usb3_lpm_parameters u1_params; | 589 | struct usb3_lpm_parameters u1_params; |
570 | struct usb3_lpm_parameters u2_params; | 590 | struct usb3_lpm_parameters u2_params; |
571 | unsigned lpm_disable_count; | 591 | unsigned lpm_disable_count; |
@@ -717,6 +737,7 @@ const struct usb_device_id *usb_match_id(struct usb_interface *interface, | |||
717 | extern int usb_match_one_id(struct usb_interface *interface, | 737 | extern int usb_match_one_id(struct usb_interface *interface, |
718 | const struct usb_device_id *id); | 738 | const struct usb_device_id *id); |
719 | 739 | ||
740 | extern int usb_for_each_dev(void *data, int (*fn)(struct usb_device *, void *)); | ||
720 | extern struct usb_interface *usb_find_interface(struct usb_driver *drv, | 741 | extern struct usb_interface *usb_find_interface(struct usb_driver *drv, |
721 | int minor); | 742 | int minor); |
722 | extern struct usb_interface *usb_ifnum_to_if(const struct usb_device *dev, | 743 | extern struct usb_interface *usb_ifnum_to_if(const struct usb_device *dev, |
diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h index 544825dde823..25629948c842 100644 --- a/include/linux/usb/chipidea.h +++ b/include/linux/usb/chipidea.h | |||
@@ -7,32 +7,33 @@ | |||
7 | 7 | ||
8 | #include <linux/usb/otg.h> | 8 | #include <linux/usb/otg.h> |
9 | 9 | ||
10 | struct ci13xxx; | 10 | struct ci_hdrc; |
11 | struct ci13xxx_platform_data { | 11 | struct ci_hdrc_platform_data { |
12 | const char *name; | 12 | const char *name; |
13 | /* offset of the capability registers */ | 13 | /* offset of the capability registers */ |
14 | uintptr_t capoffset; | 14 | uintptr_t capoffset; |
15 | unsigned power_budget; | 15 | unsigned power_budget; |
16 | struct usb_phy *phy; | 16 | struct usb_phy *phy; |
17 | enum usb_phy_interface phy_mode; | ||
17 | unsigned long flags; | 18 | unsigned long flags; |
18 | #define CI13XXX_REGS_SHARED BIT(0) | 19 | #define CI_HDRC_REGS_SHARED BIT(0) |
19 | #define CI13XXX_REQUIRE_TRANSCEIVER BIT(1) | 20 | #define CI_HDRC_REQUIRE_TRANSCEIVER BIT(1) |
20 | #define CI13XXX_PULLUP_ON_VBUS BIT(2) | 21 | #define CI_HDRC_PULLUP_ON_VBUS BIT(2) |
21 | #define CI13XXX_DISABLE_STREAMING BIT(3) | 22 | #define CI_HDRC_DISABLE_STREAMING BIT(3) |
22 | 23 | enum usb_dr_mode dr_mode; | |
23 | #define CI13XXX_CONTROLLER_RESET_EVENT 0 | 24 | #define CI_HDRC_CONTROLLER_RESET_EVENT 0 |
24 | #define CI13XXX_CONTROLLER_STOPPED_EVENT 1 | 25 | #define CI_HDRC_CONTROLLER_STOPPED_EVENT 1 |
25 | void (*notify_event) (struct ci13xxx *ci, unsigned event); | 26 | void (*notify_event) (struct ci_hdrc *ci, unsigned event); |
26 | }; | 27 | }; |
27 | 28 | ||
28 | /* Default offset of capability registers */ | 29 | /* Default offset of capability registers */ |
29 | #define DEF_CAPOFFSET 0x100 | 30 | #define DEF_CAPOFFSET 0x100 |
30 | 31 | ||
31 | /* Add ci13xxx device */ | 32 | /* Add ci hdrc device */ |
32 | struct platform_device *ci13xxx_add_device(struct device *dev, | 33 | struct platform_device *ci_hdrc_add_device(struct device *dev, |
33 | struct resource *res, int nres, | 34 | struct resource *res, int nres, |
34 | struct ci13xxx_platform_data *platdata); | 35 | struct ci_hdrc_platform_data *platdata); |
35 | /* Remove ci13xxx device */ | 36 | /* Remove ci hdrc device */ |
36 | void ci13xxx_remove_device(struct platform_device *pdev); | 37 | void ci_hdrc_remove_device(struct platform_device *pdev); |
37 | 38 | ||
38 | #endif | 39 | #endif |
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index f5f5c7dfda90..1e88377e22f4 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h | |||
@@ -218,6 +218,7 @@ struct hc_driver { | |||
218 | #define HCD_SHARED 0x0004 /* Two (or more) usb_hcds share HW */ | 218 | #define HCD_SHARED 0x0004 /* Two (or more) usb_hcds share HW */ |
219 | #define HCD_USB11 0x0010 /* USB 1.1 */ | 219 | #define HCD_USB11 0x0010 /* USB 1.1 */ |
220 | #define HCD_USB2 0x0020 /* USB 2.0 */ | 220 | #define HCD_USB2 0x0020 /* USB 2.0 */ |
221 | #define HCD_USB25 0x0030 /* Wireless USB 1.0 (USB 2.5)*/ | ||
221 | #define HCD_USB3 0x0040 /* USB 3.0 */ | 222 | #define HCD_USB3 0x0040 /* USB 3.0 */ |
222 | #define HCD_MASK 0x0070 | 223 | #define HCD_MASK 0x0070 |
223 | 224 | ||
diff --git a/include/linux/usb/of.h b/include/linux/usb/of.h new file mode 100644 index 000000000000..a0ef405368b8 --- /dev/null +++ b/include/linux/usb/of.h | |||
@@ -0,0 +1,32 @@ | |||
1 | /* | ||
2 | * OF helpers for usb devices. | ||
3 | * | ||
4 | * This file is released under the GPLv2 | ||
5 | */ | ||
6 | |||
7 | #ifndef __LINUX_USB_OF_H | ||
8 | #define __LINUX_USB_OF_H | ||
9 | |||
10 | #include <linux/usb/otg.h> | ||
11 | #include <linux/usb/phy.h> | ||
12 | |||
13 | #if IS_ENABLED(CONFIG_OF) | ||
14 | enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np); | ||
15 | #else | ||
16 | static inline enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np) | ||
17 | { | ||
18 | return USB_DR_MODE_UNKNOWN; | ||
19 | } | ||
20 | #endif | ||
21 | |||
22 | #if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_USB_PHY) | ||
23 | enum usb_phy_interface of_usb_get_phy_mode(struct device_node *np); | ||
24 | #else | ||
25 | static inline enum usb_phy_interface of_usb_get_phy_mode(struct device_node *np) | ||
26 | { | ||
27 | return USBPHY_INTERFACE_MODE_UNKNOWN; | ||
28 | } | ||
29 | |||
30 | #endif | ||
31 | |||
32 | #endif /* __LINUX_USB_OF_H */ | ||
diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h index 291e01ba32e5..154332b7c8c0 100644 --- a/include/linux/usb/otg.h +++ b/include/linux/usb/otg.h | |||
@@ -92,4 +92,11 @@ otg_start_srp(struct usb_otg *otg) | |||
92 | /* for OTG controller drivers (and maybe other stuff) */ | 92 | /* for OTG controller drivers (and maybe other stuff) */ |
93 | extern int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num); | 93 | extern int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num); |
94 | 94 | ||
95 | enum usb_dr_mode { | ||
96 | USB_DR_MODE_UNKNOWN, | ||
97 | USB_DR_MODE_HOST, | ||
98 | USB_DR_MODE_PERIPHERAL, | ||
99 | USB_DR_MODE_OTG, | ||
100 | }; | ||
101 | |||
95 | #endif /* __LINUX_USB_OTG_H */ | 102 | #endif /* __LINUX_USB_OTG_H */ |
diff --git a/include/linux/usb/phy.h b/include/linux/usb/phy.h index 6b5978f57633..44036808bf0f 100644 --- a/include/linux/usb/phy.h +++ b/include/linux/usb/phy.h | |||
@@ -12,6 +12,15 @@ | |||
12 | #include <linux/notifier.h> | 12 | #include <linux/notifier.h> |
13 | #include <linux/usb.h> | 13 | #include <linux/usb.h> |
14 | 14 | ||
15 | enum usb_phy_interface { | ||
16 | USBPHY_INTERFACE_MODE_UNKNOWN, | ||
17 | USBPHY_INTERFACE_MODE_UTMI, | ||
18 | USBPHY_INTERFACE_MODE_UTMIW, | ||
19 | USBPHY_INTERFACE_MODE_ULPI, | ||
20 | USBPHY_INTERFACE_MODE_SERIAL, | ||
21 | USBPHY_INTERFACE_MODE_HSIC, | ||
22 | }; | ||
23 | |||
15 | enum usb_phy_events { | 24 | enum usb_phy_events { |
16 | USB_EVENT_NONE, /* no events or cable disconnected */ | 25 | USB_EVENT_NONE, /* no events or cable disconnected */ |
17 | USB_EVENT_VBUS, /* vbus valid event */ | 26 | USB_EVENT_VBUS, /* vbus valid event */ |
diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 302ddf55d2da..d528b8045150 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h | |||
@@ -19,10 +19,6 @@ | |||
19 | #include <linux/sysrq.h> | 19 | #include <linux/sysrq.h> |
20 | #include <linux/kfifo.h> | 20 | #include <linux/kfifo.h> |
21 | 21 | ||
22 | #define SERIAL_TTY_MAJOR 188 /* Nice legal number now */ | ||
23 | #define SERIAL_TTY_MINORS 254 /* loads of devices :) */ | ||
24 | #define SERIAL_TTY_NO_MINOR 255 /* No minor was assigned */ | ||
25 | |||
26 | /* The maximum number of ports one device can grab at once */ | 22 | /* The maximum number of ports one device can grab at once */ |
27 | #define MAX_NUM_PORTS 8 | 23 | #define MAX_NUM_PORTS 8 |
28 | 24 | ||
@@ -37,7 +33,8 @@ | |||
37 | * @serial: pointer back to the struct usb_serial owner of this port. | 33 | * @serial: pointer back to the struct usb_serial owner of this port. |
38 | * @port: pointer to the corresponding tty_port for this port. | 34 | * @port: pointer to the corresponding tty_port for this port. |
39 | * @lock: spinlock to grab when updating portions of this structure. | 35 | * @lock: spinlock to grab when updating portions of this structure. |
40 | * @number: the number of the port (the minor number). | 36 | * @minor: the minor number of the port |
37 | * @port_number: the struct usb_serial port number of this port (starts at 0) | ||
41 | * @interrupt_in_buffer: pointer to the interrupt in buffer for this port. | 38 | * @interrupt_in_buffer: pointer to the interrupt in buffer for this port. |
42 | * @interrupt_in_urb: pointer to the interrupt in struct urb for this port. | 39 | * @interrupt_in_urb: pointer to the interrupt in struct urb for this port. |
43 | * @interrupt_in_endpointAddress: endpoint address for the interrupt in pipe | 40 | * @interrupt_in_endpointAddress: endpoint address for the interrupt in pipe |
@@ -80,7 +77,8 @@ struct usb_serial_port { | |||
80 | struct usb_serial *serial; | 77 | struct usb_serial *serial; |
81 | struct tty_port port; | 78 | struct tty_port port; |
82 | spinlock_t lock; | 79 | spinlock_t lock; |
83 | unsigned char number; | 80 | u32 minor; |
81 | u8 port_number; | ||
84 | 82 | ||
85 | unsigned char *interrupt_in_buffer; | 83 | unsigned char *interrupt_in_buffer; |
86 | struct urb *interrupt_in_urb; | 84 | struct urb *interrupt_in_urb; |
@@ -140,7 +138,6 @@ static inline void usb_set_serial_port_data(struct usb_serial_port *port, | |||
140 | * @dev: pointer to the struct usb_device for this device | 138 | * @dev: pointer to the struct usb_device for this device |
141 | * @type: pointer to the struct usb_serial_driver for this device | 139 | * @type: pointer to the struct usb_serial_driver for this device |
142 | * @interface: pointer to the struct usb_interface for this device | 140 | * @interface: pointer to the struct usb_interface for this device |
143 | * @minor: the starting minor number for this device | ||
144 | * @num_ports: the number of ports this device has | 141 | * @num_ports: the number of ports this device has |
145 | * @num_interrupt_in: number of interrupt in endpoints we have | 142 | * @num_interrupt_in: number of interrupt in endpoints we have |
146 | * @num_interrupt_out: number of interrupt out endpoints we have | 143 | * @num_interrupt_out: number of interrupt out endpoints we have |
@@ -159,7 +156,7 @@ struct usb_serial { | |||
159 | unsigned char disconnected:1; | 156 | unsigned char disconnected:1; |
160 | unsigned char suspending:1; | 157 | unsigned char suspending:1; |
161 | unsigned char attached:1; | 158 | unsigned char attached:1; |
162 | unsigned char minor; | 159 | unsigned char minors_reserved:1; |
163 | unsigned char num_ports; | 160 | unsigned char num_ports; |
164 | unsigned char num_port_pointers; | 161 | unsigned char num_port_pointers; |
165 | char num_interrupt_in; | 162 | char num_interrupt_in; |
@@ -319,7 +316,7 @@ static inline void usb_serial_console_disconnect(struct usb_serial *serial) {} | |||
319 | #endif | 316 | #endif |
320 | 317 | ||
321 | /* Functions needed by other parts of the usbserial core */ | 318 | /* Functions needed by other parts of the usbserial core */ |
322 | extern struct usb_serial *usb_serial_get_by_index(unsigned int minor); | 319 | extern struct usb_serial_port *usb_serial_port_get_by_minor(unsigned int minor); |
323 | extern void usb_serial_put(struct usb_serial *serial); | 320 | extern void usb_serial_put(struct usb_serial *serial); |
324 | extern int usb_serial_generic_open(struct tty_struct *tty, | 321 | extern int usb_serial_generic_open(struct tty_struct *tty, |
325 | struct usb_serial_port *port); | 322 | struct usb_serial_port *port); |
diff --git a/include/linux/usb/tegra_usb_phy.h b/include/linux/usb/tegra_usb_phy.h index 1b7519a8c0bf..d2ca919a5b73 100644 --- a/include/linux/usb/tegra_usb_phy.h +++ b/include/linux/usb/tegra_usb_phy.h | |||
@@ -42,6 +42,7 @@ enum tegra_usb_phy_port_speed { | |||
42 | enum tegra_usb_phy_mode { | 42 | enum tegra_usb_phy_mode { |
43 | TEGRA_USB_PHY_MODE_DEVICE, | 43 | TEGRA_USB_PHY_MODE_DEVICE, |
44 | TEGRA_USB_PHY_MODE_HOST, | 44 | TEGRA_USB_PHY_MODE_HOST, |
45 | TEGRA_USB_PHY_MODE_OTG, | ||
45 | }; | 46 | }; |
46 | 47 | ||
47 | struct tegra_xtal_freq; | 48 | struct tegra_xtal_freq; |
@@ -61,14 +62,10 @@ struct tegra_usb_phy { | |||
61 | struct device *dev; | 62 | struct device *dev; |
62 | bool is_legacy_phy; | 63 | bool is_legacy_phy; |
63 | bool is_ulpi_phy; | 64 | bool is_ulpi_phy; |
64 | void (*set_pts)(struct usb_phy *x, u8 pts_val); | 65 | int reset_gpio; |
65 | void (*set_phcd)(struct usb_phy *x, bool enable); | ||
66 | }; | 66 | }; |
67 | 67 | ||
68 | struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance, | 68 | struct usb_phy *tegra_usb_get_phy(struct device_node *dn); |
69 | void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode, | ||
70 | void (*set_pts)(struct usb_phy *x, u8 pts_val), | ||
71 | void (*set_phcd)(struct usb_phy *x, bool enable)); | ||
72 | 69 | ||
73 | void tegra_usb_phy_preresume(struct usb_phy *phy); | 70 | void tegra_usb_phy_preresume(struct usb_phy *phy); |
74 | 71 | ||
diff --git a/include/linux/usb/wusb-wa.h b/include/linux/usb/wusb-wa.h index f9dec37f617b..6be985b2a434 100644 --- a/include/linux/usb/wusb-wa.h +++ b/include/linux/usb/wusb-wa.h | |||
@@ -92,11 +92,20 @@ struct usb_rpipe_descriptor { | |||
92 | __le16 wRPipeIndex; | 92 | __le16 wRPipeIndex; |
93 | __le16 wRequests; | 93 | __le16 wRequests; |
94 | __le16 wBlocks; /* rw if 0 */ | 94 | __le16 wBlocks; /* rw if 0 */ |
95 | __le16 wMaxPacketSize; /* rw? */ | 95 | __le16 wMaxPacketSize; /* rw */ |
96 | u8 bHSHubAddress; /* reserved: 0 */ | 96 | union { |
97 | u8 bHSHubPort; /* ??? FIXME ??? */ | 97 | u8 dwa_bHSHubAddress; /* rw: DWA. */ |
98 | u8 hwa_bMaxBurst; /* rw: HWA. */ | ||
99 | }; | ||
100 | union { | ||
101 | u8 dwa_bHSHubPort; /* rw: DWA. */ | ||
102 | u8 hwa_bDeviceInfoIndex; /* rw: HWA. */ | ||
103 | }; | ||
98 | u8 bSpeed; /* rw: xfer rate 'enum uwb_phy_rate' */ | 104 | u8 bSpeed; /* rw: xfer rate 'enum uwb_phy_rate' */ |
99 | u8 bDeviceAddress; /* rw: Target device address */ | 105 | union { |
106 | u8 dwa_bDeviceAddress; /* rw: DWA Target device address. */ | ||
107 | u8 hwa_reserved; /* rw: HWA. */ | ||
108 | }; | ||
100 | u8 bEndpointAddress; /* rw: Target EP address */ | 109 | u8 bEndpointAddress; /* rw: Target EP address */ |
101 | u8 bDataSequence; /* ro: Current Data sequence */ | 110 | u8 bDataSequence; /* ro: Current Data sequence */ |
102 | __le32 dwCurrentWindow; /* ro */ | 111 | __le32 dwCurrentWindow; /* ro */ |