diff options
81 files changed, 5802 insertions, 1228 deletions
diff --git a/Documentation/ABI/testing/configfs-usb-gadget-eem b/Documentation/ABI/testing/configfs-usb-gadget-eem new file mode 100644 index 000000000000..10e87d67fa2e --- /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: May 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-phonet b/Documentation/ABI/testing/configfs-usb-gadget-phonet new file mode 100644 index 000000000000..19b67d3eab94 --- /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: May 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..ff127ddb807c --- /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: May 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-subset b/Documentation/ABI/testing/configfs-usb-gadget-subset new file mode 100644 index 000000000000..f47170a2f7dc --- /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: May 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/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/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/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..2b2a11c8977a 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,57 @@ 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_ECM_SUBSET | ||
564 | boolean "Ethernet Control Model (CDC ECM) subset" | ||
565 | depends on USB_CONFIGFS | ||
566 | depends on NET | ||
567 | select USB_U_ETHER | ||
568 | select USB_F_SUBSET | ||
569 | help | ||
570 | On hardware that can't implement the full protocol, | ||
571 | a simple CDC subset is used, placing fewer demands on USB. | ||
572 | |||
573 | config USB_CONFIGFS_RNDIS | ||
574 | bool "RNDIS" | ||
575 | depends on USB_CONFIGFS | ||
576 | depends on NET | ||
577 | select USB_U_ETHER | ||
578 | select USB_F_RNDIS | ||
579 | help | ||
580 | Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol, | ||
581 | and Microsoft provides redistributable binary RNDIS drivers for | ||
582 | older versions of Windows. | ||
583 | |||
584 | To make MS-Windows work with this, use Documentation/usb/linux.inf | ||
585 | as the "driver info file". For versions of MS-Windows older than | ||
586 | XP, you'll need to download drivers from Microsoft's website; a URL | ||
587 | is given in comments found in that info file. | ||
588 | |||
589 | config USB_CONFIGFS_EEM | ||
590 | bool "Ethernet Emulation Model (EEM)" | ||
591 | depends on USB_CONFIGFS | ||
592 | depends on NET | ||
593 | select USB_U_ETHER | ||
594 | select USB_F_EEM | ||
595 | help | ||
596 | CDC EEM is a newer USB standard that is somewhat simpler than CDC ECM | ||
597 | and therefore can be supported by more hardware. Technically ECM and | ||
598 | EEM are designed for different applications. The ECM model extends | ||
599 | the network interface to the target (e.g. a USB cable modem), and the | ||
600 | EEM model is for mobile devices to communicate with hosts using | ||
601 | ethernet over USB. For Linux gadgets, however, the interface with | ||
602 | the host is the same (a usbX device), so the differences are minimal. | ||
603 | |||
604 | config USB_CONFIGFS_PHONET | ||
605 | boolean "Phonet protocol" | ||
606 | depends on USB_CONFIGFS | ||
607 | depends on NET | ||
608 | depends on PHONET | ||
609 | select USB_U_ETHER | ||
610 | select USB_F_PHONET | ||
611 | help | ||
612 | The Phonet protocol implementation for USB device. | ||
613 | |||
537 | config USB_ZERO | 614 | config USB_ZERO |
538 | tristate "Gadget Zero (DEVELOPMENT)" | 615 | tristate "Gadget Zero (DEVELOPMENT)" |
539 | select USB_LIBCOMPOSITE | 616 | select USB_LIBCOMPOSITE |
@@ -603,6 +680,10 @@ config USB_ETH | |||
603 | tristate "Ethernet Gadget (with CDC Ethernet support)" | 680 | tristate "Ethernet Gadget (with CDC Ethernet support)" |
604 | depends on NET | 681 | depends on NET |
605 | select USB_LIBCOMPOSITE | 682 | select USB_LIBCOMPOSITE |
683 | select USB_U_ETHER | ||
684 | select USB_U_RNDIS | ||
685 | select USB_F_ECM | ||
686 | select USB_F_SUBSET | ||
606 | select CRC32 | 687 | select CRC32 |
607 | help | 688 | help |
608 | This driver implements Ethernet style communication, in one of | 689 | This driver implements Ethernet style communication, in one of |
@@ -639,6 +720,7 @@ config USB_ETH_RNDIS | |||
639 | bool "RNDIS support" | 720 | bool "RNDIS support" |
640 | depends on USB_ETH | 721 | depends on USB_ETH |
641 | select USB_LIBCOMPOSITE | 722 | select USB_LIBCOMPOSITE |
723 | select USB_F_RNDIS | ||
642 | default y | 724 | default y |
643 | help | 725 | help |
644 | Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol, | 726 | Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol, |
@@ -658,6 +740,7 @@ config USB_ETH_EEM | |||
658 | bool "Ethernet Emulation Model (EEM) support" | 740 | bool "Ethernet Emulation Model (EEM) support" |
659 | depends on USB_ETH | 741 | depends on USB_ETH |
660 | select USB_LIBCOMPOSITE | 742 | select USB_LIBCOMPOSITE |
743 | select USB_F_EEM | ||
661 | default n | 744 | default n |
662 | help | 745 | help |
663 | CDC EEM is a newer USB standard that is somewhat simpler than CDC ECM | 746 | CDC EEM is a newer USB standard that is somewhat simpler than CDC ECM |
@@ -675,6 +758,8 @@ config USB_G_NCM | |||
675 | tristate "Network Control Model (NCM) support" | 758 | tristate "Network Control Model (NCM) support" |
676 | depends on NET | 759 | depends on NET |
677 | select USB_LIBCOMPOSITE | 760 | select USB_LIBCOMPOSITE |
761 | select USB_U_ETHER | ||
762 | select USB_F_NCM | ||
678 | select CRC32 | 763 | select CRC32 |
679 | help | 764 | help |
680 | This driver implements USB CDC NCM subclass standard. NCM is | 765 | This driver implements USB CDC NCM subclass standard. NCM is |
@@ -718,6 +803,7 @@ config USB_FUNCTIONFS | |||
718 | config USB_FUNCTIONFS_ETH | 803 | config USB_FUNCTIONFS_ETH |
719 | bool "Include configuration with CDC ECM (Ethernet)" | 804 | bool "Include configuration with CDC ECM (Ethernet)" |
720 | depends on USB_FUNCTIONFS && NET | 805 | depends on USB_FUNCTIONFS && NET |
806 | select USB_U_ETHER | ||
721 | help | 807 | help |
722 | Include a configuration with CDC ECM function (Ethernet) and the | 808 | Include a configuration with CDC ECM function (Ethernet) and the |
723 | Function Filesystem. | 809 | Function Filesystem. |
@@ -725,6 +811,8 @@ config USB_FUNCTIONFS_ETH | |||
725 | config USB_FUNCTIONFS_RNDIS | 811 | config USB_FUNCTIONFS_RNDIS |
726 | bool "Include configuration with RNDIS (Ethernet)" | 812 | bool "Include configuration with RNDIS (Ethernet)" |
727 | depends on USB_FUNCTIONFS && NET | 813 | depends on USB_FUNCTIONFS && NET |
814 | select USB_U_ETHER | ||
815 | select USB_U_RNDIS | ||
728 | help | 816 | help |
729 | Include a configuration with RNDIS function (Ethernet) and the Filesystem. | 817 | Include a configuration with RNDIS function (Ethernet) and the Filesystem. |
730 | 818 | ||
@@ -825,7 +913,9 @@ config USB_CDC_COMPOSITE | |||
825 | depends on NET | 913 | depends on NET |
826 | select USB_LIBCOMPOSITE | 914 | select USB_LIBCOMPOSITE |
827 | select USB_U_SERIAL | 915 | select USB_U_SERIAL |
916 | select USB_U_ETHER | ||
828 | select USB_F_ACM | 917 | select USB_F_ACM |
918 | select USB_F_ECM | ||
829 | help | 919 | help |
830 | This driver provides two functions in one configuration: | 920 | This driver provides two functions in one configuration: |
831 | a CDC Ethernet (ECM) link, and a CDC ACM (serial port) link. | 921 | a CDC Ethernet (ECM) link, and a CDC ACM (serial port) link. |
@@ -842,7 +932,11 @@ config USB_G_NOKIA | |||
842 | depends on PHONET | 932 | depends on PHONET |
843 | select USB_LIBCOMPOSITE | 933 | select USB_LIBCOMPOSITE |
844 | select USB_U_SERIAL | 934 | select USB_U_SERIAL |
935 | select USB_U_ETHER | ||
845 | select USB_F_ACM | 936 | select USB_F_ACM |
937 | select USB_F_OBEX | ||
938 | select USB_F_PHONET | ||
939 | select USB_F_ECM | ||
846 | help | 940 | help |
847 | The Nokia composite gadget provides support for acm, obex | 941 | The Nokia composite gadget provides support for acm, obex |
848 | and phonet in only one composite gadget driver. | 942 | and phonet in only one composite gadget driver. |
@@ -869,6 +963,8 @@ config USB_G_MULTI | |||
869 | select USB_G_MULTI_CDC if !USB_G_MULTI_RNDIS | 963 | select USB_G_MULTI_CDC if !USB_G_MULTI_RNDIS |
870 | select USB_LIBCOMPOSITE | 964 | select USB_LIBCOMPOSITE |
871 | select USB_U_SERIAL | 965 | select USB_U_SERIAL |
966 | select USB_U_ETHER | ||
967 | select USB_U_RNDIS | ||
872 | select USB_F_ACM | 968 | select USB_F_ACM |
873 | help | 969 | help |
874 | The Multifunction Composite Gadget provides Ethernet (RNDIS | 970 | 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..fcafe1af4585 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,142 @@ 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 | return ERR_PTR(-EINVAL); | ||
1016 | } | ||
1017 | ecm_string_defs[1].s = ecm->ethaddr; | ||
1018 | |||
1019 | ecm->port.ioport = netdev_priv(opts->net); | ||
1020 | mutex_unlock(&opts->lock); | ||
1021 | ecm->port.cdc_filter = DEFAULT_FILTER; | ||
1022 | |||
1023 | ecm->port.func.name = "cdc_ethernet"; | ||
1024 | /* descriptors are per-instance copies */ | ||
1025 | ecm->port.func.bind = ecm_bind; | ||
1026 | ecm->port.func.unbind = ecm_unbind; | ||
1027 | ecm->port.func.set_alt = ecm_set_alt; | ||
1028 | ecm->port.func.get_alt = ecm_get_alt; | ||
1029 | ecm->port.func.setup = ecm_setup; | ||
1030 | ecm->port.func.disable = ecm_disable; | ||
1031 | ecm->port.func.free_func = ecm_free; | ||
1032 | |||
1033 | return &ecm->port.func; | ||
1034 | } | ||
1035 | |||
1036 | DECLARE_USB_FUNCTION_INIT(ecm, ecm_alloc_inst, ecm_alloc); | ||
1037 | MODULE_LICENSE("GPL"); | ||
1038 | MODULE_AUTHOR("David Brownell"); | ||
1039 | |||
1040 | #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..47a5724211cd 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,127 @@ 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 | return ERR_PTR(-EINVAL); | ||
1407 | } | ||
1321 | ncm_string_defs[STRING_MAC_IDX].s = ncm->ethaddr; | 1408 | ncm_string_defs[STRING_MAC_IDX].s = ncm->ethaddr; |
1322 | 1409 | ||
1323 | spin_lock_init(&ncm->lock); | 1410 | spin_lock_init(&ncm->lock); |
1324 | ncm_reset_values(ncm); | 1411 | ncm_reset_values(ncm); |
1325 | ncm->port.ioport = dev; | 1412 | ncm->port.ioport = netdev_priv(opts->net); |
1413 | mutex_unlock(&opts->lock); | ||
1326 | ncm->port.is_fixed = true; | 1414 | ncm->port.is_fixed = true; |
1327 | 1415 | ||
1328 | ncm->port.func.name = "cdc_network"; | 1416 | ncm->port.func.name = "cdc_network"; |
1329 | ncm->port.func.strings = ncm_strings; | ||
1330 | /* descriptors are per-instance copies */ | 1417 | /* descriptors are per-instance copies */ |
1331 | ncm->port.func.bind = ncm_bind; | 1418 | ncm->port.func.bind = ncm_bind; |
1332 | ncm->port.func.unbind = ncm_unbind; | 1419 | ncm->port.func.unbind = ncm_unbind; |
@@ -1334,12 +1421,14 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], | |||
1334 | ncm->port.func.get_alt = ncm_get_alt; | 1421 | ncm->port.func.get_alt = ncm_get_alt; |
1335 | ncm->port.func.setup = ncm_setup; | 1422 | ncm->port.func.setup = ncm_setup; |
1336 | ncm->port.func.disable = ncm_disable; | 1423 | ncm->port.func.disable = ncm_disable; |
1424 | ncm->port.func.free_func = ncm_free; | ||
1337 | 1425 | ||
1338 | ncm->port.wrap = ncm_wrap_ntb; | 1426 | ncm->port.wrap = ncm_wrap_ntb; |
1339 | ncm->port.unwrap = ncm_unwrap_ntb; | 1427 | ncm->port.unwrap = ncm_unwrap_ntb; |
1340 | 1428 | ||
1341 | status = usb_add_function(c, &ncm->port.func); | 1429 | return &ncm->port.func; |
1342 | if (status) | ||
1343 | kfree(ncm); | ||
1344 | return status; | ||
1345 | } | 1430 | } |
1431 | |||
1432 | DECLARE_USB_FUNCTION_INIT(ncm, ncm_alloc_inst, ncm_alloc); | ||
1433 | MODULE_LICENSE("GPL"); | ||
1434 | 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..fbc7a24942e4 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,129 @@ 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 | return ERR_PTR(-EINVAL); | ||
552 | } | ||
553 | geth_string_defs[1].s = geth->ethaddr; | ||
554 | |||
555 | geth->port.ioport = netdev_priv(opts->net); | ||
556 | mutex_unlock(&opts->lock); | ||
557 | geth->port.cdc_filter = DEFAULT_FILTER; | ||
558 | |||
559 | geth->port.func.name = "cdc_subset"; | ||
560 | geth->port.func.bind = geth_bind; | ||
561 | geth->port.func.unbind = geth_unbind; | ||
562 | geth->port.func.set_alt = geth_set_alt; | ||
563 | geth->port.func.disable = geth_disable; | ||
564 | geth->port.func.free_func = geth_free; | ||
565 | |||
566 | return &geth->port.func; | ||
567 | } | ||
568 | |||
569 | DECLARE_USB_FUNCTION_INIT(geth, geth_alloc_inst, geth_alloc); | ||
570 | MODULE_LICENSE("GPL"); | ||
571 | MODULE_AUTHOR("David Brownell"); | ||
572 | |||
573 | #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 751b17af68f0..07fdb3eaf48a 100644 --- a/drivers/usb/gadget/mv_u3d_core.c +++ b/drivers/usb/gadget/mv_u3d_core.c | |||
@@ -2050,7 +2050,7 @@ static SIMPLE_DEV_PM_OPS(mv_u3d_pm_ops, mv_u3d_suspend, mv_u3d_resume); | |||
2050 | 2050 | ||
2051 | static void mv_u3d_shutdown(struct platform_device *dev) | 2051 | static void mv_u3d_shutdown(struct platform_device *dev) |
2052 | { | 2052 | { |
2053 | struct mv_u3d *u3d = dev_get_drvdata(&dev->dev); | 2053 | struct mv_u3d *u3d = platform_get_drvdata(dev); |
2054 | u32 tmp; | 2054 | u32 tmp; |
2055 | 2055 | ||
2056 | 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/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/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 59d111bf44a9..8390c870299a 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c | |||
@@ -611,7 +611,7 @@ static const struct dev_pm_ops tegra_ehci_pm_ops = { | |||
611 | /* Bits of PORTSC1, which will get cleared by writing 1 into them */ | 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) | 612 | #define TEGRA_PORTSC1_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC) |
613 | 613 | ||
614 | static void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val) | 614 | void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val) |
615 | { | 615 | { |
616 | unsigned long val; | 616 | unsigned long val; |
617 | struct usb_hcd *hcd = bus_to_hcd(x->otg->host); | 617 | struct usb_hcd *hcd = bus_to_hcd(x->otg->host); |
@@ -622,8 +622,9 @@ static void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val) | |||
622 | val |= TEGRA_USB_PORTSC1_PTS(pts_val & 3); | 622 | val |= TEGRA_USB_PORTSC1_PTS(pts_val & 3); |
623 | writel(val, base + TEGRA_USB_PORTSC1); | 623 | writel(val, base + TEGRA_USB_PORTSC1); |
624 | } | 624 | } |
625 | EXPORT_SYMBOL_GPL(tegra_ehci_set_pts); | ||
625 | 626 | ||
626 | static void tegra_ehci_set_phcd(struct usb_phy *x, bool enable) | 627 | void tegra_ehci_set_phcd(struct usb_phy *x, bool enable) |
627 | { | 628 | { |
628 | unsigned long val; | 629 | unsigned long val; |
629 | struct usb_hcd *hcd = bus_to_hcd(x->otg->host); | 630 | struct usb_hcd *hcd = bus_to_hcd(x->otg->host); |
@@ -636,6 +637,7 @@ static void tegra_ehci_set_phcd(struct usb_phy *x, bool enable) | |||
636 | val &= ~TEGRA_USB_PORTSC1_PHCD; | 637 | val &= ~TEGRA_USB_PORTSC1_PHCD; |
637 | writel(val, base + TEGRA_USB_PORTSC1); | 638 | writel(val, base + TEGRA_USB_PORTSC1); |
638 | } | 639 | } |
640 | EXPORT_SYMBOL_GPL(tegra_ehci_set_phcd); | ||
639 | 641 | ||
640 | static int tegra_ehci_probe(struct platform_device *pdev) | 642 | static int tegra_ehci_probe(struct platform_device *pdev) |
641 | { | 643 | { |
@@ -645,7 +647,7 @@ static int tegra_ehci_probe(struct platform_device *pdev) | |||
645 | struct tegra_ehci_platform_data *pdata; | 647 | struct tegra_ehci_platform_data *pdata; |
646 | int err = 0; | 648 | int err = 0; |
647 | int irq; | 649 | int irq; |
648 | int instance = pdev->id; | 650 | struct device_node *np_phy; |
649 | struct usb_phy *u_phy; | 651 | struct usb_phy *u_phy; |
650 | 652 | ||
651 | pdata = pdev->dev.platform_data; | 653 | pdata = pdev->dev.platform_data; |
@@ -670,38 +672,49 @@ static int tegra_ehci_probe(struct platform_device *pdev) | |||
670 | if (!tegra) | 672 | if (!tegra) |
671 | return -ENOMEM; | 673 | return -ENOMEM; |
672 | 674 | ||
673 | hcd = usb_create_hcd(&tegra_ehci_hc_driver, &pdev->dev, | ||
674 | dev_name(&pdev->dev)); | ||
675 | if (!hcd) { | ||
676 | dev_err(&pdev->dev, "Unable to create HCD\n"); | ||
677 | return -ENOMEM; | ||
678 | } | ||
679 | |||
680 | platform_set_drvdata(pdev, tegra); | ||
681 | |||
682 | tegra->clk = devm_clk_get(&pdev->dev, NULL); | 675 | tegra->clk = devm_clk_get(&pdev->dev, NULL); |
683 | if (IS_ERR(tegra->clk)) { | 676 | if (IS_ERR(tegra->clk)) { |
684 | dev_err(&pdev->dev, "Can't get ehci clock\n"); | 677 | dev_err(&pdev->dev, "Can't get ehci clock\n"); |
685 | err = PTR_ERR(tegra->clk); | 678 | return PTR_ERR(tegra->clk); |
686 | goto fail_clk; | ||
687 | } | 679 | } |
688 | 680 | ||
689 | err = clk_prepare_enable(tegra->clk); | 681 | err = clk_prepare_enable(tegra->clk); |
690 | if (err) | 682 | if (err) |
691 | goto fail_clk; | 683 | return err; |
692 | 684 | ||
693 | tegra_periph_reset_assert(tegra->clk); | 685 | tegra_periph_reset_assert(tegra->clk); |
694 | udelay(1); | 686 | udelay(1); |
695 | tegra_periph_reset_deassert(tegra->clk); | 687 | tegra_periph_reset_deassert(tegra->clk); |
696 | 688 | ||
689 | np_phy = of_parse_phandle(pdev->dev.of_node, "nvidia,phy", 0); | ||
690 | if (!np_phy) { | ||
691 | err = -ENODEV; | ||
692 | goto cleanup_clk; | ||
693 | } | ||
694 | |||
695 | u_phy = tegra_usb_get_phy(np_phy); | ||
696 | if (IS_ERR(u_phy)) { | ||
697 | err = PTR_ERR(u_phy); | ||
698 | goto cleanup_clk; | ||
699 | } | ||
700 | |||
697 | tegra->needs_double_reset = of_property_read_bool(pdev->dev.of_node, | 701 | tegra->needs_double_reset = of_property_read_bool(pdev->dev.of_node, |
698 | "nvidia,needs-double-reset"); | 702 | "nvidia,needs-double-reset"); |
699 | 703 | ||
704 | hcd = usb_create_hcd(&tegra_ehci_hc_driver, &pdev->dev, | ||
705 | dev_name(&pdev->dev)); | ||
706 | if (!hcd) { | ||
707 | dev_err(&pdev->dev, "Unable to create HCD\n"); | ||
708 | err = -ENOMEM; | ||
709 | goto cleanup_clk; | ||
710 | } | ||
711 | hcd->phy = u_phy; | ||
712 | |||
700 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 713 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
701 | if (!res) { | 714 | if (!res) { |
702 | dev_err(&pdev->dev, "Failed to get I/O memory\n"); | 715 | dev_err(&pdev->dev, "Failed to get I/O memory\n"); |
703 | err = -ENXIO; | 716 | err = -ENXIO; |
704 | goto fail_io; | 717 | goto cleanup_hcd_create; |
705 | } | 718 | } |
706 | hcd->rsrc_start = res->start; | 719 | hcd->rsrc_start = res->start; |
707 | hcd->rsrc_len = resource_size(res); | 720 | hcd->rsrc_len = resource_size(res); |
@@ -709,58 +722,28 @@ static int tegra_ehci_probe(struct platform_device *pdev) | |||
709 | if (!hcd->regs) { | 722 | if (!hcd->regs) { |
710 | dev_err(&pdev->dev, "Failed to remap I/O memory\n"); | 723 | dev_err(&pdev->dev, "Failed to remap I/O memory\n"); |
711 | err = -ENOMEM; | 724 | err = -ENOMEM; |
712 | goto fail_io; | 725 | goto cleanup_hcd_create; |
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 | } | 726 | } |
736 | 727 | ||
737 | tegra->phy = tegra_usb_phy_open(&pdev->dev, instance, hcd->regs, | 728 | err = usb_phy_init(hcd->phy); |
738 | pdata->phy_config, | 729 | if (err) { |
739 | TEGRA_USB_PHY_MODE_HOST, | 730 | dev_err(&pdev->dev, "Failed to initialize phy\n"); |
740 | tegra_ehci_set_pts, | 731 | goto cleanup_hcd_create; |
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 | } | 732 | } |
747 | 733 | ||
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), | 734 | u_phy->otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg), |
752 | GFP_KERNEL); | 735 | GFP_KERNEL); |
753 | if (!u_phy->otg) { | 736 | if (!u_phy->otg) { |
754 | dev_err(&pdev->dev, "Failed to alloc memory for otg\n"); | 737 | dev_err(&pdev->dev, "Failed to alloc memory for otg\n"); |
755 | err = -ENOMEM; | 738 | err = -ENOMEM; |
756 | goto fail_io; | 739 | goto cleanup_phy; |
757 | } | 740 | } |
758 | u_phy->otg->host = hcd_to_bus(hcd); | 741 | u_phy->otg->host = hcd_to_bus(hcd); |
759 | 742 | ||
760 | err = usb_phy_set_suspend(hcd->phy, 0); | 743 | err = usb_phy_set_suspend(hcd->phy, 0); |
761 | if (err) { | 744 | if (err) { |
762 | dev_err(&pdev->dev, "Failed to power on the phy\n"); | 745 | dev_err(&pdev->dev, "Failed to power on the phy\n"); |
763 | goto fail_phy; | 746 | goto cleanup_phy; |
764 | } | 747 | } |
765 | 748 | ||
766 | tegra->host_resumed = 1; | 749 | tegra->host_resumed = 1; |
@@ -770,7 +753,7 @@ static int tegra_ehci_probe(struct platform_device *pdev) | |||
770 | if (!irq) { | 753 | if (!irq) { |
771 | dev_err(&pdev->dev, "Failed to get IRQ\n"); | 754 | dev_err(&pdev->dev, "Failed to get IRQ\n"); |
772 | err = -ENODEV; | 755 | err = -ENODEV; |
773 | goto fail_phy; | 756 | goto cleanup_phy; |
774 | } | 757 | } |
775 | 758 | ||
776 | if (pdata->operating_mode == TEGRA_USB_OTG) { | 759 | if (pdata->operating_mode == TEGRA_USB_OTG) { |
@@ -782,10 +765,12 @@ static int tegra_ehci_probe(struct platform_device *pdev) | |||
782 | tegra->transceiver = ERR_PTR(-ENODEV); | 765 | tegra->transceiver = ERR_PTR(-ENODEV); |
783 | } | 766 | } |
784 | 767 | ||
768 | platform_set_drvdata(pdev, tegra); | ||
769 | |||
785 | err = usb_add_hcd(hcd, irq, IRQF_SHARED); | 770 | err = usb_add_hcd(hcd, irq, IRQF_SHARED); |
786 | if (err) { | 771 | if (err) { |
787 | dev_err(&pdev->dev, "Failed to add USB HCD\n"); | 772 | dev_err(&pdev->dev, "Failed to add USB HCD\n"); |
788 | goto fail; | 773 | goto cleanup_phy; |
789 | } | 774 | } |
790 | 775 | ||
791 | pm_runtime_set_active(&pdev->dev); | 776 | pm_runtime_set_active(&pdev->dev); |
@@ -798,15 +783,15 @@ static int tegra_ehci_probe(struct platform_device *pdev) | |||
798 | pm_runtime_put_sync(&pdev->dev); | 783 | pm_runtime_put_sync(&pdev->dev); |
799 | return err; | 784 | return err; |
800 | 785 | ||
801 | fail: | 786 | cleanup_phy: |
802 | if (!IS_ERR(tegra->transceiver)) | 787 | if (!IS_ERR(tegra->transceiver)) |
803 | otg_set_host(tegra->transceiver->otg, NULL); | 788 | otg_set_host(tegra->transceiver->otg, NULL); |
804 | fail_phy: | 789 | |
805 | usb_phy_shutdown(hcd->phy); | 790 | usb_phy_shutdown(hcd->phy); |
806 | fail_io: | 791 | cleanup_hcd_create: |
807 | clk_disable_unprepare(tegra->clk); | ||
808 | fail_clk: | ||
809 | usb_put_hcd(hcd); | 792 | usb_put_hcd(hcd); |
793 | cleanup_clk: | ||
794 | clk_disable_unprepare(tegra->clk); | ||
810 | return err; | 795 | return err; |
811 | } | 796 | } |
812 | 797 | ||
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 4211e5540945..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, |
@@ -310,9 +314,9 @@ __acquires(musb->lock) | |||
310 | urb->actual_length, urb->transfer_buffer_length | 314 | urb->actual_length, urb->transfer_buffer_length |
311 | ); | 315 | ); |
312 | 316 | ||
313 | usb_hcd_unlink_urb_from_ep(musb_to_hcd(musb), urb); | 317 | usb_hcd_unlink_urb_from_ep(musb->hcd, urb); |
314 | spin_unlock(&musb->lock); | 318 | spin_unlock(&musb->lock); |
315 | usb_hcd_giveback_urb(musb_to_hcd(musb), urb, status); | 319 | usb_hcd_giveback_urb(musb->hcd, urb, status); |
316 | spin_lock(&musb->lock); | 320 | spin_lock(&musb->lock); |
317 | } | 321 | } |
318 | 322 | ||
@@ -624,7 +628,7 @@ static bool musb_tx_dma_program(struct dma_controller *dma, | |||
624 | u16 csr; | 628 | u16 csr; |
625 | u8 mode; | 629 | u8 mode; |
626 | 630 | ||
627 | #ifdef CONFIG_USB_INVENTRA_DMA | 631 | #if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_UX500_DMA) |
628 | if (length > channel->max_len) | 632 | if (length > channel->max_len) |
629 | length = channel->max_len; | 633 | length = channel->max_len; |
630 | 634 | ||
@@ -1454,7 +1458,7 @@ done: | |||
1454 | if (length > qh->maxpacket) | 1458 | if (length > qh->maxpacket) |
1455 | length = qh->maxpacket; | 1459 | length = qh->maxpacket; |
1456 | /* Unmap the buffer so that CPU can use it */ | 1460 | /* Unmap the buffer so that CPU can use it */ |
1457 | usb_hcd_unmap_urb_for_dma(musb_to_hcd(musb), urb); | 1461 | usb_hcd_unmap_urb_for_dma(musb->hcd, urb); |
1458 | 1462 | ||
1459 | /* | 1463 | /* |
1460 | * We need to map sg if the transfer_buffer is | 1464 | * We need to map sg if the transfer_buffer is |
@@ -1656,7 +1660,7 @@ void musb_host_rx(struct musb *musb, u8 epnum) | |||
1656 | 1660 | ||
1657 | /* 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 */ |
1658 | 1662 | ||
1659 | #ifndef CONFIG_USB_INVENTRA_DMA | 1663 | #if !defined(CONFIG_USB_INVENTRA_DMA) && !defined(CONFIG_USB_UX500_DMA) |
1660 | if (rx_csr & MUSB_RXCSR_H_REQPKT) { | 1664 | if (rx_csr & MUSB_RXCSR_H_REQPKT) { |
1661 | /* REVISIT this happened for a while on some short reads... | 1665 | /* REVISIT this happened for a while on some short reads... |
1662 | * the cleanup still needs investigation... looks bad... | 1666 | * the cleanup still needs investigation... looks bad... |
@@ -1688,7 +1692,7 @@ void musb_host_rx(struct musb *musb, u8 epnum) | |||
1688 | | MUSB_RXCSR_RXPKTRDY); | 1692 | | MUSB_RXCSR_RXPKTRDY); |
1689 | musb_writew(hw_ep->regs, MUSB_RXCSR, val); | 1693 | musb_writew(hw_ep->regs, MUSB_RXCSR, val); |
1690 | 1694 | ||
1691 | #ifdef CONFIG_USB_INVENTRA_DMA | 1695 | #if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_UX500_DMA) |
1692 | if (usb_pipeisoc(pipe)) { | 1696 | if (usb_pipeisoc(pipe)) { |
1693 | struct usb_iso_packet_descriptor *d; | 1697 | struct usb_iso_packet_descriptor *d; |
1694 | 1698 | ||
@@ -1744,7 +1748,7 @@ void musb_host_rx(struct musb *musb, u8 epnum) | |||
1744 | } | 1748 | } |
1745 | 1749 | ||
1746 | /* we are expecting IN packets */ | 1750 | /* we are expecting IN packets */ |
1747 | #ifdef CONFIG_USB_INVENTRA_DMA | 1751 | #if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_UX500_DMA) |
1748 | if (dma) { | 1752 | if (dma) { |
1749 | struct dma_controller *c; | 1753 | struct dma_controller *c; |
1750 | u16 rx_count; | 1754 | u16 rx_count; |
@@ -1753,10 +1757,10 @@ void musb_host_rx(struct musb *musb, u8 epnum) | |||
1753 | 1757 | ||
1754 | rx_count = musb_readw(epio, MUSB_RXCOUNT); | 1758 | rx_count = musb_readw(epio, MUSB_RXCOUNT); |
1755 | 1759 | ||
1756 | 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", |
1757 | epnum, rx_count, | 1761 | epnum, rx_count, |
1758 | urb->transfer_dma | 1762 | (unsigned long long) urb->transfer_dma |
1759 | + urb->actual_length, | 1763 | + urb->actual_length, |
1760 | qh->offset, | 1764 | qh->offset, |
1761 | urb->transfer_buffer_length); | 1765 | urb->transfer_buffer_length); |
1762 | 1766 | ||
@@ -1868,7 +1872,7 @@ void musb_host_rx(struct musb *musb, u8 epnum) | |||
1868 | unsigned int received_len; | 1872 | unsigned int received_len; |
1869 | 1873 | ||
1870 | /* Unmap the buffer so that CPU can use it */ | 1874 | /* Unmap the buffer so that CPU can use it */ |
1871 | usb_hcd_unmap_urb_for_dma(musb_to_hcd(musb), urb); | 1875 | usb_hcd_unmap_urb_for_dma(musb->hcd, urb); |
1872 | 1876 | ||
1873 | /* | 1877 | /* |
1874 | * We need to map sg if the transfer_buffer is | 1878 | * We need to map sg if the transfer_buffer is |
@@ -2462,7 +2466,6 @@ static int musb_bus_resume(struct usb_hcd *hcd) | |||
2462 | return 0; | 2466 | return 0; |
2463 | } | 2467 | } |
2464 | 2468 | ||
2465 | |||
2466 | #ifndef CONFIG_MUSB_PIO_ONLY | 2469 | #ifndef CONFIG_MUSB_PIO_ONLY |
2467 | 2470 | ||
2468 | #define MUSB_USB_DMA_ALIGN 4 | 2471 | #define MUSB_USB_DMA_ALIGN 4 |
@@ -2574,10 +2577,10 @@ static void musb_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) | |||
2574 | } | 2577 | } |
2575 | #endif /* !CONFIG_MUSB_PIO_ONLY */ | 2578 | #endif /* !CONFIG_MUSB_PIO_ONLY */ |
2576 | 2579 | ||
2577 | const struct hc_driver musb_hc_driver = { | 2580 | static const struct hc_driver musb_hc_driver = { |
2578 | .description = "musb-hcd", | 2581 | .description = "musb-hcd", |
2579 | .product_desc = "MUSB HDRC host driver", | 2582 | .product_desc = "MUSB HDRC host driver", |
2580 | .hcd_priv_size = sizeof(struct musb), | 2583 | .hcd_priv_size = sizeof(struct musb *), |
2581 | .flags = HCD_USB2 | HCD_MEMORY, | 2584 | .flags = HCD_USB2 | HCD_MEMORY, |
2582 | 2585 | ||
2583 | /* not using irq handler or reset hooks from usbcore, since | 2586 | /* not using irq handler or reset hooks from usbcore, since |
@@ -2605,3 +2608,66 @@ const struct hc_driver musb_hc_driver = { | |||
2605 | /* .start_port_reset = NULL, */ | 2608 | /* .start_port_reset = NULL, */ |
2606 | /* .hub_irq_enable = NULL, */ | 2609 | /* .hub_irq_enable = NULL, */ |
2607 | }; | 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..c7c1d7ab5471 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_resouces[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_resouces, 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 7ef3eb8617a6..37e747a9e27d 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig | |||
@@ -86,7 +86,7 @@ config OMAP_USB3 | |||
86 | on/off the PHY. | 86 | on/off the PHY. |
87 | 87 | ||
88 | config SAMSUNG_USBPHY | 88 | config SAMSUNG_USBPHY |
89 | tristate "Samsung USB PHY Driver" | 89 | tristate |
90 | help | 90 | help |
91 | Enable this to support Samsung USB phy helper driver for Samsung SoCs. | 91 | Enable this to support Samsung USB phy helper driver for Samsung SoCs. |
92 | This driver provides common interface to interact, for Samsung USB 2.0 PHY | 92 | This driver provides common interface to interact, for Samsung USB 2.0 PHY |
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-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-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..5d9af11d2731 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 |
@@ -30,9 +32,7 @@ | |||
30 | #include <linux/usb/ulpi.h> | 32 | #include <linux/usb/ulpi.h> |
31 | #include <asm/mach-types.h> | 33 | #include <asm/mach-types.h> |
32 | #include <linux/usb/tegra_usb_phy.h> | 34 | #include <linux/usb/tegra_usb_phy.h> |
33 | 35 | #include <linux/module.h> | |
34 | #define TEGRA_USB_BASE 0xC5000000 | ||
35 | #define TEGRA_USB_SIZE SZ_16K | ||
36 | 36 | ||
37 | #define ULPI_VIEWPORT 0x170 | 37 | #define ULPI_VIEWPORT 0x170 |
38 | 38 | ||
@@ -198,32 +198,15 @@ static struct tegra_utmip_config utmip_default[] = { | |||
198 | 198 | ||
199 | static int utmip_pad_open(struct tegra_usb_phy *phy) | 199 | static int utmip_pad_open(struct tegra_usb_phy *phy) |
200 | { | 200 | { |
201 | phy->pad_clk = clk_get_sys("utmip-pad", NULL); | 201 | phy->pad_clk = devm_clk_get(phy->dev, "utmi-pads"); |
202 | if (IS_ERR(phy->pad_clk)) { | 202 | if (IS_ERR(phy->pad_clk)) { |
203 | pr_err("%s: can't get utmip pad clock\n", __func__); | 203 | pr_err("%s: can't get utmip pad clock\n", __func__); |
204 | return PTR_ERR(phy->pad_clk); | 204 | return PTR_ERR(phy->pad_clk); |
205 | } | 205 | } |
206 | 206 | ||
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; | 207 | return 0; |
218 | } | 208 | } |
219 | 209 | ||
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) | 210 | static void utmip_pad_power_on(struct tegra_usb_phy *phy) |
228 | { | 211 | { |
229 | unsigned long val, flags; | 212 | unsigned long val, flags; |
@@ -299,7 +282,7 @@ static void utmi_phy_clk_disable(struct tegra_usb_phy *phy) | |||
299 | val &= ~USB_SUSP_SET; | 282 | val &= ~USB_SUSP_SET; |
300 | writel(val, base + USB_SUSP_CTRL); | 283 | writel(val, base + USB_SUSP_CTRL); |
301 | } else | 284 | } else |
302 | phy->set_phcd(&phy->u_phy, true); | 285 | tegra_ehci_set_phcd(&phy->u_phy, true); |
303 | 286 | ||
304 | if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0) | 287 | 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__); | 288 | pr_err("%s: timeout waiting for phy to stabilize\n", __func__); |
@@ -321,7 +304,7 @@ static void utmi_phy_clk_enable(struct tegra_usb_phy *phy) | |||
321 | val &= ~USB_SUSP_CLR; | 304 | val &= ~USB_SUSP_CLR; |
322 | writel(val, base + USB_SUSP_CTRL); | 305 | writel(val, base + USB_SUSP_CTRL); |
323 | } else | 306 | } else |
324 | phy->set_phcd(&phy->u_phy, false); | 307 | tegra_ehci_set_phcd(&phy->u_phy, false); |
325 | 308 | ||
326 | if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, | 309 | if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, |
327 | USB_PHY_CLK_VALID)) | 310 | USB_PHY_CLK_VALID)) |
@@ -444,7 +427,7 @@ static int utmi_phy_power_on(struct tegra_usb_phy *phy) | |||
444 | utmi_phy_clk_enable(phy); | 427 | utmi_phy_clk_enable(phy); |
445 | 428 | ||
446 | if (!phy->is_legacy_phy) | 429 | if (!phy->is_legacy_phy) |
447 | phy->set_pts(&phy->u_phy, 0); | 430 | tegra_ehci_set_pts(&phy->u_phy, 0); |
448 | 431 | ||
449 | return 0; | 432 | return 0; |
450 | } | 433 | } |
@@ -541,11 +524,18 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy) | |||
541 | int ret; | 524 | int ret; |
542 | unsigned long val; | 525 | unsigned long val; |
543 | void __iomem *base = phy->regs; | 526 | void __iomem *base = phy->regs; |
544 | struct tegra_ulpi_config *config = phy->config; | ||
545 | 527 | ||
546 | gpio_direction_output(config->reset_gpio, 0); | 528 | ret = gpio_direction_output(phy->reset_gpio, 0); |
529 | if (ret < 0) { | ||
530 | dev_err(phy->dev, "gpio %d not set to 0\n", phy->reset_gpio); | ||
531 | return ret; | ||
532 | } | ||
547 | msleep(5); | 533 | msleep(5); |
548 | gpio_direction_output(config->reset_gpio, 1); | 534 | ret = gpio_direction_output(phy->reset_gpio, 1); |
535 | if (ret < 0) { | ||
536 | dev_err(phy->dev, "gpio %d not set to 1\n", phy->reset_gpio); | ||
537 | return ret; | ||
538 | } | ||
549 | 539 | ||
550 | clk_prepare_enable(phy->clk); | 540 | clk_prepare_enable(phy->clk); |
551 | msleep(1); | 541 | msleep(1); |
@@ -603,63 +593,15 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy) | |||
603 | 593 | ||
604 | static int ulpi_phy_power_off(struct tegra_usb_phy *phy) | 594 | static int ulpi_phy_power_off(struct tegra_usb_phy *phy) |
605 | { | 595 | { |
606 | struct tegra_ulpi_config *config = phy->config; | ||
607 | |||
608 | clk_disable(phy->clk); | 596 | clk_disable(phy->clk); |
609 | return gpio_direction_output(config->reset_gpio, 0); | 597 | 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 | } | 598 | } |
651 | 599 | ||
652 | static void tegra_usb_phy_close(struct usb_phy *x) | 600 | static void tegra_usb_phy_close(struct usb_phy *x) |
653 | { | 601 | { |
654 | struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy); | 602 | struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy); |
655 | 603 | ||
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); | 604 | clk_disable_unprepare(phy->pll_u); |
661 | clk_put(phy->pll_u); | ||
662 | kfree(phy); | ||
663 | } | 605 | } |
664 | 606 | ||
665 | static int tegra_usb_phy_power_on(struct tegra_usb_phy *phy) | 607 | static int tegra_usb_phy_power_on(struct tegra_usb_phy *phy) |
@@ -687,54 +629,63 @@ static int tegra_usb_phy_suspend(struct usb_phy *x, int suspend) | |||
687 | return tegra_usb_phy_power_on(phy); | 629 | return tegra_usb_phy_power_on(phy); |
688 | } | 630 | } |
689 | 631 | ||
690 | struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance, | 632 | static int ulpi_open(struct tegra_usb_phy *phy) |
691 | void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode, | 633 | { |
692 | void (*set_pts)(struct usb_phy *x, u8 pts_val), | 634 | int err; |
693 | void (*set_phcd)(struct usb_phy *x, bool enable)) | 635 | |
636 | phy->clk = devm_clk_get(phy->dev, "ulpi-link"); | ||
637 | if (IS_ERR(phy->clk)) { | ||
638 | pr_err("%s: can't get ulpi clock\n", __func__); | ||
639 | return PTR_ERR(phy->clk); | ||
640 | } | ||
641 | |||
642 | err = devm_gpio_request(phy->dev, phy->reset_gpio, "ulpi_phy_reset_b"); | ||
643 | if (err < 0) { | ||
644 | dev_err(phy->dev, "request failed for gpio: %d\n", | ||
645 | phy->reset_gpio); | ||
646 | return err; | ||
647 | } | ||
648 | |||
649 | err = gpio_direction_output(phy->reset_gpio, 0); | ||
650 | if (err < 0) { | ||
651 | dev_err(phy->dev, "gpio %d direction not set to output\n", | ||
652 | phy->reset_gpio); | ||
653 | return err; | ||
654 | } | ||
655 | |||
656 | phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0); | ||
657 | if (!phy->ulpi) { | ||
658 | dev_err(phy->dev, "otg_ulpi_create returned NULL\n"); | ||
659 | err = -ENOMEM; | ||
660 | return err; | ||
661 | } | ||
694 | 662 | ||
663 | phy->ulpi->io_priv = phy->regs + ULPI_VIEWPORT; | ||
664 | return 0; | ||
665 | } | ||
666 | |||
667 | static int tegra_usb_phy_init(struct tegra_usb_phy *phy) | ||
695 | { | 668 | { |
696 | struct tegra_usb_phy *phy; | ||
697 | unsigned long parent_rate; | 669 | unsigned long parent_rate; |
698 | int i; | 670 | int i; |
699 | int err; | 671 | int err; |
700 | struct device_node *np = dev->of_node; | 672 | |
701 | 673 | if (!phy->is_ulpi_phy) { | |
702 | phy = kzalloc(sizeof(struct tegra_usb_phy), GFP_KERNEL); | 674 | if (phy->is_legacy_phy) |
703 | if (!phy) | 675 | phy->config = &utmip_default[0]; |
704 | return ERR_PTR(-ENOMEM); | 676 | else |
705 | 677 | 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 | } | 678 | } |
730 | 679 | ||
731 | phy->pll_u = clk_get_sys(NULL, "pll_u"); | 680 | phy->pll_u = devm_clk_get(phy->dev, "pll_u"); |
732 | if (IS_ERR(phy->pll_u)) { | 681 | if (IS_ERR(phy->pll_u)) { |
733 | pr_err("Can't get pll_u clock\n"); | 682 | pr_err("Can't get pll_u clock\n"); |
734 | err = PTR_ERR(phy->pll_u); | 683 | return PTR_ERR(phy->pll_u); |
735 | goto err0; | ||
736 | } | 684 | } |
737 | clk_prepare_enable(phy->pll_u); | 685 | |
686 | err = clk_prepare_enable(phy->pll_u); | ||
687 | if (err) | ||
688 | return err; | ||
738 | 689 | ||
739 | parent_rate = clk_get_rate(clk_get_parent(phy->pll_u)); | 690 | parent_rate = clk_get_rate(clk_get_parent(phy->pll_u)); |
740 | for (i = 0; i < ARRAY_SIZE(tegra_freq_table); i++) { | 691 | for (i = 0; i < ARRAY_SIZE(tegra_freq_table); i++) { |
@@ -746,23 +697,22 @@ struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance, | |||
746 | if (!phy->freq) { | 697 | if (!phy->freq) { |
747 | pr_err("invalid pll_u parent rate %ld\n", parent_rate); | 698 | pr_err("invalid pll_u parent rate %ld\n", parent_rate); |
748 | err = -EINVAL; | 699 | err = -EINVAL; |
749 | goto err1; | 700 | goto fail; |
750 | } | 701 | } |
751 | 702 | ||
752 | phy->u_phy.init = tegra_phy_init; | 703 | if (phy->is_ulpi_phy) |
753 | phy->u_phy.shutdown = tegra_usb_phy_close; | 704 | err = ulpi_open(phy); |
754 | phy->u_phy.set_suspend = tegra_usb_phy_suspend; | 705 | else |
706 | err = utmip_pad_open(phy); | ||
707 | if (err < 0) | ||
708 | goto fail; | ||
755 | 709 | ||
756 | return phy; | 710 | return 0; |
757 | 711 | ||
758 | err1: | 712 | fail: |
759 | clk_disable_unprepare(phy->pll_u); | 713 | clk_disable_unprepare(phy->pll_u); |
760 | clk_put(phy->pll_u); | 714 | return err; |
761 | err0: | ||
762 | kfree(phy); | ||
763 | return ERR_PTR(err); | ||
764 | } | 715 | } |
765 | EXPORT_SYMBOL_GPL(tegra_usb_phy_open); | ||
766 | 716 | ||
767 | void tegra_usb_phy_preresume(struct usb_phy *x) | 717 | void tegra_usb_phy_preresume(struct usb_phy *x) |
768 | { | 718 | { |
@@ -801,3 +751,121 @@ void tegra_ehci_phy_restore_end(struct usb_phy *x) | |||
801 | } | 751 | } |
802 | EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_end); | 752 | EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_end); |
803 | 753 | ||
754 | static int tegra_usb_phy_probe(struct platform_device *pdev) | ||
755 | { | ||
756 | struct resource *res; | ||
757 | struct tegra_usb_phy *tegra_phy = NULL; | ||
758 | struct device_node *np = pdev->dev.of_node; | ||
759 | int err; | ||
760 | |||
761 | tegra_phy = devm_kzalloc(&pdev->dev, sizeof(*tegra_phy), GFP_KERNEL); | ||
762 | if (!tegra_phy) { | ||
763 | dev_err(&pdev->dev, "unable to allocate memory for USB2 PHY\n"); | ||
764 | return -ENOMEM; | ||
765 | } | ||
766 | |||
767 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
768 | if (!res) { | ||
769 | dev_err(&pdev->dev, "Failed to get I/O memory\n"); | ||
770 | return -ENXIO; | ||
771 | } | ||
772 | |||
773 | tegra_phy->regs = devm_ioremap(&pdev->dev, res->start, | ||
774 | resource_size(res)); | ||
775 | if (!tegra_phy->regs) { | ||
776 | dev_err(&pdev->dev, "Failed to remap I/O memory\n"); | ||
777 | return -ENOMEM; | ||
778 | } | ||
779 | |||
780 | tegra_phy->is_legacy_phy = | ||
781 | of_property_read_bool(np, "nvidia,has-legacy-mode"); | ||
782 | |||
783 | err = of_property_match_string(np, "phy_type", "ulpi"); | ||
784 | if (err < 0) { | ||
785 | tegra_phy->is_ulpi_phy = false; | ||
786 | |||
787 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
788 | if (!res) { | ||
789 | dev_err(&pdev->dev, "Failed to get UTMI Pad regs\n"); | ||
790 | return -ENXIO; | ||
791 | } | ||
792 | |||
793 | tegra_phy->pad_regs = devm_ioremap(&pdev->dev, res->start, | ||
794 | resource_size(res)); | ||
795 | if (!tegra_phy->regs) { | ||
796 | dev_err(&pdev->dev, "Failed to remap UTMI Pad regs\n"); | ||
797 | return -ENOMEM; | ||
798 | } | ||
799 | } else { | ||
800 | tegra_phy->is_ulpi_phy = true; | ||
801 | |||
802 | tegra_phy->reset_gpio = | ||
803 | of_get_named_gpio(np, "nvidia,phy-reset-gpio", 0); | ||
804 | if (!gpio_is_valid(tegra_phy->reset_gpio)) { | ||
805 | dev_err(&pdev->dev, "invalid gpio: %d\n", | ||
806 | tegra_phy->reset_gpio); | ||
807 | return tegra_phy->reset_gpio; | ||
808 | } | ||
809 | } | ||
810 | |||
811 | err = of_property_match_string(np, "dr_mode", "otg"); | ||
812 | if (err < 0) { | ||
813 | err = of_property_match_string(np, "dr_mode", "peripheral"); | ||
814 | if (err < 0) | ||
815 | tegra_phy->mode = TEGRA_USB_PHY_MODE_HOST; | ||
816 | else | ||
817 | tegra_phy->mode = TEGRA_USB_PHY_MODE_DEVICE; | ||
818 | } else | ||
819 | tegra_phy->mode = TEGRA_USB_PHY_MODE_OTG; | ||
820 | |||
821 | tegra_phy->dev = &pdev->dev; | ||
822 | err = tegra_usb_phy_init(tegra_phy); | ||
823 | if (err < 0) | ||
824 | return err; | ||
825 | |||
826 | tegra_phy->u_phy.shutdown = tegra_usb_phy_close; | ||
827 | tegra_phy->u_phy.set_suspend = tegra_usb_phy_suspend; | ||
828 | |||
829 | dev_set_drvdata(&pdev->dev, tegra_phy); | ||
830 | return 0; | ||
831 | } | ||
832 | |||
833 | static struct of_device_id tegra_usb_phy_id_table[] = { | ||
834 | { .compatible = "nvidia,tegra20-usb-phy", }, | ||
835 | { }, | ||
836 | }; | ||
837 | MODULE_DEVICE_TABLE(of, tegra_usb_phy_id_table); | ||
838 | |||
839 | static struct platform_driver tegra_usb_phy_driver = { | ||
840 | .probe = tegra_usb_phy_probe, | ||
841 | .driver = { | ||
842 | .name = "tegra-phy", | ||
843 | .owner = THIS_MODULE, | ||
844 | .of_match_table = of_match_ptr(tegra_usb_phy_id_table), | ||
845 | }, | ||
846 | }; | ||
847 | module_platform_driver(tegra_usb_phy_driver); | ||
848 | |||
849 | static int tegra_usb_phy_match(struct device *dev, void *data) | ||
850 | { | ||
851 | struct tegra_usb_phy *tegra_phy = dev_get_drvdata(dev); | ||
852 | struct device_node *dn = data; | ||
853 | |||
854 | return (tegra_phy->dev->of_node == dn) ? 1 : 0; | ||
855 | } | ||
856 | |||
857 | struct usb_phy *tegra_usb_get_phy(struct device_node *dn) | ||
858 | { | ||
859 | struct device *dev; | ||
860 | struct tegra_usb_phy *tegra_phy; | ||
861 | |||
862 | dev = driver_find_device(&tegra_usb_phy_driver.driver, NULL, dn, | ||
863 | tegra_usb_phy_match); | ||
864 | if (!dev) | ||
865 | return ERR_PTR(-EPROBE_DEFER); | ||
866 | |||
867 | tegra_phy = dev_get_drvdata(dev); | ||
868 | |||
869 | return &tegra_phy->u_phy; | ||
870 | } | ||
871 | EXPORT_SYMBOL_GPL(tegra_usb_get_phy); | ||
diff --git a/include/linux/usb/tegra_usb_phy.h b/include/linux/usb/tegra_usb_phy.h index 1b7519a8c0bf..0cd15d2df53d 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 | ||
@@ -79,4 +76,8 @@ void tegra_ehci_phy_restore_start(struct usb_phy *phy, | |||
79 | 76 | ||
80 | void tegra_ehci_phy_restore_end(struct usb_phy *phy); | 77 | void tegra_ehci_phy_restore_end(struct usb_phy *phy); |
81 | 78 | ||
79 | void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val); | ||
80 | |||
81 | void tegra_ehci_set_phcd(struct usb_phy *x, bool enable); | ||
82 | |||
82 | #endif /* __TEGRA_USB_PHY_H */ | 83 | #endif /* __TEGRA_USB_PHY_H */ |