diff options
118 files changed, 3691 insertions, 838 deletions
diff --git a/Documentation/devicetree/bindings/connector/usb-connector.txt b/Documentation/devicetree/bindings/connector/usb-connector.txt index d90e17e2428b..a9a2f2fc44f2 100644 --- a/Documentation/devicetree/bindings/connector/usb-connector.txt +++ b/Documentation/devicetree/bindings/connector/usb-connector.txt | |||
@@ -14,6 +14,8 @@ Optional properties: | |||
14 | - label: symbolic name for the connector, | 14 | - label: symbolic name for the connector, |
15 | - type: size of the connector, should be specified in case of USB-A, USB-B | 15 | - type: size of the connector, should be specified in case of USB-A, USB-B |
16 | non-fullsize connectors: "mini", "micro". | 16 | non-fullsize connectors: "mini", "micro". |
17 | - self-powered: Set this property if the usb device that has its own power | ||
18 | source. | ||
17 | 19 | ||
18 | Optional properties for usb-c-connector: | 20 | Optional properties for usb-c-connector: |
19 | - power-role: should be one of "source", "sink" or "dual"(DRP) if typec | 21 | - power-role: should be one of "source", "sink" or "dual"(DRP) if typec |
diff --git a/Documentation/devicetree/bindings/net/cpsw.txt b/Documentation/devicetree/bindings/net/cpsw.txt index b3acebe08eb0..3264e1978d25 100644 --- a/Documentation/devicetree/bindings/net/cpsw.txt +++ b/Documentation/devicetree/bindings/net/cpsw.txt | |||
@@ -22,7 +22,8 @@ Required properties: | |||
22 | - cpsw-phy-sel : Specifies the phandle to the CPSW phy mode selection | 22 | - cpsw-phy-sel : Specifies the phandle to the CPSW phy mode selection |
23 | device. See also cpsw-phy-sel.txt for it's binding. | 23 | device. See also cpsw-phy-sel.txt for it's binding. |
24 | Note that in legacy cases cpsw-phy-sel may be | 24 | Note that in legacy cases cpsw-phy-sel may be |
25 | a child device instead of a phandle. | 25 | a child device instead of a phandle |
26 | (DEPRECATED, use phys property instead). | ||
26 | 27 | ||
27 | Optional properties: | 28 | Optional properties: |
28 | - ti,hwmods : Must be "cpgmac0" | 29 | - ti,hwmods : Must be "cpgmac0" |
@@ -44,6 +45,7 @@ Optional properties: | |||
44 | Slave Properties: | 45 | Slave Properties: |
45 | Required properties: | 46 | Required properties: |
46 | - phy-mode : See ethernet.txt file in the same directory | 47 | - phy-mode : See ethernet.txt file in the same directory |
48 | - phys : phandle on phy-gmii-sel PHY (see phy/ti-phy-gmii-sel.txt) | ||
47 | 49 | ||
48 | Optional properties: | 50 | Optional properties: |
49 | - dual_emac_res_vlan : Specifies VID to be used to segregate the ports | 51 | - dual_emac_res_vlan : Specifies VID to be used to segregate the ports |
@@ -85,12 +87,14 @@ Examples: | |||
85 | phy-mode = "rgmii-txid"; | 87 | phy-mode = "rgmii-txid"; |
86 | /* Filled in by U-Boot */ | 88 | /* Filled in by U-Boot */ |
87 | mac-address = [ 00 00 00 00 00 00 ]; | 89 | mac-address = [ 00 00 00 00 00 00 ]; |
90 | phys = <&phy_gmii_sel 1 0>; | ||
88 | }; | 91 | }; |
89 | cpsw_emac1: slave@1 { | 92 | cpsw_emac1: slave@1 { |
90 | phy_id = <&davinci_mdio>, <1>; | 93 | phy_id = <&davinci_mdio>, <1>; |
91 | phy-mode = "rgmii-txid"; | 94 | phy-mode = "rgmii-txid"; |
92 | /* Filled in by U-Boot */ | 95 | /* Filled in by U-Boot */ |
93 | mac-address = [ 00 00 00 00 00 00 ]; | 96 | mac-address = [ 00 00 00 00 00 00 ]; |
97 | phys = <&phy_gmii_sel 2 0>; | ||
94 | }; | 98 | }; |
95 | }; | 99 | }; |
96 | 100 | ||
@@ -114,11 +118,13 @@ Examples: | |||
114 | phy-mode = "rgmii-txid"; | 118 | phy-mode = "rgmii-txid"; |
115 | /* Filled in by U-Boot */ | 119 | /* Filled in by U-Boot */ |
116 | mac-address = [ 00 00 00 00 00 00 ]; | 120 | mac-address = [ 00 00 00 00 00 00 ]; |
121 | phys = <&phy_gmii_sel 1 0>; | ||
117 | }; | 122 | }; |
118 | cpsw_emac1: slave@1 { | 123 | cpsw_emac1: slave@1 { |
119 | phy_id = <&davinci_mdio>, <1>; | 124 | phy_id = <&davinci_mdio>, <1>; |
120 | phy-mode = "rgmii-txid"; | 125 | phy-mode = "rgmii-txid"; |
121 | /* Filled in by U-Boot */ | 126 | /* Filled in by U-Boot */ |
122 | mac-address = [ 00 00 00 00 00 00 ]; | 127 | mac-address = [ 00 00 00 00 00 00 ]; |
128 | phys = <&phy_gmii_sel 2 0>; | ||
123 | }; | 129 | }; |
124 | }; | 130 | }; |
diff --git a/Documentation/devicetree/bindings/phy/fsl,imx8mq-usb-phy.txt b/Documentation/devicetree/bindings/phy/fsl,imx8mq-usb-phy.txt new file mode 100644 index 000000000000..a22e853d710c --- /dev/null +++ b/Documentation/devicetree/bindings/phy/fsl,imx8mq-usb-phy.txt | |||
@@ -0,0 +1,17 @@ | |||
1 | * Freescale i.MX8MQ USB3 PHY binding | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: Should be "fsl,imx8mq-usb-phy" | ||
5 | - #phys-cells: must be 0 (see phy-bindings.txt in this directory) | ||
6 | - reg: The base address and length of the registers | ||
7 | - clocks: phandles to the clocks for each clock listed in clock-names | ||
8 | - clock-names: must contain "phy" | ||
9 | |||
10 | Example: | ||
11 | usb3_phy0: phy@381f0040 { | ||
12 | compatible = "fsl,imx8mq-usb-phy"; | ||
13 | reg = <0x381f0040 0x40>; | ||
14 | clocks = <&clk IMX8MQ_CLK_USB1_PHY_ROOT>; | ||
15 | clock-names = "phy"; | ||
16 | #phy-cells = <0>; | ||
17 | }; | ||
diff --git a/Documentation/devicetree/bindings/phy/phy-cadence-sierra.txt b/Documentation/devicetree/bindings/phy/phy-cadence-sierra.txt new file mode 100644 index 000000000000..6e1b47bfce43 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/phy-cadence-sierra.txt | |||
@@ -0,0 +1,67 @@ | |||
1 | Cadence Sierra PHY | ||
2 | ----------------------- | ||
3 | |||
4 | Required properties: | ||
5 | - compatible: cdns,sierra-phy-t0 | ||
6 | - clocks: Must contain an entry in clock-names. | ||
7 | See ../clocks/clock-bindings.txt for details. | ||
8 | - clock-names: Must be "phy_clk" | ||
9 | - resets: Must contain an entry for each in reset-names. | ||
10 | See ../reset/reset.txt for details. | ||
11 | - reset-names: Must include "sierra_reset" and "sierra_apb". | ||
12 | "sierra_reset" must control the reset line to the PHY. | ||
13 | "sierra_apb" must control the reset line to the APB PHY | ||
14 | interface. | ||
15 | - reg: register range for the PHY. | ||
16 | - #address-cells: Must be 1 | ||
17 | - #size-cells: Must be 0 | ||
18 | |||
19 | Optional properties: | ||
20 | - cdns,autoconf: A boolean property whose presence indicates that the | ||
21 | PHY registers will be configured by hardware. If not | ||
22 | present, all sub-node optional properties must be | ||
23 | provided. | ||
24 | |||
25 | Sub-nodes: | ||
26 | Each group of PHY lanes with a single master lane should be represented as | ||
27 | a sub-node. Note that the actual configuration of each lane is determined by | ||
28 | hardware strapping, and must match the configuration specified here. | ||
29 | |||
30 | Sub-node required properties: | ||
31 | - #phy-cells: Generic PHY binding; must be 0. | ||
32 | - reg: The master lane number. This is the lowest numbered lane | ||
33 | in the lane group. | ||
34 | - resets: Must contain one entry which controls the reset line for the | ||
35 | master lane of the sub-node. | ||
36 | See ../reset/reset.txt for details. | ||
37 | |||
38 | Sub-node optional properties: | ||
39 | - cdns,num-lanes: Number of lanes in this group. From 1 to 4. The | ||
40 | group is made up of consecutive lanes. | ||
41 | - cdns,phy-type: Can be PHY_TYPE_PCIE or PHY_TYPE_USB3, depending on | ||
42 | configuration of lanes. | ||
43 | |||
44 | Example: | ||
45 | pcie_phy4: pcie-phy@fd240000 { | ||
46 | compatible = "cdns,sierra-phy-t0"; | ||
47 | reg = <0x0 0xfd240000 0x0 0x40000>; | ||
48 | resets = <&phyrst 0>, <&phyrst 1>; | ||
49 | reset-names = "sierra_reset", "sierra_apb"; | ||
50 | clocks = <&phyclock>; | ||
51 | clock-names = "phy_clk"; | ||
52 | #address-cells = <1>; | ||
53 | #size-cells = <0>; | ||
54 | pcie0_phy0: pcie-phy@0 { | ||
55 | reg = <0>; | ||
56 | resets = <&phyrst 2>; | ||
57 | cdns,num-lanes = <2>; | ||
58 | #phy-cells = <0>; | ||
59 | cdns,phy-type = <PHY_TYPE_PCIE>; | ||
60 | }; | ||
61 | pcie0_phy1: pcie-phy@2 { | ||
62 | reg = <2>; | ||
63 | resets = <&phyrst 4>; | ||
64 | cdns,num-lanes = <1>; | ||
65 | #phy-cells = <0>; | ||
66 | cdns,phy-type = <PHY_TYPE_PCIE>; | ||
67 | }; | ||
diff --git a/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt b/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt index fbc198d5dd39..41a1074228ba 100644 --- a/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt +++ b/Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt | |||
@@ -25,10 +25,6 @@ Required properties: | |||
25 | - For all others: | 25 | - For all others: |
26 | - The reg-names property shouldn't be defined. | 26 | - The reg-names property shouldn't be defined. |
27 | 27 | ||
28 | - #clock-cells: must be 1 | ||
29 | - Phy pll outputs a bunch of clocks for Tx, Rx and Pipe | ||
30 | interface (for pipe based PHYs). These clock are then gate-controlled | ||
31 | by gcc. | ||
32 | - #address-cells: must be 1 | 28 | - #address-cells: must be 1 |
33 | - #size-cells: must be 1 | 29 | - #size-cells: must be 1 |
34 | - ranges: must be present | 30 | - ranges: must be present |
@@ -82,27 +78,33 @@ Required nodes: | |||
82 | - Each device node of QMP phy is required to have as many child nodes as | 78 | - Each device node of QMP phy is required to have as many child nodes as |
83 | the number of lanes the PHY has. | 79 | the number of lanes the PHY has. |
84 | 80 | ||
85 | Required properties for child node: | 81 | Required properties for child nodes of PCIe PHYs (one child per lane): |
86 | - reg: list of offset and length pairs of register sets for PHY blocks - | 82 | - reg: list of offset and length pairs of register sets for PHY blocks - |
87 | - index 0: tx | 83 | tx, rx, pcs, and pcs_misc (optional). |
88 | - index 1: rx | 84 | - #phy-cells: must be 0 |
89 | - index 2: pcs | ||
90 | - index 3: pcs_misc (optional) | ||
91 | 85 | ||
86 | Required properties for a single "lanes" child node of non-PCIe PHYs: | ||
87 | - reg: list of offset and length pairs of register sets for PHY blocks | ||
88 | For 1-lane devices: | ||
89 | tx, rx, pcs, and (optionally) pcs_misc | ||
90 | For 2-lane devices: | ||
91 | tx0, rx0, pcs, tx1, rx1, and (optionally) pcs_misc | ||
92 | - #phy-cells: must be 0 | 92 | - #phy-cells: must be 0 |
93 | 93 | ||
94 | Required properties child node of pcie and usb3 qmp phys: | 94 | Required properties for child node of PCIe and USB3 qmp phys: |
95 | - clocks: a list of phandles and clock-specifier pairs, | 95 | - clocks: a list of phandles and clock-specifier pairs, |
96 | one for each entry in clock-names. | 96 | one for each entry in clock-names. |
97 | - clock-names: Must contain following: | 97 | - clock-names: Must contain following: |
98 | "pipe<lane-number>" for pipe clock specific to each lane. | 98 | "pipe<lane-number>" for pipe clock specific to each lane. |
99 | - clock-output-names: Name of the PHY clock that will be the parent for | 99 | - clock-output-names: Name of the PHY clock that will be the parent for |
100 | the above pipe clock. | 100 | the above pipe clock. |
101 | |||
102 | For "qcom,ipq8074-qmp-pcie-phy": | 101 | For "qcom,ipq8074-qmp-pcie-phy": |
103 | - "pcie20_phy0_pipe_clk" Pipe Clock parent | 102 | - "pcie20_phy0_pipe_clk" Pipe Clock parent |
104 | (or) | 103 | (or) |
105 | "pcie20_phy1_pipe_clk" | 104 | "pcie20_phy1_pipe_clk" |
105 | - #clock-cells: must be 0 | ||
106 | - Phy pll outputs pipe clocks for pipe based PHYs. These clocks are then | ||
107 | gate-controlled by the gcc. | ||
106 | 108 | ||
107 | Required properties for child node of PHYs with lane reset, AKA: | 109 | Required properties for child node of PHYs with lane reset, AKA: |
108 | "qcom,msm8996-qmp-pcie-phy" | 110 | "qcom,msm8996-qmp-pcie-phy" |
@@ -115,7 +117,6 @@ Example: | |||
115 | phy@34000 { | 117 | phy@34000 { |
116 | compatible = "qcom,msm8996-qmp-pcie-phy"; | 118 | compatible = "qcom,msm8996-qmp-pcie-phy"; |
117 | reg = <0x34000 0x488>; | 119 | reg = <0x34000 0x488>; |
118 | #clock-cells = <1>; | ||
119 | #address-cells = <1>; | 120 | #address-cells = <1>; |
120 | #size-cells = <1>; | 121 | #size-cells = <1>; |
121 | ranges; | 122 | ranges; |
@@ -137,6 +138,7 @@ Example: | |||
137 | reg = <0x35000 0x130>, | 138 | reg = <0x35000 0x130>, |
138 | <0x35200 0x200>, | 139 | <0x35200 0x200>, |
139 | <0x35400 0x1dc>; | 140 | <0x35400 0x1dc>; |
141 | #clock-cells = <0>; | ||
140 | #phy-cells = <0>; | 142 | #phy-cells = <0>; |
141 | 143 | ||
142 | clocks = <&gcc GCC_PCIE_0_PIPE_CLK>; | 144 | clocks = <&gcc GCC_PCIE_0_PIPE_CLK>; |
@@ -150,3 +152,54 @@ Example: | |||
150 | ... | 152 | ... |
151 | ... | 153 | ... |
152 | }; | 154 | }; |
155 | |||
156 | phy@88eb000 { | ||
157 | compatible = "qcom,sdm845-qmp-usb3-uni-phy"; | ||
158 | reg = <0x88eb000 0x18c>; | ||
159 | #address-cells = <1>; | ||
160 | #size-cells = <1>; | ||
161 | ranges; | ||
162 | |||
163 | clocks = <&gcc GCC_USB3_SEC_PHY_AUX_CLK>, | ||
164 | <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>, | ||
165 | <&gcc GCC_USB3_SEC_CLKREF_CLK>, | ||
166 | <&gcc GCC_USB3_SEC_PHY_COM_AUX_CLK>; | ||
167 | clock-names = "aux", "cfg_ahb", "ref", "com_aux"; | ||
168 | |||
169 | resets = <&gcc GCC_USB3PHY_PHY_SEC_BCR>, | ||
170 | <&gcc GCC_USB3_PHY_SEC_BCR>; | ||
171 | reset-names = "phy", "common"; | ||
172 | |||
173 | lane@88eb200 { | ||
174 | reg = <0x88eb200 0x128>, | ||
175 | <0x88eb400 0x1fc>, | ||
176 | <0x88eb800 0x218>, | ||
177 | <0x88eb600 0x70>; | ||
178 | #clock-cells = <0>; | ||
179 | #phy-cells = <0>; | ||
180 | clocks = <&gcc GCC_USB3_SEC_PHY_PIPE_CLK>; | ||
181 | clock-names = "pipe0"; | ||
182 | clock-output-names = "usb3_uni_phy_pipe_clk_src"; | ||
183 | }; | ||
184 | }; | ||
185 | |||
186 | phy@1d87000 { | ||
187 | compatible = "qcom,sdm845-qmp-ufs-phy"; | ||
188 | reg = <0x1d87000 0x18c>; | ||
189 | #address-cells = <1>; | ||
190 | #size-cells = <1>; | ||
191 | ranges; | ||
192 | clock-names = "ref", | ||
193 | "ref_aux"; | ||
194 | clocks = <&gcc GCC_UFS_MEM_CLKREF_CLK>, | ||
195 | <&gcc GCC_UFS_PHY_PHY_AUX_CLK>; | ||
196 | |||
197 | lanes@1d87400 { | ||
198 | reg = <0x1d87400 0x108>, | ||
199 | <0x1d87600 0x1e0>, | ||
200 | <0x1d87c00 0x1dc>, | ||
201 | <0x1d87800 0x108>, | ||
202 | <0x1d87a00 0x1e0>; | ||
203 | #phy-cells = <0>; | ||
204 | }; | ||
205 | }; | ||
diff --git a/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt b/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt index 07ca4ec4a745..f2e120af17f0 100644 --- a/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt +++ b/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt | |||
@@ -14,13 +14,14 @@ Required properties: | |||
14 | * allwinner,sun8i-r40-usb-phy | 14 | * allwinner,sun8i-r40-usb-phy |
15 | * allwinner,sun8i-v3s-usb-phy | 15 | * allwinner,sun8i-v3s-usb-phy |
16 | * allwinner,sun50i-a64-usb-phy | 16 | * allwinner,sun50i-a64-usb-phy |
17 | * allwinner,sun50i-h6-usb-phy | ||
17 | - reg : a list of offset + length pairs | 18 | - reg : a list of offset + length pairs |
18 | - reg-names : | 19 | - reg-names : |
19 | * "phy_ctrl" | 20 | * "phy_ctrl" |
20 | * "pmu0" for H3, V3s and A64 | 21 | * "pmu0" for H3, V3s, A64 or H6 |
21 | * "pmu1" | 22 | * "pmu1" |
22 | * "pmu2" for sun4i, sun6i, sun7i, sun8i-a83t or sun8i-h3 | 23 | * "pmu2" for sun4i, sun6i, sun7i, sun8i-a83t or sun8i-h3 |
23 | * "pmu3" for sun8i-h3 | 24 | * "pmu3" for sun8i-h3 or sun50i-h6 |
24 | - #phy-cells : from the generic phy bindings, must be 1 | 25 | - #phy-cells : from the generic phy bindings, must be 1 |
25 | - clocks : phandle + clock specifier for the phy clocks | 26 | - clocks : phandle + clock specifier for the phy clocks |
26 | - clock-names : | 27 | - clock-names : |
@@ -29,12 +30,13 @@ Required properties: | |||
29 | * "usb0_phy", "usb1_phy" for sun8i | 30 | * "usb0_phy", "usb1_phy" for sun8i |
30 | * "usb0_phy", "usb1_phy", "usb2_phy" and "usb2_hsic_12M" for sun8i-a83t | 31 | * "usb0_phy", "usb1_phy", "usb2_phy" and "usb2_hsic_12M" for sun8i-a83t |
31 | * "usb0_phy", "usb1_phy", "usb2_phy" and "usb3_phy" for sun8i-h3 | 32 | * "usb0_phy", "usb1_phy", "usb2_phy" and "usb3_phy" for sun8i-h3 |
33 | * "usb0_phy" and "usb3_phy" for sun50i-h6 | ||
32 | - resets : a list of phandle + reset specifier pairs | 34 | - resets : a list of phandle + reset specifier pairs |
33 | - reset-names : | 35 | - reset-names : |
34 | * "usb0_reset" | 36 | * "usb0_reset" |
35 | * "usb1_reset" | 37 | * "usb1_reset" |
36 | * "usb2_reset" for sun4i, sun6i, sun7i, sun8i-a83t or sun8i-h3 | 38 | * "usb2_reset" for sun4i, sun6i, sun7i, sun8i-a83t or sun8i-h3 |
37 | * "usb3_reset" for sun8i-h3 | 39 | * "usb3_reset" for sun8i-h3 and sun50i-h6 |
38 | 40 | ||
39 | Optional properties: | 41 | Optional properties: |
40 | - usb0_id_det-gpios : gpio phandle for reading the otg id pin value | 42 | - usb0_id_det-gpios : gpio phandle for reading the otg id pin value |
diff --git a/Documentation/devicetree/bindings/phy/ti-phy-gmii-sel.txt b/Documentation/devicetree/bindings/phy/ti-phy-gmii-sel.txt new file mode 100644 index 000000000000..50ce9ae0f7a5 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/ti-phy-gmii-sel.txt | |||
@@ -0,0 +1,68 @@ | |||
1 | CPSW Port's Interface Mode Selection PHY Tree Bindings | ||
2 | ----------------------------------------------- | ||
3 | |||
4 | TI am335x/am437x/dra7(am5)/dm814x CPSW3G Ethernet Subsystem supports | ||
5 | two 10/100/1000 Ethernet ports with selectable G/MII, RMII, and RGMII interfaces. | ||
6 | The interface mode is selected by configuring the MII mode selection register(s) | ||
7 | (GMII_SEL) in the System Control Module chapter (SCM). GMII_SEL register(s) and | ||
8 | bit fields placement in SCM are different between SoCs while fields meaning | ||
9 | is the same. | ||
10 | +--------------+ | ||
11 | +-------------------------------+ |SCM | | ||
12 | | CPSW | | +---------+ | | ||
13 | | +--------------------------------+gmii_sel | | | ||
14 | | | | | +---------+ | | ||
15 | | +----v---+ +--------+ | +--------------+ | ||
16 | | |Port 1..<--+-->GMII/MII<-------> | ||
17 | | | | | | | | | ||
18 | | +--------+ | +--------+ | | ||
19 | | | | | ||
20 | | | +--------+ | | ||
21 | | | | RMII <-------> | ||
22 | | +--> | | | ||
23 | | | +--------+ | | ||
24 | | | | | ||
25 | | | +--------+ | | ||
26 | | | | RGMII <-------> | ||
27 | | +--> | | | ||
28 | | +--------+ | | ||
29 | +-------------------------------+ | ||
30 | |||
31 | CPSW Port's Interface Mode Selection PHY describes MII interface mode between | ||
32 | CPSW Port and Ethernet PHY which depends on Eth PHY and board configuration. | ||
33 | |||
34 | CPSW Port's Interface Mode Selection PHY device should defined as child device | ||
35 | of SCM node (scm_conf) and can be attached to each CPSW port node using standard | ||
36 | PHY bindings (See phy/phy-bindings.txt). | ||
37 | |||
38 | Required properties: | ||
39 | - compatible : Should be "ti,am3352-phy-gmii-sel" for am335x platform | ||
40 | "ti,dra7xx-phy-gmii-sel" for dra7xx/am57xx platform | ||
41 | "ti,am43xx-phy-gmii-sel" for am43xx platform | ||
42 | "ti,dm814-phy-gmii-sel" for dm814x platform | ||
43 | - reg : Address and length of the register set for the device | ||
44 | - #phy-cells : must be 2. | ||
45 | cell 1 - CPSW port number (starting from 1) | ||
46 | cell 2 - RMII refclk mode | ||
47 | |||
48 | Examples: | ||
49 | phy_gmii_sel: phy-gmii-sel { | ||
50 | compatible = "ti,am3352-phy-gmii-sel"; | ||
51 | reg = <0x650 0x4>; | ||
52 | #phy-cells = <2>; | ||
53 | }; | ||
54 | |||
55 | mac: ethernet@4a100000 { | ||
56 | compatible = "ti,am335x-cpsw","ti,cpsw"; | ||
57 | ... | ||
58 | |||
59 | cpsw_emac0: slave@4a100200 { | ||
60 | ... | ||
61 | phys = <&phy_gmii_sel 1 1>; | ||
62 | }; | ||
63 | |||
64 | cpsw_emac1: slave@4a100300 { | ||
65 | ... | ||
66 | phys = <&phy_gmii_sel 2 1>; | ||
67 | }; | ||
68 | }; | ||
diff --git a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt index 529e51879fb2..adae82385dd6 100644 --- a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt +++ b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt | |||
@@ -80,15 +80,19 @@ Optional properties: | |||
80 | controller. It's expected that a mux state of 0 indicates device mode and a | 80 | controller. It's expected that a mux state of 0 indicates device mode and a |
81 | mux state of 1 indicates host mode. | 81 | mux state of 1 indicates host mode. |
82 | - mux-control-names: Shall be "usb_switch" if mux-controls is specified. | 82 | - mux-control-names: Shall be "usb_switch" if mux-controls is specified. |
83 | - pinctrl-names: Names for optional pin modes in "default", "host", "device" | 83 | - pinctrl-names: Names for optional pin modes in "default", "host", "device". |
84 | In case of HSIC-mode, "idle" and "active" pin modes are mandatory. In this | ||
85 | case, the "idle" state needs to pull down the data and strobe pin | ||
86 | and the "active" state needs to pull up the strobe pin. | ||
84 | - pinctrl-n: alternate pin modes | 87 | - pinctrl-n: alternate pin modes |
85 | 88 | ||
86 | i.mx specific properties | 89 | i.mx specific properties |
87 | - fsl,usbmisc: phandler of non-core register device, with one | 90 | - fsl,usbmisc: phandler of non-core register device, with one |
88 | argument that indicate usb controller index | 91 | argument that indicate usb controller index |
89 | - disable-over-current: disable over current detect | 92 | - disable-over-current: disable over current detect |
90 | - over-current-active-high: over current signal polarity is high active, | 93 | - over-current-active-low: over current signal polarity is active low. |
91 | typically over current signal polarity is low active. | 94 | - over-current-active-high: over current signal polarity is active high. |
95 | It's recommended to specify the over current polarity. | ||
92 | - external-vbus-divider: enables off-chip resistor divider for Vbus | 96 | - external-vbus-divider: enables off-chip resistor divider for Vbus |
93 | 97 | ||
94 | Example: | 98 | Example: |
@@ -111,3 +115,29 @@ Example: | |||
111 | mux-controls = <&usb_switch>; | 115 | mux-controls = <&usb_switch>; |
112 | mux-control-names = "usb_switch"; | 116 | mux-control-names = "usb_switch"; |
113 | }; | 117 | }; |
118 | |||
119 | Example for HSIC: | ||
120 | |||
121 | usb@2184400 { | ||
122 | compatible = "fsl,imx6q-usb", "fsl,imx27-usb"; | ||
123 | reg = <0x02184400 0x200>; | ||
124 | interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; | ||
125 | clocks = <&clks IMX6QDL_CLK_USBOH3>; | ||
126 | fsl,usbphy = <&usbphynop1>; | ||
127 | fsl,usbmisc = <&usbmisc 2>; | ||
128 | phy_type = "hsic"; | ||
129 | dr_mode = "host"; | ||
130 | ahb-burst-config = <0x0>; | ||
131 | tx-burst-size-dword = <0x10>; | ||
132 | rx-burst-size-dword = <0x10>; | ||
133 | pinctrl-names = "idle", "active"; | ||
134 | pinctrl-0 = <&pinctrl_usbh2_idle>; | ||
135 | pinctrl-1 = <&pinctrl_usbh2_active>; | ||
136 | #address-cells = <1>; | ||
137 | #size-cells = <0>; | ||
138 | |||
139 | usbnet: smsc@1 { | ||
140 | compatible = "usb424,9730"; | ||
141 | reg = <1>; | ||
142 | }; | ||
143 | }; | ||
diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt index 636630fb92d7..8e5265e9f658 100644 --- a/Documentation/devicetree/bindings/usb/dwc3.txt +++ b/Documentation/devicetree/bindings/usb/dwc3.txt | |||
@@ -37,7 +37,11 @@ Optional properties: | |||
37 | - phy-names: from the *Generic PHY* bindings; supported names are "usb2-phy" | 37 | - phy-names: from the *Generic PHY* bindings; supported names are "usb2-phy" |
38 | or "usb3-phy". | 38 | or "usb3-phy". |
39 | - resets: a single pair of phandle and reset specifier | 39 | - resets: a single pair of phandle and reset specifier |
40 | - snps,usb2-lpm-disable: indicate if we don't want to enable USB2 HW LPM | ||
40 | - snps,usb3_lpm_capable: determines if platform is USB3 LPM capable | 41 | - snps,usb3_lpm_capable: determines if platform is USB3 LPM capable |
42 | - snps,dis-start-transfer-quirk: when set, disable isoc START TRANSFER command | ||
43 | failure SW work-around for DWC_usb31 version 1.70a-ea06 | ||
44 | and prior. | ||
41 | - snps,disable_scramble_quirk: true when SW should disable data scrambling. | 45 | - snps,disable_scramble_quirk: true when SW should disable data scrambling. |
42 | Only really useful for FPGA builds. | 46 | Only really useful for FPGA builds. |
43 | - snps,has-lpm-erratum: true when DWC3 was configured with LPM Erratum enabled | 47 | - snps,has-lpm-erratum: true when DWC3 was configured with LPM Erratum enabled |
diff --git a/Documentation/driver-api/usb/index.rst b/Documentation/driver-api/usb/index.rst index 8fe995a1ec94..cfa8797ea614 100644 --- a/Documentation/driver-api/usb/index.rst +++ b/Documentation/driver-api/usb/index.rst | |||
@@ -19,6 +19,7 @@ Linux USB API | |||
19 | dwc3 | 19 | dwc3 |
20 | writing_musb_glue_layer | 20 | writing_musb_glue_layer |
21 | typec | 21 | typec |
22 | typec_bus | ||
22 | usb3-debug-port | 23 | usb3-debug-port |
23 | 24 | ||
24 | .. only:: subproject and html | 25 | .. only:: subproject and html |
diff --git a/Documentation/driver-api/usb/typec.rst b/Documentation/driver-api/usb/typec.rst index 48ff58095f11..201163d8c13e 100644 --- a/Documentation/driver-api/usb/typec.rst +++ b/Documentation/driver-api/usb/typec.rst | |||
@@ -1,3 +1,4 @@ | |||
1 | .. _typec: | ||
1 | 2 | ||
2 | USB Type-C connector class | 3 | USB Type-C connector class |
3 | ========================== | 4 | ========================== |
diff --git a/Documentation/driver-api/usb/typec_bus.rst b/Documentation/driver-api/usb/typec_bus.rst index d5eec1715b5b..f47a69bff498 100644 --- a/Documentation/driver-api/usb/typec_bus.rst +++ b/Documentation/driver-api/usb/typec_bus.rst | |||
@@ -13,10 +13,10 @@ every alternate mode, so every alternate mode will need a custom driver. | |||
13 | USB Type-C bus allows binding a driver to the discovered partner alternate | 13 | USB Type-C bus allows binding a driver to the discovered partner alternate |
14 | modes by using the SVID and the mode number. | 14 | modes by using the SVID and the mode number. |
15 | 15 | ||
16 | USB Type-C Connector Class provides a device for every alternate mode a port | 16 | :ref:`USB Type-C Connector Class <typec>` provides a device for every alternate |
17 | supports, and separate device for every alternate mode the partner supports. | 17 | mode a port supports, and separate device for every alternate mode the partner |
18 | The drivers for the alternate modes are bound to the partner alternate mode | 18 | supports. The drivers for the alternate modes are bound to the partner alternate |
19 | devices, and the port alternate mode devices must be handled by the port | 19 | mode devices, and the port alternate mode devices must be handled by the port |
20 | drivers. | 20 | drivers. |
21 | 21 | ||
22 | When a new partner alternate mode device is registered, it is linked to the | 22 | When a new partner alternate mode device is registered, it is linked to the |
@@ -46,7 +46,7 @@ enter any modes on their own. | |||
46 | ``->vdm`` is the most important callback in the operation callbacks vector. It | 46 | ``->vdm`` is the most important callback in the operation callbacks vector. It |
47 | will be used to deliver all the SVID specific commands from the partner to the | 47 | will be used to deliver all the SVID specific commands from the partner to the |
48 | alternate mode driver, and vice versa in case of port drivers. The drivers send | 48 | alternate mode driver, and vice versa in case of port drivers. The drivers send |
49 | the SVID specific commands to each other using :c:func:`typec_altmode_vmd()`. | 49 | the SVID specific commands to each other using :c:func:`typec_altmode_vdm()`. |
50 | 50 | ||
51 | If the communication with the partner using the SVID specific commands results | 51 | If the communication with the partner using the SVID specific commands results |
52 | in need to reconfigure the pins on the connector, the alternate mode driver | 52 | in need to reconfigure the pins on the connector, the alternate mode driver |
@@ -67,15 +67,15 @@ Type-C Specification, and also put the connector back to ``TYPEC_STATE_USB`` | |||
67 | after the mode has been exited. | 67 | after the mode has been exited. |
68 | 68 | ||
69 | An example of working definitions for SVID specific pin configurations would | 69 | An example of working definitions for SVID specific pin configurations would |
70 | look like this: | 70 | look like this:: |
71 | 71 | ||
72 | enum { | 72 | enum { |
73 | ALTMODEX_CONF_A = TYPEC_STATE_MODAL, | 73 | ALTMODEX_CONF_A = TYPEC_STATE_MODAL, |
74 | ALTMODEX_CONF_B, | 74 | ALTMODEX_CONF_B, |
75 | ... | 75 | ... |
76 | }; | 76 | }; |
77 | 77 | ||
78 | Helper macro ``TYPEC_MODAL_STATE()`` can also be used: | 78 | Helper macro ``TYPEC_MODAL_STATE()`` can also be used:: |
79 | 79 | ||
80 | #define ALTMODEX_CONF_A = TYPEC_MODAL_STATE(0); | 80 | #define ALTMODEX_CONF_A = TYPEC_MODAL_STATE(0); |
81 | #define ALTMODEX_CONF_B = TYPEC_MODAL_STATE(1); | 81 | #define ALTMODEX_CONF_B = TYPEC_MODAL_STATE(1); |
diff --git a/Documentation/usb/authorization.txt b/Documentation/usb/authorization.txt index c7e985f05d8f..f901ec77439c 100644 --- a/Documentation/usb/authorization.txt +++ b/Documentation/usb/authorization.txt | |||
@@ -119,5 +119,5 @@ If a deauthorized interface will be authorized so the driver probing must | |||
119 | be triggered manually by writing INTERFACE to /sys/bus/usb/drivers_probe | 119 | be triggered manually by writing INTERFACE to /sys/bus/usb/drivers_probe |
120 | 120 | ||
121 | For drivers that need multiple interfaces all needed interfaces should be | 121 | For drivers that need multiple interfaces all needed interfaces should be |
122 | authroized first. After that the drivers should be probed. | 122 | authorized first. After that the drivers should be probed. |
123 | This avoids side effects. | 123 | This avoids side effects. |
diff --git a/MAINTAINERS b/MAINTAINERS index b66404ff27fa..75e8e5500e92 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -6266,6 +6266,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy.git | |||
6266 | S: Supported | 6266 | S: Supported |
6267 | F: drivers/phy/ | 6267 | F: drivers/phy/ |
6268 | F: include/linux/phy/ | 6268 | F: include/linux/phy/ |
6269 | F: Documentation/devicetree/bindings/phy/ | ||
6269 | 6270 | ||
6270 | GENERIC PINCTRL I2C DEMULTIPLEXER DRIVER | 6271 | GENERIC PINCTRL I2C DEMULTIPLEXER DRIVER |
6271 | M: Wolfram Sang <wsa+renesas@sang-engineering.com> | 6272 | M: Wolfram Sang <wsa+renesas@sang-engineering.com> |
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index f1dab0b55769..6a059d6ee03f 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | |||
@@ -1165,28 +1165,13 @@ static void mvpp22_gop_setup_irq(struct mvpp2_port *port) | |||
1165 | */ | 1165 | */ |
1166 | static int mvpp22_comphy_init(struct mvpp2_port *port) | 1166 | static int mvpp22_comphy_init(struct mvpp2_port *port) |
1167 | { | 1167 | { |
1168 | enum phy_mode mode; | ||
1169 | int ret; | 1168 | int ret; |
1170 | 1169 | ||
1171 | if (!port->comphy) | 1170 | if (!port->comphy) |
1172 | return 0; | 1171 | return 0; |
1173 | 1172 | ||
1174 | switch (port->phy_interface) { | 1173 | ret = phy_set_mode_ext(port->comphy, PHY_MODE_ETHERNET, |
1175 | case PHY_INTERFACE_MODE_SGMII: | 1174 | port->phy_interface); |
1176 | case PHY_INTERFACE_MODE_1000BASEX: | ||
1177 | mode = PHY_MODE_SGMII; | ||
1178 | break; | ||
1179 | case PHY_INTERFACE_MODE_2500BASEX: | ||
1180 | mode = PHY_MODE_2500SGMII; | ||
1181 | break; | ||
1182 | case PHY_INTERFACE_MODE_10GKR: | ||
1183 | mode = PHY_MODE_10GKR; | ||
1184 | break; | ||
1185 | default: | ||
1186 | return -EINVAL; | ||
1187 | } | ||
1188 | |||
1189 | ret = phy_set_mode(port->comphy, mode); | ||
1190 | if (ret) | 1175 | if (ret) |
1191 | return ret; | 1176 | return ret; |
1192 | 1177 | ||
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 3238b9ee42f3..3edb6082c670 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c | |||
@@ -472,7 +472,6 @@ static int ocelot_port_open(struct net_device *dev) | |||
472 | { | 472 | { |
473 | struct ocelot_port *port = netdev_priv(dev); | 473 | struct ocelot_port *port = netdev_priv(dev); |
474 | struct ocelot *ocelot = port->ocelot; | 474 | struct ocelot *ocelot = port->ocelot; |
475 | enum phy_mode phy_mode; | ||
476 | int err; | 475 | int err; |
477 | 476 | ||
478 | /* Enable receiving frames on the port, and activate auto-learning of | 477 | /* Enable receiving frames on the port, and activate auto-learning of |
@@ -484,12 +483,8 @@ static int ocelot_port_open(struct net_device *dev) | |||
484 | ANA_PORT_PORT_CFG, port->chip_port); | 483 | ANA_PORT_PORT_CFG, port->chip_port); |
485 | 484 | ||
486 | if (port->serdes) { | 485 | if (port->serdes) { |
487 | if (port->phy_mode == PHY_INTERFACE_MODE_SGMII) | 486 | err = phy_set_mode_ext(port->serdes, PHY_MODE_ETHERNET, |
488 | phy_mode = PHY_MODE_SGMII; | 487 | port->phy_mode); |
489 | else | ||
490 | phy_mode = PHY_MODE_QSGMII; | ||
491 | |||
492 | err = phy_set_mode(port->serdes, phy_mode); | ||
493 | if (err) { | 488 | if (err) { |
494 | netdev_err(dev, "Could not set mode of SerDes\n"); | 489 | netdev_err(dev, "Could not set mode of SerDes\n"); |
495 | return err; | 490 | return err; |
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 500f7ed8c58c..94e5e5b791ec 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/netdevice.h> | 26 | #include <linux/netdevice.h> |
27 | #include <linux/net_tstamp.h> | 27 | #include <linux/net_tstamp.h> |
28 | #include <linux/phy.h> | 28 | #include <linux/phy.h> |
29 | #include <linux/phy/phy.h> | ||
29 | #include <linux/workqueue.h> | 30 | #include <linux/workqueue.h> |
30 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
31 | #include <linux/pm_runtime.h> | 32 | #include <linux/pm_runtime.h> |
@@ -387,6 +388,7 @@ struct cpsw_slave_data { | |||
387 | int phy_if; | 388 | int phy_if; |
388 | u8 mac_addr[ETH_ALEN]; | 389 | u8 mac_addr[ETH_ALEN]; |
389 | u16 dual_emac_res_vlan; /* Reserved VLAN for DualEMAC */ | 390 | u16 dual_emac_res_vlan; /* Reserved VLAN for DualEMAC */ |
391 | struct phy *ifphy; | ||
390 | }; | 392 | }; |
391 | 393 | ||
392 | struct cpsw_platform_data { | 394 | struct cpsw_platform_data { |
@@ -1510,7 +1512,12 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv) | |||
1510 | phy_start(slave->phy); | 1512 | phy_start(slave->phy); |
1511 | 1513 | ||
1512 | /* Configure GMII_SEL register */ | 1514 | /* Configure GMII_SEL register */ |
1513 | cpsw_phy_sel(cpsw->dev, slave->phy->interface, slave->slave_num); | 1515 | if (!IS_ERR(slave->data->ifphy)) |
1516 | phy_set_mode_ext(slave->data->ifphy, PHY_MODE_ETHERNET, | ||
1517 | slave->data->phy_if); | ||
1518 | else | ||
1519 | cpsw_phy_sel(cpsw->dev, slave->phy->interface, | ||
1520 | slave->slave_num); | ||
1514 | } | 1521 | } |
1515 | 1522 | ||
1516 | static inline void cpsw_add_default_vlan(struct cpsw_priv *priv) | 1523 | static inline void cpsw_add_default_vlan(struct cpsw_priv *priv) |
@@ -3147,6 +3154,16 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data, | |||
3147 | if (strcmp(slave_node->name, "slave")) | 3154 | if (strcmp(slave_node->name, "slave")) |
3148 | continue; | 3155 | continue; |
3149 | 3156 | ||
3157 | slave_data->ifphy = devm_of_phy_get(&pdev->dev, slave_node, | ||
3158 | NULL); | ||
3159 | if (!IS_ENABLED(CONFIG_TI_CPSW_PHY_SEL) && | ||
3160 | IS_ERR(slave_data->ifphy)) { | ||
3161 | ret = PTR_ERR(slave_data->ifphy); | ||
3162 | dev_err(&pdev->dev, | ||
3163 | "%d: Error retrieving port phy: %d\n", i, ret); | ||
3164 | return ret; | ||
3165 | } | ||
3166 | |||
3150 | slave_data->phy_node = of_parse_phandle(slave_node, | 3167 | slave_data->phy_node = of_parse_phandle(slave_node, |
3151 | "phy-handle", 0); | 3168 | "phy-handle", 0); |
3152 | parp = of_get_property(slave_node, "phy_id", &lenp); | 3169 | parp = of_get_property(slave_node, "phy_id", &lenp); |
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 60f949e2a684..250abe290ca1 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig | |||
@@ -15,6 +15,14 @@ config GENERIC_PHY | |||
15 | phy users can obtain reference to the PHY. All the users of this | 15 | phy users can obtain reference to the PHY. All the users of this |
16 | framework should select this config. | 16 | framework should select this config. |
17 | 17 | ||
18 | config GENERIC_PHY_MIPI_DPHY | ||
19 | bool | ||
20 | help | ||
21 | Generic MIPI D-PHY support. | ||
22 | |||
23 | Provides a number of helpers a core functions for MIPI D-PHY | ||
24 | drivers to us. | ||
25 | |||
18 | config PHY_LPC18XX_USB_OTG | 26 | config PHY_LPC18XX_USB_OTG |
19 | tristate "NXP LPC18xx/43xx SoC USB OTG PHY driver" | 27 | tristate "NXP LPC18xx/43xx SoC USB OTG PHY driver" |
20 | depends on OF && (ARCH_LPC18XX || COMPILE_TEST) | 28 | depends on OF && (ARCH_LPC18XX || COMPILE_TEST) |
@@ -44,6 +52,7 @@ source "drivers/phy/allwinner/Kconfig" | |||
44 | source "drivers/phy/amlogic/Kconfig" | 52 | source "drivers/phy/amlogic/Kconfig" |
45 | source "drivers/phy/broadcom/Kconfig" | 53 | source "drivers/phy/broadcom/Kconfig" |
46 | source "drivers/phy/cadence/Kconfig" | 54 | source "drivers/phy/cadence/Kconfig" |
55 | source "drivers/phy/freescale/Kconfig" | ||
47 | source "drivers/phy/hisilicon/Kconfig" | 56 | source "drivers/phy/hisilicon/Kconfig" |
48 | source "drivers/phy/lantiq/Kconfig" | 57 | source "drivers/phy/lantiq/Kconfig" |
49 | source "drivers/phy/marvell/Kconfig" | 58 | source "drivers/phy/marvell/Kconfig" |
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 0301e25d07c1..0d9fddc498a6 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile | |||
@@ -4,6 +4,7 @@ | |||
4 | # | 4 | # |
5 | 5 | ||
6 | obj-$(CONFIG_GENERIC_PHY) += phy-core.o | 6 | obj-$(CONFIG_GENERIC_PHY) += phy-core.o |
7 | obj-$(CONFIG_GENERIC_PHY_MIPI_DPHY) += phy-core-mipi-dphy.o | ||
7 | obj-$(CONFIG_PHY_LPC18XX_USB_OTG) += phy-lpc18xx-usb-otg.o | 8 | obj-$(CONFIG_PHY_LPC18XX_USB_OTG) += phy-lpc18xx-usb-otg.o |
8 | obj-$(CONFIG_PHY_XGENE) += phy-xgene.o | 9 | obj-$(CONFIG_PHY_XGENE) += phy-xgene.o |
9 | obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o | 10 | obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o |
@@ -16,6 +17,7 @@ obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ | |||
16 | obj-$(CONFIG_ARCH_TEGRA) += tegra/ | 17 | obj-$(CONFIG_ARCH_TEGRA) += tegra/ |
17 | obj-y += broadcom/ \ | 18 | obj-y += broadcom/ \ |
18 | cadence/ \ | 19 | cadence/ \ |
20 | freescale/ \ | ||
19 | hisilicon/ \ | 21 | hisilicon/ \ |
20 | marvell/ \ | 22 | marvell/ \ |
21 | motorola/ \ | 23 | motorola/ \ |
diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c index d4dcd39b8d76..5163097b43df 100644 --- a/drivers/phy/allwinner/phy-sun4i-usb.c +++ b/drivers/phy/allwinner/phy-sun4i-usb.c | |||
@@ -115,6 +115,7 @@ enum sun4i_usb_phy_type { | |||
115 | sun8i_r40_phy, | 115 | sun8i_r40_phy, |
116 | sun8i_v3s_phy, | 116 | sun8i_v3s_phy, |
117 | sun50i_a64_phy, | 117 | sun50i_a64_phy, |
118 | sun50i_h6_phy, | ||
118 | }; | 119 | }; |
119 | 120 | ||
120 | struct sun4i_usb_phy_cfg { | 121 | struct sun4i_usb_phy_cfg { |
@@ -126,6 +127,7 @@ struct sun4i_usb_phy_cfg { | |||
126 | bool dedicated_clocks; | 127 | bool dedicated_clocks; |
127 | bool enable_pmu_unk1; | 128 | bool enable_pmu_unk1; |
128 | bool phy0_dual_route; | 129 | bool phy0_dual_route; |
130 | int missing_phys; | ||
129 | }; | 131 | }; |
130 | 132 | ||
131 | struct sun4i_usb_phy_data { | 133 | struct sun4i_usb_phy_data { |
@@ -294,7 +296,8 @@ static int sun4i_usb_phy_init(struct phy *_phy) | |||
294 | return ret; | 296 | return ret; |
295 | } | 297 | } |
296 | 298 | ||
297 | if (data->cfg->type == sun8i_a83t_phy) { | 299 | if (data->cfg->type == sun8i_a83t_phy || |
300 | data->cfg->type == sun50i_h6_phy) { | ||
298 | if (phy->index == 0) { | 301 | if (phy->index == 0) { |
299 | val = readl(data->base + data->cfg->phyctl_offset); | 302 | val = readl(data->base + data->cfg->phyctl_offset); |
300 | val |= PHY_CTL_VBUSVLDEXT; | 303 | val |= PHY_CTL_VBUSVLDEXT; |
@@ -343,7 +346,8 @@ static int sun4i_usb_phy_exit(struct phy *_phy) | |||
343 | struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy); | 346 | struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy); |
344 | 347 | ||
345 | if (phy->index == 0) { | 348 | if (phy->index == 0) { |
346 | if (data->cfg->type == sun8i_a83t_phy) { | 349 | if (data->cfg->type == sun8i_a83t_phy || |
350 | data->cfg->type == sun50i_h6_phy) { | ||
347 | void __iomem *phyctl = data->base + | 351 | void __iomem *phyctl = data->base + |
348 | data->cfg->phyctl_offset; | 352 | data->cfg->phyctl_offset; |
349 | 353 | ||
@@ -474,7 +478,8 @@ static int sun4i_usb_phy_power_off(struct phy *_phy) | |||
474 | return 0; | 478 | return 0; |
475 | } | 479 | } |
476 | 480 | ||
477 | static int sun4i_usb_phy_set_mode(struct phy *_phy, enum phy_mode mode) | 481 | static int sun4i_usb_phy_set_mode(struct phy *_phy, |
482 | enum phy_mode mode, int submode) | ||
478 | { | 483 | { |
479 | struct sun4i_usb_phy *phy = phy_get_drvdata(_phy); | 484 | struct sun4i_usb_phy *phy = phy_get_drvdata(_phy); |
480 | struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy); | 485 | struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy); |
@@ -646,6 +651,9 @@ static struct phy *sun4i_usb_phy_xlate(struct device *dev, | |||
646 | if (args->args[0] >= data->cfg->num_phys) | 651 | if (args->args[0] >= data->cfg->num_phys) |
647 | return ERR_PTR(-ENODEV); | 652 | return ERR_PTR(-ENODEV); |
648 | 653 | ||
654 | if (data->cfg->missing_phys & BIT(args->args[0])) | ||
655 | return ERR_PTR(-ENODEV); | ||
656 | |||
649 | return data->phys[args->args[0]].phy; | 657 | return data->phys[args->args[0]].phy; |
650 | } | 658 | } |
651 | 659 | ||
@@ -741,6 +749,9 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) | |||
741 | struct sun4i_usb_phy *phy = data->phys + i; | 749 | struct sun4i_usb_phy *phy = data->phys + i; |
742 | char name[16]; | 750 | char name[16]; |
743 | 751 | ||
752 | if (data->cfg->missing_phys & BIT(i)) | ||
753 | continue; | ||
754 | |||
744 | snprintf(name, sizeof(name), "usb%d_vbus", i); | 755 | snprintf(name, sizeof(name), "usb%d_vbus", i); |
745 | phy->vbus = devm_regulator_get_optional(dev, name); | 756 | phy->vbus = devm_regulator_get_optional(dev, name); |
746 | if (IS_ERR(phy->vbus)) { | 757 | if (IS_ERR(phy->vbus)) { |
@@ -952,6 +963,17 @@ static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = { | |||
952 | .phy0_dual_route = true, | 963 | .phy0_dual_route = true, |
953 | }; | 964 | }; |
954 | 965 | ||
966 | static const struct sun4i_usb_phy_cfg sun50i_h6_cfg = { | ||
967 | .num_phys = 4, | ||
968 | .type = sun50i_h6_phy, | ||
969 | .disc_thresh = 3, | ||
970 | .phyctl_offset = REG_PHYCTL_A33, | ||
971 | .dedicated_clocks = true, | ||
972 | .enable_pmu_unk1 = true, | ||
973 | .phy0_dual_route = true, | ||
974 | .missing_phys = BIT(1) | BIT(2), | ||
975 | }; | ||
976 | |||
955 | static const struct of_device_id sun4i_usb_phy_of_match[] = { | 977 | static const struct of_device_id sun4i_usb_phy_of_match[] = { |
956 | { .compatible = "allwinner,sun4i-a10-usb-phy", .data = &sun4i_a10_cfg }, | 978 | { .compatible = "allwinner,sun4i-a10-usb-phy", .data = &sun4i_a10_cfg }, |
957 | { .compatible = "allwinner,sun5i-a13-usb-phy", .data = &sun5i_a13_cfg }, | 979 | { .compatible = "allwinner,sun5i-a13-usb-phy", .data = &sun5i_a13_cfg }, |
@@ -965,6 +987,7 @@ static const struct of_device_id sun4i_usb_phy_of_match[] = { | |||
965 | { .compatible = "allwinner,sun8i-v3s-usb-phy", .data = &sun8i_v3s_cfg }, | 987 | { .compatible = "allwinner,sun8i-v3s-usb-phy", .data = &sun8i_v3s_cfg }, |
966 | { .compatible = "allwinner,sun50i-a64-usb-phy", | 988 | { .compatible = "allwinner,sun50i-a64-usb-phy", |
967 | .data = &sun50i_a64_cfg}, | 989 | .data = &sun50i_a64_cfg}, |
990 | { .compatible = "allwinner,sun50i-h6-usb-phy", .data = &sun50i_h6_cfg }, | ||
968 | { }, | 991 | { }, |
969 | }; | 992 | }; |
970 | MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match); | 993 | MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match); |
diff --git a/drivers/phy/amlogic/phy-meson-gxl-usb2.c b/drivers/phy/amlogic/phy-meson-gxl-usb2.c index 9f9b5414b97a..148ef0bdb9c1 100644 --- a/drivers/phy/amlogic/phy-meson-gxl-usb2.c +++ b/drivers/phy/amlogic/phy-meson-gxl-usb2.c | |||
@@ -152,7 +152,8 @@ static int phy_meson_gxl_usb2_reset(struct phy *phy) | |||
152 | return 0; | 152 | return 0; |
153 | } | 153 | } |
154 | 154 | ||
155 | static int phy_meson_gxl_usb2_set_mode(struct phy *phy, enum phy_mode mode) | 155 | static int phy_meson_gxl_usb2_set_mode(struct phy *phy, |
156 | enum phy_mode mode, int submode) | ||
156 | { | 157 | { |
157 | struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy); | 158 | struct phy_meson_gxl_usb2_priv *priv = phy_get_drvdata(phy); |
158 | 159 | ||
@@ -209,7 +210,7 @@ static int phy_meson_gxl_usb2_power_on(struct phy *phy) | |||
209 | /* power on the PHY by taking it out of reset mode */ | 210 | /* power on the PHY by taking it out of reset mode */ |
210 | regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_POWER_ON_RESET, 0); | 211 | regmap_update_bits(priv->regmap, U2P_R0, U2P_R0_POWER_ON_RESET, 0); |
211 | 212 | ||
212 | ret = phy_meson_gxl_usb2_set_mode(phy, priv->mode); | 213 | ret = phy_meson_gxl_usb2_set_mode(phy, priv->mode, 0); |
213 | if (ret) { | 214 | if (ret) { |
214 | phy_meson_gxl_usb2_power_off(phy); | 215 | phy_meson_gxl_usb2_power_off(phy); |
215 | 216 | ||
diff --git a/drivers/phy/amlogic/phy-meson-gxl-usb3.c b/drivers/phy/amlogic/phy-meson-gxl-usb3.c index d37d94ddf9c0..c0e9e4c16149 100644 --- a/drivers/phy/amlogic/phy-meson-gxl-usb3.c +++ b/drivers/phy/amlogic/phy-meson-gxl-usb3.c | |||
@@ -119,7 +119,8 @@ static int phy_meson_gxl_usb3_power_off(struct phy *phy) | |||
119 | return 0; | 119 | return 0; |
120 | } | 120 | } |
121 | 121 | ||
122 | static int phy_meson_gxl_usb3_set_mode(struct phy *phy, enum phy_mode mode) | 122 | static int phy_meson_gxl_usb3_set_mode(struct phy *phy, |
123 | enum phy_mode mode, int submode) | ||
123 | { | 124 | { |
124 | struct phy_meson_gxl_usb3_priv *priv = phy_get_drvdata(phy); | 125 | struct phy_meson_gxl_usb3_priv *priv = phy_get_drvdata(phy); |
125 | 126 | ||
@@ -164,7 +165,7 @@ static int phy_meson_gxl_usb3_init(struct phy *phy) | |||
164 | if (ret) | 165 | if (ret) |
165 | goto err_disable_clk_phy; | 166 | goto err_disable_clk_phy; |
166 | 167 | ||
167 | ret = phy_meson_gxl_usb3_set_mode(phy, priv->mode); | 168 | ret = phy_meson_gxl_usb3_set_mode(phy, priv->mode, 0); |
168 | if (ret) | 169 | if (ret) |
169 | goto err_disable_clk_peripheral; | 170 | goto err_disable_clk_peripheral; |
170 | 171 | ||
diff --git a/drivers/phy/cadence/Kconfig b/drivers/phy/cadence/Kconfig index 57fff7de4031..2b8c0851ff33 100644 --- a/drivers/phy/cadence/Kconfig +++ b/drivers/phy/cadence/Kconfig | |||
@@ -1,5 +1,5 @@ | |||
1 | # | 1 | # |
2 | # Phy driver for Cadence MHDP DisplayPort controller | 2 | # Phy drivers for Cadence PHYs |
3 | # | 3 | # |
4 | config PHY_CADENCE_DP | 4 | config PHY_CADENCE_DP |
5 | tristate "Cadence MHDP DisplayPort PHY driver" | 5 | tristate "Cadence MHDP DisplayPort PHY driver" |
@@ -8,3 +8,10 @@ config PHY_CADENCE_DP | |||
8 | select GENERIC_PHY | 8 | select GENERIC_PHY |
9 | help | 9 | help |
10 | Support for Cadence MHDP DisplayPort PHY. | 10 | Support for Cadence MHDP DisplayPort PHY. |
11 | |||
12 | config PHY_CADENCE_SIERRA | ||
13 | tristate "Cadence Sierra PHY Driver" | ||
14 | depends on OF && HAS_IOMEM && RESET_CONTROLLER | ||
15 | select GENERIC_PHY | ||
16 | help | ||
17 | Enable this to support the Cadence Sierra PHY driver \ No newline at end of file | ||
diff --git a/drivers/phy/cadence/Makefile b/drivers/phy/cadence/Makefile index e5b0a11cf28a..412349af0492 100644 --- a/drivers/phy/cadence/Makefile +++ b/drivers/phy/cadence/Makefile | |||
@@ -1 +1,2 @@ | |||
1 | obj-$(CONFIG_PHY_CADENCE_DP) += phy-cadence-dp.o | 1 | obj-$(CONFIG_PHY_CADENCE_DP) += phy-cadence-dp.o |
2 | obj-$(CONFIG_PHY_CADENCE_SIERRA) += phy-cadence-sierra.o | ||
diff --git a/drivers/phy/cadence/phy-cadence-sierra.c b/drivers/phy/cadence/phy-cadence-sierra.c new file mode 100644 index 000000000000..de10402f2931 --- /dev/null +++ b/drivers/phy/cadence/phy-cadence-sierra.c | |||
@@ -0,0 +1,395 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * Cadence Sierra PHY Driver | ||
4 | * | ||
5 | * Copyright (c) 2018 Cadence Design Systems | ||
6 | * Author: Alan Douglas <adouglas@cadence.com> | ||
7 | * | ||
8 | */ | ||
9 | #include <linux/clk.h> | ||
10 | #include <linux/delay.h> | ||
11 | #include <linux/err.h> | ||
12 | #include <linux/io.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/phy/phy.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/pm_runtime.h> | ||
17 | #include <linux/regmap.h> | ||
18 | #include <linux/reset.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/of.h> | ||
21 | #include <linux/of_platform.h> | ||
22 | #include <dt-bindings/phy/phy.h> | ||
23 | |||
24 | /* PHY register offsets */ | ||
25 | #define SIERRA_PHY_PLL_CFG (0xc00e << 2) | ||
26 | #define SIERRA_DET_STANDEC_A (0x4000 << 2) | ||
27 | #define SIERRA_DET_STANDEC_B (0x4001 << 2) | ||
28 | #define SIERRA_DET_STANDEC_C (0x4002 << 2) | ||
29 | #define SIERRA_DET_STANDEC_D (0x4003 << 2) | ||
30 | #define SIERRA_DET_STANDEC_E (0x4004 << 2) | ||
31 | #define SIERRA_PSM_LANECAL (0x4008 << 2) | ||
32 | #define SIERRA_PSM_DIAG (0x4015 << 2) | ||
33 | #define SIERRA_PSC_TX_A0 (0x4028 << 2) | ||
34 | #define SIERRA_PSC_TX_A1 (0x4029 << 2) | ||
35 | #define SIERRA_PSC_TX_A2 (0x402A << 2) | ||
36 | #define SIERRA_PSC_TX_A3 (0x402B << 2) | ||
37 | #define SIERRA_PSC_RX_A0 (0x4030 << 2) | ||
38 | #define SIERRA_PSC_RX_A1 (0x4031 << 2) | ||
39 | #define SIERRA_PSC_RX_A2 (0x4032 << 2) | ||
40 | #define SIERRA_PSC_RX_A3 (0x4033 << 2) | ||
41 | #define SIERRA_PLLCTRL_SUBRATE (0x403A << 2) | ||
42 | #define SIERRA_PLLCTRL_GEN_D (0x403E << 2) | ||
43 | #define SIERRA_DRVCTRL_ATTEN (0x406A << 2) | ||
44 | #define SIERRA_CLKPATHCTRL_TMR (0x4081 << 2) | ||
45 | #define SIERRA_RX_CREQ_FLTR_A_MODE1 (0x4087 << 2) | ||
46 | #define SIERRA_RX_CREQ_FLTR_A_MODE0 (0x4088 << 2) | ||
47 | #define SIERRA_CREQ_CCLKDET_MODE01 (0x408E << 2) | ||
48 | #define SIERRA_RX_CTLE_MAINTENANCE (0x4091 << 2) | ||
49 | #define SIERRA_CREQ_FSMCLK_SEL (0x4092 << 2) | ||
50 | #define SIERRA_CTLELUT_CTRL (0x4098 << 2) | ||
51 | #define SIERRA_DFE_ECMP_RATESEL (0x40C0 << 2) | ||
52 | #define SIERRA_DFE_SMP_RATESEL (0x40C1 << 2) | ||
53 | #define SIERRA_DEQ_VGATUNE_CTRL (0x40E1 << 2) | ||
54 | #define SIERRA_TMRVAL_MODE3 (0x416E << 2) | ||
55 | #define SIERRA_TMRVAL_MODE2 (0x416F << 2) | ||
56 | #define SIERRA_TMRVAL_MODE1 (0x4170 << 2) | ||
57 | #define SIERRA_TMRVAL_MODE0 (0x4171 << 2) | ||
58 | #define SIERRA_PICNT_MODE1 (0x4174 << 2) | ||
59 | #define SIERRA_CPI_OUTBUF_RATESEL (0x417C << 2) | ||
60 | #define SIERRA_LFPSFILT_NS (0x418A << 2) | ||
61 | #define SIERRA_LFPSFILT_RD (0x418B << 2) | ||
62 | #define SIERRA_LFPSFILT_MP (0x418C << 2) | ||
63 | #define SIERRA_SDFILT_H2L_A (0x4191 << 2) | ||
64 | |||
65 | #define SIERRA_MACRO_ID 0x00007364 | ||
66 | #define SIERRA_MAX_LANES 4 | ||
67 | |||
68 | struct cdns_sierra_inst { | ||
69 | struct phy *phy; | ||
70 | u32 phy_type; | ||
71 | u32 num_lanes; | ||
72 | u32 mlane; | ||
73 | struct reset_control *lnk_rst; | ||
74 | }; | ||
75 | |||
76 | struct cdns_reg_pairs { | ||
77 | u16 val; | ||
78 | u32 off; | ||
79 | }; | ||
80 | |||
81 | struct cdns_sierra_data { | ||
82 | u32 id_value; | ||
83 | u32 pcie_regs; | ||
84 | u32 usb_regs; | ||
85 | struct cdns_reg_pairs *pcie_vals; | ||
86 | struct cdns_reg_pairs *usb_vals; | ||
87 | }; | ||
88 | |||
89 | struct cdns_sierra_phy { | ||
90 | struct device *dev; | ||
91 | void __iomem *base; | ||
92 | struct cdns_sierra_data *init_data; | ||
93 | struct cdns_sierra_inst phys[SIERRA_MAX_LANES]; | ||
94 | struct reset_control *phy_rst; | ||
95 | struct reset_control *apb_rst; | ||
96 | struct clk *clk; | ||
97 | int nsubnodes; | ||
98 | bool autoconf; | ||
99 | }; | ||
100 | |||
101 | static void cdns_sierra_phy_init(struct phy *gphy) | ||
102 | { | ||
103 | struct cdns_sierra_inst *ins = phy_get_drvdata(gphy); | ||
104 | struct cdns_sierra_phy *phy = dev_get_drvdata(gphy->dev.parent); | ||
105 | int i, j; | ||
106 | struct cdns_reg_pairs *vals; | ||
107 | u32 num_regs; | ||
108 | |||
109 | if (ins->phy_type == PHY_TYPE_PCIE) { | ||
110 | num_regs = phy->init_data->pcie_regs; | ||
111 | vals = phy->init_data->pcie_vals; | ||
112 | } else if (ins->phy_type == PHY_TYPE_USB3) { | ||
113 | num_regs = phy->init_data->usb_regs; | ||
114 | vals = phy->init_data->usb_vals; | ||
115 | } else { | ||
116 | return; | ||
117 | } | ||
118 | for (i = 0; i < ins->num_lanes; i++) | ||
119 | for (j = 0; j < num_regs ; j++) | ||
120 | writel(vals[j].val, phy->base + | ||
121 | vals[j].off + (i + ins->mlane) * 0x800); | ||
122 | } | ||
123 | |||
124 | static int cdns_sierra_phy_on(struct phy *gphy) | ||
125 | { | ||
126 | struct cdns_sierra_inst *ins = phy_get_drvdata(gphy); | ||
127 | |||
128 | /* Take the PHY lane group out of reset */ | ||
129 | return reset_control_deassert(ins->lnk_rst); | ||
130 | } | ||
131 | |||
132 | static int cdns_sierra_phy_off(struct phy *gphy) | ||
133 | { | ||
134 | struct cdns_sierra_inst *ins = phy_get_drvdata(gphy); | ||
135 | |||
136 | return reset_control_assert(ins->lnk_rst); | ||
137 | } | ||
138 | |||
139 | static const struct phy_ops ops = { | ||
140 | .power_on = cdns_sierra_phy_on, | ||
141 | .power_off = cdns_sierra_phy_off, | ||
142 | .owner = THIS_MODULE, | ||
143 | }; | ||
144 | |||
145 | static int cdns_sierra_get_optional(struct cdns_sierra_inst *inst, | ||
146 | struct device_node *child) | ||
147 | { | ||
148 | if (of_property_read_u32(child, "reg", &inst->mlane)) | ||
149 | return -EINVAL; | ||
150 | |||
151 | if (of_property_read_u32(child, "cdns,num-lanes", &inst->num_lanes)) | ||
152 | return -EINVAL; | ||
153 | |||
154 | if (of_property_read_u32(child, "cdns,phy-type", &inst->phy_type)) | ||
155 | return -EINVAL; | ||
156 | |||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | static const struct of_device_id cdns_sierra_id_table[]; | ||
161 | |||
162 | static int cdns_sierra_phy_probe(struct platform_device *pdev) | ||
163 | { | ||
164 | struct cdns_sierra_phy *sp; | ||
165 | struct phy_provider *phy_provider; | ||
166 | struct device *dev = &pdev->dev; | ||
167 | const struct of_device_id *match; | ||
168 | struct resource *res; | ||
169 | int i, ret, node = 0; | ||
170 | struct device_node *dn = dev->of_node, *child; | ||
171 | |||
172 | if (of_get_child_count(dn) == 0) | ||
173 | return -ENODEV; | ||
174 | |||
175 | sp = devm_kzalloc(dev, sizeof(*sp), GFP_KERNEL); | ||
176 | if (!sp) | ||
177 | return -ENOMEM; | ||
178 | dev_set_drvdata(dev, sp); | ||
179 | sp->dev = dev; | ||
180 | |||
181 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
182 | sp->base = devm_ioremap_resource(dev, res); | ||
183 | if (IS_ERR(sp->base)) { | ||
184 | dev_err(dev, "missing \"reg\"\n"); | ||
185 | return PTR_ERR(sp->base); | ||
186 | } | ||
187 | |||
188 | /* Get init data for this PHY */ | ||
189 | match = of_match_device(cdns_sierra_id_table, dev); | ||
190 | if (!match) | ||
191 | return -EINVAL; | ||
192 | sp->init_data = (struct cdns_sierra_data *)match->data; | ||
193 | |||
194 | platform_set_drvdata(pdev, sp); | ||
195 | |||
196 | sp->clk = devm_clk_get(dev, "phy_clk"); | ||
197 | if (IS_ERR(sp->clk)) { | ||
198 | dev_err(dev, "failed to get clock phy_clk\n"); | ||
199 | return PTR_ERR(sp->clk); | ||
200 | } | ||
201 | |||
202 | sp->phy_rst = devm_reset_control_get(dev, "sierra_reset"); | ||
203 | if (IS_ERR(sp->phy_rst)) { | ||
204 | dev_err(dev, "failed to get reset\n"); | ||
205 | return PTR_ERR(sp->phy_rst); | ||
206 | } | ||
207 | |||
208 | sp->apb_rst = devm_reset_control_get(dev, "sierra_apb"); | ||
209 | if (IS_ERR(sp->apb_rst)) { | ||
210 | dev_err(dev, "failed to get apb reset\n"); | ||
211 | return PTR_ERR(sp->apb_rst); | ||
212 | } | ||
213 | |||
214 | ret = clk_prepare_enable(sp->clk); | ||
215 | if (ret) | ||
216 | return ret; | ||
217 | |||
218 | /* Enable APB */ | ||
219 | reset_control_deassert(sp->apb_rst); | ||
220 | |||
221 | /* Check that PHY is present */ | ||
222 | if (sp->init_data->id_value != readl(sp->base)) { | ||
223 | ret = -EINVAL; | ||
224 | goto clk_disable; | ||
225 | } | ||
226 | |||
227 | sp->autoconf = of_property_read_bool(dn, "cdns,autoconf"); | ||
228 | |||
229 | for_each_available_child_of_node(dn, child) { | ||
230 | struct phy *gphy; | ||
231 | |||
232 | sp->phys[node].lnk_rst = | ||
233 | of_reset_control_get_exclusive_by_index(child, 0); | ||
234 | |||
235 | if (IS_ERR(sp->phys[node].lnk_rst)) { | ||
236 | dev_err(dev, "failed to get reset %s\n", | ||
237 | child->full_name); | ||
238 | ret = PTR_ERR(sp->phys[node].lnk_rst); | ||
239 | goto put_child2; | ||
240 | } | ||
241 | |||
242 | if (!sp->autoconf) { | ||
243 | ret = cdns_sierra_get_optional(&sp->phys[node], child); | ||
244 | if (ret) { | ||
245 | dev_err(dev, "missing property in node %s\n", | ||
246 | child->name); | ||
247 | goto put_child; | ||
248 | } | ||
249 | } | ||
250 | |||
251 | gphy = devm_phy_create(dev, child, &ops); | ||
252 | |||
253 | if (IS_ERR(gphy)) { | ||
254 | ret = PTR_ERR(gphy); | ||
255 | goto put_child; | ||
256 | } | ||
257 | sp->phys[node].phy = gphy; | ||
258 | phy_set_drvdata(gphy, &sp->phys[node]); | ||
259 | |||
260 | /* Initialise the PHY registers, unless auto configured */ | ||
261 | if (!sp->autoconf) | ||
262 | cdns_sierra_phy_init(gphy); | ||
263 | |||
264 | node++; | ||
265 | } | ||
266 | sp->nsubnodes = node; | ||
267 | |||
268 | /* If more than one subnode, configure the PHY as multilink */ | ||
269 | if (!sp->autoconf && sp->nsubnodes > 1) | ||
270 | writel(2, sp->base + SIERRA_PHY_PLL_CFG); | ||
271 | |||
272 | pm_runtime_enable(dev); | ||
273 | phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); | ||
274 | reset_control_deassert(sp->phy_rst); | ||
275 | return PTR_ERR_OR_ZERO(phy_provider); | ||
276 | |||
277 | put_child: | ||
278 | node++; | ||
279 | put_child2: | ||
280 | for (i = 0; i < node; i++) | ||
281 | reset_control_put(sp->phys[i].lnk_rst); | ||
282 | of_node_put(child); | ||
283 | clk_disable: | ||
284 | clk_disable_unprepare(sp->clk); | ||
285 | reset_control_assert(sp->apb_rst); | ||
286 | return ret; | ||
287 | } | ||
288 | |||
289 | static int cdns_sierra_phy_remove(struct platform_device *pdev) | ||
290 | { | ||
291 | struct cdns_sierra_phy *phy = dev_get_drvdata(pdev->dev.parent); | ||
292 | int i; | ||
293 | |||
294 | reset_control_assert(phy->phy_rst); | ||
295 | reset_control_assert(phy->apb_rst); | ||
296 | pm_runtime_disable(&pdev->dev); | ||
297 | |||
298 | /* | ||
299 | * The device level resets will be put automatically. | ||
300 | * Need to put the subnode resets here though. | ||
301 | */ | ||
302 | for (i = 0; i < phy->nsubnodes; i++) { | ||
303 | reset_control_assert(phy->phys[i].lnk_rst); | ||
304 | reset_control_put(phy->phys[i].lnk_rst); | ||
305 | } | ||
306 | return 0; | ||
307 | } | ||
308 | |||
309 | static struct cdns_reg_pairs cdns_usb_regs[] = { | ||
310 | /* | ||
311 | * Write USB configuration parameters to the PHY. | ||
312 | * These values are specific to this specific hardware | ||
313 | * configuration. | ||
314 | */ | ||
315 | {0xFE0A, SIERRA_DET_STANDEC_A}, | ||
316 | {0x000F, SIERRA_DET_STANDEC_B}, | ||
317 | {0x55A5, SIERRA_DET_STANDEC_C}, | ||
318 | {0x69AD, SIERRA_DET_STANDEC_D}, | ||
319 | {0x0241, SIERRA_DET_STANDEC_E}, | ||
320 | {0x0110, SIERRA_PSM_LANECAL}, | ||
321 | {0xCF00, SIERRA_PSM_DIAG}, | ||
322 | {0x001F, SIERRA_PSC_TX_A0}, | ||
323 | {0x0007, SIERRA_PSC_TX_A1}, | ||
324 | {0x0003, SIERRA_PSC_TX_A2}, | ||
325 | {0x0003, SIERRA_PSC_TX_A3}, | ||
326 | {0x0FFF, SIERRA_PSC_RX_A0}, | ||
327 | {0x0003, SIERRA_PSC_RX_A1}, | ||
328 | {0x0003, SIERRA_PSC_RX_A2}, | ||
329 | {0x0001, SIERRA_PSC_RX_A3}, | ||
330 | {0x0001, SIERRA_PLLCTRL_SUBRATE}, | ||
331 | {0x0406, SIERRA_PLLCTRL_GEN_D}, | ||
332 | {0x0000, SIERRA_DRVCTRL_ATTEN}, | ||
333 | {0x823E, SIERRA_CLKPATHCTRL_TMR}, | ||
334 | {0x078F, SIERRA_RX_CREQ_FLTR_A_MODE1}, | ||
335 | {0x078F, SIERRA_RX_CREQ_FLTR_A_MODE0}, | ||
336 | {0x7B3C, SIERRA_CREQ_CCLKDET_MODE01}, | ||
337 | {0x023C, SIERRA_RX_CTLE_MAINTENANCE}, | ||
338 | {0x3232, SIERRA_CREQ_FSMCLK_SEL}, | ||
339 | {0x8452, SIERRA_CTLELUT_CTRL}, | ||
340 | {0x4121, SIERRA_DFE_ECMP_RATESEL}, | ||
341 | {0x4121, SIERRA_DFE_SMP_RATESEL}, | ||
342 | {0x9999, SIERRA_DEQ_VGATUNE_CTRL}, | ||
343 | {0x0330, SIERRA_TMRVAL_MODE0}, | ||
344 | {0x01FF, SIERRA_PICNT_MODE1}, | ||
345 | {0x0009, SIERRA_CPI_OUTBUF_RATESEL}, | ||
346 | {0x000F, SIERRA_LFPSFILT_NS}, | ||
347 | {0x0009, SIERRA_LFPSFILT_RD}, | ||
348 | {0x0001, SIERRA_LFPSFILT_MP}, | ||
349 | {0x8013, SIERRA_SDFILT_H2L_A}, | ||
350 | {0x0400, SIERRA_TMRVAL_MODE1}, | ||
351 | }; | ||
352 | |||
353 | static struct cdns_reg_pairs cdns_pcie_regs[] = { | ||
354 | /* | ||
355 | * Write PCIe configuration parameters to the PHY. | ||
356 | * These values are specific to this specific hardware | ||
357 | * configuration. | ||
358 | */ | ||
359 | {0x891f, SIERRA_DET_STANDEC_D}, | ||
360 | {0x0053, SIERRA_DET_STANDEC_E}, | ||
361 | {0x0400, SIERRA_TMRVAL_MODE2}, | ||
362 | {0x0200, SIERRA_TMRVAL_MODE3}, | ||
363 | }; | ||
364 | |||
365 | static const struct cdns_sierra_data cdns_map_sierra = { | ||
366 | SIERRA_MACRO_ID, | ||
367 | ARRAY_SIZE(cdns_pcie_regs), | ||
368 | ARRAY_SIZE(cdns_usb_regs), | ||
369 | cdns_pcie_regs, | ||
370 | cdns_usb_regs | ||
371 | }; | ||
372 | |||
373 | static const struct of_device_id cdns_sierra_id_table[] = { | ||
374 | { | ||
375 | .compatible = "cdns,sierra-phy-t0", | ||
376 | .data = &cdns_map_sierra, | ||
377 | }, | ||
378 | {} | ||
379 | }; | ||
380 | MODULE_DEVICE_TABLE(of, cdns_sierra_id_table); | ||
381 | |||
382 | static struct platform_driver cdns_sierra_driver = { | ||
383 | .probe = cdns_sierra_phy_probe, | ||
384 | .remove = cdns_sierra_phy_remove, | ||
385 | .driver = { | ||
386 | .name = "cdns-sierra-phy", | ||
387 | .of_match_table = cdns_sierra_id_table, | ||
388 | }, | ||
389 | }; | ||
390 | module_platform_driver(cdns_sierra_driver); | ||
391 | |||
392 | MODULE_ALIAS("platform:cdns_sierra"); | ||
393 | MODULE_AUTHOR("Cadence Design Systems"); | ||
394 | MODULE_DESCRIPTION("CDNS sierra phy driver"); | ||
395 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/phy/freescale/Kconfig b/drivers/phy/freescale/Kconfig new file mode 100644 index 000000000000..f050bd4e97e0 --- /dev/null +++ b/drivers/phy/freescale/Kconfig | |||
@@ -0,0 +1,5 @@ | |||
1 | config PHY_FSL_IMX8MQ_USB | ||
2 | tristate "Freescale i.MX8M USB3 PHY" | ||
3 | depends on OF && HAS_IOMEM | ||
4 | select GENERIC_PHY | ||
5 | default SOC_IMX8MQ | ||
diff --git a/drivers/phy/freescale/Makefile b/drivers/phy/freescale/Makefile new file mode 100644 index 000000000000..dc2b3f1f2f80 --- /dev/null +++ b/drivers/phy/freescale/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-$(CONFIG_PHY_FSL_IMX8MQ_USB) += phy-fsl-imx8mq-usb.o | |||
diff --git a/drivers/phy/freescale/phy-fsl-imx8mq-usb.c b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c new file mode 100644 index 000000000000..d6ea5ce8afa5 --- /dev/null +++ b/drivers/phy/freescale/phy-fsl-imx8mq-usb.c | |||
@@ -0,0 +1,127 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0+ | ||
2 | /* Copyright (c) 2017 NXP. */ | ||
3 | |||
4 | #include <linux/clk.h> | ||
5 | #include <linux/io.h> | ||
6 | #include <linux/module.h> | ||
7 | #include <linux/phy/phy.h> | ||
8 | #include <linux/platform_device.h> | ||
9 | |||
10 | #define PHY_CTRL0 0x0 | ||
11 | #define PHY_CTRL0_REF_SSP_EN BIT(2) | ||
12 | |||
13 | #define PHY_CTRL1 0x4 | ||
14 | #define PHY_CTRL1_RESET BIT(0) | ||
15 | #define PHY_CTRL1_COMMONONN BIT(1) | ||
16 | #define PHY_CTRL1_ATERESET BIT(3) | ||
17 | #define PHY_CTRL1_VDATSRCENB0 BIT(19) | ||
18 | #define PHY_CTRL1_VDATDETENB0 BIT(20) | ||
19 | |||
20 | #define PHY_CTRL2 0x8 | ||
21 | #define PHY_CTRL2_TXENABLEN0 BIT(8) | ||
22 | |||
23 | struct imx8mq_usb_phy { | ||
24 | struct phy *phy; | ||
25 | struct clk *clk; | ||
26 | void __iomem *base; | ||
27 | }; | ||
28 | |||
29 | static int imx8mq_usb_phy_init(struct phy *phy) | ||
30 | { | ||
31 | struct imx8mq_usb_phy *imx_phy = phy_get_drvdata(phy); | ||
32 | u32 value; | ||
33 | |||
34 | value = readl(imx_phy->base + PHY_CTRL1); | ||
35 | value &= ~(PHY_CTRL1_VDATSRCENB0 | PHY_CTRL1_VDATDETENB0 | | ||
36 | PHY_CTRL1_COMMONONN); | ||
37 | value |= PHY_CTRL1_RESET | PHY_CTRL1_ATERESET; | ||
38 | writel(value, imx_phy->base + PHY_CTRL1); | ||
39 | |||
40 | value = readl(imx_phy->base + PHY_CTRL0); | ||
41 | value |= PHY_CTRL0_REF_SSP_EN; | ||
42 | writel(value, imx_phy->base + PHY_CTRL0); | ||
43 | |||
44 | value = readl(imx_phy->base + PHY_CTRL2); | ||
45 | value |= PHY_CTRL2_TXENABLEN0; | ||
46 | writel(value, imx_phy->base + PHY_CTRL2); | ||
47 | |||
48 | value = readl(imx_phy->base + PHY_CTRL1); | ||
49 | value &= ~(PHY_CTRL1_RESET | PHY_CTRL1_ATERESET); | ||
50 | writel(value, imx_phy->base + PHY_CTRL1); | ||
51 | |||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | static int imx8mq_phy_power_on(struct phy *phy) | ||
56 | { | ||
57 | struct imx8mq_usb_phy *imx_phy = phy_get_drvdata(phy); | ||
58 | |||
59 | return clk_prepare_enable(imx_phy->clk); | ||
60 | } | ||
61 | |||
62 | static int imx8mq_phy_power_off(struct phy *phy) | ||
63 | { | ||
64 | struct imx8mq_usb_phy *imx_phy = phy_get_drvdata(phy); | ||
65 | |||
66 | clk_disable_unprepare(imx_phy->clk); | ||
67 | |||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | static struct phy_ops imx8mq_usb_phy_ops = { | ||
72 | .init = imx8mq_usb_phy_init, | ||
73 | .power_on = imx8mq_phy_power_on, | ||
74 | .power_off = imx8mq_phy_power_off, | ||
75 | .owner = THIS_MODULE, | ||
76 | }; | ||
77 | |||
78 | static int imx8mq_usb_phy_probe(struct platform_device *pdev) | ||
79 | { | ||
80 | struct phy_provider *phy_provider; | ||
81 | struct device *dev = &pdev->dev; | ||
82 | struct imx8mq_usb_phy *imx_phy; | ||
83 | struct resource *res; | ||
84 | |||
85 | imx_phy = devm_kzalloc(dev, sizeof(*imx_phy), GFP_KERNEL); | ||
86 | if (!imx_phy) | ||
87 | return -ENOMEM; | ||
88 | |||
89 | imx_phy->clk = devm_clk_get(dev, "phy"); | ||
90 | if (IS_ERR(imx_phy->clk)) { | ||
91 | dev_err(dev, "failed to get imx8mq usb phy clock\n"); | ||
92 | return PTR_ERR(imx_phy->clk); | ||
93 | } | ||
94 | |||
95 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
96 | imx_phy->base = devm_ioremap_resource(dev, res); | ||
97 | if (IS_ERR(imx_phy->base)) | ||
98 | return PTR_ERR(imx_phy->base); | ||
99 | |||
100 | imx_phy->phy = devm_phy_create(dev, NULL, &imx8mq_usb_phy_ops); | ||
101 | if (IS_ERR(imx_phy->phy)) | ||
102 | return PTR_ERR(imx_phy->phy); | ||
103 | |||
104 | phy_set_drvdata(imx_phy->phy, imx_phy); | ||
105 | |||
106 | phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); | ||
107 | |||
108 | return PTR_ERR_OR_ZERO(phy_provider); | ||
109 | } | ||
110 | |||
111 | static const struct of_device_id imx8mq_usb_phy_of_match[] = { | ||
112 | {.compatible = "fsl,imx8mq-usb-phy",}, | ||
113 | { }, | ||
114 | }; | ||
115 | MODULE_DEVICE_TABLE(of, imx8mq_usb_phy_of_match); | ||
116 | |||
117 | static struct platform_driver imx8mq_usb_phy_driver = { | ||
118 | .probe = imx8mq_usb_phy_probe, | ||
119 | .driver = { | ||
120 | .name = "imx8mq-usb-phy", | ||
121 | .of_match_table = imx8mq_usb_phy_of_match, | ||
122 | } | ||
123 | }; | ||
124 | module_platform_driver(imx8mq_usb_phy_driver); | ||
125 | |||
126 | MODULE_DESCRIPTION("FSL IMX8MQ USB PHY driver"); | ||
127 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/phy/marvell/phy-mvebu-cp110-comphy.c b/drivers/phy/marvell/phy-mvebu-cp110-comphy.c index 86a5f7b9448b..187cccde53b5 100644 --- a/drivers/phy/marvell/phy-mvebu-cp110-comphy.c +++ b/drivers/phy/marvell/phy-mvebu-cp110-comphy.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/iopoll.h> | 9 | #include <linux/iopoll.h> |
10 | #include <linux/mfd/syscon.h> | 10 | #include <linux/mfd/syscon.h> |
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/phy.h> | ||
12 | #include <linux/phy/phy.h> | 13 | #include <linux/phy/phy.h> |
13 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
14 | #include <linux/regmap.h> | 15 | #include <linux/regmap.h> |
@@ -114,43 +115,45 @@ | |||
114 | #define MVEBU_COMPHY_LANES 6 | 115 | #define MVEBU_COMPHY_LANES 6 |
115 | #define MVEBU_COMPHY_PORTS 3 | 116 | #define MVEBU_COMPHY_PORTS 3 |
116 | 117 | ||
117 | struct mvebu_comhy_conf { | 118 | struct mvebu_comphy_conf { |
118 | enum phy_mode mode; | 119 | enum phy_mode mode; |
120 | int submode; | ||
119 | unsigned lane; | 121 | unsigned lane; |
120 | unsigned port; | 122 | unsigned port; |
121 | u32 mux; | 123 | u32 mux; |
122 | }; | 124 | }; |
123 | 125 | ||
124 | #define MVEBU_COMPHY_CONF(_lane, _port, _mode, _mux) \ | 126 | #define MVEBU_COMPHY_CONF(_lane, _port, _submode, _mux) \ |
125 | { \ | 127 | { \ |
126 | .lane = _lane, \ | 128 | .lane = _lane, \ |
127 | .port = _port, \ | 129 | .port = _port, \ |
128 | .mode = _mode, \ | 130 | .mode = PHY_MODE_ETHERNET, \ |
131 | .submode = _submode, \ | ||
129 | .mux = _mux, \ | 132 | .mux = _mux, \ |
130 | } | 133 | } |
131 | 134 | ||
132 | static const struct mvebu_comhy_conf mvebu_comphy_cp110_modes[] = { | 135 | static const struct mvebu_comphy_conf mvebu_comphy_cp110_modes[] = { |
133 | /* lane 0 */ | 136 | /* lane 0 */ |
134 | MVEBU_COMPHY_CONF(0, 1, PHY_MODE_SGMII, 0x1), | 137 | MVEBU_COMPHY_CONF(0, 1, PHY_INTERFACE_MODE_SGMII, 0x1), |
135 | MVEBU_COMPHY_CONF(0, 1, PHY_MODE_2500SGMII, 0x1), | 138 | MVEBU_COMPHY_CONF(0, 1, PHY_INTERFACE_MODE_2500BASEX, 0x1), |
136 | /* lane 1 */ | 139 | /* lane 1 */ |
137 | MVEBU_COMPHY_CONF(1, 2, PHY_MODE_SGMII, 0x1), | 140 | MVEBU_COMPHY_CONF(1, 2, PHY_INTERFACE_MODE_SGMII, 0x1), |
138 | MVEBU_COMPHY_CONF(1, 2, PHY_MODE_2500SGMII, 0x1), | 141 | MVEBU_COMPHY_CONF(1, 2, PHY_INTERFACE_MODE_2500BASEX, 0x1), |
139 | /* lane 2 */ | 142 | /* lane 2 */ |
140 | MVEBU_COMPHY_CONF(2, 0, PHY_MODE_SGMII, 0x1), | 143 | MVEBU_COMPHY_CONF(2, 0, PHY_INTERFACE_MODE_SGMII, 0x1), |
141 | MVEBU_COMPHY_CONF(2, 0, PHY_MODE_2500SGMII, 0x1), | 144 | MVEBU_COMPHY_CONF(2, 0, PHY_INTERFACE_MODE_2500BASEX, 0x1), |
142 | MVEBU_COMPHY_CONF(2, 0, PHY_MODE_10GKR, 0x1), | 145 | MVEBU_COMPHY_CONF(2, 0, PHY_INTERFACE_MODE_10GKR, 0x1), |
143 | /* lane 3 */ | 146 | /* lane 3 */ |
144 | MVEBU_COMPHY_CONF(3, 1, PHY_MODE_SGMII, 0x2), | 147 | MVEBU_COMPHY_CONF(3, 1, PHY_INTERFACE_MODE_SGMII, 0x2), |
145 | MVEBU_COMPHY_CONF(3, 1, PHY_MODE_2500SGMII, 0x2), | 148 | MVEBU_COMPHY_CONF(3, 1, PHY_INTERFACE_MODE_2500BASEX, 0x2), |
146 | /* lane 4 */ | 149 | /* lane 4 */ |
147 | MVEBU_COMPHY_CONF(4, 0, PHY_MODE_SGMII, 0x2), | 150 | MVEBU_COMPHY_CONF(4, 0, PHY_INTERFACE_MODE_SGMII, 0x2), |
148 | MVEBU_COMPHY_CONF(4, 0, PHY_MODE_2500SGMII, 0x2), | 151 | MVEBU_COMPHY_CONF(4, 0, PHY_INTERFACE_MODE_2500BASEX, 0x2), |
149 | MVEBU_COMPHY_CONF(4, 0, PHY_MODE_10GKR, 0x2), | 152 | MVEBU_COMPHY_CONF(4, 0, PHY_INTERFACE_MODE_10GKR, 0x2), |
150 | MVEBU_COMPHY_CONF(4, 1, PHY_MODE_SGMII, 0x1), | 153 | MVEBU_COMPHY_CONF(4, 1, PHY_INTERFACE_MODE_SGMII, 0x1), |
151 | /* lane 5 */ | 154 | /* lane 5 */ |
152 | MVEBU_COMPHY_CONF(5, 2, PHY_MODE_SGMII, 0x1), | 155 | MVEBU_COMPHY_CONF(5, 2, PHY_INTERFACE_MODE_SGMII, 0x1), |
153 | MVEBU_COMPHY_CONF(5, 2, PHY_MODE_2500SGMII, 0x1), | 156 | MVEBU_COMPHY_CONF(5, 2, PHY_INTERFACE_MODE_2500BASEX, 0x1), |
154 | }; | 157 | }; |
155 | 158 | ||
156 | struct mvebu_comphy_priv { | 159 | struct mvebu_comphy_priv { |
@@ -163,10 +166,12 @@ struct mvebu_comphy_lane { | |||
163 | struct mvebu_comphy_priv *priv; | 166 | struct mvebu_comphy_priv *priv; |
164 | unsigned id; | 167 | unsigned id; |
165 | enum phy_mode mode; | 168 | enum phy_mode mode; |
169 | int submode; | ||
166 | int port; | 170 | int port; |
167 | }; | 171 | }; |
168 | 172 | ||
169 | static int mvebu_comphy_get_mux(int lane, int port, enum phy_mode mode) | 173 | static int mvebu_comphy_get_mux(int lane, int port, |
174 | enum phy_mode mode, int submode) | ||
170 | { | 175 | { |
171 | int i, n = ARRAY_SIZE(mvebu_comphy_cp110_modes); | 176 | int i, n = ARRAY_SIZE(mvebu_comphy_cp110_modes); |
172 | 177 | ||
@@ -177,7 +182,8 @@ static int mvebu_comphy_get_mux(int lane, int port, enum phy_mode mode) | |||
177 | for (i = 0; i < n; i++) { | 182 | for (i = 0; i < n; i++) { |
178 | if (mvebu_comphy_cp110_modes[i].lane == lane && | 183 | if (mvebu_comphy_cp110_modes[i].lane == lane && |
179 | mvebu_comphy_cp110_modes[i].port == port && | 184 | mvebu_comphy_cp110_modes[i].port == port && |
180 | mvebu_comphy_cp110_modes[i].mode == mode) | 185 | mvebu_comphy_cp110_modes[i].mode == mode && |
186 | mvebu_comphy_cp110_modes[i].submode == submode) | ||
181 | break; | 187 | break; |
182 | } | 188 | } |
183 | 189 | ||
@@ -187,8 +193,7 @@ static int mvebu_comphy_get_mux(int lane, int port, enum phy_mode mode) | |||
187 | return mvebu_comphy_cp110_modes[i].mux; | 193 | return mvebu_comphy_cp110_modes[i].mux; |
188 | } | 194 | } |
189 | 195 | ||
190 | static void mvebu_comphy_ethernet_init_reset(struct mvebu_comphy_lane *lane, | 196 | static void mvebu_comphy_ethernet_init_reset(struct mvebu_comphy_lane *lane) |
191 | enum phy_mode mode) | ||
192 | { | 197 | { |
193 | struct mvebu_comphy_priv *priv = lane->priv; | 198 | struct mvebu_comphy_priv *priv = lane->priv; |
194 | u32 val; | 199 | u32 val; |
@@ -206,14 +211,14 @@ static void mvebu_comphy_ethernet_init_reset(struct mvebu_comphy_lane *lane, | |||
206 | MVEBU_COMPHY_SERDES_CFG0_HALF_BUS | | 211 | MVEBU_COMPHY_SERDES_CFG0_HALF_BUS | |
207 | MVEBU_COMPHY_SERDES_CFG0_GEN_RX(0xf) | | 212 | MVEBU_COMPHY_SERDES_CFG0_GEN_RX(0xf) | |
208 | MVEBU_COMPHY_SERDES_CFG0_GEN_TX(0xf)); | 213 | MVEBU_COMPHY_SERDES_CFG0_GEN_TX(0xf)); |
209 | if (mode == PHY_MODE_10GKR) | 214 | if (lane->submode == PHY_INTERFACE_MODE_10GKR) |
210 | val |= MVEBU_COMPHY_SERDES_CFG0_GEN_RX(0xe) | | 215 | val |= MVEBU_COMPHY_SERDES_CFG0_GEN_RX(0xe) | |
211 | MVEBU_COMPHY_SERDES_CFG0_GEN_TX(0xe); | 216 | MVEBU_COMPHY_SERDES_CFG0_GEN_TX(0xe); |
212 | else if (mode == PHY_MODE_2500SGMII) | 217 | else if (lane->submode == PHY_INTERFACE_MODE_2500BASEX) |
213 | val |= MVEBU_COMPHY_SERDES_CFG0_GEN_RX(0x8) | | 218 | val |= MVEBU_COMPHY_SERDES_CFG0_GEN_RX(0x8) | |
214 | MVEBU_COMPHY_SERDES_CFG0_GEN_TX(0x8) | | 219 | MVEBU_COMPHY_SERDES_CFG0_GEN_TX(0x8) | |
215 | MVEBU_COMPHY_SERDES_CFG0_HALF_BUS; | 220 | MVEBU_COMPHY_SERDES_CFG0_HALF_BUS; |
216 | else if (mode == PHY_MODE_SGMII) | 221 | else if (lane->submode == PHY_INTERFACE_MODE_SGMII) |
217 | val |= MVEBU_COMPHY_SERDES_CFG0_GEN_RX(0x6) | | 222 | val |= MVEBU_COMPHY_SERDES_CFG0_GEN_RX(0x6) | |
218 | MVEBU_COMPHY_SERDES_CFG0_GEN_TX(0x6) | | 223 | MVEBU_COMPHY_SERDES_CFG0_GEN_TX(0x6) | |
219 | MVEBU_COMPHY_SERDES_CFG0_HALF_BUS; | 224 | MVEBU_COMPHY_SERDES_CFG0_HALF_BUS; |
@@ -243,7 +248,7 @@ static void mvebu_comphy_ethernet_init_reset(struct mvebu_comphy_lane *lane, | |||
243 | /* refclk selection */ | 248 | /* refclk selection */ |
244 | val = readl(priv->base + MVEBU_COMPHY_MISC_CTRL0(lane->id)); | 249 | val = readl(priv->base + MVEBU_COMPHY_MISC_CTRL0(lane->id)); |
245 | val &= ~MVEBU_COMPHY_MISC_CTRL0_REFCLK_SEL; | 250 | val &= ~MVEBU_COMPHY_MISC_CTRL0_REFCLK_SEL; |
246 | if (mode == PHY_MODE_10GKR) | 251 | if (lane->submode == PHY_INTERFACE_MODE_10GKR) |
247 | val |= MVEBU_COMPHY_MISC_CTRL0_ICP_FORCE; | 252 | val |= MVEBU_COMPHY_MISC_CTRL0_ICP_FORCE; |
248 | writel(val, priv->base + MVEBU_COMPHY_MISC_CTRL0(lane->id)); | 253 | writel(val, priv->base + MVEBU_COMPHY_MISC_CTRL0(lane->id)); |
249 | 254 | ||
@@ -261,8 +266,7 @@ static void mvebu_comphy_ethernet_init_reset(struct mvebu_comphy_lane *lane, | |||
261 | writel(val, priv->base + MVEBU_COMPHY_LOOPBACK(lane->id)); | 266 | writel(val, priv->base + MVEBU_COMPHY_LOOPBACK(lane->id)); |
262 | } | 267 | } |
263 | 268 | ||
264 | static int mvebu_comphy_init_plls(struct mvebu_comphy_lane *lane, | 269 | static int mvebu_comphy_init_plls(struct mvebu_comphy_lane *lane) |
265 | enum phy_mode mode) | ||
266 | { | 270 | { |
267 | struct mvebu_comphy_priv *priv = lane->priv; | 271 | struct mvebu_comphy_priv *priv = lane->priv; |
268 | u32 val; | 272 | u32 val; |
@@ -303,13 +307,13 @@ static int mvebu_comphy_init_plls(struct mvebu_comphy_lane *lane, | |||
303 | return 0; | 307 | return 0; |
304 | } | 308 | } |
305 | 309 | ||
306 | static int mvebu_comphy_set_mode_sgmii(struct phy *phy, enum phy_mode mode) | 310 | static int mvebu_comphy_set_mode_sgmii(struct phy *phy) |
307 | { | 311 | { |
308 | struct mvebu_comphy_lane *lane = phy_get_drvdata(phy); | 312 | struct mvebu_comphy_lane *lane = phy_get_drvdata(phy); |
309 | struct mvebu_comphy_priv *priv = lane->priv; | 313 | struct mvebu_comphy_priv *priv = lane->priv; |
310 | u32 val; | 314 | u32 val; |
311 | 315 | ||
312 | mvebu_comphy_ethernet_init_reset(lane, mode); | 316 | mvebu_comphy_ethernet_init_reset(lane); |
313 | 317 | ||
314 | val = readl(priv->base + MVEBU_COMPHY_RX_CTRL1(lane->id)); | 318 | val = readl(priv->base + MVEBU_COMPHY_RX_CTRL1(lane->id)); |
315 | val &= ~MVEBU_COMPHY_RX_CTRL1_CLK8T_EN; | 319 | val &= ~MVEBU_COMPHY_RX_CTRL1_CLK8T_EN; |
@@ -330,7 +334,7 @@ static int mvebu_comphy_set_mode_sgmii(struct phy *phy, enum phy_mode mode) | |||
330 | val |= MVEBU_COMPHY_GEN1_S0_TX_EMPH(0x1); | 334 | val |= MVEBU_COMPHY_GEN1_S0_TX_EMPH(0x1); |
331 | writel(val, priv->base + MVEBU_COMPHY_GEN1_S0(lane->id)); | 335 | writel(val, priv->base + MVEBU_COMPHY_GEN1_S0(lane->id)); |
332 | 336 | ||
333 | return mvebu_comphy_init_plls(lane, PHY_MODE_SGMII); | 337 | return mvebu_comphy_init_plls(lane); |
334 | } | 338 | } |
335 | 339 | ||
336 | static int mvebu_comphy_set_mode_10gkr(struct phy *phy) | 340 | static int mvebu_comphy_set_mode_10gkr(struct phy *phy) |
@@ -339,7 +343,7 @@ static int mvebu_comphy_set_mode_10gkr(struct phy *phy) | |||
339 | struct mvebu_comphy_priv *priv = lane->priv; | 343 | struct mvebu_comphy_priv *priv = lane->priv; |
340 | u32 val; | 344 | u32 val; |
341 | 345 | ||
342 | mvebu_comphy_ethernet_init_reset(lane, PHY_MODE_10GKR); | 346 | mvebu_comphy_ethernet_init_reset(lane); |
343 | 347 | ||
344 | val = readl(priv->base + MVEBU_COMPHY_RX_CTRL1(lane->id)); | 348 | val = readl(priv->base + MVEBU_COMPHY_RX_CTRL1(lane->id)); |
345 | val |= MVEBU_COMPHY_RX_CTRL1_RXCLK2X_SEL | | 349 | val |= MVEBU_COMPHY_RX_CTRL1_RXCLK2X_SEL | |
@@ -469,7 +473,7 @@ static int mvebu_comphy_set_mode_10gkr(struct phy *phy) | |||
469 | val |= MVEBU_COMPHY_EXT_SELV_RX_SAMPL(0x1a); | 473 | val |= MVEBU_COMPHY_EXT_SELV_RX_SAMPL(0x1a); |
470 | writel(val, priv->base + MVEBU_COMPHY_EXT_SELV(lane->id)); | 474 | writel(val, priv->base + MVEBU_COMPHY_EXT_SELV(lane->id)); |
471 | 475 | ||
472 | return mvebu_comphy_init_plls(lane, PHY_MODE_10GKR); | 476 | return mvebu_comphy_init_plls(lane); |
473 | } | 477 | } |
474 | 478 | ||
475 | static int mvebu_comphy_power_on(struct phy *phy) | 479 | static int mvebu_comphy_power_on(struct phy *phy) |
@@ -479,7 +483,8 @@ static int mvebu_comphy_power_on(struct phy *phy) | |||
479 | int ret, mux; | 483 | int ret, mux; |
480 | u32 val; | 484 | u32 val; |
481 | 485 | ||
482 | mux = mvebu_comphy_get_mux(lane->id, lane->port, lane->mode); | 486 | mux = mvebu_comphy_get_mux(lane->id, lane->port, |
487 | lane->mode, lane->submode); | ||
483 | if (mux < 0) | 488 | if (mux < 0) |
484 | return -ENOTSUPP; | 489 | return -ENOTSUPP; |
485 | 490 | ||
@@ -492,12 +497,12 @@ static int mvebu_comphy_power_on(struct phy *phy) | |||
492 | val |= mux << MVEBU_COMPHY_SELECTOR_PHY(lane->id); | 497 | val |= mux << MVEBU_COMPHY_SELECTOR_PHY(lane->id); |
493 | regmap_write(priv->regmap, MVEBU_COMPHY_SELECTOR, val); | 498 | regmap_write(priv->regmap, MVEBU_COMPHY_SELECTOR, val); |
494 | 499 | ||
495 | switch (lane->mode) { | 500 | switch (lane->submode) { |
496 | case PHY_MODE_SGMII: | 501 | case PHY_INTERFACE_MODE_SGMII: |
497 | case PHY_MODE_2500SGMII: | 502 | case PHY_INTERFACE_MODE_2500BASEX: |
498 | ret = mvebu_comphy_set_mode_sgmii(phy, lane->mode); | 503 | ret = mvebu_comphy_set_mode_sgmii(phy); |
499 | break; | 504 | break; |
500 | case PHY_MODE_10GKR: | 505 | case PHY_INTERFACE_MODE_10GKR: |
501 | ret = mvebu_comphy_set_mode_10gkr(phy); | 506 | ret = mvebu_comphy_set_mode_10gkr(phy); |
502 | break; | 507 | break; |
503 | default: | 508 | default: |
@@ -512,14 +517,22 @@ static int mvebu_comphy_power_on(struct phy *phy) | |||
512 | return ret; | 517 | return ret; |
513 | } | 518 | } |
514 | 519 | ||
515 | static int mvebu_comphy_set_mode(struct phy *phy, enum phy_mode mode) | 520 | static int mvebu_comphy_set_mode(struct phy *phy, |
521 | enum phy_mode mode, int submode) | ||
516 | { | 522 | { |
517 | struct mvebu_comphy_lane *lane = phy_get_drvdata(phy); | 523 | struct mvebu_comphy_lane *lane = phy_get_drvdata(phy); |
518 | 524 | ||
519 | if (mvebu_comphy_get_mux(lane->id, lane->port, mode) < 0) | 525 | if (mode != PHY_MODE_ETHERNET) |
526 | return -EINVAL; | ||
527 | |||
528 | if (submode == PHY_INTERFACE_MODE_1000BASEX) | ||
529 | submode = PHY_INTERFACE_MODE_SGMII; | ||
530 | |||
531 | if (mvebu_comphy_get_mux(lane->id, lane->port, mode, submode) < 0) | ||
520 | return -EINVAL; | 532 | return -EINVAL; |
521 | 533 | ||
522 | lane->mode = mode; | 534 | lane->mode = mode; |
535 | lane->submode = submode; | ||
523 | return 0; | 536 | return 0; |
524 | } | 537 | } |
525 | 538 | ||
diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c index 3eb8e1bd7b78..5b6a470ca145 100644 --- a/drivers/phy/mediatek/phy-mtk-tphy.c +++ b/drivers/phy/mediatek/phy-mtk-tphy.c | |||
@@ -971,7 +971,7 @@ static int mtk_phy_exit(struct phy *phy) | |||
971 | return 0; | 971 | return 0; |
972 | } | 972 | } |
973 | 973 | ||
974 | static int mtk_phy_set_mode(struct phy *phy, enum phy_mode mode) | 974 | static int mtk_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode) |
975 | { | 975 | { |
976 | struct mtk_phy_instance *instance = phy_get_drvdata(phy); | 976 | struct mtk_phy_instance *instance = phy_get_drvdata(phy); |
977 | struct mtk_tphy *tphy = dev_get_drvdata(phy->dev.parent); | 977 | struct mtk_tphy *tphy = dev_get_drvdata(phy->dev.parent); |
diff --git a/drivers/phy/mediatek/phy-mtk-xsphy.c b/drivers/phy/mediatek/phy-mtk-xsphy.c index 020cd0227397..8c51131945c0 100644 --- a/drivers/phy/mediatek/phy-mtk-xsphy.c +++ b/drivers/phy/mediatek/phy-mtk-xsphy.c | |||
@@ -426,7 +426,7 @@ static int mtk_phy_exit(struct phy *phy) | |||
426 | return 0; | 426 | return 0; |
427 | } | 427 | } |
428 | 428 | ||
429 | static int mtk_phy_set_mode(struct phy *phy, enum phy_mode mode) | 429 | static int mtk_phy_set_mode(struct phy *phy, enum phy_mode mode, int submode) |
430 | { | 430 | { |
431 | struct xsphy_instance *inst = phy_get_drvdata(phy); | 431 | struct xsphy_instance *inst = phy_get_drvdata(phy); |
432 | struct mtk_xsphy *xsphy = dev_get_drvdata(phy->dev.parent); | 432 | struct mtk_xsphy *xsphy = dev_get_drvdata(phy->dev.parent); |
diff --git a/drivers/phy/motorola/phy-mapphone-mdm6600.c b/drivers/phy/motorola/phy-mapphone-mdm6600.c index 25d456a323c2..ee184d5607bd 100644 --- a/drivers/phy/motorola/phy-mapphone-mdm6600.c +++ b/drivers/phy/motorola/phy-mapphone-mdm6600.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/gpio/consumer.h> | 16 | #include <linux/gpio/consumer.h> |
17 | #include <linux/of_platform.h> | 17 | #include <linux/of_platform.h> |
18 | #include <linux/phy/phy.h> | 18 | #include <linux/phy/phy.h> |
19 | #include <linux/pinctrl/consumer.h> | ||
19 | 20 | ||
20 | #define PHY_MDM6600_PHY_DELAY_MS 4000 /* PHY enable 2.2s to 3.5s */ | 21 | #define PHY_MDM6600_PHY_DELAY_MS 4000 /* PHY enable 2.2s to 3.5s */ |
21 | #define PHY_MDM6600_ENABLED_DELAY_MS 8000 /* 8s more total for MDM6600 */ | 22 | #define PHY_MDM6600_ENABLED_DELAY_MS 8000 /* 8s more total for MDM6600 */ |
@@ -120,12 +121,22 @@ static int phy_mdm6600_power_on(struct phy *x) | |||
120 | { | 121 | { |
121 | struct phy_mdm6600 *ddata = phy_get_drvdata(x); | 122 | struct phy_mdm6600 *ddata = phy_get_drvdata(x); |
122 | struct gpio_desc *enable_gpio = ddata->ctrl_gpios[PHY_MDM6600_ENABLE]; | 123 | struct gpio_desc *enable_gpio = ddata->ctrl_gpios[PHY_MDM6600_ENABLE]; |
124 | int error; | ||
123 | 125 | ||
124 | if (!ddata->enabled) | 126 | if (!ddata->enabled) |
125 | return -ENODEV; | 127 | return -ENODEV; |
126 | 128 | ||
129 | error = pinctrl_pm_select_default_state(ddata->dev); | ||
130 | if (error) | ||
131 | dev_warn(ddata->dev, "%s: error with default_state: %i\n", | ||
132 | __func__, error); | ||
133 | |||
127 | gpiod_set_value_cansleep(enable_gpio, 1); | 134 | gpiod_set_value_cansleep(enable_gpio, 1); |
128 | 135 | ||
136 | /* Allow aggressive PM for USB, it's only needed for n_gsm port */ | ||
137 | if (pm_runtime_enabled(&x->dev)) | ||
138 | phy_pm_runtime_put(x); | ||
139 | |||
129 | return 0; | 140 | return 0; |
130 | } | 141 | } |
131 | 142 | ||
@@ -133,12 +144,26 @@ static int phy_mdm6600_power_off(struct phy *x) | |||
133 | { | 144 | { |
134 | struct phy_mdm6600 *ddata = phy_get_drvdata(x); | 145 | struct phy_mdm6600 *ddata = phy_get_drvdata(x); |
135 | struct gpio_desc *enable_gpio = ddata->ctrl_gpios[PHY_MDM6600_ENABLE]; | 146 | struct gpio_desc *enable_gpio = ddata->ctrl_gpios[PHY_MDM6600_ENABLE]; |
147 | int error; | ||
136 | 148 | ||
137 | if (!ddata->enabled) | 149 | if (!ddata->enabled) |
138 | return -ENODEV; | 150 | return -ENODEV; |
139 | 151 | ||
152 | /* Paired with phy_pm_runtime_put() in phy_mdm6600_power_on() */ | ||
153 | if (pm_runtime_enabled(&x->dev)) { | ||
154 | error = phy_pm_runtime_get(x); | ||
155 | if (error < 0 && error != -EINPROGRESS) | ||
156 | dev_warn(ddata->dev, "%s: phy_pm_runtime_get: %i\n", | ||
157 | __func__, error); | ||
158 | } | ||
159 | |||
140 | gpiod_set_value_cansleep(enable_gpio, 0); | 160 | gpiod_set_value_cansleep(enable_gpio, 0); |
141 | 161 | ||
162 | error = pinctrl_pm_select_sleep_state(ddata->dev); | ||
163 | if (error) | ||
164 | dev_warn(ddata->dev, "%s: error with sleep_state: %i\n", | ||
165 | __func__, error); | ||
166 | |||
142 | return 0; | 167 | return 0; |
143 | } | 168 | } |
144 | 169 | ||
@@ -529,28 +554,17 @@ static int phy_mdm6600_probe(struct platform_device *pdev) | |||
529 | ddata->dev = &pdev->dev; | 554 | ddata->dev = &pdev->dev; |
530 | platform_set_drvdata(pdev, ddata); | 555 | platform_set_drvdata(pdev, ddata); |
531 | 556 | ||
557 | /* Active state selected in phy_mdm6600_power_on() */ | ||
558 | error = pinctrl_pm_select_sleep_state(ddata->dev); | ||
559 | if (error) | ||
560 | dev_warn(ddata->dev, "%s: error with sleep_state: %i\n", | ||
561 | __func__, error); | ||
562 | |||
532 | error = phy_mdm6600_init_lines(ddata); | 563 | error = phy_mdm6600_init_lines(ddata); |
533 | if (error) | 564 | if (error) |
534 | return error; | 565 | return error; |
535 | 566 | ||
536 | phy_mdm6600_init_irq(ddata); | 567 | phy_mdm6600_init_irq(ddata); |
537 | |||
538 | ddata->generic_phy = devm_phy_create(ddata->dev, NULL, &gpio_usb_ops); | ||
539 | if (IS_ERR(ddata->generic_phy)) { | ||
540 | error = PTR_ERR(ddata->generic_phy); | ||
541 | goto cleanup; | ||
542 | } | ||
543 | |||
544 | phy_set_drvdata(ddata->generic_phy, ddata); | ||
545 | |||
546 | ddata->phy_provider = | ||
547 | devm_of_phy_provider_register(ddata->dev, | ||
548 | of_phy_simple_xlate); | ||
549 | if (IS_ERR(ddata->phy_provider)) { | ||
550 | error = PTR_ERR(ddata->phy_provider); | ||
551 | goto cleanup; | ||
552 | } | ||
553 | |||
554 | schedule_delayed_work(&ddata->bootup_work, 0); | 568 | schedule_delayed_work(&ddata->bootup_work, 0); |
555 | 569 | ||
556 | /* | 570 | /* |
@@ -574,14 +588,31 @@ static int phy_mdm6600_probe(struct platform_device *pdev) | |||
574 | if (error < 0) { | 588 | if (error < 0) { |
575 | dev_warn(ddata->dev, "failed to wake modem: %i\n", error); | 589 | dev_warn(ddata->dev, "failed to wake modem: %i\n", error); |
576 | pm_runtime_put_noidle(ddata->dev); | 590 | pm_runtime_put_noidle(ddata->dev); |
591 | goto cleanup; | ||
577 | } | 592 | } |
593 | |||
594 | ddata->generic_phy = devm_phy_create(ddata->dev, NULL, &gpio_usb_ops); | ||
595 | if (IS_ERR(ddata->generic_phy)) { | ||
596 | error = PTR_ERR(ddata->generic_phy); | ||
597 | goto idle; | ||
598 | } | ||
599 | |||
600 | phy_set_drvdata(ddata->generic_phy, ddata); | ||
601 | |||
602 | ddata->phy_provider = | ||
603 | devm_of_phy_provider_register(ddata->dev, | ||
604 | of_phy_simple_xlate); | ||
605 | if (IS_ERR(ddata->phy_provider)) | ||
606 | error = PTR_ERR(ddata->phy_provider); | ||
607 | |||
608 | idle: | ||
578 | pm_runtime_mark_last_busy(ddata->dev); | 609 | pm_runtime_mark_last_busy(ddata->dev); |
579 | pm_runtime_put_autosuspend(ddata->dev); | 610 | pm_runtime_put_autosuspend(ddata->dev); |
580 | 611 | ||
581 | return 0; | ||
582 | |||
583 | cleanup: | 612 | cleanup: |
584 | phy_mdm6600_device_power_off(ddata); | 613 | if (error < 0) |
614 | phy_mdm6600_device_power_off(ddata); | ||
615 | |||
585 | return error; | 616 | return error; |
586 | } | 617 | } |
587 | 618 | ||
diff --git a/drivers/phy/mscc/phy-ocelot-serdes.c b/drivers/phy/mscc/phy-ocelot-serdes.c index cbb49d9da6f9..77c46f639fbf 100644 --- a/drivers/phy/mscc/phy-ocelot-serdes.c +++ b/drivers/phy/mscc/phy-ocelot-serdes.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/of.h> | 12 | #include <linux/of.h> |
13 | #include <linux/of_platform.h> | 13 | #include <linux/of_platform.h> |
14 | #include <linux/phy.h> | ||
14 | #include <linux/phy/phy.h> | 15 | #include <linux/phy/phy.h> |
15 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
16 | #include <linux/regmap.h> | 17 | #include <linux/regmap.h> |
@@ -104,20 +105,24 @@ struct serdes_mux { | |||
104 | u8 idx; | 105 | u8 idx; |
105 | u8 port; | 106 | u8 port; |
106 | enum phy_mode mode; | 107 | enum phy_mode mode; |
108 | int submode; | ||
107 | u32 mask; | 109 | u32 mask; |
108 | u32 mux; | 110 | u32 mux; |
109 | }; | 111 | }; |
110 | 112 | ||
111 | #define SERDES_MUX(_idx, _port, _mode, _mask, _mux) { \ | 113 | #define SERDES_MUX(_idx, _port, _mode, _submode, _mask, _mux) { \ |
112 | .idx = _idx, \ | 114 | .idx = _idx, \ |
113 | .port = _port, \ | 115 | .port = _port, \ |
114 | .mode = _mode, \ | 116 | .mode = _mode, \ |
117 | .submode = _submode, \ | ||
115 | .mask = _mask, \ | 118 | .mask = _mask, \ |
116 | .mux = _mux, \ | 119 | .mux = _mux, \ |
117 | } | 120 | } |
118 | 121 | ||
119 | #define SERDES_MUX_SGMII(i, p, m, c) SERDES_MUX(i, p, PHY_MODE_SGMII, m, c) | 122 | #define SERDES_MUX_SGMII(i, p, m, c) \ |
120 | #define SERDES_MUX_QSGMII(i, p, m, c) SERDES_MUX(i, p, PHY_MODE_QSGMII, m, c) | 123 | SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_SGMII, m, c) |
124 | #define SERDES_MUX_QSGMII(i, p, m, c) \ | ||
125 | SERDES_MUX(i, p, PHY_MODE_ETHERNET, PHY_INTERFACE_MODE_QSGMII, m, c) | ||
121 | 126 | ||
122 | static const struct serdes_mux ocelot_serdes_muxes[] = { | 127 | static const struct serdes_mux ocelot_serdes_muxes[] = { |
123 | SERDES_MUX_SGMII(SERDES1G(0), 0, 0, 0), | 128 | SERDES_MUX_SGMII(SERDES1G(0), 0, 0, 0), |
@@ -154,22 +159,27 @@ static const struct serdes_mux ocelot_serdes_muxes[] = { | |||
154 | SERDES_MUX_SGMII(SERDES6G(1), 8, 0, 0), | 159 | SERDES_MUX_SGMII(SERDES6G(1), 8, 0, 0), |
155 | SERDES_MUX_SGMII(SERDES6G(2), 10, HSIO_HW_CFG_PCIE_ENA | | 160 | SERDES_MUX_SGMII(SERDES6G(2), 10, HSIO_HW_CFG_PCIE_ENA | |
156 | HSIO_HW_CFG_DEV2G5_10_MODE, 0), | 161 | HSIO_HW_CFG_DEV2G5_10_MODE, 0), |
157 | SERDES_MUX(SERDES6G(2), 10, PHY_MODE_PCIE, HSIO_HW_CFG_PCIE_ENA, | 162 | SERDES_MUX(SERDES6G(2), 10, PHY_MODE_PCIE, 0, HSIO_HW_CFG_PCIE_ENA, |
158 | HSIO_HW_CFG_PCIE_ENA), | 163 | HSIO_HW_CFG_PCIE_ENA), |
159 | }; | 164 | }; |
160 | 165 | ||
161 | static int serdes_set_mode(struct phy *phy, enum phy_mode mode) | 166 | static int serdes_set_mode(struct phy *phy, enum phy_mode mode, int submode) |
162 | { | 167 | { |
163 | struct serdes_macro *macro = phy_get_drvdata(phy); | 168 | struct serdes_macro *macro = phy_get_drvdata(phy); |
164 | unsigned int i; | 169 | unsigned int i; |
165 | int ret; | 170 | int ret; |
166 | 171 | ||
172 | /* As of now only PHY_MODE_ETHERNET is supported */ | ||
173 | if (mode != PHY_MODE_ETHERNET) | ||
174 | return -EOPNOTSUPP; | ||
175 | |||
167 | for (i = 0; i < ARRAY_SIZE(ocelot_serdes_muxes); i++) { | 176 | for (i = 0; i < ARRAY_SIZE(ocelot_serdes_muxes); i++) { |
168 | if (macro->idx != ocelot_serdes_muxes[i].idx || | 177 | if (macro->idx != ocelot_serdes_muxes[i].idx || |
169 | mode != ocelot_serdes_muxes[i].mode) | 178 | mode != ocelot_serdes_muxes[i].mode || |
179 | submode != ocelot_serdes_muxes[i].submode) | ||
170 | continue; | 180 | continue; |
171 | 181 | ||
172 | if (mode != PHY_MODE_QSGMII && | 182 | if (submode != PHY_INTERFACE_MODE_QSGMII && |
173 | macro->port != ocelot_serdes_muxes[i].port) | 183 | macro->port != ocelot_serdes_muxes[i].port) |
174 | continue; | 184 | continue; |
175 | 185 | ||
diff --git a/drivers/phy/phy-core-mipi-dphy.c b/drivers/phy/phy-core-mipi-dphy.c new file mode 100644 index 000000000000..465fa1b91a5f --- /dev/null +++ b/drivers/phy/phy-core-mipi-dphy.c | |||
@@ -0,0 +1,166 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | /* | ||
3 | * Copyright (C) 2013 NVIDIA Corporation | ||
4 | * Copyright (C) 2018 Cadence Design Systems Inc. | ||
5 | */ | ||
6 | |||
7 | #include <linux/errno.h> | ||
8 | #include <linux/export.h> | ||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/time64.h> | ||
11 | |||
12 | #include <linux/phy/phy.h> | ||
13 | #include <linux/phy/phy-mipi-dphy.h> | ||
14 | |||
15 | #define PSEC_PER_SEC 1000000000000LL | ||
16 | |||
17 | /* | ||
18 | * Minimum D-PHY timings based on MIPI D-PHY specification. Derived | ||
19 | * from the valid ranges specified in Section 6.9, Table 14, Page 41 | ||
20 | * of the D-PHY specification (v2.1). | ||
21 | */ | ||
22 | int phy_mipi_dphy_get_default_config(unsigned long pixel_clock, | ||
23 | unsigned int bpp, | ||
24 | unsigned int lanes, | ||
25 | struct phy_configure_opts_mipi_dphy *cfg) | ||
26 | { | ||
27 | unsigned long long hs_clk_rate; | ||
28 | unsigned long long ui; | ||
29 | |||
30 | if (!cfg) | ||
31 | return -EINVAL; | ||
32 | |||
33 | hs_clk_rate = pixel_clock * bpp; | ||
34 | do_div(hs_clk_rate, lanes); | ||
35 | |||
36 | ui = ALIGN(PSEC_PER_SEC, hs_clk_rate); | ||
37 | do_div(ui, hs_clk_rate); | ||
38 | |||
39 | cfg->clk_miss = 0; | ||
40 | cfg->clk_post = 60000 + 52 * ui; | ||
41 | cfg->clk_pre = 8000; | ||
42 | cfg->clk_prepare = 38000; | ||
43 | cfg->clk_settle = 95000; | ||
44 | cfg->clk_term_en = 0; | ||
45 | cfg->clk_trail = 60000; | ||
46 | cfg->clk_zero = 262000; | ||
47 | cfg->d_term_en = 0; | ||
48 | cfg->eot = 0; | ||
49 | cfg->hs_exit = 100000; | ||
50 | cfg->hs_prepare = 40000 + 4 * ui; | ||
51 | cfg->hs_zero = 105000 + 6 * ui; | ||
52 | cfg->hs_settle = 85000 + 6 * ui; | ||
53 | cfg->hs_skip = 40000; | ||
54 | |||
55 | /* | ||
56 | * The MIPI D-PHY specification (Section 6.9, v1.2, Table 14, Page 40) | ||
57 | * contains this formula as: | ||
58 | * | ||
59 | * T_HS-TRAIL = max(n * 8 * ui, 60 + n * 4 * ui) | ||
60 | * | ||
61 | * where n = 1 for forward-direction HS mode and n = 4 for reverse- | ||
62 | * direction HS mode. There's only one setting and this function does | ||
63 | * not parameterize on anything other that ui, so this code will | ||
64 | * assumes that reverse-direction HS mode is supported and uses n = 4. | ||
65 | */ | ||
66 | cfg->hs_trail = max(4 * 8 * ui, 60000 + 4 * 4 * ui); | ||
67 | |||
68 | cfg->init = 100000000; | ||
69 | cfg->lpx = 60000; | ||
70 | cfg->ta_get = 5 * cfg->lpx; | ||
71 | cfg->ta_go = 4 * cfg->lpx; | ||
72 | cfg->ta_sure = 2 * cfg->lpx; | ||
73 | cfg->wakeup = 1000000000; | ||
74 | |||
75 | cfg->hs_clk_rate = hs_clk_rate; | ||
76 | cfg->lanes = lanes; | ||
77 | |||
78 | return 0; | ||
79 | } | ||
80 | EXPORT_SYMBOL(phy_mipi_dphy_get_default_config); | ||
81 | |||
82 | /* | ||
83 | * Validate D-PHY configuration according to MIPI D-PHY specification | ||
84 | * (v1.2, Section Section 6.9 "Global Operation Timing Parameters"). | ||
85 | */ | ||
86 | int phy_mipi_dphy_config_validate(struct phy_configure_opts_mipi_dphy *cfg) | ||
87 | { | ||
88 | unsigned long long ui; | ||
89 | |||
90 | if (!cfg) | ||
91 | return -EINVAL; | ||
92 | |||
93 | ui = ALIGN(PSEC_PER_SEC, cfg->hs_clk_rate); | ||
94 | do_div(ui, cfg->hs_clk_rate); | ||
95 | |||
96 | if (cfg->clk_miss > 60000) | ||
97 | return -EINVAL; | ||
98 | |||
99 | if (cfg->clk_post < (60000 + 52 * ui)) | ||
100 | return -EINVAL; | ||
101 | |||
102 | if (cfg->clk_pre < 8000) | ||
103 | return -EINVAL; | ||
104 | |||
105 | if (cfg->clk_prepare < 38000 || cfg->clk_prepare > 95000) | ||
106 | return -EINVAL; | ||
107 | |||
108 | if (cfg->clk_settle < 95000 || cfg->clk_settle > 300000) | ||
109 | return -EINVAL; | ||
110 | |||
111 | if (cfg->clk_term_en > 38000) | ||
112 | return -EINVAL; | ||
113 | |||
114 | if (cfg->clk_trail < 60000) | ||
115 | return -EINVAL; | ||
116 | |||
117 | if ((cfg->clk_prepare + cfg->clk_zero) < 300000) | ||
118 | return -EINVAL; | ||
119 | |||
120 | if (cfg->d_term_en > (35000 + 4 * ui)) | ||
121 | return -EINVAL; | ||
122 | |||
123 | if (cfg->eot > (105000 + 12 * ui)) | ||
124 | return -EINVAL; | ||
125 | |||
126 | if (cfg->hs_exit < 100000) | ||
127 | return -EINVAL; | ||
128 | |||
129 | if (cfg->hs_prepare < (40000 + 4 * ui) || | ||
130 | cfg->hs_prepare > (85000 + 6 * ui)) | ||
131 | return -EINVAL; | ||
132 | |||
133 | if ((cfg->hs_prepare + cfg->hs_zero) < (145000 + 10 * ui)) | ||
134 | return -EINVAL; | ||
135 | |||
136 | if ((cfg->hs_settle < (85000 + 6 * ui)) || | ||
137 | (cfg->hs_settle > (145000 + 10 * ui))) | ||
138 | return -EINVAL; | ||
139 | |||
140 | if (cfg->hs_skip < 40000 || cfg->hs_skip > (55000 + 4 * ui)) | ||
141 | return -EINVAL; | ||
142 | |||
143 | if (cfg->hs_trail < max(8 * ui, 60000 + 4 * ui)) | ||
144 | return -EINVAL; | ||
145 | |||
146 | if (cfg->init < 100000000) | ||
147 | return -EINVAL; | ||
148 | |||
149 | if (cfg->lpx < 50000) | ||
150 | return -EINVAL; | ||
151 | |||
152 | if (cfg->ta_get != (5 * cfg->lpx)) | ||
153 | return -EINVAL; | ||
154 | |||
155 | if (cfg->ta_go != (4 * cfg->lpx)) | ||
156 | return -EINVAL; | ||
157 | |||
158 | if (cfg->ta_sure < cfg->lpx || cfg->ta_sure > (2 * cfg->lpx)) | ||
159 | return -EINVAL; | ||
160 | |||
161 | if (cfg->wakeup < 1000000000) | ||
162 | return -EINVAL; | ||
163 | |||
164 | return 0; | ||
165 | } | ||
166 | EXPORT_SYMBOL(phy_mipi_dphy_config_validate); | ||
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index 35fd38c5a4a1..19b05e824ee4 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c | |||
@@ -360,7 +360,7 @@ int phy_power_off(struct phy *phy) | |||
360 | } | 360 | } |
361 | EXPORT_SYMBOL_GPL(phy_power_off); | 361 | EXPORT_SYMBOL_GPL(phy_power_off); |
362 | 362 | ||
363 | int phy_set_mode(struct phy *phy, enum phy_mode mode) | 363 | int phy_set_mode_ext(struct phy *phy, enum phy_mode mode, int submode) |
364 | { | 364 | { |
365 | int ret; | 365 | int ret; |
366 | 366 | ||
@@ -368,14 +368,14 @@ int phy_set_mode(struct phy *phy, enum phy_mode mode) | |||
368 | return 0; | 368 | return 0; |
369 | 369 | ||
370 | mutex_lock(&phy->mutex); | 370 | mutex_lock(&phy->mutex); |
371 | ret = phy->ops->set_mode(phy, mode); | 371 | ret = phy->ops->set_mode(phy, mode, submode); |
372 | if (!ret) | 372 | if (!ret) |
373 | phy->attrs.mode = mode; | 373 | phy->attrs.mode = mode; |
374 | mutex_unlock(&phy->mutex); | 374 | mutex_unlock(&phy->mutex); |
375 | 375 | ||
376 | return ret; | 376 | return ret; |
377 | } | 377 | } |
378 | EXPORT_SYMBOL_GPL(phy_set_mode); | 378 | EXPORT_SYMBOL_GPL(phy_set_mode_ext); |
379 | 379 | ||
380 | int phy_reset(struct phy *phy) | 380 | int phy_reset(struct phy *phy) |
381 | { | 381 | { |
@@ -408,6 +408,70 @@ int phy_calibrate(struct phy *phy) | |||
408 | EXPORT_SYMBOL_GPL(phy_calibrate); | 408 | EXPORT_SYMBOL_GPL(phy_calibrate); |
409 | 409 | ||
410 | /** | 410 | /** |
411 | * phy_configure() - Changes the phy parameters | ||
412 | * @phy: the phy returned by phy_get() | ||
413 | * @opts: New configuration to apply | ||
414 | * | ||
415 | * Used to change the PHY parameters. phy_init() must have been called | ||
416 | * on the phy. The configuration will be applied on the current phy | ||
417 | * mode, that can be changed using phy_set_mode(). | ||
418 | * | ||
419 | * Returns: 0 if successful, an negative error code otherwise | ||
420 | */ | ||
421 | int phy_configure(struct phy *phy, union phy_configure_opts *opts) | ||
422 | { | ||
423 | int ret; | ||
424 | |||
425 | if (!phy) | ||
426 | return -EINVAL; | ||
427 | |||
428 | if (!phy->ops->configure) | ||
429 | return -EOPNOTSUPP; | ||
430 | |||
431 | mutex_lock(&phy->mutex); | ||
432 | ret = phy->ops->configure(phy, opts); | ||
433 | mutex_unlock(&phy->mutex); | ||
434 | |||
435 | return ret; | ||
436 | } | ||
437 | EXPORT_SYMBOL_GPL(phy_configure); | ||
438 | |||
439 | /** | ||
440 | * phy_validate() - Checks the phy parameters | ||
441 | * @phy: the phy returned by phy_get() | ||
442 | * @mode: phy_mode the configuration is applicable to. | ||
443 | * @submode: PHY submode the configuration is applicable to. | ||
444 | * @opts: Configuration to check | ||
445 | * | ||
446 | * Used to check that the current set of parameters can be handled by | ||
447 | * the phy. Implementations are free to tune the parameters passed as | ||
448 | * arguments if needed by some implementation detail or | ||
449 | * constraints. It will not change any actual configuration of the | ||
450 | * PHY, so calling it as many times as deemed fit will have no side | ||
451 | * effect. | ||
452 | * | ||
453 | * Returns: 0 if successful, an negative error code otherwise | ||
454 | */ | ||
455 | int phy_validate(struct phy *phy, enum phy_mode mode, int submode, | ||
456 | union phy_configure_opts *opts) | ||
457 | { | ||
458 | int ret; | ||
459 | |||
460 | if (!phy) | ||
461 | return -EINVAL; | ||
462 | |||
463 | if (!phy->ops->validate) | ||
464 | return -EOPNOTSUPP; | ||
465 | |||
466 | mutex_lock(&phy->mutex); | ||
467 | ret = phy->ops->validate(phy, mode, submode, opts); | ||
468 | mutex_unlock(&phy->mutex); | ||
469 | |||
470 | return ret; | ||
471 | } | ||
472 | EXPORT_SYMBOL_GPL(phy_validate); | ||
473 | |||
474 | /** | ||
411 | * _of_phy_get() - lookup and obtain a reference to a phy by phandle | 475 | * _of_phy_get() - lookup and obtain a reference to a phy by phandle |
412 | * @np: device_node for which to get the phy | 476 | * @np: device_node for which to get the phy |
413 | * @index: the index of the phy | 477 | * @index: the index of the phy |
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.c b/drivers/phy/qualcomm/phy-qcom-qmp.c index a83332411026..b4006818e1b6 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp.c | |||
@@ -72,6 +72,9 @@ | |||
72 | 72 | ||
73 | #define MAX_PROP_NAME 32 | 73 | #define MAX_PROP_NAME 32 |
74 | 74 | ||
75 | /* Define the assumed distance between lanes for underspecified device trees. */ | ||
76 | #define QMP_PHY_LEGACY_LANE_STRIDE 0x400 | ||
77 | |||
75 | struct qmp_phy_init_tbl { | 78 | struct qmp_phy_init_tbl { |
76 | unsigned int offset; | 79 | unsigned int offset; |
77 | unsigned int val; | 80 | unsigned int val; |
@@ -733,9 +736,6 @@ struct qmp_phy_cfg { | |||
733 | bool has_phy_dp_com_ctrl; | 736 | bool has_phy_dp_com_ctrl; |
734 | /* true, if PHY has secondary tx/rx lanes to be configured */ | 737 | /* true, if PHY has secondary tx/rx lanes to be configured */ |
735 | bool is_dual_lane_phy; | 738 | bool is_dual_lane_phy; |
736 | /* Register offset of secondary tx/rx lanes for USB DP combo PHY */ | ||
737 | unsigned int tx_b_lane_offset; | ||
738 | unsigned int rx_b_lane_offset; | ||
739 | 739 | ||
740 | /* true, if PCS block has no separate SW_RESET register */ | 740 | /* true, if PCS block has no separate SW_RESET register */ |
741 | bool no_pcs_sw_reset; | 741 | bool no_pcs_sw_reset; |
@@ -748,6 +748,8 @@ struct qmp_phy_cfg { | |||
748 | * @tx: iomapped memory space for lane's tx | 748 | * @tx: iomapped memory space for lane's tx |
749 | * @rx: iomapped memory space for lane's rx | 749 | * @rx: iomapped memory space for lane's rx |
750 | * @pcs: iomapped memory space for lane's pcs | 750 | * @pcs: iomapped memory space for lane's pcs |
751 | * @tx2: iomapped memory space for second lane's tx (in dual lane PHYs) | ||
752 | * @rx2: iomapped memory space for second lane's rx (in dual lane PHYs) | ||
751 | * @pcs_misc: iomapped memory space for lane's pcs_misc | 753 | * @pcs_misc: iomapped memory space for lane's pcs_misc |
752 | * @pipe_clk: pipe lock | 754 | * @pipe_clk: pipe lock |
753 | * @index: lane index | 755 | * @index: lane index |
@@ -759,6 +761,8 @@ struct qmp_phy { | |||
759 | void __iomem *tx; | 761 | void __iomem *tx; |
760 | void __iomem *rx; | 762 | void __iomem *rx; |
761 | void __iomem *pcs; | 763 | void __iomem *pcs; |
764 | void __iomem *tx2; | ||
765 | void __iomem *rx2; | ||
762 | void __iomem *pcs_misc; | 766 | void __iomem *pcs_misc; |
763 | struct clk *pipe_clk; | 767 | struct clk *pipe_clk; |
764 | unsigned int index; | 768 | unsigned int index; |
@@ -975,8 +979,6 @@ static const struct qmp_phy_cfg qmp_v3_usb3phy_cfg = { | |||
975 | 979 | ||
976 | .has_phy_dp_com_ctrl = true, | 980 | .has_phy_dp_com_ctrl = true, |
977 | .is_dual_lane_phy = true, | 981 | .is_dual_lane_phy = true, |
978 | .tx_b_lane_offset = 0x400, | ||
979 | .rx_b_lane_offset = 0x400, | ||
980 | }; | 982 | }; |
981 | 983 | ||
982 | static const struct qmp_phy_cfg qmp_v3_usb3_uniphy_cfg = { | 984 | static const struct qmp_phy_cfg qmp_v3_usb3_uniphy_cfg = { |
@@ -1031,9 +1033,6 @@ static const struct qmp_phy_cfg sdm845_ufsphy_cfg = { | |||
1031 | .mask_pcs_ready = PCS_READY, | 1033 | .mask_pcs_ready = PCS_READY, |
1032 | 1034 | ||
1033 | .is_dual_lane_phy = true, | 1035 | .is_dual_lane_phy = true, |
1034 | .tx_b_lane_offset = 0x400, | ||
1035 | .rx_b_lane_offset = 0x400, | ||
1036 | |||
1037 | .no_pcs_sw_reset = true, | 1036 | .no_pcs_sw_reset = true, |
1038 | }; | 1037 | }; |
1039 | 1038 | ||
@@ -1238,12 +1237,12 @@ static int qcom_qmp_phy_init(struct phy *phy) | |||
1238 | qcom_qmp_phy_configure(tx, cfg->regs, cfg->tx_tbl, cfg->tx_tbl_num); | 1237 | qcom_qmp_phy_configure(tx, cfg->regs, cfg->tx_tbl, cfg->tx_tbl_num); |
1239 | /* Configuration for other LANE for USB-DP combo PHY */ | 1238 | /* Configuration for other LANE for USB-DP combo PHY */ |
1240 | if (cfg->is_dual_lane_phy) | 1239 | if (cfg->is_dual_lane_phy) |
1241 | qcom_qmp_phy_configure(tx + cfg->tx_b_lane_offset, cfg->regs, | 1240 | qcom_qmp_phy_configure(qphy->tx2, cfg->regs, |
1242 | cfg->tx_tbl, cfg->tx_tbl_num); | 1241 | cfg->tx_tbl, cfg->tx_tbl_num); |
1243 | 1242 | ||
1244 | qcom_qmp_phy_configure(rx, cfg->regs, cfg->rx_tbl, cfg->rx_tbl_num); | 1243 | qcom_qmp_phy_configure(rx, cfg->regs, cfg->rx_tbl, cfg->rx_tbl_num); |
1245 | if (cfg->is_dual_lane_phy) | 1244 | if (cfg->is_dual_lane_phy) |
1246 | qcom_qmp_phy_configure(rx + cfg->rx_b_lane_offset, cfg->regs, | 1245 | qcom_qmp_phy_configure(qphy->rx2, cfg->regs, |
1247 | cfg->rx_tbl, cfg->rx_tbl_num); | 1246 | cfg->rx_tbl, cfg->rx_tbl_num); |
1248 | 1247 | ||
1249 | qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); | 1248 | qcom_qmp_phy_configure(pcs, cfg->regs, cfg->pcs_tbl, cfg->pcs_tbl_num); |
@@ -1365,7 +1364,8 @@ static int qcom_qmp_phy_poweron(struct phy *phy) | |||
1365 | return ret; | 1364 | return ret; |
1366 | } | 1365 | } |
1367 | 1366 | ||
1368 | static int qcom_qmp_phy_set_mode(struct phy *phy, enum phy_mode mode) | 1367 | static int qcom_qmp_phy_set_mode(struct phy *phy, |
1368 | enum phy_mode mode, int submode) | ||
1369 | { | 1369 | { |
1370 | struct qmp_phy *qphy = phy_get_drvdata(phy); | 1370 | struct qmp_phy *qphy = phy_get_drvdata(phy); |
1371 | struct qcom_qmp *qmp = qphy->qmp; | 1371 | struct qcom_qmp *qmp = qphy->qmp; |
@@ -1542,6 +1542,11 @@ static int qcom_qmp_phy_clk_init(struct device *dev) | |||
1542 | return devm_clk_bulk_get(dev, num, qmp->clks); | 1542 | return devm_clk_bulk_get(dev, num, qmp->clks); |
1543 | } | 1543 | } |
1544 | 1544 | ||
1545 | static void phy_pipe_clk_release_provider(void *res) | ||
1546 | { | ||
1547 | of_clk_del_provider(res); | ||
1548 | } | ||
1549 | |||
1545 | /* | 1550 | /* |
1546 | * Register a fixed rate pipe clock. | 1551 | * Register a fixed rate pipe clock. |
1547 | * | 1552 | * |
@@ -1588,7 +1593,23 @@ static int phy_pipe_clk_register(struct qcom_qmp *qmp, struct device_node *np) | |||
1588 | fixed->fixed_rate = 125000000; | 1593 | fixed->fixed_rate = 125000000; |
1589 | fixed->hw.init = &init; | 1594 | fixed->hw.init = &init; |
1590 | 1595 | ||
1591 | return devm_clk_hw_register(qmp->dev, &fixed->hw); | 1596 | ret = devm_clk_hw_register(qmp->dev, &fixed->hw); |
1597 | if (ret) | ||
1598 | return ret; | ||
1599 | |||
1600 | ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, &fixed->hw); | ||
1601 | if (ret) | ||
1602 | return ret; | ||
1603 | |||
1604 | /* | ||
1605 | * Roll a devm action because the clock provider is the child node, but | ||
1606 | * the child node is not actually a device. | ||
1607 | */ | ||
1608 | ret = devm_add_action(qmp->dev, phy_pipe_clk_release_provider, np); | ||
1609 | if (ret) | ||
1610 | phy_pipe_clk_release_provider(np); | ||
1611 | |||
1612 | return ret; | ||
1592 | } | 1613 | } |
1593 | 1614 | ||
1594 | static const struct phy_ops qcom_qmp_phy_gen_ops = { | 1615 | static const struct phy_ops qcom_qmp_phy_gen_ops = { |
@@ -1614,8 +1635,9 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id) | |||
1614 | 1635 | ||
1615 | /* | 1636 | /* |
1616 | * Get memory resources for each phy lane: | 1637 | * Get memory resources for each phy lane: |
1617 | * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2; and | 1638 | * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2. |
1618 | * pcs_misc (optional) -> 3. | 1639 | * For dual lane PHYs: tx2 -> 3, rx2 -> 4, pcs_misc (optional) -> 5 |
1640 | * For single lane PHYs: pcs_misc (optional) -> 3. | ||
1619 | */ | 1641 | */ |
1620 | qphy->tx = of_iomap(np, 0); | 1642 | qphy->tx = of_iomap(np, 0); |
1621 | if (!qphy->tx) | 1643 | if (!qphy->tx) |
@@ -1629,7 +1651,32 @@ int qcom_qmp_phy_create(struct device *dev, struct device_node *np, int id) | |||
1629 | if (!qphy->pcs) | 1651 | if (!qphy->pcs) |
1630 | return -ENOMEM; | 1652 | return -ENOMEM; |
1631 | 1653 | ||
1632 | qphy->pcs_misc = of_iomap(np, 3); | 1654 | /* |
1655 | * If this is a dual-lane PHY, then there should be registers for the | ||
1656 | * second lane. Some old device trees did not specify this, so fall | ||
1657 | * back to old legacy behavior of assuming they can be reached at an | ||
1658 | * offset from the first lane. | ||
1659 | */ | ||
1660 | if (qmp->cfg->is_dual_lane_phy) { | ||
1661 | qphy->tx2 = of_iomap(np, 3); | ||
1662 | qphy->rx2 = of_iomap(np, 4); | ||
1663 | if (!qphy->tx2 || !qphy->rx2) { | ||
1664 | dev_warn(dev, | ||
1665 | "Underspecified device tree, falling back to legacy register regions\n"); | ||
1666 | |||
1667 | /* In the old version, pcs_misc is at index 3. */ | ||
1668 | qphy->pcs_misc = qphy->tx2; | ||
1669 | qphy->tx2 = qphy->tx + QMP_PHY_LEGACY_LANE_STRIDE; | ||
1670 | qphy->rx2 = qphy->rx + QMP_PHY_LEGACY_LANE_STRIDE; | ||
1671 | |||
1672 | } else { | ||
1673 | qphy->pcs_misc = of_iomap(np, 5); | ||
1674 | } | ||
1675 | |||
1676 | } else { | ||
1677 | qphy->pcs_misc = of_iomap(np, 3); | ||
1678 | } | ||
1679 | |||
1633 | if (!qphy->pcs_misc) | 1680 | if (!qphy->pcs_misc) |
1634 | dev_vdbg(dev, "PHY pcs_misc-reg not used\n"); | 1681 | dev_vdbg(dev, "PHY pcs_misc-reg not used\n"); |
1635 | 1682 | ||
diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c index 6d4b44b569bc..9177989f22d1 100644 --- a/drivers/phy/qualcomm/phy-qcom-qusb2.c +++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c | |||
@@ -425,7 +425,8 @@ static void qusb2_phy_set_tune2_param(struct qusb2_phy *qphy) | |||
425 | HSTX_TRIM_MASK); | 425 | HSTX_TRIM_MASK); |
426 | } | 426 | } |
427 | 427 | ||
428 | static int qusb2_phy_set_mode(struct phy *phy, enum phy_mode mode) | 428 | static int qusb2_phy_set_mode(struct phy *phy, |
429 | enum phy_mode mode, int submode) | ||
429 | { | 430 | { |
430 | struct qusb2_phy *qphy = phy_get_drvdata(phy); | 431 | struct qusb2_phy *qphy = phy_get_drvdata(phy); |
431 | 432 | ||
diff --git a/drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.c b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.c index ba1895b76a5d..1e0d4f2046a4 100644 --- a/drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.c +++ b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.c | |||
@@ -65,7 +65,8 @@ static int ufs_qcom_phy_qmp_14nm_exit(struct phy *generic_phy) | |||
65 | } | 65 | } |
66 | 66 | ||
67 | static | 67 | static |
68 | int ufs_qcom_phy_qmp_14nm_set_mode(struct phy *generic_phy, enum phy_mode mode) | 68 | int ufs_qcom_phy_qmp_14nm_set_mode(struct phy *generic_phy, |
69 | enum phy_mode mode, int submode) | ||
69 | { | 70 | { |
70 | struct ufs_qcom_phy *phy_common = get_ufs_qcom_phy(generic_phy); | 71 | struct ufs_qcom_phy *phy_common = get_ufs_qcom_phy(generic_phy); |
71 | 72 | ||
diff --git a/drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.c b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.c index 49f435c71147..aef40f7a41d4 100644 --- a/drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.c +++ b/drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.c | |||
@@ -84,7 +84,8 @@ static int ufs_qcom_phy_qmp_20nm_exit(struct phy *generic_phy) | |||
84 | } | 84 | } |
85 | 85 | ||
86 | static | 86 | static |
87 | int ufs_qcom_phy_qmp_20nm_set_mode(struct phy *generic_phy, enum phy_mode mode) | 87 | int ufs_qcom_phy_qmp_20nm_set_mode(struct phy *generic_phy, |
88 | enum phy_mode mode, int submode) | ||
88 | { | 89 | { |
89 | struct ufs_qcom_phy *phy_common = get_ufs_qcom_phy(generic_phy); | 90 | struct ufs_qcom_phy *phy_common = get_ufs_qcom_phy(generic_phy); |
90 | 91 | ||
diff --git a/drivers/phy/qualcomm/phy-qcom-usb-hs.c b/drivers/phy/qualcomm/phy-qcom-usb-hs.c index abbbe75070da..04934f8dac91 100644 --- a/drivers/phy/qualcomm/phy-qcom-usb-hs.c +++ b/drivers/phy/qualcomm/phy-qcom-usb-hs.c | |||
@@ -42,7 +42,8 @@ struct qcom_usb_hs_phy { | |||
42 | struct notifier_block vbus_notify; | 42 | struct notifier_block vbus_notify; |
43 | }; | 43 | }; |
44 | 44 | ||
45 | static int qcom_usb_hs_phy_set_mode(struct phy *phy, enum phy_mode mode) | 45 | static int qcom_usb_hs_phy_set_mode(struct phy *phy, |
46 | enum phy_mode mode, int submode) | ||
46 | { | 47 | { |
47 | struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy); | 48 | struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy); |
48 | u8 addr; | 49 | u8 addr; |
diff --git a/drivers/phy/renesas/phy-rcar-gen3-usb2.c b/drivers/phy/renesas/phy-rcar-gen3-usb2.c index d0f412c25981..0a34782aaaa2 100644 --- a/drivers/phy/renesas/phy-rcar-gen3-usb2.c +++ b/drivers/phy/renesas/phy-rcar-gen3-usb2.c | |||
@@ -307,16 +307,21 @@ static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch) | |||
307 | void __iomem *usb2_base = ch->base; | 307 | void __iomem *usb2_base = ch->base; |
308 | u32 val; | 308 | u32 val; |
309 | 309 | ||
310 | /* Should not use functions of read-modify-write a register */ | ||
311 | val = readl(usb2_base + USB2_LINECTRL1); | ||
312 | val = (val & ~USB2_LINECTRL1_DP_RPD) | USB2_LINECTRL1_DPRPD_EN | | ||
313 | USB2_LINECTRL1_DMRPD_EN | USB2_LINECTRL1_DM_RPD; | ||
314 | writel(val, usb2_base + USB2_LINECTRL1); | ||
315 | |||
310 | val = readl(usb2_base + USB2_VBCTRL); | 316 | val = readl(usb2_base + USB2_VBCTRL); |
311 | writel(val | USB2_VBCTRL_DRVVBUSSEL, usb2_base + USB2_VBCTRL); | 317 | writel(val | USB2_VBCTRL_DRVVBUSSEL, usb2_base + USB2_VBCTRL); |
312 | writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTSTA); | ||
313 | rcar_gen3_control_otg_irq(ch, 1); | ||
314 | val = readl(usb2_base + USB2_ADPCTRL); | 318 | val = readl(usb2_base + USB2_ADPCTRL); |
315 | writel(val | USB2_ADPCTRL_IDPULLUP, usb2_base + USB2_ADPCTRL); | 319 | writel(val | USB2_ADPCTRL_IDPULLUP, usb2_base + USB2_ADPCTRL); |
316 | val = readl(usb2_base + USB2_LINECTRL1); | 320 | |
317 | rcar_gen3_set_linectrl(ch, 0, 0); | 321 | msleep(20); |
318 | writel(val | USB2_LINECTRL1_DPRPD_EN | USB2_LINECTRL1_DMRPD_EN, | 322 | |
319 | usb2_base + USB2_LINECTRL1); | 323 | writel(0xffffffff, usb2_base + USB2_OBINTSTA); |
324 | writel(USB2_OBINT_BITS, usb2_base + USB2_OBINTEN); | ||
320 | 325 | ||
321 | rcar_gen3_device_recognition(ch); | 326 | rcar_gen3_device_recognition(ch); |
322 | } | 327 | } |
diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c index 24bd2717abdb..91fba60267a0 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c | |||
@@ -1168,8 +1168,8 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev) | |||
1168 | struct phy *phy; | 1168 | struct phy *phy; |
1169 | 1169 | ||
1170 | /* This driver aims to support both otg-port and host-port */ | 1170 | /* This driver aims to support both otg-port and host-port */ |
1171 | if (of_node_cmp(child_np->name, "host-port") && | 1171 | if (!of_node_name_eq(child_np, "host-port") && |
1172 | of_node_cmp(child_np->name, "otg-port")) | 1172 | !of_node_name_eq(child_np, "otg-port")) |
1173 | goto next_child; | 1173 | goto next_child; |
1174 | 1174 | ||
1175 | phy = devm_phy_create(dev, child_np, &rockchip_usb2phy_ops); | 1175 | phy = devm_phy_create(dev, child_np, &rockchip_usb2phy_ops); |
@@ -1183,7 +1183,7 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev) | |||
1183 | phy_set_drvdata(rport->phy, rport); | 1183 | phy_set_drvdata(rport->phy, rport); |
1184 | 1184 | ||
1185 | /* initialize otg/host port separately */ | 1185 | /* initialize otg/host port separately */ |
1186 | if (!of_node_cmp(child_np->name, "host-port")) { | 1186 | if (of_node_name_eq(child_np, "host-port")) { |
1187 | ret = rockchip_usb2phy_host_port_init(rphy, rport, | 1187 | ret = rockchip_usb2phy_host_port_init(rphy, rport, |
1188 | child_np); | 1188 | child_np); |
1189 | if (ret) | 1189 | if (ret) |
diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c b/drivers/phy/rockchip/phy-rockchip-typec.c index c57e496f0b0c..e32edeebcd63 100644 --- a/drivers/phy/rockchip/phy-rockchip-typec.c +++ b/drivers/phy/rockchip/phy-rockchip-typec.c | |||
@@ -1176,10 +1176,10 @@ static int rockchip_typec_phy_probe(struct platform_device *pdev) | |||
1176 | for_each_available_child_of_node(np, child_np) { | 1176 | for_each_available_child_of_node(np, child_np) { |
1177 | struct phy *phy; | 1177 | struct phy *phy; |
1178 | 1178 | ||
1179 | if (!of_node_cmp(child_np->name, "dp-port")) | 1179 | if (of_node_name_eq(child_np, "dp-port")) |
1180 | phy = devm_phy_create(dev, child_np, | 1180 | phy = devm_phy_create(dev, child_np, |
1181 | &rockchip_dp_phy_ops); | 1181 | &rockchip_dp_phy_ops); |
1182 | else if (!of_node_cmp(child_np->name, "usb3-port")) | 1182 | else if (of_node_name_eq(child_np, "usb3-port")) |
1183 | phy = devm_phy_create(dev, child_np, | 1183 | phy = devm_phy_create(dev, child_np, |
1184 | &rockchip_usb3_phy_ops); | 1184 | &rockchip_usb3_phy_ops); |
1185 | else | 1185 | else |
diff --git a/drivers/phy/ti/Kconfig b/drivers/phy/ti/Kconfig index 20503562666c..f137e0107764 100644 --- a/drivers/phy/ti/Kconfig +++ b/drivers/phy/ti/Kconfig | |||
@@ -76,3 +76,13 @@ config TWL4030_USB | |||
76 | family chips (including the TWL5030 and TPS659x0 devices). | 76 | family chips (including the TWL5030 and TPS659x0 devices). |
77 | This transceiver supports high and full speed devices plus, | 77 | This transceiver supports high and full speed devices plus, |
78 | in host mode, low speed. | 78 | in host mode, low speed. |
79 | |||
80 | config PHY_TI_GMII_SEL | ||
81 | tristate | ||
82 | default y if TI_CPSW=y | ||
83 | depends on TI_CPSW || COMPILE_TEST | ||
84 | select GENERIC_PHY | ||
85 | default m | ||
86 | help | ||
87 | This driver supports configuring of the TI CPSW Port mode depending on | ||
88 | the Ethernet PHY connected to the CPSW Port. | ||
diff --git a/drivers/phy/ti/Makefile b/drivers/phy/ti/Makefile index 9f361756eaf2..bea8f25a137a 100644 --- a/drivers/phy/ti/Makefile +++ b/drivers/phy/ti/Makefile | |||
@@ -6,3 +6,4 @@ obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o | |||
6 | obj-$(CONFIG_TI_PIPE3) += phy-ti-pipe3.o | 6 | obj-$(CONFIG_TI_PIPE3) += phy-ti-pipe3.o |
7 | obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o | 7 | obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o |
8 | obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o | 8 | obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o |
9 | obj-$(CONFIG_PHY_TI_GMII_SEL) += phy-gmii-sel.o | ||
diff --git a/drivers/phy/ti/phy-da8xx-usb.c b/drivers/phy/ti/phy-da8xx-usb.c index befb886ff121..d5f4fbc32b52 100644 --- a/drivers/phy/ti/phy-da8xx-usb.c +++ b/drivers/phy/ti/phy-da8xx-usb.c | |||
@@ -93,7 +93,8 @@ static int da8xx_usb20_phy_power_off(struct phy *phy) | |||
93 | return 0; | 93 | return 0; |
94 | } | 94 | } |
95 | 95 | ||
96 | static int da8xx_usb20_phy_set_mode(struct phy *phy, enum phy_mode mode) | 96 | static int da8xx_usb20_phy_set_mode(struct phy *phy, |
97 | enum phy_mode mode, int submode) | ||
97 | { | 98 | { |
98 | struct da8xx_usb_phy *d_phy = phy_get_drvdata(phy); | 99 | struct da8xx_usb_phy *d_phy = phy_get_drvdata(phy); |
99 | u32 val; | 100 | u32 val; |
diff --git a/drivers/phy/ti/phy-gmii-sel.c b/drivers/phy/ti/phy-gmii-sel.c new file mode 100644 index 000000000000..77fdaa551977 --- /dev/null +++ b/drivers/phy/ti/phy-gmii-sel.c | |||
@@ -0,0 +1,349 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * Texas Instruments CPSW Port's PHY Interface Mode selection Driver | ||
4 | * | ||
5 | * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ | ||
6 | * | ||
7 | * Based on cpsw-phy-sel.c driver created by Mugunthan V N <mugunthanvnm@ti.com> | ||
8 | */ | ||
9 | |||
10 | #include <linux/platform_device.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/mfd/syscon.h> | ||
13 | #include <linux/of.h> | ||
14 | #include <linux/of_net.h> | ||
15 | #include <linux/phy.h> | ||
16 | #include <linux/phy/phy.h> | ||
17 | #include <linux/regmap.h> | ||
18 | |||
19 | /* AM33xx SoC specific definitions for the CONTROL port */ | ||
20 | #define AM33XX_GMII_SEL_MODE_MII 0 | ||
21 | #define AM33XX_GMII_SEL_MODE_RMII 1 | ||
22 | #define AM33XX_GMII_SEL_MODE_RGMII 2 | ||
23 | |||
24 | enum { | ||
25 | PHY_GMII_SEL_PORT_MODE, | ||
26 | PHY_GMII_SEL_RGMII_ID_MODE, | ||
27 | PHY_GMII_SEL_RMII_IO_CLK_EN, | ||
28 | PHY_GMII_SEL_LAST, | ||
29 | }; | ||
30 | |||
31 | struct phy_gmii_sel_phy_priv { | ||
32 | struct phy_gmii_sel_priv *priv; | ||
33 | u32 id; | ||
34 | struct phy *if_phy; | ||
35 | int rmii_clock_external; | ||
36 | int phy_if_mode; | ||
37 | struct regmap_field *fields[PHY_GMII_SEL_LAST]; | ||
38 | }; | ||
39 | |||
40 | struct phy_gmii_sel_soc_data { | ||
41 | u32 num_ports; | ||
42 | u32 features; | ||
43 | const struct reg_field (*regfields)[PHY_GMII_SEL_LAST]; | ||
44 | }; | ||
45 | |||
46 | struct phy_gmii_sel_priv { | ||
47 | struct device *dev; | ||
48 | const struct phy_gmii_sel_soc_data *soc_data; | ||
49 | struct regmap *regmap; | ||
50 | struct phy_provider *phy_provider; | ||
51 | struct phy_gmii_sel_phy_priv *if_phys; | ||
52 | }; | ||
53 | |||
54 | static int phy_gmii_sel_mode(struct phy *phy, enum phy_mode mode, int submode) | ||
55 | { | ||
56 | struct phy_gmii_sel_phy_priv *if_phy = phy_get_drvdata(phy); | ||
57 | const struct phy_gmii_sel_soc_data *soc_data = if_phy->priv->soc_data; | ||
58 | struct device *dev = if_phy->priv->dev; | ||
59 | struct regmap_field *regfield; | ||
60 | int ret, rgmii_id = 0; | ||
61 | u32 gmii_sel_mode = 0; | ||
62 | |||
63 | if (mode != PHY_MODE_ETHERNET) | ||
64 | return -EINVAL; | ||
65 | |||
66 | switch (submode) { | ||
67 | case PHY_INTERFACE_MODE_RMII: | ||
68 | gmii_sel_mode = AM33XX_GMII_SEL_MODE_RMII; | ||
69 | break; | ||
70 | |||
71 | case PHY_INTERFACE_MODE_RGMII: | ||
72 | gmii_sel_mode = AM33XX_GMII_SEL_MODE_RGMII; | ||
73 | break; | ||
74 | |||
75 | case PHY_INTERFACE_MODE_RGMII_ID: | ||
76 | case PHY_INTERFACE_MODE_RGMII_RXID: | ||
77 | case PHY_INTERFACE_MODE_RGMII_TXID: | ||
78 | gmii_sel_mode = AM33XX_GMII_SEL_MODE_RGMII; | ||
79 | rgmii_id = 1; | ||
80 | break; | ||
81 | |||
82 | case PHY_INTERFACE_MODE_MII: | ||
83 | mode = AM33XX_GMII_SEL_MODE_MII; | ||
84 | break; | ||
85 | |||
86 | default: | ||
87 | dev_warn(dev, | ||
88 | "port%u: unsupported mode: \"%s\". Defaulting to MII.\n", | ||
89 | if_phy->id, phy_modes(rgmii_id)); | ||
90 | return -EINVAL; | ||
91 | } | ||
92 | |||
93 | if_phy->phy_if_mode = submode; | ||
94 | |||
95 | dev_dbg(dev, "%s id:%u mode:%u rgmii_id:%d rmii_clk_ext:%d\n", | ||
96 | __func__, if_phy->id, mode, rgmii_id, | ||
97 | if_phy->rmii_clock_external); | ||
98 | |||
99 | regfield = if_phy->fields[PHY_GMII_SEL_PORT_MODE]; | ||
100 | ret = regmap_field_write(regfield, gmii_sel_mode); | ||
101 | if (ret) { | ||
102 | dev_err(dev, "port%u: set mode fail %d", if_phy->id, ret); | ||
103 | return ret; | ||
104 | } | ||
105 | |||
106 | if (soc_data->features & BIT(PHY_GMII_SEL_RGMII_ID_MODE) && | ||
107 | if_phy->fields[PHY_GMII_SEL_RGMII_ID_MODE]) { | ||
108 | regfield = if_phy->fields[PHY_GMII_SEL_RGMII_ID_MODE]; | ||
109 | ret = regmap_field_write(regfield, rgmii_id); | ||
110 | if (ret) | ||
111 | return ret; | ||
112 | } | ||
113 | |||
114 | if (soc_data->features & BIT(PHY_GMII_SEL_RMII_IO_CLK_EN) && | ||
115 | if_phy->fields[PHY_GMII_SEL_RMII_IO_CLK_EN]) { | ||
116 | regfield = if_phy->fields[PHY_GMII_SEL_RMII_IO_CLK_EN]; | ||
117 | ret = regmap_field_write(regfield, | ||
118 | if_phy->rmii_clock_external); | ||
119 | } | ||
120 | |||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | static const | ||
125 | struct reg_field phy_gmii_sel_fields_am33xx[][PHY_GMII_SEL_LAST] = { | ||
126 | { | ||
127 | [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x650, 0, 1), | ||
128 | [PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD(0x650, 4, 4), | ||
129 | [PHY_GMII_SEL_RMII_IO_CLK_EN] = REG_FIELD(0x650, 6, 6), | ||
130 | }, | ||
131 | { | ||
132 | [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x650, 2, 3), | ||
133 | [PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD(0x650, 5, 5), | ||
134 | [PHY_GMII_SEL_RMII_IO_CLK_EN] = REG_FIELD(0x650, 7, 7), | ||
135 | }, | ||
136 | }; | ||
137 | |||
138 | static const | ||
139 | struct phy_gmii_sel_soc_data phy_gmii_sel_soc_am33xx = { | ||
140 | .num_ports = 2, | ||
141 | .features = BIT(PHY_GMII_SEL_RGMII_ID_MODE) | | ||
142 | BIT(PHY_GMII_SEL_RMII_IO_CLK_EN), | ||
143 | .regfields = phy_gmii_sel_fields_am33xx, | ||
144 | }; | ||
145 | |||
146 | static const | ||
147 | struct reg_field phy_gmii_sel_fields_dra7[][PHY_GMII_SEL_LAST] = { | ||
148 | { | ||
149 | [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x554, 0, 1), | ||
150 | [PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD((~0), 0, 0), | ||
151 | [PHY_GMII_SEL_RMII_IO_CLK_EN] = REG_FIELD((~0), 0, 0), | ||
152 | }, | ||
153 | { | ||
154 | [PHY_GMII_SEL_PORT_MODE] = REG_FIELD(0x554, 4, 5), | ||
155 | [PHY_GMII_SEL_RGMII_ID_MODE] = REG_FIELD((~0), 0, 0), | ||
156 | [PHY_GMII_SEL_RMII_IO_CLK_EN] = REG_FIELD((~0), 0, 0), | ||
157 | }, | ||
158 | }; | ||
159 | |||
160 | static const | ||
161 | struct phy_gmii_sel_soc_data phy_gmii_sel_soc_dra7 = { | ||
162 | .num_ports = 2, | ||
163 | .regfields = phy_gmii_sel_fields_dra7, | ||
164 | }; | ||
165 | |||
166 | static const | ||
167 | struct phy_gmii_sel_soc_data phy_gmii_sel_soc_dm814 = { | ||
168 | .num_ports = 2, | ||
169 | .features = BIT(PHY_GMII_SEL_RGMII_ID_MODE), | ||
170 | .regfields = phy_gmii_sel_fields_am33xx, | ||
171 | }; | ||
172 | |||
173 | static const struct of_device_id phy_gmii_sel_id_table[] = { | ||
174 | { | ||
175 | .compatible = "ti,am3352-phy-gmii-sel", | ||
176 | .data = &phy_gmii_sel_soc_am33xx, | ||
177 | }, | ||
178 | { | ||
179 | .compatible = "ti,dra7xx-phy-gmii-sel", | ||
180 | .data = &phy_gmii_sel_soc_dra7, | ||
181 | }, | ||
182 | { | ||
183 | .compatible = "ti,am43xx-phy-gmii-sel", | ||
184 | .data = &phy_gmii_sel_soc_am33xx, | ||
185 | }, | ||
186 | { | ||
187 | .compatible = "ti,dm814-phy-gmii-sel", | ||
188 | .data = &phy_gmii_sel_soc_dm814, | ||
189 | }, | ||
190 | {} | ||
191 | }; | ||
192 | MODULE_DEVICE_TABLE(of, phy_gmii_sel_id_table); | ||
193 | |||
194 | static const struct phy_ops phy_gmii_sel_ops = { | ||
195 | .set_mode = phy_gmii_sel_mode, | ||
196 | .owner = THIS_MODULE, | ||
197 | }; | ||
198 | |||
199 | static struct phy *phy_gmii_sel_of_xlate(struct device *dev, | ||
200 | struct of_phandle_args *args) | ||
201 | { | ||
202 | struct phy_gmii_sel_priv *priv = dev_get_drvdata(dev); | ||
203 | int phy_id = args->args[0]; | ||
204 | |||
205 | if (args->args_count < 1) | ||
206 | return ERR_PTR(-EINVAL); | ||
207 | if (priv->soc_data->features & BIT(PHY_GMII_SEL_RMII_IO_CLK_EN) && | ||
208 | args->args_count < 2) | ||
209 | return ERR_PTR(-EINVAL); | ||
210 | if (!priv || !priv->if_phys) | ||
211 | return ERR_PTR(-ENODEV); | ||
212 | if (phy_id > priv->soc_data->num_ports) | ||
213 | return ERR_PTR(-EINVAL); | ||
214 | if (phy_id != priv->if_phys[phy_id - 1].id) | ||
215 | return ERR_PTR(-EINVAL); | ||
216 | |||
217 | phy_id--; | ||
218 | if (priv->soc_data->features & BIT(PHY_GMII_SEL_RMII_IO_CLK_EN)) | ||
219 | priv->if_phys[phy_id].rmii_clock_external = args->args[1]; | ||
220 | dev_dbg(dev, "%s id:%u ext:%d\n", __func__, | ||
221 | priv->if_phys[phy_id].id, args->args[1]); | ||
222 | |||
223 | return priv->if_phys[phy_id].if_phy; | ||
224 | } | ||
225 | |||
226 | static int phy_gmii_sel_init_ports(struct phy_gmii_sel_priv *priv) | ||
227 | { | ||
228 | const struct phy_gmii_sel_soc_data *soc_data = priv->soc_data; | ||
229 | struct device *dev = priv->dev; | ||
230 | struct phy_gmii_sel_phy_priv *if_phys; | ||
231 | int i, num_ports, ret; | ||
232 | |||
233 | num_ports = priv->soc_data->num_ports; | ||
234 | |||
235 | if_phys = devm_kcalloc(priv->dev, num_ports, | ||
236 | sizeof(*if_phys), GFP_KERNEL); | ||
237 | if (!if_phys) | ||
238 | return -ENOMEM; | ||
239 | dev_dbg(dev, "%s %d\n", __func__, num_ports); | ||
240 | |||
241 | for (i = 0; i < num_ports; i++) { | ||
242 | const struct reg_field *field; | ||
243 | struct regmap_field *regfield; | ||
244 | |||
245 | if_phys[i].id = i + 1; | ||
246 | if_phys[i].priv = priv; | ||
247 | |||
248 | field = &soc_data->regfields[i][PHY_GMII_SEL_PORT_MODE]; | ||
249 | dev_dbg(dev, "%s field %x %d %d\n", __func__, | ||
250 | field->reg, field->msb, field->lsb); | ||
251 | |||
252 | regfield = devm_regmap_field_alloc(dev, priv->regmap, *field); | ||
253 | if (IS_ERR(regfield)) | ||
254 | return PTR_ERR(regfield); | ||
255 | if_phys[i].fields[PHY_GMII_SEL_PORT_MODE] = regfield; | ||
256 | |||
257 | field = &soc_data->regfields[i][PHY_GMII_SEL_RGMII_ID_MODE]; | ||
258 | if (field->reg != (~0)) { | ||
259 | regfield = devm_regmap_field_alloc(dev, | ||
260 | priv->regmap, | ||
261 | *field); | ||
262 | if (IS_ERR(regfield)) | ||
263 | return PTR_ERR(regfield); | ||
264 | if_phys[i].fields[PHY_GMII_SEL_RGMII_ID_MODE] = | ||
265 | regfield; | ||
266 | } | ||
267 | |||
268 | field = &soc_data->regfields[i][PHY_GMII_SEL_RMII_IO_CLK_EN]; | ||
269 | if (field->reg != (~0)) { | ||
270 | regfield = devm_regmap_field_alloc(dev, | ||
271 | priv->regmap, | ||
272 | *field); | ||
273 | if (IS_ERR(regfield)) | ||
274 | return PTR_ERR(regfield); | ||
275 | if_phys[i].fields[PHY_GMII_SEL_RMII_IO_CLK_EN] = | ||
276 | regfield; | ||
277 | } | ||
278 | |||
279 | if_phys[i].if_phy = devm_phy_create(dev, | ||
280 | priv->dev->of_node, | ||
281 | &phy_gmii_sel_ops); | ||
282 | if (IS_ERR(if_phys[i].if_phy)) { | ||
283 | ret = PTR_ERR(if_phys[i].if_phy); | ||
284 | dev_err(dev, "Failed to create phy%d %d\n", i, ret); | ||
285 | return ret; | ||
286 | } | ||
287 | phy_set_drvdata(if_phys[i].if_phy, &if_phys[i]); | ||
288 | } | ||
289 | |||
290 | priv->if_phys = if_phys; | ||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | static int phy_gmii_sel_probe(struct platform_device *pdev) | ||
295 | { | ||
296 | struct device *dev = &pdev->dev; | ||
297 | struct device_node *node = dev->of_node; | ||
298 | const struct of_device_id *of_id; | ||
299 | struct phy_gmii_sel_priv *priv; | ||
300 | int ret; | ||
301 | |||
302 | of_id = of_match_node(phy_gmii_sel_id_table, pdev->dev.of_node); | ||
303 | if (!of_id) | ||
304 | return -EINVAL; | ||
305 | |||
306 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | ||
307 | if (!priv) | ||
308 | return -ENOMEM; | ||
309 | |||
310 | priv->dev = &pdev->dev; | ||
311 | priv->soc_data = of_id->data; | ||
312 | |||
313 | priv->regmap = syscon_node_to_regmap(node->parent); | ||
314 | if (IS_ERR(priv->regmap)) { | ||
315 | ret = PTR_ERR(priv->regmap); | ||
316 | dev_err(dev, "Failed to get syscon %d\n", ret); | ||
317 | return ret; | ||
318 | } | ||
319 | |||
320 | ret = phy_gmii_sel_init_ports(priv); | ||
321 | if (ret) | ||
322 | return ret; | ||
323 | |||
324 | dev_set_drvdata(&pdev->dev, priv); | ||
325 | |||
326 | priv->phy_provider = | ||
327 | devm_of_phy_provider_register(dev, | ||
328 | phy_gmii_sel_of_xlate); | ||
329 | if (IS_ERR(priv->phy_provider)) { | ||
330 | ret = PTR_ERR(priv->phy_provider); | ||
331 | dev_err(dev, "Failed to create phy provider %d\n", ret); | ||
332 | return ret; | ||
333 | } | ||
334 | |||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | static struct platform_driver phy_gmii_sel_driver = { | ||
339 | .probe = phy_gmii_sel_probe, | ||
340 | .driver = { | ||
341 | .name = "phy-gmii-sel", | ||
342 | .of_match_table = phy_gmii_sel_id_table, | ||
343 | }, | ||
344 | }; | ||
345 | module_platform_driver(phy_gmii_sel_driver); | ||
346 | |||
347 | MODULE_LICENSE("GPL v2"); | ||
348 | MODULE_AUTHOR("Grygorii Strashko <grygorii.strashko@ti.com>"); | ||
349 | MODULE_DESCRIPTION("TI CPSW Port's PHY Interface Mode selection Driver"); | ||
diff --git a/drivers/phy/ti/phy-tusb1210.c b/drivers/phy/ti/phy-tusb1210.c index b8ec39ac4dfc..329fb938099a 100644 --- a/drivers/phy/ti/phy-tusb1210.c +++ b/drivers/phy/ti/phy-tusb1210.c | |||
@@ -53,7 +53,7 @@ static int tusb1210_power_off(struct phy *phy) | |||
53 | return 0; | 53 | return 0; |
54 | } | 54 | } |
55 | 55 | ||
56 | static int tusb1210_set_mode(struct phy *phy, enum phy_mode mode) | 56 | static int tusb1210_set_mode(struct phy *phy, enum phy_mode mode, int submode) |
57 | { | 57 | { |
58 | struct tusb1210 *tusb = phy_get_drvdata(phy); | 58 | struct tusb1210 *tusb = phy_get_drvdata(phy); |
59 | int ret; | 59 | int ret; |
diff --git a/drivers/platform/x86/intel_cht_int33fe.c b/drivers/platform/x86/intel_cht_int33fe.c index 464fe93657b5..87cbf18d0305 100644 --- a/drivers/platform/x86/intel_cht_int33fe.c +++ b/drivers/platform/x86/intel_cht_int33fe.c | |||
@@ -79,7 +79,7 @@ static const struct property_entry max17047_props[] = { | |||
79 | }; | 79 | }; |
80 | 80 | ||
81 | static const struct property_entry fusb302_props[] = { | 81 | static const struct property_entry fusb302_props[] = { |
82 | PROPERTY_ENTRY_STRING("fcs,extcon-name", "cht_wcove_pwrsrc"), | 82 | PROPERTY_ENTRY_STRING("linux,extcon-name", "cht_wcove_pwrsrc"), |
83 | PROPERTY_ENTRY_U32("fcs,max-sink-microvolt", 12000000), | 83 | PROPERTY_ENTRY_U32("fcs,max-sink-microvolt", 12000000), |
84 | PROPERTY_ENTRY_U32("fcs,max-sink-microamp", 3000000), | 84 | PROPERTY_ENTRY_U32("fcs,max-sink-microamp", 3000000), |
85 | PROPERTY_ENTRY_U32("fcs,max-sink-microwatt", 36000000), | 85 | PROPERTY_ENTRY_U32("fcs,max-sink-microwatt", 36000000), |
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 987fc5ba6321..70e6c956c23c 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig | |||
@@ -205,8 +205,4 @@ config USB_ULPI_BUS | |||
205 | To compile this driver as a module, choose M here: the module will | 205 | To compile this driver as a module, choose M here: the module will |
206 | be called ulpi. | 206 | be called ulpi. |
207 | 207 | ||
208 | config USB_ROLE_SWITCH | ||
209 | tristate | ||
210 | select USB_COMMON | ||
211 | |||
212 | endif # USB_SUPPORT | 208 | endif # USB_SUPPORT |
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c index 09b37c0d075d..e81de9ca8729 100644 --- a/drivers/usb/chipidea/ci_hdrc_imx.c +++ b/drivers/usb/chipidea/ci_hdrc_imx.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/usb/chipidea.h> | 14 | #include <linux/usb/chipidea.h> |
15 | #include <linux/usb/of.h> | 15 | #include <linux/usb/of.h> |
16 | #include <linux/clk.h> | 16 | #include <linux/clk.h> |
17 | #include <linux/pinctrl/consumer.h> | ||
17 | 18 | ||
18 | #include "ci.h" | 19 | #include "ci.h" |
19 | #include "ci_hdrc_imx.h" | 20 | #include "ci_hdrc_imx.h" |
@@ -85,6 +86,9 @@ struct ci_hdrc_imx_data { | |||
85 | bool supports_runtime_pm; | 86 | bool supports_runtime_pm; |
86 | bool override_phy_control; | 87 | bool override_phy_control; |
87 | bool in_lpm; | 88 | bool in_lpm; |
89 | struct pinctrl *pinctrl; | ||
90 | struct pinctrl_state *pinctrl_hsic_active; | ||
91 | struct regulator *hsic_pad_regulator; | ||
88 | /* SoC before i.mx6 (except imx23/imx28) needs three clks */ | 92 | /* SoC before i.mx6 (except imx23/imx28) needs three clks */ |
89 | bool need_three_clks; | 93 | bool need_three_clks; |
90 | struct clk *clk_ipg; | 94 | struct clk *clk_ipg; |
@@ -132,11 +136,21 @@ static struct imx_usbmisc_data *usbmisc_get_init_data(struct device *dev) | |||
132 | 136 | ||
133 | data->dev = &misc_pdev->dev; | 137 | data->dev = &misc_pdev->dev; |
134 | 138 | ||
135 | if (of_find_property(np, "disable-over-current", NULL)) | 139 | /* |
140 | * Check the various over current related properties. If over current | ||
141 | * detection is disabled we're not interested in the polarity. | ||
142 | */ | ||
143 | if (of_find_property(np, "disable-over-current", NULL)) { | ||
136 | data->disable_oc = 1; | 144 | data->disable_oc = 1; |
137 | 145 | } else if (of_find_property(np, "over-current-active-high", NULL)) { | |
138 | if (of_find_property(np, "over-current-active-high", NULL)) | 146 | data->oc_pol_active_low = 0; |
139 | data->oc_polarity = 1; | 147 | data->oc_pol_configured = 1; |
148 | } else if (of_find_property(np, "over-current-active-low", NULL)) { | ||
149 | data->oc_pol_active_low = 1; | ||
150 | data->oc_pol_configured = 1; | ||
151 | } else { | ||
152 | dev_warn(dev, "No over current polarity defined\n"); | ||
153 | } | ||
140 | 154 | ||
141 | if (of_find_property(np, "external-vbus-divider", NULL)) | 155 | if (of_find_property(np, "external-vbus-divider", NULL)) |
142 | data->evdo = 1; | 156 | data->evdo = 1; |
@@ -245,19 +259,49 @@ static void imx_disable_unprepare_clks(struct device *dev) | |||
245 | } | 259 | } |
246 | } | 260 | } |
247 | 261 | ||
262 | static int ci_hdrc_imx_notify_event(struct ci_hdrc *ci, unsigned int event) | ||
263 | { | ||
264 | struct device *dev = ci->dev->parent; | ||
265 | struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); | ||
266 | int ret = 0; | ||
267 | |||
268 | switch (event) { | ||
269 | case CI_HDRC_IMX_HSIC_ACTIVE_EVENT: | ||
270 | ret = pinctrl_select_state(data->pinctrl, | ||
271 | data->pinctrl_hsic_active); | ||
272 | if (ret) | ||
273 | dev_err(dev, "hsic_active select failed, err=%d\n", | ||
274 | ret); | ||
275 | break; | ||
276 | case CI_HDRC_IMX_HSIC_SUSPEND_EVENT: | ||
277 | ret = imx_usbmisc_hsic_set_connect(data->usbmisc_data); | ||
278 | if (ret) | ||
279 | dev_err(dev, | ||
280 | "hsic_set_connect failed, err=%d\n", ret); | ||
281 | break; | ||
282 | default: | ||
283 | break; | ||
284 | } | ||
285 | |||
286 | return ret; | ||
287 | } | ||
288 | |||
248 | static int ci_hdrc_imx_probe(struct platform_device *pdev) | 289 | static int ci_hdrc_imx_probe(struct platform_device *pdev) |
249 | { | 290 | { |
250 | struct ci_hdrc_imx_data *data; | 291 | struct ci_hdrc_imx_data *data; |
251 | struct ci_hdrc_platform_data pdata = { | 292 | struct ci_hdrc_platform_data pdata = { |
252 | .name = dev_name(&pdev->dev), | 293 | .name = dev_name(&pdev->dev), |
253 | .capoffset = DEF_CAPOFFSET, | 294 | .capoffset = DEF_CAPOFFSET, |
295 | .notify_event = ci_hdrc_imx_notify_event, | ||
254 | }; | 296 | }; |
255 | int ret; | 297 | int ret; |
256 | const struct of_device_id *of_id; | 298 | const struct of_device_id *of_id; |
257 | const struct ci_hdrc_imx_platform_flag *imx_platform_flag; | 299 | const struct ci_hdrc_imx_platform_flag *imx_platform_flag; |
258 | struct device_node *np = pdev->dev.of_node; | 300 | struct device_node *np = pdev->dev.of_node; |
301 | struct device *dev = &pdev->dev; | ||
302 | struct pinctrl_state *pinctrl_hsic_idle; | ||
259 | 303 | ||
260 | of_id = of_match_device(ci_hdrc_imx_dt_ids, &pdev->dev); | 304 | of_id = of_match_device(ci_hdrc_imx_dt_ids, dev); |
261 | if (!of_id) | 305 | if (!of_id) |
262 | return -ENODEV; | 306 | return -ENODEV; |
263 | 307 | ||
@@ -268,19 +312,73 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) | |||
268 | return -ENOMEM; | 312 | return -ENOMEM; |
269 | 313 | ||
270 | platform_set_drvdata(pdev, data); | 314 | platform_set_drvdata(pdev, data); |
271 | data->usbmisc_data = usbmisc_get_init_data(&pdev->dev); | 315 | data->usbmisc_data = usbmisc_get_init_data(dev); |
272 | if (IS_ERR(data->usbmisc_data)) | 316 | if (IS_ERR(data->usbmisc_data)) |
273 | return PTR_ERR(data->usbmisc_data); | 317 | return PTR_ERR(data->usbmisc_data); |
274 | 318 | ||
275 | ret = imx_get_clks(&pdev->dev); | 319 | if (of_usb_get_phy_mode(dev->of_node) == USBPHY_INTERFACE_MODE_HSIC) { |
320 | pdata.flags |= CI_HDRC_IMX_IS_HSIC; | ||
321 | data->usbmisc_data->hsic = 1; | ||
322 | data->pinctrl = devm_pinctrl_get(dev); | ||
323 | if (IS_ERR(data->pinctrl)) { | ||
324 | dev_err(dev, "pinctrl get failed, err=%ld\n", | ||
325 | PTR_ERR(data->pinctrl)); | ||
326 | return PTR_ERR(data->pinctrl); | ||
327 | } | ||
328 | |||
329 | pinctrl_hsic_idle = pinctrl_lookup_state(data->pinctrl, "idle"); | ||
330 | if (IS_ERR(pinctrl_hsic_idle)) { | ||
331 | dev_err(dev, | ||
332 | "pinctrl_hsic_idle lookup failed, err=%ld\n", | ||
333 | PTR_ERR(pinctrl_hsic_idle)); | ||
334 | return PTR_ERR(pinctrl_hsic_idle); | ||
335 | } | ||
336 | |||
337 | ret = pinctrl_select_state(data->pinctrl, pinctrl_hsic_idle); | ||
338 | if (ret) { | ||
339 | dev_err(dev, "hsic_idle select failed, err=%d\n", ret); | ||
340 | return ret; | ||
341 | } | ||
342 | |||
343 | data->pinctrl_hsic_active = pinctrl_lookup_state(data->pinctrl, | ||
344 | "active"); | ||
345 | if (IS_ERR(data->pinctrl_hsic_active)) { | ||
346 | dev_err(dev, | ||
347 | "pinctrl_hsic_active lookup failed, err=%ld\n", | ||
348 | PTR_ERR(data->pinctrl_hsic_active)); | ||
349 | return PTR_ERR(data->pinctrl_hsic_active); | ||
350 | } | ||
351 | |||
352 | data->hsic_pad_regulator = devm_regulator_get(dev, "hsic"); | ||
353 | if (PTR_ERR(data->hsic_pad_regulator) == -EPROBE_DEFER) { | ||
354 | return -EPROBE_DEFER; | ||
355 | } else if (PTR_ERR(data->hsic_pad_regulator) == -ENODEV) { | ||
356 | /* no pad regualator is needed */ | ||
357 | data->hsic_pad_regulator = NULL; | ||
358 | } else if (IS_ERR(data->hsic_pad_regulator)) { | ||
359 | dev_err(dev, "Get HSIC pad regulator error: %ld\n", | ||
360 | PTR_ERR(data->hsic_pad_regulator)); | ||
361 | return PTR_ERR(data->hsic_pad_regulator); | ||
362 | } | ||
363 | |||
364 | if (data->hsic_pad_regulator) { | ||
365 | ret = regulator_enable(data->hsic_pad_regulator); | ||
366 | if (ret) { | ||
367 | dev_err(dev, | ||
368 | "Failed to enable HSIC pad regulator\n"); | ||
369 | return ret; | ||
370 | } | ||
371 | } | ||
372 | } | ||
373 | ret = imx_get_clks(dev); | ||
276 | if (ret) | 374 | if (ret) |
277 | return ret; | 375 | goto disable_hsic_regulator; |
278 | 376 | ||
279 | ret = imx_prepare_enable_clks(&pdev->dev); | 377 | ret = imx_prepare_enable_clks(dev); |
280 | if (ret) | 378 | if (ret) |
281 | return ret; | 379 | goto disable_hsic_regulator; |
282 | 380 | ||
283 | data->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "fsl,usbphy", 0); | 381 | data->phy = devm_usb_get_phy_by_phandle(dev, "fsl,usbphy", 0); |
284 | if (IS_ERR(data->phy)) { | 382 | if (IS_ERR(data->phy)) { |
285 | ret = PTR_ERR(data->phy); | 383 | ret = PTR_ERR(data->phy); |
286 | /* Return -EINVAL if no usbphy is available */ | 384 | /* Return -EINVAL if no usbphy is available */ |
@@ -305,40 +403,43 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev) | |||
305 | 403 | ||
306 | ret = imx_usbmisc_init(data->usbmisc_data); | 404 | ret = imx_usbmisc_init(data->usbmisc_data); |
307 | if (ret) { | 405 | if (ret) { |
308 | dev_err(&pdev->dev, "usbmisc init failed, ret=%d\n", ret); | 406 | dev_err(dev, "usbmisc init failed, ret=%d\n", ret); |
309 | goto err_clk; | 407 | goto err_clk; |
310 | } | 408 | } |
311 | 409 | ||
312 | data->ci_pdev = ci_hdrc_add_device(&pdev->dev, | 410 | data->ci_pdev = ci_hdrc_add_device(dev, |
313 | pdev->resource, pdev->num_resources, | 411 | pdev->resource, pdev->num_resources, |
314 | &pdata); | 412 | &pdata); |
315 | if (IS_ERR(data->ci_pdev)) { | 413 | if (IS_ERR(data->ci_pdev)) { |
316 | ret = PTR_ERR(data->ci_pdev); | 414 | ret = PTR_ERR(data->ci_pdev); |
317 | if (ret != -EPROBE_DEFER) | 415 | if (ret != -EPROBE_DEFER) |
318 | dev_err(&pdev->dev, | 416 | dev_err(dev, "ci_hdrc_add_device failed, err=%d\n", |
319 | "ci_hdrc_add_device failed, err=%d\n", ret); | 417 | ret); |
320 | goto err_clk; | 418 | goto err_clk; |
321 | } | 419 | } |
322 | 420 | ||
323 | ret = imx_usbmisc_init_post(data->usbmisc_data); | 421 | ret = imx_usbmisc_init_post(data->usbmisc_data); |
324 | if (ret) { | 422 | if (ret) { |
325 | dev_err(&pdev->dev, "usbmisc post failed, ret=%d\n", ret); | 423 | dev_err(dev, "usbmisc post failed, ret=%d\n", ret); |
326 | goto disable_device; | 424 | goto disable_device; |
327 | } | 425 | } |
328 | 426 | ||
329 | if (data->supports_runtime_pm) { | 427 | if (data->supports_runtime_pm) { |
330 | pm_runtime_set_active(&pdev->dev); | 428 | pm_runtime_set_active(dev); |
331 | pm_runtime_enable(&pdev->dev); | 429 | pm_runtime_enable(dev); |
332 | } | 430 | } |
333 | 431 | ||
334 | device_set_wakeup_capable(&pdev->dev, true); | 432 | device_set_wakeup_capable(dev, true); |
335 | 433 | ||
336 | return 0; | 434 | return 0; |
337 | 435 | ||
338 | disable_device: | 436 | disable_device: |
339 | ci_hdrc_remove_device(data->ci_pdev); | 437 | ci_hdrc_remove_device(data->ci_pdev); |
340 | err_clk: | 438 | err_clk: |
341 | imx_disable_unprepare_clks(&pdev->dev); | 439 | imx_disable_unprepare_clks(dev); |
440 | disable_hsic_regulator: | ||
441 | if (data->hsic_pad_regulator) | ||
442 | ret = regulator_disable(data->hsic_pad_regulator); | ||
342 | return ret; | 443 | return ret; |
343 | } | 444 | } |
344 | 445 | ||
@@ -355,6 +456,8 @@ static int ci_hdrc_imx_remove(struct platform_device *pdev) | |||
355 | if (data->override_phy_control) | 456 | if (data->override_phy_control) |
356 | usb_phy_shutdown(data->phy); | 457 | usb_phy_shutdown(data->phy); |
357 | imx_disable_unprepare_clks(&pdev->dev); | 458 | imx_disable_unprepare_clks(&pdev->dev); |
459 | if (data->hsic_pad_regulator) | ||
460 | regulator_disable(data->hsic_pad_regulator); | ||
358 | 461 | ||
359 | return 0; | 462 | return 0; |
360 | } | 463 | } |
@@ -367,9 +470,16 @@ static void ci_hdrc_imx_shutdown(struct platform_device *pdev) | |||
367 | static int __maybe_unused imx_controller_suspend(struct device *dev) | 470 | static int __maybe_unused imx_controller_suspend(struct device *dev) |
368 | { | 471 | { |
369 | struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); | 472 | struct ci_hdrc_imx_data *data = dev_get_drvdata(dev); |
473 | int ret = 0; | ||
370 | 474 | ||
371 | dev_dbg(dev, "at %s\n", __func__); | 475 | dev_dbg(dev, "at %s\n", __func__); |
372 | 476 | ||
477 | ret = imx_usbmisc_hsic_set_clk(data->usbmisc_data, false); | ||
478 | if (ret) { | ||
479 | dev_err(dev, "usbmisc hsic_set_clk failed, ret=%d\n", ret); | ||
480 | return ret; | ||
481 | } | ||
482 | |||
373 | imx_disable_unprepare_clks(dev); | 483 | imx_disable_unprepare_clks(dev); |
374 | data->in_lpm = true; | 484 | data->in_lpm = true; |
375 | 485 | ||
@@ -400,8 +510,16 @@ static int __maybe_unused imx_controller_resume(struct device *dev) | |||
400 | goto clk_disable; | 510 | goto clk_disable; |
401 | } | 511 | } |
402 | 512 | ||
513 | ret = imx_usbmisc_hsic_set_clk(data->usbmisc_data, true); | ||
514 | if (ret) { | ||
515 | dev_err(dev, "usbmisc hsic_set_clk failed, ret=%d\n", ret); | ||
516 | goto hsic_set_clk_fail; | ||
517 | } | ||
518 | |||
403 | return 0; | 519 | return 0; |
404 | 520 | ||
521 | hsic_set_clk_fail: | ||
522 | imx_usbmisc_set_wakeup(data->usbmisc_data, true); | ||
405 | clk_disable: | 523 | clk_disable: |
406 | imx_disable_unprepare_clks(dev); | 524 | imx_disable_unprepare_clks(dev); |
407 | return ret; | 525 | return ret; |
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.h b/drivers/usb/chipidea/ci_hdrc_imx.h index 204275f47573..7cc53e2ce564 100644 --- a/drivers/usb/chipidea/ci_hdrc_imx.h +++ b/drivers/usb/chipidea/ci_hdrc_imx.h | |||
@@ -11,13 +11,22 @@ struct imx_usbmisc_data { | |||
11 | int index; | 11 | int index; |
12 | 12 | ||
13 | unsigned int disable_oc:1; /* over current detect disabled */ | 13 | unsigned int disable_oc:1; /* over current detect disabled */ |
14 | unsigned int oc_polarity:1; /* over current polarity if oc enabled */ | 14 | |
15 | /* true if over-current polarity is active low */ | ||
16 | unsigned int oc_pol_active_low:1; | ||
17 | |||
18 | /* true if dt specifies polarity */ | ||
19 | unsigned int oc_pol_configured:1; | ||
20 | |||
15 | unsigned int evdo:1; /* set external vbus divider option */ | 21 | unsigned int evdo:1; /* set external vbus divider option */ |
16 | unsigned int ulpi:1; /* connected to an ULPI phy */ | 22 | unsigned int ulpi:1; /* connected to an ULPI phy */ |
23 | unsigned int hsic:1; /* HSIC controlller */ | ||
17 | }; | 24 | }; |
18 | 25 | ||
19 | int imx_usbmisc_init(struct imx_usbmisc_data *); | 26 | int imx_usbmisc_init(struct imx_usbmisc_data *data); |
20 | int imx_usbmisc_init_post(struct imx_usbmisc_data *); | 27 | int imx_usbmisc_init_post(struct imx_usbmisc_data *data); |
21 | int imx_usbmisc_set_wakeup(struct imx_usbmisc_data *, bool); | 28 | int imx_usbmisc_set_wakeup(struct imx_usbmisc_data *data, bool enabled); |
29 | int imx_usbmisc_hsic_set_connect(struct imx_usbmisc_data *data); | ||
30 | int imx_usbmisc_hsic_set_clk(struct imx_usbmisc_data *data, bool on); | ||
22 | 31 | ||
23 | #endif /* __DRIVER_USB_CHIPIDEA_CI_HDRC_IMX_H */ | 32 | #endif /* __DRIVER_USB_CHIPIDEA_CI_HDRC_IMX_H */ |
diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c index d858a82c4f44..b45ceb91c735 100644 --- a/drivers/usb/chipidea/host.c +++ b/drivers/usb/chipidea/host.c | |||
@@ -170,6 +170,11 @@ static int host_start(struct ci_hdrc *ci) | |||
170 | otg->host = &hcd->self; | 170 | otg->host = &hcd->self; |
171 | hcd->self.otg_port = 1; | 171 | hcd->self.otg_port = 1; |
172 | } | 172 | } |
173 | |||
174 | if (ci->platdata->notify_event && | ||
175 | (ci->platdata->flags & CI_HDRC_IMX_IS_HSIC)) | ||
176 | ci->platdata->notify_event | ||
177 | (ci, CI_HDRC_IMX_HSIC_ACTIVE_EVENT); | ||
173 | } | 178 | } |
174 | 179 | ||
175 | return ret; | 180 | return ret; |
@@ -215,9 +220,85 @@ void ci_hdrc_host_destroy(struct ci_hdrc *ci) | |||
215 | host_stop(ci); | 220 | host_stop(ci); |
216 | } | 221 | } |
217 | 222 | ||
223 | /* The below code is based on tegra ehci driver */ | ||
224 | static int ci_ehci_hub_control( | ||
225 | struct usb_hcd *hcd, | ||
226 | u16 typeReq, | ||
227 | u16 wValue, | ||
228 | u16 wIndex, | ||
229 | char *buf, | ||
230 | u16 wLength | ||
231 | ) | ||
232 | { | ||
233 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | ||
234 | u32 __iomem *status_reg; | ||
235 | u32 temp; | ||
236 | unsigned long flags; | ||
237 | int retval = 0; | ||
238 | struct device *dev = hcd->self.controller; | ||
239 | struct ci_hdrc *ci = dev_get_drvdata(dev); | ||
240 | |||
241 | status_reg = &ehci->regs->port_status[(wIndex & 0xff) - 1]; | ||
242 | |||
243 | spin_lock_irqsave(&ehci->lock, flags); | ||
244 | |||
245 | if (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_SUSPEND) { | ||
246 | temp = ehci_readl(ehci, status_reg); | ||
247 | if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) { | ||
248 | retval = -EPIPE; | ||
249 | goto done; | ||
250 | } | ||
251 | |||
252 | temp &= ~(PORT_RWC_BITS | PORT_WKCONN_E); | ||
253 | temp |= PORT_WKDISC_E | PORT_WKOC_E; | ||
254 | ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); | ||
255 | |||
256 | /* | ||
257 | * If a transaction is in progress, there may be a delay in | ||
258 | * suspending the port. Poll until the port is suspended. | ||
259 | */ | ||
260 | if (ehci_handshake(ehci, status_reg, PORT_SUSPEND, | ||
261 | PORT_SUSPEND, 5000)) | ||
262 | ehci_err(ehci, "timeout waiting for SUSPEND\n"); | ||
263 | |||
264 | if (ci->platdata->flags & CI_HDRC_IMX_IS_HSIC) { | ||
265 | if (ci->platdata->notify_event) | ||
266 | ci->platdata->notify_event(ci, | ||
267 | CI_HDRC_IMX_HSIC_SUSPEND_EVENT); | ||
268 | |||
269 | temp = ehci_readl(ehci, status_reg); | ||
270 | temp &= ~(PORT_WKDISC_E | PORT_WKCONN_E); | ||
271 | ehci_writel(ehci, temp, status_reg); | ||
272 | } | ||
273 | |||
274 | set_bit((wIndex & 0xff) - 1, &ehci->suspended_ports); | ||
275 | goto done; | ||
276 | } | ||
277 | |||
278 | /* | ||
279 | * After resume has finished, it needs do some post resume | ||
280 | * operation for some SoCs. | ||
281 | */ | ||
282 | else if (typeReq == ClearPortFeature && | ||
283 | wValue == USB_PORT_FEAT_C_SUSPEND) { | ||
284 | /* Make sure the resume has finished, it should be finished */ | ||
285 | if (ehci_handshake(ehci, status_reg, PORT_RESUME, 0, 25000)) | ||
286 | ehci_err(ehci, "timeout waiting for resume\n"); | ||
287 | } | ||
288 | |||
289 | spin_unlock_irqrestore(&ehci->lock, flags); | ||
290 | |||
291 | /* Handle the hub control events here */ | ||
292 | return ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); | ||
293 | done: | ||
294 | spin_unlock_irqrestore(&ehci->lock, flags); | ||
295 | return retval; | ||
296 | } | ||
218 | static int ci_ehci_bus_suspend(struct usb_hcd *hcd) | 297 | static int ci_ehci_bus_suspend(struct usb_hcd *hcd) |
219 | { | 298 | { |
220 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | 299 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
300 | struct device *dev = hcd->self.controller; | ||
301 | struct ci_hdrc *ci = dev_get_drvdata(dev); | ||
221 | int port; | 302 | int port; |
222 | u32 tmp; | 303 | u32 tmp; |
223 | 304 | ||
@@ -249,6 +330,16 @@ static int ci_ehci_bus_suspend(struct usb_hcd *hcd) | |||
249 | * It needs a short delay between set RS bit and PHCD. | 330 | * It needs a short delay between set RS bit and PHCD. |
250 | */ | 331 | */ |
251 | usleep_range(150, 200); | 332 | usleep_range(150, 200); |
333 | /* | ||
334 | * Need to clear WKCN and WKOC for imx HSIC, | ||
335 | * otherwise, there will be wakeup event. | ||
336 | */ | ||
337 | if (ci->platdata->flags & CI_HDRC_IMX_IS_HSIC) { | ||
338 | tmp = ehci_readl(ehci, reg); | ||
339 | tmp &= ~(PORT_WKDISC_E | PORT_WKCONN_E); | ||
340 | ehci_writel(ehci, tmp, reg); | ||
341 | } | ||
342 | |||
252 | break; | 343 | break; |
253 | } | 344 | } |
254 | } | 345 | } |
@@ -281,4 +372,5 @@ void ci_hdrc_host_driver_init(void) | |||
281 | ehci_init_driver(&ci_ehci_hc_driver, &ehci_ci_overrides); | 372 | ehci_init_driver(&ci_ehci_hc_driver, &ehci_ci_overrides); |
282 | orig_bus_suspend = ci_ehci_hc_driver.bus_suspend; | 373 | orig_bus_suspend = ci_ehci_hc_driver.bus_suspend; |
283 | ci_ehci_hc_driver.bus_suspend = ci_ehci_bus_suspend; | 374 | ci_ehci_hc_driver.bus_suspend = ci_ehci_bus_suspend; |
375 | ci_ehci_hc_driver.hub_control = ci_ehci_hub_control; | ||
284 | } | 376 | } |
diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c index def80ff547e4..097ffbca0bd9 100644 --- a/drivers/usb/chipidea/usbmisc_imx.c +++ b/drivers/usb/chipidea/usbmisc_imx.c | |||
@@ -64,10 +64,22 @@ | |||
64 | #define MX6_BM_OVER_CUR_DIS BIT(7) | 64 | #define MX6_BM_OVER_CUR_DIS BIT(7) |
65 | #define MX6_BM_OVER_CUR_POLARITY BIT(8) | 65 | #define MX6_BM_OVER_CUR_POLARITY BIT(8) |
66 | #define MX6_BM_WAKEUP_ENABLE BIT(10) | 66 | #define MX6_BM_WAKEUP_ENABLE BIT(10) |
67 | #define MX6_BM_UTMI_ON_CLOCK BIT(13) | ||
67 | #define MX6_BM_ID_WAKEUP BIT(16) | 68 | #define MX6_BM_ID_WAKEUP BIT(16) |
68 | #define MX6_BM_VBUS_WAKEUP BIT(17) | 69 | #define MX6_BM_VBUS_WAKEUP BIT(17) |
69 | #define MX6SX_BM_DPDM_WAKEUP_EN BIT(29) | 70 | #define MX6SX_BM_DPDM_WAKEUP_EN BIT(29) |
70 | #define MX6_BM_WAKEUP_INTR BIT(31) | 71 | #define MX6_BM_WAKEUP_INTR BIT(31) |
72 | |||
73 | #define MX6_USB_HSIC_CTRL_OFFSET 0x10 | ||
74 | /* Send resume signal without 480Mhz PHY clock */ | ||
75 | #define MX6SX_BM_HSIC_AUTO_RESUME BIT(23) | ||
76 | /* set before portsc.suspendM = 1 */ | ||
77 | #define MX6_BM_HSIC_DEV_CONN BIT(21) | ||
78 | /* HSIC enable */ | ||
79 | #define MX6_BM_HSIC_EN BIT(12) | ||
80 | /* Force HSIC module 480M clock on, even when in Host is in suspend mode */ | ||
81 | #define MX6_BM_HSIC_CLK_ON BIT(11) | ||
82 | |||
71 | #define MX6_USB_OTG1_PHY_CTRL 0x18 | 83 | #define MX6_USB_OTG1_PHY_CTRL 0x18 |
72 | /* For imx6dql, it is host-only controller, for later imx6, it is otg's */ | 84 | /* For imx6dql, it is host-only controller, for later imx6, it is otg's */ |
73 | #define MX6_USB_OTG2_PHY_CTRL 0x1c | 85 | #define MX6_USB_OTG2_PHY_CTRL 0x1c |
@@ -94,6 +106,10 @@ struct usbmisc_ops { | |||
94 | int (*post)(struct imx_usbmisc_data *data); | 106 | int (*post)(struct imx_usbmisc_data *data); |
95 | /* It's called when we need to enable/disable usb wakeup */ | 107 | /* It's called when we need to enable/disable usb wakeup */ |
96 | int (*set_wakeup)(struct imx_usbmisc_data *data, bool enabled); | 108 | int (*set_wakeup)(struct imx_usbmisc_data *data, bool enabled); |
109 | /* It's called before setting portsc.suspendM */ | ||
110 | int (*hsic_set_connect)(struct imx_usbmisc_data *data); | ||
111 | /* It's called during suspend/resume */ | ||
112 | int (*hsic_set_clk)(struct imx_usbmisc_data *data, bool enabled); | ||
97 | }; | 113 | }; |
98 | 114 | ||
99 | struct imx_usbmisc { | 115 | struct imx_usbmisc { |
@@ -120,6 +136,14 @@ static int usbmisc_imx25_init(struct imx_usbmisc_data *data) | |||
120 | val &= ~(MX25_OTG_SIC_MASK | MX25_OTG_PP_BIT); | 136 | val &= ~(MX25_OTG_SIC_MASK | MX25_OTG_PP_BIT); |
121 | val |= (MX25_EHCI_INTERFACE_DIFF_UNI & MX25_EHCI_INTERFACE_MASK) << MX25_OTG_SIC_SHIFT; | 137 | val |= (MX25_EHCI_INTERFACE_DIFF_UNI & MX25_EHCI_INTERFACE_MASK) << MX25_OTG_SIC_SHIFT; |
122 | val |= (MX25_OTG_PM_BIT | MX25_OTG_OCPOL_BIT); | 138 | val |= (MX25_OTG_PM_BIT | MX25_OTG_OCPOL_BIT); |
139 | |||
140 | /* | ||
141 | * If the polarity is not configured assume active high for | ||
142 | * historical reasons. | ||
143 | */ | ||
144 | if (data->oc_pol_configured && data->oc_pol_active_low) | ||
145 | val &= ~MX25_OTG_OCPOL_BIT; | ||
146 | |||
123 | writel(val, usbmisc->base); | 147 | writel(val, usbmisc->base); |
124 | break; | 148 | break; |
125 | case 1: | 149 | case 1: |
@@ -129,6 +153,13 @@ static int usbmisc_imx25_init(struct imx_usbmisc_data *data) | |||
129 | val |= (MX25_H1_PM_BIT | MX25_H1_OCPOL_BIT | MX25_H1_TLL_BIT | | 153 | val |= (MX25_H1_PM_BIT | MX25_H1_OCPOL_BIT | MX25_H1_TLL_BIT | |
130 | MX25_H1_USBTE_BIT | MX25_H1_IPPUE_DOWN_BIT); | 154 | MX25_H1_USBTE_BIT | MX25_H1_IPPUE_DOWN_BIT); |
131 | 155 | ||
156 | /* | ||
157 | * If the polarity is not configured assume active high for | ||
158 | * historical reasons. | ||
159 | */ | ||
160 | if (data->oc_pol_configured && data->oc_pol_active_low) | ||
161 | val &= ~MX25_H1_OCPOL_BIT; | ||
162 | |||
132 | writel(val, usbmisc->base); | 163 | writel(val, usbmisc->base); |
133 | 164 | ||
134 | break; | 165 | break; |
@@ -340,11 +371,17 @@ static int usbmisc_imx6q_init(struct imx_usbmisc_data *data) | |||
340 | reg = readl(usbmisc->base + data->index * 4); | 371 | reg = readl(usbmisc->base + data->index * 4); |
341 | if (data->disable_oc) { | 372 | if (data->disable_oc) { |
342 | reg |= MX6_BM_OVER_CUR_DIS; | 373 | reg |= MX6_BM_OVER_CUR_DIS; |
343 | } else if (data->oc_polarity == 1) { | ||
344 | /* High active */ | ||
345 | reg &= ~(MX6_BM_OVER_CUR_DIS | MX6_BM_OVER_CUR_POLARITY); | ||
346 | } else { | 374 | } else { |
347 | reg &= ~(MX6_BM_OVER_CUR_DIS); | 375 | reg &= ~MX6_BM_OVER_CUR_DIS; |
376 | |||
377 | /* | ||
378 | * If the polarity is not configured keep it as setup by the | ||
379 | * bootloader. | ||
380 | */ | ||
381 | if (data->oc_pol_configured && data->oc_pol_active_low) | ||
382 | reg |= MX6_BM_OVER_CUR_POLARITY; | ||
383 | else if (data->oc_pol_configured) | ||
384 | reg &= ~MX6_BM_OVER_CUR_POLARITY; | ||
348 | } | 385 | } |
349 | writel(reg, usbmisc->base + data->index * 4); | 386 | writel(reg, usbmisc->base + data->index * 4); |
350 | 387 | ||
@@ -353,6 +390,18 @@ static int usbmisc_imx6q_init(struct imx_usbmisc_data *data) | |||
353 | writel(reg | MX6_BM_NON_BURST_SETTING, | 390 | writel(reg | MX6_BM_NON_BURST_SETTING, |
354 | usbmisc->base + data->index * 4); | 391 | usbmisc->base + data->index * 4); |
355 | 392 | ||
393 | /* For HSIC controller */ | ||
394 | if (data->hsic) { | ||
395 | reg = readl(usbmisc->base + data->index * 4); | ||
396 | writel(reg | MX6_BM_UTMI_ON_CLOCK, | ||
397 | usbmisc->base + data->index * 4); | ||
398 | reg = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET | ||
399 | + (data->index - 2) * 4); | ||
400 | reg |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON; | ||
401 | writel(reg, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET | ||
402 | + (data->index - 2) * 4); | ||
403 | } | ||
404 | |||
356 | spin_unlock_irqrestore(&usbmisc->lock, flags); | 405 | spin_unlock_irqrestore(&usbmisc->lock, flags); |
357 | 406 | ||
358 | usbmisc_imx6q_set_wakeup(data, false); | 407 | usbmisc_imx6q_set_wakeup(data, false); |
@@ -360,6 +409,79 @@ static int usbmisc_imx6q_init(struct imx_usbmisc_data *data) | |||
360 | return 0; | 409 | return 0; |
361 | } | 410 | } |
362 | 411 | ||
412 | static int usbmisc_imx6_hsic_get_reg_offset(struct imx_usbmisc_data *data) | ||
413 | { | ||
414 | int offset, ret = 0; | ||
415 | |||
416 | if (data->index == 2 || data->index == 3) { | ||
417 | offset = (data->index - 2) * 4; | ||
418 | } else if (data->index == 0) { | ||
419 | /* | ||
420 | * For SoCs like i.MX7D and later, each USB controller has | ||
421 | * its own non-core register region. For SoCs before i.MX7D, | ||
422 | * the first two USB controllers are non-HSIC controllers. | ||
423 | */ | ||
424 | offset = 0; | ||
425 | } else { | ||
426 | dev_err(data->dev, "index is error for usbmisc\n"); | ||
427 | ret = -EINVAL; | ||
428 | } | ||
429 | |||
430 | return ret ? ret : offset; | ||
431 | } | ||
432 | |||
433 | static int usbmisc_imx6_hsic_set_connect(struct imx_usbmisc_data *data) | ||
434 | { | ||
435 | unsigned long flags; | ||
436 | u32 val; | ||
437 | struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); | ||
438 | int offset; | ||
439 | |||
440 | spin_lock_irqsave(&usbmisc->lock, flags); | ||
441 | offset = usbmisc_imx6_hsic_get_reg_offset(data); | ||
442 | if (offset < 0) { | ||
443 | spin_unlock_irqrestore(&usbmisc->lock, flags); | ||
444 | return offset; | ||
445 | } | ||
446 | |||
447 | val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset); | ||
448 | if (!(val & MX6_BM_HSIC_DEV_CONN)) | ||
449 | writel(val | MX6_BM_HSIC_DEV_CONN, | ||
450 | usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset); | ||
451 | |||
452 | spin_unlock_irqrestore(&usbmisc->lock, flags); | ||
453 | |||
454 | return 0; | ||
455 | } | ||
456 | |||
457 | static int usbmisc_imx6_hsic_set_clk(struct imx_usbmisc_data *data, bool on) | ||
458 | { | ||
459 | unsigned long flags; | ||
460 | u32 val; | ||
461 | struct imx_usbmisc *usbmisc = dev_get_drvdata(data->dev); | ||
462 | int offset; | ||
463 | |||
464 | spin_lock_irqsave(&usbmisc->lock, flags); | ||
465 | offset = usbmisc_imx6_hsic_get_reg_offset(data); | ||
466 | if (offset < 0) { | ||
467 | spin_unlock_irqrestore(&usbmisc->lock, flags); | ||
468 | return offset; | ||
469 | } | ||
470 | |||
471 | val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset); | ||
472 | val |= MX6_BM_HSIC_EN | MX6_BM_HSIC_CLK_ON; | ||
473 | if (on) | ||
474 | val |= MX6_BM_HSIC_CLK_ON; | ||
475 | else | ||
476 | val &= ~MX6_BM_HSIC_CLK_ON; | ||
477 | |||
478 | writel(val, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET + offset); | ||
479 | spin_unlock_irqrestore(&usbmisc->lock, flags); | ||
480 | |||
481 | return 0; | ||
482 | } | ||
483 | |||
484 | |||
363 | static int usbmisc_imx6sx_init(struct imx_usbmisc_data *data) | 485 | static int usbmisc_imx6sx_init(struct imx_usbmisc_data *data) |
364 | { | 486 | { |
365 | void __iomem *reg = NULL; | 487 | void __iomem *reg = NULL; |
@@ -385,6 +507,13 @@ static int usbmisc_imx6sx_init(struct imx_usbmisc_data *data) | |||
385 | spin_unlock_irqrestore(&usbmisc->lock, flags); | 507 | spin_unlock_irqrestore(&usbmisc->lock, flags); |
386 | } | 508 | } |
387 | 509 | ||
510 | /* For HSIC controller */ | ||
511 | if (data->hsic) { | ||
512 | val = readl(usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET); | ||
513 | val |= MX6SX_BM_HSIC_AUTO_RESUME; | ||
514 | writel(val, usbmisc->base + MX6_USB_HSIC_CTRL_OFFSET); | ||
515 | } | ||
516 | |||
388 | return 0; | 517 | return 0; |
389 | } | 518 | } |
390 | 519 | ||
@@ -444,9 +573,17 @@ static int usbmisc_imx7d_init(struct imx_usbmisc_data *data) | |||
444 | reg = readl(usbmisc->base); | 573 | reg = readl(usbmisc->base); |
445 | if (data->disable_oc) { | 574 | if (data->disable_oc) { |
446 | reg |= MX6_BM_OVER_CUR_DIS; | 575 | reg |= MX6_BM_OVER_CUR_DIS; |
447 | } else if (data->oc_polarity == 1) { | 576 | } else { |
448 | /* High active */ | 577 | reg &= ~MX6_BM_OVER_CUR_DIS; |
449 | reg &= ~(MX6_BM_OVER_CUR_DIS | MX6_BM_OVER_CUR_POLARITY); | 578 | |
579 | /* | ||
580 | * If the polarity is not configured keep it as setup by the | ||
581 | * bootloader. | ||
582 | */ | ||
583 | if (data->oc_pol_configured && data->oc_pol_active_low) | ||
584 | reg |= MX6_BM_OVER_CUR_POLARITY; | ||
585 | else if (data->oc_pol_configured) | ||
586 | reg &= ~MX6_BM_OVER_CUR_POLARITY; | ||
450 | } | 587 | } |
451 | writel(reg, usbmisc->base); | 588 | writel(reg, usbmisc->base); |
452 | 589 | ||
@@ -454,6 +591,7 @@ static int usbmisc_imx7d_init(struct imx_usbmisc_data *data) | |||
454 | reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK; | 591 | reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK; |
455 | writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID, | 592 | writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID, |
456 | usbmisc->base + MX7D_USBNC_USB_CTRL2); | 593 | usbmisc->base + MX7D_USBNC_USB_CTRL2); |
594 | |||
457 | spin_unlock_irqrestore(&usbmisc->lock, flags); | 595 | spin_unlock_irqrestore(&usbmisc->lock, flags); |
458 | 596 | ||
459 | usbmisc_imx7d_set_wakeup(data, false); | 597 | usbmisc_imx7d_set_wakeup(data, false); |
@@ -481,6 +619,8 @@ static const struct usbmisc_ops imx53_usbmisc_ops = { | |||
481 | static const struct usbmisc_ops imx6q_usbmisc_ops = { | 619 | static const struct usbmisc_ops imx6q_usbmisc_ops = { |
482 | .set_wakeup = usbmisc_imx6q_set_wakeup, | 620 | .set_wakeup = usbmisc_imx6q_set_wakeup, |
483 | .init = usbmisc_imx6q_init, | 621 | .init = usbmisc_imx6q_init, |
622 | .hsic_set_connect = usbmisc_imx6_hsic_set_connect, | ||
623 | .hsic_set_clk = usbmisc_imx6_hsic_set_clk, | ||
484 | }; | 624 | }; |
485 | 625 | ||
486 | static const struct usbmisc_ops vf610_usbmisc_ops = { | 626 | static const struct usbmisc_ops vf610_usbmisc_ops = { |
@@ -490,6 +630,8 @@ static const struct usbmisc_ops vf610_usbmisc_ops = { | |||
490 | static const struct usbmisc_ops imx6sx_usbmisc_ops = { | 630 | static const struct usbmisc_ops imx6sx_usbmisc_ops = { |
491 | .set_wakeup = usbmisc_imx6q_set_wakeup, | 631 | .set_wakeup = usbmisc_imx6q_set_wakeup, |
492 | .init = usbmisc_imx6sx_init, | 632 | .init = usbmisc_imx6sx_init, |
633 | .hsic_set_connect = usbmisc_imx6_hsic_set_connect, | ||
634 | .hsic_set_clk = usbmisc_imx6_hsic_set_clk, | ||
493 | }; | 635 | }; |
494 | 636 | ||
495 | static const struct usbmisc_ops imx7d_usbmisc_ops = { | 637 | static const struct usbmisc_ops imx7d_usbmisc_ops = { |
@@ -546,6 +688,33 @@ int imx_usbmisc_set_wakeup(struct imx_usbmisc_data *data, bool enabled) | |||
546 | } | 688 | } |
547 | EXPORT_SYMBOL_GPL(imx_usbmisc_set_wakeup); | 689 | EXPORT_SYMBOL_GPL(imx_usbmisc_set_wakeup); |
548 | 690 | ||
691 | int imx_usbmisc_hsic_set_connect(struct imx_usbmisc_data *data) | ||
692 | { | ||
693 | struct imx_usbmisc *usbmisc; | ||
694 | |||
695 | if (!data) | ||
696 | return 0; | ||
697 | |||
698 | usbmisc = dev_get_drvdata(data->dev); | ||
699 | if (!usbmisc->ops->hsic_set_connect || !data->hsic) | ||
700 | return 0; | ||
701 | return usbmisc->ops->hsic_set_connect(data); | ||
702 | } | ||
703 | EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_connect); | ||
704 | |||
705 | int imx_usbmisc_hsic_set_clk(struct imx_usbmisc_data *data, bool on) | ||
706 | { | ||
707 | struct imx_usbmisc *usbmisc; | ||
708 | |||
709 | if (!data) | ||
710 | return 0; | ||
711 | |||
712 | usbmisc = dev_get_drvdata(data->dev); | ||
713 | if (!usbmisc->ops->hsic_set_clk || !data->hsic) | ||
714 | return 0; | ||
715 | return usbmisc->ops->hsic_set_clk(data, on); | ||
716 | } | ||
717 | EXPORT_SYMBOL_GPL(imx_usbmisc_hsic_set_clk); | ||
549 | static const struct of_device_id usbmisc_imx_dt_ids[] = { | 718 | static const struct of_device_id usbmisc_imx_dt_ids[] = { |
550 | { | 719 | { |
551 | .compatible = "fsl,imx25-usbmisc", | 720 | .compatible = "fsl,imx25-usbmisc", |
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 1b68fed464cb..ed8c62b2d9d1 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
@@ -581,6 +581,13 @@ static int acm_tty_install(struct tty_driver *driver, struct tty_struct *tty) | |||
581 | if (retval) | 581 | if (retval) |
582 | goto error_init_termios; | 582 | goto error_init_termios; |
583 | 583 | ||
584 | /* | ||
585 | * Suppress initial echoing for some devices which might send data | ||
586 | * immediately after acm driver has been installed. | ||
587 | */ | ||
588 | if (acm->quirks & DISABLE_ECHO) | ||
589 | tty->termios.c_lflag &= ~ECHO; | ||
590 | |||
584 | tty->driver_data = acm; | 591 | tty->driver_data = acm; |
585 | 592 | ||
586 | return 0; | 593 | return 0; |
@@ -1657,6 +1664,9 @@ static const struct usb_device_id acm_ids[] = { | |||
1657 | { USB_DEVICE(0x0e8d, 0x0003), /* FIREFLY, MediaTek Inc; andrey.arapov@gmail.com */ | 1664 | { USB_DEVICE(0x0e8d, 0x0003), /* FIREFLY, MediaTek Inc; andrey.arapov@gmail.com */ |
1658 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ | 1665 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ |
1659 | }, | 1666 | }, |
1667 | { USB_DEVICE(0x0e8d, 0x2000), /* MediaTek Inc Preloader */ | ||
1668 | .driver_info = DISABLE_ECHO, /* DISABLE ECHO in termios flag */ | ||
1669 | }, | ||
1660 | { USB_DEVICE(0x0e8d, 0x3329), /* MediaTek Inc GPS */ | 1670 | { USB_DEVICE(0x0e8d, 0x3329), /* MediaTek Inc GPS */ |
1661 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ | 1671 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ |
1662 | }, | 1672 | }, |
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h index ca06b20d7af9..515aad0847ee 100644 --- a/drivers/usb/class/cdc-acm.h +++ b/drivers/usb/class/cdc-acm.h | |||
@@ -140,3 +140,4 @@ struct acm { | |||
140 | #define QUIRK_CONTROL_LINE_STATE BIT(6) | 140 | #define QUIRK_CONTROL_LINE_STATE BIT(6) |
141 | #define CLEAR_HALT_CONDITIONS BIT(7) | 141 | #define CLEAR_HALT_CONDITIONS BIT(7) |
142 | #define SEND_ZERO_PACKET BIT(8) | 142 | #define SEND_ZERO_PACKET BIT(8) |
143 | #define DISABLE_ECHO BIT(9) | ||
diff --git a/drivers/usb/common/Makefile b/drivers/usb/common/Makefile index fb4d5ef4165c..0a7c45e85481 100644 --- a/drivers/usb/common/Makefile +++ b/drivers/usb/common/Makefile | |||
@@ -9,4 +9,3 @@ usb-common-$(CONFIG_USB_LED_TRIG) += led.o | |||
9 | 9 | ||
10 | obj-$(CONFIG_USB_OTG_FSM) += usb-otg-fsm.o | 10 | obj-$(CONFIG_USB_OTG_FSM) += usb-otg-fsm.o |
11 | obj-$(CONFIG_USB_ULPI_BUS) += ulpi.o | 11 | obj-$(CONFIG_USB_ULPI_BUS) += ulpi.o |
12 | obj-$(CONFIG_USB_ROLE_SWITCH) += roles.o | ||
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 487025d31d44..015b126ce455 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
@@ -1074,8 +1074,6 @@ static int register_root_hub(struct usb_hcd *hcd) | |||
1074 | 1074 | ||
1075 | usb_dev->devnum = devnum; | 1075 | usb_dev->devnum = devnum; |
1076 | usb_dev->bus->devnum_next = devnum + 1; | 1076 | usb_dev->bus->devnum_next = devnum + 1; |
1077 | memset (&usb_dev->bus->devmap.devicemap, 0, | ||
1078 | sizeof usb_dev->bus->devmap.devicemap); | ||
1079 | set_bit (devnum, usb_dev->bus->devmap.devicemap); | 1077 | set_bit (devnum, usb_dev->bus->devmap.devicemap); |
1080 | usb_set_device_state(usb_dev, USB_STATE_ADDRESS); | 1078 | usb_set_device_state(usb_dev, USB_STATE_ADDRESS); |
1081 | 1079 | ||
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index f76b2e0aba9d..1d1e61e980f3 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -1112,6 +1112,16 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) | |||
1112 | USB_PORT_FEAT_ENABLE); | 1112 | USB_PORT_FEAT_ENABLE); |
1113 | } | 1113 | } |
1114 | 1114 | ||
1115 | /* | ||
1116 | * Add debounce if USB3 link is in polling/link training state. | ||
1117 | * Link will automatically transition to Enabled state after | ||
1118 | * link training completes. | ||
1119 | */ | ||
1120 | if (hub_is_superspeed(hdev) && | ||
1121 | ((portstatus & USB_PORT_STAT_LINK_STATE) == | ||
1122 | USB_SS_PORT_LS_POLLING)) | ||
1123 | need_debounce_delay = true; | ||
1124 | |||
1115 | /* Clear status-change flags; we'll debounce later */ | 1125 | /* Clear status-change flags; we'll debounce later */ |
1116 | if (portchange & USB_PORT_STAT_C_CONNECTION) { | 1126 | if (portchange & USB_PORT_STAT_C_CONNECTION) { |
1117 | need_debounce_delay = true; | 1127 | need_debounce_delay = true; |
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 2d6d2c8244de..68ad75a7460d 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c | |||
@@ -262,7 +262,7 @@ static void dwc2_gadget_wkup_alert_handler(struct dwc2_hsotg *hsotg) | |||
262 | if (gintsts2 & GINTSTS2_WKUP_ALERT_INT) { | 262 | if (gintsts2 & GINTSTS2_WKUP_ALERT_INT) { |
263 | dev_dbg(hsotg->dev, "%s: Wkup_Alert_Int\n", __func__); | 263 | dev_dbg(hsotg->dev, "%s: Wkup_Alert_Int\n", __func__); |
264 | dwc2_clear_bit(hsotg, GINTSTS2, GINTSTS2_WKUP_ALERT_INT); | 264 | dwc2_clear_bit(hsotg, GINTSTS2, GINTSTS2_WKUP_ALERT_INT); |
265 | dwc2_set_bit(hsotg, DCFG, DCTL_RMTWKUPSIG); | 265 | dwc2_set_bit(hsotg, DCTL, DCTL_RMTWKUPSIG); |
266 | } | 266 | } |
267 | } | 267 | } |
268 | 268 | ||
@@ -3165,8 +3165,6 @@ static void kill_all_requests(struct dwc2_hsotg *hsotg, | |||
3165 | dwc2_hsotg_txfifo_flush(hsotg, ep->fifo_index); | 3165 | dwc2_hsotg_txfifo_flush(hsotg, ep->fifo_index); |
3166 | } | 3166 | } |
3167 | 3167 | ||
3168 | static int dwc2_hsotg_ep_disable(struct usb_ep *ep); | ||
3169 | |||
3170 | /** | 3168 | /** |
3171 | * dwc2_hsotg_disconnect - disconnect service | 3169 | * dwc2_hsotg_disconnect - disconnect service |
3172 | * @hsotg: The device state. | 3170 | * @hsotg: The device state. |
@@ -3188,9 +3186,11 @@ void dwc2_hsotg_disconnect(struct dwc2_hsotg *hsotg) | |||
3188 | /* all endpoints should be shutdown */ | 3186 | /* all endpoints should be shutdown */ |
3189 | for (ep = 0; ep < hsotg->num_of_eps; ep++) { | 3187 | for (ep = 0; ep < hsotg->num_of_eps; ep++) { |
3190 | if (hsotg->eps_in[ep]) | 3188 | if (hsotg->eps_in[ep]) |
3191 | dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep); | 3189 | kill_all_requests(hsotg, hsotg->eps_in[ep], |
3190 | -ESHUTDOWN); | ||
3192 | if (hsotg->eps_out[ep]) | 3191 | if (hsotg->eps_out[ep]) |
3193 | dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep); | 3192 | kill_all_requests(hsotg, hsotg->eps_out[ep], |
3193 | -ESHUTDOWN); | ||
3194 | } | 3194 | } |
3195 | 3195 | ||
3196 | call_gadget(hsotg, disconnect); | 3196 | call_gadget(hsotg, disconnect); |
@@ -3234,6 +3234,7 @@ static void dwc2_hsotg_irq_fifoempty(struct dwc2_hsotg *hsotg, bool periodic) | |||
3234 | GINTSTS_PTXFEMP | \ | 3234 | GINTSTS_PTXFEMP | \ |
3235 | GINTSTS_RXFLVL) | 3235 | GINTSTS_RXFLVL) |
3236 | 3236 | ||
3237 | static int dwc2_hsotg_ep_disable(struct usb_ep *ep); | ||
3237 | /** | 3238 | /** |
3238 | * dwc2_hsotg_core_init - issue softreset to the core | 3239 | * dwc2_hsotg_core_init - issue softreset to the core |
3239 | * @hsotg: The device state | 3240 | * @hsotg: The device state |
@@ -4069,10 +4070,8 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep) | |||
4069 | struct dwc2_hsotg *hsotg = hs_ep->parent; | 4070 | struct dwc2_hsotg *hsotg = hs_ep->parent; |
4070 | int dir_in = hs_ep->dir_in; | 4071 | int dir_in = hs_ep->dir_in; |
4071 | int index = hs_ep->index; | 4072 | int index = hs_ep->index; |
4072 | unsigned long flags; | ||
4073 | u32 epctrl_reg; | 4073 | u32 epctrl_reg; |
4074 | u32 ctrl; | 4074 | u32 ctrl; |
4075 | int locked; | ||
4076 | 4075 | ||
4077 | dev_dbg(hsotg->dev, "%s(ep %p)\n", __func__, ep); | 4076 | dev_dbg(hsotg->dev, "%s(ep %p)\n", __func__, ep); |
4078 | 4077 | ||
@@ -4088,10 +4087,6 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep) | |||
4088 | 4087 | ||
4089 | epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index); | 4088 | epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index); |
4090 | 4089 | ||
4091 | locked = spin_is_locked(&hsotg->lock); | ||
4092 | if (!locked) | ||
4093 | spin_lock_irqsave(&hsotg->lock, flags); | ||
4094 | |||
4095 | ctrl = dwc2_readl(hsotg, epctrl_reg); | 4090 | ctrl = dwc2_readl(hsotg, epctrl_reg); |
4096 | 4091 | ||
4097 | if (ctrl & DXEPCTL_EPENA) | 4092 | if (ctrl & DXEPCTL_EPENA) |
@@ -4114,12 +4109,22 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep) | |||
4114 | hs_ep->fifo_index = 0; | 4109 | hs_ep->fifo_index = 0; |
4115 | hs_ep->fifo_size = 0; | 4110 | hs_ep->fifo_size = 0; |
4116 | 4111 | ||
4117 | if (!locked) | ||
4118 | spin_unlock_irqrestore(&hsotg->lock, flags); | ||
4119 | |||
4120 | return 0; | 4112 | return 0; |
4121 | } | 4113 | } |
4122 | 4114 | ||
4115 | static int dwc2_hsotg_ep_disable_lock(struct usb_ep *ep) | ||
4116 | { | ||
4117 | struct dwc2_hsotg_ep *hs_ep = our_ep(ep); | ||
4118 | struct dwc2_hsotg *hsotg = hs_ep->parent; | ||
4119 | unsigned long flags; | ||
4120 | int ret; | ||
4121 | |||
4122 | spin_lock_irqsave(&hsotg->lock, flags); | ||
4123 | ret = dwc2_hsotg_ep_disable(ep); | ||
4124 | spin_unlock_irqrestore(&hsotg->lock, flags); | ||
4125 | return ret; | ||
4126 | } | ||
4127 | |||
4123 | /** | 4128 | /** |
4124 | * on_list - check request is on the given endpoint | 4129 | * on_list - check request is on the given endpoint |
4125 | * @ep: The endpoint to check. | 4130 | * @ep: The endpoint to check. |
@@ -4267,7 +4272,7 @@ static int dwc2_hsotg_ep_sethalt_lock(struct usb_ep *ep, int value) | |||
4267 | 4272 | ||
4268 | static const struct usb_ep_ops dwc2_hsotg_ep_ops = { | 4273 | static const struct usb_ep_ops dwc2_hsotg_ep_ops = { |
4269 | .enable = dwc2_hsotg_ep_enable, | 4274 | .enable = dwc2_hsotg_ep_enable, |
4270 | .disable = dwc2_hsotg_ep_disable, | 4275 | .disable = dwc2_hsotg_ep_disable_lock, |
4271 | .alloc_request = dwc2_hsotg_ep_alloc_request, | 4276 | .alloc_request = dwc2_hsotg_ep_alloc_request, |
4272 | .free_request = dwc2_hsotg_ep_free_request, | 4277 | .free_request = dwc2_hsotg_ep_free_request, |
4273 | .queue = dwc2_hsotg_ep_queue_lock, | 4278 | .queue = dwc2_hsotg_ep_queue_lock, |
@@ -4407,9 +4412,9 @@ static int dwc2_hsotg_udc_stop(struct usb_gadget *gadget) | |||
4407 | /* all endpoints should be shutdown */ | 4412 | /* all endpoints should be shutdown */ |
4408 | for (ep = 1; ep < hsotg->num_of_eps; ep++) { | 4413 | for (ep = 1; ep < hsotg->num_of_eps; ep++) { |
4409 | if (hsotg->eps_in[ep]) | 4414 | if (hsotg->eps_in[ep]) |
4410 | dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep); | 4415 | dwc2_hsotg_ep_disable_lock(&hsotg->eps_in[ep]->ep); |
4411 | if (hsotg->eps_out[ep]) | 4416 | if (hsotg->eps_out[ep]) |
4412 | dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep); | 4417 | dwc2_hsotg_ep_disable_lock(&hsotg->eps_out[ep]->ep); |
4413 | } | 4418 | } |
4414 | 4419 | ||
4415 | spin_lock_irqsave(&hsotg->lock, flags); | 4420 | spin_lock_irqsave(&hsotg->lock, flags); |
@@ -4857,9 +4862,9 @@ int dwc2_hsotg_suspend(struct dwc2_hsotg *hsotg) | |||
4857 | 4862 | ||
4858 | for (ep = 0; ep < hsotg->num_of_eps; ep++) { | 4863 | for (ep = 0; ep < hsotg->num_of_eps; ep++) { |
4859 | if (hsotg->eps_in[ep]) | 4864 | if (hsotg->eps_in[ep]) |
4860 | dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep); | 4865 | dwc2_hsotg_ep_disable_lock(&hsotg->eps_in[ep]->ep); |
4861 | if (hsotg->eps_out[ep]) | 4866 | if (hsotg->eps_out[ep]) |
4862 | dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep); | 4867 | dwc2_hsotg_ep_disable_lock(&hsotg->eps_out[ep]->ep); |
4863 | } | 4868 | } |
4864 | } | 4869 | } |
4865 | 4870 | ||
@@ -5026,6 +5031,7 @@ void dwc2_gadget_init_lpm(struct dwc2_hsotg *hsotg) | |||
5026 | val |= hsotg->params.lpm_clock_gating ? GLPMCFG_ENBLSLPM : 0; | 5031 | val |= hsotg->params.lpm_clock_gating ? GLPMCFG_ENBLSLPM : 0; |
5027 | val |= hsotg->params.hird_threshold << GLPMCFG_HIRD_THRES_SHIFT; | 5032 | val |= hsotg->params.hird_threshold << GLPMCFG_HIRD_THRES_SHIFT; |
5028 | val |= hsotg->params.besl ? GLPMCFG_ENBESL : 0; | 5033 | val |= hsotg->params.besl ? GLPMCFG_ENBESL : 0; |
5034 | val |= GLPMCFG_LPM_ACCEPT_CTRL_ISOC; | ||
5029 | dwc2_writel(hsotg, val, GLPMCFG); | 5035 | dwc2_writel(hsotg, val, GLPMCFG); |
5030 | dev_dbg(hsotg->dev, "GLPMCFG=0x%08x\n", dwc2_readl(hsotg, GLPMCFG)); | 5036 | dev_dbg(hsotg->dev, "GLPMCFG=0x%08x\n", dwc2_readl(hsotg, GLPMCFG)); |
5031 | 5037 | ||
diff --git a/drivers/usb/dwc2/hcd.h b/drivers/usb/dwc2/hcd.h index 3f9bccc95add..c089ffa1f0a8 100644 --- a/drivers/usb/dwc2/hcd.h +++ b/drivers/usb/dwc2/hcd.h | |||
@@ -366,7 +366,7 @@ struct dwc2_qh { | |||
366 | u32 desc_list_sz; | 366 | u32 desc_list_sz; |
367 | u32 *n_bytes; | 367 | u32 *n_bytes; |
368 | struct timer_list unreserve_timer; | 368 | struct timer_list unreserve_timer; |
369 | struct timer_list wait_timer; | 369 | struct hrtimer wait_timer; |
370 | struct dwc2_tt *dwc_tt; | 370 | struct dwc2_tt *dwc_tt; |
371 | int ttport; | 371 | int ttport; |
372 | unsigned tt_buffer_dirty:1; | 372 | unsigned tt_buffer_dirty:1; |
diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c index 40839591d2ec..ea3aa640c15c 100644 --- a/drivers/usb/dwc2/hcd_queue.c +++ b/drivers/usb/dwc2/hcd_queue.c | |||
@@ -59,7 +59,7 @@ | |||
59 | #define DWC2_UNRESERVE_DELAY (msecs_to_jiffies(5)) | 59 | #define DWC2_UNRESERVE_DELAY (msecs_to_jiffies(5)) |
60 | 60 | ||
61 | /* If we get a NAK, wait this long before retrying */ | 61 | /* If we get a NAK, wait this long before retrying */ |
62 | #define DWC2_RETRY_WAIT_DELAY (msecs_to_jiffies(1)) | 62 | #define DWC2_RETRY_WAIT_DELAY 1*1E6L |
63 | 63 | ||
64 | /** | 64 | /** |
65 | * dwc2_periodic_channel_available() - Checks that a channel is available for a | 65 | * dwc2_periodic_channel_available() - Checks that a channel is available for a |
@@ -1464,10 +1464,12 @@ static void dwc2_deschedule_periodic(struct dwc2_hsotg *hsotg, | |||
1464 | * qh back to the "inactive" list, then queues transactions. | 1464 | * qh back to the "inactive" list, then queues transactions. |
1465 | * | 1465 | * |
1466 | * @t: Pointer to wait_timer in a qh. | 1466 | * @t: Pointer to wait_timer in a qh. |
1467 | * | ||
1468 | * Return: HRTIMER_NORESTART to not automatically restart this timer. | ||
1467 | */ | 1469 | */ |
1468 | static void dwc2_wait_timer_fn(struct timer_list *t) | 1470 | static enum hrtimer_restart dwc2_wait_timer_fn(struct hrtimer *t) |
1469 | { | 1471 | { |
1470 | struct dwc2_qh *qh = from_timer(qh, t, wait_timer); | 1472 | struct dwc2_qh *qh = container_of(t, struct dwc2_qh, wait_timer); |
1471 | struct dwc2_hsotg *hsotg = qh->hsotg; | 1473 | struct dwc2_hsotg *hsotg = qh->hsotg; |
1472 | unsigned long flags; | 1474 | unsigned long flags; |
1473 | 1475 | ||
@@ -1491,6 +1493,7 @@ static void dwc2_wait_timer_fn(struct timer_list *t) | |||
1491 | } | 1493 | } |
1492 | 1494 | ||
1493 | spin_unlock_irqrestore(&hsotg->lock, flags); | 1495 | spin_unlock_irqrestore(&hsotg->lock, flags); |
1496 | return HRTIMER_NORESTART; | ||
1494 | } | 1497 | } |
1495 | 1498 | ||
1496 | /** | 1499 | /** |
@@ -1521,7 +1524,8 @@ static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, | |||
1521 | /* Initialize QH */ | 1524 | /* Initialize QH */ |
1522 | qh->hsotg = hsotg; | 1525 | qh->hsotg = hsotg; |
1523 | timer_setup(&qh->unreserve_timer, dwc2_unreserve_timer_fn, 0); | 1526 | timer_setup(&qh->unreserve_timer, dwc2_unreserve_timer_fn, 0); |
1524 | timer_setup(&qh->wait_timer, dwc2_wait_timer_fn, 0); | 1527 | hrtimer_init(&qh->wait_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); |
1528 | qh->wait_timer.function = &dwc2_wait_timer_fn; | ||
1525 | qh->ep_type = ep_type; | 1529 | qh->ep_type = ep_type; |
1526 | qh->ep_is_in = ep_is_in; | 1530 | qh->ep_is_in = ep_is_in; |
1527 | 1531 | ||
@@ -1690,7 +1694,7 @@ void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) | |||
1690 | * won't do anything anyway, but we want it to finish before we free | 1694 | * won't do anything anyway, but we want it to finish before we free |
1691 | * memory. | 1695 | * memory. |
1692 | */ | 1696 | */ |
1693 | del_timer_sync(&qh->wait_timer); | 1697 | hrtimer_cancel(&qh->wait_timer); |
1694 | 1698 | ||
1695 | dwc2_host_put_tt_info(hsotg, qh->dwc_tt); | 1699 | dwc2_host_put_tt_info(hsotg, qh->dwc_tt); |
1696 | 1700 | ||
@@ -1716,6 +1720,7 @@ int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) | |||
1716 | { | 1720 | { |
1717 | int status; | 1721 | int status; |
1718 | u32 intr_mask; | 1722 | u32 intr_mask; |
1723 | ktime_t delay; | ||
1719 | 1724 | ||
1720 | if (dbg_qh(qh)) | 1725 | if (dbg_qh(qh)) |
1721 | dev_vdbg(hsotg->dev, "%s()\n", __func__); | 1726 | dev_vdbg(hsotg->dev, "%s()\n", __func__); |
@@ -1734,8 +1739,8 @@ int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) | |||
1734 | list_add_tail(&qh->qh_list_entry, | 1739 | list_add_tail(&qh->qh_list_entry, |
1735 | &hsotg->non_periodic_sched_waiting); | 1740 | &hsotg->non_periodic_sched_waiting); |
1736 | qh->wait_timer_cancel = false; | 1741 | qh->wait_timer_cancel = false; |
1737 | mod_timer(&qh->wait_timer, | 1742 | delay = ktime_set(0, DWC2_RETRY_WAIT_DELAY); |
1738 | jiffies + DWC2_RETRY_WAIT_DELAY + 1); | 1743 | hrtimer_start(&qh->wait_timer, delay, HRTIMER_MODE_REL); |
1739 | } else { | 1744 | } else { |
1740 | list_add_tail(&qh->qh_list_entry, | 1745 | list_add_tail(&qh->qh_list_entry, |
1741 | &hsotg->non_periodic_sched_inactive); | 1746 | &hsotg->non_periodic_sched_inactive); |
diff --git a/drivers/usb/dwc2/hw.h b/drivers/usb/dwc2/hw.h index 2b1ea441b7d4..98af924a9a5c 100644 --- a/drivers/usb/dwc2/hw.h +++ b/drivers/usb/dwc2/hw.h | |||
@@ -333,6 +333,8 @@ | |||
333 | #define GLPMCFG_SNDLPM BIT(24) | 333 | #define GLPMCFG_SNDLPM BIT(24) |
334 | #define GLPMCFG_RETRY_CNT_MASK (0x7 << 21) | 334 | #define GLPMCFG_RETRY_CNT_MASK (0x7 << 21) |
335 | #define GLPMCFG_RETRY_CNT_SHIFT 21 | 335 | #define GLPMCFG_RETRY_CNT_SHIFT 21 |
336 | #define GLPMCFG_LPM_ACCEPT_CTRL_CONTROL BIT(21) | ||
337 | #define GLPMCFG_LPM_ACCEPT_CTRL_ISOC BIT(22) | ||
336 | #define GLPMCFG_LPM_CHNL_INDX_MASK (0xf << 17) | 338 | #define GLPMCFG_LPM_CHNL_INDX_MASK (0xf << 17) |
337 | #define GLPMCFG_LPM_CHNL_INDX_SHIFT 17 | 339 | #define GLPMCFG_LPM_CHNL_INDX_SHIFT 17 |
338 | #define GLPMCFG_L1RESUMEOK BIT(16) | 340 | #define GLPMCFG_L1RESUMEOK BIT(16) |
diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c index 7c1b6938f212..24ff5f21cb25 100644 --- a/drivers/usb/dwc2/params.c +++ b/drivers/usb/dwc2/params.c | |||
@@ -71,6 +71,13 @@ static void dwc2_set_his_params(struct dwc2_hsotg *hsotg) | |||
71 | p->power_down = false; | 71 | p->power_down = false; |
72 | } | 72 | } |
73 | 73 | ||
74 | static void dwc2_set_s3c6400_params(struct dwc2_hsotg *hsotg) | ||
75 | { | ||
76 | struct dwc2_core_params *p = &hsotg->params; | ||
77 | |||
78 | p->power_down = 0; | ||
79 | } | ||
80 | |||
74 | static void dwc2_set_rk_params(struct dwc2_hsotg *hsotg) | 81 | static void dwc2_set_rk_params(struct dwc2_hsotg *hsotg) |
75 | { | 82 | { |
76 | struct dwc2_core_params *p = &hsotg->params; | 83 | struct dwc2_core_params *p = &hsotg->params; |
@@ -111,6 +118,7 @@ static void dwc2_set_amlogic_params(struct dwc2_hsotg *hsotg) | |||
111 | p->phy_type = DWC2_PHY_TYPE_PARAM_UTMI; | 118 | p->phy_type = DWC2_PHY_TYPE_PARAM_UTMI; |
112 | p->ahbcfg = GAHBCFG_HBSTLEN_INCR8 << | 119 | p->ahbcfg = GAHBCFG_HBSTLEN_INCR8 << |
113 | GAHBCFG_HBSTLEN_SHIFT; | 120 | GAHBCFG_HBSTLEN_SHIFT; |
121 | p->power_down = DWC2_POWER_DOWN_PARAM_NONE; | ||
114 | } | 122 | } |
115 | 123 | ||
116 | static void dwc2_set_amcc_params(struct dwc2_hsotg *hsotg) | 124 | static void dwc2_set_amcc_params(struct dwc2_hsotg *hsotg) |
@@ -151,7 +159,8 @@ const struct of_device_id dwc2_of_match_table[] = { | |||
151 | { .compatible = "lantiq,arx100-usb", .data = dwc2_set_ltq_params }, | 159 | { .compatible = "lantiq,arx100-usb", .data = dwc2_set_ltq_params }, |
152 | { .compatible = "lantiq,xrx200-usb", .data = dwc2_set_ltq_params }, | 160 | { .compatible = "lantiq,xrx200-usb", .data = dwc2_set_ltq_params }, |
153 | { .compatible = "snps,dwc2" }, | 161 | { .compatible = "snps,dwc2" }, |
154 | { .compatible = "samsung,s3c6400-hsotg" }, | 162 | { .compatible = "samsung,s3c6400-hsotg", |
163 | .data = dwc2_set_s3c6400_params }, | ||
155 | { .compatible = "amlogic,meson8-usb", | 164 | { .compatible = "amlogic,meson8-usb", |
156 | .data = dwc2_set_amlogic_params }, | 165 | .data = dwc2_set_amlogic_params }, |
157 | { .compatible = "amlogic,meson8b-usb", | 166 | { .compatible = "amlogic,meson8b-usb", |
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 2f2048aa5fde..a1b126f90261 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c | |||
@@ -80,11 +80,12 @@ static int dwc3_get_dr_mode(struct dwc3 *dwc) | |||
80 | mode = USB_DR_MODE_PERIPHERAL; | 80 | mode = USB_DR_MODE_PERIPHERAL; |
81 | 81 | ||
82 | /* | 82 | /* |
83 | * dwc_usb31 does not support OTG mode. If the controller | 83 | * DWC_usb31 and DWC_usb3 v3.30a and higher do not support OTG |
84 | * supports DRD but the dr_mode is not specified or set to OTG, | 84 | * mode. If the controller supports DRD but the dr_mode is not |
85 | * then set the mode to peripheral. | 85 | * specified or set to OTG, then set the mode to peripheral. |
86 | */ | 86 | */ |
87 | if (mode == USB_DR_MODE_OTG && dwc3_is_usb31(dwc)) | 87 | if (mode == USB_DR_MODE_OTG && |
88 | dwc->revision >= DWC3_REVISION_330A) | ||
88 | mode = USB_DR_MODE_PERIPHERAL; | 89 | mode = USB_DR_MODE_PERIPHERAL; |
89 | } | 90 | } |
90 | 91 | ||
@@ -661,6 +662,8 @@ static int dwc3_phy_setup(struct dwc3 *dwc) | |||
661 | 662 | ||
662 | if (dwc->dis_enblslpm_quirk) | 663 | if (dwc->dis_enblslpm_quirk) |
663 | reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM; | 664 | reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM; |
665 | else | ||
666 | reg |= DWC3_GUSB2PHYCFG_ENBLSLPM; | ||
664 | 667 | ||
665 | if (dwc->dis_u2_freeclk_exists_quirk) | 668 | if (dwc->dis_u2_freeclk_exists_quirk) |
666 | reg &= ~DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS; | 669 | reg &= ~DWC3_GUSB2PHYCFG_U2_FREECLK_EXISTS; |
@@ -702,6 +705,7 @@ static bool dwc3_core_is_valid(struct dwc3 *dwc) | |||
702 | /* Detected DWC_usb31 IP */ | 705 | /* Detected DWC_usb31 IP */ |
703 | dwc->revision = dwc3_readl(dwc->regs, DWC3_VER_NUMBER); | 706 | dwc->revision = dwc3_readl(dwc->regs, DWC3_VER_NUMBER); |
704 | dwc->revision |= DWC3_REVISION_IS_DWC31; | 707 | dwc->revision |= DWC3_REVISION_IS_DWC31; |
708 | dwc->version_type = dwc3_readl(dwc->regs, DWC3_VER_TYPE); | ||
705 | } else { | 709 | } else { |
706 | return false; | 710 | return false; |
707 | } | 711 | } |
@@ -1244,8 +1248,12 @@ static void dwc3_get_properties(struct dwc3 *dwc) | |||
1244 | "snps,is-utmi-l1-suspend"); | 1248 | "snps,is-utmi-l1-suspend"); |
1245 | device_property_read_u8(dev, "snps,hird-threshold", | 1249 | device_property_read_u8(dev, "snps,hird-threshold", |
1246 | &hird_threshold); | 1250 | &hird_threshold); |
1251 | dwc->dis_start_transfer_quirk = device_property_read_bool(dev, | ||
1252 | "snps,dis-start-transfer-quirk"); | ||
1247 | dwc->usb3_lpm_capable = device_property_read_bool(dev, | 1253 | dwc->usb3_lpm_capable = device_property_read_bool(dev, |
1248 | "snps,usb3_lpm_capable"); | 1254 | "snps,usb3_lpm_capable"); |
1255 | dwc->usb2_lpm_disable = device_property_read_bool(dev, | ||
1256 | "snps,usb2-lpm-disable"); | ||
1249 | device_property_read_u8(dev, "snps,rx-thr-num-pkt-prd", | 1257 | device_property_read_u8(dev, "snps,rx-thr-num-pkt-prd", |
1250 | &rx_thr_num_pkt_prd); | 1258 | &rx_thr_num_pkt_prd); |
1251 | device_property_read_u8(dev, "snps,rx-max-burst-prd", | 1259 | device_property_read_u8(dev, "snps,rx-max-burst-prd", |
@@ -1482,7 +1490,8 @@ static int dwc3_probe(struct platform_device *pdev) | |||
1482 | 1490 | ||
1483 | ret = dwc3_core_init(dwc); | 1491 | ret = dwc3_core_init(dwc); |
1484 | if (ret) { | 1492 | if (ret) { |
1485 | dev_err(dev, "failed to initialize core\n"); | 1493 | if (ret != -EPROBE_DEFER) |
1494 | dev_err(dev, "failed to initialize core: %d\n", ret); | ||
1486 | goto err4; | 1495 | goto err4; |
1487 | } | 1496 | } |
1488 | 1497 | ||
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 5bfb62533e0f..df876418cb78 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h | |||
@@ -37,6 +37,7 @@ | |||
37 | #define DWC3_EP0_SETUP_SIZE 512 | 37 | #define DWC3_EP0_SETUP_SIZE 512 |
38 | #define DWC3_ENDPOINTS_NUM 32 | 38 | #define DWC3_ENDPOINTS_NUM 32 |
39 | #define DWC3_XHCI_RESOURCES_NUM 2 | 39 | #define DWC3_XHCI_RESOURCES_NUM 2 |
40 | #define DWC3_ISOC_MAX_RETRIES 5 | ||
40 | 41 | ||
41 | #define DWC3_SCRATCHBUF_SIZE 4096 /* each buffer is assumed to be 4KiB */ | 42 | #define DWC3_SCRATCHBUF_SIZE 4096 /* each buffer is assumed to be 4KiB */ |
42 | #define DWC3_EVENT_BUFFERS_SIZE 4096 | 43 | #define DWC3_EVENT_BUFFERS_SIZE 4096 |
@@ -174,13 +175,19 @@ | |||
174 | #define DWC3_GSBUSCFG0_INCRBRSTENA (1 << 0) /* undefined length enable */ | 175 | #define DWC3_GSBUSCFG0_INCRBRSTENA (1 << 0) /* undefined length enable */ |
175 | #define DWC3_GSBUSCFG0_INCRBRST_MASK 0xff | 176 | #define DWC3_GSBUSCFG0_INCRBRST_MASK 0xff |
176 | 177 | ||
178 | /* Global Debug LSP MUX Select */ | ||
179 | #define DWC3_GDBGLSPMUX_ENDBC BIT(15) /* Host only */ | ||
180 | #define DWC3_GDBGLSPMUX_HOSTSELECT(n) ((n) & 0x3fff) | ||
181 | #define DWC3_GDBGLSPMUX_DEVSELECT(n) (((n) & 0xf) << 4) | ||
182 | #define DWC3_GDBGLSPMUX_EPSELECT(n) ((n) & 0xf) | ||
183 | |||
177 | /* Global Debug Queue/FIFO Space Available Register */ | 184 | /* Global Debug Queue/FIFO Space Available Register */ |
178 | #define DWC3_GDBGFIFOSPACE_NUM(n) ((n) & 0x1f) | 185 | #define DWC3_GDBGFIFOSPACE_NUM(n) ((n) & 0x1f) |
179 | #define DWC3_GDBGFIFOSPACE_TYPE(n) (((n) << 5) & 0x1e0) | 186 | #define DWC3_GDBGFIFOSPACE_TYPE(n) (((n) << 5) & 0x1e0) |
180 | #define DWC3_GDBGFIFOSPACE_SPACE_AVAILABLE(n) (((n) >> 16) & 0xffff) | 187 | #define DWC3_GDBGFIFOSPACE_SPACE_AVAILABLE(n) (((n) >> 16) & 0xffff) |
181 | 188 | ||
182 | #define DWC3_TXFIFOQ 0 | 189 | #define DWC3_TXFIFO 0 |
183 | #define DWC3_RXFIFOQ 1 | 190 | #define DWC3_RXFIFO 1 |
184 | #define DWC3_TXREQQ 2 | 191 | #define DWC3_TXREQQ 2 |
185 | #define DWC3_RXREQQ 3 | 192 | #define DWC3_RXREQQ 3 |
186 | #define DWC3_RXINFOQ 4 | 193 | #define DWC3_RXINFOQ 4 |
@@ -253,6 +260,9 @@ | |||
253 | #define DWC3_GSTS_DEVICE_IP BIT(6) | 260 | #define DWC3_GSTS_DEVICE_IP BIT(6) |
254 | #define DWC3_GSTS_CSR_TIMEOUT BIT(5) | 261 | #define DWC3_GSTS_CSR_TIMEOUT BIT(5) |
255 | #define DWC3_GSTS_BUS_ERR_ADDR_VLD BIT(4) | 262 | #define DWC3_GSTS_BUS_ERR_ADDR_VLD BIT(4) |
263 | #define DWC3_GSTS_CURMOD(n) ((n) & 0x3) | ||
264 | #define DWC3_GSTS_CURMOD_DEVICE 0 | ||
265 | #define DWC3_GSTS_CURMOD_HOST 1 | ||
256 | 266 | ||
257 | /* Global USB2 PHY Configuration Register */ | 267 | /* Global USB2 PHY Configuration Register */ |
258 | #define DWC3_GUSB2PHYCFG_PHYSOFTRST BIT(31) | 268 | #define DWC3_GUSB2PHYCFG_PHYSOFTRST BIT(31) |
@@ -321,6 +331,7 @@ | |||
321 | #define DWC3_GHWPARAMS1_EN_PWROPT_HIB 2 | 331 | #define DWC3_GHWPARAMS1_EN_PWROPT_HIB 2 |
322 | #define DWC3_GHWPARAMS1_PWROPT(n) ((n) << 24) | 332 | #define DWC3_GHWPARAMS1_PWROPT(n) ((n) << 24) |
323 | #define DWC3_GHWPARAMS1_PWROPT_MASK DWC3_GHWPARAMS1_PWROPT(3) | 333 | #define DWC3_GHWPARAMS1_PWROPT_MASK DWC3_GHWPARAMS1_PWROPT(3) |
334 | #define DWC3_GHWPARAMS1_ENDBC BIT(31) | ||
324 | 335 | ||
325 | /* Global HWPARAMS3 Register */ | 336 | /* Global HWPARAMS3 Register */ |
326 | #define DWC3_GHWPARAMS3_SSPHY_IFC(n) ((n) & 3) | 337 | #define DWC3_GHWPARAMS3_SSPHY_IFC(n) ((n) & 3) |
@@ -636,9 +647,9 @@ struct dwc3_event_buffer { | |||
636 | /** | 647 | /** |
637 | * struct dwc3_ep - device side endpoint representation | 648 | * struct dwc3_ep - device side endpoint representation |
638 | * @endpoint: usb endpoint | 649 | * @endpoint: usb endpoint |
650 | * @cancelled_list: list of cancelled requests for this endpoint | ||
639 | * @pending_list: list of pending requests for this endpoint | 651 | * @pending_list: list of pending requests for this endpoint |
640 | * @started_list: list of started requests on this endpoint | 652 | * @started_list: list of started requests on this endpoint |
641 | * @wait_end_transfer: wait_queue_head_t for waiting on End Transfer complete | ||
642 | * @lock: spinlock for endpoint request queue traversal | 653 | * @lock: spinlock for endpoint request queue traversal |
643 | * @regs: pointer to first endpoint register | 654 | * @regs: pointer to first endpoint register |
644 | * @trb_pool: array of transaction buffers | 655 | * @trb_pool: array of transaction buffers |
@@ -656,14 +667,17 @@ struct dwc3_event_buffer { | |||
656 | * @name: a human readable name e.g. ep1out-bulk | 667 | * @name: a human readable name e.g. ep1out-bulk |
657 | * @direction: true for TX, false for RX | 668 | * @direction: true for TX, false for RX |
658 | * @stream_capable: true when streams are enabled | 669 | * @stream_capable: true when streams are enabled |
670 | * @combo_num: the test combination BIT[15:14] of the frame number to test | ||
671 | * isochronous START TRANSFER command failure workaround | ||
672 | * @start_cmd_status: the status of testing START TRANSFER command with | ||
673 | * combo_num = 'b00 | ||
659 | */ | 674 | */ |
660 | struct dwc3_ep { | 675 | struct dwc3_ep { |
661 | struct usb_ep endpoint; | 676 | struct usb_ep endpoint; |
677 | struct list_head cancelled_list; | ||
662 | struct list_head pending_list; | 678 | struct list_head pending_list; |
663 | struct list_head started_list; | 679 | struct list_head started_list; |
664 | 680 | ||
665 | wait_queue_head_t wait_end_transfer; | ||
666 | |||
667 | spinlock_t lock; | 681 | spinlock_t lock; |
668 | void __iomem *regs; | 682 | void __iomem *regs; |
669 | 683 | ||
@@ -705,6 +719,10 @@ struct dwc3_ep { | |||
705 | 719 | ||
706 | unsigned direction:1; | 720 | unsigned direction:1; |
707 | unsigned stream_capable:1; | 721 | unsigned stream_capable:1; |
722 | |||
723 | /* For isochronous START TRANSFER workaround only */ | ||
724 | u8 combo_num; | ||
725 | int start_cmd_status; | ||
708 | }; | 726 | }; |
709 | 727 | ||
710 | enum dwc3_phy { | 728 | enum dwc3_phy { |
@@ -766,6 +784,7 @@ enum dwc3_link_state { | |||
766 | #define DWC3_TRB_CTRL_ISP_IMI BIT(10) | 784 | #define DWC3_TRB_CTRL_ISP_IMI BIT(10) |
767 | #define DWC3_TRB_CTRL_IOC BIT(11) | 785 | #define DWC3_TRB_CTRL_IOC BIT(11) |
768 | #define DWC3_TRB_CTRL_SID_SOFN(n) (((n) & 0xffff) << 14) | 786 | #define DWC3_TRB_CTRL_SID_SOFN(n) (((n) & 0xffff) << 14) |
787 | #define DWC3_TRB_CTRL_GET_SID_SOFN(n) (((n) & (0xffff << 14)) >> 14) | ||
769 | 788 | ||
770 | #define DWC3_TRBCTL_TYPE(n) ((n) & (0x3f << 4)) | 789 | #define DWC3_TRBCTL_TYPE(n) ((n) & (0x3f << 4)) |
771 | #define DWC3_TRBCTL_NORMAL DWC3_TRB_CTRL_TRBCTL(1) | 790 | #define DWC3_TRBCTL_NORMAL DWC3_TRB_CTRL_TRBCTL(1) |
@@ -847,11 +866,12 @@ struct dwc3_hwparams { | |||
847 | * @epnum: endpoint number to which this request refers | 866 | * @epnum: endpoint number to which this request refers |
848 | * @trb: pointer to struct dwc3_trb | 867 | * @trb: pointer to struct dwc3_trb |
849 | * @trb_dma: DMA address of @trb | 868 | * @trb_dma: DMA address of @trb |
850 | * @unaligned: true for OUT endpoints with length not divisible by maxp | 869 | * @num_trbs: number of TRBs used by this request |
870 | * @needs_extra_trb: true when request needs one extra TRB (either due to ZLP | ||
871 | * or unaligned OUT) | ||
851 | * @direction: IN or OUT direction flag | 872 | * @direction: IN or OUT direction flag |
852 | * @mapped: true when request has been dma-mapped | 873 | * @mapped: true when request has been dma-mapped |
853 | * @started: request is started | 874 | * @started: request is started |
854 | * @zero: wants a ZLP | ||
855 | */ | 875 | */ |
856 | struct dwc3_request { | 876 | struct dwc3_request { |
857 | struct usb_request request; | 877 | struct usb_request request; |
@@ -867,11 +887,12 @@ struct dwc3_request { | |||
867 | struct dwc3_trb *trb; | 887 | struct dwc3_trb *trb; |
868 | dma_addr_t trb_dma; | 888 | dma_addr_t trb_dma; |
869 | 889 | ||
870 | unsigned unaligned:1; | 890 | unsigned num_trbs; |
891 | |||
892 | unsigned needs_extra_trb:1; | ||
871 | unsigned direction:1; | 893 | unsigned direction:1; |
872 | unsigned mapped:1; | 894 | unsigned mapped:1; |
873 | unsigned started:1; | 895 | unsigned started:1; |
874 | unsigned zero:1; | ||
875 | }; | 896 | }; |
876 | 897 | ||
877 | /* | 898 | /* |
@@ -918,6 +939,7 @@ struct dwc3_scratchpad_array { | |||
918 | * @u1u2: only used on revisions <1.83a for workaround | 939 | * @u1u2: only used on revisions <1.83a for workaround |
919 | * @maximum_speed: maximum speed requested (mainly for testing purposes) | 940 | * @maximum_speed: maximum speed requested (mainly for testing purposes) |
920 | * @revision: revision register contents | 941 | * @revision: revision register contents |
942 | * @version_type: VERSIONTYPE register contents, a sub release of a revision | ||
921 | * @dr_mode: requested mode of operation | 943 | * @dr_mode: requested mode of operation |
922 | * @current_dr_role: current role of operation when in dual-role mode | 944 | * @current_dr_role: current role of operation when in dual-role mode |
923 | * @desired_dr_role: desired role of operation when in dual-role mode | 945 | * @desired_dr_role: desired role of operation when in dual-role mode |
@@ -945,6 +967,7 @@ struct dwc3_scratchpad_array { | |||
945 | * @hwparams: copy of hwparams registers | 967 | * @hwparams: copy of hwparams registers |
946 | * @root: debugfs root folder pointer | 968 | * @root: debugfs root folder pointer |
947 | * @regset: debugfs pointer to regdump file | 969 | * @regset: debugfs pointer to regdump file |
970 | * @dbg_lsp_select: current debug lsp mux register selection | ||
948 | * @test_mode: true when we're entering a USB test mode | 971 | * @test_mode: true when we're entering a USB test mode |
949 | * @test_mode_nr: test feature selector | 972 | * @test_mode_nr: test feature selector |
950 | * @lpm_nyet_threshold: LPM NYET response threshold | 973 | * @lpm_nyet_threshold: LPM NYET response threshold |
@@ -970,7 +993,10 @@ struct dwc3_scratchpad_array { | |||
970 | * @pullups_connected: true when Run/Stop bit is set | 993 | * @pullups_connected: true when Run/Stop bit is set |
971 | * @setup_packet_pending: true when there's a Setup Packet in FIFO. Workaround | 994 | * @setup_packet_pending: true when there's a Setup Packet in FIFO. Workaround |
972 | * @three_stage_setup: set if we perform a three phase setup | 995 | * @three_stage_setup: set if we perform a three phase setup |
996 | * @dis_start_transfer_quirk: set if start_transfer failure SW workaround is | ||
997 | * not needed for DWC_usb31 version 1.70a-ea06 and below | ||
973 | * @usb3_lpm_capable: set if hadrware supports Link Power Management | 998 | * @usb3_lpm_capable: set if hadrware supports Link Power Management |
999 | * @usb2_lpm_disable: set to disable usb2 lpm | ||
974 | * @disable_scramble_quirk: set if we enable the disable scramble quirk | 1000 | * @disable_scramble_quirk: set if we enable the disable scramble quirk |
975 | * @u2exit_lfps_quirk: set if we enable u2exit lfps quirk | 1001 | * @u2exit_lfps_quirk: set if we enable u2exit lfps quirk |
976 | * @u2ss_inp3_quirk: set if we enable P3 OK for U2/SS Inactive quirk | 1002 | * @u2ss_inp3_quirk: set if we enable P3 OK for U2/SS Inactive quirk |
@@ -1095,6 +1121,7 @@ struct dwc3 { | |||
1095 | #define DWC3_REVISION_290A 0x5533290a | 1121 | #define DWC3_REVISION_290A 0x5533290a |
1096 | #define DWC3_REVISION_300A 0x5533300a | 1122 | #define DWC3_REVISION_300A 0x5533300a |
1097 | #define DWC3_REVISION_310A 0x5533310a | 1123 | #define DWC3_REVISION_310A 0x5533310a |
1124 | #define DWC3_REVISION_330A 0x5533330a | ||
1098 | 1125 | ||
1099 | /* | 1126 | /* |
1100 | * NOTICE: we're using bit 31 as a "is usb 3.1" flag. This is really | 1127 | * NOTICE: we're using bit 31 as a "is usb 3.1" flag. This is really |
@@ -1103,6 +1130,17 @@ struct dwc3 { | |||
1103 | #define DWC3_REVISION_IS_DWC31 0x80000000 | 1130 | #define DWC3_REVISION_IS_DWC31 0x80000000 |
1104 | #define DWC3_USB31_REVISION_110A (0x3131302a | DWC3_REVISION_IS_DWC31) | 1131 | #define DWC3_USB31_REVISION_110A (0x3131302a | DWC3_REVISION_IS_DWC31) |
1105 | #define DWC3_USB31_REVISION_120A (0x3132302a | DWC3_REVISION_IS_DWC31) | 1132 | #define DWC3_USB31_REVISION_120A (0x3132302a | DWC3_REVISION_IS_DWC31) |
1133 | #define DWC3_USB31_REVISION_160A (0x3136302a | DWC3_REVISION_IS_DWC31) | ||
1134 | #define DWC3_USB31_REVISION_170A (0x3137302a | DWC3_REVISION_IS_DWC31) | ||
1135 | |||
1136 | u32 version_type; | ||
1137 | |||
1138 | #define DWC31_VERSIONTYPE_EA01 0x65613031 | ||
1139 | #define DWC31_VERSIONTYPE_EA02 0x65613032 | ||
1140 | #define DWC31_VERSIONTYPE_EA03 0x65613033 | ||
1141 | #define DWC31_VERSIONTYPE_EA04 0x65613034 | ||
1142 | #define DWC31_VERSIONTYPE_EA05 0x65613035 | ||
1143 | #define DWC31_VERSIONTYPE_EA06 0x65613036 | ||
1106 | 1144 | ||
1107 | enum dwc3_ep0_next ep0_next_event; | 1145 | enum dwc3_ep0_next ep0_next_event; |
1108 | enum dwc3_ep0_state ep0state; | 1146 | enum dwc3_ep0_state ep0state; |
@@ -1121,6 +1159,8 @@ struct dwc3 { | |||
1121 | struct dentry *root; | 1159 | struct dentry *root; |
1122 | struct debugfs_regset32 *regset; | 1160 | struct debugfs_regset32 *regset; |
1123 | 1161 | ||
1162 | u32 dbg_lsp_select; | ||
1163 | |||
1124 | u8 test_mode; | 1164 | u8 test_mode; |
1125 | u8 test_mode_nr; | 1165 | u8 test_mode_nr; |
1126 | u8 lpm_nyet_threshold; | 1166 | u8 lpm_nyet_threshold; |
@@ -1145,7 +1185,9 @@ struct dwc3 { | |||
1145 | unsigned pullups_connected:1; | 1185 | unsigned pullups_connected:1; |
1146 | unsigned setup_packet_pending:1; | 1186 | unsigned setup_packet_pending:1; |
1147 | unsigned three_stage_setup:1; | 1187 | unsigned three_stage_setup:1; |
1188 | unsigned dis_start_transfer_quirk:1; | ||
1148 | unsigned usb3_lpm_capable:1; | 1189 | unsigned usb3_lpm_capable:1; |
1190 | unsigned usb2_lpm_disable:1; | ||
1149 | 1191 | ||
1150 | unsigned disable_scramble_quirk:1; | 1192 | unsigned disable_scramble_quirk:1; |
1151 | unsigned u2exit_lfps_quirk:1; | 1193 | unsigned u2exit_lfps_quirk:1; |
diff --git a/drivers/usb/dwc3/debug.h b/drivers/usb/dwc3/debug.h index c66d216dcc30..4f75ab3505b7 100644 --- a/drivers/usb/dwc3/debug.h +++ b/drivers/usb/dwc3/debug.h | |||
@@ -117,6 +117,35 @@ dwc3_gadget_link_string(enum dwc3_link_state link_state) | |||
117 | } | 117 | } |
118 | 118 | ||
119 | /** | 119 | /** |
120 | * dwc3_gadget_hs_link_string - returns highspeed and below link name | ||
121 | * @link_state: link state code | ||
122 | */ | ||
123 | static inline const char * | ||
124 | dwc3_gadget_hs_link_string(enum dwc3_link_state link_state) | ||
125 | { | ||
126 | switch (link_state) { | ||
127 | case DWC3_LINK_STATE_U0: | ||
128 | return "On"; | ||
129 | case DWC3_LINK_STATE_U2: | ||
130 | return "Sleep"; | ||
131 | case DWC3_LINK_STATE_U3: | ||
132 | return "Suspend"; | ||
133 | case DWC3_LINK_STATE_SS_DIS: | ||
134 | return "Disconnected"; | ||
135 | case DWC3_LINK_STATE_RX_DET: | ||
136 | return "Early Suspend"; | ||
137 | case DWC3_LINK_STATE_RECOV: | ||
138 | return "Recovery"; | ||
139 | case DWC3_LINK_STATE_RESET: | ||
140 | return "Reset"; | ||
141 | case DWC3_LINK_STATE_RESUME: | ||
142 | return "Resume"; | ||
143 | default: | ||
144 | return "UNKNOWN link state\n"; | ||
145 | } | ||
146 | } | ||
147 | |||
148 | /** | ||
120 | * dwc3_trb_type_string - returns TRB type as a string | 149 | * dwc3_trb_type_string - returns TRB type as a string |
121 | * @type: the type of the TRB | 150 | * @type: the type of the TRB |
122 | */ | 151 | */ |
diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index df8e73ec3342..1c792710348f 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c | |||
@@ -25,6 +25,8 @@ | |||
25 | #include "io.h" | 25 | #include "io.h" |
26 | #include "debug.h" | 26 | #include "debug.h" |
27 | 27 | ||
28 | #define DWC3_LSP_MUX_UNSELECTED 0xfffff | ||
29 | |||
28 | #define dump_register(nm) \ | 30 | #define dump_register(nm) \ |
29 | { \ | 31 | { \ |
30 | .name = __stringify(nm), \ | 32 | .name = __stringify(nm), \ |
@@ -82,10 +84,6 @@ static const struct debugfs_reg32 dwc3_regs[] = { | |||
82 | dump_register(GDBGFIFOSPACE), | 84 | dump_register(GDBGFIFOSPACE), |
83 | dump_register(GDBGLTSSM), | 85 | dump_register(GDBGLTSSM), |
84 | dump_register(GDBGBMU), | 86 | dump_register(GDBGBMU), |
85 | dump_register(GDBGLSPMUX), | ||
86 | dump_register(GDBGLSP), | ||
87 | dump_register(GDBGEPINFO0), | ||
88 | dump_register(GDBGEPINFO1), | ||
89 | dump_register(GPRTBIMAP_HS0), | 87 | dump_register(GPRTBIMAP_HS0), |
90 | dump_register(GPRTBIMAP_HS1), | 88 | dump_register(GPRTBIMAP_HS1), |
91 | dump_register(GPRTBIMAP_FS0), | 89 | dump_register(GPRTBIMAP_FS0), |
@@ -279,6 +277,114 @@ static const struct debugfs_reg32 dwc3_regs[] = { | |||
279 | dump_register(OSTS), | 277 | dump_register(OSTS), |
280 | }; | 278 | }; |
281 | 279 | ||
280 | static void dwc3_host_lsp(struct seq_file *s) | ||
281 | { | ||
282 | struct dwc3 *dwc = s->private; | ||
283 | bool dbc_enabled; | ||
284 | u32 sel; | ||
285 | u32 reg; | ||
286 | u32 val; | ||
287 | |||
288 | dbc_enabled = !!(dwc->hwparams.hwparams1 & DWC3_GHWPARAMS1_ENDBC); | ||
289 | |||
290 | sel = dwc->dbg_lsp_select; | ||
291 | if (sel == DWC3_LSP_MUX_UNSELECTED) { | ||
292 | seq_puts(s, "Write LSP selection to print for host\n"); | ||
293 | return; | ||
294 | } | ||
295 | |||
296 | reg = DWC3_GDBGLSPMUX_HOSTSELECT(sel); | ||
297 | |||
298 | dwc3_writel(dwc->regs, DWC3_GDBGLSPMUX, reg); | ||
299 | val = dwc3_readl(dwc->regs, DWC3_GDBGLSP); | ||
300 | seq_printf(s, "GDBGLSP[%d] = 0x%08x\n", sel, val); | ||
301 | |||
302 | if (dbc_enabled && sel < 256) { | ||
303 | reg |= DWC3_GDBGLSPMUX_ENDBC; | ||
304 | dwc3_writel(dwc->regs, DWC3_GDBGLSPMUX, reg); | ||
305 | val = dwc3_readl(dwc->regs, DWC3_GDBGLSP); | ||
306 | seq_printf(s, "GDBGLSP_DBC[%d] = 0x%08x\n", sel, val); | ||
307 | } | ||
308 | } | ||
309 | |||
310 | static void dwc3_gadget_lsp(struct seq_file *s) | ||
311 | { | ||
312 | struct dwc3 *dwc = s->private; | ||
313 | int i; | ||
314 | u32 reg; | ||
315 | |||
316 | for (i = 0; i < 16; i++) { | ||
317 | reg = DWC3_GDBGLSPMUX_DEVSELECT(i); | ||
318 | dwc3_writel(dwc->regs, DWC3_GDBGLSPMUX, reg); | ||
319 | reg = dwc3_readl(dwc->regs, DWC3_GDBGLSP); | ||
320 | seq_printf(s, "GDBGLSP[%d] = 0x%08x\n", i, reg); | ||
321 | } | ||
322 | } | ||
323 | |||
324 | static int dwc3_lsp_show(struct seq_file *s, void *unused) | ||
325 | { | ||
326 | struct dwc3 *dwc = s->private; | ||
327 | unsigned int current_mode; | ||
328 | unsigned long flags; | ||
329 | u32 reg; | ||
330 | |||
331 | spin_lock_irqsave(&dwc->lock, flags); | ||
332 | reg = dwc3_readl(dwc->regs, DWC3_GSTS); | ||
333 | current_mode = DWC3_GSTS_CURMOD(reg); | ||
334 | |||
335 | switch (current_mode) { | ||
336 | case DWC3_GSTS_CURMOD_HOST: | ||
337 | dwc3_host_lsp(s); | ||
338 | break; | ||
339 | case DWC3_GSTS_CURMOD_DEVICE: | ||
340 | dwc3_gadget_lsp(s); | ||
341 | break; | ||
342 | default: | ||
343 | seq_puts(s, "Mode is unknown, no LSP register printed\n"); | ||
344 | break; | ||
345 | } | ||
346 | spin_unlock_irqrestore(&dwc->lock, flags); | ||
347 | |||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | static int dwc3_lsp_open(struct inode *inode, struct file *file) | ||
352 | { | ||
353 | return single_open(file, dwc3_lsp_show, inode->i_private); | ||
354 | } | ||
355 | |||
356 | static ssize_t dwc3_lsp_write(struct file *file, const char __user *ubuf, | ||
357 | size_t count, loff_t *ppos) | ||
358 | { | ||
359 | struct seq_file *s = file->private_data; | ||
360 | struct dwc3 *dwc = s->private; | ||
361 | unsigned long flags; | ||
362 | char buf[32] = { 0 }; | ||
363 | u32 sel; | ||
364 | int ret; | ||
365 | |||
366 | if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) | ||
367 | return -EFAULT; | ||
368 | |||
369 | ret = kstrtouint(buf, 0, &sel); | ||
370 | if (ret) | ||
371 | return ret; | ||
372 | |||
373 | spin_lock_irqsave(&dwc->lock, flags); | ||
374 | dwc->dbg_lsp_select = sel; | ||
375 | spin_unlock_irqrestore(&dwc->lock, flags); | ||
376 | |||
377 | return count; | ||
378 | } | ||
379 | |||
380 | static const struct file_operations dwc3_lsp_fops = { | ||
381 | .open = dwc3_lsp_open, | ||
382 | .write = dwc3_lsp_write, | ||
383 | .read = seq_read, | ||
384 | .llseek = seq_lseek, | ||
385 | .release = single_release, | ||
386 | }; | ||
387 | |||
282 | static int dwc3_mode_show(struct seq_file *s, void *unused) | 388 | static int dwc3_mode_show(struct seq_file *s, void *unused) |
283 | { | 389 | { |
284 | struct dwc3 *dwc = s->private; | 390 | struct dwc3 *dwc = s->private; |
@@ -433,13 +539,24 @@ static int dwc3_link_state_show(struct seq_file *s, void *unused) | |||
433 | unsigned long flags; | 539 | unsigned long flags; |
434 | enum dwc3_link_state state; | 540 | enum dwc3_link_state state; |
435 | u32 reg; | 541 | u32 reg; |
542 | u8 speed; | ||
436 | 543 | ||
437 | spin_lock_irqsave(&dwc->lock, flags); | 544 | spin_lock_irqsave(&dwc->lock, flags); |
545 | reg = dwc3_readl(dwc->regs, DWC3_GSTS); | ||
546 | if (DWC3_GSTS_CURMOD(reg) != DWC3_GSTS_CURMOD_DEVICE) { | ||
547 | seq_puts(s, "Not available\n"); | ||
548 | spin_unlock_irqrestore(&dwc->lock, flags); | ||
549 | return 0; | ||
550 | } | ||
551 | |||
438 | reg = dwc3_readl(dwc->regs, DWC3_DSTS); | 552 | reg = dwc3_readl(dwc->regs, DWC3_DSTS); |
439 | state = DWC3_DSTS_USBLNKST(reg); | 553 | state = DWC3_DSTS_USBLNKST(reg); |
440 | spin_unlock_irqrestore(&dwc->lock, flags); | 554 | speed = reg & DWC3_DSTS_CONNECTSPD; |
441 | 555 | ||
442 | seq_printf(s, "%s\n", dwc3_gadget_link_string(state)); | 556 | seq_printf(s, "%s\n", (speed >= DWC3_DSTS_SUPERSPEED) ? |
557 | dwc3_gadget_link_string(state) : | ||
558 | dwc3_gadget_hs_link_string(state)); | ||
559 | spin_unlock_irqrestore(&dwc->lock, flags); | ||
443 | 560 | ||
444 | return 0; | 561 | return 0; |
445 | } | 562 | } |
@@ -457,6 +574,8 @@ static ssize_t dwc3_link_state_write(struct file *file, | |||
457 | unsigned long flags; | 574 | unsigned long flags; |
458 | enum dwc3_link_state state = 0; | 575 | enum dwc3_link_state state = 0; |
459 | char buf[32]; | 576 | char buf[32]; |
577 | u32 reg; | ||
578 | u8 speed; | ||
460 | 579 | ||
461 | if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) | 580 | if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) |
462 | return -EFAULT; | 581 | return -EFAULT; |
@@ -477,6 +596,21 @@ static ssize_t dwc3_link_state_write(struct file *file, | |||
477 | return -EINVAL; | 596 | return -EINVAL; |
478 | 597 | ||
479 | spin_lock_irqsave(&dwc->lock, flags); | 598 | spin_lock_irqsave(&dwc->lock, flags); |
599 | reg = dwc3_readl(dwc->regs, DWC3_GSTS); | ||
600 | if (DWC3_GSTS_CURMOD(reg) != DWC3_GSTS_CURMOD_DEVICE) { | ||
601 | spin_unlock_irqrestore(&dwc->lock, flags); | ||
602 | return -EINVAL; | ||
603 | } | ||
604 | |||
605 | reg = dwc3_readl(dwc->regs, DWC3_DSTS); | ||
606 | speed = reg & DWC3_DSTS_CONNECTSPD; | ||
607 | |||
608 | if (speed < DWC3_DSTS_SUPERSPEED && | ||
609 | state != DWC3_LINK_STATE_RECOV) { | ||
610 | spin_unlock_irqrestore(&dwc->lock, flags); | ||
611 | return -EINVAL; | ||
612 | } | ||
613 | |||
480 | dwc3_gadget_set_link_state(dwc, state); | 614 | dwc3_gadget_set_link_state(dwc, state); |
481 | spin_unlock_irqrestore(&dwc->lock, flags); | 615 | spin_unlock_irqrestore(&dwc->lock, flags); |
482 | 616 | ||
@@ -496,7 +630,7 @@ struct dwc3_ep_file_map { | |||
496 | const struct file_operations *const fops; | 630 | const struct file_operations *const fops; |
497 | }; | 631 | }; |
498 | 632 | ||
499 | static int dwc3_tx_fifo_queue_show(struct seq_file *s, void *unused) | 633 | static int dwc3_tx_fifo_size_show(struct seq_file *s, void *unused) |
500 | { | 634 | { |
501 | struct dwc3_ep *dep = s->private; | 635 | struct dwc3_ep *dep = s->private; |
502 | struct dwc3 *dwc = dep->dwc; | 636 | struct dwc3 *dwc = dep->dwc; |
@@ -504,14 +638,18 @@ static int dwc3_tx_fifo_queue_show(struct seq_file *s, void *unused) | |||
504 | u32 val; | 638 | u32 val; |
505 | 639 | ||
506 | spin_lock_irqsave(&dwc->lock, flags); | 640 | spin_lock_irqsave(&dwc->lock, flags); |
507 | val = dwc3_core_fifo_space(dep, DWC3_TXFIFOQ); | 641 | val = dwc3_core_fifo_space(dep, DWC3_TXFIFO); |
642 | |||
643 | /* Convert to bytes */ | ||
644 | val *= DWC3_MDWIDTH(dwc->hwparams.hwparams0); | ||
645 | val >>= 3; | ||
508 | seq_printf(s, "%u\n", val); | 646 | seq_printf(s, "%u\n", val); |
509 | spin_unlock_irqrestore(&dwc->lock, flags); | 647 | spin_unlock_irqrestore(&dwc->lock, flags); |
510 | 648 | ||
511 | return 0; | 649 | return 0; |
512 | } | 650 | } |
513 | 651 | ||
514 | static int dwc3_rx_fifo_queue_show(struct seq_file *s, void *unused) | 652 | static int dwc3_rx_fifo_size_show(struct seq_file *s, void *unused) |
515 | { | 653 | { |
516 | struct dwc3_ep *dep = s->private; | 654 | struct dwc3_ep *dep = s->private; |
517 | struct dwc3 *dwc = dep->dwc; | 655 | struct dwc3 *dwc = dep->dwc; |
@@ -519,7 +657,11 @@ static int dwc3_rx_fifo_queue_show(struct seq_file *s, void *unused) | |||
519 | u32 val; | 657 | u32 val; |
520 | 658 | ||
521 | spin_lock_irqsave(&dwc->lock, flags); | 659 | spin_lock_irqsave(&dwc->lock, flags); |
522 | val = dwc3_core_fifo_space(dep, DWC3_RXFIFOQ); | 660 | val = dwc3_core_fifo_space(dep, DWC3_RXFIFO); |
661 | |||
662 | /* Convert to bytes */ | ||
663 | val *= DWC3_MDWIDTH(dwc->hwparams.hwparams0); | ||
664 | val >>= 3; | ||
523 | seq_printf(s, "%u\n", val); | 665 | seq_printf(s, "%u\n", val); |
524 | spin_unlock_irqrestore(&dwc->lock, flags); | 666 | spin_unlock_irqrestore(&dwc->lock, flags); |
525 | 667 | ||
@@ -675,8 +817,32 @@ out: | |||
675 | return 0; | 817 | return 0; |
676 | } | 818 | } |
677 | 819 | ||
678 | DEFINE_SHOW_ATTRIBUTE(dwc3_tx_fifo_queue); | 820 | static int dwc3_ep_info_register_show(struct seq_file *s, void *unused) |
679 | DEFINE_SHOW_ATTRIBUTE(dwc3_rx_fifo_queue); | 821 | { |
822 | struct dwc3_ep *dep = s->private; | ||
823 | struct dwc3 *dwc = dep->dwc; | ||
824 | unsigned long flags; | ||
825 | u64 ep_info; | ||
826 | u32 lower_32_bits; | ||
827 | u32 upper_32_bits; | ||
828 | u32 reg; | ||
829 | |||
830 | spin_lock_irqsave(&dwc->lock, flags); | ||
831 | reg = DWC3_GDBGLSPMUX_EPSELECT(dep->number); | ||
832 | dwc3_writel(dwc->regs, DWC3_GDBGLSPMUX, reg); | ||
833 | |||
834 | lower_32_bits = dwc3_readl(dwc->regs, DWC3_GDBGEPINFO0); | ||
835 | upper_32_bits = dwc3_readl(dwc->regs, DWC3_GDBGEPINFO1); | ||
836 | |||
837 | ep_info = ((u64)upper_32_bits << 32) | lower_32_bits; | ||
838 | seq_printf(s, "0x%016llx\n", ep_info); | ||
839 | spin_unlock_irqrestore(&dwc->lock, flags); | ||
840 | |||
841 | return 0; | ||
842 | } | ||
843 | |||
844 | DEFINE_SHOW_ATTRIBUTE(dwc3_tx_fifo_size); | ||
845 | DEFINE_SHOW_ATTRIBUTE(dwc3_rx_fifo_size); | ||
680 | DEFINE_SHOW_ATTRIBUTE(dwc3_tx_request_queue); | 846 | DEFINE_SHOW_ATTRIBUTE(dwc3_tx_request_queue); |
681 | DEFINE_SHOW_ATTRIBUTE(dwc3_rx_request_queue); | 847 | DEFINE_SHOW_ATTRIBUTE(dwc3_rx_request_queue); |
682 | DEFINE_SHOW_ATTRIBUTE(dwc3_rx_info_queue); | 848 | DEFINE_SHOW_ATTRIBUTE(dwc3_rx_info_queue); |
@@ -684,10 +850,11 @@ DEFINE_SHOW_ATTRIBUTE(dwc3_descriptor_fetch_queue); | |||
684 | DEFINE_SHOW_ATTRIBUTE(dwc3_event_queue); | 850 | DEFINE_SHOW_ATTRIBUTE(dwc3_event_queue); |
685 | DEFINE_SHOW_ATTRIBUTE(dwc3_transfer_type); | 851 | DEFINE_SHOW_ATTRIBUTE(dwc3_transfer_type); |
686 | DEFINE_SHOW_ATTRIBUTE(dwc3_trb_ring); | 852 | DEFINE_SHOW_ATTRIBUTE(dwc3_trb_ring); |
853 | DEFINE_SHOW_ATTRIBUTE(dwc3_ep_info_register); | ||
687 | 854 | ||
688 | static const struct dwc3_ep_file_map dwc3_ep_file_map[] = { | 855 | static const struct dwc3_ep_file_map dwc3_ep_file_map[] = { |
689 | { "tx_fifo_queue", &dwc3_tx_fifo_queue_fops, }, | 856 | { "tx_fifo_size", &dwc3_tx_fifo_size_fops, }, |
690 | { "rx_fifo_queue", &dwc3_rx_fifo_queue_fops, }, | 857 | { "rx_fifo_size", &dwc3_rx_fifo_size_fops, }, |
691 | { "tx_request_queue", &dwc3_tx_request_queue_fops, }, | 858 | { "tx_request_queue", &dwc3_tx_request_queue_fops, }, |
692 | { "rx_request_queue", &dwc3_rx_request_queue_fops, }, | 859 | { "rx_request_queue", &dwc3_rx_request_queue_fops, }, |
693 | { "rx_info_queue", &dwc3_rx_info_queue_fops, }, | 860 | { "rx_info_queue", &dwc3_rx_info_queue_fops, }, |
@@ -695,6 +862,7 @@ static const struct dwc3_ep_file_map dwc3_ep_file_map[] = { | |||
695 | { "event_queue", &dwc3_event_queue_fops, }, | 862 | { "event_queue", &dwc3_event_queue_fops, }, |
696 | { "transfer_type", &dwc3_transfer_type_fops, }, | 863 | { "transfer_type", &dwc3_transfer_type_fops, }, |
697 | { "trb_ring", &dwc3_trb_ring_fops, }, | 864 | { "trb_ring", &dwc3_trb_ring_fops, }, |
865 | { "GDBGEPINFO", &dwc3_ep_info_register_fops, }, | ||
698 | }; | 866 | }; |
699 | 867 | ||
700 | static void dwc3_debugfs_create_endpoint_files(struct dwc3_ep *dep, | 868 | static void dwc3_debugfs_create_endpoint_files(struct dwc3_ep *dep, |
@@ -742,6 +910,8 @@ void dwc3_debugfs_init(struct dwc3 *dwc) | |||
742 | if (!dwc->regset) | 910 | if (!dwc->regset) |
743 | return; | 911 | return; |
744 | 912 | ||
913 | dwc->dbg_lsp_select = DWC3_LSP_MUX_UNSELECTED; | ||
914 | |||
745 | dwc->regset->regs = dwc3_regs; | 915 | dwc->regset->regs = dwc3_regs; |
746 | dwc->regset->nregs = ARRAY_SIZE(dwc3_regs); | 916 | dwc->regset->nregs = ARRAY_SIZE(dwc3_regs); |
747 | dwc->regset->base = dwc->regs - DWC3_GLOBALS_REGS_START; | 917 | dwc->regset->base = dwc->regs - DWC3_GLOBALS_REGS_START; |
@@ -751,6 +921,9 @@ void dwc3_debugfs_init(struct dwc3 *dwc) | |||
751 | 921 | ||
752 | debugfs_create_regset32("regdump", S_IRUGO, root, dwc->regset); | 922 | debugfs_create_regset32("regdump", S_IRUGO, root, dwc->regset); |
753 | 923 | ||
924 | debugfs_create_file("lsp_dump", S_IRUGO | S_IWUSR, root, dwc, | ||
925 | &dwc3_lsp_fops); | ||
926 | |||
754 | if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)) { | 927 | if (IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)) { |
755 | debugfs_create_file("mode", S_IRUGO | S_IWUSR, root, dwc, | 928 | debugfs_create_file("mode", S_IRUGO | S_IWUSR, root, dwc, |
756 | &dwc3_mode_fops); | 929 | &dwc3_mode_fops); |
diff --git a/drivers/usb/dwc3/drd.c b/drivers/usb/dwc3/drd.c index 218371f985ca..869725d15c74 100644 --- a/drivers/usb/dwc3/drd.c +++ b/drivers/usb/dwc3/drd.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/extcon.h> | 10 | #include <linux/extcon.h> |
11 | #include <linux/of_graph.h> | 11 | #include <linux/of_graph.h> |
12 | #include <linux/platform_device.h> | 12 | #include <linux/platform_device.h> |
13 | #include <linux/property.h> | ||
13 | 14 | ||
14 | #include "debug.h" | 15 | #include "debug.h" |
15 | #include "core.h" | 16 | #include "core.h" |
@@ -445,9 +446,19 @@ static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc) | |||
445 | struct device *dev = dwc->dev; | 446 | struct device *dev = dwc->dev; |
446 | struct device_node *np_phy, *np_conn; | 447 | struct device_node *np_phy, *np_conn; |
447 | struct extcon_dev *edev; | 448 | struct extcon_dev *edev; |
449 | const char *name; | ||
448 | 450 | ||
449 | if (of_property_read_bool(dev->of_node, "extcon")) | 451 | if (device_property_read_bool(dev, "extcon")) |
450 | return extcon_get_edev_by_phandle(dwc->dev, 0); | 452 | return extcon_get_edev_by_phandle(dev, 0); |
453 | |||
454 | /* | ||
455 | * Device tree platforms should get extcon via phandle. | ||
456 | * On ACPI platforms, we get the name from a device property. | ||
457 | * This device property is for kernel internal use only and | ||
458 | * is expected to be set by the glue code. | ||
459 | */ | ||
460 | if (device_property_read_string(dev, "linux,extcon-name", &name) == 0) | ||
461 | return extcon_get_extcon_dev(name); | ||
451 | 462 | ||
452 | np_phy = of_parse_phandle(dev->of_node, "phys", 0); | 463 | np_phy = of_parse_phandle(dev->of_node, "phys", 0); |
453 | np_conn = of_graph_get_remote_node(np_phy, -1, -1); | 464 | np_conn = of_graph_get_remote_node(np_phy, -1, -1); |
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index 842795856bf4..fdc6e4e403e8 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c | |||
@@ -170,20 +170,20 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc) | |||
170 | * put the gpio descriptors again here because the phy driver | 170 | * put the gpio descriptors again here because the phy driver |
171 | * might want to grab them, too. | 171 | * might want to grab them, too. |
172 | */ | 172 | */ |
173 | gpio = devm_gpiod_get_optional(&pdev->dev, "cs", | 173 | gpio = gpiod_get_optional(&pdev->dev, "cs", GPIOD_OUT_LOW); |
174 | GPIOD_OUT_LOW); | ||
175 | if (IS_ERR(gpio)) | 174 | if (IS_ERR(gpio)) |
176 | return PTR_ERR(gpio); | 175 | return PTR_ERR(gpio); |
177 | 176 | ||
178 | gpiod_set_value_cansleep(gpio, 1); | 177 | gpiod_set_value_cansleep(gpio, 1); |
178 | gpiod_put(gpio); | ||
179 | 179 | ||
180 | gpio = devm_gpiod_get_optional(&pdev->dev, "reset", | 180 | gpio = gpiod_get_optional(&pdev->dev, "reset", GPIOD_OUT_LOW); |
181 | GPIOD_OUT_LOW); | ||
182 | if (IS_ERR(gpio)) | 181 | if (IS_ERR(gpio)) |
183 | return PTR_ERR(gpio); | 182 | return PTR_ERR(gpio); |
184 | 183 | ||
185 | if (gpio) { | 184 | if (gpio) { |
186 | gpiod_set_value_cansleep(gpio, 1); | 185 | gpiod_set_value_cansleep(gpio, 1); |
186 | gpiod_put(gpio); | ||
187 | usleep_range(10000, 11000); | 187 | usleep_range(10000, 11000); |
188 | } | 188 | } |
189 | } | 189 | } |
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 9f92ee03dde7..07bd31bb2f8a 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include "gadget.h" | 27 | #include "gadget.h" |
28 | #include "io.h" | 28 | #include "io.h" |
29 | 29 | ||
30 | #define DWC3_ALIGN_FRAME(d) (((d)->frame_number + (d)->interval) \ | 30 | #define DWC3_ALIGN_FRAME(d, n) (((d)->frame_number + ((d)->interval * (n))) \ |
31 | & ~((d)->interval - 1)) | 31 | & ~((d)->interval - 1)) |
32 | 32 | ||
33 | /** | 33 | /** |
@@ -647,8 +647,6 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action) | |||
647 | reg |= DWC3_DALEPENA_EP(dep->number); | 647 | reg |= DWC3_DALEPENA_EP(dep->number); |
648 | dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); | 648 | dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); |
649 | 649 | ||
650 | init_waitqueue_head(&dep->wait_end_transfer); | ||
651 | |||
652 | if (usb_endpoint_xfer_control(desc)) | 650 | if (usb_endpoint_xfer_control(desc)) |
653 | goto out; | 651 | goto out; |
654 | 652 | ||
@@ -672,7 +670,7 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action) | |||
672 | * Issue StartTransfer here with no-op TRB so we can always rely on No | 670 | * Issue StartTransfer here with no-op TRB so we can always rely on No |
673 | * Response Update Transfer command. | 671 | * Response Update Transfer command. |
674 | */ | 672 | */ |
675 | if (usb_endpoint_xfer_bulk(desc) || | 673 | if ((usb_endpoint_xfer_bulk(desc) && !dep->stream_capable) || |
676 | usb_endpoint_xfer_int(desc)) { | 674 | usb_endpoint_xfer_int(desc)) { |
677 | struct dwc3_gadget_ep_cmd_params params; | 675 | struct dwc3_gadget_ep_cmd_params params; |
678 | struct dwc3_trb *trb; | 676 | struct dwc3_trb *trb; |
@@ -919,8 +917,6 @@ static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb, | |||
919 | struct usb_gadget *gadget = &dwc->gadget; | 917 | struct usb_gadget *gadget = &dwc->gadget; |
920 | enum usb_device_speed speed = gadget->speed; | 918 | enum usb_device_speed speed = gadget->speed; |
921 | 919 | ||
922 | dwc3_ep_inc_enq(dep); | ||
923 | |||
924 | trb->size = DWC3_TRB_SIZE_LENGTH(length); | 920 | trb->size = DWC3_TRB_SIZE_LENGTH(length); |
925 | trb->bpl = lower_32_bits(dma); | 921 | trb->bpl = lower_32_bits(dma); |
926 | trb->bph = upper_32_bits(dma); | 922 | trb->bph = upper_32_bits(dma); |
@@ -990,16 +986,20 @@ static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb, | |||
990 | usb_endpoint_type(dep->endpoint.desc)); | 986 | usb_endpoint_type(dep->endpoint.desc)); |
991 | } | 987 | } |
992 | 988 | ||
993 | /* always enable Continue on Short Packet */ | 989 | /* |
990 | * Enable Continue on Short Packet | ||
991 | * when endpoint is not a stream capable | ||
992 | */ | ||
994 | if (usb_endpoint_dir_out(dep->endpoint.desc)) { | 993 | if (usb_endpoint_dir_out(dep->endpoint.desc)) { |
995 | trb->ctrl |= DWC3_TRB_CTRL_CSP; | 994 | if (!dep->stream_capable) |
995 | trb->ctrl |= DWC3_TRB_CTRL_CSP; | ||
996 | 996 | ||
997 | if (short_not_ok) | 997 | if (short_not_ok) |
998 | trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI; | 998 | trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI; |
999 | } | 999 | } |
1000 | 1000 | ||
1001 | if ((!no_interrupt && !chain) || | 1001 | if ((!no_interrupt && !chain) || |
1002 | (dwc3_calc_trbs_left(dep) == 0)) | 1002 | (dwc3_calc_trbs_left(dep) == 1)) |
1003 | trb->ctrl |= DWC3_TRB_CTRL_IOC; | 1003 | trb->ctrl |= DWC3_TRB_CTRL_IOC; |
1004 | 1004 | ||
1005 | if (chain) | 1005 | if (chain) |
@@ -1010,6 +1010,8 @@ static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb, | |||
1010 | 1010 | ||
1011 | trb->ctrl |= DWC3_TRB_CTRL_HWO; | 1011 | trb->ctrl |= DWC3_TRB_CTRL_HWO; |
1012 | 1012 | ||
1013 | dwc3_ep_inc_enq(dep); | ||
1014 | |||
1013 | trace_dwc3_prepare_trb(dep, trb); | 1015 | trace_dwc3_prepare_trb(dep, trb); |
1014 | } | 1016 | } |
1015 | 1017 | ||
@@ -1046,6 +1048,8 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, | |||
1046 | req->trb_dma = dwc3_trb_dma_offset(dep, trb); | 1048 | req->trb_dma = dwc3_trb_dma_offset(dep, trb); |
1047 | } | 1049 | } |
1048 | 1050 | ||
1051 | req->num_trbs++; | ||
1052 | |||
1049 | __dwc3_prepare_one_trb(dep, trb, dma, length, chain, node, | 1053 | __dwc3_prepare_one_trb(dep, trb, dma, length, chain, node, |
1050 | stream_id, short_not_ok, no_interrupt); | 1054 | stream_id, short_not_ok, no_interrupt); |
1051 | } | 1055 | } |
@@ -1073,13 +1077,14 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, | |||
1073 | struct dwc3 *dwc = dep->dwc; | 1077 | struct dwc3 *dwc = dep->dwc; |
1074 | struct dwc3_trb *trb; | 1078 | struct dwc3_trb *trb; |
1075 | 1079 | ||
1076 | req->unaligned = true; | 1080 | req->needs_extra_trb = true; |
1077 | 1081 | ||
1078 | /* prepare normal TRB */ | 1082 | /* prepare normal TRB */ |
1079 | dwc3_prepare_one_trb(dep, req, true, i); | 1083 | dwc3_prepare_one_trb(dep, req, true, i); |
1080 | 1084 | ||
1081 | /* Now prepare one extra TRB to align transfer size */ | 1085 | /* Now prepare one extra TRB to align transfer size */ |
1082 | trb = &dep->trb_pool[dep->trb_enqueue]; | 1086 | trb = &dep->trb_pool[dep->trb_enqueue]; |
1087 | req->num_trbs++; | ||
1083 | __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, | 1088 | __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, |
1084 | maxp - rem, false, 1, | 1089 | maxp - rem, false, 1, |
1085 | req->request.stream_id, | 1090 | req->request.stream_id, |
@@ -1117,13 +1122,14 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep, | |||
1117 | struct dwc3 *dwc = dep->dwc; | 1122 | struct dwc3 *dwc = dep->dwc; |
1118 | struct dwc3_trb *trb; | 1123 | struct dwc3_trb *trb; |
1119 | 1124 | ||
1120 | req->unaligned = true; | 1125 | req->needs_extra_trb = true; |
1121 | 1126 | ||
1122 | /* prepare normal TRB */ | 1127 | /* prepare normal TRB */ |
1123 | dwc3_prepare_one_trb(dep, req, true, 0); | 1128 | dwc3_prepare_one_trb(dep, req, true, 0); |
1124 | 1129 | ||
1125 | /* Now prepare one extra TRB to align transfer size */ | 1130 | /* Now prepare one extra TRB to align transfer size */ |
1126 | trb = &dep->trb_pool[dep->trb_enqueue]; | 1131 | trb = &dep->trb_pool[dep->trb_enqueue]; |
1132 | req->num_trbs++; | ||
1127 | __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, maxp - rem, | 1133 | __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, maxp - rem, |
1128 | false, 1, req->request.stream_id, | 1134 | false, 1, req->request.stream_id, |
1129 | req->request.short_not_ok, | 1135 | req->request.short_not_ok, |
@@ -1133,13 +1139,14 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep, | |||
1133 | struct dwc3 *dwc = dep->dwc; | 1139 | struct dwc3 *dwc = dep->dwc; |
1134 | struct dwc3_trb *trb; | 1140 | struct dwc3_trb *trb; |
1135 | 1141 | ||
1136 | req->zero = true; | 1142 | req->needs_extra_trb = true; |
1137 | 1143 | ||
1138 | /* prepare normal TRB */ | 1144 | /* prepare normal TRB */ |
1139 | dwc3_prepare_one_trb(dep, req, true, 0); | 1145 | dwc3_prepare_one_trb(dep, req, true, 0); |
1140 | 1146 | ||
1141 | /* Now prepare one extra TRB to handle ZLP */ | 1147 | /* Now prepare one extra TRB to handle ZLP */ |
1142 | trb = &dep->trb_pool[dep->trb_enqueue]; | 1148 | trb = &dep->trb_pool[dep->trb_enqueue]; |
1149 | req->num_trbs++; | ||
1143 | __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, 0, | 1150 | __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, 0, |
1144 | false, 1, req->request.stream_id, | 1151 | false, 1, req->request.stream_id, |
1145 | req->request.short_not_ok, | 1152 | req->request.short_not_ok, |
@@ -1232,6 +1239,9 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep) | |||
1232 | params.param1 = lower_32_bits(req->trb_dma); | 1239 | params.param1 = lower_32_bits(req->trb_dma); |
1233 | cmd = DWC3_DEPCMD_STARTTRANSFER; | 1240 | cmd = DWC3_DEPCMD_STARTTRANSFER; |
1234 | 1241 | ||
1242 | if (dep->stream_capable) | ||
1243 | cmd |= DWC3_DEPCMD_PARAM(req->request.stream_id); | ||
1244 | |||
1235 | if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) | 1245 | if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) |
1236 | cmd |= DWC3_DEPCMD_PARAM(dep->frame_number); | 1246 | cmd |= DWC3_DEPCMD_PARAM(dep->frame_number); |
1237 | } else { | 1247 | } else { |
@@ -1263,17 +1273,151 @@ static int __dwc3_gadget_get_frame(struct dwc3 *dwc) | |||
1263 | return DWC3_DSTS_SOFFN(reg); | 1273 | return DWC3_DSTS_SOFFN(reg); |
1264 | } | 1274 | } |
1265 | 1275 | ||
1266 | static void __dwc3_gadget_start_isoc(struct dwc3_ep *dep) | 1276 | /** |
1277 | * dwc3_gadget_start_isoc_quirk - workaround invalid frame number | ||
1278 | * @dep: isoc endpoint | ||
1279 | * | ||
1280 | * This function tests for the correct combination of BIT[15:14] from the 16-bit | ||
1281 | * microframe number reported by the XferNotReady event for the future frame | ||
1282 | * number to start the isoc transfer. | ||
1283 | * | ||
1284 | * In DWC_usb31 version 1.70a-ea06 and prior, for highspeed and fullspeed | ||
1285 | * isochronous IN, BIT[15:14] of the 16-bit microframe number reported by the | ||
1286 | * XferNotReady event are invalid. The driver uses this number to schedule the | ||
1287 | * isochronous transfer and passes it to the START TRANSFER command. Because | ||
1288 | * this number is invalid, the command may fail. If BIT[15:14] matches the | ||
1289 | * internal 16-bit microframe, the START TRANSFER command will pass and the | ||
1290 | * transfer will start at the scheduled time, if it is off by 1, the command | ||
1291 | * will still pass, but the transfer will start 2 seconds in the future. For all | ||
1292 | * other conditions, the START TRANSFER command will fail with bus-expiry. | ||
1293 | * | ||
1294 | * In order to workaround this issue, we can test for the correct combination of | ||
1295 | * BIT[15:14] by sending START TRANSFER commands with different values of | ||
1296 | * BIT[15:14]: 'b00, 'b01, 'b10, and 'b11. Each combination is 2^14 uframe apart | ||
1297 | * (or 2 seconds). 4 seconds into the future will result in a bus-expiry status. | ||
1298 | * As the result, within the 4 possible combinations for BIT[15:14], there will | ||
1299 | * be 2 successful and 2 failure START COMMAND status. One of the 2 successful | ||
1300 | * command status will result in a 2-second delay start. The smaller BIT[15:14] | ||
1301 | * value is the correct combination. | ||
1302 | * | ||
1303 | * Since there are only 4 outcomes and the results are ordered, we can simply | ||
1304 | * test 2 START TRANSFER commands with BIT[15:14] combinations 'b00 and 'b01 to | ||
1305 | * deduce the smaller successful combination. | ||
1306 | * | ||
1307 | * Let test0 = test status for combination 'b00 and test1 = test status for 'b01 | ||
1308 | * of BIT[15:14]. The correct combination is as follow: | ||
1309 | * | ||
1310 | * if test0 fails and test1 passes, BIT[15:14] is 'b01 | ||
1311 | * if test0 fails and test1 fails, BIT[15:14] is 'b10 | ||
1312 | * if test0 passes and test1 fails, BIT[15:14] is 'b11 | ||
1313 | * if test0 passes and test1 passes, BIT[15:14] is 'b00 | ||
1314 | * | ||
1315 | * Synopsys STAR 9001202023: Wrong microframe number for isochronous IN | ||
1316 | * endpoints. | ||
1317 | */ | ||
1318 | static int dwc3_gadget_start_isoc_quirk(struct dwc3_ep *dep) | ||
1319 | { | ||
1320 | int cmd_status = 0; | ||
1321 | bool test0; | ||
1322 | bool test1; | ||
1323 | |||
1324 | while (dep->combo_num < 2) { | ||
1325 | struct dwc3_gadget_ep_cmd_params params; | ||
1326 | u32 test_frame_number; | ||
1327 | u32 cmd; | ||
1328 | |||
1329 | /* | ||
1330 | * Check if we can start isoc transfer on the next interval or | ||
1331 | * 4 uframes in the future with BIT[15:14] as dep->combo_num | ||
1332 | */ | ||
1333 | test_frame_number = dep->frame_number & 0x3fff; | ||
1334 | test_frame_number |= dep->combo_num << 14; | ||
1335 | test_frame_number += max_t(u32, 4, dep->interval); | ||
1336 | |||
1337 | params.param0 = upper_32_bits(dep->dwc->bounce_addr); | ||
1338 | params.param1 = lower_32_bits(dep->dwc->bounce_addr); | ||
1339 | |||
1340 | cmd = DWC3_DEPCMD_STARTTRANSFER; | ||
1341 | cmd |= DWC3_DEPCMD_PARAM(test_frame_number); | ||
1342 | cmd_status = dwc3_send_gadget_ep_cmd(dep, cmd, ¶ms); | ||
1343 | |||
1344 | /* Redo if some other failure beside bus-expiry is received */ | ||
1345 | if (cmd_status && cmd_status != -EAGAIN) { | ||
1346 | dep->start_cmd_status = 0; | ||
1347 | dep->combo_num = 0; | ||
1348 | return 0; | ||
1349 | } | ||
1350 | |||
1351 | /* Store the first test status */ | ||
1352 | if (dep->combo_num == 0) | ||
1353 | dep->start_cmd_status = cmd_status; | ||
1354 | |||
1355 | dep->combo_num++; | ||
1356 | |||
1357 | /* | ||
1358 | * End the transfer if the START_TRANSFER command is successful | ||
1359 | * to wait for the next XferNotReady to test the command again | ||
1360 | */ | ||
1361 | if (cmd_status == 0) { | ||
1362 | dwc3_stop_active_transfer(dep, true); | ||
1363 | return 0; | ||
1364 | } | ||
1365 | } | ||
1366 | |||
1367 | /* test0 and test1 are both completed at this point */ | ||
1368 | test0 = (dep->start_cmd_status == 0); | ||
1369 | test1 = (cmd_status == 0); | ||
1370 | |||
1371 | if (!test0 && test1) | ||
1372 | dep->combo_num = 1; | ||
1373 | else if (!test0 && !test1) | ||
1374 | dep->combo_num = 2; | ||
1375 | else if (test0 && !test1) | ||
1376 | dep->combo_num = 3; | ||
1377 | else if (test0 && test1) | ||
1378 | dep->combo_num = 0; | ||
1379 | |||
1380 | dep->frame_number &= 0x3fff; | ||
1381 | dep->frame_number |= dep->combo_num << 14; | ||
1382 | dep->frame_number += max_t(u32, 4, dep->interval); | ||
1383 | |||
1384 | /* Reinitialize test variables */ | ||
1385 | dep->start_cmd_status = 0; | ||
1386 | dep->combo_num = 0; | ||
1387 | |||
1388 | return __dwc3_gadget_kick_transfer(dep); | ||
1389 | } | ||
1390 | |||
1391 | static int __dwc3_gadget_start_isoc(struct dwc3_ep *dep) | ||
1267 | { | 1392 | { |
1393 | struct dwc3 *dwc = dep->dwc; | ||
1394 | int ret; | ||
1395 | int i; | ||
1396 | |||
1268 | if (list_empty(&dep->pending_list)) { | 1397 | if (list_empty(&dep->pending_list)) { |
1269 | dev_info(dep->dwc->dev, "%s: ran out of requests\n", | ||
1270 | dep->name); | ||
1271 | dep->flags |= DWC3_EP_PENDING_REQUEST; | 1398 | dep->flags |= DWC3_EP_PENDING_REQUEST; |
1272 | return; | 1399 | return -EAGAIN; |
1400 | } | ||
1401 | |||
1402 | if (!dwc->dis_start_transfer_quirk && dwc3_is_usb31(dwc) && | ||
1403 | (dwc->revision <= DWC3_USB31_REVISION_160A || | ||
1404 | (dwc->revision == DWC3_USB31_REVISION_170A && | ||
1405 | dwc->version_type >= DWC31_VERSIONTYPE_EA01 && | ||
1406 | dwc->version_type <= DWC31_VERSIONTYPE_EA06))) { | ||
1407 | |||
1408 | if (dwc->gadget.speed <= USB_SPEED_HIGH && dep->direction) | ||
1409 | return dwc3_gadget_start_isoc_quirk(dep); | ||
1273 | } | 1410 | } |
1274 | 1411 | ||
1275 | dep->frame_number = DWC3_ALIGN_FRAME(dep); | 1412 | for (i = 0; i < DWC3_ISOC_MAX_RETRIES; i++) { |
1276 | __dwc3_gadget_kick_transfer(dep); | 1413 | dep->frame_number = DWC3_ALIGN_FRAME(dep, i + 1); |
1414 | |||
1415 | ret = __dwc3_gadget_kick_transfer(dep); | ||
1416 | if (ret != -EAGAIN) | ||
1417 | break; | ||
1418 | } | ||
1419 | |||
1420 | return ret; | ||
1277 | } | 1421 | } |
1278 | 1422 | ||
1279 | static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) | 1423 | static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) |
@@ -1314,8 +1458,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) | |||
1314 | 1458 | ||
1315 | if ((dep->flags & DWC3_EP_PENDING_REQUEST)) { | 1459 | if ((dep->flags & DWC3_EP_PENDING_REQUEST)) { |
1316 | if (!(dep->flags & DWC3_EP_TRANSFER_STARTED)) { | 1460 | if (!(dep->flags & DWC3_EP_TRANSFER_STARTED)) { |
1317 | __dwc3_gadget_start_isoc(dep); | 1461 | return __dwc3_gadget_start_isoc(dep); |
1318 | return 0; | ||
1319 | } | 1462 | } |
1320 | } | 1463 | } |
1321 | } | 1464 | } |
@@ -1341,6 +1484,40 @@ static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request, | |||
1341 | return ret; | 1484 | return ret; |
1342 | } | 1485 | } |
1343 | 1486 | ||
1487 | static void dwc3_gadget_ep_skip_trbs(struct dwc3_ep *dep, struct dwc3_request *req) | ||
1488 | { | ||
1489 | int i; | ||
1490 | |||
1491 | /* | ||
1492 | * If request was already started, this means we had to | ||
1493 | * stop the transfer. With that we also need to ignore | ||
1494 | * all TRBs used by the request, however TRBs can only | ||
1495 | * be modified after completion of END_TRANSFER | ||
1496 | * command. So what we do here is that we wait for | ||
1497 | * END_TRANSFER completion and only after that, we jump | ||
1498 | * over TRBs by clearing HWO and incrementing dequeue | ||
1499 | * pointer. | ||
1500 | */ | ||
1501 | for (i = 0; i < req->num_trbs; i++) { | ||
1502 | struct dwc3_trb *trb; | ||
1503 | |||
1504 | trb = req->trb + i; | ||
1505 | trb->ctrl &= ~DWC3_TRB_CTRL_HWO; | ||
1506 | dwc3_ep_inc_deq(dep); | ||
1507 | } | ||
1508 | } | ||
1509 | |||
1510 | static void dwc3_gadget_ep_cleanup_cancelled_requests(struct dwc3_ep *dep) | ||
1511 | { | ||
1512 | struct dwc3_request *req; | ||
1513 | struct dwc3_request *tmp; | ||
1514 | |||
1515 | list_for_each_entry_safe(req, tmp, &dep->cancelled_list, list) { | ||
1516 | dwc3_gadget_ep_skip_trbs(dep, req); | ||
1517 | dwc3_gadget_giveback(dep, req, -ECONNRESET); | ||
1518 | } | ||
1519 | } | ||
1520 | |||
1344 | static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, | 1521 | static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, |
1345 | struct usb_request *request) | 1522 | struct usb_request *request) |
1346 | { | 1523 | { |
@@ -1371,68 +1548,11 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, | |||
1371 | /* wait until it is processed */ | 1548 | /* wait until it is processed */ |
1372 | dwc3_stop_active_transfer(dep, true); | 1549 | dwc3_stop_active_transfer(dep, true); |
1373 | 1550 | ||
1374 | /* | ||
1375 | * If request was already started, this means we had to | ||
1376 | * stop the transfer. With that we also need to ignore | ||
1377 | * all TRBs used by the request, however TRBs can only | ||
1378 | * be modified after completion of END_TRANSFER | ||
1379 | * command. So what we do here is that we wait for | ||
1380 | * END_TRANSFER completion and only after that, we jump | ||
1381 | * over TRBs by clearing HWO and incrementing dequeue | ||
1382 | * pointer. | ||
1383 | * | ||
1384 | * Note that we have 2 possible types of transfers here: | ||
1385 | * | ||
1386 | * i) Linear buffer request | ||
1387 | * ii) SG-list based request | ||
1388 | * | ||
1389 | * SG-list based requests will have r->num_pending_sgs | ||
1390 | * set to a valid number (> 0). Linear requests, | ||
1391 | * normally use a single TRB. | ||
1392 | * | ||
1393 | * For each of these two cases, if r->unaligned flag is | ||
1394 | * set, one extra TRB has been used to align transfer | ||
1395 | * size to wMaxPacketSize. | ||
1396 | * | ||
1397 | * All of these cases need to be taken into | ||
1398 | * consideration so we don't mess up our TRB ring | ||
1399 | * pointers. | ||
1400 | */ | ||
1401 | wait_event_lock_irq(dep->wait_end_transfer, | ||
1402 | !(dep->flags & DWC3_EP_END_TRANSFER_PENDING), | ||
1403 | dwc->lock); | ||
1404 | |||
1405 | if (!r->trb) | 1551 | if (!r->trb) |
1406 | goto out0; | 1552 | goto out0; |
1407 | 1553 | ||
1408 | if (r->num_pending_sgs) { | 1554 | dwc3_gadget_move_cancelled_request(req); |
1409 | struct dwc3_trb *trb; | 1555 | goto out0; |
1410 | int i = 0; | ||
1411 | |||
1412 | for (i = 0; i < r->num_pending_sgs; i++) { | ||
1413 | trb = r->trb + i; | ||
1414 | trb->ctrl &= ~DWC3_TRB_CTRL_HWO; | ||
1415 | dwc3_ep_inc_deq(dep); | ||
1416 | } | ||
1417 | |||
1418 | if (r->unaligned || r->zero) { | ||
1419 | trb = r->trb + r->num_pending_sgs + 1; | ||
1420 | trb->ctrl &= ~DWC3_TRB_CTRL_HWO; | ||
1421 | dwc3_ep_inc_deq(dep); | ||
1422 | } | ||
1423 | } else { | ||
1424 | struct dwc3_trb *trb = r->trb; | ||
1425 | |||
1426 | trb->ctrl &= ~DWC3_TRB_CTRL_HWO; | ||
1427 | dwc3_ep_inc_deq(dep); | ||
1428 | |||
1429 | if (r->unaligned || r->zero) { | ||
1430 | trb = r->trb + 1; | ||
1431 | trb->ctrl &= ~DWC3_TRB_CTRL_HWO; | ||
1432 | dwc3_ep_inc_deq(dep); | ||
1433 | } | ||
1434 | } | ||
1435 | goto out1; | ||
1436 | } | 1556 | } |
1437 | dev_err(dwc->dev, "request %pK was not queued to %s\n", | 1557 | dev_err(dwc->dev, "request %pK was not queued to %s\n", |
1438 | request, ep->name); | 1558 | request, ep->name); |
@@ -1440,9 +1560,6 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep, | |||
1440 | goto out0; | 1560 | goto out0; |
1441 | } | 1561 | } |
1442 | 1562 | ||
1443 | out1: | ||
1444 | /* giveback the request */ | ||
1445 | |||
1446 | dwc3_gadget_giveback(dep, req, -ECONNRESET); | 1563 | dwc3_gadget_giveback(dep, req, -ECONNRESET); |
1447 | 1564 | ||
1448 | out0: | 1565 | out0: |
@@ -1934,8 +2051,6 @@ static int dwc3_gadget_stop(struct usb_gadget *g) | |||
1934 | { | 2051 | { |
1935 | struct dwc3 *dwc = gadget_to_dwc(g); | 2052 | struct dwc3 *dwc = gadget_to_dwc(g); |
1936 | unsigned long flags; | 2053 | unsigned long flags; |
1937 | int epnum; | ||
1938 | u32 tmo_eps = 0; | ||
1939 | 2054 | ||
1940 | spin_lock_irqsave(&dwc->lock, flags); | 2055 | spin_lock_irqsave(&dwc->lock, flags); |
1941 | 2056 | ||
@@ -1944,36 +2059,6 @@ static int dwc3_gadget_stop(struct usb_gadget *g) | |||
1944 | 2059 | ||
1945 | __dwc3_gadget_stop(dwc); | 2060 | __dwc3_gadget_stop(dwc); |
1946 | 2061 | ||
1947 | for (epnum = 2; epnum < DWC3_ENDPOINTS_NUM; epnum++) { | ||
1948 | struct dwc3_ep *dep = dwc->eps[epnum]; | ||
1949 | int ret; | ||
1950 | |||
1951 | if (!dep) | ||
1952 | continue; | ||
1953 | |||
1954 | if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING)) | ||
1955 | continue; | ||
1956 | |||
1957 | ret = wait_event_interruptible_lock_irq_timeout(dep->wait_end_transfer, | ||
1958 | !(dep->flags & DWC3_EP_END_TRANSFER_PENDING), | ||
1959 | dwc->lock, msecs_to_jiffies(5)); | ||
1960 | |||
1961 | if (ret <= 0) { | ||
1962 | /* Timed out or interrupted! There's nothing much | ||
1963 | * we can do so we just log here and print which | ||
1964 | * endpoints timed out at the end. | ||
1965 | */ | ||
1966 | tmo_eps |= 1 << epnum; | ||
1967 | dep->flags &= DWC3_EP_END_TRANSFER_PENDING; | ||
1968 | } | ||
1969 | } | ||
1970 | |||
1971 | if (tmo_eps) { | ||
1972 | dev_err(dwc->dev, | ||
1973 | "end transfer timed out on endpoints 0x%x [bitmap]\n", | ||
1974 | tmo_eps); | ||
1975 | } | ||
1976 | |||
1977 | out: | 2062 | out: |
1978 | dwc->gadget_driver = NULL; | 2063 | dwc->gadget_driver = NULL; |
1979 | spin_unlock_irqrestore(&dwc->lock, flags); | 2064 | spin_unlock_irqrestore(&dwc->lock, flags); |
@@ -2148,6 +2233,8 @@ static int dwc3_gadget_init_endpoint(struct dwc3 *dwc, u8 epnum) | |||
2148 | dep->direction = direction; | 2233 | dep->direction = direction; |
2149 | dep->regs = dwc->regs + DWC3_DEP_BASE(epnum); | 2234 | dep->regs = dwc->regs + DWC3_DEP_BASE(epnum); |
2150 | dwc->eps[epnum] = dep; | 2235 | dwc->eps[epnum] = dep; |
2236 | dep->combo_num = 0; | ||
2237 | dep->start_cmd_status = 0; | ||
2151 | 2238 | ||
2152 | snprintf(dep->name, sizeof(dep->name), "ep%u%s", num, | 2239 | snprintf(dep->name, sizeof(dep->name), "ep%u%s", num, |
2153 | direction ? "in" : "out"); | 2240 | direction ? "in" : "out"); |
@@ -2176,6 +2263,7 @@ static int dwc3_gadget_init_endpoint(struct dwc3 *dwc, u8 epnum) | |||
2176 | 2263 | ||
2177 | INIT_LIST_HEAD(&dep->pending_list); | 2264 | INIT_LIST_HEAD(&dep->pending_list); |
2178 | INIT_LIST_HEAD(&dep->started_list); | 2265 | INIT_LIST_HEAD(&dep->started_list); |
2266 | INIT_LIST_HEAD(&dep->cancelled_list); | ||
2179 | 2267 | ||
2180 | return 0; | 2268 | return 0; |
2181 | } | 2269 | } |
@@ -2235,6 +2323,7 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep, | |||
2235 | dwc3_ep_inc_deq(dep); | 2323 | dwc3_ep_inc_deq(dep); |
2236 | 2324 | ||
2237 | trace_dwc3_complete_trb(dep, trb); | 2325 | trace_dwc3_complete_trb(dep, trb); |
2326 | req->num_trbs--; | ||
2238 | 2327 | ||
2239 | /* | 2328 | /* |
2240 | * If we're in the middle of series of chained TRBs and we | 2329 | * If we're in the middle of series of chained TRBs and we |
@@ -2250,11 +2339,25 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep, | |||
2250 | trb->ctrl &= ~DWC3_TRB_CTRL_HWO; | 2339 | trb->ctrl &= ~DWC3_TRB_CTRL_HWO; |
2251 | 2340 | ||
2252 | /* | 2341 | /* |
2342 | * For isochronous transfers, the first TRB in a service interval must | ||
2343 | * have the Isoc-First type. Track and report its interval frame number. | ||
2344 | */ | ||
2345 | if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && | ||
2346 | (trb->ctrl & DWC3_TRBCTL_ISOCHRONOUS_FIRST)) { | ||
2347 | unsigned int frame_number; | ||
2348 | |||
2349 | frame_number = DWC3_TRB_CTRL_GET_SID_SOFN(trb->ctrl); | ||
2350 | frame_number &= ~(dep->interval - 1); | ||
2351 | req->request.frame_number = frame_number; | ||
2352 | } | ||
2353 | |||
2354 | /* | ||
2253 | * If we're dealing with unaligned size OUT transfer, we will be left | 2355 | * If we're dealing with unaligned size OUT transfer, we will be left |
2254 | * with one TRB pending in the ring. We need to manually clear HWO bit | 2356 | * with one TRB pending in the ring. We need to manually clear HWO bit |
2255 | * from that TRB. | 2357 | * from that TRB. |
2256 | */ | 2358 | */ |
2257 | if ((req->zero || req->unaligned) && !(trb->ctrl & DWC3_TRB_CTRL_CHN)) { | 2359 | |
2360 | if (req->needs_extra_trb && !(trb->ctrl & DWC3_TRB_CTRL_CHN)) { | ||
2258 | trb->ctrl &= ~DWC3_TRB_CTRL_HWO; | 2361 | trb->ctrl &= ~DWC3_TRB_CTRL_HWO; |
2259 | return 1; | 2362 | return 1; |
2260 | } | 2363 | } |
@@ -2331,11 +2434,10 @@ static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep, | |||
2331 | ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event, | 2434 | ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event, |
2332 | status); | 2435 | status); |
2333 | 2436 | ||
2334 | if (req->unaligned || req->zero) { | 2437 | if (req->needs_extra_trb) { |
2335 | ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event, | 2438 | ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event, |
2336 | status); | 2439 | status); |
2337 | req->unaligned = false; | 2440 | req->needs_extra_trb = false; |
2338 | req->zero = false; | ||
2339 | } | 2441 | } |
2340 | 2442 | ||
2341 | req->request.actual = req->request.length - req->remaining; | 2443 | req->request.actual = req->request.length - req->remaining; |
@@ -2430,7 +2532,7 @@ static void dwc3_gadget_endpoint_transfer_not_ready(struct dwc3_ep *dep, | |||
2430 | const struct dwc3_event_depevt *event) | 2532 | const struct dwc3_event_depevt *event) |
2431 | { | 2533 | { |
2432 | dwc3_gadget_endpoint_frame_from_event(dep, event); | 2534 | dwc3_gadget_endpoint_frame_from_event(dep, event); |
2433 | __dwc3_gadget_start_isoc(dep); | 2535 | (void) __dwc3_gadget_start_isoc(dep); |
2434 | } | 2536 | } |
2435 | 2537 | ||
2436 | static void dwc3_endpoint_interrupt(struct dwc3 *dwc, | 2538 | static void dwc3_endpoint_interrupt(struct dwc3 *dwc, |
@@ -2468,7 +2570,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, | |||
2468 | 2570 | ||
2469 | if (cmd == DWC3_DEPCMD_ENDTRANSFER) { | 2571 | if (cmd == DWC3_DEPCMD_ENDTRANSFER) { |
2470 | dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING; | 2572 | dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING; |
2471 | wake_up(&dep->wait_end_transfer); | 2573 | dwc3_gadget_ep_cleanup_cancelled_requests(dep); |
2472 | } | 2574 | } |
2473 | break; | 2575 | break; |
2474 | case DWC3_DEPEVT_STREAMEVT: | 2576 | case DWC3_DEPEVT_STREAMEVT: |
diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h index 2aacd1afd9ff..023a473648eb 100644 --- a/drivers/usb/dwc3/gadget.h +++ b/drivers/usb/dwc3/gadget.h | |||
@@ -79,6 +79,21 @@ static inline void dwc3_gadget_move_started_request(struct dwc3_request *req) | |||
79 | list_move_tail(&req->list, &dep->started_list); | 79 | list_move_tail(&req->list, &dep->started_list); |
80 | } | 80 | } |
81 | 81 | ||
82 | /** | ||
83 | * dwc3_gadget_move_cancelled_request - move @req to the cancelled_list | ||
84 | * @req: the request to be moved | ||
85 | * | ||
86 | * Caller should take care of locking. This function will move @req from its | ||
87 | * current list to the endpoint's cancelled_list. | ||
88 | */ | ||
89 | static inline void dwc3_gadget_move_cancelled_request(struct dwc3_request *req) | ||
90 | { | ||
91 | struct dwc3_ep *dep = req->dep; | ||
92 | |||
93 | req->started = false; | ||
94 | list_move_tail(&req->list, &dep->cancelled_list); | ||
95 | } | ||
96 | |||
82 | void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, | 97 | void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, |
83 | int status); | 98 | int status); |
84 | 99 | ||
diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c index 1a3878a3be78..f55947294f7c 100644 --- a/drivers/usb/dwc3/host.c +++ b/drivers/usb/dwc3/host.c | |||
@@ -46,7 +46,7 @@ out: | |||
46 | 46 | ||
47 | int dwc3_host_init(struct dwc3 *dwc) | 47 | int dwc3_host_init(struct dwc3 *dwc) |
48 | { | 48 | { |
49 | struct property_entry props[3]; | 49 | struct property_entry props[4]; |
50 | struct platform_device *xhci; | 50 | struct platform_device *xhci; |
51 | int ret, irq; | 51 | int ret, irq; |
52 | struct resource *res; | 52 | struct resource *res; |
@@ -93,6 +93,9 @@ int dwc3_host_init(struct dwc3 *dwc) | |||
93 | if (dwc->usb3_lpm_capable) | 93 | if (dwc->usb3_lpm_capable) |
94 | props[prop_idx++].name = "usb3-lpm-capable"; | 94 | props[prop_idx++].name = "usb3-lpm-capable"; |
95 | 95 | ||
96 | if (dwc->usb2_lpm_disable) | ||
97 | props[prop_idx++].name = "usb2-lpm-disable"; | ||
98 | |||
96 | /** | 99 | /** |
97 | * WORKAROUND: dwc3 revisions <=3.00a have a limitation | 100 | * WORKAROUND: dwc3 revisions <=3.00a have a limitation |
98 | * where Port Disable command doesn't work. | 101 | * where Port Disable command doesn't work. |
diff --git a/drivers/usb/dwc3/trace.h b/drivers/usb/dwc3/trace.h index f22714cce070..e97a00593dda 100644 --- a/drivers/usb/dwc3/trace.h +++ b/drivers/usb/dwc3/trace.h | |||
@@ -199,7 +199,7 @@ DECLARE_EVENT_CLASS(dwc3_log_gadget_ep_cmd, | |||
199 | __entry->param2 = params->param2; | 199 | __entry->param2 = params->param2; |
200 | __entry->cmd_status = cmd_status; | 200 | __entry->cmd_status = cmd_status; |
201 | ), | 201 | ), |
202 | TP_printk("%s: cmd '%s' [%d] params %08x %08x %08x --> status: %s", | 202 | TP_printk("%s: cmd '%s' [%x] params %08x %08x %08x --> status: %s", |
203 | __get_str(name), dwc3_gadget_ep_cmd_string(__entry->cmd), | 203 | __get_str(name), dwc3_gadget_ep_cmd_string(__entry->cmd), |
204 | __entry->cmd, __entry->param0, | 204 | __entry->cmd, __entry->param0, |
205 | __entry->param1, __entry->param2, | 205 | __entry->param1, __entry->param2, |
@@ -251,9 +251,11 @@ DECLARE_EVENT_CLASS(dwc3_log_trb, | |||
251 | s = "2x "; | 251 | s = "2x "; |
252 | break; | 252 | break; |
253 | case 3: | 253 | case 3: |
254 | default: | ||
254 | s = "3x "; | 255 | s = "3x "; |
255 | break; | 256 | break; |
256 | } | 257 | } |
258 | break; | ||
257 | default: | 259 | default: |
258 | s = ""; | 260 | s = ""; |
259 | } s; }), | 261 | } s; }), |
diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c index d633c2abe5a4..ea0d531c63e2 100644 --- a/drivers/usb/early/ehci-dbgp.c +++ b/drivers/usb/early/ehci-dbgp.c | |||
@@ -631,28 +631,28 @@ static int ehci_reset_port(int port) | |||
631 | if (!(portsc & PORT_RESET)) | 631 | if (!(portsc & PORT_RESET)) |
632 | break; | 632 | break; |
633 | } | 633 | } |
634 | if (portsc & PORT_RESET) { | 634 | if (portsc & PORT_RESET) { |
635 | /* force reset to complete */ | 635 | /* force reset to complete */ |
636 | loop = 100 * 1000; | 636 | loop = 100 * 1000; |
637 | writel(portsc & ~(PORT_RWC_BITS | PORT_RESET), | 637 | writel(portsc & ~(PORT_RWC_BITS | PORT_RESET), |
638 | &ehci_regs->port_status[port - 1]); | 638 | &ehci_regs->port_status[port - 1]); |
639 | do { | 639 | do { |
640 | udelay(1); | 640 | udelay(1); |
641 | portsc = readl(&ehci_regs->port_status[port-1]); | 641 | portsc = readl(&ehci_regs->port_status[port-1]); |
642 | } while ((portsc & PORT_RESET) && (--loop > 0)); | 642 | } while ((portsc & PORT_RESET) && (--loop > 0)); |
643 | } | 643 | } |
644 | 644 | ||
645 | /* Device went away? */ | 645 | /* Device went away? */ |
646 | if (!(portsc & PORT_CONNECT)) | 646 | if (!(portsc & PORT_CONNECT)) |
647 | return -ENOTCONN; | 647 | return -ENOTCONN; |
648 | 648 | ||
649 | /* bomb out completely if something weird happened */ | 649 | /* bomb out completely if something weird happened */ |
650 | if ((portsc & PORT_CSC)) | 650 | if ((portsc & PORT_CSC)) |
651 | return -EINVAL; | 651 | return -EINVAL; |
652 | 652 | ||
653 | /* If we've finished resetting, then break out of the loop */ | 653 | /* If we've finished resetting, then break out of the loop */ |
654 | if (!(portsc & PORT_RESET) && (portsc & PORT_PE)) | 654 | if (!(portsc & PORT_RESET) && (portsc & PORT_PE)) |
655 | return 0; | 655 | return 0; |
656 | return -EBUSY; | 656 | return -EBUSY; |
657 | } | 657 | } |
658 | 658 | ||
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 31e8bf3578c8..1e5430438703 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c | |||
@@ -18,11 +18,15 @@ | |||
18 | #include <linux/pagemap.h> | 18 | #include <linux/pagemap.h> |
19 | #include <linux/export.h> | 19 | #include <linux/export.h> |
20 | #include <linux/hid.h> | 20 | #include <linux/hid.h> |
21 | #include <linux/mm.h> | ||
21 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/scatterlist.h> | ||
22 | #include <linux/sched/signal.h> | 24 | #include <linux/sched/signal.h> |
23 | #include <linux/uio.h> | 25 | #include <linux/uio.h> |
26 | #include <linux/vmalloc.h> | ||
24 | #include <asm/unaligned.h> | 27 | #include <asm/unaligned.h> |
25 | 28 | ||
29 | #include <linux/usb/ccid.h> | ||
26 | #include <linux/usb/composite.h> | 30 | #include <linux/usb/composite.h> |
27 | #include <linux/usb/functionfs.h> | 31 | #include <linux/usb/functionfs.h> |
28 | 32 | ||
@@ -218,6 +222,8 @@ struct ffs_io_data { | |||
218 | 222 | ||
219 | struct usb_ep *ep; | 223 | struct usb_ep *ep; |
220 | struct usb_request *req; | 224 | struct usb_request *req; |
225 | struct sg_table sgt; | ||
226 | bool use_sg; | ||
221 | 227 | ||
222 | struct ffs_data *ffs; | 228 | struct ffs_data *ffs; |
223 | }; | 229 | }; |
@@ -749,6 +755,65 @@ static ssize_t ffs_copy_to_iter(void *data, int data_len, struct iov_iter *iter) | |||
749 | return ret; | 755 | return ret; |
750 | } | 756 | } |
751 | 757 | ||
758 | /* | ||
759 | * allocate a virtually contiguous buffer and create a scatterlist describing it | ||
760 | * @sg_table - pointer to a place to be filled with sg_table contents | ||
761 | * @size - required buffer size | ||
762 | */ | ||
763 | static void *ffs_build_sg_list(struct sg_table *sgt, size_t sz) | ||
764 | { | ||
765 | struct page **pages; | ||
766 | void *vaddr, *ptr; | ||
767 | unsigned int n_pages; | ||
768 | int i; | ||
769 | |||
770 | vaddr = vmalloc(sz); | ||
771 | if (!vaddr) | ||
772 | return NULL; | ||
773 | |||
774 | n_pages = PAGE_ALIGN(sz) >> PAGE_SHIFT; | ||
775 | pages = kvmalloc_array(n_pages, sizeof(struct page *), GFP_KERNEL); | ||
776 | if (!pages) { | ||
777 | vfree(vaddr); | ||
778 | |||
779 | return NULL; | ||
780 | } | ||
781 | for (i = 0, ptr = vaddr; i < n_pages; ++i, ptr += PAGE_SIZE) | ||
782 | pages[i] = vmalloc_to_page(ptr); | ||
783 | |||
784 | if (sg_alloc_table_from_pages(sgt, pages, n_pages, 0, sz, GFP_KERNEL)) { | ||
785 | kvfree(pages); | ||
786 | vfree(vaddr); | ||
787 | |||
788 | return NULL; | ||
789 | } | ||
790 | kvfree(pages); | ||
791 | |||
792 | return vaddr; | ||
793 | } | ||
794 | |||
795 | static inline void *ffs_alloc_buffer(struct ffs_io_data *io_data, | ||
796 | size_t data_len) | ||
797 | { | ||
798 | if (io_data->use_sg) | ||
799 | return ffs_build_sg_list(&io_data->sgt, data_len); | ||
800 | |||
801 | return kmalloc(data_len, GFP_KERNEL); | ||
802 | } | ||
803 | |||
804 | static inline void ffs_free_buffer(struct ffs_io_data *io_data) | ||
805 | { | ||
806 | if (!io_data->buf) | ||
807 | return; | ||
808 | |||
809 | if (io_data->use_sg) { | ||
810 | sg_free_table(&io_data->sgt); | ||
811 | vfree(io_data->buf); | ||
812 | } else { | ||
813 | kfree(io_data->buf); | ||
814 | } | ||
815 | } | ||
816 | |||
752 | static void ffs_user_copy_worker(struct work_struct *work) | 817 | static void ffs_user_copy_worker(struct work_struct *work) |
753 | { | 818 | { |
754 | struct ffs_io_data *io_data = container_of(work, struct ffs_io_data, | 819 | struct ffs_io_data *io_data = container_of(work, struct ffs_io_data, |
@@ -776,7 +841,7 @@ static void ffs_user_copy_worker(struct work_struct *work) | |||
776 | 841 | ||
777 | if (io_data->read) | 842 | if (io_data->read) |
778 | kfree(io_data->to_free); | 843 | kfree(io_data->to_free); |
779 | kfree(io_data->buf); | 844 | ffs_free_buffer(io_data); |
780 | kfree(io_data); | 845 | kfree(io_data); |
781 | } | 846 | } |
782 | 847 | ||
@@ -932,6 +997,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) | |||
932 | * earlier | 997 | * earlier |
933 | */ | 998 | */ |
934 | gadget = epfile->ffs->gadget; | 999 | gadget = epfile->ffs->gadget; |
1000 | io_data->use_sg = gadget->sg_supported && data_len > PAGE_SIZE; | ||
935 | 1001 | ||
936 | spin_lock_irq(&epfile->ffs->eps_lock); | 1002 | spin_lock_irq(&epfile->ffs->eps_lock); |
937 | /* In the meantime, endpoint got disabled or changed. */ | 1003 | /* In the meantime, endpoint got disabled or changed. */ |
@@ -948,7 +1014,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) | |||
948 | data_len = usb_ep_align_maybe(gadget, ep->ep, data_len); | 1014 | data_len = usb_ep_align_maybe(gadget, ep->ep, data_len); |
949 | spin_unlock_irq(&epfile->ffs->eps_lock); | 1015 | spin_unlock_irq(&epfile->ffs->eps_lock); |
950 | 1016 | ||
951 | data = kmalloc(data_len, GFP_KERNEL); | 1017 | data = ffs_alloc_buffer(io_data, data_len); |
952 | if (unlikely(!data)) { | 1018 | if (unlikely(!data)) { |
953 | ret = -ENOMEM; | 1019 | ret = -ENOMEM; |
954 | goto error_mutex; | 1020 | goto error_mutex; |
@@ -988,8 +1054,16 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) | |||
988 | bool interrupted = false; | 1054 | bool interrupted = false; |
989 | 1055 | ||
990 | req = ep->req; | 1056 | req = ep->req; |
991 | req->buf = data; | 1057 | if (io_data->use_sg) { |
992 | req->length = data_len; | 1058 | req->buf = NULL; |
1059 | req->sg = io_data->sgt.sgl; | ||
1060 | req->num_sgs = io_data->sgt.nents; | ||
1061 | } else { | ||
1062 | req->buf = data; | ||
1063 | } | ||
1064 | req->length = data_len; | ||
1065 | |||
1066 | io_data->buf = data; | ||
993 | 1067 | ||
994 | req->context = &done; | 1068 | req->context = &done; |
995 | req->complete = ffs_epfile_io_complete; | 1069 | req->complete = ffs_epfile_io_complete; |
@@ -1022,8 +1096,14 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) | |||
1022 | } else if (!(req = usb_ep_alloc_request(ep->ep, GFP_ATOMIC))) { | 1096 | } else if (!(req = usb_ep_alloc_request(ep->ep, GFP_ATOMIC))) { |
1023 | ret = -ENOMEM; | 1097 | ret = -ENOMEM; |
1024 | } else { | 1098 | } else { |
1025 | req->buf = data; | 1099 | if (io_data->use_sg) { |
1026 | req->length = data_len; | 1100 | req->buf = NULL; |
1101 | req->sg = io_data->sgt.sgl; | ||
1102 | req->num_sgs = io_data->sgt.nents; | ||
1103 | } else { | ||
1104 | req->buf = data; | ||
1105 | } | ||
1106 | req->length = data_len; | ||
1027 | 1107 | ||
1028 | io_data->buf = data; | 1108 | io_data->buf = data; |
1029 | io_data->ep = ep->ep; | 1109 | io_data->ep = ep->ep; |
@@ -1052,7 +1132,7 @@ error_lock: | |||
1052 | error_mutex: | 1132 | error_mutex: |
1053 | mutex_unlock(&epfile->mutex); | 1133 | mutex_unlock(&epfile->mutex); |
1054 | error: | 1134 | error: |
1055 | kfree(data); | 1135 | ffs_free_buffer(io_data); |
1056 | return ret; | 1136 | return ret; |
1057 | } | 1137 | } |
1058 | 1138 | ||
@@ -1926,7 +2006,7 @@ typedef int (*ffs_os_desc_callback)(enum ffs_os_desc_type entity, | |||
1926 | 2006 | ||
1927 | static int __must_check ffs_do_single_desc(char *data, unsigned len, | 2007 | static int __must_check ffs_do_single_desc(char *data, unsigned len, |
1928 | ffs_entity_callback entity, | 2008 | ffs_entity_callback entity, |
1929 | void *priv) | 2009 | void *priv, int *current_class) |
1930 | { | 2010 | { |
1931 | struct usb_descriptor_header *_ds = (void *)data; | 2011 | struct usb_descriptor_header *_ds = (void *)data; |
1932 | u8 length; | 2012 | u8 length; |
@@ -1984,6 +2064,7 @@ static int __must_check ffs_do_single_desc(char *data, unsigned len, | |||
1984 | __entity(INTERFACE, ds->bInterfaceNumber); | 2064 | __entity(INTERFACE, ds->bInterfaceNumber); |
1985 | if (ds->iInterface) | 2065 | if (ds->iInterface) |
1986 | __entity(STRING, ds->iInterface); | 2066 | __entity(STRING, ds->iInterface); |
2067 | *current_class = ds->bInterfaceClass; | ||
1987 | } | 2068 | } |
1988 | break; | 2069 | break; |
1989 | 2070 | ||
@@ -1997,11 +2078,22 @@ static int __must_check ffs_do_single_desc(char *data, unsigned len, | |||
1997 | } | 2078 | } |
1998 | break; | 2079 | break; |
1999 | 2080 | ||
2000 | case HID_DT_HID: | 2081 | case USB_TYPE_CLASS | 0x01: |
2001 | pr_vdebug("hid descriptor\n"); | 2082 | if (*current_class == USB_INTERFACE_CLASS_HID) { |
2002 | if (length != sizeof(struct hid_descriptor)) | 2083 | pr_vdebug("hid descriptor\n"); |
2003 | goto inv_length; | 2084 | if (length != sizeof(struct hid_descriptor)) |
2004 | break; | 2085 | goto inv_length; |
2086 | break; | ||
2087 | } else if (*current_class == USB_INTERFACE_CLASS_CCID) { | ||
2088 | pr_vdebug("ccid descriptor\n"); | ||
2089 | if (length != sizeof(struct ccid_descriptor)) | ||
2090 | goto inv_length; | ||
2091 | break; | ||
2092 | } else { | ||
2093 | pr_vdebug("unknown descriptor: %d for class %d\n", | ||
2094 | _ds->bDescriptorType, *current_class); | ||
2095 | return -EINVAL; | ||
2096 | } | ||
2005 | 2097 | ||
2006 | case USB_DT_OTG: | 2098 | case USB_DT_OTG: |
2007 | if (length != sizeof(struct usb_otg_descriptor)) | 2099 | if (length != sizeof(struct usb_otg_descriptor)) |
@@ -2058,6 +2150,7 @@ static int __must_check ffs_do_descs(unsigned count, char *data, unsigned len, | |||
2058 | { | 2150 | { |
2059 | const unsigned _len = len; | 2151 | const unsigned _len = len; |
2060 | unsigned long num = 0; | 2152 | unsigned long num = 0; |
2153 | int current_class = -1; | ||
2061 | 2154 | ||
2062 | ENTER(); | 2155 | ENTER(); |
2063 | 2156 | ||
@@ -2078,7 +2171,8 @@ static int __must_check ffs_do_descs(unsigned count, char *data, unsigned len, | |||
2078 | if (!data) | 2171 | if (!data) |
2079 | return _len - len; | 2172 | return _len - len; |
2080 | 2173 | ||
2081 | ret = ffs_do_single_desc(data, len, entity, priv); | 2174 | ret = ffs_do_single_desc(data, len, entity, priv, |
2175 | ¤t_class); | ||
2082 | if (unlikely(ret < 0)) { | 2176 | if (unlikely(ret < 0)) { |
2083 | pr_debug("%s returns %d\n", __func__, ret); | 2177 | pr_debug("%s returns %d\n", __func__, ret); |
2084 | return ret; | 2178 | return ret; |
diff --git a/drivers/usb/gadget/function/uvc_queue.c b/drivers/usb/gadget/function/uvc_queue.c index f2497cb96abb..61e2c94cc0b0 100644 --- a/drivers/usb/gadget/function/uvc_queue.c +++ b/drivers/usb/gadget/function/uvc_queue.c | |||
@@ -102,7 +102,7 @@ static void uvc_buffer_queue(struct vb2_buffer *vb) | |||
102 | spin_unlock_irqrestore(&queue->irqlock, flags); | 102 | spin_unlock_irqrestore(&queue->irqlock, flags); |
103 | } | 103 | } |
104 | 104 | ||
105 | static struct vb2_ops uvc_queue_qops = { | 105 | static const struct vb2_ops uvc_queue_qops = { |
106 | .queue_setup = uvc_queue_setup, | 106 | .queue_setup = uvc_queue_setup, |
107 | .buf_prepare = uvc_buffer_prepare, | 107 | .buf_prepare = uvc_buffer_prepare, |
108 | .buf_queue = uvc_buffer_queue, | 108 | .buf_queue = uvc_buffer_queue, |
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/dev.c b/drivers/usb/gadget/udc/aspeed-vhub/dev.c index f0233912bace..6b1b16b17d7d 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/dev.c +++ b/drivers/usb/gadget/udc/aspeed-vhub/dev.c | |||
@@ -438,7 +438,7 @@ static int ast_vhub_udc_stop(struct usb_gadget *gadget) | |||
438 | return 0; | 438 | return 0; |
439 | } | 439 | } |
440 | 440 | ||
441 | static struct usb_gadget_ops ast_vhub_udc_ops = { | 441 | static const struct usb_gadget_ops ast_vhub_udc_ops = { |
442 | .get_frame = ast_vhub_udc_get_frame, | 442 | .get_frame = ast_vhub_udc_get_frame, |
443 | .wakeup = ast_vhub_udc_wakeup, | 443 | .wakeup = ast_vhub_udc_wakeup, |
444 | .pullup = ast_vhub_udc_pullup, | 444 | .pullup = ast_vhub_udc_pullup, |
diff --git a/drivers/usb/gadget/udc/pch_udc.c b/drivers/usb/gadget/udc/pch_udc.c index afaea11ec771..55c8c8abeacd 100644 --- a/drivers/usb/gadget/udc/pch_udc.c +++ b/drivers/usb/gadget/udc/pch_udc.c | |||
@@ -1330,7 +1330,7 @@ static void pch_vbus_gpio_work_rise(struct work_struct *irq_work) | |||
1330 | } | 1330 | } |
1331 | 1331 | ||
1332 | /** | 1332 | /** |
1333 | * pch_vbus_gpio_irq() - IRQ handler for GPIO intrerrupt for changing VBUS | 1333 | * pch_vbus_gpio_irq() - IRQ handler for GPIO interrupt for changing VBUS |
1334 | * @irq: Interrupt request number | 1334 | * @irq: Interrupt request number |
1335 | * @dev: Reference to the device structure | 1335 | * @dev: Reference to the device structure |
1336 | * | 1336 | * |
diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c index cdffbd1e0316..6e34f9594159 100644 --- a/drivers/usb/gadget/udc/renesas_usb3.c +++ b/drivers/usb/gadget/udc/renesas_usb3.c | |||
@@ -358,6 +358,7 @@ struct renesas_usb3 { | |||
358 | bool extcon_host; /* check id and set EXTCON_USB_HOST */ | 358 | bool extcon_host; /* check id and set EXTCON_USB_HOST */ |
359 | bool extcon_usb; /* check vbus and set EXTCON_USB */ | 359 | bool extcon_usb; /* check vbus and set EXTCON_USB */ |
360 | bool forced_b_device; | 360 | bool forced_b_device; |
361 | bool start_to_connect; | ||
361 | }; | 362 | }; |
362 | 363 | ||
363 | #define gadget_to_renesas_usb3(_gadget) \ | 364 | #define gadget_to_renesas_usb3(_gadget) \ |
@@ -476,7 +477,8 @@ static void usb3_init_axi_bridge(struct renesas_usb3 *usb3) | |||
476 | static void usb3_init_epc_registers(struct renesas_usb3 *usb3) | 477 | static void usb3_init_epc_registers(struct renesas_usb3 *usb3) |
477 | { | 478 | { |
478 | usb3_write(usb3, ~0, USB3_USB_INT_STA_1); | 479 | usb3_write(usb3, ~0, USB3_USB_INT_STA_1); |
479 | usb3_enable_irq_1(usb3, USB_INT_1_VBUS_CNG); | 480 | if (!usb3->workaround_for_vbus) |
481 | usb3_enable_irq_1(usb3, USB_INT_1_VBUS_CNG); | ||
480 | } | 482 | } |
481 | 483 | ||
482 | static bool usb3_wakeup_usb2_phy(struct renesas_usb3 *usb3) | 484 | static bool usb3_wakeup_usb2_phy(struct renesas_usb3 *usb3) |
@@ -700,8 +702,7 @@ static void usb3_mode_config(struct renesas_usb3 *usb3, bool host, bool a_dev) | |||
700 | usb3_set_mode_by_role_sw(usb3, host); | 702 | usb3_set_mode_by_role_sw(usb3, host); |
701 | usb3_vbus_out(usb3, a_dev); | 703 | usb3_vbus_out(usb3, a_dev); |
702 | /* for A-Peripheral or forced B-device mode */ | 704 | /* for A-Peripheral or forced B-device mode */ |
703 | if ((!host && a_dev) || | 705 | if ((!host && a_dev) || usb3->start_to_connect) |
704 | (usb3->workaround_for_vbus && usb3->forced_b_device)) | ||
705 | usb3_connect(usb3); | 706 | usb3_connect(usb3); |
706 | spin_unlock_irqrestore(&usb3->lock, flags); | 707 | spin_unlock_irqrestore(&usb3->lock, flags); |
707 | } | 708 | } |
@@ -2432,7 +2433,11 @@ static ssize_t renesas_usb3_b_device_write(struct file *file, | |||
2432 | if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) | 2433 | if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) |
2433 | return -EFAULT; | 2434 | return -EFAULT; |
2434 | 2435 | ||
2435 | if (!strncmp(buf, "1", 1)) | 2436 | usb3->start_to_connect = false; |
2437 | if (usb3->workaround_for_vbus && usb3->forced_b_device && | ||
2438 | !strncmp(buf, "2", 1)) | ||
2439 | usb3->start_to_connect = true; | ||
2440 | else if (!strncmp(buf, "1", 1)) | ||
2436 | usb3->forced_b_device = true; | 2441 | usb3->forced_b_device = true; |
2437 | else | 2442 | else |
2438 | usb3->forced_b_device = false; | 2443 | usb3->forced_b_device = false; |
@@ -2440,7 +2445,7 @@ static ssize_t renesas_usb3_b_device_write(struct file *file, | |||
2440 | if (usb3->workaround_for_vbus) | 2445 | if (usb3->workaround_for_vbus) |
2441 | usb3_disconnect(usb3); | 2446 | usb3_disconnect(usb3); |
2442 | 2447 | ||
2443 | /* Let this driver call usb3_connect() anyway */ | 2448 | /* Let this driver call usb3_connect() if needed */ |
2444 | usb3_check_id(usb3); | 2449 | usb3_check_id(usb3); |
2445 | 2450 | ||
2446 | return count; | 2451 | return count; |
diff --git a/drivers/usb/gadget/udc/s3c2410_udc.c b/drivers/usb/gadget/udc/s3c2410_udc.c index 8bf5ad7a59ad..af3e63316ace 100644 --- a/drivers/usb/gadget/udc/s3c2410_udc.c +++ b/drivers/usb/gadget/udc/s3c2410_udc.c | |||
@@ -119,7 +119,7 @@ static void dprintk(int level, const char *fmt, ...) | |||
119 | } | 119 | } |
120 | #endif | 120 | #endif |
121 | 121 | ||
122 | static int s3c2410_udc_debugfs_seq_show(struct seq_file *m, void *p) | 122 | static int s3c2410_udc_debugfs_show(struct seq_file *m, void *p) |
123 | { | 123 | { |
124 | u32 addr_reg, pwr_reg, ep_int_reg, usb_int_reg; | 124 | u32 addr_reg, pwr_reg, ep_int_reg, usb_int_reg; |
125 | u32 ep_int_en_reg, usb_int_en_reg, ep0_csr; | 125 | u32 ep_int_en_reg, usb_int_en_reg, ep0_csr; |
@@ -168,20 +168,7 @@ static int s3c2410_udc_debugfs_seq_show(struct seq_file *m, void *p) | |||
168 | 168 | ||
169 | return 0; | 169 | return 0; |
170 | } | 170 | } |
171 | 171 | DEFINE_SHOW_ATTRIBUTE(s3c2410_udc_debugfs); | |
172 | static int s3c2410_udc_debugfs_fops_open(struct inode *inode, | ||
173 | struct file *file) | ||
174 | { | ||
175 | return single_open(file, s3c2410_udc_debugfs_seq_show, NULL); | ||
176 | } | ||
177 | |||
178 | static const struct file_operations s3c2410_udc_debugfs_fops = { | ||
179 | .open = s3c2410_udc_debugfs_fops_open, | ||
180 | .read = seq_read, | ||
181 | .llseek = seq_lseek, | ||
182 | .release = single_release, | ||
183 | .owner = THIS_MODULE, | ||
184 | }; | ||
185 | 172 | ||
186 | /* io macros */ | 173 | /* io macros */ |
187 | 174 | ||
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 7e4c13346a1e..7d20296cbe9f 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c | |||
@@ -159,11 +159,12 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) | |||
159 | /* get the PHY device */ | 159 | /* get the PHY device */ |
160 | phy = devm_usb_get_phy_by_phandle(dev, "phys", i); | 160 | phy = devm_usb_get_phy_by_phandle(dev, "phys", i); |
161 | if (IS_ERR(phy)) { | 161 | if (IS_ERR(phy)) { |
162 | /* Don't bail out if PHY is not absolutely necessary */ | 162 | ret = PTR_ERR(phy); |
163 | if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY) | 163 | if (ret == -ENODEV) { /* no PHY */ |
164 | phy = NULL; | ||
164 | continue; | 165 | continue; |
166 | } | ||
165 | 167 | ||
166 | ret = PTR_ERR(phy); | ||
167 | if (ret != -EPROBE_DEFER) | 168 | if (ret != -EPROBE_DEFER) |
168 | dev_err(dev, "Can't get PHY for port %d: %d\n", | 169 | dev_err(dev, "Can't get PHY for port %d: %d\n", |
169 | i, ret); | 170 | i, ret); |
diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c index b21c386e6a46..28bf8bfb091e 100644 --- a/drivers/usb/host/isp1362-hcd.c +++ b/drivers/usb/host/isp1362-hcd.c | |||
@@ -2159,25 +2159,15 @@ static int isp1362_show(struct seq_file *s, void *unused) | |||
2159 | 2159 | ||
2160 | return 0; | 2160 | return 0; |
2161 | } | 2161 | } |
2162 | 2162 | DEFINE_SHOW_ATTRIBUTE(isp1362); | |
2163 | static int isp1362_open(struct inode *inode, struct file *file) | ||
2164 | { | ||
2165 | return single_open(file, isp1362_show, inode); | ||
2166 | } | ||
2167 | |||
2168 | static const struct file_operations debug_ops = { | ||
2169 | .open = isp1362_open, | ||
2170 | .read = seq_read, | ||
2171 | .llseek = seq_lseek, | ||
2172 | .release = single_release, | ||
2173 | }; | ||
2174 | 2163 | ||
2175 | /* expect just one isp1362_hcd per system */ | 2164 | /* expect just one isp1362_hcd per system */ |
2176 | static void create_debug_file(struct isp1362_hcd *isp1362_hcd) | 2165 | static void create_debug_file(struct isp1362_hcd *isp1362_hcd) |
2177 | { | 2166 | { |
2178 | isp1362_hcd->debug_file = debugfs_create_file("isp1362", S_IRUGO, | 2167 | isp1362_hcd->debug_file = debugfs_create_file("isp1362", S_IRUGO, |
2179 | usb_debug_root, | 2168 | usb_debug_root, |
2180 | isp1362_hcd, &debug_ops); | 2169 | isp1362_hcd, |
2170 | &isp1362_fops); | ||
2181 | } | 2171 | } |
2182 | 2172 | ||
2183 | static void remove_debug_file(struct isp1362_hcd *isp1362_hcd) | 2173 | static void remove_debug_file(struct isp1362_hcd *isp1362_hcd) |
diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c index b3da3f12e5b1..3965ac0341eb 100644 --- a/drivers/usb/host/ohci-mem.c +++ b/drivers/usb/host/ohci-mem.c | |||
@@ -57,14 +57,10 @@ static int ohci_mem_init (struct ohci_hcd *ohci) | |||
57 | 57 | ||
58 | static void ohci_mem_cleanup (struct ohci_hcd *ohci) | 58 | static void ohci_mem_cleanup (struct ohci_hcd *ohci) |
59 | { | 59 | { |
60 | if (ohci->td_cache) { | 60 | dma_pool_destroy(ohci->td_cache); |
61 | dma_pool_destroy (ohci->td_cache); | 61 | ohci->td_cache = NULL; |
62 | ohci->td_cache = NULL; | 62 | dma_pool_destroy(ohci->ed_cache); |
63 | } | 63 | ohci->ed_cache = NULL; |
64 | if (ohci->ed_cache) { | ||
65 | dma_pool_destroy (ohci->ed_cache); | ||
66 | ohci->ed_cache = NULL; | ||
67 | } | ||
68 | } | 64 | } |
69 | 65 | ||
70 | /*-------------------------------------------------------------------------*/ | 66 | /*-------------------------------------------------------------------------*/ |
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 984892dd72f5..42668aeca57c 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c | |||
@@ -1979,6 +1979,8 @@ static int r8a66597_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, | |||
1979 | 1979 | ||
1980 | static void r8a66597_endpoint_disable(struct usb_hcd *hcd, | 1980 | static void r8a66597_endpoint_disable(struct usb_hcd *hcd, |
1981 | struct usb_host_endpoint *hep) | 1981 | struct usb_host_endpoint *hep) |
1982 | __acquires(r8a66597->lock) | ||
1983 | __releases(r8a66597->lock) | ||
1982 | { | 1984 | { |
1983 | struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd); | 1985 | struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd); |
1984 | struct r8a66597_pipe *pipe = (struct r8a66597_pipe *)hep->hcpriv; | 1986 | struct r8a66597_pipe *pipe = (struct r8a66597_pipe *)hep->hcpriv; |
@@ -1991,13 +1993,14 @@ static void r8a66597_endpoint_disable(struct usb_hcd *hcd, | |||
1991 | return; | 1993 | return; |
1992 | pipenum = pipe->info.pipenum; | 1994 | pipenum = pipe->info.pipenum; |
1993 | 1995 | ||
1996 | spin_lock_irqsave(&r8a66597->lock, flags); | ||
1994 | if (pipenum == 0) { | 1997 | if (pipenum == 0) { |
1995 | kfree(hep->hcpriv); | 1998 | kfree(hep->hcpriv); |
1996 | hep->hcpriv = NULL; | 1999 | hep->hcpriv = NULL; |
2000 | spin_unlock_irqrestore(&r8a66597->lock, flags); | ||
1997 | return; | 2001 | return; |
1998 | } | 2002 | } |
1999 | 2003 | ||
2000 | spin_lock_irqsave(&r8a66597->lock, flags); | ||
2001 | pipe_stop(r8a66597, pipe); | 2004 | pipe_stop(r8a66597, pipe); |
2002 | pipe_irq_disable(r8a66597, pipenum); | 2005 | pipe_irq_disable(r8a66597, pipenum); |
2003 | disable_irq_empty(r8a66597, pipenum); | 2006 | disable_irq_empty(r8a66597, pipenum); |
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 01b5818a4be5..e2eece693655 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c | |||
@@ -714,13 +714,6 @@ void xhci_test_and_clear_bit(struct xhci_hcd *xhci, struct xhci_port *port, | |||
714 | } | 714 | } |
715 | } | 715 | } |
716 | 716 | ||
717 | /* Updates Link Status for USB 2.1 port */ | ||
718 | static void xhci_hub_report_usb2_link_state(u32 *status, u32 status_reg) | ||
719 | { | ||
720 | if ((status_reg & PORT_PLS_MASK) == XDEV_U2) | ||
721 | *status |= USB_PORT_STAT_L1; | ||
722 | } | ||
723 | |||
724 | /* Updates Link Status for super Speed port */ | 717 | /* Updates Link Status for super Speed port */ |
725 | static void xhci_hub_report_usb3_link_state(struct xhci_hcd *xhci, | 718 | static void xhci_hub_report_usb3_link_state(struct xhci_hcd *xhci, |
726 | u32 *status, u32 status_reg) | 719 | u32 *status, u32 status_reg) |
@@ -802,6 +795,100 @@ static void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status, | |||
802 | } | 795 | } |
803 | } | 796 | } |
804 | 797 | ||
798 | static int xhci_handle_usb2_port_link_resume(struct xhci_port *port, | ||
799 | u32 *status, u32 portsc, | ||
800 | unsigned long flags) | ||
801 | { | ||
802 | struct xhci_bus_state *bus_state; | ||
803 | struct xhci_hcd *xhci; | ||
804 | struct usb_hcd *hcd; | ||
805 | int slot_id; | ||
806 | u32 wIndex; | ||
807 | |||
808 | hcd = port->rhub->hcd; | ||
809 | bus_state = &port->rhub->bus_state; | ||
810 | xhci = hcd_to_xhci(hcd); | ||
811 | wIndex = port->hcd_portnum; | ||
812 | |||
813 | if ((portsc & PORT_RESET) || !(portsc & PORT_PE)) { | ||
814 | *status = 0xffffffff; | ||
815 | return -EINVAL; | ||
816 | } | ||
817 | /* did port event handler already start resume timing? */ | ||
818 | if (!bus_state->resume_done[wIndex]) { | ||
819 | /* If not, maybe we are in a host initated resume? */ | ||
820 | if (test_bit(wIndex, &bus_state->resuming_ports)) { | ||
821 | /* Host initated resume doesn't time the resume | ||
822 | * signalling using resume_done[]. | ||
823 | * It manually sets RESUME state, sleeps 20ms | ||
824 | * and sets U0 state. This should probably be | ||
825 | * changed, but not right now. | ||
826 | */ | ||
827 | } else { | ||
828 | /* port resume was discovered now and here, | ||
829 | * start resume timing | ||
830 | */ | ||
831 | unsigned long timeout = jiffies + | ||
832 | msecs_to_jiffies(USB_RESUME_TIMEOUT); | ||
833 | |||
834 | set_bit(wIndex, &bus_state->resuming_ports); | ||
835 | bus_state->resume_done[wIndex] = timeout; | ||
836 | mod_timer(&hcd->rh_timer, timeout); | ||
837 | usb_hcd_start_port_resume(&hcd->self, wIndex); | ||
838 | } | ||
839 | /* Has resume been signalled for USB_RESUME_TIME yet? */ | ||
840 | } else if (time_after_eq(jiffies, bus_state->resume_done[wIndex])) { | ||
841 | int time_left; | ||
842 | |||
843 | xhci_dbg(xhci, "Resume USB2 port %d\n", wIndex + 1); | ||
844 | bus_state->resume_done[wIndex] = 0; | ||
845 | clear_bit(wIndex, &bus_state->resuming_ports); | ||
846 | |||
847 | set_bit(wIndex, &bus_state->rexit_ports); | ||
848 | |||
849 | xhci_test_and_clear_bit(xhci, port, PORT_PLC); | ||
850 | xhci_set_link_state(xhci, port, XDEV_U0); | ||
851 | |||
852 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
853 | time_left = wait_for_completion_timeout( | ||
854 | &bus_state->rexit_done[wIndex], | ||
855 | msecs_to_jiffies(XHCI_MAX_REXIT_TIMEOUT_MS)); | ||
856 | spin_lock_irqsave(&xhci->lock, flags); | ||
857 | |||
858 | if (time_left) { | ||
859 | slot_id = xhci_find_slot_id_by_port(hcd, xhci, | ||
860 | wIndex + 1); | ||
861 | if (!slot_id) { | ||
862 | xhci_dbg(xhci, "slot_id is zero\n"); | ||
863 | *status = 0xffffffff; | ||
864 | return -ENODEV; | ||
865 | } | ||
866 | xhci_ring_device(xhci, slot_id); | ||
867 | } else { | ||
868 | int port_status = readl(port->addr); | ||
869 | |||
870 | xhci_warn(xhci, "Port resume %i msec timed out, portsc = 0x%x\n", | ||
871 | XHCI_MAX_REXIT_TIMEOUT_MS, | ||
872 | port_status); | ||
873 | *status |= USB_PORT_STAT_SUSPEND; | ||
874 | clear_bit(wIndex, &bus_state->rexit_ports); | ||
875 | } | ||
876 | |||
877 | usb_hcd_end_port_resume(&hcd->self, wIndex); | ||
878 | bus_state->port_c_suspend |= 1 << wIndex; | ||
879 | bus_state->suspended_ports &= ~(1 << wIndex); | ||
880 | } else { | ||
881 | /* | ||
882 | * The resume has been signaling for less than | ||
883 | * USB_RESUME_TIME. Report the port status as SUSPEND, | ||
884 | * let the usbcore check port status again and clear | ||
885 | * resume signaling later. | ||
886 | */ | ||
887 | *status |= USB_PORT_STAT_SUSPEND; | ||
888 | } | ||
889 | return 0; | ||
890 | } | ||
891 | |||
805 | static u32 xhci_get_ext_port_status(u32 raw_port_status, u32 port_li) | 892 | static u32 xhci_get_ext_port_status(u32 raw_port_status, u32 port_li) |
806 | { | 893 | { |
807 | u32 ext_stat = 0; | 894 | u32 ext_stat = 0; |
@@ -818,6 +905,85 @@ static u32 xhci_get_ext_port_status(u32 raw_port_status, u32 port_li) | |||
818 | return ext_stat; | 905 | return ext_stat; |
819 | } | 906 | } |
820 | 907 | ||
908 | static void xhci_get_usb3_port_status(struct xhci_port *port, u32 *status, | ||
909 | u32 portsc) | ||
910 | { | ||
911 | struct xhci_bus_state *bus_state; | ||
912 | struct xhci_hcd *xhci; | ||
913 | u32 link_state; | ||
914 | u32 portnum; | ||
915 | |||
916 | bus_state = &port->rhub->bus_state; | ||
917 | xhci = hcd_to_xhci(port->rhub->hcd); | ||
918 | link_state = portsc & PORT_PLS_MASK; | ||
919 | portnum = port->hcd_portnum; | ||
920 | |||
921 | /* USB3 specific wPortChange bits | ||
922 | * | ||
923 | * Port link change with port in resume state should not be | ||
924 | * reported to usbcore, as this is an internal state to be | ||
925 | * handled by xhci driver. Reporting PLC to usbcore may | ||
926 | * cause usbcore clearing PLC first and port change event | ||
927 | * irq won't be generated. | ||
928 | */ | ||
929 | |||
930 | if (portsc & PORT_PLC && (link_state != XDEV_RESUME)) | ||
931 | *status |= USB_PORT_STAT_C_LINK_STATE << 16; | ||
932 | if (portsc & PORT_WRC) | ||
933 | *status |= USB_PORT_STAT_C_BH_RESET << 16; | ||
934 | if (portsc & PORT_CEC) | ||
935 | *status |= USB_PORT_STAT_C_CONFIG_ERROR << 16; | ||
936 | |||
937 | /* USB3 specific wPortStatus bits */ | ||
938 | if (portsc & PORT_POWER) { | ||
939 | *status |= USB_SS_PORT_STAT_POWER; | ||
940 | /* link state handling */ | ||
941 | if (link_state == XDEV_U0) | ||
942 | bus_state->suspended_ports &= ~(1 << portnum); | ||
943 | } | ||
944 | |||
945 | xhci_hub_report_usb3_link_state(xhci, status, portsc); | ||
946 | xhci_del_comp_mod_timer(xhci, portsc, portnum); | ||
947 | } | ||
948 | |||
949 | static void xhci_get_usb2_port_status(struct xhci_port *port, u32 *status, | ||
950 | u32 portsc, unsigned long flags) | ||
951 | { | ||
952 | struct xhci_bus_state *bus_state; | ||
953 | u32 link_state; | ||
954 | u32 portnum; | ||
955 | int ret; | ||
956 | |||
957 | bus_state = &port->rhub->bus_state; | ||
958 | link_state = portsc & PORT_PLS_MASK; | ||
959 | portnum = port->hcd_portnum; | ||
960 | |||
961 | /* USB2 wPortStatus bits */ | ||
962 | if (portsc & PORT_POWER) { | ||
963 | *status |= USB_PORT_STAT_POWER; | ||
964 | |||
965 | /* link state is only valid if port is powered */ | ||
966 | if (link_state == XDEV_U3) | ||
967 | *status |= USB_PORT_STAT_SUSPEND; | ||
968 | if (link_state == XDEV_U2) | ||
969 | *status |= USB_PORT_STAT_L1; | ||
970 | if (link_state == XDEV_U0) { | ||
971 | bus_state->resume_done[portnum] = 0; | ||
972 | clear_bit(portnum, &bus_state->resuming_ports); | ||
973 | if (bus_state->suspended_ports & (1 << portnum)) { | ||
974 | bus_state->suspended_ports &= ~(1 << portnum); | ||
975 | bus_state->port_c_suspend |= 1 << portnum; | ||
976 | } | ||
977 | } | ||
978 | if (link_state == XDEV_RESUME) { | ||
979 | ret = xhci_handle_usb2_port_link_resume(port, status, | ||
980 | portsc, flags); | ||
981 | if (ret) | ||
982 | return; | ||
983 | } | ||
984 | } | ||
985 | } | ||
986 | |||
821 | /* | 987 | /* |
822 | * Converts a raw xHCI port status into the format that external USB 2.0 or USB | 988 | * Converts a raw xHCI port status into the format that external USB 2.0 or USB |
823 | * 3.0 hubs use. | 989 | * 3.0 hubs use. |
@@ -835,16 +1001,14 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, | |||
835 | __releases(&xhci->lock) | 1001 | __releases(&xhci->lock) |
836 | __acquires(&xhci->lock) | 1002 | __acquires(&xhci->lock) |
837 | { | 1003 | { |
838 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | ||
839 | u32 status = 0; | 1004 | u32 status = 0; |
840 | int slot_id; | ||
841 | struct xhci_hub *rhub; | 1005 | struct xhci_hub *rhub; |
842 | struct xhci_port *port; | 1006 | struct xhci_port *port; |
843 | 1007 | ||
844 | rhub = xhci_get_rhub(hcd); | 1008 | rhub = xhci_get_rhub(hcd); |
845 | port = rhub->ports[wIndex]; | 1009 | port = rhub->ports[wIndex]; |
846 | 1010 | ||
847 | /* wPortChange bits */ | 1011 | /* common wPortChange bits */ |
848 | if (raw_port_status & PORT_CSC) | 1012 | if (raw_port_status & PORT_CSC) |
849 | status |= USB_PORT_STAT_C_CONNECTION << 16; | 1013 | status |= USB_PORT_STAT_C_CONNECTION << 16; |
850 | if (raw_port_status & PORT_PEC) | 1014 | if (raw_port_status & PORT_PEC) |
@@ -853,107 +1017,25 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, | |||
853 | status |= USB_PORT_STAT_C_OVERCURRENT << 16; | 1017 | status |= USB_PORT_STAT_C_OVERCURRENT << 16; |
854 | if ((raw_port_status & PORT_RC)) | 1018 | if ((raw_port_status & PORT_RC)) |
855 | status |= USB_PORT_STAT_C_RESET << 16; | 1019 | status |= USB_PORT_STAT_C_RESET << 16; |
856 | /* USB3.0 only */ | ||
857 | if (hcd->speed >= HCD_USB3) { | ||
858 | /* Port link change with port in resume state should not be | ||
859 | * reported to usbcore, as this is an internal state to be | ||
860 | * handled by xhci driver. Reporting PLC to usbcore may | ||
861 | * cause usbcore clearing PLC first and port change event | ||
862 | * irq won't be generated. | ||
863 | */ | ||
864 | if ((raw_port_status & PORT_PLC) && | ||
865 | (raw_port_status & PORT_PLS_MASK) != XDEV_RESUME) | ||
866 | status |= USB_PORT_STAT_C_LINK_STATE << 16; | ||
867 | if ((raw_port_status & PORT_WRC)) | ||
868 | status |= USB_PORT_STAT_C_BH_RESET << 16; | ||
869 | if ((raw_port_status & PORT_CEC)) | ||
870 | status |= USB_PORT_STAT_C_CONFIG_ERROR << 16; | ||
871 | } | ||
872 | 1020 | ||
873 | if (hcd->speed < HCD_USB3) { | 1021 | /* common wPortStatus bits */ |
874 | if ((raw_port_status & PORT_PLS_MASK) == XDEV_U3 | 1022 | if (raw_port_status & PORT_CONNECT) { |
875 | && (raw_port_status & PORT_POWER)) | 1023 | status |= USB_PORT_STAT_CONNECTION; |
876 | status |= USB_PORT_STAT_SUSPEND; | 1024 | status |= xhci_port_speed(raw_port_status); |
877 | } | 1025 | } |
878 | if ((raw_port_status & PORT_PLS_MASK) == XDEV_RESUME && | 1026 | if (raw_port_status & PORT_PE) |
879 | !DEV_SUPERSPEED_ANY(raw_port_status) && hcd->speed < HCD_USB3) { | 1027 | status |= USB_PORT_STAT_ENABLE; |
880 | if ((raw_port_status & PORT_RESET) || | 1028 | if (raw_port_status & PORT_OC) |
881 | !(raw_port_status & PORT_PE)) | 1029 | status |= USB_PORT_STAT_OVERCURRENT; |
882 | return 0xffffffff; | 1030 | if (raw_port_status & PORT_RESET) |
883 | /* did port event handler already start resume timing? */ | 1031 | status |= USB_PORT_STAT_RESET; |
884 | if (!bus_state->resume_done[wIndex]) { | ||
885 | /* If not, maybe we are in a host initated resume? */ | ||
886 | if (test_bit(wIndex, &bus_state->resuming_ports)) { | ||
887 | /* Host initated resume doesn't time the resume | ||
888 | * signalling using resume_done[]. | ||
889 | * It manually sets RESUME state, sleeps 20ms | ||
890 | * and sets U0 state. This should probably be | ||
891 | * changed, but not right now. | ||
892 | */ | ||
893 | } else { | ||
894 | /* port resume was discovered now and here, | ||
895 | * start resume timing | ||
896 | */ | ||
897 | unsigned long timeout = jiffies + | ||
898 | msecs_to_jiffies(USB_RESUME_TIMEOUT); | ||
899 | |||
900 | set_bit(wIndex, &bus_state->resuming_ports); | ||
901 | bus_state->resume_done[wIndex] = timeout; | ||
902 | mod_timer(&hcd->rh_timer, timeout); | ||
903 | usb_hcd_start_port_resume(&hcd->self, wIndex); | ||
904 | } | ||
905 | /* Has resume been signalled for USB_RESUME_TIME yet? */ | ||
906 | } else if (time_after_eq(jiffies, | ||
907 | bus_state->resume_done[wIndex])) { | ||
908 | int time_left; | ||
909 | |||
910 | xhci_dbg(xhci, "Resume USB2 port %d\n", | ||
911 | wIndex + 1); | ||
912 | bus_state->resume_done[wIndex] = 0; | ||
913 | clear_bit(wIndex, &bus_state->resuming_ports); | ||
914 | |||
915 | set_bit(wIndex, &bus_state->rexit_ports); | ||
916 | |||
917 | xhci_test_and_clear_bit(xhci, port, PORT_PLC); | ||
918 | xhci_set_link_state(xhci, port, XDEV_U0); | ||
919 | |||
920 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
921 | time_left = wait_for_completion_timeout( | ||
922 | &bus_state->rexit_done[wIndex], | ||
923 | msecs_to_jiffies( | ||
924 | XHCI_MAX_REXIT_TIMEOUT_MS)); | ||
925 | spin_lock_irqsave(&xhci->lock, flags); | ||
926 | |||
927 | if (time_left) { | ||
928 | slot_id = xhci_find_slot_id_by_port(hcd, | ||
929 | xhci, wIndex + 1); | ||
930 | if (!slot_id) { | ||
931 | xhci_dbg(xhci, "slot_id is zero\n"); | ||
932 | return 0xffffffff; | ||
933 | } | ||
934 | xhci_ring_device(xhci, slot_id); | ||
935 | } else { | ||
936 | int port_status = readl(port->addr); | ||
937 | xhci_warn(xhci, "Port resume took longer than %i msec, port status = 0x%x\n", | ||
938 | XHCI_MAX_REXIT_TIMEOUT_MS, | ||
939 | port_status); | ||
940 | status |= USB_PORT_STAT_SUSPEND; | ||
941 | clear_bit(wIndex, &bus_state->rexit_ports); | ||
942 | } | ||
943 | 1032 | ||
944 | usb_hcd_end_port_resume(&hcd->self, wIndex); | 1033 | /* USB2 and USB3 specific bits, including Port Link State */ |
945 | bus_state->port_c_suspend |= 1 << wIndex; | 1034 | if (hcd->speed >= HCD_USB3) |
946 | bus_state->suspended_ports &= ~(1 << wIndex); | 1035 | xhci_get_usb3_port_status(port, &status, raw_port_status); |
947 | } else { | 1036 | else |
948 | /* | 1037 | xhci_get_usb2_port_status(port, &status, raw_port_status, |
949 | * The resume has been signaling for less than | 1038 | flags); |
950 | * USB_RESUME_TIME. Report the port status as SUSPEND, | ||
951 | * let the usbcore check port status again and clear | ||
952 | * resume signaling later. | ||
953 | */ | ||
954 | status |= USB_PORT_STAT_SUSPEND; | ||
955 | } | ||
956 | } | ||
957 | /* | 1039 | /* |
958 | * Clear stale usb2 resume signalling variables in case port changed | 1040 | * Clear stale usb2 resume signalling variables in case port changed |
959 | * state during resume signalling. For example on error | 1041 | * state during resume signalling. For example on error |
@@ -967,44 +1049,6 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, | |||
967 | usb_hcd_end_port_resume(&hcd->self, wIndex); | 1049 | usb_hcd_end_port_resume(&hcd->self, wIndex); |
968 | } | 1050 | } |
969 | 1051 | ||
970 | |||
971 | if ((raw_port_status & PORT_PLS_MASK) == XDEV_U0 && | ||
972 | (raw_port_status & PORT_POWER)) { | ||
973 | if (bus_state->suspended_ports & (1 << wIndex)) { | ||
974 | bus_state->suspended_ports &= ~(1 << wIndex); | ||
975 | if (hcd->speed < HCD_USB3) | ||
976 | bus_state->port_c_suspend |= 1 << wIndex; | ||
977 | } | ||
978 | bus_state->resume_done[wIndex] = 0; | ||
979 | clear_bit(wIndex, &bus_state->resuming_ports); | ||
980 | } | ||
981 | if (raw_port_status & PORT_CONNECT) { | ||
982 | status |= USB_PORT_STAT_CONNECTION; | ||
983 | status |= xhci_port_speed(raw_port_status); | ||
984 | } | ||
985 | if (raw_port_status & PORT_PE) | ||
986 | status |= USB_PORT_STAT_ENABLE; | ||
987 | if (raw_port_status & PORT_OC) | ||
988 | status |= USB_PORT_STAT_OVERCURRENT; | ||
989 | if (raw_port_status & PORT_RESET) | ||
990 | status |= USB_PORT_STAT_RESET; | ||
991 | if (raw_port_status & PORT_POWER) { | ||
992 | if (hcd->speed >= HCD_USB3) | ||
993 | status |= USB_SS_PORT_STAT_POWER; | ||
994 | else | ||
995 | status |= USB_PORT_STAT_POWER; | ||
996 | } | ||
997 | /* Update Port Link State */ | ||
998 | if (hcd->speed >= HCD_USB3) { | ||
999 | xhci_hub_report_usb3_link_state(xhci, &status, raw_port_status); | ||
1000 | /* | ||
1001 | * Verify if all USB3 Ports Have entered U0 already. | ||
1002 | * Delete Compliance Mode Timer if so. | ||
1003 | */ | ||
1004 | xhci_del_comp_mod_timer(xhci, raw_port_status, wIndex); | ||
1005 | } else { | ||
1006 | xhci_hub_report_usb2_link_state(&status, raw_port_status); | ||
1007 | } | ||
1008 | if (bus_state->port_c_suspend & (1 << wIndex)) | 1052 | if (bus_state->port_c_suspend & (1 << wIndex)) |
1009 | status |= USB_PORT_STAT_C_SUSPEND << 16; | 1053 | status |= USB_PORT_STAT_C_SUSPEND << 16; |
1010 | 1054 | ||
@@ -1031,7 +1075,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
1031 | rhub = xhci_get_rhub(hcd); | 1075 | rhub = xhci_get_rhub(hcd); |
1032 | ports = rhub->ports; | 1076 | ports = rhub->ports; |
1033 | max_ports = rhub->num_ports; | 1077 | max_ports = rhub->num_ports; |
1034 | bus_state = &xhci->bus_state[hcd_index(hcd)]; | 1078 | bus_state = &rhub->bus_state; |
1035 | 1079 | ||
1036 | spin_lock_irqsave(&xhci->lock, flags); | 1080 | spin_lock_irqsave(&xhci->lock, flags); |
1037 | switch (typeReq) { | 1081 | switch (typeReq) { |
@@ -1421,7 +1465,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) | |||
1421 | rhub = xhci_get_rhub(hcd); | 1465 | rhub = xhci_get_rhub(hcd); |
1422 | ports = rhub->ports; | 1466 | ports = rhub->ports; |
1423 | max_ports = rhub->num_ports; | 1467 | max_ports = rhub->num_ports; |
1424 | bus_state = &xhci->bus_state[hcd_index(hcd)]; | 1468 | bus_state = &rhub->bus_state; |
1425 | 1469 | ||
1426 | /* Initial status is no changes */ | 1470 | /* Initial status is no changes */ |
1427 | retval = (max_ports + 8) / 8; | 1471 | retval = (max_ports + 8) / 8; |
@@ -1480,7 +1524,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd) | |||
1480 | rhub = xhci_get_rhub(hcd); | 1524 | rhub = xhci_get_rhub(hcd); |
1481 | ports = rhub->ports; | 1525 | ports = rhub->ports; |
1482 | max_ports = rhub->num_ports; | 1526 | max_ports = rhub->num_ports; |
1483 | bus_state = &xhci->bus_state[hcd_index(hcd)]; | 1527 | bus_state = &rhub->bus_state; |
1484 | wake_enabled = hcd->self.root_hub->do_remote_wakeup; | 1528 | wake_enabled = hcd->self.root_hub->do_remote_wakeup; |
1485 | 1529 | ||
1486 | spin_lock_irqsave(&xhci->lock, flags); | 1530 | spin_lock_irqsave(&xhci->lock, flags); |
@@ -1623,7 +1667,7 @@ int xhci_bus_resume(struct usb_hcd *hcd) | |||
1623 | rhub = xhci_get_rhub(hcd); | 1667 | rhub = xhci_get_rhub(hcd); |
1624 | ports = rhub->ports; | 1668 | ports = rhub->ports; |
1625 | max_ports = rhub->num_ports; | 1669 | max_ports = rhub->num_ports; |
1626 | bus_state = &xhci->bus_state[hcd_index(hcd)]; | 1670 | bus_state = &rhub->bus_state; |
1627 | 1671 | ||
1628 | if (time_before(jiffies, bus_state->next_statechange)) | 1672 | if (time_before(jiffies, bus_state->next_statechange)) |
1629 | msleep(5); | 1673 | msleep(5); |
@@ -1724,13 +1768,10 @@ int xhci_bus_resume(struct usb_hcd *hcd) | |||
1724 | 1768 | ||
1725 | unsigned long xhci_get_resuming_ports(struct usb_hcd *hcd) | 1769 | unsigned long xhci_get_resuming_ports(struct usb_hcd *hcd) |
1726 | { | 1770 | { |
1727 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 1771 | struct xhci_hub *rhub = xhci_get_rhub(hcd); |
1728 | struct xhci_bus_state *bus_state; | ||
1729 | |||
1730 | bus_state = &xhci->bus_state[hcd_index(hcd)]; | ||
1731 | 1772 | ||
1732 | /* USB3 port wakeups are reported via usb_wakeup_notification() */ | 1773 | /* USB3 port wakeups are reported via usb_wakeup_notification() */ |
1733 | return bus_state->resuming_ports; /* USB2 ports only */ | 1774 | return rhub->bus_state.resuming_ports; /* USB2 ports only */ |
1734 | } | 1775 | } |
1735 | 1776 | ||
1736 | #endif /* CONFIG_PM */ | 1777 | #endif /* CONFIG_PM */ |
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index b1f27aa38b10..36a3eb8849f1 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c | |||
@@ -1922,8 +1922,8 @@ no_bw: | |||
1922 | 1922 | ||
1923 | xhci->page_size = 0; | 1923 | xhci->page_size = 0; |
1924 | xhci->page_shift = 0; | 1924 | xhci->page_shift = 0; |
1925 | xhci->bus_state[0].bus_suspended = 0; | 1925 | xhci->usb2_rhub.bus_state.bus_suspended = 0; |
1926 | xhci->bus_state[1].bus_suspended = 0; | 1926 | xhci->usb3_rhub.bus_state.bus_suspended = 0; |
1927 | } | 1927 | } |
1928 | 1928 | ||
1929 | static int xhci_test_trb_in_td(struct xhci_hcd *xhci, | 1929 | static int xhci_test_trb_in_td(struct xhci_hcd *xhci, |
@@ -2181,23 +2181,11 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, | |||
2181 | if (major_revision < 0x03 && xhci->num_ext_caps < max_caps) | 2181 | if (major_revision < 0x03 && xhci->num_ext_caps < max_caps) |
2182 | xhci->ext_caps[xhci->num_ext_caps++] = temp; | 2182 | xhci->ext_caps[xhci->num_ext_caps++] = temp; |
2183 | 2183 | ||
2184 | /* Check the host's USB2 LPM capability */ | 2184 | if ((xhci->hci_version >= 0x100) && (major_revision != 0x03) && |
2185 | if ((xhci->hci_version == 0x96) && (major_revision != 0x03) && | 2185 | (temp & XHCI_HLC)) { |
2186 | (temp & XHCI_L1C)) { | ||
2187 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, | 2186 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, |
2188 | "xHCI 0.96: support USB2 software lpm"); | 2187 | "xHCI 1.0: support USB2 hardware lpm"); |
2189 | xhci->sw_lpm_support = 1; | 2188 | xhci->hw_lpm_support = 1; |
2190 | } | ||
2191 | |||
2192 | if ((xhci->hci_version >= 0x100) && (major_revision != 0x03)) { | ||
2193 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, | ||
2194 | "xHCI 1.0: support USB2 software lpm"); | ||
2195 | xhci->sw_lpm_support = 1; | ||
2196 | if (temp & XHCI_HLC) { | ||
2197 | xhci_dbg_trace(xhci, trace_xhci_dbg_init, | ||
2198 | "xHCI 1.0: support USB2 hardware lpm"); | ||
2199 | xhci->hw_lpm_support = 1; | ||
2200 | } | ||
2201 | } | 2189 | } |
2202 | 2190 | ||
2203 | port_offset--; | 2191 | port_offset--; |
@@ -2536,10 +2524,10 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) | |||
2536 | for (i = 0; i < MAX_HC_SLOTS; i++) | 2524 | for (i = 0; i < MAX_HC_SLOTS; i++) |
2537 | xhci->devs[i] = NULL; | 2525 | xhci->devs[i] = NULL; |
2538 | for (i = 0; i < USB_MAXCHILDREN; i++) { | 2526 | for (i = 0; i < USB_MAXCHILDREN; i++) { |
2539 | xhci->bus_state[0].resume_done[i] = 0; | 2527 | xhci->usb2_rhub.bus_state.resume_done[i] = 0; |
2540 | xhci->bus_state[1].resume_done[i] = 0; | 2528 | xhci->usb3_rhub.bus_state.resume_done[i] = 0; |
2541 | /* Only the USB 2.0 completions will ever be used. */ | 2529 | /* Only the USB 2.0 completions will ever be used. */ |
2542 | init_completion(&xhci->bus_state[1].rexit_done[i]); | 2530 | init_completion(&xhci->usb2_rhub.bus_state.rexit_done[i]); |
2543 | } | 2531 | } |
2544 | 2532 | ||
2545 | if (scratchpad_alloc(xhci, flags)) | 2533 | if (scratchpad_alloc(xhci, flags)) |
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 65750582133f..40fa25c4d041 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c | |||
@@ -1593,7 +1593,7 @@ static void handle_port_status(struct xhci_hcd *xhci, | |||
1593 | } | 1593 | } |
1594 | 1594 | ||
1595 | hcd = port->rhub->hcd; | 1595 | hcd = port->rhub->hcd; |
1596 | bus_state = &xhci->bus_state[hcd_index(hcd)]; | 1596 | bus_state = &port->rhub->bus_state; |
1597 | hcd_portnum = port->hcd_portnum; | 1597 | hcd_portnum = port->hcd_portnum; |
1598 | portsc = readl(port->addr); | 1598 | portsc = readl(port->addr); |
1599 | 1599 | ||
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index dae3be1b9c8f..46ab9c041091 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c | |||
@@ -169,7 +169,7 @@ int xhci_reset(struct xhci_hcd *xhci) | |||
169 | { | 169 | { |
170 | u32 command; | 170 | u32 command; |
171 | u32 state; | 171 | u32 state; |
172 | int ret, i; | 172 | int ret; |
173 | 173 | ||
174 | state = readl(&xhci->op_regs->status); | 174 | state = readl(&xhci->op_regs->status); |
175 | 175 | ||
@@ -215,11 +215,12 @@ int xhci_reset(struct xhci_hcd *xhci) | |||
215 | ret = xhci_handshake(&xhci->op_regs->status, | 215 | ret = xhci_handshake(&xhci->op_regs->status, |
216 | STS_CNR, 0, 10 * 1000 * 1000); | 216 | STS_CNR, 0, 10 * 1000 * 1000); |
217 | 217 | ||
218 | for (i = 0; i < 2; i++) { | 218 | xhci->usb2_rhub.bus_state.port_c_suspend = 0; |
219 | xhci->bus_state[i].port_c_suspend = 0; | 219 | xhci->usb2_rhub.bus_state.suspended_ports = 0; |
220 | xhci->bus_state[i].suspended_ports = 0; | 220 | xhci->usb2_rhub.bus_state.resuming_ports = 0; |
221 | xhci->bus_state[i].resuming_ports = 0; | 221 | xhci->usb3_rhub.bus_state.port_c_suspend = 0; |
222 | } | 222 | xhci->usb3_rhub.bus_state.suspended_ports = 0; |
223 | xhci->usb3_rhub.bus_state.resuming_ports = 0; | ||
223 | 224 | ||
224 | return ret; | 225 | return ret; |
225 | } | 226 | } |
@@ -1087,9 +1088,9 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) | |||
1087 | /* Wait a bit if either of the roothubs need to settle from the | 1088 | /* Wait a bit if either of the roothubs need to settle from the |
1088 | * transition into bus suspend. | 1089 | * transition into bus suspend. |
1089 | */ | 1090 | */ |
1090 | if (time_before(jiffies, xhci->bus_state[0].next_statechange) || | 1091 | |
1091 | time_before(jiffies, | 1092 | if (time_before(jiffies, xhci->usb2_rhub.bus_state.next_statechange) || |
1092 | xhci->bus_state[1].next_statechange)) | 1093 | time_before(jiffies, xhci->usb3_rhub.bus_state.next_statechange)) |
1093 | msleep(100); | 1094 | msleep(100); |
1094 | 1095 | ||
1095 | set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | 1096 | set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); |
@@ -4388,8 +4389,7 @@ static int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev) | |||
4388 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 4389 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
4389 | int portnum = udev->portnum - 1; | 4390 | int portnum = udev->portnum - 1; |
4390 | 4391 | ||
4391 | if (hcd->speed >= HCD_USB3 || !xhci->sw_lpm_support || | 4392 | if (hcd->speed >= HCD_USB3 || !udev->lpm_capable) |
4392 | !udev->lpm_capable) | ||
4393 | return 0; | 4393 | return 0; |
4394 | 4394 | ||
4395 | /* we only support lpm for non-hub device connected to root hub yet */ | 4395 | /* we only support lpm for non-hub device connected to root hub yet */ |
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 011dd45f8718..652dc36e3012 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h | |||
@@ -1682,13 +1682,6 @@ struct xhci_bus_state { | |||
1682 | */ | 1682 | */ |
1683 | #define XHCI_MAX_REXIT_TIMEOUT_MS 20 | 1683 | #define XHCI_MAX_REXIT_TIMEOUT_MS 20 |
1684 | 1684 | ||
1685 | static inline unsigned int hcd_index(struct usb_hcd *hcd) | ||
1686 | { | ||
1687 | if (hcd->speed >= HCD_USB3) | ||
1688 | return 0; | ||
1689 | else | ||
1690 | return 1; | ||
1691 | } | ||
1692 | struct xhci_port { | 1685 | struct xhci_port { |
1693 | __le32 __iomem *addr; | 1686 | __le32 __iomem *addr; |
1694 | int hw_portnum; | 1687 | int hw_portnum; |
@@ -1700,6 +1693,8 @@ struct xhci_hub { | |||
1700 | struct xhci_port **ports; | 1693 | struct xhci_port **ports; |
1701 | unsigned int num_ports; | 1694 | unsigned int num_ports; |
1702 | struct usb_hcd *hcd; | 1695 | struct usb_hcd *hcd; |
1696 | /* keep track of bus suspend info */ | ||
1697 | struct xhci_bus_state bus_state; | ||
1703 | /* supported prococol extended capabiliy values */ | 1698 | /* supported prococol extended capabiliy values */ |
1704 | u8 maj_rev; | 1699 | u8 maj_rev; |
1705 | u8 min_rev; | 1700 | u8 min_rev; |
@@ -1854,13 +1849,9 @@ struct xhci_hcd { | |||
1854 | 1849 | ||
1855 | unsigned int num_active_eps; | 1850 | unsigned int num_active_eps; |
1856 | unsigned int limit_active_eps; | 1851 | unsigned int limit_active_eps; |
1857 | /* There are two roothubs to keep track of bus suspend info for */ | ||
1858 | struct xhci_bus_state bus_state[2]; | ||
1859 | struct xhci_port *hw_ports; | 1852 | struct xhci_port *hw_ports; |
1860 | struct xhci_hub usb2_rhub; | 1853 | struct xhci_hub usb2_rhub; |
1861 | struct xhci_hub usb3_rhub; | 1854 | struct xhci_hub usb3_rhub; |
1862 | /* support xHCI 0.96 spec USB2 software LPM */ | ||
1863 | unsigned sw_lpm_support:1; | ||
1864 | /* support xHCI 1.0 spec USB2 hardware LPM */ | 1855 | /* support xHCI 1.0 spec USB2 hardware LPM */ |
1865 | unsigned hw_lpm_support:1; | 1856 | unsigned hw_lpm_support:1; |
1866 | /* Broken Suspend flag for SNPS Suspend resume issue */ | 1857 | /* Broken Suspend flag for SNPS Suspend resume issue */ |
diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c index 39ca31b4de46..ac92725458b5 100644 --- a/drivers/usb/misc/appledisplay.c +++ b/drivers/usb/misc/appledisplay.c | |||
@@ -69,7 +69,6 @@ struct appledisplay { | |||
69 | 69 | ||
70 | struct delayed_work work; | 70 | struct delayed_work work; |
71 | int button_pressed; | 71 | int button_pressed; |
72 | spinlock_t lock; | ||
73 | struct mutex sysfslock; /* concurrent read and write */ | 72 | struct mutex sysfslock; /* concurrent read and write */ |
74 | }; | 73 | }; |
75 | 74 | ||
@@ -79,7 +78,6 @@ static void appledisplay_complete(struct urb *urb) | |||
79 | { | 78 | { |
80 | struct appledisplay *pdata = urb->context; | 79 | struct appledisplay *pdata = urb->context; |
81 | struct device *dev = &pdata->udev->dev; | 80 | struct device *dev = &pdata->udev->dev; |
82 | unsigned long flags; | ||
83 | int status = urb->status; | 81 | int status = urb->status; |
84 | int retval; | 82 | int retval; |
85 | 83 | ||
@@ -105,8 +103,6 @@ static void appledisplay_complete(struct urb *urb) | |||
105 | goto exit; | 103 | goto exit; |
106 | } | 104 | } |
107 | 105 | ||
108 | spin_lock_irqsave(&pdata->lock, flags); | ||
109 | |||
110 | switch(pdata->urbdata[1]) { | 106 | switch(pdata->urbdata[1]) { |
111 | case ACD_BTN_BRIGHT_UP: | 107 | case ACD_BTN_BRIGHT_UP: |
112 | case ACD_BTN_BRIGHT_DOWN: | 108 | case ACD_BTN_BRIGHT_DOWN: |
@@ -119,8 +115,6 @@ static void appledisplay_complete(struct urb *urb) | |||
119 | break; | 115 | break; |
120 | } | 116 | } |
121 | 117 | ||
122 | spin_unlock_irqrestore(&pdata->lock, flags); | ||
123 | |||
124 | exit: | 118 | exit: |
125 | retval = usb_submit_urb(pdata->urb, GFP_ATOMIC); | 119 | retval = usb_submit_urb(pdata->urb, GFP_ATOMIC); |
126 | if (retval) { | 120 | if (retval) { |
@@ -229,7 +223,6 @@ static int appledisplay_probe(struct usb_interface *iface, | |||
229 | 223 | ||
230 | pdata->udev = udev; | 224 | pdata->udev = udev; |
231 | 225 | ||
232 | spin_lock_init(&pdata->lock); | ||
233 | INIT_DELAYED_WORK(&pdata->work, appledisplay_work); | 226 | INIT_DELAYED_WORK(&pdata->work, appledisplay_work); |
234 | mutex_init(&pdata->sysfslock); | 227 | mutex_init(&pdata->sysfslock); |
235 | 228 | ||
@@ -261,6 +254,7 @@ static int appledisplay_probe(struct usb_interface *iface, | |||
261 | usb_rcvintpipe(udev, int_in_endpointAddr), | 254 | usb_rcvintpipe(udev, int_in_endpointAddr), |
262 | pdata->urbdata, ACD_URB_BUFFER_LEN, appledisplay_complete, | 255 | pdata->urbdata, ACD_URB_BUFFER_LEN, appledisplay_complete, |
263 | pdata, 1); | 256 | pdata, 1); |
257 | pdata->urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; | ||
264 | if (usb_submit_urb(pdata->urb, GFP_KERNEL)) { | 258 | if (usb_submit_urb(pdata->urb, GFP_KERNEL)) { |
265 | retval = -EIO; | 259 | retval = -EIO; |
266 | dev_err(&iface->dev, "Submitting URB failed\n"); | 260 | dev_err(&iface->dev, "Submitting URB failed\n"); |
diff --git a/drivers/usb/mtu3/mtu3_core.c b/drivers/usb/mtu3/mtu3_core.c index ae70b9bfd797..4fee200795a5 100644 --- a/drivers/usb/mtu3/mtu3_core.c +++ b/drivers/usb/mtu3/mtu3_core.c | |||
@@ -180,7 +180,7 @@ static void mtu3_intr_enable(struct mtu3 *mtu) | |||
180 | mtu3_writel(mbase, U3D_LV1IESR, value); | 180 | mtu3_writel(mbase, U3D_LV1IESR, value); |
181 | 181 | ||
182 | /* Enable U2 common USB interrupts */ | 182 | /* Enable U2 common USB interrupts */ |
183 | value = SUSPEND_INTR | RESUME_INTR | RESET_INTR | LPM_RESUME_INTR; | 183 | value = SUSPEND_INTR | RESUME_INTR | RESET_INTR; |
184 | mtu3_writel(mbase, U3D_COMMON_USB_INTR_ENABLE, value); | 184 | mtu3_writel(mbase, U3D_COMMON_USB_INTR_ENABLE, value); |
185 | 185 | ||
186 | if (mtu->is_u3_ip) { | 186 | if (mtu->is_u3_ip) { |
@@ -484,7 +484,7 @@ void mtu3_ep0_setup(struct mtu3 *mtu) | |||
484 | mtu3_writel(mtu->mac_base, U3D_EP0CSR, csr); | 484 | mtu3_writel(mtu->mac_base, U3D_EP0CSR, csr); |
485 | 485 | ||
486 | /* Enable EP0 interrupt */ | 486 | /* Enable EP0 interrupt */ |
487 | mtu3_writel(mtu->mac_base, U3D_EPIESR, EP0ISR); | 487 | mtu3_writel(mtu->mac_base, U3D_EPIESR, EP0ISR | SETUPENDISR); |
488 | } | 488 | } |
489 | 489 | ||
490 | static int mtu3_mem_alloc(struct mtu3 *mtu) | 490 | static int mtu3_mem_alloc(struct mtu3 *mtu) |
@@ -578,12 +578,16 @@ static void mtu3_regs_init(struct mtu3 *mtu) | |||
578 | if (mtu->is_u3_ip) { | 578 | if (mtu->is_u3_ip) { |
579 | /* disable LGO_U1/U2 by default */ | 579 | /* disable LGO_U1/U2 by default */ |
580 | mtu3_clrbits(mbase, U3D_LINK_POWER_CONTROL, | 580 | mtu3_clrbits(mbase, U3D_LINK_POWER_CONTROL, |
581 | SW_U1_ACCEPT_ENABLE | SW_U2_ACCEPT_ENABLE | | ||
582 | SW_U1_REQUEST_ENABLE | SW_U2_REQUEST_ENABLE); | 581 | SW_U1_REQUEST_ENABLE | SW_U2_REQUEST_ENABLE); |
582 | /* enable accept LGO_U1/U2 link command from host */ | ||
583 | mtu3_setbits(mbase, U3D_LINK_POWER_CONTROL, | ||
584 | SW_U1_ACCEPT_ENABLE | SW_U2_ACCEPT_ENABLE); | ||
583 | /* device responses to u3_exit from host automatically */ | 585 | /* device responses to u3_exit from host automatically */ |
584 | mtu3_clrbits(mbase, U3D_LTSSM_CTRL, SOFT_U3_EXIT_EN); | 586 | mtu3_clrbits(mbase, U3D_LTSSM_CTRL, SOFT_U3_EXIT_EN); |
585 | /* automatically build U2 link when U3 detect fail */ | 587 | /* automatically build U2 link when U3 detect fail */ |
586 | mtu3_setbits(mbase, U3D_USB2_TEST_MODE, U2U3_AUTO_SWITCH); | 588 | mtu3_setbits(mbase, U3D_USB2_TEST_MODE, U2U3_AUTO_SWITCH); |
589 | /* auto clear SOFT_CONN when clear USB3_EN if work as HS */ | ||
590 | mtu3_setbits(mbase, U3D_U3U2_SWITCH_CTRL, SOFTCON_CLR_AUTO_EN); | ||
587 | } | 591 | } |
588 | 592 | ||
589 | mtu3_set_speed(mtu); | 593 | mtu3_set_speed(mtu); |
@@ -592,10 +596,10 @@ static void mtu3_regs_init(struct mtu3 *mtu) | |||
592 | mtu3_clrbits(mbase, U3D_LINK_RESET_INFO, WTCHRP_MSK); | 596 | mtu3_clrbits(mbase, U3D_LINK_RESET_INFO, WTCHRP_MSK); |
593 | /* U2/U3 detected by HW */ | 597 | /* U2/U3 detected by HW */ |
594 | mtu3_writel(mbase, U3D_DEVICE_CONF, 0); | 598 | mtu3_writel(mbase, U3D_DEVICE_CONF, 0); |
595 | /* enable QMU 16B checksum */ | ||
596 | mtu3_setbits(mbase, U3D_QCR0, QMU_CS16B_EN); | ||
597 | /* vbus detected by HW */ | 599 | /* vbus detected by HW */ |
598 | mtu3_clrbits(mbase, U3D_MISC_CTRL, VBUS_FRC_EN | VBUS_ON); | 600 | mtu3_clrbits(mbase, U3D_MISC_CTRL, VBUS_FRC_EN | VBUS_ON); |
601 | /* enable automatical HWRW from L1 */ | ||
602 | mtu3_setbits(mbase, U3D_POWER_MANAGEMENT, LPM_HRWE); | ||
599 | } | 603 | } |
600 | 604 | ||
601 | static irqreturn_t mtu3_link_isr(struct mtu3 *mtu) | 605 | static irqreturn_t mtu3_link_isr(struct mtu3 *mtu) |
@@ -708,12 +712,6 @@ static irqreturn_t mtu3_u2_common_isr(struct mtu3 *mtu) | |||
708 | if (u2comm & RESET_INTR) | 712 | if (u2comm & RESET_INTR) |
709 | mtu3_gadget_reset(mtu); | 713 | mtu3_gadget_reset(mtu); |
710 | 714 | ||
711 | if (u2comm & LPM_RESUME_INTR) { | ||
712 | if (!(mtu3_readl(mbase, U3D_POWER_MANAGEMENT) & LPM_HRWE)) | ||
713 | mtu3_setbits(mbase, U3D_USB20_MISC_CONTROL, | ||
714 | LPM_U3_ACK_EN); | ||
715 | } | ||
716 | |||
717 | return IRQ_HANDLED; | 715 | return IRQ_HANDLED; |
718 | } | 716 | } |
719 | 717 | ||
diff --git a/drivers/usb/mtu3/mtu3_gadget_ep0.c b/drivers/usb/mtu3/mtu3_gadget_ep0.c index 25216e79cd6e..7cb7ac980446 100644 --- a/drivers/usb/mtu3/mtu3_gadget_ep0.c +++ b/drivers/usb/mtu3/mtu3_gadget_ep0.c | |||
@@ -336,9 +336,9 @@ static int ep0_handle_feature_dev(struct mtu3 *mtu, | |||
336 | 336 | ||
337 | lpc = mtu3_readl(mbase, U3D_LINK_POWER_CONTROL); | 337 | lpc = mtu3_readl(mbase, U3D_LINK_POWER_CONTROL); |
338 | if (set) | 338 | if (set) |
339 | lpc |= SW_U1_ACCEPT_ENABLE; | 339 | lpc |= SW_U1_REQUEST_ENABLE; |
340 | else | 340 | else |
341 | lpc &= ~SW_U1_ACCEPT_ENABLE; | 341 | lpc &= ~SW_U1_REQUEST_ENABLE; |
342 | mtu3_writel(mbase, U3D_LINK_POWER_CONTROL, lpc); | 342 | mtu3_writel(mbase, U3D_LINK_POWER_CONTROL, lpc); |
343 | 343 | ||
344 | mtu->u1_enable = !!set; | 344 | mtu->u1_enable = !!set; |
@@ -351,9 +351,9 @@ static int ep0_handle_feature_dev(struct mtu3 *mtu, | |||
351 | 351 | ||
352 | lpc = mtu3_readl(mbase, U3D_LINK_POWER_CONTROL); | 352 | lpc = mtu3_readl(mbase, U3D_LINK_POWER_CONTROL); |
353 | if (set) | 353 | if (set) |
354 | lpc |= SW_U2_ACCEPT_ENABLE; | 354 | lpc |= SW_U2_REQUEST_ENABLE; |
355 | else | 355 | else |
356 | lpc &= ~SW_U2_ACCEPT_ENABLE; | 356 | lpc &= ~SW_U2_REQUEST_ENABLE; |
357 | mtu3_writel(mbase, U3D_LINK_POWER_CONTROL, lpc); | 357 | mtu3_writel(mbase, U3D_LINK_POWER_CONTROL, lpc); |
358 | 358 | ||
359 | mtu->u2_enable = !!set; | 359 | mtu->u2_enable = !!set; |
@@ -692,9 +692,13 @@ irqreturn_t mtu3_ep0_isr(struct mtu3 *mtu) | |||
692 | mtu3_writel(mbase, U3D_EPISR, int_status); /* W1C */ | 692 | mtu3_writel(mbase, U3D_EPISR, int_status); /* W1C */ |
693 | 693 | ||
694 | /* only handle ep0's */ | 694 | /* only handle ep0's */ |
695 | if (!(int_status & EP0ISR)) | 695 | if (!(int_status & (EP0ISR | SETUPENDISR))) |
696 | return IRQ_NONE; | 696 | return IRQ_NONE; |
697 | 697 | ||
698 | /* abort current SETUP, and process new one */ | ||
699 | if (int_status & SETUPENDISR) | ||
700 | mtu->ep0_state = MU3D_EP0_STATE_SETUP; | ||
701 | |||
698 | csr = mtu3_readl(mbase, U3D_EP0CSR); | 702 | csr = mtu3_readl(mbase, U3D_EP0CSR); |
699 | 703 | ||
700 | dev_dbg(mtu->dev, "%s csr=0x%x\n", __func__, csr); | 704 | dev_dbg(mtu->dev, "%s csr=0x%x\n", __func__, csr); |
diff --git a/drivers/usb/mtu3/mtu3_hw_regs.h b/drivers/usb/mtu3/mtu3_hw_regs.h index a45bb253939f..1d65b7476f23 100644 --- a/drivers/usb/mtu3/mtu3_hw_regs.h +++ b/drivers/usb/mtu3/mtu3_hw_regs.h | |||
@@ -104,6 +104,7 @@ | |||
104 | 104 | ||
105 | /* U3D_EPISR */ | 105 | /* U3D_EPISR */ |
106 | #define EPRISR(x) (BIT(16) << (x)) | 106 | #define EPRISR(x) (BIT(16) << (x)) |
107 | #define SETUPENDISR BIT(16) | ||
107 | #define EPTISR(x) (BIT(0) << (x)) | 108 | #define EPTISR(x) (BIT(0) << (x)) |
108 | #define EP0ISR BIT(0) | 109 | #define EP0ISR BIT(0) |
109 | 110 | ||
@@ -267,6 +268,8 @@ | |||
267 | #define U3D_LTSSM_INTR_ENABLE (SSUSB_USB3_MAC_CSR_BASE + 0x013C) | 268 | #define U3D_LTSSM_INTR_ENABLE (SSUSB_USB3_MAC_CSR_BASE + 0x013C) |
268 | #define U3D_LTSSM_INTR (SSUSB_USB3_MAC_CSR_BASE + 0x0140) | 269 | #define U3D_LTSSM_INTR (SSUSB_USB3_MAC_CSR_BASE + 0x0140) |
269 | 270 | ||
271 | #define U3D_U3U2_SWITCH_CTRL (SSUSB_USB3_MAC_CSR_BASE + 0x0170) | ||
272 | |||
270 | /*---------------- SSUSB_USB3_MAC_CSR FIELD DEFINITION ----------------*/ | 273 | /*---------------- SSUSB_USB3_MAC_CSR FIELD DEFINITION ----------------*/ |
271 | 274 | ||
272 | /* U3D_LTSSM_CTRL */ | 275 | /* U3D_LTSSM_CTRL */ |
@@ -301,6 +304,9 @@ | |||
301 | #define SS_DISABLE_INTR BIT(1) | 304 | #define SS_DISABLE_INTR BIT(1) |
302 | #define SS_INACTIVE_INTR BIT(0) | 305 | #define SS_INACTIVE_INTR BIT(0) |
303 | 306 | ||
307 | /* U3D_U3U2_SWITCH_CTRL */ | ||
308 | #define SOFTCON_CLR_AUTO_EN BIT(0) | ||
309 | |||
304 | /*---------------- SSUSB_USB3_SYS_CSR REGISTER DEFINITION ----------------*/ | 310 | /*---------------- SSUSB_USB3_SYS_CSR REGISTER DEFINITION ----------------*/ |
305 | 311 | ||
306 | #define U3D_LINK_UX_INACT_TIMER (SSUSB_USB3_SYS_CSR_BASE + 0x020C) | 312 | #define U3D_LINK_UX_INACT_TIMER (SSUSB_USB3_SYS_CSR_BASE + 0x020C) |
diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c index 46551f6d16fd..e086630e41a9 100644 --- a/drivers/usb/mtu3/mtu3_plat.c +++ b/drivers/usb/mtu3/mtu3_plat.c | |||
@@ -200,6 +200,14 @@ static void ssusb_ip_sw_reset(struct ssusb_mtk *ssusb) | |||
200 | mtu3_setbits(ssusb->ippc_base, U3D_SSUSB_IP_PW_CTRL0, SSUSB_IP_SW_RST); | 200 | mtu3_setbits(ssusb->ippc_base, U3D_SSUSB_IP_PW_CTRL0, SSUSB_IP_SW_RST); |
201 | udelay(1); | 201 | udelay(1); |
202 | mtu3_clrbits(ssusb->ippc_base, U3D_SSUSB_IP_PW_CTRL0, SSUSB_IP_SW_RST); | 202 | mtu3_clrbits(ssusb->ippc_base, U3D_SSUSB_IP_PW_CTRL0, SSUSB_IP_SW_RST); |
203 | |||
204 | /* | ||
205 | * device ip may be powered on in firmware/BROM stage before entering | ||
206 | * kernel stage; | ||
207 | * power down device ip, otherwise ip-sleep will fail when working as | ||
208 | * host only mode | ||
209 | */ | ||
210 | mtu3_setbits(ssusb->ippc_base, U3D_SSUSB_IP_PW_CTRL2, SSUSB_IP_DEV_PDN); | ||
203 | } | 211 | } |
204 | 212 | ||
205 | /* ignore the error if the clock does not exist */ | 213 | /* ignore the error if the clock does not exist */ |
diff --git a/drivers/usb/mtu3/mtu3_qmu.c b/drivers/usb/mtu3/mtu3_qmu.c index ff62ba232177..09f19f70fe8f 100644 --- a/drivers/usb/mtu3/mtu3_qmu.c +++ b/drivers/usb/mtu3/mtu3_qmu.c | |||
@@ -154,27 +154,6 @@ void mtu3_gpd_ring_free(struct mtu3_ep *mep) | |||
154 | memset(ring, 0, sizeof(*ring)); | 154 | memset(ring, 0, sizeof(*ring)); |
155 | } | 155 | } |
156 | 156 | ||
157 | /* | ||
158 | * calculate check sum of a gpd or bd | ||
159 | * add "noinline" and "mb" to prevent wrong calculation | ||
160 | */ | ||
161 | static noinline u8 qmu_calc_checksum(u8 *data) | ||
162 | { | ||
163 | u8 chksum = 0; | ||
164 | int i; | ||
165 | |||
166 | data[1] = 0x0; /* set checksum to 0 */ | ||
167 | |||
168 | mb(); /* ensure the gpd/bd is really up-to-date */ | ||
169 | for (i = 0; i < QMU_CHECKSUM_LEN; i++) | ||
170 | chksum += data[i]; | ||
171 | |||
172 | /* Default: HWO=1, @flag[bit0] */ | ||
173 | chksum += 1; | ||
174 | |||
175 | return 0xFF - chksum; | ||
176 | } | ||
177 | |||
178 | void mtu3_qmu_resume(struct mtu3_ep *mep) | 157 | void mtu3_qmu_resume(struct mtu3_ep *mep) |
179 | { | 158 | { |
180 | struct mtu3 *mtu = mep->mtu; | 159 | struct mtu3 *mtu = mep->mtu; |
@@ -260,7 +239,6 @@ static int mtu3_prepare_tx_gpd(struct mtu3_ep *mep, struct mtu3_request *mreq) | |||
260 | if (req->zero) | 239 | if (req->zero) |
261 | gpd->ext_flag |= GPD_EXT_FLAG_ZLP; | 240 | gpd->ext_flag |= GPD_EXT_FLAG_ZLP; |
262 | 241 | ||
263 | gpd->chksum = qmu_calc_checksum((u8 *)gpd); | ||
264 | gpd->flag |= GPD_FLAGS_HWO; | 242 | gpd->flag |= GPD_FLAGS_HWO; |
265 | 243 | ||
266 | mreq->gpd = gpd; | 244 | mreq->gpd = gpd; |
@@ -295,7 +273,6 @@ static int mtu3_prepare_rx_gpd(struct mtu3_ep *mep, struct mtu3_request *mreq) | |||
295 | gpd->next_gpd = cpu_to_le32(lower_32_bits(enq_dma)); | 273 | gpd->next_gpd = cpu_to_le32(lower_32_bits(enq_dma)); |
296 | ext_addr |= GPD_EXT_NGP(upper_32_bits(enq_dma)); | 274 | ext_addr |= GPD_EXT_NGP(upper_32_bits(enq_dma)); |
297 | gpd->rx_ext_addr = cpu_to_le16(ext_addr); | 275 | gpd->rx_ext_addr = cpu_to_le16(ext_addr); |
298 | gpd->chksum = qmu_calc_checksum((u8 *)gpd); | ||
299 | gpd->flag |= GPD_FLAGS_HWO; | 276 | gpd->flag |= GPD_FLAGS_HWO; |
300 | 277 | ||
301 | mreq->gpd = gpd; | 278 | mreq->gpd = gpd; |
@@ -323,7 +300,6 @@ int mtu3_qmu_start(struct mtu3_ep *mep) | |||
323 | /* set QMU start address */ | 300 | /* set QMU start address */ |
324 | write_txq_start_addr(mbase, epnum, ring->dma); | 301 | write_txq_start_addr(mbase, epnum, ring->dma); |
325 | mtu3_setbits(mbase, MU3D_EP_TXCR0(epnum), TX_DMAREQEN); | 302 | mtu3_setbits(mbase, MU3D_EP_TXCR0(epnum), TX_DMAREQEN); |
326 | mtu3_setbits(mbase, U3D_QCR0, QMU_TX_CS_EN(epnum)); | ||
327 | /* send zero length packet according to ZLP flag in GPD */ | 303 | /* send zero length packet according to ZLP flag in GPD */ |
328 | mtu3_setbits(mbase, U3D_QCR1, QMU_TX_ZLP(epnum)); | 304 | mtu3_setbits(mbase, U3D_QCR1, QMU_TX_ZLP(epnum)); |
329 | mtu3_writel(mbase, U3D_TQERRIESR0, | 305 | mtu3_writel(mbase, U3D_TQERRIESR0, |
@@ -338,7 +314,6 @@ int mtu3_qmu_start(struct mtu3_ep *mep) | |||
338 | } else { | 314 | } else { |
339 | write_rxq_start_addr(mbase, epnum, ring->dma); | 315 | write_rxq_start_addr(mbase, epnum, ring->dma); |
340 | mtu3_setbits(mbase, MU3D_EP_RXCR0(epnum), RX_DMAREQEN); | 316 | mtu3_setbits(mbase, MU3D_EP_RXCR0(epnum), RX_DMAREQEN); |
341 | mtu3_setbits(mbase, U3D_QCR0, QMU_RX_CS_EN(epnum)); | ||
342 | /* don't expect ZLP */ | 317 | /* don't expect ZLP */ |
343 | mtu3_clrbits(mbase, U3D_QCR3, QMU_RX_ZLP(epnum)); | 318 | mtu3_clrbits(mbase, U3D_QCR3, QMU_RX_ZLP(epnum)); |
344 | /* move to next GPD when receive ZLP */ | 319 | /* move to next GPD when receive ZLP */ |
@@ -427,7 +402,7 @@ static void qmu_tx_zlp_error_handler(struct mtu3 *mtu, u8 epnum) | |||
427 | return; | 402 | return; |
428 | } | 403 | } |
429 | 404 | ||
430 | dev_dbg(mtu->dev, "%s send ZLP for req=%p\n", __func__, mreq); | 405 | dev_dbg(mtu->dev, "%s send ZLP for req=%p\n", __func__, req); |
431 | 406 | ||
432 | mtu3_clrbits(mbase, MU3D_EP_TXCR0(mep->epnum), TX_DMAREQEN); | 407 | mtu3_clrbits(mbase, MU3D_EP_TXCR0(mep->epnum), TX_DMAREQEN); |
433 | 408 | ||
@@ -441,7 +416,6 @@ static void qmu_tx_zlp_error_handler(struct mtu3 *mtu, u8 epnum) | |||
441 | 416 | ||
442 | /* by pass the current GDP */ | 417 | /* by pass the current GDP */ |
443 | gpd_current->flag |= GPD_FLAGS_BPS; | 418 | gpd_current->flag |= GPD_FLAGS_BPS; |
444 | gpd_current->chksum = qmu_calc_checksum((u8 *)gpd_current); | ||
445 | gpd_current->flag |= GPD_FLAGS_HWO; | 419 | gpd_current->flag |= GPD_FLAGS_HWO; |
446 | 420 | ||
447 | /*enable DMAREQEN, switch back to QMU mode */ | 421 | /*enable DMAREQEN, switch back to QMU mode */ |
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 23a0df79ef21..403eb97915f8 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c | |||
@@ -181,9 +181,11 @@ static void dsps_musb_enable(struct musb *musb) | |||
181 | 181 | ||
182 | musb_writel(reg_base, wrp->epintr_set, epmask); | 182 | musb_writel(reg_base, wrp->epintr_set, epmask); |
183 | musb_writel(reg_base, wrp->coreintr_set, coremask); | 183 | musb_writel(reg_base, wrp->coreintr_set, coremask); |
184 | /* start polling for ID change in dual-role idle mode */ | 184 | /* |
185 | if (musb->xceiv->otg->state == OTG_STATE_B_IDLE && | 185 | * start polling for runtime PM active and idle, |
186 | musb->port_mode == MUSB_OTG) | 186 | * and for ID change in dual-role idle mode. |
187 | */ | ||
188 | if (musb->xceiv->otg->state == OTG_STATE_B_IDLE) | ||
187 | dsps_mod_timer(glue, -1); | 189 | dsps_mod_timer(glue, -1); |
188 | } | 190 | } |
189 | 191 | ||
@@ -227,8 +229,13 @@ static int dsps_check_status(struct musb *musb, void *unused) | |||
227 | 229 | ||
228 | switch (musb->xceiv->otg->state) { | 230 | switch (musb->xceiv->otg->state) { |
229 | case OTG_STATE_A_WAIT_VRISE: | 231 | case OTG_STATE_A_WAIT_VRISE: |
230 | dsps_mod_timer_optional(glue); | 232 | if (musb->port_mode == MUSB_HOST) { |
231 | break; | 233 | musb->xceiv->otg->state = OTG_STATE_A_WAIT_BCON; |
234 | dsps_mod_timer_optional(glue); | ||
235 | break; | ||
236 | } | ||
237 | /* fall through */ | ||
238 | |||
232 | case OTG_STATE_A_WAIT_BCON: | 239 | case OTG_STATE_A_WAIT_BCON: |
233 | /* keep VBUS on for host-only mode */ | 240 | /* keep VBUS on for host-only mode */ |
234 | if (musb->port_mode == MUSB_HOST) { | 241 | if (musb->port_mode == MUSB_HOST) { |
@@ -249,6 +256,10 @@ static int dsps_check_status(struct musb *musb, void *unused) | |||
249 | musb->xceiv->otg->state = OTG_STATE_A_IDLE; | 256 | musb->xceiv->otg->state = OTG_STATE_A_IDLE; |
250 | MUSB_HST_MODE(musb); | 257 | MUSB_HST_MODE(musb); |
251 | } | 258 | } |
259 | |||
260 | if (musb->port_mode == MUSB_PERIPHERAL) | ||
261 | skip_session = 1; | ||
262 | |||
252 | if (!(devctl & MUSB_DEVCTL_SESSION) && !skip_session) | 263 | if (!(devctl & MUSB_DEVCTL_SESSION) && !skip_session) |
253 | musb_writeb(mregs, MUSB_DEVCTL, | 264 | musb_writeb(mregs, MUSB_DEVCTL, |
254 | MUSB_DEVCTL_SESSION); | 265 | MUSB_DEVCTL_SESSION); |
diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c index a3e1290d682d..249fbee97f3f 100644 --- a/drivers/usb/renesas_usbhs/common.c +++ b/drivers/usb/renesas_usbhs/common.c | |||
@@ -540,6 +540,10 @@ static int usbhsc_drvcllbck_notify_hotplug(struct platform_device *pdev) | |||
540 | */ | 540 | */ |
541 | static const struct of_device_id usbhs_of_match[] = { | 541 | static const struct of_device_id usbhs_of_match[] = { |
542 | { | 542 | { |
543 | .compatible = "renesas,usbhs-r8a774c0", | ||
544 | .data = (void *)USBHS_TYPE_RCAR_GEN3_WITH_PLL, | ||
545 | }, | ||
546 | { | ||
543 | .compatible = "renesas,usbhs-r8a7790", | 547 | .compatible = "renesas,usbhs-r8a7790", |
544 | .data = (void *)USBHS_TYPE_RCAR_GEN2, | 548 | .data = (void *)USBHS_TYPE_RCAR_GEN2, |
545 | }, | 549 | }, |
@@ -841,7 +845,7 @@ static int usbhs_remove(struct platform_device *pdev) | |||
841 | return 0; | 845 | return 0; |
842 | } | 846 | } |
843 | 847 | ||
844 | static int usbhsc_suspend(struct device *dev) | 848 | static __maybe_unused int usbhsc_suspend(struct device *dev) |
845 | { | 849 | { |
846 | struct usbhs_priv *priv = dev_get_drvdata(dev); | 850 | struct usbhs_priv *priv = dev_get_drvdata(dev); |
847 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); | 851 | struct usbhs_mod *mod = usbhs_mod_get_current(priv); |
@@ -857,7 +861,7 @@ static int usbhsc_suspend(struct device *dev) | |||
857 | return 0; | 861 | return 0; |
858 | } | 862 | } |
859 | 863 | ||
860 | static int usbhsc_resume(struct device *dev) | 864 | static __maybe_unused int usbhsc_resume(struct device *dev) |
861 | { | 865 | { |
862 | struct usbhs_priv *priv = dev_get_drvdata(dev); | 866 | struct usbhs_priv *priv = dev_get_drvdata(dev); |
863 | struct platform_device *pdev = usbhs_priv_to_pdev(priv); | 867 | struct platform_device *pdev = usbhs_priv_to_pdev(priv); |
@@ -874,24 +878,7 @@ static int usbhsc_resume(struct device *dev) | |||
874 | return 0; | 878 | return 0; |
875 | } | 879 | } |
876 | 880 | ||
877 | static int usbhsc_runtime_nop(struct device *dev) | 881 | static SIMPLE_DEV_PM_OPS(usbhsc_pm_ops, usbhsc_suspend, usbhsc_resume); |
878 | { | ||
879 | /* Runtime PM callback shared between ->runtime_suspend() | ||
880 | * and ->runtime_resume(). Simply returns success. | ||
881 | * | ||
882 | * This driver re-initializes all registers after | ||
883 | * pm_runtime_get_sync() anyway so there is no need | ||
884 | * to save and restore registers here. | ||
885 | */ | ||
886 | return 0; | ||
887 | } | ||
888 | |||
889 | static const struct dev_pm_ops usbhsc_pm_ops = { | ||
890 | .suspend = usbhsc_suspend, | ||
891 | .resume = usbhsc_resume, | ||
892 | .runtime_suspend = usbhsc_runtime_nop, | ||
893 | .runtime_resume = usbhsc_runtime_nop, | ||
894 | }; | ||
895 | 882 | ||
896 | static struct platform_driver renesas_usbhs_driver = { | 883 | static struct platform_driver renesas_usbhs_driver = { |
897 | .driver = { | 884 | .driver = { |
diff --git a/drivers/usb/roles/Kconfig b/drivers/usb/roles/Kconfig index f5a5e6f79f1b..e4194ac94510 100644 --- a/drivers/usb/roles/Kconfig +++ b/drivers/usb/roles/Kconfig | |||
@@ -1,3 +1,16 @@ | |||
1 | config USB_ROLE_SWITCH | ||
2 | tristate "USB Role Switch Support" | ||
3 | help | ||
4 | USB Role Switch is a device that can select the USB role - host or | ||
5 | device - for a USB port (connector). In most cases dual-role capable | ||
6 | USB controller will also represent the switch, but on some platforms | ||
7 | multiplexer/demultiplexer switch is used to route the data lines on | ||
8 | the USB connector between separate USB host and device controllers. | ||
9 | |||
10 | Say Y here if your USB connectors support both device and host roles. | ||
11 | To compile the driver as module, choose M here: the module will be | ||
12 | called roles.ko. | ||
13 | |||
1 | if USB_ROLE_SWITCH | 14 | if USB_ROLE_SWITCH |
2 | 15 | ||
3 | config USB_ROLES_INTEL_XHCI | 16 | config USB_ROLES_INTEL_XHCI |
diff --git a/drivers/usb/roles/Makefile b/drivers/usb/roles/Makefile index e44b179ba275..c02873206fc1 100644 --- a/drivers/usb/roles/Makefile +++ b/drivers/usb/roles/Makefile | |||
@@ -1 +1,3 @@ | |||
1 | obj-$(CONFIG_USB_ROLES_INTEL_XHCI) += intel-xhci-usb-role-switch.o | 1 | obj-$(CONFIG_USB_ROLE_SWITCH) += roles.o |
2 | roles-y := class.o | ||
3 | obj-$(CONFIG_USB_ROLES_INTEL_XHCI) += intel-xhci-usb-role-switch.o | ||
diff --git a/drivers/usb/common/roles.c b/drivers/usb/roles/class.c index 99116af07f1d..99116af07f1d 100644 --- a/drivers/usb/common/roles.c +++ b/drivers/usb/roles/class.c | |||
diff --git a/drivers/usb/serial/f81534.c b/drivers/usb/serial/f81534.c index 380933db34dd..2b39bda035c7 100644 --- a/drivers/usb/serial/f81534.c +++ b/drivers/usb/serial/f81534.c | |||
@@ -45,14 +45,17 @@ | |||
45 | #define F81534_CONFIG1_REG (0x09 + F81534_UART_BASE_ADDRESS) | 45 | #define F81534_CONFIG1_REG (0x09 + F81534_UART_BASE_ADDRESS) |
46 | 46 | ||
47 | #define F81534_DEF_CONF_ADDRESS_START 0x3000 | 47 | #define F81534_DEF_CONF_ADDRESS_START 0x3000 |
48 | #define F81534_DEF_CONF_SIZE 8 | 48 | #define F81534_DEF_CONF_SIZE 12 |
49 | 49 | ||
50 | #define F81534_CUSTOM_ADDRESS_START 0x2f00 | 50 | #define F81534_CUSTOM_ADDRESS_START 0x2f00 |
51 | #define F81534_CUSTOM_DATA_SIZE 0x10 | 51 | #define F81534_CUSTOM_DATA_SIZE 0x10 |
52 | #define F81534_CUSTOM_NO_CUSTOM_DATA 0xff | 52 | #define F81534_CUSTOM_NO_CUSTOM_DATA 0xff |
53 | #define F81534_CUSTOM_VALID_TOKEN 0xf0 | 53 | #define F81534_CUSTOM_VALID_TOKEN 0xf0 |
54 | #define F81534_CONF_OFFSET 1 | 54 | #define F81534_CONF_OFFSET 1 |
55 | #define F81534_CONF_GPIO_OFFSET 4 | 55 | #define F81534_CONF_INIT_GPIO_OFFSET 4 |
56 | #define F81534_CONF_WORK_GPIO_OFFSET 8 | ||
57 | #define F81534_CONF_GPIO_SHUTDOWN 7 | ||
58 | #define F81534_CONF_GPIO_RS232 1 | ||
56 | 59 | ||
57 | #define F81534_MAX_DATA_BLOCK 64 | 60 | #define F81534_MAX_DATA_BLOCK 64 |
58 | #define F81534_MAX_BUS_RETRY 20 | 61 | #define F81534_MAX_BUS_RETRY 20 |
@@ -1337,8 +1340,19 @@ static int f81534_set_port_output_pin(struct usb_serial_port *port) | |||
1337 | serial_priv = usb_get_serial_data(serial); | 1340 | serial_priv = usb_get_serial_data(serial); |
1338 | port_priv = usb_get_serial_port_data(port); | 1341 | port_priv = usb_get_serial_port_data(port); |
1339 | 1342 | ||
1340 | idx = F81534_CONF_GPIO_OFFSET + port_priv->phy_num; | 1343 | idx = F81534_CONF_INIT_GPIO_OFFSET + port_priv->phy_num; |
1341 | value = serial_priv->conf_data[idx]; | 1344 | value = serial_priv->conf_data[idx]; |
1345 | if (value >= F81534_CONF_GPIO_SHUTDOWN) { | ||
1346 | /* | ||
1347 | * Newer IC configure will make transceiver in shutdown mode on | ||
1348 | * initial power on. We need enable it before using UARTs. | ||
1349 | */ | ||
1350 | idx = F81534_CONF_WORK_GPIO_OFFSET + port_priv->phy_num; | ||
1351 | value = serial_priv->conf_data[idx]; | ||
1352 | if (value >= F81534_CONF_GPIO_SHUTDOWN) | ||
1353 | value = F81534_CONF_GPIO_RS232; | ||
1354 | } | ||
1355 | |||
1342 | pins = &f81534_port_out_pins[port_priv->phy_num]; | 1356 | pins = &f81534_port_out_pins[port_priv->phy_num]; |
1343 | 1357 | ||
1344 | for (i = 0; i < ARRAY_SIZE(pins->pin); ++i) { | 1358 | for (i = 0; i < ARRAY_SIZE(pins->pin); ++i) { |
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 609198d9594c..1ab2a6191013 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -1130,7 +1130,7 @@ static unsigned short int ftdi_232am_baud_base_to_divisor(int baud, int base) | |||
1130 | { | 1130 | { |
1131 | unsigned short int divisor; | 1131 | unsigned short int divisor; |
1132 | /* divisor shifted 3 bits to the left */ | 1132 | /* divisor shifted 3 bits to the left */ |
1133 | int divisor3 = base / 2 / baud; | 1133 | int divisor3 = DIV_ROUND_CLOSEST(base, 2 * baud); |
1134 | if ((divisor3 & 0x7) == 7) | 1134 | if ((divisor3 & 0x7) == 7) |
1135 | divisor3++; /* round x.7/8 up to x+1 */ | 1135 | divisor3++; /* round x.7/8 up to x+1 */ |
1136 | divisor = divisor3 >> 3; | 1136 | divisor = divisor3 >> 3; |
@@ -1156,7 +1156,7 @@ static u32 ftdi_232bm_baud_base_to_divisor(int baud, int base) | |||
1156 | static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 }; | 1156 | static const unsigned char divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7 }; |
1157 | u32 divisor; | 1157 | u32 divisor; |
1158 | /* divisor shifted 3 bits to the left */ | 1158 | /* divisor shifted 3 bits to the left */ |
1159 | int divisor3 = base / 2 / baud; | 1159 | int divisor3 = DIV_ROUND_CLOSEST(base, 2 * baud); |
1160 | divisor = divisor3 >> 3; | 1160 | divisor = divisor3 >> 3; |
1161 | divisor |= (u32)divfrac[divisor3 & 0x7] << 14; | 1161 | divisor |= (u32)divfrac[divisor3 & 0x7] << 14; |
1162 | /* Deal with special cases for highest baud rates. */ | 1162 | /* Deal with special cases for highest baud rates. */ |
@@ -1179,7 +1179,7 @@ static u32 ftdi_2232h_baud_base_to_divisor(int baud, int base) | |||
1179 | int divisor3; | 1179 | int divisor3; |
1180 | 1180 | ||
1181 | /* hi-speed baud rate is 10-bit sampling instead of 16-bit */ | 1181 | /* hi-speed baud rate is 10-bit sampling instead of 16-bit */ |
1182 | divisor3 = base * 8 / (baud * 10); | 1182 | divisor3 = DIV_ROUND_CLOSEST(8 * base, 10 * baud); |
1183 | 1183 | ||
1184 | divisor = divisor3 >> 3; | 1184 | divisor = divisor3 >> 3; |
1185 | divisor |= (u32)divfrac[divisor3 & 0x7] << 14; | 1185 | divisor |= (u32)divfrac[divisor3 & 0x7] << 14; |
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 88828b4b8c44..a698d46ba773 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c | |||
@@ -94,6 +94,7 @@ | |||
94 | /* The native mos7840/7820 component */ | 94 | /* The native mos7840/7820 component */ |
95 | #define USB_VENDOR_ID_MOSCHIP 0x9710 | 95 | #define USB_VENDOR_ID_MOSCHIP 0x9710 |
96 | #define MOSCHIP_DEVICE_ID_7840 0x7840 | 96 | #define MOSCHIP_DEVICE_ID_7840 0x7840 |
97 | #define MOSCHIP_DEVICE_ID_7843 0x7843 | ||
97 | #define MOSCHIP_DEVICE_ID_7820 0x7820 | 98 | #define MOSCHIP_DEVICE_ID_7820 0x7820 |
98 | #define MOSCHIP_DEVICE_ID_7810 0x7810 | 99 | #define MOSCHIP_DEVICE_ID_7810 0x7810 |
99 | /* The native component can have its vendor/device id's overridden | 100 | /* The native component can have its vendor/device id's overridden |
@@ -176,6 +177,7 @@ enum mos7840_flag { | |||
176 | 177 | ||
177 | static const struct usb_device_id id_table[] = { | 178 | static const struct usb_device_id id_table[] = { |
178 | {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)}, | 179 | {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)}, |
180 | {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7843)}, | ||
179 | {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)}, | 181 | {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)}, |
180 | {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7810)}, | 182 | {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7810)}, |
181 | {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)}, | 183 | {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)}, |
@@ -298,15 +300,10 @@ static int mos7840_set_uart_reg(struct usb_serial_port *port, __u16 reg, | |||
298 | val = val & 0x00ff; | 300 | val = val & 0x00ff; |
299 | /* For the UART control registers, the application number need | 301 | /* For the UART control registers, the application number need |
300 | to be Or'ed */ | 302 | to be Or'ed */ |
301 | if (port->serial->num_ports == 4) { | 303 | if (port->serial->num_ports == 2 && port->port_number != 0) |
304 | val |= ((__u16)port->port_number + 2) << 8; | ||
305 | else | ||
302 | val |= ((__u16)port->port_number + 1) << 8; | 306 | val |= ((__u16)port->port_number + 1) << 8; |
303 | } else { | ||
304 | if (port->port_number == 0) { | ||
305 | val |= ((__u16)port->port_number + 1) << 8; | ||
306 | } else { | ||
307 | val |= ((__u16)port->port_number + 2) << 8; | ||
308 | } | ||
309 | } | ||
310 | dev_dbg(&port->dev, "%s application number is %x\n", __func__, val); | 307 | dev_dbg(&port->dev, "%s application number is %x\n", __func__, val); |
311 | return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ, | 308 | return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ, |
312 | MCS_WR_RTYPE, val, reg, NULL, 0, | 309 | MCS_WR_RTYPE, val, reg, NULL, 0, |
@@ -332,15 +329,10 @@ static int mos7840_get_uart_reg(struct usb_serial_port *port, __u16 reg, | |||
332 | return -ENOMEM; | 329 | return -ENOMEM; |
333 | 330 | ||
334 | /* Wval is same as application number */ | 331 | /* Wval is same as application number */ |
335 | if (port->serial->num_ports == 4) { | 332 | if (port->serial->num_ports == 2 && port->port_number != 0) |
333 | Wval = ((__u16)port->port_number + 2) << 8; | ||
334 | else | ||
336 | Wval = ((__u16)port->port_number + 1) << 8; | 335 | Wval = ((__u16)port->port_number + 1) << 8; |
337 | } else { | ||
338 | if (port->port_number == 0) { | ||
339 | Wval = ((__u16)port->port_number + 1) << 8; | ||
340 | } else { | ||
341 | Wval = ((__u16)port->port_number + 2) << 8; | ||
342 | } | ||
343 | } | ||
344 | dev_dbg(&port->dev, "%s application number is %x\n", __func__, Wval); | 336 | dev_dbg(&port->dev, "%s application number is %x\n", __func__, Wval); |
345 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ, | 337 | ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ, |
346 | MCS_RD_RTYPE, Wval, reg, buf, VENDOR_READ_LENGTH, | 338 | MCS_RD_RTYPE, Wval, reg, buf, VENDOR_READ_LENGTH, |
@@ -601,7 +593,7 @@ static void mos7840_interrupt_callback(struct urb *urb) | |||
601 | struct usb_serial *serial; | 593 | struct usb_serial *serial; |
602 | __u16 Data; | 594 | __u16 Data; |
603 | unsigned char *data; | 595 | unsigned char *data; |
604 | __u8 sp[5], st; | 596 | __u8 sp[5]; |
605 | int i, rv = 0; | 597 | int i, rv = 0; |
606 | __u16 wval, wreg = 0; | 598 | __u16 wval, wreg = 0; |
607 | int status = urb->status; | 599 | int status = urb->status; |
@@ -644,7 +636,6 @@ static void mos7840_interrupt_callback(struct urb *urb) | |||
644 | sp[1] = (__u8) data[1]; | 636 | sp[1] = (__u8) data[1]; |
645 | sp[2] = (__u8) data[2]; | 637 | sp[2] = (__u8) data[2]; |
646 | sp[3] = (__u8) data[3]; | 638 | sp[3] = (__u8) data[3]; |
647 | st = (__u8) data[4]; | ||
648 | 639 | ||
649 | for (i = 0; i < serial->num_ports; i++) { | 640 | for (i = 0; i < serial->num_ports; i++) { |
650 | mos7840_port = mos7840_get_port_private(serial->port[i]); | 641 | mos7840_port = mos7840_get_port_private(serial->port[i]); |
@@ -1300,7 +1291,6 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
1300 | struct urb *urb; | 1291 | struct urb *urb; |
1301 | /* __u16 Data; */ | 1292 | /* __u16 Data; */ |
1302 | const unsigned char *current_position = data; | 1293 | const unsigned char *current_position = data; |
1303 | unsigned char *data1; | ||
1304 | 1294 | ||
1305 | if (mos7840_port_paranoia_check(port, __func__)) | 1295 | if (mos7840_port_paranoia_check(port, __func__)) |
1306 | return -1; | 1296 | return -1; |
@@ -1361,7 +1351,6 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
1361 | mos7840_bulk_out_data_callback, mos7840_port); | 1351 | mos7840_bulk_out_data_callback, mos7840_port); |
1362 | } | 1352 | } |
1363 | 1353 | ||
1364 | data1 = urb->transfer_buffer; | ||
1365 | dev_dbg(&port->dev, "bulkout endpoint is %d\n", port->bulk_out_endpointAddress); | 1354 | dev_dbg(&port->dev, "bulkout endpoint is %d\n", port->bulk_out_endpointAddress); |
1366 | 1355 | ||
1367 | if (mos7840_port->has_led) | 1356 | if (mos7840_port->has_led) |
@@ -1592,7 +1581,6 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port, | |||
1592 | int divisor = 0; | 1581 | int divisor = 0; |
1593 | int status; | 1582 | int status; |
1594 | __u16 Data; | 1583 | __u16 Data; |
1595 | unsigned char number; | ||
1596 | __u16 clk_sel_val; | 1584 | __u16 clk_sel_val; |
1597 | struct usb_serial_port *port; | 1585 | struct usb_serial_port *port; |
1598 | 1586 | ||
@@ -1606,8 +1594,6 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port, | |||
1606 | if (mos7840_serial_paranoia_check(port->serial, __func__)) | 1594 | if (mos7840_serial_paranoia_check(port->serial, __func__)) |
1607 | return -1; | 1595 | return -1; |
1608 | 1596 | ||
1609 | number = mos7840_port->port->port_number; | ||
1610 | |||
1611 | dev_dbg(&port->dev, "%s - baud = %d\n", __func__, baudRate); | 1597 | dev_dbg(&port->dev, "%s - baud = %d\n", __func__, baudRate); |
1612 | /* reset clk_uart_sel in spregOffset */ | 1598 | /* reset clk_uart_sel in spregOffset */ |
1613 | if (baudRate > 115200) { | 1599 | if (baudRate > 115200) { |
@@ -1697,14 +1683,12 @@ static void mos7840_change_port_settings(struct tty_struct *tty, | |||
1697 | { | 1683 | { |
1698 | int baud; | 1684 | int baud; |
1699 | unsigned cflag; | 1685 | unsigned cflag; |
1700 | unsigned iflag; | ||
1701 | __u8 lData; | 1686 | __u8 lData; |
1702 | __u8 lParity; | 1687 | __u8 lParity; |
1703 | __u8 lStop; | 1688 | __u8 lStop; |
1704 | int status; | 1689 | int status; |
1705 | __u16 Data; | 1690 | __u16 Data; |
1706 | struct usb_serial_port *port; | 1691 | struct usb_serial_port *port; |
1707 | struct usb_serial *serial; | ||
1708 | 1692 | ||
1709 | if (mos7840_port == NULL) | 1693 | if (mos7840_port == NULL) |
1710 | return; | 1694 | return; |
@@ -1717,8 +1701,6 @@ static void mos7840_change_port_settings(struct tty_struct *tty, | |||
1717 | if (mos7840_serial_paranoia_check(port->serial, __func__)) | 1701 | if (mos7840_serial_paranoia_check(port->serial, __func__)) |
1718 | return; | 1702 | return; |
1719 | 1703 | ||
1720 | serial = port->serial; | ||
1721 | |||
1722 | if (!mos7840_port->open) { | 1704 | if (!mos7840_port->open) { |
1723 | dev_dbg(&port->dev, "%s - port not opened\n", __func__); | 1705 | dev_dbg(&port->dev, "%s - port not opened\n", __func__); |
1724 | return; | 1706 | return; |
@@ -1729,7 +1711,6 @@ static void mos7840_change_port_settings(struct tty_struct *tty, | |||
1729 | lParity = LCR_PAR_NONE; | 1711 | lParity = LCR_PAR_NONE; |
1730 | 1712 | ||
1731 | cflag = tty->termios.c_cflag; | 1713 | cflag = tty->termios.c_cflag; |
1732 | iflag = tty->termios.c_iflag; | ||
1733 | 1714 | ||
1734 | /* Change the number of bits */ | 1715 | /* Change the number of bits */ |
1735 | switch (cflag & CSIZE) { | 1716 | switch (cflag & CSIZE) { |
@@ -2043,7 +2024,8 @@ static int mos7840_probe(struct usb_serial *serial, | |||
2043 | int device_type; | 2024 | int device_type; |
2044 | 2025 | ||
2045 | if (product == MOSCHIP_DEVICE_ID_7810 || | 2026 | if (product == MOSCHIP_DEVICE_ID_7810 || |
2046 | product == MOSCHIP_DEVICE_ID_7820) { | 2027 | product == MOSCHIP_DEVICE_ID_7820 || |
2028 | product == MOSCHIP_DEVICE_ID_7843) { | ||
2047 | device_type = product; | 2029 | device_type = product; |
2048 | goto out; | 2030 | goto out; |
2049 | } | 2031 | } |
@@ -2077,7 +2059,10 @@ static int mos7840_calc_num_ports(struct usb_serial *serial, | |||
2077 | int device_type = (unsigned long)usb_get_serial_data(serial); | 2059 | int device_type = (unsigned long)usb_get_serial_data(serial); |
2078 | int num_ports; | 2060 | int num_ports; |
2079 | 2061 | ||
2080 | num_ports = (device_type >> 4) & 0x000F; | 2062 | if (device_type == MOSCHIP_DEVICE_ID_7843) |
2063 | num_ports = 3; | ||
2064 | else | ||
2065 | num_ports = (device_type >> 4) & 0x000F; | ||
2081 | 2066 | ||
2082 | /* | 2067 | /* |
2083 | * num_ports is currently never zero as device_type is one of | 2068 | * num_ports is currently never zero as device_type is one of |
@@ -2132,22 +2117,16 @@ static int mos7840_port_probe(struct usb_serial_port *port) | |||
2132 | mos7840_port->SpRegOffset = 0x0; | 2117 | mos7840_port->SpRegOffset = 0x0; |
2133 | mos7840_port->ControlRegOffset = 0x1; | 2118 | mos7840_port->ControlRegOffset = 0x1; |
2134 | mos7840_port->DcrRegOffset = 0x4; | 2119 | mos7840_port->DcrRegOffset = 0x4; |
2135 | } else if ((mos7840_port->port_num == 2) && (serial->num_ports == 4)) { | 2120 | } else { |
2136 | mos7840_port->SpRegOffset = 0x8; | 2121 | u8 phy_num = mos7840_port->port_num; |
2137 | mos7840_port->ControlRegOffset = 0x9; | 2122 | |
2138 | mos7840_port->DcrRegOffset = 0x16; | 2123 | /* Port 2 in the 2-port case uses registers of port 3 */ |
2139 | } else if ((mos7840_port->port_num == 2) && (serial->num_ports == 2)) { | 2124 | if (serial->num_ports == 2) |
2140 | mos7840_port->SpRegOffset = 0xa; | 2125 | phy_num = 3; |
2141 | mos7840_port->ControlRegOffset = 0xb; | 2126 | |
2142 | mos7840_port->DcrRegOffset = 0x19; | 2127 | mos7840_port->SpRegOffset = 0x8 + 2 * (phy_num - 2); |
2143 | } else if ((mos7840_port->port_num == 3) && (serial->num_ports == 4)) { | 2128 | mos7840_port->ControlRegOffset = 0x9 + 2 * (phy_num - 2); |
2144 | mos7840_port->SpRegOffset = 0xa; | 2129 | mos7840_port->DcrRegOffset = 0x16 + 3 * (phy_num - 2); |
2145 | mos7840_port->ControlRegOffset = 0xb; | ||
2146 | mos7840_port->DcrRegOffset = 0x19; | ||
2147 | } else if ((mos7840_port->port_num == 4) && (serial->num_ports == 4)) { | ||
2148 | mos7840_port->SpRegOffset = 0xc; | ||
2149 | mos7840_port->ControlRegOffset = 0xd; | ||
2150 | mos7840_port->DcrRegOffset = 0x1c; | ||
2151 | } | 2130 | } |
2152 | mos7840_dump_serial_port(port, mos7840_port); | 2131 | mos7840_dump_serial_port(port, mos7840_port); |
2153 | mos7840_set_port_private(port, mos7840_port); | 2132 | mos7840_set_port_private(port, mos7840_port); |
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index a4e0d13fc121..98e7a5df0f6d 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c | |||
@@ -91,9 +91,14 @@ static const struct usb_device_id id_table[] = { | |||
91 | { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) }, | 91 | { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) }, |
92 | { USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) }, | 92 | { USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) }, |
93 | { USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) }, | 93 | { USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) }, |
94 | { USB_DEVICE(HP_VENDOR_ID, HP_LD220TA_PRODUCT_ID) }, | ||
94 | { USB_DEVICE(HP_VENDOR_ID, HP_LD960_PRODUCT_ID) }, | 95 | { USB_DEVICE(HP_VENDOR_ID, HP_LD960_PRODUCT_ID) }, |
96 | { USB_DEVICE(HP_VENDOR_ID, HP_LD960TA_PRODUCT_ID) }, | ||
95 | { USB_DEVICE(HP_VENDOR_ID, HP_LCM220_PRODUCT_ID) }, | 97 | { USB_DEVICE(HP_VENDOR_ID, HP_LCM220_PRODUCT_ID) }, |
96 | { USB_DEVICE(HP_VENDOR_ID, HP_LCM960_PRODUCT_ID) }, | 98 | { USB_DEVICE(HP_VENDOR_ID, HP_LCM960_PRODUCT_ID) }, |
99 | { USB_DEVICE(HP_VENDOR_ID, HP_LM920_PRODUCT_ID) }, | ||
100 | { USB_DEVICE(HP_VENDOR_ID, HP_LM940_PRODUCT_ID) }, | ||
101 | { USB_DEVICE(HP_VENDOR_ID, HP_TD620_PRODUCT_ID) }, | ||
97 | { USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) }, | 102 | { USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) }, |
98 | { USB_DEVICE(ZEAGLE_VENDOR_ID, ZEAGLE_N2ITION3_PRODUCT_ID) }, | 103 | { USB_DEVICE(ZEAGLE_VENDOR_ID, ZEAGLE_N2ITION3_PRODUCT_ID) }, |
99 | { USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) }, | 104 | { USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) }, |
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index 26965cc23c17..4e2554d55362 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h | |||
@@ -119,10 +119,15 @@ | |||
119 | 119 | ||
120 | /* Hewlett-Packard POS Pole Displays */ | 120 | /* Hewlett-Packard POS Pole Displays */ |
121 | #define HP_VENDOR_ID 0x03f0 | 121 | #define HP_VENDOR_ID 0x03f0 |
122 | #define HP_LM920_PRODUCT_ID 0x026b | ||
123 | #define HP_TD620_PRODUCT_ID 0x0956 | ||
122 | #define HP_LD960_PRODUCT_ID 0x0b39 | 124 | #define HP_LD960_PRODUCT_ID 0x0b39 |
123 | #define HP_LCM220_PRODUCT_ID 0x3139 | 125 | #define HP_LCM220_PRODUCT_ID 0x3139 |
124 | #define HP_LCM960_PRODUCT_ID 0x3239 | 126 | #define HP_LCM960_PRODUCT_ID 0x3239 |
125 | #define HP_LD220_PRODUCT_ID 0x3524 | 127 | #define HP_LD220_PRODUCT_ID 0x3524 |
128 | #define HP_LD220TA_PRODUCT_ID 0x4349 | ||
129 | #define HP_LD960TA_PRODUCT_ID 0x4439 | ||
130 | #define HP_LM940_PRODUCT_ID 0x5039 | ||
126 | 131 | ||
127 | /* Cressi Edy (diving computer) PC interface */ | 132 | /* Cressi Edy (diving computer) PC interface */ |
128 | #define CRESSI_VENDOR_ID 0x04b8 | 133 | #define CRESSI_VENDOR_ID 0x04b8 |
diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index f2fbe1ec9701..a62981ca7a73 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c | |||
@@ -500,7 +500,6 @@ static void qt2_process_read_urb(struct urb *urb) | |||
500 | struct usb_serial *serial; | 500 | struct usb_serial *serial; |
501 | struct qt2_serial_private *serial_priv; | 501 | struct qt2_serial_private *serial_priv; |
502 | struct usb_serial_port *port; | 502 | struct usb_serial_port *port; |
503 | struct qt2_port_private *port_priv; | ||
504 | bool escapeflag; | 503 | bool escapeflag; |
505 | unsigned char *ch; | 504 | unsigned char *ch; |
506 | int i; | 505 | int i; |
@@ -514,7 +513,6 @@ static void qt2_process_read_urb(struct urb *urb) | |||
514 | serial = urb->context; | 513 | serial = urb->context; |
515 | serial_priv = usb_get_serial_data(serial); | 514 | serial_priv = usb_get_serial_data(serial); |
516 | port = serial->port[serial_priv->current_port]; | 515 | port = serial->port[serial_priv->current_port]; |
517 | port_priv = usb_get_serial_port_data(port); | ||
518 | 516 | ||
519 | for (i = 0; i < urb->actual_length; i++) { | 517 | for (i = 0; i < urb->actual_length; i++) { |
520 | ch = (unsigned char *)urb->transfer_buffer + i; | 518 | ch = (unsigned char *)urb->transfer_buffer + i; |
@@ -566,7 +564,6 @@ static void qt2_process_read_urb(struct urb *urb) | |||
566 | 564 | ||
567 | serial_priv->current_port = newport; | 565 | serial_priv->current_port = newport; |
568 | port = serial->port[serial_priv->current_port]; | 566 | port = serial->port[serial_priv->current_port]; |
569 | port_priv = usb_get_serial_port_data(port); | ||
570 | i += 3; | 567 | i += 3; |
571 | escapeflag = true; | 568 | escapeflag = true; |
572 | break; | 569 | break; |
diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c index 4d261e4de9ad..c26129d5b943 100644 --- a/drivers/usb/storage/ene_ub6250.c +++ b/drivers/usb/storage/ene_ub6250.c | |||
@@ -1131,7 +1131,7 @@ static int ms_lib_alloc_writebuf(struct us_data *us) | |||
1131 | 1131 | ||
1132 | ms_lib_clear_writebuf(us); | 1132 | ms_lib_clear_writebuf(us); |
1133 | 1133 | ||
1134 | return 0; | 1134 | return 0; |
1135 | } | 1135 | } |
1136 | 1136 | ||
1137 | static int ms_lib_force_setlogical_pair(struct us_data *us, u16 logblk, u16 phyblk) | 1137 | static int ms_lib_force_setlogical_pair(struct us_data *us, u16 logblk, u16 phyblk) |
diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c index 43b64d9309d0..e9344997329c 100644 --- a/drivers/usb/typec/tcpm/fusb302.c +++ b/drivers/usb/typec/tcpm/fusb302.c | |||
@@ -1765,7 +1765,7 @@ static int fusb302_probe(struct i2c_client *client, | |||
1765 | * to be set by the platform code which also registers the i2c client | 1765 | * to be set by the platform code which also registers the i2c client |
1766 | * for the fusb302. | 1766 | * for the fusb302. |
1767 | */ | 1767 | */ |
1768 | if (device_property_read_string(dev, "fcs,extcon-name", &name) == 0) { | 1768 | if (device_property_read_string(dev, "linux,extcon-name", &name) == 0) { |
1769 | chip->extcon = extcon_get_extcon_dev(name); | 1769 | chip->extcon = extcon_get_extcon_dev(name); |
1770 | if (!chip->extcon) | 1770 | if (!chip->extcon) |
1771 | return -EPROBE_DEFER; | 1771 | return -EPROBE_DEFER; |
diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index dbbd71f754d0..4bc29b586698 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c | |||
@@ -317,6 +317,9 @@ struct tcpm_port { | |||
317 | /* Deadline in jiffies to exit src_try_wait state */ | 317 | /* Deadline in jiffies to exit src_try_wait state */ |
318 | unsigned long max_wait; | 318 | unsigned long max_wait; |
319 | 319 | ||
320 | /* port belongs to a self powered device */ | ||
321 | bool self_powered; | ||
322 | |||
320 | #ifdef CONFIG_DEBUG_FS | 323 | #ifdef CONFIG_DEBUG_FS |
321 | struct dentry *dentry; | 324 | struct dentry *dentry; |
322 | struct mutex logbuffer_lock; /* log buffer access lock */ | 325 | struct mutex logbuffer_lock; /* log buffer access lock */ |
@@ -2210,7 +2213,8 @@ static unsigned int tcpm_pd_select_pps_apdo(struct tcpm_port *port) | |||
2210 | unsigned int i, j, max_mw = 0, max_mv = 0; | 2213 | unsigned int i, j, max_mw = 0, max_mv = 0; |
2211 | unsigned int min_src_mv, max_src_mv, src_ma, src_mw; | 2214 | unsigned int min_src_mv, max_src_mv, src_ma, src_mw; |
2212 | unsigned int min_snk_mv, max_snk_mv; | 2215 | unsigned int min_snk_mv, max_snk_mv; |
2213 | u32 pdo; | 2216 | unsigned int max_op_mv; |
2217 | u32 pdo, src, snk; | ||
2214 | unsigned int src_pdo = 0, snk_pdo = 0; | 2218 | unsigned int src_pdo = 0, snk_pdo = 0; |
2215 | 2219 | ||
2216 | /* | 2220 | /* |
@@ -2260,16 +2264,18 @@ static unsigned int tcpm_pd_select_pps_apdo(struct tcpm_port *port) | |||
2260 | continue; | 2264 | continue; |
2261 | } | 2265 | } |
2262 | 2266 | ||
2263 | if (max_src_mv <= max_snk_mv && | 2267 | if (min_src_mv <= max_snk_mv && |
2264 | min_src_mv >= min_snk_mv) { | 2268 | max_src_mv >= min_snk_mv) { |
2269 | max_op_mv = min(max_src_mv, max_snk_mv); | ||
2270 | src_mw = (max_op_mv * src_ma) / 1000; | ||
2265 | /* Prefer higher voltages if available */ | 2271 | /* Prefer higher voltages if available */ |
2266 | if ((src_mw == max_mw && | 2272 | if ((src_mw == max_mw && |
2267 | min_src_mv > max_mv) || | 2273 | max_op_mv > max_mv) || |
2268 | src_mw > max_mw) { | 2274 | src_mw > max_mw) { |
2269 | src_pdo = i; | 2275 | src_pdo = i; |
2270 | snk_pdo = j; | 2276 | snk_pdo = j; |
2271 | max_mw = src_mw; | 2277 | max_mw = src_mw; |
2272 | max_mv = max_src_mv; | 2278 | max_mv = max_op_mv; |
2273 | } | 2279 | } |
2274 | } | 2280 | } |
2275 | } | 2281 | } |
@@ -2282,16 +2288,18 @@ static unsigned int tcpm_pd_select_pps_apdo(struct tcpm_port *port) | |||
2282 | } | 2288 | } |
2283 | 2289 | ||
2284 | if (src_pdo) { | 2290 | if (src_pdo) { |
2285 | pdo = port->source_caps[src_pdo]; | 2291 | src = port->source_caps[src_pdo]; |
2286 | 2292 | snk = port->snk_pdo[snk_pdo]; | |
2287 | port->pps_data.min_volt = pdo_pps_apdo_min_voltage(pdo); | 2293 | |
2288 | port->pps_data.max_volt = pdo_pps_apdo_max_voltage(pdo); | 2294 | port->pps_data.min_volt = max(pdo_pps_apdo_min_voltage(src), |
2289 | port->pps_data.max_curr = | 2295 | pdo_pps_apdo_min_voltage(snk)); |
2290 | min_pps_apdo_current(pdo, port->snk_pdo[snk_pdo]); | 2296 | port->pps_data.max_volt = min(pdo_pps_apdo_max_voltage(src), |
2291 | port->pps_data.out_volt = | 2297 | pdo_pps_apdo_max_voltage(snk)); |
2292 | min(pdo_pps_apdo_max_voltage(pdo), port->pps_data.out_volt); | 2298 | port->pps_data.max_curr = min_pps_apdo_current(src, snk); |
2293 | port->pps_data.op_curr = | 2299 | port->pps_data.out_volt = min(port->pps_data.max_volt, |
2294 | min(port->pps_data.max_curr, port->pps_data.op_curr); | 2300 | port->pps_data.out_volt); |
2301 | port->pps_data.op_curr = min(port->pps_data.max_curr, | ||
2302 | port->pps_data.op_curr); | ||
2295 | } | 2303 | } |
2296 | 2304 | ||
2297 | return src_pdo; | 2305 | return src_pdo; |
@@ -3254,7 +3262,8 @@ static void run_state_machine(struct tcpm_port *port) | |||
3254 | case SRC_HARD_RESET_VBUS_OFF: | 3262 | case SRC_HARD_RESET_VBUS_OFF: |
3255 | tcpm_set_vconn(port, true); | 3263 | tcpm_set_vconn(port, true); |
3256 | tcpm_set_vbus(port, false); | 3264 | tcpm_set_vbus(port, false); |
3257 | tcpm_set_roles(port, false, TYPEC_SOURCE, TYPEC_HOST); | 3265 | tcpm_set_roles(port, port->self_powered, TYPEC_SOURCE, |
3266 | TYPEC_HOST); | ||
3258 | tcpm_set_state(port, SRC_HARD_RESET_VBUS_ON, PD_T_SRC_RECOVER); | 3267 | tcpm_set_state(port, SRC_HARD_RESET_VBUS_ON, PD_T_SRC_RECOVER); |
3259 | break; | 3268 | break; |
3260 | case SRC_HARD_RESET_VBUS_ON: | 3269 | case SRC_HARD_RESET_VBUS_ON: |
@@ -3266,8 +3275,10 @@ static void run_state_machine(struct tcpm_port *port) | |||
3266 | case SNK_HARD_RESET_SINK_OFF: | 3275 | case SNK_HARD_RESET_SINK_OFF: |
3267 | memset(&port->pps_data, 0, sizeof(port->pps_data)); | 3276 | memset(&port->pps_data, 0, sizeof(port->pps_data)); |
3268 | tcpm_set_vconn(port, false); | 3277 | tcpm_set_vconn(port, false); |
3269 | tcpm_set_charge(port, false); | 3278 | if (port->pd_capable) |
3270 | tcpm_set_roles(port, false, TYPEC_SINK, TYPEC_DEVICE); | 3279 | tcpm_set_charge(port, false); |
3280 | tcpm_set_roles(port, port->self_powered, TYPEC_SINK, | ||
3281 | TYPEC_DEVICE); | ||
3271 | /* | 3282 | /* |
3272 | * VBUS may or may not toggle, depending on the adapter. | 3283 | * VBUS may or may not toggle, depending on the adapter. |
3273 | * If it doesn't toggle, transition to SNK_HARD_RESET_SINK_ON | 3284 | * If it doesn't toggle, transition to SNK_HARD_RESET_SINK_ON |
@@ -3297,6 +3308,12 @@ static void run_state_machine(struct tcpm_port *port) | |||
3297 | * Similar, dual-mode ports in source mode should transition | 3308 | * Similar, dual-mode ports in source mode should transition |
3298 | * to PE_SNK_Transition_to_default. | 3309 | * to PE_SNK_Transition_to_default. |
3299 | */ | 3310 | */ |
3311 | if (port->pd_capable) { | ||
3312 | tcpm_set_current_limit(port, | ||
3313 | tcpm_get_current_limit(port), | ||
3314 | 5000); | ||
3315 | tcpm_set_charge(port, true); | ||
3316 | } | ||
3300 | tcpm_set_attached_state(port, true); | 3317 | tcpm_set_attached_state(port, true); |
3301 | tcpm_set_state(port, SNK_STARTUP, 0); | 3318 | tcpm_set_state(port, SNK_STARTUP, 0); |
3302 | break; | 3319 | break; |
@@ -4412,6 +4429,8 @@ sink: | |||
4412 | return -EINVAL; | 4429 | return -EINVAL; |
4413 | port->operating_snk_mw = mw / 1000; | 4430 | port->operating_snk_mw = mw / 1000; |
4414 | 4431 | ||
4432 | port->self_powered = fwnode_property_read_bool(fwnode, "self-powered"); | ||
4433 | |||
4415 | return 0; | 4434 | return 0; |
4416 | } | 4435 | } |
4417 | 4436 | ||
@@ -4720,6 +4739,7 @@ static int tcpm_copy_caps(struct tcpm_port *port, | |||
4720 | port->typec_caps.prefer_role = tcfg->default_role; | 4739 | port->typec_caps.prefer_role = tcfg->default_role; |
4721 | port->typec_caps.type = tcfg->type; | 4740 | port->typec_caps.type = tcfg->type; |
4722 | port->typec_caps.data = tcfg->data; | 4741 | port->typec_caps.data = tcfg->data; |
4742 | port->self_powered = port->tcpc->config->self_powered; | ||
4723 | 4743 | ||
4724 | return 0; | 4744 | return 0; |
4725 | } | 4745 | } |
diff --git a/drivers/uwb/i1480/dfu/usb.c b/drivers/uwb/i1480/dfu/usb.c index c0430a41e24b..b1b466cbc33e 100644 --- a/drivers/uwb/i1480/dfu/usb.c +++ b/drivers/uwb/i1480/dfu/usb.c | |||
@@ -309,7 +309,7 @@ int i1480_usb_cmd(struct i1480 *i1480, const char *cmd_name, size_t cmd_size) | |||
309 | if (result < 0) { | 309 | if (result < 0) { |
310 | dev_err(dev, "%s: cannot submit NEEP read: %d\n", | 310 | dev_err(dev, "%s: cannot submit NEEP read: %d\n", |
311 | cmd_name, result); | 311 | cmd_name, result); |
312 | goto error_submit_ep1; | 312 | goto error_submit_ep1; |
313 | } | 313 | } |
314 | /* Now post the command on EP0 */ | 314 | /* Now post the command on EP0 */ |
315 | result = usb_control_msg( | 315 | result = usb_control_msg( |
diff --git a/include/linux/phy/phy-mipi-dphy.h b/include/linux/phy/phy-mipi-dphy.h new file mode 100644 index 000000000000..c08aacc0ac35 --- /dev/null +++ b/include/linux/phy/phy-mipi-dphy.h | |||
@@ -0,0 +1,285 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | /* | ||
3 | * Copyright (C) 2018 Cadence Design Systems Inc. | ||
4 | */ | ||
5 | |||
6 | #ifndef __PHY_MIPI_DPHY_H_ | ||
7 | #define __PHY_MIPI_DPHY_H_ | ||
8 | |||
9 | #include <video/videomode.h> | ||
10 | |||
11 | /** | ||
12 | * struct phy_configure_opts_mipi_dphy - MIPI D-PHY configuration set | ||
13 | * | ||
14 | * This structure is used to represent the configuration state of a | ||
15 | * MIPI D-PHY phy. | ||
16 | */ | ||
17 | struct phy_configure_opts_mipi_dphy { | ||
18 | /** | ||
19 | * @clk_miss: | ||
20 | * | ||
21 | * Timeout, in picoseconds, for receiver to detect absence of | ||
22 | * Clock transitions and disable the Clock Lane HS-RX. | ||
23 | * | ||
24 | * Maximum value: 60000 ps | ||
25 | */ | ||
26 | unsigned int clk_miss; | ||
27 | |||
28 | /** | ||
29 | * @clk_post: | ||
30 | * | ||
31 | * Time, in picoseconds, that the transmitter continues to | ||
32 | * send HS clock after the last associated Data Lane has | ||
33 | * transitioned to LP Mode. Interval is defined as the period | ||
34 | * from the end of @hs_trail to the beginning of @clk_trail. | ||
35 | * | ||
36 | * Minimum value: 60000 ps + 52 * @hs_clk_rate period in ps | ||
37 | */ | ||
38 | unsigned int clk_post; | ||
39 | |||
40 | /** | ||
41 | * @clk_pre: | ||
42 | * | ||
43 | * Time, in UI, that the HS clock shall be driven by | ||
44 | * the transmitter prior to any associated Data Lane beginning | ||
45 | * the transition from LP to HS mode. | ||
46 | * | ||
47 | * Minimum value: 8 UI | ||
48 | */ | ||
49 | unsigned int clk_pre; | ||
50 | |||
51 | /** | ||
52 | * @clk_prepare: | ||
53 | * | ||
54 | * Time, in picoseconds, that the transmitter drives the Clock | ||
55 | * Lane LP-00 Line state immediately before the HS-0 Line | ||
56 | * state starting the HS transmission. | ||
57 | * | ||
58 | * Minimum value: 38000 ps | ||
59 | * Maximum value: 95000 ps | ||
60 | */ | ||
61 | unsigned int clk_prepare; | ||
62 | |||
63 | /** | ||
64 | * @clk_settle: | ||
65 | * | ||
66 | * Time interval, in picoseconds, during which the HS receiver | ||
67 | * should ignore any Clock Lane HS transitions, starting from | ||
68 | * the beginning of @clk_prepare. | ||
69 | * | ||
70 | * Minimum value: 95000 ps | ||
71 | * Maximum value: 300000 ps | ||
72 | */ | ||
73 | unsigned int clk_settle; | ||
74 | |||
75 | /** | ||
76 | * @clk_term_en: | ||
77 | * | ||
78 | * Time, in picoseconds, for the Clock Lane receiver to enable | ||
79 | * the HS line termination. | ||
80 | * | ||
81 | * Maximum value: 38000 ps | ||
82 | */ | ||
83 | unsigned int clk_term_en; | ||
84 | |||
85 | /** | ||
86 | * @clk_trail: | ||
87 | * | ||
88 | * Time, in picoseconds, that the transmitter drives the HS-0 | ||
89 | * state after the last payload clock bit of a HS transmission | ||
90 | * burst. | ||
91 | * | ||
92 | * Minimum value: 60000 ps | ||
93 | */ | ||
94 | unsigned int clk_trail; | ||
95 | |||
96 | /** | ||
97 | * @clk_zero: | ||
98 | * | ||
99 | * Time, in picoseconds, that the transmitter drives the HS-0 | ||
100 | * state prior to starting the Clock. | ||
101 | */ | ||
102 | unsigned int clk_zero; | ||
103 | |||
104 | /** | ||
105 | * @d_term_en: | ||
106 | * | ||
107 | * Time, in picoseconds, for the Data Lane receiver to enable | ||
108 | * the HS line termination. | ||
109 | * | ||
110 | * Maximum value: 35000 ps + 4 * @hs_clk_rate period in ps | ||
111 | */ | ||
112 | unsigned int d_term_en; | ||
113 | |||
114 | /** | ||
115 | * @eot: | ||
116 | * | ||
117 | * Transmitted time interval, in picoseconds, from the start | ||
118 | * of @hs_trail or @clk_trail, to the start of the LP- 11 | ||
119 | * state following a HS burst. | ||
120 | * | ||
121 | * Maximum value: 105000 ps + 12 * @hs_clk_rate period in ps | ||
122 | */ | ||
123 | unsigned int eot; | ||
124 | |||
125 | /** | ||
126 | * @hs_exit: | ||
127 | * | ||
128 | * Time, in picoseconds, that the transmitter drives LP-11 | ||
129 | * following a HS burst. | ||
130 | * | ||
131 | * Minimum value: 100000 ps | ||
132 | */ | ||
133 | unsigned int hs_exit; | ||
134 | |||
135 | /** | ||
136 | * @hs_prepare: | ||
137 | * | ||
138 | * Time, in picoseconds, that the transmitter drives the Data | ||
139 | * Lane LP-00 Line state immediately before the HS-0 Line | ||
140 | * state starting the HS transmission. | ||
141 | * | ||
142 | * Minimum value: 40000 ps + 4 * @hs_clk_rate period in ps | ||
143 | * Maximum value: 85000 ps + 6 * @hs_clk_rate period in ps | ||
144 | */ | ||
145 | unsigned int hs_prepare; | ||
146 | |||
147 | /** | ||
148 | * @hs_settle: | ||
149 | * | ||
150 | * Time interval, in picoseconds, during which the HS receiver | ||
151 | * shall ignore any Data Lane HS transitions, starting from | ||
152 | * the beginning of @hs_prepare. | ||
153 | * | ||
154 | * Minimum value: 85000 ps + 6 * @hs_clk_rate period in ps | ||
155 | * Maximum value: 145000 ps + 10 * @hs_clk_rate period in ps | ||
156 | */ | ||
157 | unsigned int hs_settle; | ||
158 | |||
159 | /** | ||
160 | * @hs_skip: | ||
161 | * | ||
162 | * Time interval, in picoseconds, during which the HS-RX | ||
163 | * should ignore any transitions on the Data Lane, following a | ||
164 | * HS burst. The end point of the interval is defined as the | ||
165 | * beginning of the LP-11 state following the HS burst. | ||
166 | * | ||
167 | * Minimum value: 40000 ps | ||
168 | * Maximum value: 55000 ps + 4 * @hs_clk_rate period in ps | ||
169 | */ | ||
170 | unsigned int hs_skip; | ||
171 | |||
172 | /** | ||
173 | * @hs_trail: | ||
174 | * | ||
175 | * Time, in picoseconds, that the transmitter drives the | ||
176 | * flipped differential state after last payload data bit of a | ||
177 | * HS transmission burst | ||
178 | * | ||
179 | * Minimum value: max(8 * @hs_clk_rate period in ps, | ||
180 | * 60000 ps + 4 * @hs_clk_rate period in ps) | ||
181 | */ | ||
182 | unsigned int hs_trail; | ||
183 | |||
184 | /** | ||
185 | * @hs_zero: | ||
186 | * | ||
187 | * Time, in picoseconds, that the transmitter drives the HS-0 | ||
188 | * state prior to transmitting the Sync sequence. | ||
189 | */ | ||
190 | unsigned int hs_zero; | ||
191 | |||
192 | /** | ||
193 | * @init: | ||
194 | * | ||
195 | * Time, in picoseconds for the initialization period to | ||
196 | * complete. | ||
197 | * | ||
198 | * Minimum value: 100000000 ps | ||
199 | */ | ||
200 | unsigned int init; | ||
201 | |||
202 | /** | ||
203 | * @lpx: | ||
204 | * | ||
205 | * Transmitted length, in picoseconds, of any Low-Power state | ||
206 | * period. | ||
207 | * | ||
208 | * Minimum value: 50000 ps | ||
209 | */ | ||
210 | unsigned int lpx; | ||
211 | |||
212 | /** | ||
213 | * @ta_get: | ||
214 | * | ||
215 | * Time, in picoseconds, that the new transmitter drives the | ||
216 | * Bridge state (LP-00) after accepting control during a Link | ||
217 | * Turnaround. | ||
218 | * | ||
219 | * Value: 5 * @lpx | ||
220 | */ | ||
221 | unsigned int ta_get; | ||
222 | |||
223 | /** | ||
224 | * @ta_go: | ||
225 | * | ||
226 | * Time, in picoseconds, that the transmitter drives the | ||
227 | * Bridge state (LP-00) before releasing control during a Link | ||
228 | * Turnaround. | ||
229 | * | ||
230 | * Value: 4 * @lpx | ||
231 | */ | ||
232 | unsigned int ta_go; | ||
233 | |||
234 | /** | ||
235 | * @ta_sure: | ||
236 | * | ||
237 | * Time, in picoseconds, that the new transmitter waits after | ||
238 | * the LP-10 state before transmitting the Bridge state | ||
239 | * (LP-00) during a Link Turnaround. | ||
240 | * | ||
241 | * Minimum value: @lpx | ||
242 | * Maximum value: 2 * @lpx | ||
243 | */ | ||
244 | unsigned int ta_sure; | ||
245 | |||
246 | /** | ||
247 | * @wakeup: | ||
248 | * | ||
249 | * Time, in picoseconds, that a transmitter drives a Mark-1 | ||
250 | * state prior to a Stop state in order to initiate an exit | ||
251 | * from ULPS. | ||
252 | * | ||
253 | * Minimum value: 1000000000 ps | ||
254 | */ | ||
255 | unsigned int wakeup; | ||
256 | |||
257 | /** | ||
258 | * @hs_clk_rate: | ||
259 | * | ||
260 | * Clock rate, in Hertz, of the high-speed clock. | ||
261 | */ | ||
262 | unsigned long hs_clk_rate; | ||
263 | |||
264 | /** | ||
265 | * @lp_clk_rate: | ||
266 | * | ||
267 | * Clock rate, in Hertz, of the low-power clock. | ||
268 | */ | ||
269 | unsigned long lp_clk_rate; | ||
270 | |||
271 | /** | ||
272 | * @lanes: | ||
273 | * | ||
274 | * Number of active data lanes used for the transmissions. | ||
275 | */ | ||
276 | unsigned char lanes; | ||
277 | }; | ||
278 | |||
279 | int phy_mipi_dphy_get_default_config(unsigned long pixel_clock, | ||
280 | unsigned int bpp, | ||
281 | unsigned int lanes, | ||
282 | struct phy_configure_opts_mipi_dphy *cfg); | ||
283 | int phy_mipi_dphy_config_validate(struct phy_configure_opts_mipi_dphy *cfg); | ||
284 | |||
285 | #endif /* __PHY_MIPI_DPHY_H_ */ | ||
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h index 03b319f89a34..1fdefadf150a 100644 --- a/include/linux/phy/phy.h +++ b/include/linux/phy/phy.h | |||
@@ -20,6 +20,8 @@ | |||
20 | #include <linux/pm_runtime.h> | 20 | #include <linux/pm_runtime.h> |
21 | #include <linux/regulator/consumer.h> | 21 | #include <linux/regulator/consumer.h> |
22 | 22 | ||
23 | #include <linux/phy/phy-mipi-dphy.h> | ||
24 | |||
23 | struct phy; | 25 | struct phy; |
24 | 26 | ||
25 | enum phy_mode { | 27 | enum phy_mode { |
@@ -35,13 +37,21 @@ enum phy_mode { | |||
35 | PHY_MODE_USB_DEVICE_HS, | 37 | PHY_MODE_USB_DEVICE_HS, |
36 | PHY_MODE_USB_DEVICE_SS, | 38 | PHY_MODE_USB_DEVICE_SS, |
37 | PHY_MODE_USB_OTG, | 39 | PHY_MODE_USB_OTG, |
38 | PHY_MODE_SGMII, | ||
39 | PHY_MODE_2500SGMII, | ||
40 | PHY_MODE_QSGMII, | ||
41 | PHY_MODE_10GKR, | ||
42 | PHY_MODE_UFS_HS_A, | 40 | PHY_MODE_UFS_HS_A, |
43 | PHY_MODE_UFS_HS_B, | 41 | PHY_MODE_UFS_HS_B, |
44 | PHY_MODE_PCIE, | 42 | PHY_MODE_PCIE, |
43 | PHY_MODE_ETHERNET, | ||
44 | PHY_MODE_MIPI_DPHY, | ||
45 | }; | ||
46 | |||
47 | /** | ||
48 | * union phy_configure_opts - Opaque generic phy configuration | ||
49 | * | ||
50 | * @mipi_dphy: Configuration set applicable for phys supporting | ||
51 | * the MIPI_DPHY phy mode. | ||
52 | */ | ||
53 | union phy_configure_opts { | ||
54 | struct phy_configure_opts_mipi_dphy mipi_dphy; | ||
45 | }; | 55 | }; |
46 | 56 | ||
47 | /** | 57 | /** |
@@ -60,7 +70,38 @@ struct phy_ops { | |||
60 | int (*exit)(struct phy *phy); | 70 | int (*exit)(struct phy *phy); |
61 | int (*power_on)(struct phy *phy); | 71 | int (*power_on)(struct phy *phy); |
62 | int (*power_off)(struct phy *phy); | 72 | int (*power_off)(struct phy *phy); |
63 | int (*set_mode)(struct phy *phy, enum phy_mode mode); | 73 | int (*set_mode)(struct phy *phy, enum phy_mode mode, int submode); |
74 | |||
75 | /** | ||
76 | * @configure: | ||
77 | * | ||
78 | * Optional. | ||
79 | * | ||
80 | * Used to change the PHY parameters. phy_init() must have | ||
81 | * been called on the phy. | ||
82 | * | ||
83 | * Returns: 0 if successful, an negative error code otherwise | ||
84 | */ | ||
85 | int (*configure)(struct phy *phy, union phy_configure_opts *opts); | ||
86 | |||
87 | /** | ||
88 | * @validate: | ||
89 | * | ||
90 | * Optional. | ||
91 | * | ||
92 | * Used to check that the current set of parameters can be | ||
93 | * handled by the phy. Implementations are free to tune the | ||
94 | * parameters passed as arguments if needed by some | ||
95 | * implementation detail or constraints. It must not change | ||
96 | * any actual configuration of the PHY, so calling it as many | ||
97 | * times as deemed fit by the consumer must have no side | ||
98 | * effect. | ||
99 | * | ||
100 | * Returns: 0 if the configuration can be applied, an negative | ||
101 | * error code otherwise | ||
102 | */ | ||
103 | int (*validate)(struct phy *phy, enum phy_mode mode, int submode, | ||
104 | union phy_configure_opts *opts); | ||
64 | int (*reset)(struct phy *phy); | 105 | int (*reset)(struct phy *phy); |
65 | int (*calibrate)(struct phy *phy); | 106 | int (*calibrate)(struct phy *phy); |
66 | struct module *owner; | 107 | struct module *owner; |
@@ -164,7 +205,13 @@ int phy_init(struct phy *phy); | |||
164 | int phy_exit(struct phy *phy); | 205 | int phy_exit(struct phy *phy); |
165 | int phy_power_on(struct phy *phy); | 206 | int phy_power_on(struct phy *phy); |
166 | int phy_power_off(struct phy *phy); | 207 | int phy_power_off(struct phy *phy); |
167 | int phy_set_mode(struct phy *phy, enum phy_mode mode); | 208 | int phy_set_mode_ext(struct phy *phy, enum phy_mode mode, int submode); |
209 | #define phy_set_mode(phy, mode) \ | ||
210 | phy_set_mode_ext(phy, mode, 0) | ||
211 | int phy_configure(struct phy *phy, union phy_configure_opts *opts); | ||
212 | int phy_validate(struct phy *phy, enum phy_mode mode, int submode, | ||
213 | union phy_configure_opts *opts); | ||
214 | |||
168 | static inline enum phy_mode phy_get_mode(struct phy *phy) | 215 | static inline enum phy_mode phy_get_mode(struct phy *phy) |
169 | { | 216 | { |
170 | return phy->attrs.mode; | 217 | return phy->attrs.mode; |
@@ -278,13 +325,17 @@ static inline int phy_power_off(struct phy *phy) | |||
278 | return -ENOSYS; | 325 | return -ENOSYS; |
279 | } | 326 | } |
280 | 327 | ||
281 | static inline int phy_set_mode(struct phy *phy, enum phy_mode mode) | 328 | static inline int phy_set_mode_ext(struct phy *phy, enum phy_mode mode, |
329 | int submode) | ||
282 | { | 330 | { |
283 | if (!phy) | 331 | if (!phy) |
284 | return 0; | 332 | return 0; |
285 | return -ENOSYS; | 333 | return -ENOSYS; |
286 | } | 334 | } |
287 | 335 | ||
336 | #define phy_set_mode(phy, mode) \ | ||
337 | phy_set_mode_ext(phy, mode, 0) | ||
338 | |||
288 | static inline enum phy_mode phy_get_mode(struct phy *phy) | 339 | static inline enum phy_mode phy_get_mode(struct phy *phy) |
289 | { | 340 | { |
290 | return PHY_MODE_INVALID; | 341 | return PHY_MODE_INVALID; |
@@ -304,6 +355,24 @@ static inline int phy_calibrate(struct phy *phy) | |||
304 | return -ENOSYS; | 355 | return -ENOSYS; |
305 | } | 356 | } |
306 | 357 | ||
358 | static inline int phy_configure(struct phy *phy, | ||
359 | union phy_configure_opts *opts) | ||
360 | { | ||
361 | if (!phy) | ||
362 | return 0; | ||
363 | |||
364 | return -ENOSYS; | ||
365 | } | ||
366 | |||
367 | static inline int phy_validate(struct phy *phy, enum phy_mode mode, int submode, | ||
368 | union phy_configure_opts *opts) | ||
369 | { | ||
370 | if (!phy) | ||
371 | return 0; | ||
372 | |||
373 | return -ENOSYS; | ||
374 | } | ||
375 | |||
307 | static inline int phy_get_bus_width(struct phy *phy) | 376 | static inline int phy_get_bus_width(struct phy *phy) |
308 | { | 377 | { |
309 | return -ENOSYS; | 378 | return -ENOSYS; |
diff --git a/include/linux/usb/ccid.h b/include/linux/usb/ccid.h new file mode 100644 index 000000000000..3431446d6864 --- /dev/null +++ b/include/linux/usb/ccid.h | |||
@@ -0,0 +1,51 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2018 Vincent Pelletier | ||
3 | */ | ||
4 | /* | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | #ifndef __CCID_H | ||
20 | #define __CCID_H | ||
21 | |||
22 | #include <linux/types.h> | ||
23 | |||
24 | #define USB_INTERFACE_CLASS_CCID 0x0b | ||
25 | |||
26 | struct ccid_descriptor { | ||
27 | __u8 bLength; | ||
28 | __u8 bDescriptorType; | ||
29 | __le16 bcdCCID; | ||
30 | __u8 bMaxSlotIndex; | ||
31 | __u8 bVoltageSupport; | ||
32 | __le32 dwProtocols; | ||
33 | __le32 dwDefaultClock; | ||
34 | __le32 dwMaximumClock; | ||
35 | __u8 bNumClockSupported; | ||
36 | __le32 dwDataRate; | ||
37 | __le32 dwMaxDataRate; | ||
38 | __u8 bNumDataRatesSupported; | ||
39 | __le32 dwMaxIFSD; | ||
40 | __le32 dwSynchProtocols; | ||
41 | __le32 dwMechanical; | ||
42 | __le32 dwFeatures; | ||
43 | __le32 dwMaxCCIDMessageLength; | ||
44 | __u8 bClassGetResponse; | ||
45 | __u8 bClassEnvelope; | ||
46 | __le16 wLcdLayout; | ||
47 | __u8 bPINSupport; | ||
48 | __u8 bMaxCCIDBusySlots; | ||
49 | } __attribute__ ((packed)); | ||
50 | |||
51 | #endif /* __CCID_H */ | ||
diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h index 63758c399e4e..911e05af671e 100644 --- a/include/linux/usb/chipidea.h +++ b/include/linux/usb/chipidea.h | |||
@@ -60,9 +60,12 @@ struct ci_hdrc_platform_data { | |||
60 | #define CI_HDRC_OVERRIDE_RX_BURST BIT(11) | 60 | #define CI_HDRC_OVERRIDE_RX_BURST BIT(11) |
61 | #define CI_HDRC_OVERRIDE_PHY_CONTROL BIT(12) /* Glue layer manages phy */ | 61 | #define CI_HDRC_OVERRIDE_PHY_CONTROL BIT(12) /* Glue layer manages phy */ |
62 | #define CI_HDRC_REQUIRES_ALIGNED_DMA BIT(13) | 62 | #define CI_HDRC_REQUIRES_ALIGNED_DMA BIT(13) |
63 | #define CI_HDRC_IMX_IS_HSIC BIT(14) | ||
63 | enum usb_dr_mode dr_mode; | 64 | enum usb_dr_mode dr_mode; |
64 | #define CI_HDRC_CONTROLLER_RESET_EVENT 0 | 65 | #define CI_HDRC_CONTROLLER_RESET_EVENT 0 |
65 | #define CI_HDRC_CONTROLLER_STOPPED_EVENT 1 | 66 | #define CI_HDRC_CONTROLLER_STOPPED_EVENT 1 |
67 | #define CI_HDRC_IMX_HSIC_ACTIVE_EVENT 2 | ||
68 | #define CI_HDRC_IMX_HSIC_SUSPEND_EVENT 3 | ||
66 | int (*notify_event) (struct ci_hdrc *ci, unsigned event); | 69 | int (*notify_event) (struct ci_hdrc *ci, unsigned event); |
67 | struct regulator *reg_vbus; | 70 | struct regulator *reg_vbus; |
68 | struct usb_otg_caps ci_otg_caps; | 71 | struct usb_otg_caps ci_otg_caps; |
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index e5cd84a0f84a..7595056b96c1 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h | |||
@@ -61,6 +61,8 @@ struct usb_ep; | |||
61 | * invalidated by the error may first be dequeued. | 61 | * invalidated by the error may first be dequeued. |
62 | * @context: For use by the completion callback | 62 | * @context: For use by the completion callback |
63 | * @list: For use by the gadget driver. | 63 | * @list: For use by the gadget driver. |
64 | * @frame_number: Reports the interval number in (micro)frame in which the | ||
65 | * isochronous transfer was transmitted or received. | ||
64 | * @status: Reports completion code, zero or a negative errno. | 66 | * @status: Reports completion code, zero or a negative errno. |
65 | * Normally, faults block the transfer queue from advancing until | 67 | * Normally, faults block the transfer queue from advancing until |
66 | * the completion callback returns. | 68 | * the completion callback returns. |
@@ -112,6 +114,8 @@ struct usb_request { | |||
112 | void *context; | 114 | void *context; |
113 | struct list_head list; | 115 | struct list_head list; |
114 | 116 | ||
117 | unsigned frame_number; /* ISO ONLY */ | ||
118 | |||
115 | int status; | 119 | int status; |
116 | unsigned actual; | 120 | unsigned actual; |
117 | }; | 121 | }; |
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index 97e2ddec18b1..7dc3a411bece 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h | |||
@@ -235,11 +235,6 @@ static inline struct usb_hcd *bus_to_hcd(struct usb_bus *bus) | |||
235 | return container_of(bus, struct usb_hcd, self); | 235 | return container_of(bus, struct usb_hcd, self); |
236 | } | 236 | } |
237 | 237 | ||
238 | struct hcd_timeout { /* timeouts we allocate */ | ||
239 | struct list_head timeout_list; | ||
240 | struct timer_list timer; | ||
241 | }; | ||
242 | |||
243 | /*-------------------------------------------------------------------------*/ | 238 | /*-------------------------------------------------------------------------*/ |
244 | 239 | ||
245 | 240 | ||
diff --git a/include/linux/usb/tcpm.h b/include/linux/usb/tcpm.h index 7e7fbfb84e8e..50c74a77db55 100644 --- a/include/linux/usb/tcpm.h +++ b/include/linux/usb/tcpm.h | |||
@@ -89,6 +89,7 @@ struct tcpc_config { | |||
89 | enum typec_port_data data; | 89 | enum typec_port_data data; |
90 | enum typec_role default_role; | 90 | enum typec_role default_role; |
91 | bool try_role_hw; /* try.{src,snk} implemented in hardware */ | 91 | bool try_role_hw; /* try.{src,snk} implemented in hardware */ |
92 | bool self_powered; /* port belongs to a self powered device */ | ||
92 | 93 | ||
93 | const struct typec_altmode_desc *alt_modes; | 94 | const struct typec_altmode_desc *alt_modes; |
94 | }; | 95 | }; |