USB/PHY driver updates for 4.14-rc1
Here is the large USB and PHY driver update for 4.14-rc1. Not all that exciting, a few new PHY drivers, the usual mess of gadget driver updates and fixes, and of course, xhci updates to try to tame that beast. A number of usb-serial updates and other small fixes all over the USB driver tree are in here as well. Full details are in the shortlog. All of these have been in linux-next for a while with no reported issues. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCWa2Buw8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+yk0VQCeK9SbD3sNVE0NXnwBYPTptghtr1EAoKwg96LG e4TUNAUcKadcDHJ8S81i =zy8S -----END PGP SIGNATURE----- Merge tag 'usb-4.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb Pull USB/PHY driver updates from Greg KH: "Here is the large USB and PHY driver update for 4.14-rc1. Not all that exciting, a few new PHY drivers, the usual mess of gadget driver updates and fixes, and of course, xhci updates to try to tame that beast. A number of usb-serial updates and other small fixes all over the USB driver tree are in here as well. Full details are in the shortlog. All of these have been in linux-next for a while with no reported issues" * tag 'usb-4.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (171 commits) usbip: vhci-hcd: make vhci_hc_driver const usb: phy: Avoid unchecked dereference warning usb: imx21-hcd: make imx21_hc_driver const usb: host: make ehci_fsl_overrides const and __initconst dt-bindings: mt8173-mtu3: add generic compatible and rename file dt-bindings: mt8173-xhci: add generic compatible and rename file usb: xhci-mtk: add generic compatible string usbip: auto retry for concurrent attach USB: serial: option: simplify 3 D-Link device entries USB: serial: option: add support for D-Link DWM-157 C1 usb: core: usbport: fix "BUG: key not in .data" when lockdep is enabled usb: chipidea: usb2: check memory allocation failure usb: Add device quirk for Logitech HD Pro Webcam C920-C usb: misc: lvstest: add entry to place port in compliance mode usb: xhci: Support enabling of compliance mode for xhci 1.1 usb:xhci:Fix regression when ATI chipsets detected usb: quirks: add delay init quirk for Corsair Strafe RGB keyboard usb: gadget: make snd_pcm_hardware const usb: common: use of_property_read_bool() USB: core: constify vm_operations_struct ...
This commit is contained in:
commit
1a3b85ea36
@ -12,3 +12,6 @@ Description:
|
|||||||
Ethernet over USB link
|
Ethernet over USB link
|
||||||
dev_addr - MAC address of device's end of this
|
dev_addr - MAC address of device's end of this
|
||||||
Ethernet over USB link
|
Ethernet over USB link
|
||||||
|
class - USB interface class, default is 02 (hex)
|
||||||
|
subclass - USB interface subclass, default is 06 (hex)
|
||||||
|
protocol - USB interface protocol, default is 00 (hex)
|
||||||
|
@ -45,3 +45,16 @@ Contact: Pratyush Anand <pratyush.anand@gmail.com>
|
|||||||
Description:
|
Description:
|
||||||
Write to this node to issue "U3 exit" for Link Layer
|
Write to this node to issue "U3 exit" for Link Layer
|
||||||
Validation device. It is needed for TD.7.36.
|
Validation device. It is needed for TD.7.36.
|
||||||
|
|
||||||
|
What: /sys/bus/usb/devices/.../enable_compliance
|
||||||
|
Date: July 2017
|
||||||
|
Description:
|
||||||
|
Write to this node to set the port to compliance mode to test
|
||||||
|
with Link Layer Validation device. It is needed for TD.7.34.
|
||||||
|
|
||||||
|
What: /sys/bus/usb/devices/.../warm_reset
|
||||||
|
Date: July 2017
|
||||||
|
Description:
|
||||||
|
Write to this node to issue "Warm Reset" for Link Layer Validation
|
||||||
|
device. It may be needed to properly reset an xHCI 1.1 host port if
|
||||||
|
compliance mode needed to be explicitly enabled.
|
||||||
|
@ -31,6 +31,7 @@ Required properties:
|
|||||||
../interrupt-controller/interrupts.txt
|
../interrupt-controller/interrupts.txt
|
||||||
|
|
||||||
Optional sub-nodes:
|
Optional sub-nodes:
|
||||||
|
- phys : Contains a phandle to the USB PHY.
|
||||||
- regulators : Contains sub-nodes for each of the regulators supplied by
|
- regulators : Contains sub-nodes for each of the regulators supplied by
|
||||||
the device. The regulators are bound using their names listed below:
|
the device. The regulators are bound using their names listed below:
|
||||||
|
|
||||||
|
@ -1,13 +1,18 @@
|
|||||||
mt65xx USB3.0 PHY binding
|
MediaTek T-PHY binding
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
This binding describes a usb3.0 phy for mt65xx platforms of Medaitek SoC.
|
T-phy controller supports physical layer functionality for a number of
|
||||||
|
controllers on MediaTek SoCs, such as, USB2.0, USB3.0, PCIe, and SATA.
|
||||||
|
|
||||||
Required properties (controller (parent) node):
|
Required properties (controller (parent) node):
|
||||||
- compatible : should be one of
|
- compatible : should be one of
|
||||||
"mediatek,mt2701-u3phy"
|
"mediatek,generic-tphy-v1"
|
||||||
"mediatek,mt2712-u3phy"
|
"mediatek,generic-tphy-v2"
|
||||||
"mediatek,mt8173-u3phy"
|
"mediatek,mt2701-u3phy" (deprecated)
|
||||||
|
"mediatek,mt2712-u3phy" (deprecated)
|
||||||
|
"mediatek,mt8173-u3phy";
|
||||||
|
make use of "mediatek,generic-tphy-v1" on mt2701 instead and
|
||||||
|
"mediatek,generic-tphy-v2" on mt2712 instead.
|
||||||
- clocks : (deprecated, use port's clocks instead) a list of phandle +
|
- clocks : (deprecated, use port's clocks instead) a list of phandle +
|
||||||
clock-specifier pairs, one for each entry in clock-names
|
clock-specifier pairs, one for each entry in clock-names
|
||||||
- clock-names : (deprecated, use port's one instead) must contain
|
- clock-names : (deprecated, use port's one instead) must contain
|
||||||
@ -35,6 +40,8 @@ Required properties (port (child) node):
|
|||||||
cell after port phandle is phy type from:
|
cell after port phandle is phy type from:
|
||||||
- PHY_TYPE_USB2
|
- PHY_TYPE_USB2
|
||||||
- PHY_TYPE_USB3
|
- PHY_TYPE_USB3
|
||||||
|
- PHY_TYPE_PCIE
|
||||||
|
- PHY_TYPE_SATA
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
@ -6,6 +6,7 @@ Required properties (phy (parent) node):
|
|||||||
* "rockchip,rk3328-usb2phy"
|
* "rockchip,rk3328-usb2phy"
|
||||||
* "rockchip,rk3366-usb2phy"
|
* "rockchip,rk3366-usb2phy"
|
||||||
* "rockchip,rk3399-usb2phy"
|
* "rockchip,rk3399-usb2phy"
|
||||||
|
* "rockchip,rv1108-usb2phy"
|
||||||
- reg : the address offset of grf for usb-phy configuration.
|
- reg : the address offset of grf for usb-phy configuration.
|
||||||
- #clock-cells : should be 0.
|
- #clock-cells : should be 0.
|
||||||
- clock-output-names : specify the 480m output clock name.
|
- clock-output-names : specify the 480m output clock name.
|
||||||
@ -18,6 +19,10 @@ Optional properties:
|
|||||||
usb-phy output 480m and xin24m.
|
usb-phy output 480m and xin24m.
|
||||||
Refer to clk/clock-bindings.txt for generic clock
|
Refer to clk/clock-bindings.txt for generic clock
|
||||||
consumer properties.
|
consumer properties.
|
||||||
|
- rockchip,usbgrf : phandle to the syscon managing the "usb general
|
||||||
|
register files". When set driver will request its
|
||||||
|
phandle as one companion-grf for some special SoCs
|
||||||
|
(e.g RV1108).
|
||||||
|
|
||||||
Required nodes : a sub-node is required for each port the phy provides.
|
Required nodes : a sub-node is required for each port the phy provides.
|
||||||
The sub-node name is used to identify host or otg port,
|
The sub-node name is used to identify host or otg port,
|
||||||
@ -28,10 +33,14 @@ Required nodes : a sub-node is required for each port the phy provides.
|
|||||||
Required properties (port (child) node):
|
Required properties (port (child) node):
|
||||||
- #phy-cells : must be 0. See ./phy-bindings.txt for details.
|
- #phy-cells : must be 0. See ./phy-bindings.txt for details.
|
||||||
- interrupts : specify an interrupt for each entry in interrupt-names.
|
- interrupts : specify an interrupt for each entry in interrupt-names.
|
||||||
- interrupt-names : a list which shall be the following entries:
|
- interrupt-names : a list which should be one of the following cases:
|
||||||
|
Regular case:
|
||||||
* "otg-id" : for the otg id interrupt.
|
* "otg-id" : for the otg id interrupt.
|
||||||
* "otg-bvalid" : for the otg vbus interrupt.
|
* "otg-bvalid" : for the otg vbus interrupt.
|
||||||
* "linestate" : for the host/otg linestate interrupt.
|
* "linestate" : for the host/otg linestate interrupt.
|
||||||
|
Some SoCs use one interrupt with the above muxed together, so for these
|
||||||
|
* "otg-mux" : otg-port interrupt, which mux otg-id/otg-bvalid/linestate
|
||||||
|
to one.
|
||||||
|
|
||||||
Optional properties:
|
Optional properties:
|
||||||
- phy-supply : phandle to a regulator that provides power to VBUS.
|
- phy-supply : phandle to a regulator that provides power to VBUS.
|
||||||
|
@ -6,6 +6,7 @@ controllers on Qualcomm chipsets, such as, PCIe, UFS, and USB.
|
|||||||
|
|
||||||
Required properties:
|
Required properties:
|
||||||
- compatible: compatible list, contains:
|
- compatible: compatible list, contains:
|
||||||
|
"qcom,ipq8074-qmp-pcie-phy" for PCIe phy on IPQ8074
|
||||||
"qcom,msm8996-qmp-pcie-phy" for 14nm PCIe phy on msm8996,
|
"qcom,msm8996-qmp-pcie-phy" for 14nm PCIe phy on msm8996,
|
||||||
"qcom,msm8996-qmp-usb3-phy" for 14nm USB3 phy on msm8996.
|
"qcom,msm8996-qmp-usb3-phy" for 14nm USB3 phy on msm8996.
|
||||||
|
|
||||||
@ -38,6 +39,8 @@ Required properties:
|
|||||||
"phy", "common", "cfg".
|
"phy", "common", "cfg".
|
||||||
For "qcom,msm8996-qmp-usb3-phy" must contain
|
For "qcom,msm8996-qmp-usb3-phy" must contain
|
||||||
"phy", "common".
|
"phy", "common".
|
||||||
|
For "qcom,ipq8074-qmp-pcie-phy" must contain:
|
||||||
|
"phy", "common".
|
||||||
|
|
||||||
- vdda-phy-supply: Phandle to a regulator supply to PHY core block.
|
- vdda-phy-supply: Phandle to a regulator supply to PHY core block.
|
||||||
- vdda-pll-supply: Phandle to 1.8V regulator supply to PHY refclk pll block.
|
- vdda-pll-supply: Phandle to 1.8V regulator supply to PHY refclk pll block.
|
||||||
@ -60,6 +63,13 @@ Required properties for child node:
|
|||||||
one for each entry in clock-names.
|
one for each entry in clock-names.
|
||||||
- clock-names: Must contain following for pcie and usb qmp phys:
|
- clock-names: Must contain following for pcie and usb qmp phys:
|
||||||
"pipe<lane-number>" for pipe clock specific to each lane.
|
"pipe<lane-number>" for pipe clock specific to each lane.
|
||||||
|
- clock-output-names: Name of the PHY clock that will be the parent for
|
||||||
|
the above pipe clock.
|
||||||
|
|
||||||
|
For "qcom,ipq8074-qmp-pcie-phy":
|
||||||
|
- "pcie20_phy0_pipe_clk" Pipe Clock parent
|
||||||
|
(or)
|
||||||
|
"pcie20_phy1_pipe_clk"
|
||||||
|
|
||||||
- resets: a list of phandles and reset controller specifier pairs,
|
- resets: a list of phandles and reset controller specifier pairs,
|
||||||
one for each entry in reset-names.
|
one for each entry in reset-names.
|
||||||
@ -96,6 +106,7 @@ Example:
|
|||||||
|
|
||||||
clocks = <&gcc GCC_PCIE_0_PIPE_CLK>;
|
clocks = <&gcc GCC_PCIE_0_PIPE_CLK>;
|
||||||
clock-names = "pipe0";
|
clock-names = "pipe0";
|
||||||
|
clock-output-names = "pcie_0_pipe_clk_src";
|
||||||
resets = <&gcc GCC_PCIE_0_PHY_BCR>;
|
resets = <&gcc GCC_PCIE_0_PHY_BCR>;
|
||||||
reset-names = "lane0";
|
reset-names = "lane0";
|
||||||
};
|
};
|
||||||
|
23
Documentation/devicetree/bindings/phy/ralink-usb-phy.txt
Normal file
23
Documentation/devicetree/bindings/phy/ralink-usb-phy.txt
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
Mediatek/Ralink USB PHY
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
- compatible: "ralink,rt3352-usbphy"
|
||||||
|
"mediatek,mt7620-usbphy"
|
||||||
|
"mediatek,mt7628-usbphy"
|
||||||
|
- reg: required for "mediatek,mt7628-usbphy", unused otherwise
|
||||||
|
- #phy-cells: should be 0
|
||||||
|
- ralink,sysctl: a phandle to a ralink syscon register region
|
||||||
|
- resets: the two reset controllers for host and device
|
||||||
|
- reset-names: the names of the 2 reset controllers
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
usbphy: phy {
|
||||||
|
compatible = "mediatek,mt7628-usbphy";
|
||||||
|
reg = <0x10120000 0x1000>;
|
||||||
|
#phy-cells = <0>;
|
||||||
|
|
||||||
|
ralink,sysctl = <&sysc>;
|
||||||
|
resets = <&rstctrl 22 &rstctrl 25>;
|
||||||
|
reset-names = "host", "device";
|
||||||
|
};
|
@ -9,6 +9,7 @@ Required properties:
|
|||||||
* allwinner,sun7i-a20-usb-phy
|
* allwinner,sun7i-a20-usb-phy
|
||||||
* allwinner,sun8i-a23-usb-phy
|
* allwinner,sun8i-a23-usb-phy
|
||||||
* allwinner,sun8i-a33-usb-phy
|
* allwinner,sun8i-a33-usb-phy
|
||||||
|
* allwinner,sun8i-a83t-usb-phy
|
||||||
* allwinner,sun8i-h3-usb-phy
|
* allwinner,sun8i-h3-usb-phy
|
||||||
* allwinner,sun8i-v3s-usb-phy
|
* allwinner,sun8i-v3s-usb-phy
|
||||||
* allwinner,sun50i-a64-usb-phy
|
* allwinner,sun50i-a64-usb-phy
|
||||||
@ -17,18 +18,22 @@ Required properties:
|
|||||||
* "phy_ctrl"
|
* "phy_ctrl"
|
||||||
* "pmu0" for H3, V3s and A64
|
* "pmu0" for H3, V3s and A64
|
||||||
* "pmu1"
|
* "pmu1"
|
||||||
* "pmu2" for sun4i, sun6i or sun7i
|
* "pmu2" for sun4i, sun6i, sun7i, sun8i-a83t or sun8i-h3
|
||||||
|
* "pmu3" for sun8i-h3
|
||||||
- #phy-cells : from the generic phy bindings, must be 1
|
- #phy-cells : from the generic phy bindings, must be 1
|
||||||
- clocks : phandle + clock specifier for the phy clocks
|
- clocks : phandle + clock specifier for the phy clocks
|
||||||
- clock-names :
|
- clock-names :
|
||||||
* "usb_phy" for sun4i, sun5i or sun7i
|
* "usb_phy" for sun4i, sun5i or sun7i
|
||||||
* "usb0_phy", "usb1_phy" and "usb2_phy" for sun6i
|
* "usb0_phy", "usb1_phy" and "usb2_phy" for sun6i
|
||||||
* "usb0_phy", "usb1_phy" for sun8i
|
* "usb0_phy", "usb1_phy" for sun8i
|
||||||
|
* "usb0_phy", "usb1_phy", "usb2_phy" and "usb2_hsic_12M" for sun8i-a83t
|
||||||
|
* "usb0_phy", "usb1_phy", "usb2_phy" and "usb3_phy" for sun8i-h3
|
||||||
- resets : a list of phandle + reset specifier pairs
|
- resets : a list of phandle + reset specifier pairs
|
||||||
- reset-names :
|
- reset-names :
|
||||||
* "usb0_reset"
|
* "usb0_reset"
|
||||||
* "usb1_reset"
|
* "usb1_reset"
|
||||||
* "usb2_reset" for sun4i, sun6i or sun7i
|
* "usb2_reset" for sun4i, sun6i, sun7i, sun8i-a83t or sun8i-h3
|
||||||
|
* "usb3_reset" for sun8i-h3
|
||||||
|
|
||||||
Optional properties:
|
Optional properties:
|
||||||
- usb0_id_det-gpios : gpio phandle for reading the otg id pin value
|
- usb0_id_det-gpios : gpio phandle for reading the otg id pin value
|
||||||
@ -37,6 +42,7 @@ Optional properties:
|
|||||||
- usb0_vbus-supply : regulator phandle for controller usb0 vbus
|
- usb0_vbus-supply : regulator phandle for controller usb0 vbus
|
||||||
- usb1_vbus-supply : regulator phandle for controller usb1 vbus
|
- usb1_vbus-supply : regulator phandle for controller usb1 vbus
|
||||||
- usb2_vbus-supply : regulator phandle for controller usb2 vbus
|
- usb2_vbus-supply : regulator phandle for controller usb2 vbus
|
||||||
|
- usb3_vbus-supply : regulator phandle for controller usb3 vbus
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
usbphy: phy@0x01c13400 {
|
usbphy: phy@0x01c13400 {
|
||||||
|
29
Documentation/devicetree/bindings/usb/brcm,bdc.txt
Normal file
29
Documentation/devicetree/bindings/usb/brcm,bdc.txt
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
Broadcom USB Device Controller (BDC)
|
||||||
|
====================================
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
|
||||||
|
- compatible: must be one of:
|
||||||
|
"brcm,bdc-v0.16"
|
||||||
|
"brcm,bdc"
|
||||||
|
- reg: the base register address and length
|
||||||
|
- interrupts: the interrupt line for this controller
|
||||||
|
|
||||||
|
Optional properties:
|
||||||
|
|
||||||
|
On Broadcom STB platforms, these properties are required:
|
||||||
|
|
||||||
|
- phys: phandle to one or two USB PHY blocks
|
||||||
|
NOTE: Some SoC's have a single phy and some have
|
||||||
|
USB 2.0 and USB 3.0 phys
|
||||||
|
- clocks: phandle to the functional clock of this block
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
bdc@f0b02000 {
|
||||||
|
compatible = "brcm,bdc-v0.16";
|
||||||
|
reg = <0xf0b02000 0xfc4>;
|
||||||
|
interrupts = <0x0 0x60 0x0>;
|
||||||
|
phys = <&usbphy_0 0x0>;
|
||||||
|
clocks = <&sw_usbd>;
|
||||||
|
};
|
@ -12,8 +12,21 @@ Required properties:
|
|||||||
MPU.
|
MPU.
|
||||||
- ranges: allows valid 1:1 translation between child's address space and
|
- ranges: allows valid 1:1 translation between child's address space and
|
||||||
parent's address space.
|
parent's address space.
|
||||||
- clocks: Clock IDs array as required by the controller.
|
|
||||||
- clock-names: names of clocks correseponding to IDs in the clock property.
|
SoC-specific Required Properties:
|
||||||
|
The following are mandatory properties for Keystone 2 66AK2HK, 66AK2L and 66AK2E
|
||||||
|
SoCs only:
|
||||||
|
|
||||||
|
- clocks: Clock ID for USB functional clock.
|
||||||
|
- clock-names: Must be "usb".
|
||||||
|
|
||||||
|
|
||||||
|
The following are mandatory properties for Keystone 2 66AK2G SoCs only:
|
||||||
|
|
||||||
|
- power-domains: Should contain a phandle to a PM domain provider node
|
||||||
|
and an args specifier containing the USB device id
|
||||||
|
value. This property is as per the binding,
|
||||||
|
Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
|
||||||
|
|
||||||
Sub-nodes:
|
Sub-nodes:
|
||||||
The dwc3 core should be added as subnode to Keystone DWC3 glue.
|
The dwc3 core should be added as subnode to Keystone DWC3 glue.
|
||||||
|
@ -11,7 +11,11 @@ into two parts.
|
|||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
|
|
||||||
Required properties:
|
Required properties:
|
||||||
- compatible : should contain "mediatek,mt8173-xhci"
|
- compatible : should be "mediatek,<soc-model>-xhci", "mediatek,mtk-xhci",
|
||||||
|
soc-model is the name of SoC, such as mt8173, mt2712 etc, when using
|
||||||
|
"mediatek,mtk-xhci" compatible string, you need SoC specific ones in
|
||||||
|
addition, one of:
|
||||||
|
- "mediatek,mt8173-xhci"
|
||||||
- reg : specifies physical base address and size of the registers
|
- reg : specifies physical base address and size of the registers
|
||||||
- reg-names: should be "mac" for xHCI MAC and "ippc" for IP port control
|
- reg-names: should be "mac" for xHCI MAC and "ippc" for IP port control
|
||||||
- interrupts : interrupt used by the controller
|
- interrupts : interrupt used by the controller
|
||||||
@ -68,10 +72,14 @@ usb30: usb@11270000 {
|
|||||||
|
|
||||||
In the case, xhci is added as subnode to mtu3. An example and the DT binding
|
In the case, xhci is added as subnode to mtu3. An example and the DT binding
|
||||||
details of mtu3 can be found in:
|
details of mtu3 can be found in:
|
||||||
Documentation/devicetree/bindings/usb/mt8173-mtu3.txt
|
Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
|
||||||
|
|
||||||
Required properties:
|
Required properties:
|
||||||
- compatible : should contain "mediatek,mt8173-xhci"
|
- compatible : should be "mediatek,<soc-model>-xhci", "mediatek,mtk-xhci",
|
||||||
|
soc-model is the name of SoC, such as mt8173, mt2712 etc, when using
|
||||||
|
"mediatek,mtk-xhci" compatible string, you need SoC specific ones in
|
||||||
|
addition, one of:
|
||||||
|
- "mediatek,mt8173-xhci"
|
||||||
- reg : specifies physical base address and size of the registers
|
- reg : specifies physical base address and size of the registers
|
||||||
- reg-names: should be "mac" for xHCI MAC
|
- reg-names: should be "mac" for xHCI MAC
|
||||||
- interrupts : interrupt used by the host controller
|
- interrupts : interrupt used by the host controller
|
@ -1,7 +1,11 @@
|
|||||||
The device node for Mediatek USB3.0 DRD controller
|
The device node for Mediatek USB3.0 DRD controller
|
||||||
|
|
||||||
Required properties:
|
Required properties:
|
||||||
- compatible : should be "mediatek,mt8173-mtu3"
|
- compatible : should be "mediatek,<soc-model>-mtu3", "mediatek,mtu3",
|
||||||
|
soc-model is the name of SoC, such as mt8173, mt2712 etc,
|
||||||
|
when using "mediatek,mtu3" compatible string, you need SoC specific
|
||||||
|
ones in addition, one of:
|
||||||
|
- "mediatek,mt8173-mtu3"
|
||||||
- reg : specifies physical base address and size of the registers
|
- reg : specifies physical base address and size of the registers
|
||||||
- reg-names: should be "mac" for device IP and "ippc" for IP port control
|
- reg-names: should be "mac" for device IP and "ippc" for IP port control
|
||||||
- interrupts : interrupt used by the device IP
|
- interrupts : interrupt used by the device IP
|
||||||
@ -44,7 +48,7 @@ Optional properties:
|
|||||||
Sub-nodes:
|
Sub-nodes:
|
||||||
The xhci should be added as subnode to mtu3 as shown in the following example
|
The xhci should be added as subnode to mtu3 as shown in the following example
|
||||||
if host mode is enabled. The DT binding details of xhci can be found in:
|
if host mode is enabled. The DT binding details of xhci can be found in:
|
||||||
Documentation/devicetree/bindings/usb/mt8173-xhci.txt
|
Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
ssusb: usb@11271000 {
|
ssusb: usb@11271000 {
|
@ -3,20 +3,30 @@ Renesas Electronics USB3.0 Peripheral driver
|
|||||||
Required properties:
|
Required properties:
|
||||||
- compatible: Must contain one of the following:
|
- compatible: Must contain one of the following:
|
||||||
- "renesas,r8a7795-usb3-peri"
|
- "renesas,r8a7795-usb3-peri"
|
||||||
|
- "renesas,r8a7796-usb3-peri"
|
||||||
|
- "renesas,rcar-gen3-usb3-peri" for a generic R-Car Gen3 compatible
|
||||||
|
device
|
||||||
|
|
||||||
|
When compatible with the generic version, nodes must list the
|
||||||
|
SoC-specific version corresponding to the platform first
|
||||||
|
followed by the generic version.
|
||||||
|
|
||||||
- reg: Base address and length of the register for the USB3.0 Peripheral
|
- reg: Base address and length of the register for the USB3.0 Peripheral
|
||||||
- interrupts: Interrupt specifier for the USB3.0 Peripheral
|
- interrupts: Interrupt specifier for the USB3.0 Peripheral
|
||||||
- clocks: clock phandle and specifier pair
|
- clocks: clock phandle and specifier pair
|
||||||
|
|
||||||
Example:
|
Example of R-Car H3 ES1.x:
|
||||||
usb3_peri0: usb@ee020000 {
|
usb3_peri0: usb@ee020000 {
|
||||||
compatible = "renesas,r8a7795-usb3-peri";
|
compatible = "renesas,r8a7795-usb3-peri",
|
||||||
|
"renesas,rcar-gen3-usb3-peri";
|
||||||
reg = <0 0xee020000 0 0x400>;
|
reg = <0 0xee020000 0 0x400>;
|
||||||
interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&cpg CPG_MOD 328>;
|
clocks = <&cpg CPG_MOD 328>;
|
||||||
};
|
};
|
||||||
|
|
||||||
usb3_peri1: usb@ee060000 {
|
usb3_peri1: usb@ee060000 {
|
||||||
compatible = "renesas,r8a7795-usb3-peri";
|
compatible = "renesas,r8a7795-usb3-peri",
|
||||||
|
"renesas,rcar-gen3-usb3-peri";
|
||||||
reg = <0 0xee060000 0 0x400>;
|
reg = <0 0xee060000 0 0x400>;
|
||||||
interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
|
interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
clocks = <&cpg CPG_MOD 327>;
|
clocks = <&cpg CPG_MOD 327>;
|
||||||
|
10
MAINTAINERS
10
MAINTAINERS
@ -1570,7 +1570,7 @@ M: Chunfeng Yun <chunfeng.yun@mediatek.com>
|
|||||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||||
L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
|
L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: drivers/phy/phy-mt65xx-usb3.c
|
F: drivers/phy/mediatek/phy-mtk-tphy.c
|
||||||
|
|
||||||
ARM/MICREL KS8695 ARCHITECTURE
|
ARM/MICREL KS8695 ARCHITECTURE
|
||||||
M: Greg Ungerer <gerg@uclinux.org>
|
M: Greg Ungerer <gerg@uclinux.org>
|
||||||
@ -8475,6 +8475,14 @@ M: Sean Wang <sean.wang@mediatek.com>
|
|||||||
S: Maintained
|
S: Maintained
|
||||||
F: drivers/char/hw_random/mtk-rng.c
|
F: drivers/char/hw_random/mtk-rng.c
|
||||||
|
|
||||||
|
MEDIATEK USB3 DRD IP DRIVER
|
||||||
|
M: Chunfeng Yun <chunfeng.yun@mediatek.com>
|
||||||
|
L: linux-usb@vger.kernel.org (moderated for non-subscribers)
|
||||||
|
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||||
|
L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
|
||||||
|
S: Maintained
|
||||||
|
F: drivers/usb/mtu3/
|
||||||
|
|
||||||
MEGACHIPS STDPXXXX-GE-B850V3-FW LVDS/DP++ BRIDGES
|
MEGACHIPS STDPXXXX-GE-B850V3-FW LVDS/DP++ BRIDGES
|
||||||
M: Peter Senna Tschudin <peter.senna@collabora.com>
|
M: Peter Senna Tschudin <peter.senna@collabora.com>
|
||||||
M: Martin Donnelly <martin.donnelly@ge.com>
|
M: Martin Donnelly <martin.donnelly@ge.com>
|
||||||
|
@ -26,14 +26,6 @@ config PHY_LPC18XX_USB_OTG
|
|||||||
This driver is need for USB0 support on LPC18xx/43xx and takes
|
This driver is need for USB0 support on LPC18xx/43xx and takes
|
||||||
care of enabling and clock setup.
|
care of enabling and clock setup.
|
||||||
|
|
||||||
config PHY_MT65XX_USB3
|
|
||||||
tristate "Mediatek USB3.0 PHY Driver"
|
|
||||||
depends on ARCH_MEDIATEK && OF
|
|
||||||
select GENERIC_PHY
|
|
||||||
help
|
|
||||||
Say 'Y' here to add support for Mediatek USB3.0 PHY driver,
|
|
||||||
it supports multiple usb2.0 and usb3.0 ports.
|
|
||||||
|
|
||||||
config PHY_PISTACHIO_USB
|
config PHY_PISTACHIO_USB
|
||||||
tristate "IMG Pistachio USB2.0 PHY driver"
|
tristate "IMG Pistachio USB2.0 PHY driver"
|
||||||
depends on MACH_PISTACHIO
|
depends on MACH_PISTACHIO
|
||||||
@ -53,8 +45,10 @@ source "drivers/phy/amlogic/Kconfig"
|
|||||||
source "drivers/phy/broadcom/Kconfig"
|
source "drivers/phy/broadcom/Kconfig"
|
||||||
source "drivers/phy/hisilicon/Kconfig"
|
source "drivers/phy/hisilicon/Kconfig"
|
||||||
source "drivers/phy/marvell/Kconfig"
|
source "drivers/phy/marvell/Kconfig"
|
||||||
|
source "drivers/phy/mediatek/Kconfig"
|
||||||
source "drivers/phy/motorola/Kconfig"
|
source "drivers/phy/motorola/Kconfig"
|
||||||
source "drivers/phy/qualcomm/Kconfig"
|
source "drivers/phy/qualcomm/Kconfig"
|
||||||
|
source "drivers/phy/ralink/Kconfig"
|
||||||
source "drivers/phy/renesas/Kconfig"
|
source "drivers/phy/renesas/Kconfig"
|
||||||
source "drivers/phy/rockchip/Kconfig"
|
source "drivers/phy/rockchip/Kconfig"
|
||||||
source "drivers/phy/samsung/Kconfig"
|
source "drivers/phy/samsung/Kconfig"
|
||||||
|
@ -4,12 +4,12 @@
|
|||||||
|
|
||||||
obj-$(CONFIG_GENERIC_PHY) += phy-core.o
|
obj-$(CONFIG_GENERIC_PHY) += phy-core.o
|
||||||
obj-$(CONFIG_PHY_LPC18XX_USB_OTG) += phy-lpc18xx-usb-otg.o
|
obj-$(CONFIG_PHY_LPC18XX_USB_OTG) += phy-lpc18xx-usb-otg.o
|
||||||
obj-$(CONFIG_PHY_MT65XX_USB3) += phy-mt65xx-usb3.o
|
|
||||||
obj-$(CONFIG_PHY_XGENE) += phy-xgene.o
|
obj-$(CONFIG_PHY_XGENE) += phy-xgene.o
|
||||||
obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o
|
obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o
|
||||||
|
|
||||||
obj-$(CONFIG_ARCH_SUNXI) += allwinner/
|
obj-$(CONFIG_ARCH_SUNXI) += allwinner/
|
||||||
obj-$(CONFIG_ARCH_MESON) += amlogic/
|
obj-$(CONFIG_ARCH_MESON) += amlogic/
|
||||||
|
obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
|
||||||
obj-$(CONFIG_ARCH_RENESAS) += renesas/
|
obj-$(CONFIG_ARCH_RENESAS) += renesas/
|
||||||
obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
|
obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
|
||||||
obj-$(CONFIG_ARCH_TEGRA) += tegra/
|
obj-$(CONFIG_ARCH_TEGRA) += tegra/
|
||||||
@ -18,6 +18,7 @@ obj-y += broadcom/ \
|
|||||||
marvell/ \
|
marvell/ \
|
||||||
motorola/ \
|
motorola/ \
|
||||||
qualcomm/ \
|
qualcomm/ \
|
||||||
|
ralink/ \
|
||||||
samsung/ \
|
samsung/ \
|
||||||
st/ \
|
st/ \
|
||||||
ti/
|
ti/
|
||||||
|
@ -87,6 +87,16 @@
|
|||||||
#define PHY_DISCON_TH_SEL 0x2a
|
#define PHY_DISCON_TH_SEL 0x2a
|
||||||
#define PHY_SQUELCH_DETECT 0x3c
|
#define PHY_SQUELCH_DETECT 0x3c
|
||||||
|
|
||||||
|
/* A83T specific control bits for PHY0 */
|
||||||
|
#define PHY_CTL_VBUSVLDEXT BIT(5)
|
||||||
|
#define PHY_CTL_SIDDQ BIT(3)
|
||||||
|
|
||||||
|
/* A83T specific control bits for PHY2 HSIC */
|
||||||
|
#define SUNXI_EHCI_HS_FORCE BIT(20)
|
||||||
|
#define SUNXI_HSIC_CONNECT_DET BIT(17)
|
||||||
|
#define SUNXI_HSIC_CONNECT_INT BIT(16)
|
||||||
|
#define SUNXI_HSIC BIT(1)
|
||||||
|
|
||||||
#define MAX_PHYS 4
|
#define MAX_PHYS 4
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -100,6 +110,7 @@ enum sun4i_usb_phy_type {
|
|||||||
sun4i_a10_phy,
|
sun4i_a10_phy,
|
||||||
sun6i_a31_phy,
|
sun6i_a31_phy,
|
||||||
sun8i_a33_phy,
|
sun8i_a33_phy,
|
||||||
|
sun8i_a83t_phy,
|
||||||
sun8i_h3_phy,
|
sun8i_h3_phy,
|
||||||
sun8i_v3s_phy,
|
sun8i_v3s_phy,
|
||||||
sun50i_a64_phy,
|
sun50i_a64_phy,
|
||||||
@ -107,6 +118,7 @@ enum sun4i_usb_phy_type {
|
|||||||
|
|
||||||
struct sun4i_usb_phy_cfg {
|
struct sun4i_usb_phy_cfg {
|
||||||
int num_phys;
|
int num_phys;
|
||||||
|
int hsic_index;
|
||||||
enum sun4i_usb_phy_type type;
|
enum sun4i_usb_phy_type type;
|
||||||
u32 disc_thresh;
|
u32 disc_thresh;
|
||||||
u8 phyctl_offset;
|
u8 phyctl_offset;
|
||||||
@ -126,6 +138,7 @@ struct sun4i_usb_phy_data {
|
|||||||
struct regulator *vbus;
|
struct regulator *vbus;
|
||||||
struct reset_control *reset;
|
struct reset_control *reset;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
|
struct clk *clk2;
|
||||||
bool regulator_on;
|
bool regulator_on;
|
||||||
int index;
|
int index;
|
||||||
} phys[MAX_PHYS];
|
} phys[MAX_PHYS];
|
||||||
@ -232,6 +245,7 @@ static void sun4i_usb_phy_write(struct sun4i_usb_phy *phy, u32 addr, u32 data,
|
|||||||
|
|
||||||
static void sun4i_usb_phy_passby(struct sun4i_usb_phy *phy, int enable)
|
static void sun4i_usb_phy_passby(struct sun4i_usb_phy *phy, int enable)
|
||||||
{
|
{
|
||||||
|
struct sun4i_usb_phy_data *phy_data = to_sun4i_usb_phy_data(phy);
|
||||||
u32 bits, reg_value;
|
u32 bits, reg_value;
|
||||||
|
|
||||||
if (!phy->pmu)
|
if (!phy->pmu)
|
||||||
@ -240,6 +254,11 @@ static void sun4i_usb_phy_passby(struct sun4i_usb_phy *phy, int enable)
|
|||||||
bits = SUNXI_AHB_ICHR8_EN | SUNXI_AHB_INCR4_BURST_EN |
|
bits = SUNXI_AHB_ICHR8_EN | SUNXI_AHB_INCR4_BURST_EN |
|
||||||
SUNXI_AHB_INCRX_ALIGN_EN | SUNXI_ULPI_BYPASS_EN;
|
SUNXI_AHB_INCRX_ALIGN_EN | SUNXI_ULPI_BYPASS_EN;
|
||||||
|
|
||||||
|
/* A83T USB2 is HSIC */
|
||||||
|
if (phy_data->cfg->type == sun8i_a83t_phy && phy->index == 2)
|
||||||
|
bits |= SUNXI_EHCI_HS_FORCE | SUNXI_HSIC_CONNECT_INT |
|
||||||
|
SUNXI_HSIC;
|
||||||
|
|
||||||
reg_value = readl(phy->pmu);
|
reg_value = readl(phy->pmu);
|
||||||
|
|
||||||
if (enable)
|
if (enable)
|
||||||
@ -261,27 +280,43 @@ static int sun4i_usb_phy_init(struct phy *_phy)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = reset_control_deassert(phy->reset);
|
ret = clk_prepare_enable(phy->clk2);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
clk_disable_unprepare(phy->clk);
|
clk_disable_unprepare(phy->clk);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (phy->pmu && data->cfg->enable_pmu_unk1) {
|
ret = reset_control_deassert(phy->reset);
|
||||||
val = readl(phy->pmu + REG_PMU_UNK1);
|
if (ret) {
|
||||||
writel(val & ~2, phy->pmu + REG_PMU_UNK1);
|
clk_disable_unprepare(phy->clk2);
|
||||||
|
clk_disable_unprepare(phy->clk);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable USB 45 Ohm resistor calibration */
|
if (data->cfg->type == sun8i_a83t_phy) {
|
||||||
if (phy->index == 0)
|
if (phy->index == 0) {
|
||||||
sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, 0x01, 1);
|
val = readl(data->base + data->cfg->phyctl_offset);
|
||||||
|
val |= PHY_CTL_VBUSVLDEXT;
|
||||||
|
val &= ~PHY_CTL_SIDDQ;
|
||||||
|
writel(val, data->base + data->cfg->phyctl_offset);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (phy->pmu && data->cfg->enable_pmu_unk1) {
|
||||||
|
val = readl(phy->pmu + REG_PMU_UNK1);
|
||||||
|
writel(val & ~2, phy->pmu + REG_PMU_UNK1);
|
||||||
|
}
|
||||||
|
|
||||||
/* Adjust PHY's magnitude and rate */
|
/* Enable USB 45 Ohm resistor calibration */
|
||||||
sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, 0x14, 5);
|
if (phy->index == 0)
|
||||||
|
sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, 0x01, 1);
|
||||||
|
|
||||||
/* Disconnect threshold adjustment */
|
/* Adjust PHY's magnitude and rate */
|
||||||
sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL,
|
sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, 0x14, 5);
|
||||||
data->cfg->disc_thresh, 2);
|
|
||||||
|
/* Disconnect threshold adjustment */
|
||||||
|
sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL,
|
||||||
|
data->cfg->disc_thresh, 2);
|
||||||
|
}
|
||||||
|
|
||||||
sun4i_usb_phy_passby(phy, 1);
|
sun4i_usb_phy_passby(phy, 1);
|
||||||
|
|
||||||
@ -307,6 +342,13 @@ static int sun4i_usb_phy_exit(struct phy *_phy)
|
|||||||
struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
|
struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
|
||||||
|
|
||||||
if (phy->index == 0) {
|
if (phy->index == 0) {
|
||||||
|
if (data->cfg->type == sun8i_a83t_phy) {
|
||||||
|
void __iomem *phyctl = data->base +
|
||||||
|
data->cfg->phyctl_offset;
|
||||||
|
|
||||||
|
writel(readl(phyctl) | PHY_CTL_SIDDQ, phyctl);
|
||||||
|
}
|
||||||
|
|
||||||
/* Disable pull-ups */
|
/* Disable pull-ups */
|
||||||
sun4i_usb_phy0_update_iscr(_phy, ISCR_DPDM_PULLUP_EN, 0);
|
sun4i_usb_phy0_update_iscr(_phy, ISCR_DPDM_PULLUP_EN, 0);
|
||||||
sun4i_usb_phy0_update_iscr(_phy, ISCR_ID_PULLUP_EN, 0);
|
sun4i_usb_phy0_update_iscr(_phy, ISCR_ID_PULLUP_EN, 0);
|
||||||
@ -315,6 +357,7 @@ static int sun4i_usb_phy_exit(struct phy *_phy)
|
|||||||
|
|
||||||
sun4i_usb_phy_passby(phy, 0);
|
sun4i_usb_phy_passby(phy, 0);
|
||||||
reset_control_assert(phy->reset);
|
reset_control_assert(phy->reset);
|
||||||
|
clk_disable_unprepare(phy->clk2);
|
||||||
clk_disable_unprepare(phy->clk);
|
clk_disable_unprepare(phy->clk);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -653,19 +696,25 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
data->id_det_gpio = devm_gpiod_get_optional(dev, "usb0_id_det",
|
data->id_det_gpio = devm_gpiod_get_optional(dev, "usb0_id_det",
|
||||||
GPIOD_IN);
|
GPIOD_IN);
|
||||||
if (IS_ERR(data->id_det_gpio))
|
if (IS_ERR(data->id_det_gpio)) {
|
||||||
|
dev_err(dev, "Couldn't request ID GPIO\n");
|
||||||
return PTR_ERR(data->id_det_gpio);
|
return PTR_ERR(data->id_det_gpio);
|
||||||
|
}
|
||||||
|
|
||||||
data->vbus_det_gpio = devm_gpiod_get_optional(dev, "usb0_vbus_det",
|
data->vbus_det_gpio = devm_gpiod_get_optional(dev, "usb0_vbus_det",
|
||||||
GPIOD_IN);
|
GPIOD_IN);
|
||||||
if (IS_ERR(data->vbus_det_gpio))
|
if (IS_ERR(data->vbus_det_gpio)) {
|
||||||
|
dev_err(dev, "Couldn't request VBUS detect GPIO\n");
|
||||||
return PTR_ERR(data->vbus_det_gpio);
|
return PTR_ERR(data->vbus_det_gpio);
|
||||||
|
}
|
||||||
|
|
||||||
if (of_find_property(np, "usb0_vbus_power-supply", NULL)) {
|
if (of_find_property(np, "usb0_vbus_power-supply", NULL)) {
|
||||||
data->vbus_power_supply = devm_power_supply_get_by_phandle(dev,
|
data->vbus_power_supply = devm_power_supply_get_by_phandle(dev,
|
||||||
"usb0_vbus_power-supply");
|
"usb0_vbus_power-supply");
|
||||||
if (IS_ERR(data->vbus_power_supply))
|
if (IS_ERR(data->vbus_power_supply)) {
|
||||||
|
dev_err(dev, "Couldn't get the VBUS power supply\n");
|
||||||
return PTR_ERR(data->vbus_power_supply);
|
return PTR_ERR(data->vbus_power_supply);
|
||||||
|
}
|
||||||
|
|
||||||
if (!data->vbus_power_supply)
|
if (!data->vbus_power_supply)
|
||||||
return -EPROBE_DEFER;
|
return -EPROBE_DEFER;
|
||||||
@ -674,8 +723,10 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
|
|||||||
data->dr_mode = of_usb_get_dr_mode_by_phy(np, 0);
|
data->dr_mode = of_usb_get_dr_mode_by_phy(np, 0);
|
||||||
|
|
||||||
data->extcon = devm_extcon_dev_allocate(dev, sun4i_usb_phy0_cable);
|
data->extcon = devm_extcon_dev_allocate(dev, sun4i_usb_phy0_cable);
|
||||||
if (IS_ERR(data->extcon))
|
if (IS_ERR(data->extcon)) {
|
||||||
|
dev_err(dev, "Couldn't allocate our extcon device\n");
|
||||||
return PTR_ERR(data->extcon);
|
return PTR_ERR(data->extcon);
|
||||||
|
}
|
||||||
|
|
||||||
ret = devm_extcon_dev_register(dev, data->extcon);
|
ret = devm_extcon_dev_register(dev, data->extcon);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@ -690,8 +741,13 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
|
|||||||
snprintf(name, sizeof(name), "usb%d_vbus", i);
|
snprintf(name, sizeof(name), "usb%d_vbus", i);
|
||||||
phy->vbus = devm_regulator_get_optional(dev, name);
|
phy->vbus = devm_regulator_get_optional(dev, name);
|
||||||
if (IS_ERR(phy->vbus)) {
|
if (IS_ERR(phy->vbus)) {
|
||||||
if (PTR_ERR(phy->vbus) == -EPROBE_DEFER)
|
if (PTR_ERR(phy->vbus) == -EPROBE_DEFER) {
|
||||||
|
dev_err(dev,
|
||||||
|
"Couldn't get regulator %s... Deferring probe\n",
|
||||||
|
name);
|
||||||
return -EPROBE_DEFER;
|
return -EPROBE_DEFER;
|
||||||
|
}
|
||||||
|
|
||||||
phy->vbus = NULL;
|
phy->vbus = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -706,6 +762,17 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
|
|||||||
return PTR_ERR(phy->clk);
|
return PTR_ERR(phy->clk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The first PHY is always tied to OTG, and never HSIC */
|
||||||
|
if (data->cfg->hsic_index && i == data->cfg->hsic_index) {
|
||||||
|
/* HSIC needs secondary clock */
|
||||||
|
snprintf(name, sizeof(name), "usb%d_hsic_12M", i);
|
||||||
|
phy->clk2 = devm_clk_get(dev, name);
|
||||||
|
if (IS_ERR(phy->clk2)) {
|
||||||
|
dev_err(dev, "failed to get clock %s\n", name);
|
||||||
|
return PTR_ERR(phy->clk2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
snprintf(name, sizeof(name), "usb%d_reset", i);
|
snprintf(name, sizeof(name), "usb%d_reset", i);
|
||||||
phy->reset = devm_reset_control_get(dev, name);
|
phy->reset = devm_reset_control_get(dev, name);
|
||||||
if (IS_ERR(phy->reset)) {
|
if (IS_ERR(phy->reset)) {
|
||||||
@ -775,6 +842,8 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
|
|||||||
return PTR_ERR(phy_provider);
|
return PTR_ERR(phy_provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dev_dbg(dev, "successfully loaded\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -832,6 +901,14 @@ static const struct sun4i_usb_phy_cfg sun8i_a33_cfg = {
|
|||||||
.enable_pmu_unk1 = false,
|
.enable_pmu_unk1 = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct sun4i_usb_phy_cfg sun8i_a83t_cfg = {
|
||||||
|
.num_phys = 3,
|
||||||
|
.hsic_index = 2,
|
||||||
|
.type = sun8i_a83t_phy,
|
||||||
|
.phyctl_offset = REG_PHYCTL_A33,
|
||||||
|
.dedicated_clocks = true,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = {
|
static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = {
|
||||||
.num_phys = 4,
|
.num_phys = 4,
|
||||||
.type = sun8i_h3_phy,
|
.type = sun8i_h3_phy,
|
||||||
@ -868,6 +945,7 @@ static const struct of_device_id sun4i_usb_phy_of_match[] = {
|
|||||||
{ .compatible = "allwinner,sun7i-a20-usb-phy", .data = &sun7i_a20_cfg },
|
{ .compatible = "allwinner,sun7i-a20-usb-phy", .data = &sun7i_a20_cfg },
|
||||||
{ .compatible = "allwinner,sun8i-a23-usb-phy", .data = &sun8i_a23_cfg },
|
{ .compatible = "allwinner,sun8i-a23-usb-phy", .data = &sun8i_a23_cfg },
|
||||||
{ .compatible = "allwinner,sun8i-a33-usb-phy", .data = &sun8i_a33_cfg },
|
{ .compatible = "allwinner,sun8i-a33-usb-phy", .data = &sun8i_a33_cfg },
|
||||||
|
{ .compatible = "allwinner,sun8i-a83t-usb-phy", .data = &sun8i_a83t_cfg },
|
||||||
{ .compatible = "allwinner,sun8i-h3-usb-phy", .data = &sun8i_h3_cfg },
|
{ .compatible = "allwinner,sun8i-h3-usb-phy", .data = &sun8i_h3_cfg },
|
||||||
{ .compatible = "allwinner,sun8i-v3s-usb-phy", .data = &sun8i_v3s_cfg },
|
{ .compatible = "allwinner,sun8i-v3s-usb-phy", .data = &sun8i_v3s_cfg },
|
||||||
{ .compatible = "allwinner,sun50i-a64-usb-phy",
|
{ .compatible = "allwinner,sun50i-a64-usb-phy",
|
||||||
|
@ -335,7 +335,7 @@ static int brcm_nsp_sata_init(struct brcm_sata_port *port)
|
|||||||
|
|
||||||
/* Wait for pll_seq_done bit */
|
/* Wait for pll_seq_done bit */
|
||||||
try = 50;
|
try = 50;
|
||||||
while (try--) {
|
while (--try) {
|
||||||
val = brcm_sata_phy_rd(base, BLOCK0_REG_BANK,
|
val = brcm_sata_phy_rd(base, BLOCK0_REG_BANK,
|
||||||
BLOCK0_XGXSSTATUS);
|
BLOCK0_XGXSSTATUS);
|
||||||
if (val & BLOCK0_XGXSSTATUS_PLL_LOCK)
|
if (val & BLOCK0_XGXSSTATUS_PLL_LOCK)
|
||||||
|
14
drivers/phy/mediatek/Kconfig
Normal file
14
drivers/phy/mediatek/Kconfig
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#
|
||||||
|
# Phy drivers for Mediatek devices
|
||||||
|
#
|
||||||
|
config PHY_MTK_TPHY
|
||||||
|
tristate "MediaTek T-PHY Driver"
|
||||||
|
depends on ARCH_MEDIATEK && OF
|
||||||
|
select GENERIC_PHY
|
||||||
|
help
|
||||||
|
Say 'Y' here to add support for MediaTek T-PHY driver,
|
||||||
|
it supports multiple usb2.0, usb3.0 ports, PCIe and
|
||||||
|
SATA, and meanwhile supports two version T-PHY which have
|
||||||
|
different banks layout, the T-PHY with shared banks between
|
||||||
|
multi-ports is first version, otherwise is second veriosn,
|
||||||
|
so you can easily distinguish them by banks layout.
|
5
drivers/phy/mediatek/Makefile
Normal file
5
drivers/phy/mediatek/Makefile
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#
|
||||||
|
# Makefile for the phy drivers.
|
||||||
|
#
|
||||||
|
|
||||||
|
obj-$(CONFIG_PHY_MTK_TPHY) += phy-mtk-tphy.o
|
@ -29,7 +29,7 @@
|
|||||||
#define SSUSB_SIFSLV_V1_U2FREQ 0x100 /* shared by u2 phys */
|
#define SSUSB_SIFSLV_V1_U2FREQ 0x100 /* shared by u2 phys */
|
||||||
/* u2 phy bank */
|
/* u2 phy bank */
|
||||||
#define SSUSB_SIFSLV_V1_U2PHY_COM 0x000
|
#define SSUSB_SIFSLV_V1_U2PHY_COM 0x000
|
||||||
/* u3 phy banks */
|
/* u3/pcie/sata phy banks */
|
||||||
#define SSUSB_SIFSLV_V1_U3PHYD 0x000
|
#define SSUSB_SIFSLV_V1_U3PHYD 0x000
|
||||||
#define SSUSB_SIFSLV_V1_U3PHYA 0x200
|
#define SSUSB_SIFSLV_V1_U3PHYA 0x200
|
||||||
|
|
||||||
@ -38,7 +38,7 @@
|
|||||||
#define SSUSB_SIFSLV_V2_MISC 0x000
|
#define SSUSB_SIFSLV_V2_MISC 0x000
|
||||||
#define SSUSB_SIFSLV_V2_U2FREQ 0x100
|
#define SSUSB_SIFSLV_V2_U2FREQ 0x100
|
||||||
#define SSUSB_SIFSLV_V2_U2PHY_COM 0x300
|
#define SSUSB_SIFSLV_V2_U2PHY_COM 0x300
|
||||||
/* u3 phy banks */
|
/* u3/pcie/sata phy banks */
|
||||||
#define SSUSB_SIFSLV_V2_SPLLC 0x000
|
#define SSUSB_SIFSLV_V2_SPLLC 0x000
|
||||||
#define SSUSB_SIFSLV_V2_CHIP 0x100
|
#define SSUSB_SIFSLV_V2_CHIP 0x100
|
||||||
#define SSUSB_SIFSLV_V2_U3PHYD 0x200
|
#define SSUSB_SIFSLV_V2_U3PHYD 0x200
|
||||||
@ -99,6 +99,23 @@
|
|||||||
#define P2C_RG_SESSEND BIT(4)
|
#define P2C_RG_SESSEND BIT(4)
|
||||||
#define P2C_RG_AVALID BIT(2)
|
#define P2C_RG_AVALID BIT(2)
|
||||||
|
|
||||||
|
#define U3P_U3_CHIP_GPIO_CTLD 0x0c
|
||||||
|
#define P3C_REG_IP_SW_RST BIT(31)
|
||||||
|
#define P3C_MCU_BUS_CK_GATE_EN BIT(30)
|
||||||
|
#define P3C_FORCE_IP_SW_RST BIT(29)
|
||||||
|
|
||||||
|
#define U3P_U3_CHIP_GPIO_CTLE 0x10
|
||||||
|
#define P3C_RG_SWRST_U3_PHYD BIT(25)
|
||||||
|
#define P3C_RG_SWRST_U3_PHYD_FORCE_EN BIT(24)
|
||||||
|
|
||||||
|
#define U3P_U3_PHYA_REG0 0x000
|
||||||
|
#define P3A_RG_CLKDRV_OFF GENMASK(3, 2)
|
||||||
|
#define P3A_RG_CLKDRV_OFF_VAL(x) ((0x3 & (x)) << 2)
|
||||||
|
|
||||||
|
#define U3P_U3_PHYA_REG1 0x004
|
||||||
|
#define P3A_RG_CLKDRV_AMP GENMASK(31, 29)
|
||||||
|
#define P3A_RG_CLKDRV_AMP_VAL(x) ((0x7 & (x)) << 29)
|
||||||
|
|
||||||
#define U3P_U3_PHYA_REG6 0x018
|
#define U3P_U3_PHYA_REG6 0x018
|
||||||
#define P3A_RG_TX_EIDLE_CM GENMASK(31, 28)
|
#define P3A_RG_TX_EIDLE_CM GENMASK(31, 28)
|
||||||
#define P3A_RG_TX_EIDLE_CM_VAL(x) ((0xf & (x)) << 28)
|
#define P3A_RG_TX_EIDLE_CM_VAL(x) ((0xf & (x)) << 28)
|
||||||
@ -108,9 +125,40 @@
|
|||||||
#define P3A_RG_RX_DAC_MUX_VAL(x) ((0x1f & (x)) << 1)
|
#define P3A_RG_RX_DAC_MUX_VAL(x) ((0x1f & (x)) << 1)
|
||||||
|
|
||||||
#define U3P_U3_PHYA_DA_REG0 0x100
|
#define U3P_U3_PHYA_DA_REG0 0x100
|
||||||
|
#define P3A_RG_XTAL_EXT_PE2H GENMASK(17, 16)
|
||||||
|
#define P3A_RG_XTAL_EXT_PE2H_VAL(x) ((0x3 & (x)) << 16)
|
||||||
|
#define P3A_RG_XTAL_EXT_PE1H GENMASK(13, 12)
|
||||||
|
#define P3A_RG_XTAL_EXT_PE1H_VAL(x) ((0x3 & (x)) << 12)
|
||||||
#define P3A_RG_XTAL_EXT_EN_U3 GENMASK(11, 10)
|
#define P3A_RG_XTAL_EXT_EN_U3 GENMASK(11, 10)
|
||||||
#define P3A_RG_XTAL_EXT_EN_U3_VAL(x) ((0x3 & (x)) << 10)
|
#define P3A_RG_XTAL_EXT_EN_U3_VAL(x) ((0x3 & (x)) << 10)
|
||||||
|
|
||||||
|
#define U3P_U3_PHYA_DA_REG4 0x108
|
||||||
|
#define P3A_RG_PLL_DIVEN_PE2H GENMASK(21, 19)
|
||||||
|
#define P3A_RG_PLL_BC_PE2H GENMASK(7, 6)
|
||||||
|
#define P3A_RG_PLL_BC_PE2H_VAL(x) ((0x3 & (x)) << 6)
|
||||||
|
|
||||||
|
#define U3P_U3_PHYA_DA_REG5 0x10c
|
||||||
|
#define P3A_RG_PLL_BR_PE2H GENMASK(29, 28)
|
||||||
|
#define P3A_RG_PLL_BR_PE2H_VAL(x) ((0x3 & (x)) << 28)
|
||||||
|
#define P3A_RG_PLL_IC_PE2H GENMASK(15, 12)
|
||||||
|
#define P3A_RG_PLL_IC_PE2H_VAL(x) ((0xf & (x)) << 12)
|
||||||
|
|
||||||
|
#define U3P_U3_PHYA_DA_REG6 0x110
|
||||||
|
#define P3A_RG_PLL_IR_PE2H GENMASK(19, 16)
|
||||||
|
#define P3A_RG_PLL_IR_PE2H_VAL(x) ((0xf & (x)) << 16)
|
||||||
|
|
||||||
|
#define U3P_U3_PHYA_DA_REG7 0x114
|
||||||
|
#define P3A_RG_PLL_BP_PE2H GENMASK(19, 16)
|
||||||
|
#define P3A_RG_PLL_BP_PE2H_VAL(x) ((0xf & (x)) << 16)
|
||||||
|
|
||||||
|
#define U3P_U3_PHYA_DA_REG20 0x13c
|
||||||
|
#define P3A_RG_PLL_DELTA1_PE2H GENMASK(31, 16)
|
||||||
|
#define P3A_RG_PLL_DELTA1_PE2H_VAL(x) ((0xffff & (x)) << 16)
|
||||||
|
|
||||||
|
#define U3P_U3_PHYA_DA_REG25 0x148
|
||||||
|
#define P3A_RG_PLL_DELTA_PE2H GENMASK(15, 0)
|
||||||
|
#define P3A_RG_PLL_DELTA_PE2H_VAL(x) (0xffff & (x))
|
||||||
|
|
||||||
#define U3P_U3_PHYD_LFPS1 0x00c
|
#define U3P_U3_PHYD_LFPS1 0x00c
|
||||||
#define P3D_RG_FWAKE_TH GENMASK(21, 16)
|
#define P3D_RG_FWAKE_TH GENMASK(21, 16)
|
||||||
#define P3D_RG_FWAKE_TH_VAL(x) ((0x3f & (x)) << 16)
|
#define P3D_RG_FWAKE_TH_VAL(x) ((0x3f & (x)) << 16)
|
||||||
@ -151,15 +199,74 @@
|
|||||||
#define U3P_SR_COEF_DIVISOR 1000
|
#define U3P_SR_COEF_DIVISOR 1000
|
||||||
#define U3P_FM_DET_CYCLE_CNT 1024
|
#define U3P_FM_DET_CYCLE_CNT 1024
|
||||||
|
|
||||||
enum mt_phy_version {
|
/* SATA register setting */
|
||||||
MT_PHY_V1 = 1,
|
#define PHYD_CTRL_SIGNAL_MODE4 0x1c
|
||||||
MT_PHY_V2,
|
/* CDR Charge Pump P-path current adjustment */
|
||||||
|
#define RG_CDR_BICLTD1_GEN1_MSK GENMASK(23, 20)
|
||||||
|
#define RG_CDR_BICLTD1_GEN1_VAL(x) ((0xf & (x)) << 20)
|
||||||
|
#define RG_CDR_BICLTD0_GEN1_MSK GENMASK(11, 8)
|
||||||
|
#define RG_CDR_BICLTD0_GEN1_VAL(x) ((0xf & (x)) << 8)
|
||||||
|
|
||||||
|
#define PHYD_DESIGN_OPTION2 0x24
|
||||||
|
/* Symbol lock count selection */
|
||||||
|
#define RG_LOCK_CNT_SEL_MSK GENMASK(5, 4)
|
||||||
|
#define RG_LOCK_CNT_SEL_VAL(x) ((0x3 & (x)) << 4)
|
||||||
|
|
||||||
|
#define PHYD_DESIGN_OPTION9 0x40
|
||||||
|
/* COMWAK GAP width window */
|
||||||
|
#define RG_TG_MAX_MSK GENMASK(20, 16)
|
||||||
|
#define RG_TG_MAX_VAL(x) ((0x1f & (x)) << 16)
|
||||||
|
/* COMINIT GAP width window */
|
||||||
|
#define RG_T2_MAX_MSK GENMASK(13, 8)
|
||||||
|
#define RG_T2_MAX_VAL(x) ((0x3f & (x)) << 8)
|
||||||
|
/* COMWAK GAP width window */
|
||||||
|
#define RG_TG_MIN_MSK GENMASK(7, 5)
|
||||||
|
#define RG_TG_MIN_VAL(x) ((0x7 & (x)) << 5)
|
||||||
|
/* COMINIT GAP width window */
|
||||||
|
#define RG_T2_MIN_MSK GENMASK(4, 0)
|
||||||
|
#define RG_T2_MIN_VAL(x) (0x1f & (x))
|
||||||
|
|
||||||
|
#define ANA_RG_CTRL_SIGNAL1 0x4c
|
||||||
|
/* TX driver tail current control for 0dB de-empahsis mdoe for Gen1 speed */
|
||||||
|
#define RG_IDRV_0DB_GEN1_MSK GENMASK(13, 8)
|
||||||
|
#define RG_IDRV_0DB_GEN1_VAL(x) ((0x3f & (x)) << 8)
|
||||||
|
|
||||||
|
#define ANA_RG_CTRL_SIGNAL4 0x58
|
||||||
|
#define RG_CDR_BICLTR_GEN1_MSK GENMASK(23, 20)
|
||||||
|
#define RG_CDR_BICLTR_GEN1_VAL(x) ((0xf & (x)) << 20)
|
||||||
|
/* Loop filter R1 resistance adjustment for Gen1 speed */
|
||||||
|
#define RG_CDR_BR_GEN2_MSK GENMASK(10, 8)
|
||||||
|
#define RG_CDR_BR_GEN2_VAL(x) ((0x7 & (x)) << 8)
|
||||||
|
|
||||||
|
#define ANA_RG_CTRL_SIGNAL6 0x60
|
||||||
|
/* I-path capacitance adjustment for Gen1 */
|
||||||
|
#define RG_CDR_BC_GEN1_MSK GENMASK(28, 24)
|
||||||
|
#define RG_CDR_BC_GEN1_VAL(x) ((0x1f & (x)) << 24)
|
||||||
|
#define RG_CDR_BIRLTR_GEN1_MSK GENMASK(4, 0)
|
||||||
|
#define RG_CDR_BIRLTR_GEN1_VAL(x) (0x1f & (x))
|
||||||
|
|
||||||
|
#define ANA_EQ_EYE_CTRL_SIGNAL1 0x6c
|
||||||
|
/* RX Gen1 LEQ tuning step */
|
||||||
|
#define RG_EQ_DLEQ_LFI_GEN1_MSK GENMASK(11, 8)
|
||||||
|
#define RG_EQ_DLEQ_LFI_GEN1_VAL(x) ((0xf & (x)) << 8)
|
||||||
|
|
||||||
|
#define ANA_EQ_EYE_CTRL_SIGNAL4 0xd8
|
||||||
|
#define RG_CDR_BIRLTD0_GEN1_MSK GENMASK(20, 16)
|
||||||
|
#define RG_CDR_BIRLTD0_GEN1_VAL(x) ((0x1f & (x)) << 16)
|
||||||
|
|
||||||
|
#define ANA_EQ_EYE_CTRL_SIGNAL5 0xdc
|
||||||
|
#define RG_CDR_BIRLTD0_GEN3_MSK GENMASK(4, 0)
|
||||||
|
#define RG_CDR_BIRLTD0_GEN3_VAL(x) (0x1f & (x))
|
||||||
|
|
||||||
|
enum mtk_phy_version {
|
||||||
|
MTK_PHY_V1 = 1,
|
||||||
|
MTK_PHY_V2,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mt65xx_phy_pdata {
|
struct mtk_phy_pdata {
|
||||||
/* avoid RX sensitivity level degradation only for mt8173 */
|
/* avoid RX sensitivity level degradation only for mt8173 */
|
||||||
bool avoid_rx_sen_degradation;
|
bool avoid_rx_sen_degradation;
|
||||||
enum mt_phy_version version;
|
enum mtk_phy_version version;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct u2phy_banks {
|
struct u2phy_banks {
|
||||||
@ -175,7 +282,7 @@ struct u3phy_banks {
|
|||||||
void __iomem *phya; /* include u3phya_da */
|
void __iomem *phya; /* include u3phya_da */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mt65xx_phy_instance {
|
struct mtk_phy_instance {
|
||||||
struct phy *phy;
|
struct phy *phy;
|
||||||
void __iomem *port_base;
|
void __iomem *port_base;
|
||||||
union {
|
union {
|
||||||
@ -187,18 +294,18 @@ struct mt65xx_phy_instance {
|
|||||||
u8 type;
|
u8 type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mt65xx_u3phy {
|
struct mtk_tphy {
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
void __iomem *sif_base; /* only shared sif */
|
void __iomem *sif_base; /* only shared sif */
|
||||||
/* deprecated, use @ref_clk instead in phy instance */
|
/* deprecated, use @ref_clk instead in phy instance */
|
||||||
struct clk *u3phya_ref; /* reference clock of usb3 anolog phy */
|
struct clk *u3phya_ref; /* reference clock of usb3 anolog phy */
|
||||||
const struct mt65xx_phy_pdata *pdata;
|
const struct mtk_phy_pdata *pdata;
|
||||||
struct mt65xx_phy_instance **phys;
|
struct mtk_phy_instance **phys;
|
||||||
int nphys;
|
int nphys;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void hs_slew_rate_calibrate(struct mt65xx_u3phy *u3phy,
|
static void hs_slew_rate_calibrate(struct mtk_tphy *tphy,
|
||||||
struct mt65xx_phy_instance *instance)
|
struct mtk_phy_instance *instance)
|
||||||
{
|
{
|
||||||
struct u2phy_banks *u2_banks = &instance->u2_banks;
|
struct u2phy_banks *u2_banks = &instance->u2_banks;
|
||||||
void __iomem *fmreg = u2_banks->fmreg;
|
void __iomem *fmreg = u2_banks->fmreg;
|
||||||
@ -222,7 +329,7 @@ static void hs_slew_rate_calibrate(struct mt65xx_u3phy *u3phy,
|
|||||||
tmp = readl(fmreg + U3P_U2FREQ_FMCR0);
|
tmp = readl(fmreg + U3P_U2FREQ_FMCR0);
|
||||||
tmp &= ~(P2F_RG_CYCLECNT | P2F_RG_MONCLK_SEL);
|
tmp &= ~(P2F_RG_CYCLECNT | P2F_RG_MONCLK_SEL);
|
||||||
tmp |= P2F_RG_CYCLECNT_VAL(U3P_FM_DET_CYCLE_CNT);
|
tmp |= P2F_RG_CYCLECNT_VAL(U3P_FM_DET_CYCLE_CNT);
|
||||||
if (u3phy->pdata->version == MT_PHY_V1)
|
if (tphy->pdata->version == MTK_PHY_V1)
|
||||||
tmp |= P2F_RG_MONCLK_SEL_VAL(instance->index >> 1);
|
tmp |= P2F_RG_MONCLK_SEL_VAL(instance->index >> 1);
|
||||||
|
|
||||||
writel(tmp, fmreg + U3P_U2FREQ_FMCR0);
|
writel(tmp, fmreg + U3P_U2FREQ_FMCR0);
|
||||||
@ -257,7 +364,7 @@ static void hs_slew_rate_calibrate(struct mt65xx_u3phy *u3phy,
|
|||||||
/* if FM detection fail, set default value */
|
/* if FM detection fail, set default value */
|
||||||
calibration_val = 4;
|
calibration_val = 4;
|
||||||
}
|
}
|
||||||
dev_dbg(u3phy->dev, "phy:%d, fm_out:%d, calib:%d\n",
|
dev_dbg(tphy->dev, "phy:%d, fm_out:%d, calib:%d\n",
|
||||||
instance->index, fm_out, calibration_val);
|
instance->index, fm_out, calibration_val);
|
||||||
|
|
||||||
/* set HS slew rate */
|
/* set HS slew rate */
|
||||||
@ -272,8 +379,8 @@ static void hs_slew_rate_calibrate(struct mt65xx_u3phy *u3phy,
|
|||||||
writel(tmp, com + U3P_USBPHYACR5);
|
writel(tmp, com + U3P_USBPHYACR5);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void u3_phy_instance_init(struct mt65xx_u3phy *u3phy,
|
static void u3_phy_instance_init(struct mtk_tphy *tphy,
|
||||||
struct mt65xx_phy_instance *instance)
|
struct mtk_phy_instance *instance)
|
||||||
{
|
{
|
||||||
struct u3phy_banks *u3_banks = &instance->u3_banks;
|
struct u3phy_banks *u3_banks = &instance->u3_banks;
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
@ -319,11 +426,11 @@ static void u3_phy_instance_init(struct mt65xx_u3phy *u3phy,
|
|||||||
tmp |= P3D_RG_RXDET_STB2_SET_P3_VAL(0x10);
|
tmp |= P3D_RG_RXDET_STB2_SET_P3_VAL(0x10);
|
||||||
writel(tmp, u3_banks->phyd + U3P_U3_PHYD_RXDET2);
|
writel(tmp, u3_banks->phyd + U3P_U3_PHYD_RXDET2);
|
||||||
|
|
||||||
dev_dbg(u3phy->dev, "%s(%d)\n", __func__, instance->index);
|
dev_dbg(tphy->dev, "%s(%d)\n", __func__, instance->index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void phy_instance_init(struct mt65xx_u3phy *u3phy,
|
static void u2_phy_instance_init(struct mtk_tphy *tphy,
|
||||||
struct mt65xx_phy_instance *instance)
|
struct mtk_phy_instance *instance)
|
||||||
{
|
{
|
||||||
struct u2phy_banks *u2_banks = &instance->u2_banks;
|
struct u2phy_banks *u2_banks = &instance->u2_banks;
|
||||||
void __iomem *com = u2_banks->com;
|
void __iomem *com = u2_banks->com;
|
||||||
@ -355,7 +462,7 @@ static void phy_instance_init(struct mt65xx_u3phy *u3phy,
|
|||||||
writel(tmp, com + U3P_U2PHYACR4);
|
writel(tmp, com + U3P_U2PHYACR4);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (u3phy->pdata->avoid_rx_sen_degradation) {
|
if (tphy->pdata->avoid_rx_sen_degradation) {
|
||||||
if (!index) {
|
if (!index) {
|
||||||
tmp = readl(com + U3P_USBPHYACR2);
|
tmp = readl(com + U3P_USBPHYACR2);
|
||||||
tmp |= PA2_RG_SIF_U2PLL_FORCE_EN;
|
tmp |= PA2_RG_SIF_U2PLL_FORCE_EN;
|
||||||
@ -381,11 +488,11 @@ static void phy_instance_init(struct mt65xx_u3phy *u3phy,
|
|||||||
tmp |= PA6_RG_U2_SQTH_VAL(2);
|
tmp |= PA6_RG_U2_SQTH_VAL(2);
|
||||||
writel(tmp, com + U3P_USBPHYACR6);
|
writel(tmp, com + U3P_USBPHYACR6);
|
||||||
|
|
||||||
dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index);
|
dev_dbg(tphy->dev, "%s(%d)\n", __func__, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void phy_instance_power_on(struct mt65xx_u3phy *u3phy,
|
static void u2_phy_instance_power_on(struct mtk_tphy *tphy,
|
||||||
struct mt65xx_phy_instance *instance)
|
struct mtk_phy_instance *instance)
|
||||||
{
|
{
|
||||||
struct u2phy_banks *u2_banks = &instance->u2_banks;
|
struct u2phy_banks *u2_banks = &instance->u2_banks;
|
||||||
void __iomem *com = u2_banks->com;
|
void __iomem *com = u2_banks->com;
|
||||||
@ -408,7 +515,7 @@ static void phy_instance_power_on(struct mt65xx_u3phy *u3phy,
|
|||||||
tmp &= ~P2C_RG_SESSEND;
|
tmp &= ~P2C_RG_SESSEND;
|
||||||
writel(tmp, com + U3P_U2PHYDTM1);
|
writel(tmp, com + U3P_U2PHYDTM1);
|
||||||
|
|
||||||
if (u3phy->pdata->avoid_rx_sen_degradation && index) {
|
if (tphy->pdata->avoid_rx_sen_degradation && index) {
|
||||||
tmp = readl(com + U3D_U2PHYDCR0);
|
tmp = readl(com + U3D_U2PHYDCR0);
|
||||||
tmp |= P2C_RG_SIF_U2PLL_FORCE_ON;
|
tmp |= P2C_RG_SIF_U2PLL_FORCE_ON;
|
||||||
writel(tmp, com + U3D_U2PHYDCR0);
|
writel(tmp, com + U3D_U2PHYDCR0);
|
||||||
@ -417,11 +524,11 @@ static void phy_instance_power_on(struct mt65xx_u3phy *u3phy,
|
|||||||
tmp |= P2C_RG_SUSPENDM | P2C_FORCE_SUSPENDM;
|
tmp |= P2C_RG_SUSPENDM | P2C_FORCE_SUSPENDM;
|
||||||
writel(tmp, com + U3P_U2PHYDTM0);
|
writel(tmp, com + U3P_U2PHYDTM0);
|
||||||
}
|
}
|
||||||
dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index);
|
dev_dbg(tphy->dev, "%s(%d)\n", __func__, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void phy_instance_power_off(struct mt65xx_u3phy *u3phy,
|
static void u2_phy_instance_power_off(struct mtk_tphy *tphy,
|
||||||
struct mt65xx_phy_instance *instance)
|
struct mtk_phy_instance *instance)
|
||||||
{
|
{
|
||||||
struct u2phy_banks *u2_banks = &instance->u2_banks;
|
struct u2phy_banks *u2_banks = &instance->u2_banks;
|
||||||
void __iomem *com = u2_banks->com;
|
void __iomem *com = u2_banks->com;
|
||||||
@ -449,24 +556,24 @@ static void phy_instance_power_off(struct mt65xx_u3phy *u3phy,
|
|||||||
tmp |= P2C_RG_SESSEND;
|
tmp |= P2C_RG_SESSEND;
|
||||||
writel(tmp, com + U3P_U2PHYDTM1);
|
writel(tmp, com + U3P_U2PHYDTM1);
|
||||||
|
|
||||||
if (u3phy->pdata->avoid_rx_sen_degradation && index) {
|
if (tphy->pdata->avoid_rx_sen_degradation && index) {
|
||||||
tmp = readl(com + U3D_U2PHYDCR0);
|
tmp = readl(com + U3D_U2PHYDCR0);
|
||||||
tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON;
|
tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON;
|
||||||
writel(tmp, com + U3D_U2PHYDCR0);
|
writel(tmp, com + U3D_U2PHYDCR0);
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_dbg(u3phy->dev, "%s(%d)\n", __func__, index);
|
dev_dbg(tphy->dev, "%s(%d)\n", __func__, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void phy_instance_exit(struct mt65xx_u3phy *u3phy,
|
static void u2_phy_instance_exit(struct mtk_tphy *tphy,
|
||||||
struct mt65xx_phy_instance *instance)
|
struct mtk_phy_instance *instance)
|
||||||
{
|
{
|
||||||
struct u2phy_banks *u2_banks = &instance->u2_banks;
|
struct u2phy_banks *u2_banks = &instance->u2_banks;
|
||||||
void __iomem *com = u2_banks->com;
|
void __iomem *com = u2_banks->com;
|
||||||
u32 index = instance->index;
|
u32 index = instance->index;
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
|
|
||||||
if (u3phy->pdata->avoid_rx_sen_degradation && index) {
|
if (tphy->pdata->avoid_rx_sen_degradation && index) {
|
||||||
tmp = readl(com + U3D_U2PHYDCR0);
|
tmp = readl(com + U3D_U2PHYDCR0);
|
||||||
tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON;
|
tmp &= ~P2C_RG_SIF_U2PLL_FORCE_ON;
|
||||||
writel(tmp, com + U3D_U2PHYDCR0);
|
writel(tmp, com + U3D_U2PHYDCR0);
|
||||||
@ -477,109 +584,307 @@ static void phy_instance_exit(struct mt65xx_u3phy *u3phy,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void phy_v1_banks_init(struct mt65xx_u3phy *u3phy,
|
static void pcie_phy_instance_init(struct mtk_tphy *tphy,
|
||||||
struct mt65xx_phy_instance *instance)
|
struct mtk_phy_instance *instance)
|
||||||
|
{
|
||||||
|
struct u3phy_banks *u3_banks = &instance->u3_banks;
|
||||||
|
u32 tmp;
|
||||||
|
|
||||||
|
if (tphy->pdata->version != MTK_PHY_V1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
tmp = readl(u3_banks->phya + U3P_U3_PHYA_DA_REG0);
|
||||||
|
tmp &= ~(P3A_RG_XTAL_EXT_PE1H | P3A_RG_XTAL_EXT_PE2H);
|
||||||
|
tmp |= P3A_RG_XTAL_EXT_PE1H_VAL(0x2) | P3A_RG_XTAL_EXT_PE2H_VAL(0x2);
|
||||||
|
writel(tmp, u3_banks->phya + U3P_U3_PHYA_DA_REG0);
|
||||||
|
|
||||||
|
/* ref clk drive */
|
||||||
|
tmp = readl(u3_banks->phya + U3P_U3_PHYA_REG1);
|
||||||
|
tmp &= ~P3A_RG_CLKDRV_AMP;
|
||||||
|
tmp |= P3A_RG_CLKDRV_AMP_VAL(0x4);
|
||||||
|
writel(tmp, u3_banks->phya + U3P_U3_PHYA_REG1);
|
||||||
|
|
||||||
|
tmp = readl(u3_banks->phya + U3P_U3_PHYA_REG0);
|
||||||
|
tmp &= ~P3A_RG_CLKDRV_OFF;
|
||||||
|
tmp |= P3A_RG_CLKDRV_OFF_VAL(0x1);
|
||||||
|
writel(tmp, u3_banks->phya + U3P_U3_PHYA_REG0);
|
||||||
|
|
||||||
|
/* SSC delta -5000ppm */
|
||||||
|
tmp = readl(u3_banks->phya + U3P_U3_PHYA_DA_REG20);
|
||||||
|
tmp &= ~P3A_RG_PLL_DELTA1_PE2H;
|
||||||
|
tmp |= P3A_RG_PLL_DELTA1_PE2H_VAL(0x3c);
|
||||||
|
writel(tmp, u3_banks->phya + U3P_U3_PHYA_DA_REG20);
|
||||||
|
|
||||||
|
tmp = readl(u3_banks->phya + U3P_U3_PHYA_DA_REG25);
|
||||||
|
tmp &= ~P3A_RG_PLL_DELTA_PE2H;
|
||||||
|
tmp |= P3A_RG_PLL_DELTA_PE2H_VAL(0x36);
|
||||||
|
writel(tmp, u3_banks->phya + U3P_U3_PHYA_DA_REG25);
|
||||||
|
|
||||||
|
/* change pll BW 0.6M */
|
||||||
|
tmp = readl(u3_banks->phya + U3P_U3_PHYA_DA_REG5);
|
||||||
|
tmp &= ~(P3A_RG_PLL_BR_PE2H | P3A_RG_PLL_IC_PE2H);
|
||||||
|
tmp |= P3A_RG_PLL_BR_PE2H_VAL(0x1) | P3A_RG_PLL_IC_PE2H_VAL(0x1);
|
||||||
|
writel(tmp, u3_banks->phya + U3P_U3_PHYA_DA_REG5);
|
||||||
|
|
||||||
|
tmp = readl(u3_banks->phya + U3P_U3_PHYA_DA_REG4);
|
||||||
|
tmp &= ~(P3A_RG_PLL_DIVEN_PE2H | P3A_RG_PLL_BC_PE2H);
|
||||||
|
tmp |= P3A_RG_PLL_BC_PE2H_VAL(0x3);
|
||||||
|
writel(tmp, u3_banks->phya + U3P_U3_PHYA_DA_REG4);
|
||||||
|
|
||||||
|
tmp = readl(u3_banks->phya + U3P_U3_PHYA_DA_REG6);
|
||||||
|
tmp &= ~P3A_RG_PLL_IR_PE2H;
|
||||||
|
tmp |= P3A_RG_PLL_IR_PE2H_VAL(0x2);
|
||||||
|
writel(tmp, u3_banks->phya + U3P_U3_PHYA_DA_REG6);
|
||||||
|
|
||||||
|
tmp = readl(u3_banks->phya + U3P_U3_PHYA_DA_REG7);
|
||||||
|
tmp &= ~P3A_RG_PLL_BP_PE2H;
|
||||||
|
tmp |= P3A_RG_PLL_BP_PE2H_VAL(0xa);
|
||||||
|
writel(tmp, u3_banks->phya + U3P_U3_PHYA_DA_REG7);
|
||||||
|
|
||||||
|
/* Tx Detect Rx Timing: 10us -> 5us */
|
||||||
|
tmp = readl(u3_banks->phyd + U3P_U3_PHYD_RXDET1);
|
||||||
|
tmp &= ~P3D_RG_RXDET_STB2_SET;
|
||||||
|
tmp |= P3D_RG_RXDET_STB2_SET_VAL(0x10);
|
||||||
|
writel(tmp, u3_banks->phyd + U3P_U3_PHYD_RXDET1);
|
||||||
|
|
||||||
|
tmp = readl(u3_banks->phyd + U3P_U3_PHYD_RXDET2);
|
||||||
|
tmp &= ~P3D_RG_RXDET_STB2_SET_P3;
|
||||||
|
tmp |= P3D_RG_RXDET_STB2_SET_P3_VAL(0x10);
|
||||||
|
writel(tmp, u3_banks->phyd + U3P_U3_PHYD_RXDET2);
|
||||||
|
|
||||||
|
/* wait for PCIe subsys register to active */
|
||||||
|
usleep_range(2500, 3000);
|
||||||
|
dev_dbg(tphy->dev, "%s(%d)\n", __func__, instance->index);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pcie_phy_instance_power_on(struct mtk_tphy *tphy,
|
||||||
|
struct mtk_phy_instance *instance)
|
||||||
|
{
|
||||||
|
struct u3phy_banks *bank = &instance->u3_banks;
|
||||||
|
u32 tmp;
|
||||||
|
|
||||||
|
tmp = readl(bank->chip + U3P_U3_CHIP_GPIO_CTLD);
|
||||||
|
tmp &= ~(P3C_FORCE_IP_SW_RST | P3C_MCU_BUS_CK_GATE_EN |
|
||||||
|
P3C_REG_IP_SW_RST);
|
||||||
|
writel(tmp, bank->chip + U3P_U3_CHIP_GPIO_CTLD);
|
||||||
|
|
||||||
|
tmp = readl(bank->chip + U3P_U3_CHIP_GPIO_CTLE);
|
||||||
|
tmp &= ~(P3C_RG_SWRST_U3_PHYD_FORCE_EN | P3C_RG_SWRST_U3_PHYD);
|
||||||
|
writel(tmp, bank->chip + U3P_U3_CHIP_GPIO_CTLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pcie_phy_instance_power_off(struct mtk_tphy *tphy,
|
||||||
|
struct mtk_phy_instance *instance)
|
||||||
|
|
||||||
|
{
|
||||||
|
struct u3phy_banks *bank = &instance->u3_banks;
|
||||||
|
u32 tmp;
|
||||||
|
|
||||||
|
tmp = readl(bank->chip + U3P_U3_CHIP_GPIO_CTLD);
|
||||||
|
tmp |= P3C_FORCE_IP_SW_RST | P3C_REG_IP_SW_RST;
|
||||||
|
writel(tmp, bank->chip + U3P_U3_CHIP_GPIO_CTLD);
|
||||||
|
|
||||||
|
tmp = readl(bank->chip + U3P_U3_CHIP_GPIO_CTLE);
|
||||||
|
tmp |= P3C_RG_SWRST_U3_PHYD_FORCE_EN | P3C_RG_SWRST_U3_PHYD;
|
||||||
|
writel(tmp, bank->chip + U3P_U3_CHIP_GPIO_CTLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sata_phy_instance_init(struct mtk_tphy *tphy,
|
||||||
|
struct mtk_phy_instance *instance)
|
||||||
|
{
|
||||||
|
struct u3phy_banks *u3_banks = &instance->u3_banks;
|
||||||
|
void __iomem *phyd = u3_banks->phyd;
|
||||||
|
u32 tmp;
|
||||||
|
|
||||||
|
/* charge current adjustment */
|
||||||
|
tmp = readl(phyd + ANA_RG_CTRL_SIGNAL6);
|
||||||
|
tmp &= ~(RG_CDR_BIRLTR_GEN1_MSK | RG_CDR_BC_GEN1_MSK);
|
||||||
|
tmp |= RG_CDR_BIRLTR_GEN1_VAL(0x6) | RG_CDR_BC_GEN1_VAL(0x1a);
|
||||||
|
writel(tmp, phyd + ANA_RG_CTRL_SIGNAL6);
|
||||||
|
|
||||||
|
tmp = readl(phyd + ANA_EQ_EYE_CTRL_SIGNAL4);
|
||||||
|
tmp &= ~RG_CDR_BIRLTD0_GEN1_MSK;
|
||||||
|
tmp |= RG_CDR_BIRLTD0_GEN1_VAL(0x18);
|
||||||
|
writel(tmp, phyd + ANA_EQ_EYE_CTRL_SIGNAL4);
|
||||||
|
|
||||||
|
tmp = readl(phyd + ANA_EQ_EYE_CTRL_SIGNAL5);
|
||||||
|
tmp &= ~RG_CDR_BIRLTD0_GEN3_MSK;
|
||||||
|
tmp |= RG_CDR_BIRLTD0_GEN3_VAL(0x06);
|
||||||
|
writel(tmp, phyd + ANA_EQ_EYE_CTRL_SIGNAL5);
|
||||||
|
|
||||||
|
tmp = readl(phyd + ANA_RG_CTRL_SIGNAL4);
|
||||||
|
tmp &= ~(RG_CDR_BICLTR_GEN1_MSK | RG_CDR_BR_GEN2_MSK);
|
||||||
|
tmp |= RG_CDR_BICLTR_GEN1_VAL(0x0c) | RG_CDR_BR_GEN2_VAL(0x07);
|
||||||
|
writel(tmp, phyd + ANA_RG_CTRL_SIGNAL4);
|
||||||
|
|
||||||
|
tmp = readl(phyd + PHYD_CTRL_SIGNAL_MODE4);
|
||||||
|
tmp &= ~(RG_CDR_BICLTD0_GEN1_MSK | RG_CDR_BICLTD1_GEN1_MSK);
|
||||||
|
tmp |= RG_CDR_BICLTD0_GEN1_VAL(0x08) | RG_CDR_BICLTD1_GEN1_VAL(0x02);
|
||||||
|
writel(tmp, phyd + PHYD_CTRL_SIGNAL_MODE4);
|
||||||
|
|
||||||
|
tmp = readl(phyd + PHYD_DESIGN_OPTION2);
|
||||||
|
tmp &= ~RG_LOCK_CNT_SEL_MSK;
|
||||||
|
tmp |= RG_LOCK_CNT_SEL_VAL(0x02);
|
||||||
|
writel(tmp, phyd + PHYD_DESIGN_OPTION2);
|
||||||
|
|
||||||
|
tmp = readl(phyd + PHYD_DESIGN_OPTION9);
|
||||||
|
tmp &= ~(RG_T2_MIN_MSK | RG_TG_MIN_MSK |
|
||||||
|
RG_T2_MAX_MSK | RG_TG_MAX_MSK);
|
||||||
|
tmp |= RG_T2_MIN_VAL(0x12) | RG_TG_MIN_VAL(0x04) |
|
||||||
|
RG_T2_MAX_VAL(0x31) | RG_TG_MAX_VAL(0x0e);
|
||||||
|
writel(tmp, phyd + PHYD_DESIGN_OPTION9);
|
||||||
|
|
||||||
|
tmp = readl(phyd + ANA_RG_CTRL_SIGNAL1);
|
||||||
|
tmp &= ~RG_IDRV_0DB_GEN1_MSK;
|
||||||
|
tmp |= RG_IDRV_0DB_GEN1_VAL(0x20);
|
||||||
|
writel(tmp, phyd + ANA_RG_CTRL_SIGNAL1);
|
||||||
|
|
||||||
|
tmp = readl(phyd + ANA_EQ_EYE_CTRL_SIGNAL1);
|
||||||
|
tmp &= ~RG_EQ_DLEQ_LFI_GEN1_MSK;
|
||||||
|
tmp |= RG_EQ_DLEQ_LFI_GEN1_VAL(0x03);
|
||||||
|
writel(tmp, phyd + ANA_EQ_EYE_CTRL_SIGNAL1);
|
||||||
|
|
||||||
|
dev_dbg(tphy->dev, "%s(%d)\n", __func__, instance->index);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void phy_v1_banks_init(struct mtk_tphy *tphy,
|
||||||
|
struct mtk_phy_instance *instance)
|
||||||
{
|
{
|
||||||
struct u2phy_banks *u2_banks = &instance->u2_banks;
|
struct u2phy_banks *u2_banks = &instance->u2_banks;
|
||||||
struct u3phy_banks *u3_banks = &instance->u3_banks;
|
struct u3phy_banks *u3_banks = &instance->u3_banks;
|
||||||
|
|
||||||
if (instance->type == PHY_TYPE_USB2) {
|
switch (instance->type) {
|
||||||
|
case PHY_TYPE_USB2:
|
||||||
u2_banks->misc = NULL;
|
u2_banks->misc = NULL;
|
||||||
u2_banks->fmreg = u3phy->sif_base + SSUSB_SIFSLV_V1_U2FREQ;
|
u2_banks->fmreg = tphy->sif_base + SSUSB_SIFSLV_V1_U2FREQ;
|
||||||
u2_banks->com = instance->port_base + SSUSB_SIFSLV_V1_U2PHY_COM;
|
u2_banks->com = instance->port_base + SSUSB_SIFSLV_V1_U2PHY_COM;
|
||||||
} else if (instance->type == PHY_TYPE_USB3) {
|
break;
|
||||||
u3_banks->spllc = u3phy->sif_base + SSUSB_SIFSLV_V1_SPLLC;
|
case PHY_TYPE_USB3:
|
||||||
|
case PHY_TYPE_PCIE:
|
||||||
|
u3_banks->spllc = tphy->sif_base + SSUSB_SIFSLV_V1_SPLLC;
|
||||||
u3_banks->chip = NULL;
|
u3_banks->chip = NULL;
|
||||||
u3_banks->phyd = instance->port_base + SSUSB_SIFSLV_V1_U3PHYD;
|
u3_banks->phyd = instance->port_base + SSUSB_SIFSLV_V1_U3PHYD;
|
||||||
u3_banks->phya = instance->port_base + SSUSB_SIFSLV_V1_U3PHYA;
|
u3_banks->phya = instance->port_base + SSUSB_SIFSLV_V1_U3PHYA;
|
||||||
|
break;
|
||||||
|
case PHY_TYPE_SATA:
|
||||||
|
u3_banks->phyd = instance->port_base + SSUSB_SIFSLV_V1_U3PHYD;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dev_err(tphy->dev, "incompatible PHY type\n");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void phy_v2_banks_init(struct mt65xx_u3phy *u3phy,
|
static void phy_v2_banks_init(struct mtk_tphy *tphy,
|
||||||
struct mt65xx_phy_instance *instance)
|
struct mtk_phy_instance *instance)
|
||||||
{
|
{
|
||||||
struct u2phy_banks *u2_banks = &instance->u2_banks;
|
struct u2phy_banks *u2_banks = &instance->u2_banks;
|
||||||
struct u3phy_banks *u3_banks = &instance->u3_banks;
|
struct u3phy_banks *u3_banks = &instance->u3_banks;
|
||||||
|
|
||||||
if (instance->type == PHY_TYPE_USB2) {
|
switch (instance->type) {
|
||||||
|
case PHY_TYPE_USB2:
|
||||||
u2_banks->misc = instance->port_base + SSUSB_SIFSLV_V2_MISC;
|
u2_banks->misc = instance->port_base + SSUSB_SIFSLV_V2_MISC;
|
||||||
u2_banks->fmreg = instance->port_base + SSUSB_SIFSLV_V2_U2FREQ;
|
u2_banks->fmreg = instance->port_base + SSUSB_SIFSLV_V2_U2FREQ;
|
||||||
u2_banks->com = instance->port_base + SSUSB_SIFSLV_V2_U2PHY_COM;
|
u2_banks->com = instance->port_base + SSUSB_SIFSLV_V2_U2PHY_COM;
|
||||||
} else if (instance->type == PHY_TYPE_USB3) {
|
break;
|
||||||
|
case PHY_TYPE_USB3:
|
||||||
|
case PHY_TYPE_PCIE:
|
||||||
u3_banks->spllc = instance->port_base + SSUSB_SIFSLV_V2_SPLLC;
|
u3_banks->spllc = instance->port_base + SSUSB_SIFSLV_V2_SPLLC;
|
||||||
u3_banks->chip = instance->port_base + SSUSB_SIFSLV_V2_CHIP;
|
u3_banks->chip = instance->port_base + SSUSB_SIFSLV_V2_CHIP;
|
||||||
u3_banks->phyd = instance->port_base + SSUSB_SIFSLV_V2_U3PHYD;
|
u3_banks->phyd = instance->port_base + SSUSB_SIFSLV_V2_U3PHYD;
|
||||||
u3_banks->phya = instance->port_base + SSUSB_SIFSLV_V2_U3PHYA;
|
u3_banks->phya = instance->port_base + SSUSB_SIFSLV_V2_U3PHYA;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dev_err(tphy->dev, "incompatible PHY type\n");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mt65xx_phy_init(struct phy *phy)
|
static int mtk_phy_init(struct phy *phy)
|
||||||
{
|
{
|
||||||
struct mt65xx_phy_instance *instance = phy_get_drvdata(phy);
|
struct mtk_phy_instance *instance = phy_get_drvdata(phy);
|
||||||
struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent);
|
struct mtk_tphy *tphy = dev_get_drvdata(phy->dev.parent);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = clk_prepare_enable(u3phy->u3phya_ref);
|
ret = clk_prepare_enable(tphy->u3phya_ref);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(u3phy->dev, "failed to enable u3phya_ref\n");
|
dev_err(tphy->dev, "failed to enable u3phya_ref\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = clk_prepare_enable(instance->ref_clk);
|
ret = clk_prepare_enable(instance->ref_clk);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(u3phy->dev, "failed to enable ref_clk\n");
|
dev_err(tphy->dev, "failed to enable ref_clk\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (instance->type == PHY_TYPE_USB2)
|
switch (instance->type) {
|
||||||
phy_instance_init(u3phy, instance);
|
case PHY_TYPE_USB2:
|
||||||
else
|
u2_phy_instance_init(tphy, instance);
|
||||||
u3_phy_instance_init(u3phy, instance);
|
break;
|
||||||
|
case PHY_TYPE_USB3:
|
||||||
|
u3_phy_instance_init(tphy, instance);
|
||||||
|
break;
|
||||||
|
case PHY_TYPE_PCIE:
|
||||||
|
pcie_phy_instance_init(tphy, instance);
|
||||||
|
break;
|
||||||
|
case PHY_TYPE_SATA:
|
||||||
|
sata_phy_instance_init(tphy, instance);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dev_err(tphy->dev, "incompatible PHY type\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mt65xx_phy_power_on(struct phy *phy)
|
static int mtk_phy_power_on(struct phy *phy)
|
||||||
{
|
{
|
||||||
struct mt65xx_phy_instance *instance = phy_get_drvdata(phy);
|
struct mtk_phy_instance *instance = phy_get_drvdata(phy);
|
||||||
struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent);
|
struct mtk_tphy *tphy = dev_get_drvdata(phy->dev.parent);
|
||||||
|
|
||||||
if (instance->type == PHY_TYPE_USB2) {
|
if (instance->type == PHY_TYPE_USB2) {
|
||||||
phy_instance_power_on(u3phy, instance);
|
u2_phy_instance_power_on(tphy, instance);
|
||||||
hs_slew_rate_calibrate(u3phy, instance);
|
hs_slew_rate_calibrate(tphy, instance);
|
||||||
|
} else if (instance->type == PHY_TYPE_PCIE) {
|
||||||
|
pcie_phy_instance_power_on(tphy, instance);
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mt65xx_phy_power_off(struct phy *phy)
|
|
||||||
{
|
|
||||||
struct mt65xx_phy_instance *instance = phy_get_drvdata(phy);
|
|
||||||
struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent);
|
|
||||||
|
|
||||||
if (instance->type == PHY_TYPE_USB2)
|
|
||||||
phy_instance_power_off(u3phy, instance);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mt65xx_phy_exit(struct phy *phy)
|
static int mtk_phy_power_off(struct phy *phy)
|
||||||
{
|
{
|
||||||
struct mt65xx_phy_instance *instance = phy_get_drvdata(phy);
|
struct mtk_phy_instance *instance = phy_get_drvdata(phy);
|
||||||
struct mt65xx_u3phy *u3phy = dev_get_drvdata(phy->dev.parent);
|
struct mtk_tphy *tphy = dev_get_drvdata(phy->dev.parent);
|
||||||
|
|
||||||
if (instance->type == PHY_TYPE_USB2)
|
if (instance->type == PHY_TYPE_USB2)
|
||||||
phy_instance_exit(u3phy, instance);
|
u2_phy_instance_power_off(tphy, instance);
|
||||||
|
else if (instance->type == PHY_TYPE_PCIE)
|
||||||
|
pcie_phy_instance_power_off(tphy, instance);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mtk_phy_exit(struct phy *phy)
|
||||||
|
{
|
||||||
|
struct mtk_phy_instance *instance = phy_get_drvdata(phy);
|
||||||
|
struct mtk_tphy *tphy = dev_get_drvdata(phy->dev.parent);
|
||||||
|
|
||||||
|
if (instance->type == PHY_TYPE_USB2)
|
||||||
|
u2_phy_instance_exit(tphy, instance);
|
||||||
|
|
||||||
clk_disable_unprepare(instance->ref_clk);
|
clk_disable_unprepare(instance->ref_clk);
|
||||||
clk_disable_unprepare(u3phy->u3phya_ref);
|
clk_disable_unprepare(tphy->u3phya_ref);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct phy *mt65xx_phy_xlate(struct device *dev,
|
static struct phy *mtk_phy_xlate(struct device *dev,
|
||||||
struct of_phandle_args *args)
|
struct of_phandle_args *args)
|
||||||
{
|
{
|
||||||
struct mt65xx_u3phy *u3phy = dev_get_drvdata(dev);
|
struct mtk_tphy *tphy = dev_get_drvdata(dev);
|
||||||
struct mt65xx_phy_instance *instance = NULL;
|
struct mtk_phy_instance *instance = NULL;
|
||||||
struct device_node *phy_np = args->np;
|
struct device_node *phy_np = args->np;
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
@ -588,9 +893,9 @@ static struct phy *mt65xx_phy_xlate(struct device *dev,
|
|||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (index = 0; index < u3phy->nphys; index++)
|
for (index = 0; index < tphy->nphys; index++)
|
||||||
if (phy_np == u3phy->phys[index]->phy->dev.of_node) {
|
if (phy_np == tphy->phys[index]->phy->dev.of_node) {
|
||||||
instance = u3phy->phys[index];
|
instance = tphy->phys[index];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -601,15 +906,17 @@ static struct phy *mt65xx_phy_xlate(struct device *dev,
|
|||||||
|
|
||||||
instance->type = args->args[0];
|
instance->type = args->args[0];
|
||||||
if (!(instance->type == PHY_TYPE_USB2 ||
|
if (!(instance->type == PHY_TYPE_USB2 ||
|
||||||
instance->type == PHY_TYPE_USB3)) {
|
instance->type == PHY_TYPE_USB3 ||
|
||||||
|
instance->type == PHY_TYPE_PCIE ||
|
||||||
|
instance->type == PHY_TYPE_SATA)) {
|
||||||
dev_err(dev, "unsupported device type: %d\n", instance->type);
|
dev_err(dev, "unsupported device type: %d\n", instance->type);
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (u3phy->pdata->version == MT_PHY_V1) {
|
if (tphy->pdata->version == MTK_PHY_V1) {
|
||||||
phy_v1_banks_init(u3phy, instance);
|
phy_v1_banks_init(tphy, instance);
|
||||||
} else if (u3phy->pdata->version == MT_PHY_V2) {
|
} else if (tphy->pdata->version == MTK_PHY_V2) {
|
||||||
phy_v2_banks_init(u3phy, instance);
|
phy_v2_banks_init(tphy, instance);
|
||||||
} else {
|
} else {
|
||||||
dev_err(dev, "phy version is not supported\n");
|
dev_err(dev, "phy version is not supported\n");
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
@ -618,38 +925,40 @@ static struct phy *mt65xx_phy_xlate(struct device *dev,
|
|||||||
return instance->phy;
|
return instance->phy;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct phy_ops mt65xx_u3phy_ops = {
|
static const struct phy_ops mtk_tphy_ops = {
|
||||||
.init = mt65xx_phy_init,
|
.init = mtk_phy_init,
|
||||||
.exit = mt65xx_phy_exit,
|
.exit = mtk_phy_exit,
|
||||||
.power_on = mt65xx_phy_power_on,
|
.power_on = mtk_phy_power_on,
|
||||||
.power_off = mt65xx_phy_power_off,
|
.power_off = mtk_phy_power_off,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct mt65xx_phy_pdata mt2701_pdata = {
|
static const struct mtk_phy_pdata tphy_v1_pdata = {
|
||||||
.avoid_rx_sen_degradation = false,
|
.avoid_rx_sen_degradation = false,
|
||||||
.version = MT_PHY_V1,
|
.version = MTK_PHY_V1,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct mt65xx_phy_pdata mt2712_pdata = {
|
static const struct mtk_phy_pdata tphy_v2_pdata = {
|
||||||
.avoid_rx_sen_degradation = false,
|
.avoid_rx_sen_degradation = false,
|
||||||
.version = MT_PHY_V2,
|
.version = MTK_PHY_V2,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct mt65xx_phy_pdata mt8173_pdata = {
|
static const struct mtk_phy_pdata mt8173_pdata = {
|
||||||
.avoid_rx_sen_degradation = true,
|
.avoid_rx_sen_degradation = true,
|
||||||
.version = MT_PHY_V1,
|
.version = MTK_PHY_V1,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct of_device_id mt65xx_u3phy_id_table[] = {
|
static const struct of_device_id mtk_tphy_id_table[] = {
|
||||||
{ .compatible = "mediatek,mt2701-u3phy", .data = &mt2701_pdata },
|
{ .compatible = "mediatek,mt2701-u3phy", .data = &tphy_v1_pdata },
|
||||||
{ .compatible = "mediatek,mt2712-u3phy", .data = &mt2712_pdata },
|
{ .compatible = "mediatek,mt2712-u3phy", .data = &tphy_v2_pdata },
|
||||||
{ .compatible = "mediatek,mt8173-u3phy", .data = &mt8173_pdata },
|
{ .compatible = "mediatek,mt8173-u3phy", .data = &mt8173_pdata },
|
||||||
|
{ .compatible = "mediatek,generic-tphy-v1", .data = &tphy_v1_pdata },
|
||||||
|
{ .compatible = "mediatek,generic-tphy-v2", .data = &tphy_v2_pdata },
|
||||||
{ },
|
{ },
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, mt65xx_u3phy_id_table);
|
MODULE_DEVICE_TABLE(of, mtk_tphy_id_table);
|
||||||
|
|
||||||
static int mt65xx_u3phy_probe(struct platform_device *pdev)
|
static int mtk_tphy_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
const struct of_device_id *match;
|
const struct of_device_id *match;
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
@ -657,50 +966,50 @@ static int mt65xx_u3phy_probe(struct platform_device *pdev)
|
|||||||
struct device_node *child_np;
|
struct device_node *child_np;
|
||||||
struct phy_provider *provider;
|
struct phy_provider *provider;
|
||||||
struct resource *sif_res;
|
struct resource *sif_res;
|
||||||
struct mt65xx_u3phy *u3phy;
|
struct mtk_tphy *tphy;
|
||||||
struct resource res;
|
struct resource res;
|
||||||
int port, retval;
|
int port, retval;
|
||||||
|
|
||||||
match = of_match_node(mt65xx_u3phy_id_table, pdev->dev.of_node);
|
match = of_match_node(mtk_tphy_id_table, pdev->dev.of_node);
|
||||||
if (!match)
|
if (!match)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
u3phy = devm_kzalloc(dev, sizeof(*u3phy), GFP_KERNEL);
|
tphy = devm_kzalloc(dev, sizeof(*tphy), GFP_KERNEL);
|
||||||
if (!u3phy)
|
if (!tphy)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
u3phy->pdata = match->data;
|
tphy->pdata = match->data;
|
||||||
u3phy->nphys = of_get_child_count(np);
|
tphy->nphys = of_get_child_count(np);
|
||||||
u3phy->phys = devm_kcalloc(dev, u3phy->nphys,
|
tphy->phys = devm_kcalloc(dev, tphy->nphys,
|
||||||
sizeof(*u3phy->phys), GFP_KERNEL);
|
sizeof(*tphy->phys), GFP_KERNEL);
|
||||||
if (!u3phy->phys)
|
if (!tphy->phys)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
u3phy->dev = dev;
|
tphy->dev = dev;
|
||||||
platform_set_drvdata(pdev, u3phy);
|
platform_set_drvdata(pdev, tphy);
|
||||||
|
|
||||||
if (u3phy->pdata->version == MT_PHY_V1) {
|
if (tphy->pdata->version == MTK_PHY_V1) {
|
||||||
/* get banks shared by multiple phys */
|
/* get banks shared by multiple phys */
|
||||||
sif_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
sif_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
u3phy->sif_base = devm_ioremap_resource(dev, sif_res);
|
tphy->sif_base = devm_ioremap_resource(dev, sif_res);
|
||||||
if (IS_ERR(u3phy->sif_base)) {
|
if (IS_ERR(tphy->sif_base)) {
|
||||||
dev_err(dev, "failed to remap sif regs\n");
|
dev_err(dev, "failed to remap sif regs\n");
|
||||||
return PTR_ERR(u3phy->sif_base);
|
return PTR_ERR(tphy->sif_base);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* it's deprecated, make it optional for backward compatibility */
|
/* it's deprecated, make it optional for backward compatibility */
|
||||||
u3phy->u3phya_ref = devm_clk_get(dev, "u3phya_ref");
|
tphy->u3phya_ref = devm_clk_get(dev, "u3phya_ref");
|
||||||
if (IS_ERR(u3phy->u3phya_ref)) {
|
if (IS_ERR(tphy->u3phya_ref)) {
|
||||||
if (PTR_ERR(u3phy->u3phya_ref) == -EPROBE_DEFER)
|
if (PTR_ERR(tphy->u3phya_ref) == -EPROBE_DEFER)
|
||||||
return -EPROBE_DEFER;
|
return -EPROBE_DEFER;
|
||||||
|
|
||||||
u3phy->u3phya_ref = NULL;
|
tphy->u3phya_ref = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
port = 0;
|
port = 0;
|
||||||
for_each_child_of_node(np, child_np) {
|
for_each_child_of_node(np, child_np) {
|
||||||
struct mt65xx_phy_instance *instance;
|
struct mtk_phy_instance *instance;
|
||||||
struct phy *phy;
|
struct phy *phy;
|
||||||
|
|
||||||
instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL);
|
instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL);
|
||||||
@ -709,9 +1018,9 @@ static int mt65xx_u3phy_probe(struct platform_device *pdev)
|
|||||||
goto put_child;
|
goto put_child;
|
||||||
}
|
}
|
||||||
|
|
||||||
u3phy->phys[port] = instance;
|
tphy->phys[port] = instance;
|
||||||
|
|
||||||
phy = devm_phy_create(dev, child_np, &mt65xx_u3phy_ops);
|
phy = devm_phy_create(dev, child_np, &mtk_tphy_ops);
|
||||||
if (IS_ERR(phy)) {
|
if (IS_ERR(phy)) {
|
||||||
dev_err(dev, "failed to create phy\n");
|
dev_err(dev, "failed to create phy\n");
|
||||||
retval = PTR_ERR(phy);
|
retval = PTR_ERR(phy);
|
||||||
@ -738,7 +1047,7 @@ static int mt65xx_u3phy_probe(struct platform_device *pdev)
|
|||||||
port++;
|
port++;
|
||||||
|
|
||||||
/* if deprecated clock is provided, ignore instance's one */
|
/* if deprecated clock is provided, ignore instance's one */
|
||||||
if (u3phy->u3phya_ref)
|
if (tphy->u3phya_ref)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
instance->ref_clk = devm_clk_get(&phy->dev, "ref");
|
instance->ref_clk = devm_clk_get(&phy->dev, "ref");
|
||||||
@ -749,7 +1058,7 @@ static int mt65xx_u3phy_probe(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
provider = devm_of_phy_provider_register(dev, mt65xx_phy_xlate);
|
provider = devm_of_phy_provider_register(dev, mtk_phy_xlate);
|
||||||
|
|
||||||
return PTR_ERR_OR_ZERO(provider);
|
return PTR_ERR_OR_ZERO(provider);
|
||||||
put_child:
|
put_child:
|
||||||
@ -757,16 +1066,16 @@ put_child:
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct platform_driver mt65xx_u3phy_driver = {
|
static struct platform_driver mtk_tphy_driver = {
|
||||||
.probe = mt65xx_u3phy_probe,
|
.probe = mtk_tphy_probe,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "mt65xx-u3phy",
|
.name = "mtk-tphy",
|
||||||
.of_match_table = mt65xx_u3phy_id_table,
|
.of_match_table = mtk_tphy_id_table,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module_platform_driver(mt65xx_u3phy_driver);
|
module_platform_driver(mtk_tphy_driver);
|
||||||
|
|
||||||
MODULE_AUTHOR("Chunfeng Yun <chunfeng.yun@mediatek.com>");
|
MODULE_AUTHOR("Chunfeng Yun <chunfeng.yun@mediatek.com>");
|
||||||
MODULE_DESCRIPTION("mt65xx USB PHY driver");
|
MODULE_DESCRIPTION("MediaTek T-PHY driver");
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
@ -506,7 +506,7 @@ static void cpcap_usb_init_optional_gpios(struct cpcap_phy_ddata *ddata)
|
|||||||
if (IS_ERR(ddata->gpio[i])) {
|
if (IS_ERR(ddata->gpio[i])) {
|
||||||
dev_info(ddata->dev, "no mode change GPIO%i: %li\n",
|
dev_info(ddata->dev, "no mode change GPIO%i: %li\n",
|
||||||
i, PTR_ERR(ddata->gpio[i]));
|
i, PTR_ERR(ddata->gpio[i]));
|
||||||
ddata->gpio[i] = NULL;
|
ddata->gpio[i] = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,7 @@
|
|||||||
#define QSERDES_COM_PLL_RCTRL_MODE1 0x088
|
#define QSERDES_COM_PLL_RCTRL_MODE1 0x088
|
||||||
#define QSERDES_COM_PLL_CCTRL_MODE0 0x090
|
#define QSERDES_COM_PLL_CCTRL_MODE0 0x090
|
||||||
#define QSERDES_COM_PLL_CCTRL_MODE1 0x094
|
#define QSERDES_COM_PLL_CCTRL_MODE1 0x094
|
||||||
|
#define QSERDES_COM_BIAS_EN_CTRL_BY_PSM 0x0a8
|
||||||
#define QSERDES_COM_SYSCLK_EN_SEL 0x0ac
|
#define QSERDES_COM_SYSCLK_EN_SEL 0x0ac
|
||||||
#define QSERDES_COM_RESETSM_CNTRL 0x0b4
|
#define QSERDES_COM_RESETSM_CNTRL 0x0b4
|
||||||
#define QSERDES_COM_RESTRIM_CTRL 0x0bc
|
#define QSERDES_COM_RESTRIM_CTRL 0x0bc
|
||||||
@ -143,6 +144,11 @@
|
|||||||
#define QPHY_LOCK_DETECT_CONFIG3 0x88
|
#define QPHY_LOCK_DETECT_CONFIG3 0x88
|
||||||
#define QPHY_PWRUP_RESET_DLY_TIME_AUXCLK 0xa0
|
#define QPHY_PWRUP_RESET_DLY_TIME_AUXCLK 0xa0
|
||||||
#define QPHY_LP_WAKEUP_DLY_TIME_AUXCLK 0xa4
|
#define QPHY_LP_WAKEUP_DLY_TIME_AUXCLK 0xa4
|
||||||
|
#define QPHY_PLL_LOCK_CHK_DLY_TIME_AUXCLK_LSB 0x1A8
|
||||||
|
#define QPHY_OSC_DTCT_ACTIONS 0x1AC
|
||||||
|
#define QPHY_RX_SIGDET_LVL 0x1D8
|
||||||
|
#define QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB 0x1DC
|
||||||
|
#define QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB 0x1E0
|
||||||
|
|
||||||
/* QPHY_SW_RESET bit */
|
/* QPHY_SW_RESET bit */
|
||||||
#define SW_RESET BIT(0)
|
#define SW_RESET BIT(0)
|
||||||
@ -382,6 +388,85 @@ static const struct qmp_phy_init_tbl msm8996_usb3_pcs_tbl[] = {
|
|||||||
QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG2, 0x08),
|
QMP_PHY_INIT_CFG(QPHY_POWER_STATE_CONFIG2, 0x08),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct qmp_phy_init_tbl ipq8074_pcie_serdes_tbl[] = {
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x18),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_CLK_ENABLE1, 0x10),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0xf),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x1),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x0),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER1, 0x1f),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_TIMER2, 0x3f),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x6),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0xf),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x0),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x1),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x20),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0xa),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x20),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0xa),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0xa),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x3),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x0),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0xD),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0xD04),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x33),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x2),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_BUF_ENABLE, 0x1f),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0xb),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x0),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CTRL_BY_PSM, 0x1),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_CTRL, 0xa),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x1),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x1),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x2),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x0),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0x2f),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x19),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_COM_CLK_EP_DIV, 0x19),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_CNTRL, 0x7),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct qmp_phy_init_tbl ipq8074_pcie_tx_tbl[] = {
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, 0x45),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_TX_LANE_MODE, 0x6),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_TX_RES_CODE_LANE_OFFSET, 0x2),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_TX_RCV_DETECT_LVL_2, 0x12),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct qmp_phy_init_tbl ipq8074_pcie_rx_tbl[] = {
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_ENABLES, 0x1c),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x14),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x1),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL3, 0x0),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_RX_RX_EQU_ADAPTOR_CNTRL4, 0xdb),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x4b),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN, 0x4),
|
||||||
|
QMP_PHY_INIT_CFG(QSERDES_RX_UCDR_SO_GAIN_HALF, 0x4),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct qmp_phy_init_tbl ipq8074_pcie_pcs_tbl[] = {
|
||||||
|
QMP_PHY_INIT_CFG(QPHY_ENDPOINT_REFCLK_DRIVE, 0x4),
|
||||||
|
QMP_PHY_INIT_CFG(QPHY_OSC_DTCT_ACTIONS, 0x0),
|
||||||
|
QMP_PHY_INIT_CFG(QPHY_PWRUP_RESET_DLY_TIME_AUXCLK, 0x40),
|
||||||
|
QMP_PHY_INIT_CFG(QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_MSB, 0x0),
|
||||||
|
QMP_PHY_INIT_CFG(QPHY_L1SS_WAKEUP_DLY_TIME_AUXCLK_LSB, 0x40),
|
||||||
|
QMP_PHY_INIT_CFG(QPHY_PLL_LOCK_CHK_DLY_TIME_AUXCLK_LSB, 0x0),
|
||||||
|
QMP_PHY_INIT_CFG(QPHY_LP_WAKEUP_DLY_TIME_AUXCLK, 0x40),
|
||||||
|
QMP_PHY_INIT_CFG_L(QPHY_PLL_LOCK_CHK_DLY_TIME, 0x73),
|
||||||
|
QMP_PHY_INIT_CFG(QPHY_RX_SIGDET_LVL, 0x99),
|
||||||
|
QMP_PHY_INIT_CFG(QPHY_TXDEEMPH_M6DB_V0, 0x15),
|
||||||
|
QMP_PHY_INIT_CFG(QPHY_TXDEEMPH_M3P5DB_V0, 0xe),
|
||||||
|
QMP_PHY_INIT_CFG_L(QPHY_SW_RESET, 0x0),
|
||||||
|
QMP_PHY_INIT_CFG_L(QPHY_START_CTRL, 0x3),
|
||||||
|
};
|
||||||
|
|
||||||
/* struct qmp_phy_cfg - per-PHY initialization config */
|
/* struct qmp_phy_cfg - per-PHY initialization config */
|
||||||
struct qmp_phy_cfg {
|
struct qmp_phy_cfg {
|
||||||
/* phy-type - PCIE/UFS/USB */
|
/* phy-type - PCIE/UFS/USB */
|
||||||
@ -580,6 +665,42 @@ static const struct qmp_phy_cfg msm8996_usb3phy_cfg = {
|
|||||||
.mask_pcs_ready = PHYSTATUS,
|
.mask_pcs_ready = PHYSTATUS,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* list of resets */
|
||||||
|
static const char * const ipq8074_pciephy_reset_l[] = {
|
||||||
|
"phy", "common",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct qmp_phy_cfg ipq8074_pciephy_cfg = {
|
||||||
|
.type = PHY_TYPE_PCIE,
|
||||||
|
.nlanes = 1,
|
||||||
|
|
||||||
|
.serdes_tbl = ipq8074_pcie_serdes_tbl,
|
||||||
|
.serdes_tbl_num = ARRAY_SIZE(ipq8074_pcie_serdes_tbl),
|
||||||
|
.tx_tbl = ipq8074_pcie_tx_tbl,
|
||||||
|
.tx_tbl_num = ARRAY_SIZE(ipq8074_pcie_tx_tbl),
|
||||||
|
.rx_tbl = ipq8074_pcie_rx_tbl,
|
||||||
|
.rx_tbl_num = ARRAY_SIZE(ipq8074_pcie_rx_tbl),
|
||||||
|
.pcs_tbl = ipq8074_pcie_pcs_tbl,
|
||||||
|
.pcs_tbl_num = ARRAY_SIZE(ipq8074_pcie_pcs_tbl),
|
||||||
|
.clk_list = NULL,
|
||||||
|
.num_clks = 0,
|
||||||
|
.reset_list = ipq8074_pciephy_reset_l,
|
||||||
|
.num_resets = ARRAY_SIZE(ipq8074_pciephy_reset_l),
|
||||||
|
.vreg_list = NULL,
|
||||||
|
.num_vregs = 0,
|
||||||
|
.regs = pciephy_regs_layout,
|
||||||
|
|
||||||
|
.start_ctrl = SERDES_START | PCS_START,
|
||||||
|
.pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL,
|
||||||
|
.mask_pcs_ready = PHYSTATUS,
|
||||||
|
|
||||||
|
.has_phy_com_ctrl = false,
|
||||||
|
.has_lane_rst = false,
|
||||||
|
.has_pwrdn_delay = true,
|
||||||
|
.pwrdn_delay_min = 995, /* us */
|
||||||
|
.pwrdn_delay_max = 1005, /* us */
|
||||||
|
};
|
||||||
|
|
||||||
static void qcom_qmp_phy_configure(void __iomem *base,
|
static void qcom_qmp_phy_configure(void __iomem *base,
|
||||||
const unsigned int *regs,
|
const unsigned int *regs,
|
||||||
const struct qmp_phy_init_tbl tbl[],
|
const struct qmp_phy_init_tbl tbl[],
|
||||||
@ -654,8 +775,6 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
|
|||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(qmp->dev, "%s reset deassert failed\n",
|
dev_err(qmp->dev, "%s reset deassert failed\n",
|
||||||
qmp->cfg->reset_list[i]);
|
qmp->cfg->reset_list[i]);
|
||||||
while (--i >= 0)
|
|
||||||
reset_control_assert(qmp->resets[i]);
|
|
||||||
goto err_rst;
|
goto err_rst;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -684,7 +803,7 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
|
|||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(qmp->dev,
|
dev_err(qmp->dev,
|
||||||
"phy common block init timed-out\n");
|
"phy common block init timed-out\n");
|
||||||
goto err_com_init;
|
goto err_rst;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -692,11 +811,11 @@ static int qcom_qmp_phy_com_init(struct qcom_qmp *qmp)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_com_init:
|
err_rst:
|
||||||
while (--i >= 0)
|
while (--i >= 0)
|
||||||
reset_control_assert(qmp->resets[i]);
|
reset_control_assert(qmp->resets[i]);
|
||||||
err_rst:
|
|
||||||
mutex_unlock(&qmp->phy_mutex);
|
mutex_unlock(&qmp->phy_mutex);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -749,14 +868,13 @@ static int qcom_qmp_phy_init(struct phy *phy)
|
|||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(qmp->dev, "failed to enable %s clk, err=%d\n",
|
dev_err(qmp->dev, "failed to enable %s clk, err=%d\n",
|
||||||
qmp->cfg->clk_list[i], ret);
|
qmp->cfg->clk_list[i], ret);
|
||||||
while (--i >= 0)
|
goto err_clk;
|
||||||
clk_disable_unprepare(qmp->clks[i]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = qcom_qmp_phy_com_init(qmp);
|
ret = qcom_qmp_phy_com_init(qmp);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err_com_init;
|
goto err_clk;
|
||||||
|
|
||||||
if (cfg->has_lane_rst) {
|
if (cfg->has_lane_rst) {
|
||||||
ret = reset_control_deassert(qphy->lane_rst);
|
ret = reset_control_deassert(qphy->lane_rst);
|
||||||
@ -804,7 +922,7 @@ err_pcs_ready:
|
|||||||
reset_control_assert(qphy->lane_rst);
|
reset_control_assert(qphy->lane_rst);
|
||||||
err_lane_rst:
|
err_lane_rst:
|
||||||
qcom_qmp_phy_com_exit(qmp);
|
qcom_qmp_phy_com_exit(qmp);
|
||||||
err_com_init:
|
err_clk:
|
||||||
while (--i >= 0)
|
while (--i >= 0)
|
||||||
clk_disable_unprepare(qmp->clks[i]);
|
clk_disable_unprepare(qmp->clks[i]);
|
||||||
|
|
||||||
@ -925,29 +1043,28 @@ static int qcom_qmp_phy_clk_init(struct device *dev)
|
|||||||
* clk | +-------+ | +-----+
|
* clk | +-------+ | +-----+
|
||||||
* +---------------+
|
* +---------------+
|
||||||
*/
|
*/
|
||||||
static int phy_pipe_clk_register(struct qcom_qmp *qmp, int id)
|
static int phy_pipe_clk_register(struct qcom_qmp *qmp, struct device_node *np)
|
||||||
{
|
{
|
||||||
char name[24];
|
|
||||||
struct clk_fixed_rate *fixed;
|
struct clk_fixed_rate *fixed;
|
||||||
struct clk_init_data init = { };
|
struct clk_init_data init = { };
|
||||||
|
int ret;
|
||||||
|
|
||||||
switch (qmp->cfg->type) {
|
if ((qmp->cfg->type != PHY_TYPE_USB3) &&
|
||||||
case PHY_TYPE_USB3:
|
(qmp->cfg->type != PHY_TYPE_PCIE)) {
|
||||||
snprintf(name, sizeof(name), "usb3_phy_pipe_clk_src");
|
|
||||||
break;
|
|
||||||
case PHY_TYPE_PCIE:
|
|
||||||
snprintf(name, sizeof(name), "pcie_%d_pipe_clk_src", id);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* not all phys register pipe clocks, so return success */
|
/* not all phys register pipe clocks, so return success */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = of_property_read_string(np, "clock-output-names", &init.name);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(qmp->dev, "%s: No clock-output-names\n", np->name);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
fixed = devm_kzalloc(qmp->dev, sizeof(*fixed), GFP_KERNEL);
|
fixed = devm_kzalloc(qmp->dev, sizeof(*fixed), GFP_KERNEL);
|
||||||
if (!fixed)
|
if (!fixed)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
init.name = name;
|
|
||||||
init.ops = &clk_fixed_rate_ops;
|
init.ops = &clk_fixed_rate_ops;
|
||||||
|
|
||||||
/* controllers using QMP phys use 125MHz pipe clock interface */
|
/* controllers using QMP phys use 125MHz pipe clock interface */
|
||||||
@ -1049,6 +1166,9 @@ static const struct of_device_id qcom_qmp_phy_of_match_table[] = {
|
|||||||
}, {
|
}, {
|
||||||
.compatible = "qcom,msm8996-qmp-usb3-phy",
|
.compatible = "qcom,msm8996-qmp-usb3-phy",
|
||||||
.data = &msm8996_usb3phy_cfg,
|
.data = &msm8996_usb3phy_cfg,
|
||||||
|
}, {
|
||||||
|
.compatible = "qcom,ipq8074-qmp-pcie-phy",
|
||||||
|
.data = &ipq8074_pciephy_cfg,
|
||||||
},
|
},
|
||||||
{ },
|
{ },
|
||||||
};
|
};
|
||||||
@ -1122,7 +1242,7 @@ static int qcom_qmp_phy_probe(struct platform_device *pdev)
|
|||||||
* Register the pipe clock provided by phy.
|
* Register the pipe clock provided by phy.
|
||||||
* See function description to see details of this pipe clock.
|
* See function description to see details of this pipe clock.
|
||||||
*/
|
*/
|
||||||
ret = phy_pipe_clk_register(qmp, id);
|
ret = phy_pipe_clk_register(qmp, child);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(qmp->dev,
|
dev_err(qmp->dev,
|
||||||
"failed to register pipe clock source\n");
|
"failed to register pipe clock source\n");
|
||||||
|
11
drivers/phy/ralink/Kconfig
Normal file
11
drivers/phy/ralink/Kconfig
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#
|
||||||
|
# PHY drivers for Ralink platforms.
|
||||||
|
#
|
||||||
|
config PHY_RALINK_USB
|
||||||
|
tristate "Ralink USB PHY driver"
|
||||||
|
depends on RALINK || COMPILE_TEST
|
||||||
|
select GENERIC_PHY
|
||||||
|
select MFD_SYSCON
|
||||||
|
help
|
||||||
|
This option enables support for the Ralink USB PHY found inside
|
||||||
|
RT3352, MT7620, MT7628 and MT7688.
|
1
drivers/phy/ralink/Makefile
Normal file
1
drivers/phy/ralink/Makefile
Normal file
@ -0,0 +1 @@
|
|||||||
|
obj-$(CONFIG_PHY_RALINK_USB) += phy-ralink-usb.o
|
249
drivers/phy/ralink/phy-ralink-usb.c
Normal file
249
drivers/phy/ralink/phy-ralink-usb.c
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 John Crispin <john@phrozen.org>
|
||||||
|
*
|
||||||
|
* Based on code from
|
||||||
|
* Allwinner Technology Co., Ltd. <www.allwinnertech.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/mfd/syscon.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
|
#include <linux/of_platform.h>
|
||||||
|
#include <linux/phy/phy.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
#include <linux/reset.h>
|
||||||
|
|
||||||
|
#define RT_SYSC_REG_SYSCFG1 0x014
|
||||||
|
#define RT_SYSC_REG_CLKCFG1 0x030
|
||||||
|
#define RT_SYSC_REG_USB_PHY_CFG 0x05c
|
||||||
|
|
||||||
|
#define OFS_U2_PHY_AC0 0x800
|
||||||
|
#define OFS_U2_PHY_AC1 0x804
|
||||||
|
#define OFS_U2_PHY_AC2 0x808
|
||||||
|
#define OFS_U2_PHY_ACR0 0x810
|
||||||
|
#define OFS_U2_PHY_ACR1 0x814
|
||||||
|
#define OFS_U2_PHY_ACR2 0x818
|
||||||
|
#define OFS_U2_PHY_ACR3 0x81C
|
||||||
|
#define OFS_U2_PHY_ACR4 0x820
|
||||||
|
#define OFS_U2_PHY_AMON0 0x824
|
||||||
|
#define OFS_U2_PHY_DCR0 0x860
|
||||||
|
#define OFS_U2_PHY_DCR1 0x864
|
||||||
|
#define OFS_U2_PHY_DTM0 0x868
|
||||||
|
#define OFS_U2_PHY_DTM1 0x86C
|
||||||
|
|
||||||
|
#define RT_RSTCTRL_UDEV BIT(25)
|
||||||
|
#define RT_RSTCTRL_UHST BIT(22)
|
||||||
|
#define RT_SYSCFG1_USB0_HOST_MODE BIT(10)
|
||||||
|
|
||||||
|
#define MT7620_CLKCFG1_UPHY0_CLK_EN BIT(25)
|
||||||
|
#define MT7620_CLKCFG1_UPHY1_CLK_EN BIT(22)
|
||||||
|
#define RT_CLKCFG1_UPHY1_CLK_EN BIT(20)
|
||||||
|
#define RT_CLKCFG1_UPHY0_CLK_EN BIT(18)
|
||||||
|
|
||||||
|
#define USB_PHY_UTMI_8B60M BIT(1)
|
||||||
|
#define UDEV_WAKEUP BIT(0)
|
||||||
|
|
||||||
|
struct ralink_usb_phy {
|
||||||
|
struct reset_control *rstdev;
|
||||||
|
struct reset_control *rsthost;
|
||||||
|
u32 clk;
|
||||||
|
struct phy *phy;
|
||||||
|
void __iomem *base;
|
||||||
|
struct regmap *sysctl;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void u2_phy_w32(struct ralink_usb_phy *phy, u32 val, u32 reg)
|
||||||
|
{
|
||||||
|
writel(val, phy->base + reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 u2_phy_r32(struct ralink_usb_phy *phy, u32 reg)
|
||||||
|
{
|
||||||
|
return readl(phy->base + reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ralink_usb_phy_init(struct ralink_usb_phy *phy)
|
||||||
|
{
|
||||||
|
u2_phy_r32(phy, OFS_U2_PHY_AC2);
|
||||||
|
u2_phy_r32(phy, OFS_U2_PHY_ACR0);
|
||||||
|
u2_phy_r32(phy, OFS_U2_PHY_DCR0);
|
||||||
|
|
||||||
|
u2_phy_w32(phy, 0x00ffff02, OFS_U2_PHY_DCR0);
|
||||||
|
u2_phy_r32(phy, OFS_U2_PHY_DCR0);
|
||||||
|
u2_phy_w32(phy, 0x00555502, OFS_U2_PHY_DCR0);
|
||||||
|
u2_phy_r32(phy, OFS_U2_PHY_DCR0);
|
||||||
|
u2_phy_w32(phy, 0x00aaaa02, OFS_U2_PHY_DCR0);
|
||||||
|
u2_phy_r32(phy, OFS_U2_PHY_DCR0);
|
||||||
|
u2_phy_w32(phy, 0x00000402, OFS_U2_PHY_DCR0);
|
||||||
|
u2_phy_r32(phy, OFS_U2_PHY_DCR0);
|
||||||
|
u2_phy_w32(phy, 0x0048086a, OFS_U2_PHY_AC0);
|
||||||
|
u2_phy_w32(phy, 0x4400001c, OFS_U2_PHY_AC1);
|
||||||
|
u2_phy_w32(phy, 0xc0200000, OFS_U2_PHY_ACR3);
|
||||||
|
u2_phy_w32(phy, 0x02000000, OFS_U2_PHY_DTM0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ralink_usb_phy_power_on(struct phy *_phy)
|
||||||
|
{
|
||||||
|
struct ralink_usb_phy *phy = phy_get_drvdata(_phy);
|
||||||
|
u32 t;
|
||||||
|
|
||||||
|
/* enable the phy */
|
||||||
|
regmap_update_bits(phy->sysctl, RT_SYSC_REG_CLKCFG1,
|
||||||
|
phy->clk, phy->clk);
|
||||||
|
|
||||||
|
/* setup host mode */
|
||||||
|
regmap_update_bits(phy->sysctl, RT_SYSC_REG_SYSCFG1,
|
||||||
|
RT_SYSCFG1_USB0_HOST_MODE,
|
||||||
|
RT_SYSCFG1_USB0_HOST_MODE);
|
||||||
|
|
||||||
|
/* deassert the reset lines */
|
||||||
|
reset_control_deassert(phy->rsthost);
|
||||||
|
reset_control_deassert(phy->rstdev);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The SDK kernel had a delay of 100ms. however on device
|
||||||
|
* testing showed that 10ms is enough
|
||||||
|
*/
|
||||||
|
mdelay(10);
|
||||||
|
|
||||||
|
if (phy->base)
|
||||||
|
ralink_usb_phy_init(phy);
|
||||||
|
|
||||||
|
/* print some status info */
|
||||||
|
regmap_read(phy->sysctl, RT_SYSC_REG_USB_PHY_CFG, &t);
|
||||||
|
dev_info(&phy->phy->dev, "remote usb device wakeup %s\n",
|
||||||
|
(t & UDEV_WAKEUP) ? ("enabled") : ("disabled"));
|
||||||
|
if (t & USB_PHY_UTMI_8B60M)
|
||||||
|
dev_info(&phy->phy->dev, "UTMI 8bit 60MHz\n");
|
||||||
|
else
|
||||||
|
dev_info(&phy->phy->dev, "UTMI 16bit 30MHz\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ralink_usb_phy_power_off(struct phy *_phy)
|
||||||
|
{
|
||||||
|
struct ralink_usb_phy *phy = phy_get_drvdata(_phy);
|
||||||
|
|
||||||
|
/* disable the phy */
|
||||||
|
regmap_update_bits(phy->sysctl, RT_SYSC_REG_CLKCFG1,
|
||||||
|
phy->clk, 0);
|
||||||
|
|
||||||
|
/* assert the reset lines */
|
||||||
|
reset_control_assert(phy->rstdev);
|
||||||
|
reset_control_assert(phy->rsthost);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct phy_ops ralink_usb_phy_ops = {
|
||||||
|
.power_on = ralink_usb_phy_power_on,
|
||||||
|
.power_off = ralink_usb_phy_power_off,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct of_device_id ralink_usb_phy_of_match[] = {
|
||||||
|
{
|
||||||
|
.compatible = "ralink,rt3352-usbphy",
|
||||||
|
.data = (void *)(uintptr_t)(RT_CLKCFG1_UPHY1_CLK_EN |
|
||||||
|
RT_CLKCFG1_UPHY0_CLK_EN)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "mediatek,mt7620-usbphy",
|
||||||
|
.data = (void *)(uintptr_t)(MT7620_CLKCFG1_UPHY1_CLK_EN |
|
||||||
|
MT7620_CLKCFG1_UPHY0_CLK_EN)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "mediatek,mt7628-usbphy",
|
||||||
|
.data = (void *)(uintptr_t)(MT7620_CLKCFG1_UPHY1_CLK_EN |
|
||||||
|
MT7620_CLKCFG1_UPHY0_CLK_EN) },
|
||||||
|
{ },
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, ralink_usb_phy_of_match);
|
||||||
|
|
||||||
|
static int ralink_usb_phy_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
struct resource *res;
|
||||||
|
struct phy_provider *phy_provider;
|
||||||
|
const struct of_device_id *match;
|
||||||
|
struct ralink_usb_phy *phy;
|
||||||
|
|
||||||
|
match = of_match_device(ralink_usb_phy_of_match, &pdev->dev);
|
||||||
|
if (!match)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
|
||||||
|
if (!phy)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
phy->clk = (uintptr_t)match->data;
|
||||||
|
phy->base = NULL;
|
||||||
|
|
||||||
|
phy->sysctl = syscon_regmap_lookup_by_phandle(dev->of_node, "ralink,sysctl");
|
||||||
|
if (IS_ERR(phy->sysctl)) {
|
||||||
|
dev_err(dev, "failed to get sysctl registers\n");
|
||||||
|
return PTR_ERR(phy->sysctl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The MT7628 and MT7688 require extra setup of PHY registers. */
|
||||||
|
if (of_device_is_compatible(dev->of_node, "mediatek,mt7628-usbphy")) {
|
||||||
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
phy->base = devm_ioremap_resource(&pdev->dev, res);
|
||||||
|
if (IS_ERR(phy->base)) {
|
||||||
|
dev_err(dev, "failed to remap register memory\n");
|
||||||
|
return PTR_ERR(phy->base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
phy->rsthost = devm_reset_control_get(&pdev->dev, "host");
|
||||||
|
if (IS_ERR(phy->rsthost)) {
|
||||||
|
dev_err(dev, "host reset is missing\n");
|
||||||
|
return PTR_ERR(phy->rsthost);
|
||||||
|
}
|
||||||
|
|
||||||
|
phy->rstdev = devm_reset_control_get(&pdev->dev, "device");
|
||||||
|
if (IS_ERR(phy->rstdev)) {
|
||||||
|
dev_err(dev, "device reset is missing\n");
|
||||||
|
return PTR_ERR(phy->rstdev);
|
||||||
|
}
|
||||||
|
|
||||||
|
phy->phy = devm_phy_create(dev, NULL, &ralink_usb_phy_ops);
|
||||||
|
if (IS_ERR(phy->phy)) {
|
||||||
|
dev_err(dev, "failed to create PHY\n");
|
||||||
|
return PTR_ERR(phy->phy);
|
||||||
|
}
|
||||||
|
phy_set_drvdata(phy->phy, phy);
|
||||||
|
|
||||||
|
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
|
||||||
|
|
||||||
|
return PTR_ERR_OR_ZERO(phy_provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct platform_driver ralink_usb_phy_driver = {
|
||||||
|
.probe = ralink_usb_phy_probe,
|
||||||
|
.driver = {
|
||||||
|
.of_match_table = ralink_usb_phy_of_match,
|
||||||
|
.name = "ralink-usb-phy",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
module_platform_driver(ralink_usb_phy_driver);
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("Ralink USB phy driver");
|
||||||
|
MODULE_AUTHOR("John Crispin <john@phrozen.org>");
|
||||||
|
MODULE_LICENSE("GPL v2");
|
@ -172,6 +172,8 @@ struct rockchip_usb2phy_cfg {
|
|||||||
* @vbus_attached: otg device vbus status.
|
* @vbus_attached: otg device vbus status.
|
||||||
* @bvalid_irq: IRQ number assigned for vbus valid rise detection.
|
* @bvalid_irq: IRQ number assigned for vbus valid rise detection.
|
||||||
* @ls_irq: IRQ number assigned for linestate detection.
|
* @ls_irq: IRQ number assigned for linestate detection.
|
||||||
|
* @otg_mux_irq: IRQ number which multiplex otg-id/otg-bvalid/linestate
|
||||||
|
* irqs to one irq in otg-port.
|
||||||
* @mutex: for register updating in sm_work.
|
* @mutex: for register updating in sm_work.
|
||||||
* @chg_work: charge detect work.
|
* @chg_work: charge detect work.
|
||||||
* @otg_sm_work: OTG state machine work.
|
* @otg_sm_work: OTG state machine work.
|
||||||
@ -189,6 +191,7 @@ struct rockchip_usb2phy_port {
|
|||||||
bool vbus_attached;
|
bool vbus_attached;
|
||||||
int bvalid_irq;
|
int bvalid_irq;
|
||||||
int ls_irq;
|
int ls_irq;
|
||||||
|
int otg_mux_irq;
|
||||||
struct mutex mutex;
|
struct mutex mutex;
|
||||||
struct delayed_work chg_work;
|
struct delayed_work chg_work;
|
||||||
struct delayed_work otg_sm_work;
|
struct delayed_work otg_sm_work;
|
||||||
@ -202,6 +205,7 @@ struct rockchip_usb2phy_port {
|
|||||||
/**
|
/**
|
||||||
* struct rockchip_usb2phy: usb2.0 phy driver data.
|
* struct rockchip_usb2phy: usb2.0 phy driver data.
|
||||||
* @grf: General Register Files regmap.
|
* @grf: General Register Files regmap.
|
||||||
|
* @usbgrf: USB General Register Files regmap.
|
||||||
* @clk: clock struct of phy input clk.
|
* @clk: clock struct of phy input clk.
|
||||||
* @clk480m: clock struct of phy output clk.
|
* @clk480m: clock struct of phy output clk.
|
||||||
* @clk_hw: clock struct of phy output clk management.
|
* @clk_hw: clock struct of phy output clk management.
|
||||||
@ -216,6 +220,7 @@ struct rockchip_usb2phy_port {
|
|||||||
struct rockchip_usb2phy {
|
struct rockchip_usb2phy {
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct regmap *grf;
|
struct regmap *grf;
|
||||||
|
struct regmap *usbgrf;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
struct clk *clk480m;
|
struct clk *clk480m;
|
||||||
struct clk_hw clk480m_hw;
|
struct clk_hw clk480m_hw;
|
||||||
@ -227,7 +232,12 @@ struct rockchip_usb2phy {
|
|||||||
struct rockchip_usb2phy_port ports[USB2PHY_NUM_PORTS];
|
struct rockchip_usb2phy_port ports[USB2PHY_NUM_PORTS];
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline int property_enable(struct rockchip_usb2phy *rphy,
|
static inline struct regmap *get_reg_base(struct rockchip_usb2phy *rphy)
|
||||||
|
{
|
||||||
|
return rphy->usbgrf == NULL ? rphy->grf : rphy->usbgrf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int property_enable(struct regmap *base,
|
||||||
const struct usb2phy_reg *reg, bool en)
|
const struct usb2phy_reg *reg, bool en)
|
||||||
{
|
{
|
||||||
unsigned int val, mask, tmp;
|
unsigned int val, mask, tmp;
|
||||||
@ -236,17 +246,17 @@ static inline int property_enable(struct rockchip_usb2phy *rphy,
|
|||||||
mask = GENMASK(reg->bitend, reg->bitstart);
|
mask = GENMASK(reg->bitend, reg->bitstart);
|
||||||
val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT);
|
val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT);
|
||||||
|
|
||||||
return regmap_write(rphy->grf, reg->offset, val);
|
return regmap_write(base, reg->offset, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool property_enabled(struct rockchip_usb2phy *rphy,
|
static inline bool property_enabled(struct regmap *base,
|
||||||
const struct usb2phy_reg *reg)
|
const struct usb2phy_reg *reg)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
unsigned int tmp, orig;
|
unsigned int tmp, orig;
|
||||||
unsigned int mask = GENMASK(reg->bitend, reg->bitstart);
|
unsigned int mask = GENMASK(reg->bitend, reg->bitstart);
|
||||||
|
|
||||||
ret = regmap_read(rphy->grf, reg->offset, &orig);
|
ret = regmap_read(base, reg->offset, &orig);
|
||||||
if (ret)
|
if (ret)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -258,11 +268,12 @@ static int rockchip_usb2phy_clk480m_prepare(struct clk_hw *hw)
|
|||||||
{
|
{
|
||||||
struct rockchip_usb2phy *rphy =
|
struct rockchip_usb2phy *rphy =
|
||||||
container_of(hw, struct rockchip_usb2phy, clk480m_hw);
|
container_of(hw, struct rockchip_usb2phy, clk480m_hw);
|
||||||
|
struct regmap *base = get_reg_base(rphy);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* turn on 480m clk output if it is off */
|
/* turn on 480m clk output if it is off */
|
||||||
if (!property_enabled(rphy, &rphy->phy_cfg->clkout_ctl)) {
|
if (!property_enabled(base, &rphy->phy_cfg->clkout_ctl)) {
|
||||||
ret = property_enable(rphy, &rphy->phy_cfg->clkout_ctl, true);
|
ret = property_enable(base, &rphy->phy_cfg->clkout_ctl, true);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -277,17 +288,19 @@ static void rockchip_usb2phy_clk480m_unprepare(struct clk_hw *hw)
|
|||||||
{
|
{
|
||||||
struct rockchip_usb2phy *rphy =
|
struct rockchip_usb2phy *rphy =
|
||||||
container_of(hw, struct rockchip_usb2phy, clk480m_hw);
|
container_of(hw, struct rockchip_usb2phy, clk480m_hw);
|
||||||
|
struct regmap *base = get_reg_base(rphy);
|
||||||
|
|
||||||
/* turn off 480m clk output */
|
/* turn off 480m clk output */
|
||||||
property_enable(rphy, &rphy->phy_cfg->clkout_ctl, false);
|
property_enable(base, &rphy->phy_cfg->clkout_ctl, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rockchip_usb2phy_clk480m_prepared(struct clk_hw *hw)
|
static int rockchip_usb2phy_clk480m_prepared(struct clk_hw *hw)
|
||||||
{
|
{
|
||||||
struct rockchip_usb2phy *rphy =
|
struct rockchip_usb2phy *rphy =
|
||||||
container_of(hw, struct rockchip_usb2phy, clk480m_hw);
|
container_of(hw, struct rockchip_usb2phy, clk480m_hw);
|
||||||
|
struct regmap *base = get_reg_base(rphy);
|
||||||
|
|
||||||
return property_enabled(rphy, &rphy->phy_cfg->clkout_ctl);
|
return property_enabled(base, &rphy->phy_cfg->clkout_ctl);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned long
|
static unsigned long
|
||||||
@ -409,13 +422,13 @@ static int rockchip_usb2phy_init(struct phy *phy)
|
|||||||
if (rport->mode != USB_DR_MODE_HOST &&
|
if (rport->mode != USB_DR_MODE_HOST &&
|
||||||
rport->mode != USB_DR_MODE_UNKNOWN) {
|
rport->mode != USB_DR_MODE_UNKNOWN) {
|
||||||
/* clear bvalid status and enable bvalid detect irq */
|
/* clear bvalid status and enable bvalid detect irq */
|
||||||
ret = property_enable(rphy,
|
ret = property_enable(rphy->grf,
|
||||||
&rport->port_cfg->bvalid_det_clr,
|
&rport->port_cfg->bvalid_det_clr,
|
||||||
true);
|
true);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ret = property_enable(rphy,
|
ret = property_enable(rphy->grf,
|
||||||
&rport->port_cfg->bvalid_det_en,
|
&rport->port_cfg->bvalid_det_en,
|
||||||
true);
|
true);
|
||||||
if (ret)
|
if (ret)
|
||||||
@ -429,11 +442,13 @@ static int rockchip_usb2phy_init(struct phy *phy)
|
|||||||
}
|
}
|
||||||
} else if (rport->port_id == USB2PHY_PORT_HOST) {
|
} else if (rport->port_id == USB2PHY_PORT_HOST) {
|
||||||
/* clear linestate and enable linestate detect irq */
|
/* clear linestate and enable linestate detect irq */
|
||||||
ret = property_enable(rphy, &rport->port_cfg->ls_det_clr, true);
|
ret = property_enable(rphy->grf,
|
||||||
|
&rport->port_cfg->ls_det_clr, true);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ret = property_enable(rphy, &rport->port_cfg->ls_det_en, true);
|
ret = property_enable(rphy->grf,
|
||||||
|
&rport->port_cfg->ls_det_en, true);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@ -449,6 +464,7 @@ static int rockchip_usb2phy_power_on(struct phy *phy)
|
|||||||
{
|
{
|
||||||
struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
|
struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
|
||||||
struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
|
struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
|
||||||
|
struct regmap *base = get_reg_base(rphy);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
dev_dbg(&rport->phy->dev, "port power on\n");
|
dev_dbg(&rport->phy->dev, "port power on\n");
|
||||||
@ -460,7 +476,7 @@ static int rockchip_usb2phy_power_on(struct phy *phy)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = property_enable(rphy, &rport->port_cfg->phy_sus, false);
|
ret = property_enable(base, &rport->port_cfg->phy_sus, false);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -475,6 +491,7 @@ static int rockchip_usb2phy_power_off(struct phy *phy)
|
|||||||
{
|
{
|
||||||
struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
|
struct rockchip_usb2phy_port *rport = phy_get_drvdata(phy);
|
||||||
struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
|
struct rockchip_usb2phy *rphy = dev_get_drvdata(phy->dev.parent);
|
||||||
|
struct regmap *base = get_reg_base(rphy);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
dev_dbg(&rport->phy->dev, "port power off\n");
|
dev_dbg(&rport->phy->dev, "port power off\n");
|
||||||
@ -482,7 +499,7 @@ static int rockchip_usb2phy_power_off(struct phy *phy)
|
|||||||
if (rport->suspended)
|
if (rport->suspended)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ret = property_enable(rphy, &rport->port_cfg->phy_sus, true);
|
ret = property_enable(base, &rport->port_cfg->phy_sus, true);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -526,11 +543,11 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work)
|
|||||||
bool vbus_attach, sch_work, notify_charger;
|
bool vbus_attach, sch_work, notify_charger;
|
||||||
|
|
||||||
if (rport->utmi_avalid)
|
if (rport->utmi_avalid)
|
||||||
vbus_attach =
|
vbus_attach = property_enabled(rphy->grf,
|
||||||
property_enabled(rphy, &rport->port_cfg->utmi_avalid);
|
&rport->port_cfg->utmi_avalid);
|
||||||
else
|
else
|
||||||
vbus_attach =
|
vbus_attach = property_enabled(rphy->grf,
|
||||||
property_enabled(rphy, &rport->port_cfg->utmi_bvalid);
|
&rport->port_cfg->utmi_bvalid);
|
||||||
|
|
||||||
sch_work = false;
|
sch_work = false;
|
||||||
notify_charger = false;
|
notify_charger = false;
|
||||||
@ -650,22 +667,28 @@ static const char *chg_to_string(enum power_supply_type chg_type)
|
|||||||
static void rockchip_chg_enable_dcd(struct rockchip_usb2phy *rphy,
|
static void rockchip_chg_enable_dcd(struct rockchip_usb2phy *rphy,
|
||||||
bool en)
|
bool en)
|
||||||
{
|
{
|
||||||
property_enable(rphy, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en);
|
struct regmap *base = get_reg_base(rphy);
|
||||||
property_enable(rphy, &rphy->phy_cfg->chg_det.idp_src_en, en);
|
|
||||||
|
property_enable(base, &rphy->phy_cfg->chg_det.rdm_pdwn_en, en);
|
||||||
|
property_enable(base, &rphy->phy_cfg->chg_det.idp_src_en, en);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rockchip_chg_enable_primary_det(struct rockchip_usb2phy *rphy,
|
static void rockchip_chg_enable_primary_det(struct rockchip_usb2phy *rphy,
|
||||||
bool en)
|
bool en)
|
||||||
{
|
{
|
||||||
property_enable(rphy, &rphy->phy_cfg->chg_det.vdp_src_en, en);
|
struct regmap *base = get_reg_base(rphy);
|
||||||
property_enable(rphy, &rphy->phy_cfg->chg_det.idm_sink_en, en);
|
|
||||||
|
property_enable(base, &rphy->phy_cfg->chg_det.vdp_src_en, en);
|
||||||
|
property_enable(base, &rphy->phy_cfg->chg_det.idm_sink_en, en);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rockchip_chg_enable_secondary_det(struct rockchip_usb2phy *rphy,
|
static void rockchip_chg_enable_secondary_det(struct rockchip_usb2phy *rphy,
|
||||||
bool en)
|
bool en)
|
||||||
{
|
{
|
||||||
property_enable(rphy, &rphy->phy_cfg->chg_det.vdm_src_en, en);
|
struct regmap *base = get_reg_base(rphy);
|
||||||
property_enable(rphy, &rphy->phy_cfg->chg_det.idp_sink_en, en);
|
|
||||||
|
property_enable(base, &rphy->phy_cfg->chg_det.vdm_src_en, en);
|
||||||
|
property_enable(base, &rphy->phy_cfg->chg_det.idp_sink_en, en);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CHG_DCD_POLL_TIME (100 * HZ / 1000)
|
#define CHG_DCD_POLL_TIME (100 * HZ / 1000)
|
||||||
@ -677,6 +700,7 @@ static void rockchip_chg_detect_work(struct work_struct *work)
|
|||||||
struct rockchip_usb2phy_port *rport =
|
struct rockchip_usb2phy_port *rport =
|
||||||
container_of(work, struct rockchip_usb2phy_port, chg_work.work);
|
container_of(work, struct rockchip_usb2phy_port, chg_work.work);
|
||||||
struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
|
struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
|
||||||
|
struct regmap *base = get_reg_base(rphy);
|
||||||
bool is_dcd, tmout, vout;
|
bool is_dcd, tmout, vout;
|
||||||
unsigned long delay;
|
unsigned long delay;
|
||||||
|
|
||||||
@ -687,7 +711,7 @@ static void rockchip_chg_detect_work(struct work_struct *work)
|
|||||||
if (!rport->suspended)
|
if (!rport->suspended)
|
||||||
rockchip_usb2phy_power_off(rport->phy);
|
rockchip_usb2phy_power_off(rport->phy);
|
||||||
/* put the controller in non-driving mode */
|
/* put the controller in non-driving mode */
|
||||||
property_enable(rphy, &rphy->phy_cfg->chg_det.opmode, false);
|
property_enable(base, &rphy->phy_cfg->chg_det.opmode, false);
|
||||||
/* Start DCD processing stage 1 */
|
/* Start DCD processing stage 1 */
|
||||||
rockchip_chg_enable_dcd(rphy, true);
|
rockchip_chg_enable_dcd(rphy, true);
|
||||||
rphy->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
|
rphy->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
|
||||||
@ -696,7 +720,8 @@ static void rockchip_chg_detect_work(struct work_struct *work)
|
|||||||
break;
|
break;
|
||||||
case USB_CHG_STATE_WAIT_FOR_DCD:
|
case USB_CHG_STATE_WAIT_FOR_DCD:
|
||||||
/* get data contact detection status */
|
/* get data contact detection status */
|
||||||
is_dcd = property_enabled(rphy, &rphy->phy_cfg->chg_det.dp_det);
|
is_dcd = property_enabled(rphy->grf,
|
||||||
|
&rphy->phy_cfg->chg_det.dp_det);
|
||||||
tmout = ++rphy->dcd_retries == CHG_DCD_MAX_RETRIES;
|
tmout = ++rphy->dcd_retries == CHG_DCD_MAX_RETRIES;
|
||||||
/* stage 2 */
|
/* stage 2 */
|
||||||
if (is_dcd || tmout) {
|
if (is_dcd || tmout) {
|
||||||
@ -713,7 +738,8 @@ static void rockchip_chg_detect_work(struct work_struct *work)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case USB_CHG_STATE_DCD_DONE:
|
case USB_CHG_STATE_DCD_DONE:
|
||||||
vout = property_enabled(rphy, &rphy->phy_cfg->chg_det.cp_det);
|
vout = property_enabled(rphy->grf,
|
||||||
|
&rphy->phy_cfg->chg_det.cp_det);
|
||||||
rockchip_chg_enable_primary_det(rphy, false);
|
rockchip_chg_enable_primary_det(rphy, false);
|
||||||
if (vout) {
|
if (vout) {
|
||||||
/* Voltage Source on DM, Probe on DP */
|
/* Voltage Source on DM, Probe on DP */
|
||||||
@ -734,7 +760,8 @@ static void rockchip_chg_detect_work(struct work_struct *work)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case USB_CHG_STATE_PRIMARY_DONE:
|
case USB_CHG_STATE_PRIMARY_DONE:
|
||||||
vout = property_enabled(rphy, &rphy->phy_cfg->chg_det.dcp_det);
|
vout = property_enabled(rphy->grf,
|
||||||
|
&rphy->phy_cfg->chg_det.dcp_det);
|
||||||
/* Turn off voltage source */
|
/* Turn off voltage source */
|
||||||
rockchip_chg_enable_secondary_det(rphy, false);
|
rockchip_chg_enable_secondary_det(rphy, false);
|
||||||
if (vout)
|
if (vout)
|
||||||
@ -748,7 +775,7 @@ static void rockchip_chg_detect_work(struct work_struct *work)
|
|||||||
/* fall through */
|
/* fall through */
|
||||||
case USB_CHG_STATE_DETECTED:
|
case USB_CHG_STATE_DETECTED:
|
||||||
/* put the controller in normal mode */
|
/* put the controller in normal mode */
|
||||||
property_enable(rphy, &rphy->phy_cfg->chg_det.opmode, true);
|
property_enable(base, &rphy->phy_cfg->chg_det.opmode, true);
|
||||||
rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work);
|
rockchip_usb2phy_otg_sm_work(&rport->otg_sm_work.work);
|
||||||
dev_info(&rport->phy->dev, "charger = %s\n",
|
dev_info(&rport->phy->dev, "charger = %s\n",
|
||||||
chg_to_string(rphy->chg_type));
|
chg_to_string(rphy->chg_type));
|
||||||
@ -790,8 +817,7 @@ static void rockchip_usb2phy_sm_work(struct work_struct *work)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto next_schedule;
|
goto next_schedule;
|
||||||
|
|
||||||
ret = regmap_read(rphy->grf, rport->port_cfg->utmi_hstdet.offset,
|
ret = regmap_read(rphy->grf, rport->port_cfg->utmi_hstdet.offset, &uhd);
|
||||||
&uhd);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto next_schedule;
|
goto next_schedule;
|
||||||
|
|
||||||
@ -845,8 +871,8 @@ static void rockchip_usb2phy_sm_work(struct work_struct *work)
|
|||||||
* activate the linestate detection to get the next device
|
* activate the linestate detection to get the next device
|
||||||
* plug-in irq.
|
* plug-in irq.
|
||||||
*/
|
*/
|
||||||
property_enable(rphy, &rport->port_cfg->ls_det_clr, true);
|
property_enable(rphy->grf, &rport->port_cfg->ls_det_clr, true);
|
||||||
property_enable(rphy, &rport->port_cfg->ls_det_en, true);
|
property_enable(rphy->grf, &rport->port_cfg->ls_det_en, true);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* we don't need to rearm the delayed work when the phy port
|
* we don't need to rearm the delayed work when the phy port
|
||||||
@ -869,14 +895,14 @@ static irqreturn_t rockchip_usb2phy_linestate_irq(int irq, void *data)
|
|||||||
struct rockchip_usb2phy_port *rport = data;
|
struct rockchip_usb2phy_port *rport = data;
|
||||||
struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
|
struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
|
||||||
|
|
||||||
if (!property_enabled(rphy, &rport->port_cfg->ls_det_st))
|
if (!property_enabled(rphy->grf, &rport->port_cfg->ls_det_st))
|
||||||
return IRQ_NONE;
|
return IRQ_NONE;
|
||||||
|
|
||||||
mutex_lock(&rport->mutex);
|
mutex_lock(&rport->mutex);
|
||||||
|
|
||||||
/* disable linestate detect irq and clear its status */
|
/* disable linestate detect irq and clear its status */
|
||||||
property_enable(rphy, &rport->port_cfg->ls_det_en, false);
|
property_enable(rphy->grf, &rport->port_cfg->ls_det_en, false);
|
||||||
property_enable(rphy, &rport->port_cfg->ls_det_clr, true);
|
property_enable(rphy->grf, &rport->port_cfg->ls_det_clr, true);
|
||||||
|
|
||||||
mutex_unlock(&rport->mutex);
|
mutex_unlock(&rport->mutex);
|
||||||
|
|
||||||
@ -896,13 +922,13 @@ static irqreturn_t rockchip_usb2phy_bvalid_irq(int irq, void *data)
|
|||||||
struct rockchip_usb2phy_port *rport = data;
|
struct rockchip_usb2phy_port *rport = data;
|
||||||
struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
|
struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
|
||||||
|
|
||||||
if (!property_enabled(rphy, &rport->port_cfg->bvalid_det_st))
|
if (!property_enabled(rphy->grf, &rport->port_cfg->bvalid_det_st))
|
||||||
return IRQ_NONE;
|
return IRQ_NONE;
|
||||||
|
|
||||||
mutex_lock(&rport->mutex);
|
mutex_lock(&rport->mutex);
|
||||||
|
|
||||||
/* clear bvalid detect irq pending status */
|
/* clear bvalid detect irq pending status */
|
||||||
property_enable(rphy, &rport->port_cfg->bvalid_det_clr, true);
|
property_enable(rphy->grf, &rport->port_cfg->bvalid_det_clr, true);
|
||||||
|
|
||||||
mutex_unlock(&rport->mutex);
|
mutex_unlock(&rport->mutex);
|
||||||
|
|
||||||
@ -911,6 +937,17 @@ static irqreturn_t rockchip_usb2phy_bvalid_irq(int irq, void *data)
|
|||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static irqreturn_t rockchip_usb2phy_otg_mux_irq(int irq, void *data)
|
||||||
|
{
|
||||||
|
struct rockchip_usb2phy_port *rport = data;
|
||||||
|
struct rockchip_usb2phy *rphy = dev_get_drvdata(rport->phy->dev.parent);
|
||||||
|
|
||||||
|
if (property_enabled(rphy->grf, &rport->port_cfg->bvalid_det_st))
|
||||||
|
return rockchip_usb2phy_bvalid_irq(irq, data);
|
||||||
|
else
|
||||||
|
return IRQ_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
static int rockchip_usb2phy_host_port_init(struct rockchip_usb2phy *rphy,
|
static int rockchip_usb2phy_host_port_init(struct rockchip_usb2phy *rphy,
|
||||||
struct rockchip_usb2phy_port *rport,
|
struct rockchip_usb2phy_port *rport,
|
||||||
struct device_node *child_np)
|
struct device_node *child_np)
|
||||||
@ -987,20 +1024,43 @@ static int rockchip_usb2phy_otg_port_init(struct rockchip_usb2phy *rphy,
|
|||||||
rport->utmi_avalid =
|
rport->utmi_avalid =
|
||||||
of_property_read_bool(child_np, "rockchip,utmi-avalid");
|
of_property_read_bool(child_np, "rockchip,utmi-avalid");
|
||||||
|
|
||||||
rport->bvalid_irq = of_irq_get_byname(child_np, "otg-bvalid");
|
/*
|
||||||
if (rport->bvalid_irq < 0) {
|
* Some SoCs use one interrupt with otg-id/otg-bvalid/linestate
|
||||||
dev_err(rphy->dev, "no vbus valid irq provided\n");
|
* interrupts muxed together, so probe the otg-mux interrupt first,
|
||||||
ret = rport->bvalid_irq;
|
* if not found, then look for the regular interrupts one by one.
|
||||||
goto out;
|
*/
|
||||||
}
|
rport->otg_mux_irq = of_irq_get_byname(child_np, "otg-mux");
|
||||||
|
if (rport->otg_mux_irq > 0) {
|
||||||
|
ret = devm_request_threaded_irq(rphy->dev, rport->otg_mux_irq,
|
||||||
|
NULL,
|
||||||
|
rockchip_usb2phy_otg_mux_irq,
|
||||||
|
IRQF_ONESHOT,
|
||||||
|
"rockchip_usb2phy_otg",
|
||||||
|
rport);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(rphy->dev,
|
||||||
|
"failed to request otg-mux irq handle\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rport->bvalid_irq = of_irq_get_byname(child_np, "otg-bvalid");
|
||||||
|
if (rport->bvalid_irq < 0) {
|
||||||
|
dev_err(rphy->dev, "no vbus valid irq provided\n");
|
||||||
|
ret = rport->bvalid_irq;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
ret = devm_request_threaded_irq(rphy->dev, rport->bvalid_irq, NULL,
|
ret = devm_request_threaded_irq(rphy->dev, rport->bvalid_irq,
|
||||||
rockchip_usb2phy_bvalid_irq,
|
NULL,
|
||||||
IRQF_ONESHOT,
|
rockchip_usb2phy_bvalid_irq,
|
||||||
"rockchip_usb2phy_bvalid", rport);
|
IRQF_ONESHOT,
|
||||||
if (ret) {
|
"rockchip_usb2phy_bvalid",
|
||||||
dev_err(rphy->dev, "failed to request otg-bvalid irq handle\n");
|
rport);
|
||||||
goto out;
|
if (ret) {
|
||||||
|
dev_err(rphy->dev,
|
||||||
|
"failed to request otg-bvalid irq handle\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IS_ERR(rphy->edev)) {
|
if (!IS_ERR(rphy->edev)) {
|
||||||
@ -1045,6 +1105,16 @@ static int rockchip_usb2phy_probe(struct platform_device *pdev)
|
|||||||
if (IS_ERR(rphy->grf))
|
if (IS_ERR(rphy->grf))
|
||||||
return PTR_ERR(rphy->grf);
|
return PTR_ERR(rphy->grf);
|
||||||
|
|
||||||
|
if (of_device_is_compatible(np, "rockchip,rv1108-usb2phy")) {
|
||||||
|
rphy->usbgrf =
|
||||||
|
syscon_regmap_lookup_by_phandle(dev->of_node,
|
||||||
|
"rockchip,usbgrf");
|
||||||
|
if (IS_ERR(rphy->usbgrf))
|
||||||
|
return PTR_ERR(rphy->usbgrf);
|
||||||
|
} else {
|
||||||
|
rphy->usbgrf = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (of_property_read_u32(np, "reg", ®)) {
|
if (of_property_read_u32(np, "reg", ®)) {
|
||||||
dev_err(dev, "the reg property is not assigned in %s node\n",
|
dev_err(dev, "the reg property is not assigned in %s node\n",
|
||||||
np->name);
|
np->name);
|
||||||
@ -1327,11 +1397,54 @@ static const struct rockchip_usb2phy_cfg rk3399_phy_cfgs[] = {
|
|||||||
{ /* sentinel */ }
|
{ /* sentinel */ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct rockchip_usb2phy_cfg rv1108_phy_cfgs[] = {
|
||||||
|
{
|
||||||
|
.reg = 0x100,
|
||||||
|
.num_ports = 2,
|
||||||
|
.clkout_ctl = { 0x108, 4, 4, 1, 0 },
|
||||||
|
.port_cfgs = {
|
||||||
|
[USB2PHY_PORT_OTG] = {
|
||||||
|
.phy_sus = { 0x0100, 15, 0, 0, 0x1d1 },
|
||||||
|
.bvalid_det_en = { 0x0680, 3, 3, 0, 1 },
|
||||||
|
.bvalid_det_st = { 0x0690, 3, 3, 0, 1 },
|
||||||
|
.bvalid_det_clr = { 0x06a0, 3, 3, 0, 1 },
|
||||||
|
.ls_det_en = { 0x0680, 2, 2, 0, 1 },
|
||||||
|
.ls_det_st = { 0x0690, 2, 2, 0, 1 },
|
||||||
|
.ls_det_clr = { 0x06a0, 2, 2, 0, 1 },
|
||||||
|
.utmi_bvalid = { 0x0804, 10, 10, 0, 1 },
|
||||||
|
.utmi_ls = { 0x0804, 13, 12, 0, 1 },
|
||||||
|
},
|
||||||
|
[USB2PHY_PORT_HOST] = {
|
||||||
|
.phy_sus = { 0x0104, 15, 0, 0, 0x1d1 },
|
||||||
|
.ls_det_en = { 0x0680, 4, 4, 0, 1 },
|
||||||
|
.ls_det_st = { 0x0690, 4, 4, 0, 1 },
|
||||||
|
.ls_det_clr = { 0x06a0, 4, 4, 0, 1 },
|
||||||
|
.utmi_ls = { 0x0804, 9, 8, 0, 1 },
|
||||||
|
.utmi_hstdet = { 0x0804, 7, 7, 0, 1 }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.chg_det = {
|
||||||
|
.opmode = { 0x0100, 3, 0, 5, 1 },
|
||||||
|
.cp_det = { 0x0804, 1, 1, 0, 1 },
|
||||||
|
.dcp_det = { 0x0804, 0, 0, 0, 1 },
|
||||||
|
.dp_det = { 0x0804, 2, 2, 0, 1 },
|
||||||
|
.idm_sink_en = { 0x0108, 8, 8, 0, 1 },
|
||||||
|
.idp_sink_en = { 0x0108, 7, 7, 0, 1 },
|
||||||
|
.idp_src_en = { 0x0108, 9, 9, 0, 1 },
|
||||||
|
.rdm_pdwn_en = { 0x0108, 10, 10, 0, 1 },
|
||||||
|
.vdm_src_en = { 0x0108, 12, 12, 0, 1 },
|
||||||
|
.vdp_src_en = { 0x0108, 11, 11, 0, 1 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ /* sentinel */ }
|
||||||
|
};
|
||||||
|
|
||||||
static const struct of_device_id rockchip_usb2phy_dt_match[] = {
|
static const struct of_device_id rockchip_usb2phy_dt_match[] = {
|
||||||
{ .compatible = "rockchip,rk3228-usb2phy", .data = &rk3228_phy_cfgs },
|
{ .compatible = "rockchip,rk3228-usb2phy", .data = &rk3228_phy_cfgs },
|
||||||
{ .compatible = "rockchip,rk3328-usb2phy", .data = &rk3328_phy_cfgs },
|
{ .compatible = "rockchip,rk3328-usb2phy", .data = &rk3328_phy_cfgs },
|
||||||
{ .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs },
|
{ .compatible = "rockchip,rk3366-usb2phy", .data = &rk3366_phy_cfgs },
|
||||||
{ .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs },
|
{ .compatible = "rockchip,rk3399-usb2phy", .data = &rk3399_phy_cfgs },
|
||||||
|
{ .compatible = "rockchip,rv1108-usb2phy", .data = &rv1108_phy_cfgs },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, rockchip_usb2phy_dt_match);
|
MODULE_DEVICE_TABLE(of, rockchip_usb2phy_dt_match);
|
||||||
|
@ -622,12 +622,11 @@ static int tcphy_get_mode(struct rockchip_typec_phy *tcphy)
|
|||||||
struct extcon_dev *edev = tcphy->extcon;
|
struct extcon_dev *edev = tcphy->extcon;
|
||||||
union extcon_property_value property;
|
union extcon_property_value property;
|
||||||
unsigned int id;
|
unsigned int id;
|
||||||
bool dfp, ufp, dp;
|
bool ufp, dp;
|
||||||
u8 mode;
|
u8 mode;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ufp = extcon_get_state(edev, EXTCON_USB);
|
ufp = extcon_get_state(edev, EXTCON_USB);
|
||||||
dfp = extcon_get_state(edev, EXTCON_USB_HOST);
|
|
||||||
dp = extcon_get_state(edev, EXTCON_DISP_DP);
|
dp = extcon_get_state(edev, EXTCON_DISP_DP);
|
||||||
|
|
||||||
mode = MODE_DFP_USB;
|
mode = MODE_DFP_USB;
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include <linux/mfd/syscon.h>
|
#include <linux/mfd/syscon.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/of_address.h>
|
#include <linux/of_address.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
#include <linux/phy/phy.h>
|
#include <linux/phy/phy.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/regmap.h>
|
#include <linux/regmap.h>
|
||||||
@ -78,7 +79,6 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev)
|
|||||||
{
|
{
|
||||||
struct exynos_dp_video_phy *state;
|
struct exynos_dp_video_phy *state;
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
const struct of_device_id *match;
|
|
||||||
struct phy_provider *phy_provider;
|
struct phy_provider *phy_provider;
|
||||||
struct phy *phy;
|
struct phy *phy;
|
||||||
|
|
||||||
@ -93,8 +93,7 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev)
|
|||||||
return PTR_ERR(state->regs);
|
return PTR_ERR(state->regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
match = of_match_node(exynos_dp_video_phy_of_match, dev->of_node);
|
state->drvdata = of_device_get_match_data(dev);
|
||||||
state->drvdata = match->data;
|
|
||||||
|
|
||||||
phy = devm_phy_create(dev, NULL, &exynos_dp_video_phy_ops);
|
phy = devm_phy_create(dev, NULL, &exynos_dp_video_phy_ops);
|
||||||
if (IS_ERR(phy)) {
|
if (IS_ERR(phy)) {
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/of_address.h>
|
#include <linux/of_address.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
#include <linux/phy/phy.h>
|
#include <linux/phy/phy.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
@ -662,7 +663,6 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
|
|||||||
struct exynos5_usbdrd_phy *phy_drd;
|
struct exynos5_usbdrd_phy *phy_drd;
|
||||||
struct phy_provider *phy_provider;
|
struct phy_provider *phy_provider;
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
const struct of_device_id *match;
|
|
||||||
const struct exynos5_usbdrd_phy_drvdata *drv_data;
|
const struct exynos5_usbdrd_phy_drvdata *drv_data;
|
||||||
struct regmap *reg_pmu;
|
struct regmap *reg_pmu;
|
||||||
u32 pmu_offset;
|
u32 pmu_offset;
|
||||||
@ -681,9 +681,10 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
|
|||||||
if (IS_ERR(phy_drd->reg_phy))
|
if (IS_ERR(phy_drd->reg_phy))
|
||||||
return PTR_ERR(phy_drd->reg_phy);
|
return PTR_ERR(phy_drd->reg_phy);
|
||||||
|
|
||||||
match = of_match_node(exynos5_usbdrd_phy_of_match, pdev->dev.of_node);
|
drv_data = of_device_get_match_data(dev);
|
||||||
|
if (!drv_data)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
drv_data = match->data;
|
|
||||||
phy_drd->drv_data = drv_data;
|
phy_drd->drv_data = drv_data;
|
||||||
|
|
||||||
ret = exynos5_usbdrd_phy_clk_handle(phy_drd);
|
ret = exynos5_usbdrd_phy_clk_handle(phy_drd);
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/of_address.h>
|
#include <linux/of_address.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
#include <linux/phy/phy.h>
|
#include <linux/phy/phy.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
@ -142,7 +143,6 @@ MODULE_DEVICE_TABLE(of, samsung_usb2_phy_of_match);
|
|||||||
|
|
||||||
static int samsung_usb2_phy_probe(struct platform_device *pdev)
|
static int samsung_usb2_phy_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
const struct of_device_id *match;
|
|
||||||
const struct samsung_usb2_phy_config *cfg;
|
const struct samsung_usb2_phy_config *cfg;
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct phy_provider *phy_provider;
|
struct phy_provider *phy_provider;
|
||||||
@ -155,12 +155,9 @@ static int samsung_usb2_phy_probe(struct platform_device *pdev)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
match = of_match_node(samsung_usb2_phy_of_match, pdev->dev.of_node);
|
cfg = of_device_get_match_data(dev);
|
||||||
if (!match) {
|
if (!cfg)
|
||||||
dev_err(dev, "of_match_node() failed\n");
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
|
||||||
cfg = match->data;
|
|
||||||
|
|
||||||
drv = devm_kzalloc(dev, sizeof(struct samsung_usb2_phy_driver) +
|
drv = devm_kzalloc(dev, sizeof(struct samsung_usb2_phy_driver) +
|
||||||
cfg->num_phys * sizeof(struct samsung_usb2_phy_instance),
|
cfg->num_phys * sizeof(struct samsung_usb2_phy_instance),
|
||||||
|
@ -118,12 +118,12 @@ static struct pipe3_dpll_map dpll_map_usb[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static struct pipe3_dpll_map dpll_map_sata[] = {
|
static struct pipe3_dpll_map dpll_map_sata[] = {
|
||||||
{12000000, {1000, 7, 4, 6, 0} }, /* 12 MHz */
|
{12000000, {625, 4, 4, 6, 0} }, /* 12 MHz */
|
||||||
{16800000, {714, 7, 4, 6, 0} }, /* 16.8 MHz */
|
{16800000, {625, 6, 4, 7, 0} }, /* 16.8 MHz */
|
||||||
{19200000, {625, 7, 4, 6, 0} }, /* 19.2 MHz */
|
{19200000, {625, 7, 4, 6, 0} }, /* 19.2 MHz */
|
||||||
{20000000, {600, 7, 4, 6, 0} }, /* 20 MHz */
|
{20000000, {750, 9, 4, 6, 0} }, /* 20 MHz */
|
||||||
{26000000, {461, 7, 4, 6, 0} }, /* 26 MHz */
|
{26000000, {750, 12, 4, 6, 0} }, /* 26 MHz */
|
||||||
{38400000, {312, 7, 4, 6, 0} }, /* 38.4 MHz */
|
{38400000, {625, 15, 4, 6, 0} }, /* 38.4 MHz */
|
||||||
{ }, /* Terminator */
|
{ }, /* Terminator */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ struct twl4030_usb {
|
|||||||
static int twl4030_i2c_write_u8_verify(struct twl4030_usb *twl,
|
static int twl4030_i2c_write_u8_verify(struct twl4030_usb *twl,
|
||||||
u8 module, u8 data, u8 address)
|
u8 module, u8 data, u8 address)
|
||||||
{
|
{
|
||||||
u8 check;
|
u8 check = 0xFF;
|
||||||
|
|
||||||
if ((twl_i2c_write_u8(module, data, address) >= 0) &&
|
if ((twl_i2c_write_u8(module, data, address) >= 0) &&
|
||||||
(twl_i2c_read_u8(module, &check, address) >= 0) &&
|
(twl_i2c_read_u8(module, &check, address) >= 0) &&
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/power_supply.h>
|
#include <linux/power_supply.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
#include <linux/usb/phy.h>
|
||||||
|
|
||||||
#include <linux/mfd/wm831x/core.h>
|
#include <linux/mfd/wm831x/core.h>
|
||||||
#include <linux/mfd/wm831x/auxadc.h>
|
#include <linux/mfd/wm831x/auxadc.h>
|
||||||
@ -31,6 +32,8 @@ struct wm831x_power {
|
|||||||
char usb_name[20];
|
char usb_name[20];
|
||||||
char battery_name[20];
|
char battery_name[20];
|
||||||
bool have_battery;
|
bool have_battery;
|
||||||
|
struct usb_phy *usb_phy;
|
||||||
|
struct notifier_block usb_notify;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int wm831x_power_check_online(struct wm831x *wm831x, int supply,
|
static int wm831x_power_check_online(struct wm831x *wm831x, int supply,
|
||||||
@ -125,6 +128,43 @@ static enum power_supply_property wm831x_usb_props[] = {
|
|||||||
POWER_SUPPLY_PROP_VOLTAGE_NOW,
|
POWER_SUPPLY_PROP_VOLTAGE_NOW,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* In milliamps */
|
||||||
|
static const unsigned int wm831x_usb_limits[] = {
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
100,
|
||||||
|
500,
|
||||||
|
900,
|
||||||
|
1500,
|
||||||
|
1800,
|
||||||
|
550,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int wm831x_usb_limit_change(struct notifier_block *nb,
|
||||||
|
unsigned long limit, void *data)
|
||||||
|
{
|
||||||
|
struct wm831x_power *wm831x_power = container_of(nb,
|
||||||
|
struct wm831x_power,
|
||||||
|
usb_notify);
|
||||||
|
unsigned int i, best;
|
||||||
|
|
||||||
|
/* Find the highest supported limit */
|
||||||
|
best = 0;
|
||||||
|
for (i = 0; i < ARRAY_SIZE(wm831x_usb_limits); i++) {
|
||||||
|
if (limit >= wm831x_usb_limits[i] &&
|
||||||
|
wm831x_usb_limits[best] < wm831x_usb_limits[i])
|
||||||
|
best = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_dbg(wm831x_power->wm831x->dev,
|
||||||
|
"Limiting USB current to %umA", wm831x_usb_limits[best]);
|
||||||
|
|
||||||
|
wm831x_set_bits(wm831x_power->wm831x, WM831X_POWER_STATE,
|
||||||
|
WM831X_USB_ILIM_MASK, best);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
* Battery properties
|
* Battery properties
|
||||||
*********************************************************************/
|
*********************************************************************/
|
||||||
@ -607,6 +647,33 @@ static int wm831x_power_probe(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
power->usb_phy = devm_usb_get_phy_by_phandle(&pdev->dev, "phys", 0);
|
||||||
|
ret = PTR_ERR_OR_ZERO(power->usb_phy);
|
||||||
|
|
||||||
|
switch (ret) {
|
||||||
|
case 0:
|
||||||
|
power->usb_notify.notifier_call = wm831x_usb_limit_change;
|
||||||
|
ret = usb_register_notifier(power->usb_phy, &power->usb_notify);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(&pdev->dev, "Failed to register notifier: %d\n",
|
||||||
|
ret);
|
||||||
|
goto err_bat_irq;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case -EINVAL:
|
||||||
|
case -ENODEV:
|
||||||
|
/* ignore missing usb-phy, it's optional */
|
||||||
|
power->usb_phy = NULL;
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dev_err(&pdev->dev, "Failed to find USB phy: %d\n", ret);
|
||||||
|
/* fall-through */
|
||||||
|
case -EPROBE_DEFER:
|
||||||
|
goto err_bat_irq;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
err_bat_irq:
|
err_bat_irq:
|
||||||
@ -637,6 +704,11 @@ static int wm831x_power_remove(struct platform_device *pdev)
|
|||||||
struct wm831x *wm831x = wm831x_power->wm831x;
|
struct wm831x *wm831x = wm831x_power->wm831x;
|
||||||
int irq, i;
|
int irq, i;
|
||||||
|
|
||||||
|
if (wm831x_power->usb_phy) {
|
||||||
|
usb_unregister_notifier(wm831x_power->usb_phy,
|
||||||
|
&wm831x_power->usb_notify);
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) {
|
for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) {
|
||||||
irq = wm831x_irq(wm831x,
|
irq = wm831x_irq(wm831x,
|
||||||
platform_get_irq_byname(pdev,
|
platform_get_irq_byname(pdev,
|
||||||
|
@ -43,7 +43,6 @@
|
|||||||
#include "usbatm.h"
|
#include "usbatm.h"
|
||||||
|
|
||||||
#define DRIVER_AUTHOR "Roman Kagan, David Woodhouse, Duncan Sands, Simon Arlott"
|
#define DRIVER_AUTHOR "Roman Kagan, David Woodhouse, Duncan Sands, Simon Arlott"
|
||||||
#define DRIVER_VERSION "0.4"
|
|
||||||
#define DRIVER_DESC "Conexant AccessRunner ADSL USB modem driver"
|
#define DRIVER_DESC "Conexant AccessRunner ADSL USB modem driver"
|
||||||
|
|
||||||
static const char cxacru_driver_name[] = "cxacru";
|
static const char cxacru_driver_name[] = "cxacru";
|
||||||
@ -1380,4 +1379,3 @@ module_usb_driver(cxacru_usb_driver);
|
|||||||
MODULE_AUTHOR(DRIVER_AUTHOR);
|
MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_VERSION(DRIVER_VERSION);
|
|
||||||
|
@ -40,8 +40,7 @@
|
|||||||
#include "usbatm.h"
|
#include "usbatm.h"
|
||||||
|
|
||||||
#define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands@free.fr>"
|
#define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands@free.fr>"
|
||||||
#define DRIVER_VERSION "1.10"
|
#define DRIVER_DESC "Alcatel SpeedTouch USB driver"
|
||||||
#define DRIVER_DESC "Alcatel SpeedTouch USB driver version " DRIVER_VERSION
|
|
||||||
|
|
||||||
static const char speedtch_driver_name[] = "speedtch";
|
static const char speedtch_driver_name[] = "speedtch";
|
||||||
|
|
||||||
@ -738,7 +737,7 @@ static int speedtch_post_reset(struct usb_interface *intf)
|
|||||||
** USB **
|
** USB **
|
||||||
**********/
|
**********/
|
||||||
|
|
||||||
static struct usb_device_id speedtch_usb_ids[] = {
|
static const struct usb_device_id speedtch_usb_ids[] = {
|
||||||
{USB_DEVICE(0x06b9, 0x4061)},
|
{USB_DEVICE(0x06b9, 0x4061)},
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
@ -962,4 +961,3 @@ module_usb_driver(speedtch_usb_driver);
|
|||||||
MODULE_AUTHOR(DRIVER_AUTHOR);
|
MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_VERSION(DRIVER_VERSION);
|
|
||||||
|
@ -2212,7 +2212,7 @@ static int uea_boot(struct uea_softc *sc)
|
|||||||
ret = usb_submit_urb(sc->urb_int, GFP_KERNEL);
|
ret = usb_submit_urb(sc->urb_int, GFP_KERNEL);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
uea_err(INS_TO_USBDEV(sc),
|
uea_err(INS_TO_USBDEV(sc),
|
||||||
"urb submition failed with error %d\n", ret);
|
"urb submission failed with error %d\n", ret);
|
||||||
goto err1;
|
goto err1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2522,7 +2522,7 @@ static struct attribute *attrs[] = {
|
|||||||
&dev_attr_stat_firmid.attr,
|
&dev_attr_stat_firmid.attr,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
static struct attribute_group attr_grp = {
|
static const struct attribute_group attr_grp = {
|
||||||
.attrs = attrs,
|
.attrs = attrs,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -93,8 +93,7 @@ static int usbatm_print_packet(struct usbatm_data *instance, const unsigned char
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands@free.fr>"
|
#define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands@free.fr>"
|
||||||
#define DRIVER_VERSION "1.10"
|
#define DRIVER_DESC "Generic USB ATM/DSL I/O"
|
||||||
#define DRIVER_DESC "Generic USB ATM/DSL I/O, version " DRIVER_VERSION
|
|
||||||
|
|
||||||
static const char usbatm_driver_name[] = "usbatm";
|
static const char usbatm_driver_name[] = "usbatm";
|
||||||
|
|
||||||
@ -174,7 +173,7 @@ static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd, void __us
|
|||||||
static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb);
|
static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb);
|
||||||
static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t *pos, char *page);
|
static int usbatm_atm_proc_read(struct atm_dev *atm_dev, loff_t *pos, char *page);
|
||||||
|
|
||||||
static struct atmdev_ops usbatm_atm_devops = {
|
static const struct atmdev_ops usbatm_atm_devops = {
|
||||||
.dev_close = usbatm_atm_dev_close,
|
.dev_close = usbatm_atm_dev_close,
|
||||||
.open = usbatm_atm_open,
|
.open = usbatm_atm_open,
|
||||||
.close = usbatm_atm_close,
|
.close = usbatm_atm_close,
|
||||||
@ -1315,7 +1314,6 @@ module_exit(usbatm_usb_exit);
|
|||||||
MODULE_AUTHOR(DRIVER_AUTHOR);
|
MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_VERSION(DRIVER_VERSION);
|
|
||||||
|
|
||||||
/************
|
/************
|
||||||
** debug **
|
** debug **
|
||||||
|
@ -228,4 +228,3 @@ module_exit(xusbatm_exit);
|
|||||||
MODULE_AUTHOR("Roman Kagan, Duncan Sands");
|
MODULE_AUTHOR("Roman Kagan, Duncan Sands");
|
||||||
MODULE_DESCRIPTION("Driver for USB ADSL modems initialized in userspace");
|
MODULE_DESCRIPTION("Driver for USB ADSL modems initialized in userspace");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_VERSION("0.1");
|
|
||||||
|
@ -305,7 +305,7 @@ static int c67x00_hcd_get_frame(struct usb_hcd *hcd)
|
|||||||
return temp_val ? (temp_val - 1) : HOST_FRAME_MASK;
|
return temp_val ? (temp_val - 1) : HOST_FRAME_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct hc_driver c67x00_hc_driver = {
|
static const struct hc_driver c67x00_hc_driver = {
|
||||||
.description = "c67x00-hcd",
|
.description = "c67x00-hcd",
|
||||||
.product_desc = "Cypress C67X00 Host Controller",
|
.product_desc = "Cypress C67X00 Host Controller",
|
||||||
.hcd_priv_size = sizeof(struct c67x00_hcd),
|
.hcd_priv_size = sizeof(struct c67x00_hcd),
|
||||||
|
@ -15,3 +15,4 @@ obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc_zevio.o
|
|||||||
obj-$(CONFIG_USB_CHIPIDEA_PCI) += ci_hdrc_pci.o
|
obj-$(CONFIG_USB_CHIPIDEA_PCI) += ci_hdrc_pci.o
|
||||||
|
|
||||||
obj-$(CONFIG_USB_CHIPIDEA_OF) += usbmisc_imx.o ci_hdrc_imx.o
|
obj-$(CONFIG_USB_CHIPIDEA_OF) += usbmisc_imx.o ci_hdrc_imx.o
|
||||||
|
obj-$(CONFIG_USB_CHIPIDEA_OF) += ci_hdrc_tegra.o
|
||||||
|
@ -251,7 +251,7 @@ static int ci_hdrc_msm_probe(struct platform_device *pdev)
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto err_mux;
|
goto err_mux;
|
||||||
|
|
||||||
ulpi_node = of_find_node_by_name(pdev->dev.of_node, "ulpi");
|
ulpi_node = of_find_node_by_name(of_node_get(pdev->dev.of_node), "ulpi");
|
||||||
if (ulpi_node) {
|
if (ulpi_node) {
|
||||||
phy_node = of_get_next_available_child(ulpi_node, NULL);
|
phy_node = of_get_next_available_child(ulpi_node, NULL);
|
||||||
ci->hsic = of_device_is_compatible(phy_node, "qcom,usb-hsic-phy");
|
ci->hsic = of_device_is_compatible(phy_node, "qcom,usb-hsic-phy");
|
||||||
|
@ -170,5 +170,4 @@ module_pci_driver(ci_hdrc_pci_driver);
|
|||||||
MODULE_AUTHOR("MIPS - David Lopo <dlopo@chipidea.mips.com>");
|
MODULE_AUTHOR("MIPS - David Lopo <dlopo@chipidea.mips.com>");
|
||||||
MODULE_DESCRIPTION("MIPS CI13XXX USB Peripheral Controller");
|
MODULE_DESCRIPTION("MIPS CI13XXX USB Peripheral Controller");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_VERSION("June 2008");
|
|
||||||
MODULE_ALIAS("platform:ci13xxx_pci");
|
MODULE_ALIAS("platform:ci13xxx_pci");
|
||||||
|
155
drivers/usb/chipidea/ci_hdrc_tegra.c
Normal file
155
drivers/usb/chipidea/ci_hdrc_tegra.c
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, NVIDIA Corporation
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
|
#include <linux/reset.h>
|
||||||
|
|
||||||
|
#include <linux/usb/chipidea.h>
|
||||||
|
|
||||||
|
#include "ci.h"
|
||||||
|
|
||||||
|
struct tegra_udc {
|
||||||
|
struct ci_hdrc_platform_data data;
|
||||||
|
struct platform_device *dev;
|
||||||
|
|
||||||
|
struct usb_phy *phy;
|
||||||
|
struct clk *clk;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tegra_udc_soc_info {
|
||||||
|
unsigned long flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct tegra_udc_soc_info tegra20_udc_soc_info = {
|
||||||
|
.flags = CI_HDRC_REQUIRES_ALIGNED_DMA,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct tegra_udc_soc_info tegra30_udc_soc_info = {
|
||||||
|
.flags = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct tegra_udc_soc_info tegra114_udc_soc_info = {
|
||||||
|
.flags = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct tegra_udc_soc_info tegra124_udc_soc_info = {
|
||||||
|
.flags = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct of_device_id tegra_udc_of_match[] = {
|
||||||
|
{
|
||||||
|
.compatible = "nvidia,tegra20-udc",
|
||||||
|
.data = &tegra20_udc_soc_info,
|
||||||
|
}, {
|
||||||
|
.compatible = "nvidia,tegra30-udc",
|
||||||
|
.data = &tegra30_udc_soc_info,
|
||||||
|
}, {
|
||||||
|
.compatible = "nvidia,tegra114-udc",
|
||||||
|
.data = &tegra114_udc_soc_info,
|
||||||
|
}, {
|
||||||
|
.compatible = "nvidia,tegra124-udc",
|
||||||
|
.data = &tegra124_udc_soc_info,
|
||||||
|
}, {
|
||||||
|
/* sentinel */
|
||||||
|
}
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, tegra_udc_of_match);
|
||||||
|
|
||||||
|
static int tegra_udc_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
const struct tegra_udc_soc_info *soc;
|
||||||
|
struct tegra_udc *udc;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
udc = devm_kzalloc(&pdev->dev, sizeof(*udc), GFP_KERNEL);
|
||||||
|
if (!udc)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
soc = of_device_get_match_data(&pdev->dev);
|
||||||
|
if (!soc) {
|
||||||
|
dev_err(&pdev->dev, "failed to match OF data\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
udc->phy = devm_usb_get_phy_by_phandle(&pdev->dev, "nvidia,phy", 0);
|
||||||
|
if (IS_ERR(udc->phy)) {
|
||||||
|
err = PTR_ERR(udc->phy);
|
||||||
|
dev_err(&pdev->dev, "failed to get PHY: %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
udc->clk = devm_clk_get(&pdev->dev, NULL);
|
||||||
|
if (IS_ERR(udc->clk)) {
|
||||||
|
err = PTR_ERR(udc->clk);
|
||||||
|
dev_err(&pdev->dev, "failed to get clock: %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = clk_prepare_enable(udc->clk);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(&pdev->dev, "failed to enable clock: %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tegra's USB PHY driver doesn't implement optional phy_init()
|
||||||
|
* hook, so we have to power on UDC controller before ChipIdea
|
||||||
|
* driver initialization kicks in.
|
||||||
|
*/
|
||||||
|
usb_phy_set_suspend(udc->phy, 0);
|
||||||
|
|
||||||
|
/* setup and register ChipIdea HDRC device */
|
||||||
|
udc->data.name = "tegra-udc";
|
||||||
|
udc->data.flags = soc->flags;
|
||||||
|
udc->data.usb_phy = udc->phy;
|
||||||
|
udc->data.capoffset = DEF_CAPOFFSET;
|
||||||
|
|
||||||
|
udc->dev = ci_hdrc_add_device(&pdev->dev, pdev->resource,
|
||||||
|
pdev->num_resources, &udc->data);
|
||||||
|
if (IS_ERR(udc->dev)) {
|
||||||
|
err = PTR_ERR(udc->dev);
|
||||||
|
dev_err(&pdev->dev, "failed to add HDRC device: %d\n", err);
|
||||||
|
goto fail_power_off;
|
||||||
|
}
|
||||||
|
|
||||||
|
platform_set_drvdata(pdev, udc);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail_power_off:
|
||||||
|
usb_phy_set_suspend(udc->phy, 1);
|
||||||
|
clk_disable_unprepare(udc->clk);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra_udc_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct tegra_udc *udc = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
|
usb_phy_set_suspend(udc->phy, 1);
|
||||||
|
clk_disable_unprepare(udc->clk);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct platform_driver tegra_udc_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "tegra-udc",
|
||||||
|
.of_match_table = tegra_udc_of_match,
|
||||||
|
},
|
||||||
|
.probe = tegra_udc_probe,
|
||||||
|
.remove = tegra_udc_remove,
|
||||||
|
};
|
||||||
|
module_platform_driver(tegra_udc_driver);
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("NVIDIA Tegra USB device mode driver");
|
||||||
|
MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
|
||||||
|
MODULE_ALIAS("platform:tegra-udc");
|
||||||
|
MODULE_LICENSE("GPL v2");
|
@ -52,6 +52,8 @@ static int ci_hdrc_usb2_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
if (!ci_pdata) {
|
if (!ci_pdata) {
|
||||||
ci_pdata = devm_kmalloc(dev, sizeof(*ci_pdata), GFP_KERNEL);
|
ci_pdata = devm_kmalloc(dev, sizeof(*ci_pdata), GFP_KERNEL);
|
||||||
|
if (!ci_pdata)
|
||||||
|
return -ENOMEM;
|
||||||
*ci_pdata = ci_default_pdata; /* struct copy */
|
*ci_pdata = ci_default_pdata; /* struct copy */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -736,7 +736,7 @@ static int ci_extcon_register(struct ci_hdrc *ci)
|
|||||||
|
|
||||||
id = &ci->platdata->id_extcon;
|
id = &ci->platdata->id_extcon;
|
||||||
id->ci = ci;
|
id->ci = ci;
|
||||||
if (!IS_ERR(id->edev)) {
|
if (!IS_ERR_OR_NULL(id->edev)) {
|
||||||
ret = devm_extcon_register_notifier(ci->dev, id->edev,
|
ret = devm_extcon_register_notifier(ci->dev, id->edev,
|
||||||
EXTCON_USB_HOST, &id->nb);
|
EXTCON_USB_HOST, &id->nb);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@ -747,7 +747,7 @@ static int ci_extcon_register(struct ci_hdrc *ci)
|
|||||||
|
|
||||||
vbus = &ci->platdata->vbus_extcon;
|
vbus = &ci->platdata->vbus_extcon;
|
||||||
vbus->ci = ci;
|
vbus->ci = ci;
|
||||||
if (!IS_ERR(vbus->edev)) {
|
if (!IS_ERR_OR_NULL(vbus->edev)) {
|
||||||
ret = devm_extcon_register_notifier(ci->dev, vbus->edev,
|
ret = devm_extcon_register_notifier(ci->dev, vbus->edev,
|
||||||
EXTCON_USB, &vbus->nb);
|
EXTCON_USB, &vbus->nb);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@ -887,7 +887,7 @@ static struct attribute *ci_attrs[] = {
|
|||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attribute_group ci_attr_group = {
|
static const struct attribute_group ci_attr_group = {
|
||||||
.attrs = ci_attrs,
|
.attrs = ci_attrs,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -193,7 +193,7 @@ static struct attribute *inputs_attrs[] = {
|
|||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attribute_group inputs_attr_group = {
|
static const struct attribute_group inputs_attr_group = {
|
||||||
.name = "inputs",
|
.name = "inputs",
|
||||||
.attrs = inputs_attrs,
|
.attrs = inputs_attrs,
|
||||||
};
|
};
|
||||||
|
@ -944,7 +944,6 @@ isr_setup_status_complete(struct usb_ep *ep, struct usb_request *req)
|
|||||||
*/
|
*/
|
||||||
static int isr_setup_status_phase(struct ci_hdrc *ci)
|
static int isr_setup_status_phase(struct ci_hdrc *ci)
|
||||||
{
|
{
|
||||||
int retval;
|
|
||||||
struct ci_hw_ep *hwep;
|
struct ci_hw_ep *hwep;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -960,9 +959,7 @@ static int isr_setup_status_phase(struct ci_hdrc *ci)
|
|||||||
ci->status->context = ci;
|
ci->status->context = ci;
|
||||||
ci->status->complete = isr_setup_status_complete;
|
ci->status->complete = isr_setup_status_complete;
|
||||||
|
|
||||||
retval = _ep_queue(&hwep->ep, ci->status, GFP_ATOMIC);
|
return _ep_queue(&hwep->ep, ci->status, GFP_ATOMIC);
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1899,6 +1896,9 @@ static int udc_start(struct ci_hdrc *ci)
|
|||||||
ci->gadget.name = ci->platdata->name;
|
ci->gadget.name = ci->platdata->name;
|
||||||
ci->gadget.otg_caps = otg_caps;
|
ci->gadget.otg_caps = otg_caps;
|
||||||
|
|
||||||
|
if (ci->platdata->flags & CI_HDRC_REQUIRES_ALIGNED_DMA)
|
||||||
|
ci->gadget.quirk_avoids_skb_reserve = 1;
|
||||||
|
|
||||||
if (ci->is_otg && (otg_caps->hnp_support || otg_caps->srp_support ||
|
if (ci->is_otg && (otg_caps->hnp_support || otg_caps->srp_support ||
|
||||||
otg_caps->adp_support))
|
otg_caps->adp_support))
|
||||||
ci->gadget.is_otg = 1;
|
ci->gadget.is_otg = 1;
|
||||||
|
@ -26,10 +26,6 @@
|
|||||||
#include <asm/unaligned.h>
|
#include <asm/unaligned.h>
|
||||||
#include <linux/usb/cdc-wdm.h>
|
#include <linux/usb/cdc-wdm.h>
|
||||||
|
|
||||||
/*
|
|
||||||
* Version Information
|
|
||||||
*/
|
|
||||||
#define DRIVER_VERSION "v0.03"
|
|
||||||
#define DRIVER_AUTHOR "Oliver Neukum"
|
#define DRIVER_AUTHOR "Oliver Neukum"
|
||||||
#define DRIVER_DESC "USB Abstract Control Model driver for USB WCM Device Management"
|
#define DRIVER_DESC "USB Abstract Control Model driver for USB WCM Device Management"
|
||||||
|
|
||||||
|
@ -1085,7 +1085,7 @@ static struct attribute *capability_attrs[] = {
|
|||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attribute_group capability_attr_grp = {
|
static const struct attribute_group capability_attr_grp = {
|
||||||
.attrs = capability_attrs,
|
.attrs = capability_attrs,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1151,7 +1151,7 @@ static struct attribute *data_attrs[] = {
|
|||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attribute_group data_attr_grp = {
|
static const struct attribute_group data_attr_grp = {
|
||||||
.attrs = data_attrs,
|
.attrs = data_attrs,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -190,10 +190,7 @@ EXPORT_SYMBOL_GPL(of_usb_get_dr_mode_by_phy);
|
|||||||
*/
|
*/
|
||||||
bool of_usb_host_tpl_support(struct device_node *np)
|
bool of_usb_host_tpl_support(struct device_node *np)
|
||||||
{
|
{
|
||||||
if (of_find_property(np, "tpl-support", NULL))
|
return of_property_read_bool(np, "tpl-support");
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(of_usb_host_tpl_support);
|
EXPORT_SYMBOL_GPL(of_usb_host_tpl_support);
|
||||||
|
|
||||||
@ -227,8 +224,8 @@ int of_usb_update_otg_caps(struct device_node *np,
|
|||||||
otg_caps->otg_rev = otg_rev;
|
otg_caps->otg_rev = otg_rev;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
pr_err("%s: unsupported otg-rev: 0x%x\n",
|
pr_err("%pOF: unsupported otg-rev: 0x%x\n",
|
||||||
np->full_name, otg_rev);
|
np, otg_rev);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -240,11 +237,11 @@ int of_usb_update_otg_caps(struct device_node *np,
|
|||||||
otg_caps->otg_rev = 0;
|
otg_caps->otg_rev = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (of_find_property(np, "hnp-disable", NULL))
|
if (of_property_read_bool(np, "hnp-disable"))
|
||||||
otg_caps->hnp_support = false;
|
otg_caps->hnp_support = false;
|
||||||
if (of_find_property(np, "srp-disable", NULL))
|
if (of_property_read_bool(np, "srp-disable"))
|
||||||
otg_caps->srp_support = false;
|
otg_caps->srp_support = false;
|
||||||
if (of_find_property(np, "adp-disable", NULL) ||
|
if (of_property_read_bool(np, "adp-disable") ||
|
||||||
(otg_caps->otg_rev < 0x0200))
|
(otg_caps->otg_rev < 0x0200))
|
||||||
otg_caps->adp_support = false;
|
otg_caps->adp_support = false;
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ static void ulpi_dev_release(struct device *dev)
|
|||||||
kfree(to_ulpi_dev(dev));
|
kfree(to_ulpi_dev(dev));
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct device_type ulpi_dev_type = {
|
static const struct device_type ulpi_dev_type = {
|
||||||
.name = "ulpi_device",
|
.name = "ulpi_device",
|
||||||
.groups = ulpi_dev_attr_groups,
|
.groups = ulpi_dev_attr_groups,
|
||||||
.release = ulpi_dev_release,
|
.release = ulpi_dev_release,
|
||||||
|
@ -210,7 +210,7 @@ static void usbdev_vm_close(struct vm_area_struct *vma)
|
|||||||
dec_usb_memory_use_count(usbm, &usbm->vma_use_count);
|
dec_usb_memory_use_count(usbm, &usbm->vma_use_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct vm_operations_struct usbdev_vm_ops = {
|
static const struct vm_operations_struct usbdev_vm_ops = {
|
||||||
.open = usbdev_vm_open,
|
.open = usbdev_vm_open,
|
||||||
.close = usbdev_vm_close
|
.close = usbdev_vm_close
|
||||||
};
|
};
|
||||||
@ -623,6 +623,8 @@ static void async_completed(struct urb *urb)
|
|||||||
if (as->status < 0 && as->bulk_addr && as->status != -ECONNRESET &&
|
if (as->status < 0 && as->bulk_addr && as->status != -ECONNRESET &&
|
||||||
as->status != -ENOENT)
|
as->status != -ENOENT)
|
||||||
cancel_bulk_urbs(ps, as->bulk_addr);
|
cancel_bulk_urbs(ps, as->bulk_addr);
|
||||||
|
|
||||||
|
wake_up(&ps->wait);
|
||||||
spin_unlock(&ps->lock);
|
spin_unlock(&ps->lock);
|
||||||
|
|
||||||
if (signr) {
|
if (signr) {
|
||||||
@ -630,8 +632,6 @@ static void async_completed(struct urb *urb)
|
|||||||
put_pid(pid);
|
put_pid(pid);
|
||||||
put_cred(cred);
|
put_cred(cred);
|
||||||
}
|
}
|
||||||
|
|
||||||
wake_up(&ps->wait);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void destroy_async(struct usb_dev_state *ps, struct list_head *list)
|
static void destroy_async(struct usb_dev_state *ps, struct list_head *list)
|
||||||
|
@ -972,7 +972,7 @@ static struct attribute *usb_bus_attrs[] = {
|
|||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct attribute_group usb_bus_attr_group = {
|
static const struct attribute_group usb_bus_attr_group = {
|
||||||
.name = NULL, /* we want them in the same directory */
|
.name = NULL, /* we want them in the same directory */
|
||||||
.attrs = usb_bus_attrs,
|
.attrs = usb_bus_attrs,
|
||||||
};
|
};
|
||||||
|
@ -2614,7 +2614,7 @@ static unsigned hub_is_wusb(struct usb_hub *hub)
|
|||||||
#define SET_CONFIG_TRIES (2 * (use_both_schemes + 1))
|
#define SET_CONFIG_TRIES (2 * (use_both_schemes + 1))
|
||||||
#define USE_NEW_SCHEME(i) ((i) / 2 == (int)old_scheme_first)
|
#define USE_NEW_SCHEME(i) ((i) / 2 == (int)old_scheme_first)
|
||||||
|
|
||||||
#define HUB_ROOT_RESET_TIME 50 /* times are in msec */
|
#define HUB_ROOT_RESET_TIME 60 /* times are in msec */
|
||||||
#define HUB_SHORT_RESET_TIME 10
|
#define HUB_SHORT_RESET_TIME 10
|
||||||
#define HUB_BH_RESET_TIME 50
|
#define HUB_BH_RESET_TIME 50
|
||||||
#define HUB_LONG_RESET_TIME 200
|
#define HUB_LONG_RESET_TIME 200
|
||||||
@ -4342,6 +4342,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
|
|||||||
enum usb_device_speed oldspeed = udev->speed;
|
enum usb_device_speed oldspeed = udev->speed;
|
||||||
const char *speed;
|
const char *speed;
|
||||||
int devnum = udev->devnum;
|
int devnum = udev->devnum;
|
||||||
|
const char *driver_name;
|
||||||
|
|
||||||
/* root hub ports have a slightly longer reset period
|
/* root hub ports have a slightly longer reset period
|
||||||
* (from USB 2.0 spec, section 7.1.7.5)
|
* (from USB 2.0 spec, section 7.1.7.5)
|
||||||
@ -4409,11 +4410,23 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
|
|||||||
else
|
else
|
||||||
speed = usb_speed_string(udev->speed);
|
speed = usb_speed_string(udev->speed);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The controller driver may be NULL if the controller device
|
||||||
|
* is the middle device between platform device and roothub.
|
||||||
|
* This middle device may not need a device driver due to
|
||||||
|
* all hardware control can be at platform device driver, this
|
||||||
|
* platform device is usually a dual-role USB controller device.
|
||||||
|
*/
|
||||||
|
if (udev->bus->controller->driver)
|
||||||
|
driver_name = udev->bus->controller->driver->name;
|
||||||
|
else
|
||||||
|
driver_name = udev->bus->sysdev->driver->name;
|
||||||
|
|
||||||
if (udev->speed < USB_SPEED_SUPER)
|
if (udev->speed < USB_SPEED_SUPER)
|
||||||
dev_info(&udev->dev,
|
dev_info(&udev->dev,
|
||||||
"%s %s USB device number %d using %s\n",
|
"%s %s USB device number %d using %s\n",
|
||||||
(udev->config) ? "reset" : "new", speed,
|
(udev->config) ? "reset" : "new", speed,
|
||||||
devnum, udev->bus->controller->driver->name);
|
devnum, driver_name);
|
||||||
|
|
||||||
/* Set up TT records, if needed */
|
/* Set up TT records, if needed */
|
||||||
if (hdev->tt) {
|
if (hdev->tt) {
|
||||||
@ -4545,7 +4558,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
|
|||||||
"%s SuperSpeed%s USB device number %d using %s\n",
|
"%s SuperSpeed%s USB device number %d using %s\n",
|
||||||
(udev->config) ? "reset" : "new",
|
(udev->config) ? "reset" : "new",
|
||||||
(udev->speed == USB_SPEED_SUPER_PLUS) ? "Plus" : "",
|
(udev->speed == USB_SPEED_SUPER_PLUS) ? "Plus" : "",
|
||||||
devnum, udev->bus->controller->driver->name);
|
devnum, driver_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cope with hardware quirkiness:
|
/* cope with hardware quirkiness:
|
||||||
|
@ -149,8 +149,8 @@ static bool usbport_trig_port_observed(struct usbport_trig_data *usbport_data,
|
|||||||
count = of_count_phandle_with_args(led_np, "trigger-sources",
|
count = of_count_phandle_with_args(led_np, "trigger-sources",
|
||||||
"#trigger-source-cells");
|
"#trigger-source-cells");
|
||||||
if (count < 0) {
|
if (count < 0) {
|
||||||
dev_warn(dev, "Failed to get trigger sources for %s\n",
|
dev_warn(dev, "Failed to get trigger sources for %pOF\n",
|
||||||
led_np->full_name);
|
led_np);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,6 +205,7 @@ static int usbport_trig_add_port(struct usbport_trig_data *usbport_data,
|
|||||||
}
|
}
|
||||||
snprintf(port->port_name, len, "%s-port%d", hub_name, portnum);
|
snprintf(port->port_name, len, "%s-port%d", hub_name, portnum);
|
||||||
|
|
||||||
|
sysfs_attr_init(&port->attr.attr);
|
||||||
port->attr.attr.name = port->port_name;
|
port->attr.attr.name = port->port_name;
|
||||||
port->attr.attr.mode = S_IRUSR | S_IWUSR;
|
port->attr.attr.mode = S_IRUSR | S_IWUSR;
|
||||||
port->attr.show = usbport_trig_port_show;
|
port->attr.show = usbport_trig_port_show;
|
||||||
|
@ -57,8 +57,9 @@ static const struct usb_device_id usb_quirk_list[] = {
|
|||||||
/* Microsoft LifeCam-VX700 v2.0 */
|
/* Microsoft LifeCam-VX700 v2.0 */
|
||||||
{ USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME },
|
{ USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME },
|
||||||
|
|
||||||
/* Logitech HD Pro Webcams C920 and C930e */
|
/* Logitech HD Pro Webcams C920, C920-C and C930e */
|
||||||
{ USB_DEVICE(0x046d, 0x082d), .driver_info = USB_QUIRK_DELAY_INIT },
|
{ USB_DEVICE(0x046d, 0x082d), .driver_info = USB_QUIRK_DELAY_INIT },
|
||||||
|
{ USB_DEVICE(0x046d, 0x0841), .driver_info = USB_QUIRK_DELAY_INIT },
|
||||||
{ USB_DEVICE(0x046d, 0x0843), .driver_info = USB_QUIRK_DELAY_INIT },
|
{ USB_DEVICE(0x046d, 0x0843), .driver_info = USB_QUIRK_DELAY_INIT },
|
||||||
|
|
||||||
/* Logitech ConferenceCam CC3000e */
|
/* Logitech ConferenceCam CC3000e */
|
||||||
@ -217,6 +218,9 @@ static const struct usb_device_id usb_quirk_list[] = {
|
|||||||
{ USB_DEVICE(0x1a0a, 0x0200), .driver_info =
|
{ USB_DEVICE(0x1a0a, 0x0200), .driver_info =
|
||||||
USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL },
|
USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL },
|
||||||
|
|
||||||
|
/* Corsair Strafe RGB */
|
||||||
|
{ USB_DEVICE(0x1b1c, 0x1b20), .driver_info = USB_QUIRK_DELAY_INIT },
|
||||||
|
|
||||||
/* Acer C120 LED Projector */
|
/* Acer C120 LED Projector */
|
||||||
{ USB_DEVICE(0x1de1, 0xc102), .driver_info = USB_QUIRK_NO_LPM },
|
{ USB_DEVICE(0x1de1, 0xc102), .driver_info = USB_QUIRK_NO_LPM },
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ static ssize_t devspec_show(struct device *dev, struct device_attribute *attr,
|
|||||||
{
|
{
|
||||||
struct device_node *of_node = dev->of_node;
|
struct device_node *of_node = dev->of_node;
|
||||||
|
|
||||||
return sprintf(buf, "%s\n", of_node_full_name(of_node));
|
return sprintf(buf, "%pOF\n", of_node);
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR_RO(devspec);
|
static DEVICE_ATTR_RO(devspec);
|
||||||
#endif
|
#endif
|
||||||
|
@ -4179,7 +4179,7 @@ static int dwc2_hsotg_ep_sethalt_lock(struct usb_ep *ep, int value)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct usb_ep_ops dwc2_hsotg_ep_ops = {
|
static const struct usb_ep_ops dwc2_hsotg_ep_ops = {
|
||||||
.enable = dwc2_hsotg_ep_enable,
|
.enable = dwc2_hsotg_ep_enable,
|
||||||
.disable = dwc2_hsotg_ep_disable,
|
.disable = dwc2_hsotg_ep_disable,
|
||||||
.alloc_request = dwc2_hsotg_ep_alloc_request,
|
.alloc_request = dwc2_hsotg_ep_alloc_request,
|
||||||
|
@ -4388,6 +4388,9 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
|
|||||||
|
|
||||||
spin_lock_irqsave(&hsotg->lock, flags);
|
spin_lock_irqsave(&hsotg->lock, flags);
|
||||||
|
|
||||||
|
if (dwc2_is_device_mode(hsotg))
|
||||||
|
goto unlock;
|
||||||
|
|
||||||
if (hsotg->lx_state != DWC2_L0)
|
if (hsotg->lx_state != DWC2_L0)
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
|
||||||
@ -4446,6 +4449,9 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
|
|||||||
|
|
||||||
spin_lock_irqsave(&hsotg->lock, flags);
|
spin_lock_irqsave(&hsotg->lock, flags);
|
||||||
|
|
||||||
|
if (dwc2_is_device_mode(hsotg))
|
||||||
|
goto unlock;
|
||||||
|
|
||||||
if (hsotg->lx_state != DWC2_L2)
|
if (hsotg->lx_state != DWC2_L2)
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/clk.h>
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
@ -23,6 +22,7 @@
|
|||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
|
#include <linux/pm_runtime.h>
|
||||||
|
|
||||||
/* USBSS register offsets */
|
/* USBSS register offsets */
|
||||||
#define USBSS_REVISION 0x0000
|
#define USBSS_REVISION 0x0000
|
||||||
@ -41,7 +41,6 @@
|
|||||||
|
|
||||||
struct dwc3_keystone {
|
struct dwc3_keystone {
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct clk *clk;
|
|
||||||
void __iomem *usbss;
|
void __iomem *usbss;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -106,17 +105,13 @@ static int kdwc3_probe(struct platform_device *pdev)
|
|||||||
if (IS_ERR(kdwc->usbss))
|
if (IS_ERR(kdwc->usbss))
|
||||||
return PTR_ERR(kdwc->usbss);
|
return PTR_ERR(kdwc->usbss);
|
||||||
|
|
||||||
kdwc->clk = devm_clk_get(kdwc->dev, "usb");
|
pm_runtime_enable(kdwc->dev);
|
||||||
if (IS_ERR(kdwc->clk)) {
|
|
||||||
dev_err(kdwc->dev, "unable to get usb clock\n");
|
|
||||||
return PTR_ERR(kdwc->clk);
|
|
||||||
}
|
|
||||||
|
|
||||||
error = clk_prepare_enable(kdwc->clk);
|
error = pm_runtime_get_sync(kdwc->dev);
|
||||||
if (error < 0) {
|
if (error < 0) {
|
||||||
dev_err(kdwc->dev, "unable to enable usb clock, error %d\n",
|
dev_err(kdwc->dev, "pm_runtime_get_sync failed, error %d\n",
|
||||||
error);
|
error);
|
||||||
return error;
|
goto err_irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
irq = platform_get_irq(pdev, 0);
|
irq = platform_get_irq(pdev, 0);
|
||||||
@ -147,7 +142,8 @@ static int kdwc3_probe(struct platform_device *pdev)
|
|||||||
err_core:
|
err_core:
|
||||||
kdwc3_disable_irqs(kdwc);
|
kdwc3_disable_irqs(kdwc);
|
||||||
err_irq:
|
err_irq:
|
||||||
clk_disable_unprepare(kdwc->clk);
|
pm_runtime_put_sync(kdwc->dev);
|
||||||
|
pm_runtime_disable(kdwc->dev);
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@ -167,7 +163,9 @@ static int kdwc3_remove(struct platform_device *pdev)
|
|||||||
|
|
||||||
kdwc3_disable_irqs(kdwc);
|
kdwc3_disable_irqs(kdwc);
|
||||||
device_for_each_child(&pdev->dev, NULL, kdwc3_remove_core);
|
device_for_each_child(&pdev->dev, NULL, kdwc3_remove_core);
|
||||||
clk_disable_unprepare(kdwc->clk);
|
pm_runtime_put_sync(kdwc->dev);
|
||||||
|
pm_runtime_disable(kdwc->dev);
|
||||||
|
|
||||||
platform_set_drvdata(pdev, NULL);
|
platform_set_drvdata(pdev, NULL);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
#include <linux/clk-provider.h>
|
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
@ -96,7 +95,8 @@ static int dwc3_of_simple_probe(struct platform_device *pdev)
|
|||||||
platform_set_drvdata(pdev, simple);
|
platform_set_drvdata(pdev, simple);
|
||||||
simple->dev = dev;
|
simple->dev = dev;
|
||||||
|
|
||||||
ret = dwc3_of_simple_clk_init(simple, of_clk_get_parent_count(np));
|
ret = dwc3_of_simple_clk_init(simple, of_count_phandle_with_args(np,
|
||||||
|
"clocks", "#clock-cells"));
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -478,8 +478,8 @@ static int dwc3_omap_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
irq = platform_get_irq(pdev, 0);
|
irq = platform_get_irq(pdev, 0);
|
||||||
if (irq < 0) {
|
if (irq < 0) {
|
||||||
dev_err(dev, "missing IRQ resource\n");
|
dev_err(dev, "missing IRQ resource: %d\n", irq);
|
||||||
return -EINVAL;
|
return irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
@ -345,7 +345,7 @@ static int dwc3_pci_resume(struct device *dev)
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_PM_SLEEP */
|
#endif /* CONFIG_PM_SLEEP */
|
||||||
|
|
||||||
static struct dev_pm_ops dwc3_pci_dev_pm_ops = {
|
static const struct dev_pm_ops dwc3_pci_dev_pm_ops = {
|
||||||
SET_SYSTEM_SLEEP_PM_OPS(dwc3_pci_suspend, dwc3_pci_resume)
|
SET_SYSTEM_SLEEP_PM_OPS(dwc3_pci_suspend, dwc3_pci_resume)
|
||||||
SET_RUNTIME_PM_OPS(dwc3_pci_runtime_suspend, dwc3_pci_runtime_resume,
|
SET_RUNTIME_PM_OPS(dwc3_pci_runtime_suspend, dwc3_pci_runtime_resume,
|
||||||
NULL)
|
NULL)
|
||||||
|
@ -130,7 +130,7 @@ config USB_GADGET_STORAGE_NUM_BUFFERS
|
|||||||
|
|
||||||
config U_SERIAL_CONSOLE
|
config U_SERIAL_CONSOLE
|
||||||
bool "Serial gadget console support"
|
bool "Serial gadget console support"
|
||||||
depends on USB_G_SERIAL
|
depends on USB_U_SERIAL
|
||||||
help
|
help
|
||||||
It supports the serial gadget can be used as a console.
|
It supports the serial gadget can be used as a console.
|
||||||
|
|
||||||
|
@ -961,10 +961,9 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
|
|||||||
/* In the meantime, endpoint got disabled or changed. */
|
/* In the meantime, endpoint got disabled or changed. */
|
||||||
ret = -ESHUTDOWN;
|
ret = -ESHUTDOWN;
|
||||||
} else if (halt) {
|
} else if (halt) {
|
||||||
/* Halt */
|
ret = usb_ep_set_halt(ep->ep);
|
||||||
if (likely(epfile->ep == ep) && !WARN_ON(!ep->ep))
|
if (!ret)
|
||||||
usb_ep_set_halt(ep->ep);
|
ret = -EBADMSG;
|
||||||
ret = -EBADMSG;
|
|
||||||
} else if (unlikely(data_len == -EINVAL)) {
|
} else if (unlikely(data_len == -EINVAL)) {
|
||||||
/*
|
/*
|
||||||
* Sanity Check: even though data_len can't be used
|
* Sanity Check: even though data_len can't be used
|
||||||
|
@ -44,6 +44,7 @@ struct f_hidg {
|
|||||||
/* configuration */
|
/* configuration */
|
||||||
unsigned char bInterfaceSubClass;
|
unsigned char bInterfaceSubClass;
|
||||||
unsigned char bInterfaceProtocol;
|
unsigned char bInterfaceProtocol;
|
||||||
|
unsigned char protocol;
|
||||||
unsigned short report_desc_length;
|
unsigned short report_desc_length;
|
||||||
char *report_desc;
|
char *report_desc;
|
||||||
unsigned short report_length;
|
unsigned short report_length;
|
||||||
@ -527,7 +528,9 @@ static int hidg_setup(struct usb_function *f,
|
|||||||
case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
|
case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
|
||||||
| HID_REQ_GET_PROTOCOL):
|
| HID_REQ_GET_PROTOCOL):
|
||||||
VDBG(cdev, "get_protocol\n");
|
VDBG(cdev, "get_protocol\n");
|
||||||
goto stall;
|
length = min_t(unsigned int, length, 1);
|
||||||
|
((u8 *) req->buf)[0] = hidg->protocol;
|
||||||
|
goto respond;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
|
case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
|
||||||
@ -539,6 +542,17 @@ static int hidg_setup(struct usb_function *f,
|
|||||||
case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
|
case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
|
||||||
| HID_REQ_SET_PROTOCOL):
|
| HID_REQ_SET_PROTOCOL):
|
||||||
VDBG(cdev, "set_protocol\n");
|
VDBG(cdev, "set_protocol\n");
|
||||||
|
if (value > HID_REPORT_PROTOCOL)
|
||||||
|
goto stall;
|
||||||
|
length = 0;
|
||||||
|
/*
|
||||||
|
* We assume that programs implementing the Boot protocol
|
||||||
|
* are also compatible with the Report Protocol
|
||||||
|
*/
|
||||||
|
if (hidg->bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT) {
|
||||||
|
hidg->protocol = value;
|
||||||
|
goto respond;
|
||||||
|
}
|
||||||
goto stall;
|
goto stall;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -768,6 +782,7 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f)
|
|||||||
/* set descriptor dynamic values */
|
/* set descriptor dynamic values */
|
||||||
hidg_interface_desc.bInterfaceSubClass = hidg->bInterfaceSubClass;
|
hidg_interface_desc.bInterfaceSubClass = hidg->bInterfaceSubClass;
|
||||||
hidg_interface_desc.bInterfaceProtocol = hidg->bInterfaceProtocol;
|
hidg_interface_desc.bInterfaceProtocol = hidg->bInterfaceProtocol;
|
||||||
|
hidg->protocol = HID_REPORT_PROTOCOL;
|
||||||
hidg_ss_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
|
hidg_ss_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
|
||||||
hidg_ss_in_comp_desc.wBytesPerInterval =
|
hidg_ss_in_comp_desc.wBytesPerInterval =
|
||||||
cpu_to_le16(hidg->report_length);
|
cpu_to_le16(hidg->report_length);
|
||||||
|
@ -98,6 +98,7 @@ struct f_midi {
|
|||||||
DECLARE_KFIFO_PTR(in_req_fifo, struct usb_request *);
|
DECLARE_KFIFO_PTR(in_req_fifo, struct usb_request *);
|
||||||
spinlock_t transmit_lock;
|
spinlock_t transmit_lock;
|
||||||
unsigned int in_last_port;
|
unsigned int in_last_port;
|
||||||
|
unsigned char free_ref;
|
||||||
|
|
||||||
struct gmidi_in_port in_ports_array[/* in_ports */];
|
struct gmidi_in_port in_ports_array[/* in_ports */];
|
||||||
};
|
};
|
||||||
@ -108,6 +109,7 @@ static inline struct f_midi *func_to_midi(struct usb_function *f)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void f_midi_transmit(struct f_midi *midi);
|
static void f_midi_transmit(struct f_midi *midi);
|
||||||
|
static void f_midi_rmidi_free(struct snd_rawmidi *rmidi);
|
||||||
|
|
||||||
DECLARE_UAC_AC_HEADER_DESCRIPTOR(1);
|
DECLARE_UAC_AC_HEADER_DESCRIPTOR(1);
|
||||||
DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1);
|
DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1);
|
||||||
@ -163,6 +165,13 @@ static struct usb_endpoint_descriptor bulk_out_desc = {
|
|||||||
.bmAttributes = USB_ENDPOINT_XFER_BULK,
|
.bmAttributes = USB_ENDPOINT_XFER_BULK,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct usb_ss_ep_comp_descriptor bulk_out_ss_comp_desc = {
|
||||||
|
.bLength = sizeof(bulk_out_ss_comp_desc),
|
||||||
|
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
|
||||||
|
/* .bMaxBurst = 0, */
|
||||||
|
/* .bmAttributes = 0, */
|
||||||
|
};
|
||||||
|
|
||||||
/* B.5.2 Class-specific MS Bulk OUT Endpoint Descriptor */
|
/* B.5.2 Class-specific MS Bulk OUT Endpoint Descriptor */
|
||||||
static struct usb_ms_endpoint_descriptor_16 ms_out_desc = {
|
static struct usb_ms_endpoint_descriptor_16 ms_out_desc = {
|
||||||
/* .bLength = DYNAMIC */
|
/* .bLength = DYNAMIC */
|
||||||
@ -180,6 +189,13 @@ static struct usb_endpoint_descriptor bulk_in_desc = {
|
|||||||
.bmAttributes = USB_ENDPOINT_XFER_BULK,
|
.bmAttributes = USB_ENDPOINT_XFER_BULK,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct usb_ss_ep_comp_descriptor bulk_in_ss_comp_desc = {
|
||||||
|
.bLength = sizeof(bulk_in_ss_comp_desc),
|
||||||
|
.bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
|
||||||
|
/* .bMaxBurst = 0, */
|
||||||
|
/* .bmAttributes = 0, */
|
||||||
|
};
|
||||||
|
|
||||||
/* B.6.2 Class-specific MS Bulk IN Endpoint Descriptor */
|
/* B.6.2 Class-specific MS Bulk IN Endpoint Descriptor */
|
||||||
static struct usb_ms_endpoint_descriptor_16 ms_in_desc = {
|
static struct usb_ms_endpoint_descriptor_16 ms_in_desc = {
|
||||||
/* .bLength = DYNAMIC */
|
/* .bLength = DYNAMIC */
|
||||||
@ -755,13 +771,13 @@ static void f_midi_out_trigger(struct snd_rawmidi_substream *substream, int up)
|
|||||||
clear_bit(substream->number, &midi->out_triggered);
|
clear_bit(substream->number, &midi->out_triggered);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct snd_rawmidi_ops gmidi_in_ops = {
|
static const struct snd_rawmidi_ops gmidi_in_ops = {
|
||||||
.open = f_midi_in_open,
|
.open = f_midi_in_open,
|
||||||
.close = f_midi_in_close,
|
.close = f_midi_in_close,
|
||||||
.trigger = f_midi_in_trigger,
|
.trigger = f_midi_in_trigger,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct snd_rawmidi_ops gmidi_out_ops = {
|
static const struct snd_rawmidi_ops gmidi_out_ops = {
|
||||||
.open = f_midi_out_open,
|
.open = f_midi_out_open,
|
||||||
.close = f_midi_out_close,
|
.close = f_midi_out_close,
|
||||||
.trigger = f_midi_out_trigger
|
.trigger = f_midi_out_trigger
|
||||||
@ -818,6 +834,8 @@ static int f_midi_register_card(struct f_midi *midi)
|
|||||||
SNDRV_RAWMIDI_INFO_INPUT |
|
SNDRV_RAWMIDI_INFO_INPUT |
|
||||||
SNDRV_RAWMIDI_INFO_DUPLEX;
|
SNDRV_RAWMIDI_INFO_DUPLEX;
|
||||||
rmidi->private_data = midi;
|
rmidi->private_data = midi;
|
||||||
|
rmidi->private_free = f_midi_rmidi_free;
|
||||||
|
midi->free_ref++;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Yes, rawmidi OUTPUT = USB IN, and rawmidi INPUT = USB OUT.
|
* Yes, rawmidi OUTPUT = USB IN, and rawmidi INPUT = USB OUT.
|
||||||
@ -853,7 +871,7 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
|
|||||||
struct usb_composite_dev *cdev = c->cdev;
|
struct usb_composite_dev *cdev = c->cdev;
|
||||||
struct f_midi *midi = func_to_midi(f);
|
struct f_midi *midi = func_to_midi(f);
|
||||||
struct usb_string *us;
|
struct usb_string *us;
|
||||||
int status, n, jack = 1, i = 0;
|
int status, n, jack = 1, i = 0, endpoint_descriptor_index = 0;
|
||||||
|
|
||||||
midi->gadget = cdev->gadget;
|
midi->gadget = cdev->gadget;
|
||||||
tasklet_init(&midi->tasklet, f_midi_in_tasklet, (unsigned long) midi);
|
tasklet_init(&midi->tasklet, f_midi_in_tasklet, (unsigned long) midi);
|
||||||
@ -895,7 +913,7 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
|
|||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
/* allocate temporary function list */
|
/* allocate temporary function list */
|
||||||
midi_function = kcalloc((MAX_PORTS * 4) + 9, sizeof(*midi_function),
|
midi_function = kcalloc((MAX_PORTS * 4) + 11, sizeof(*midi_function),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!midi_function) {
|
if (!midi_function) {
|
||||||
status = -ENOMEM;
|
status = -ENOMEM;
|
||||||
@ -985,6 +1003,7 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
|
|||||||
ms_in_desc.bNumEmbMIDIJack = midi->out_ports;
|
ms_in_desc.bNumEmbMIDIJack = midi->out_ports;
|
||||||
|
|
||||||
/* ... and add them to the list */
|
/* ... and add them to the list */
|
||||||
|
endpoint_descriptor_index = i;
|
||||||
midi_function[i++] = (struct usb_descriptor_header *) &bulk_out_desc;
|
midi_function[i++] = (struct usb_descriptor_header *) &bulk_out_desc;
|
||||||
midi_function[i++] = (struct usb_descriptor_header *) &ms_out_desc;
|
midi_function[i++] = (struct usb_descriptor_header *) &ms_out_desc;
|
||||||
midi_function[i++] = (struct usb_descriptor_header *) &bulk_in_desc;
|
midi_function[i++] = (struct usb_descriptor_header *) &bulk_in_desc;
|
||||||
@ -1009,13 +1028,34 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
|
|||||||
goto fail_f_midi;
|
goto fail_f_midi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gadget_is_superspeed(c->cdev->gadget)) {
|
||||||
|
bulk_in_desc.wMaxPacketSize = cpu_to_le16(1024);
|
||||||
|
bulk_out_desc.wMaxPacketSize = cpu_to_le16(1024);
|
||||||
|
i = endpoint_descriptor_index;
|
||||||
|
midi_function[i++] = (struct usb_descriptor_header *)
|
||||||
|
&bulk_out_desc;
|
||||||
|
midi_function[i++] = (struct usb_descriptor_header *)
|
||||||
|
&bulk_out_ss_comp_desc;
|
||||||
|
midi_function[i++] = (struct usb_descriptor_header *)
|
||||||
|
&ms_out_desc;
|
||||||
|
midi_function[i++] = (struct usb_descriptor_header *)
|
||||||
|
&bulk_in_desc;
|
||||||
|
midi_function[i++] = (struct usb_descriptor_header *)
|
||||||
|
&bulk_in_ss_comp_desc;
|
||||||
|
midi_function[i++] = (struct usb_descriptor_header *)
|
||||||
|
&ms_in_desc;
|
||||||
|
f->ss_descriptors = usb_copy_descriptors(midi_function);
|
||||||
|
if (!f->ss_descriptors)
|
||||||
|
goto fail_f_midi;
|
||||||
|
}
|
||||||
|
|
||||||
kfree(midi_function);
|
kfree(midi_function);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail_f_midi:
|
fail_f_midi:
|
||||||
kfree(midi_function);
|
kfree(midi_function);
|
||||||
usb_free_descriptors(f->hs_descriptors);
|
usb_free_all_descriptors(f);
|
||||||
fail:
|
fail:
|
||||||
f_midi_unregister_card(midi);
|
f_midi_unregister_card(midi);
|
||||||
fail_register:
|
fail_register:
|
||||||
@ -1197,14 +1237,21 @@ static void f_midi_free(struct usb_function *f)
|
|||||||
|
|
||||||
midi = func_to_midi(f);
|
midi = func_to_midi(f);
|
||||||
opts = container_of(f->fi, struct f_midi_opts, func_inst);
|
opts = container_of(f->fi, struct f_midi_opts, func_inst);
|
||||||
kfree(midi->id);
|
|
||||||
mutex_lock(&opts->lock);
|
mutex_lock(&opts->lock);
|
||||||
kfifo_free(&midi->in_req_fifo);
|
if (!--midi->free_ref) {
|
||||||
kfree(midi);
|
kfree(midi->id);
|
||||||
--opts->refcnt;
|
kfifo_free(&midi->in_req_fifo);
|
||||||
|
kfree(midi);
|
||||||
|
--opts->refcnt;
|
||||||
|
}
|
||||||
mutex_unlock(&opts->lock);
|
mutex_unlock(&opts->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void f_midi_rmidi_free(struct snd_rawmidi *rmidi)
|
||||||
|
{
|
||||||
|
f_midi_free(rmidi->private_data);
|
||||||
|
}
|
||||||
|
|
||||||
static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f)
|
static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f)
|
||||||
{
|
{
|
||||||
struct usb_composite_dev *cdev = f->config->cdev;
|
struct usb_composite_dev *cdev = f->config->cdev;
|
||||||
@ -1219,7 +1266,7 @@ static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f)
|
|||||||
card = midi->card;
|
card = midi->card;
|
||||||
midi->card = NULL;
|
midi->card = NULL;
|
||||||
if (card)
|
if (card)
|
||||||
snd_card_free(card);
|
snd_card_free_when_closed(card);
|
||||||
|
|
||||||
usb_free_all_descriptors(f);
|
usb_free_all_descriptors(f);
|
||||||
}
|
}
|
||||||
@ -1263,6 +1310,7 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi)
|
|||||||
midi->buflen = opts->buflen;
|
midi->buflen = opts->buflen;
|
||||||
midi->qlen = opts->qlen;
|
midi->qlen = opts->qlen;
|
||||||
midi->in_last_port = 0;
|
midi->in_last_port = 0;
|
||||||
|
midi->free_ref = 1;
|
||||||
|
|
||||||
status = kfifo_alloc(&midi->in_req_fifo, midi->qlen, GFP_KERNEL);
|
status = kfifo_alloc(&midi->in_req_fifo, midi->qlen, GFP_KERNEL);
|
||||||
if (status)
|
if (status)
|
||||||
|
@ -925,8 +925,6 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
|
|||||||
*/
|
*/
|
||||||
ncm->port.is_zlp_ok =
|
ncm->port.is_zlp_ok =
|
||||||
gadget_is_zlp_supported(cdev->gadget);
|
gadget_is_zlp_supported(cdev->gadget);
|
||||||
ncm->port.no_skb_reserve =
|
|
||||||
gadget_avoids_skb_reserve(cdev->gadget);
|
|
||||||
ncm->port.cdc_filter = DEFAULT_FILTER;
|
ncm->port.cdc_filter = DEFAULT_FILTER;
|
||||||
DBG(cdev, "activate ncm\n");
|
DBG(cdev, "activate ncm\n");
|
||||||
net = gether_connect(&ncm->port);
|
net = gether_connect(&ncm->port);
|
||||||
|
@ -691,6 +691,10 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
|
|||||||
f->os_desc_table[0].os_desc = &rndis_opts->rndis_os_desc;
|
f->os_desc_table[0].os_desc = &rndis_opts->rndis_os_desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rndis_iad_descriptor.bFunctionClass = rndis_opts->class;
|
||||||
|
rndis_iad_descriptor.bFunctionSubClass = rndis_opts->subclass;
|
||||||
|
rndis_iad_descriptor.bFunctionProtocol = rndis_opts->protocol;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* in drivers/usb/gadget/configfs.c:configfs_composite_bind()
|
* in drivers/usb/gadget/configfs.c:configfs_composite_bind()
|
||||||
* configurations are bound in sequence with list_for_each_entry,
|
* configurations are bound in sequence with list_for_each_entry,
|
||||||
@ -866,11 +870,23 @@ USB_ETHERNET_CONFIGFS_ITEM_ATTR_QMULT(rndis);
|
|||||||
/* f_rndis_opts_ifname */
|
/* f_rndis_opts_ifname */
|
||||||
USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(rndis);
|
USB_ETHERNET_CONFIGFS_ITEM_ATTR_IFNAME(rndis);
|
||||||
|
|
||||||
|
/* f_rndis_opts_class */
|
||||||
|
USB_ETHER_CONFIGFS_ITEM_ATTR_U8_RW(rndis, class);
|
||||||
|
|
||||||
|
/* f_rndis_opts_subclass */
|
||||||
|
USB_ETHER_CONFIGFS_ITEM_ATTR_U8_RW(rndis, subclass);
|
||||||
|
|
||||||
|
/* f_rndis_opts_protocol */
|
||||||
|
USB_ETHER_CONFIGFS_ITEM_ATTR_U8_RW(rndis, protocol);
|
||||||
|
|
||||||
static struct configfs_attribute *rndis_attrs[] = {
|
static struct configfs_attribute *rndis_attrs[] = {
|
||||||
&rndis_opts_attr_dev_addr,
|
&rndis_opts_attr_dev_addr,
|
||||||
&rndis_opts_attr_host_addr,
|
&rndis_opts_attr_host_addr,
|
||||||
&rndis_opts_attr_qmult,
|
&rndis_opts_attr_qmult,
|
||||||
&rndis_opts_attr_ifname,
|
&rndis_opts_attr_ifname,
|
||||||
|
&rndis_opts_attr_class,
|
||||||
|
&rndis_opts_attr_subclass,
|
||||||
|
&rndis_opts_attr_protocol,
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -916,6 +932,10 @@ static struct usb_function_instance *rndis_alloc_inst(void)
|
|||||||
}
|
}
|
||||||
INIT_LIST_HEAD(&opts->rndis_os_desc.ext_prop);
|
INIT_LIST_HEAD(&opts->rndis_os_desc.ext_prop);
|
||||||
|
|
||||||
|
opts->class = rndis_iad_descriptor.bFunctionClass;
|
||||||
|
opts->subclass = rndis_iad_descriptor.bFunctionSubClass;
|
||||||
|
opts->protocol = rndis_iad_descriptor.bFunctionProtocol;
|
||||||
|
|
||||||
descs[0] = &opts->rndis_os_desc;
|
descs[0] = &opts->rndis_os_desc;
|
||||||
names[0] = "rndis";
|
names[0] = "rndis";
|
||||||
config_group_init_type_name(&opts->func_inst.group, "",
|
config_group_init_type_name(&opts->func_inst.group, "",
|
||||||
|
@ -79,7 +79,7 @@ struct snd_uac_chip {
|
|||||||
unsigned int p_framesize;
|
unsigned int p_framesize;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct snd_pcm_hardware uac_pcm_hardware = {
|
static const struct snd_pcm_hardware uac_pcm_hardware = {
|
||||||
.info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER
|
.info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER
|
||||||
| SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID
|
| SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID
|
||||||
| SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
|
| SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
|
||||||
@ -354,7 +354,7 @@ static int uac_pcm_null(struct snd_pcm_substream *substream)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct snd_pcm_ops uac_pcm_ops = {
|
static const struct snd_pcm_ops uac_pcm_ops = {
|
||||||
.open = uac_pcm_open,
|
.open = uac_pcm_open,
|
||||||
.close = uac_pcm_null,
|
.close = uac_pcm_null,
|
||||||
.ioctl = snd_pcm_lib_ioctl,
|
.ioctl = snd_pcm_lib_ioctl,
|
||||||
|
@ -1073,7 +1073,7 @@ struct net_device *gether_connect(struct gether *link)
|
|||||||
|
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
dev->zlp = link->is_zlp_ok;
|
dev->zlp = link->is_zlp_ok;
|
||||||
dev->no_skb_reserve = link->no_skb_reserve;
|
dev->no_skb_reserve = gadget_avoids_skb_reserve(dev->gadget);
|
||||||
DBG(dev, "qlen %d\n", qlen(dev->gadget, dev->qmult));
|
DBG(dev, "qlen %d\n", qlen(dev->gadget, dev->qmult));
|
||||||
|
|
||||||
dev->header_len = link->header_len;
|
dev->header_len = link->header_len;
|
||||||
|
@ -64,7 +64,6 @@ struct gether {
|
|||||||
struct usb_ep *out_ep;
|
struct usb_ep *out_ep;
|
||||||
|
|
||||||
bool is_zlp_ok;
|
bool is_zlp_ok;
|
||||||
bool no_skb_reserve;
|
|
||||||
|
|
||||||
u16 cdc_filter;
|
u16 cdc_filter;
|
||||||
|
|
||||||
|
@ -153,4 +153,39 @@ out: \
|
|||||||
\
|
\
|
||||||
CONFIGFS_ATTR_RO(_f_##_opts_, ifname)
|
CONFIGFS_ATTR_RO(_f_##_opts_, ifname)
|
||||||
|
|
||||||
|
#define USB_ETHER_CONFIGFS_ITEM_ATTR_U8_RW(_f_, _n_) \
|
||||||
|
static ssize_t _f_##_opts_##_n_##_show(struct config_item *item,\
|
||||||
|
char *page) \
|
||||||
|
{ \
|
||||||
|
struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
|
||||||
|
int ret; \
|
||||||
|
\
|
||||||
|
mutex_lock(&opts->lock); \
|
||||||
|
ret = sprintf(page, "%02x\n", opts->_n_); \
|
||||||
|
mutex_unlock(&opts->lock); \
|
||||||
|
\
|
||||||
|
return ret; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static ssize_t _f_##_opts_##_n_##_store(struct config_item *item,\
|
||||||
|
const char *page, \
|
||||||
|
size_t len) \
|
||||||
|
{ \
|
||||||
|
struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \
|
||||||
|
int ret; \
|
||||||
|
u8 val; \
|
||||||
|
\
|
||||||
|
mutex_lock(&opts->lock); \
|
||||||
|
ret = sscanf(page, "%02hhx", &val); \
|
||||||
|
if (ret > 0) { \
|
||||||
|
opts->_n_ = val; \
|
||||||
|
ret = len; \
|
||||||
|
} \
|
||||||
|
mutex_unlock(&opts->lock); \
|
||||||
|
\
|
||||||
|
return ret; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
CONFIGFS_ATTR(_f_##_opts_, _n_)
|
||||||
|
|
||||||
#endif /* __U_ETHER_CONFIGFS_H */
|
#endif /* __U_ETHER_CONFIGFS_H */
|
||||||
|
@ -29,6 +29,10 @@ struct f_rndis_opts {
|
|||||||
struct usb_os_desc rndis_os_desc;
|
struct usb_os_desc rndis_os_desc;
|
||||||
char rndis_ext_compat_id[16];
|
char rndis_ext_compat_id[16];
|
||||||
|
|
||||||
|
u8 class;
|
||||||
|
u8 subclass;
|
||||||
|
u8 protocol;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read/write access to configfs attributes is handled by configfs.
|
* Read/write access to configfs attributes is handled by configfs.
|
||||||
*
|
*
|
||||||
|
@ -537,7 +537,7 @@ static void gs_rx_push(unsigned long _port)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* push data to (open) tty */
|
/* push data to (open) tty */
|
||||||
if (req->actual) {
|
if (req->actual && tty) {
|
||||||
char *packet = req->buf;
|
char *packet = req->buf;
|
||||||
unsigned size = req->actual;
|
unsigned size = req->actual;
|
||||||
unsigned n;
|
unsigned n;
|
||||||
|
@ -436,5 +436,4 @@ module_usb_composite_driver(webcam_driver);
|
|||||||
MODULE_AUTHOR("Laurent Pinchart");
|
MODULE_AUTHOR("Laurent Pinchart");
|
||||||
MODULE_DESCRIPTION("Webcam Video Gadget");
|
MODULE_DESCRIPTION("Webcam Video Gadget");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_VERSION("0.1.0");
|
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
config USB_BDC_UDC
|
config USB_BDC_UDC
|
||||||
tristate "Broadcom USB3.0 device controller IP driver(BDC)"
|
tristate "Broadcom USB3.0 device controller IP driver(BDC)"
|
||||||
depends on USB_GADGET && HAS_DMA
|
depends on USB_GADGET && HAS_DMA
|
||||||
|
default ARCH_BRCMSTB
|
||||||
|
|
||||||
help
|
help
|
||||||
BDC is Broadcom's USB3.0 device controller IP. If your SOC has a BDC IP
|
BDC is Broadcom's USB3.0 device controller IP. If your SOC has a BDC IP
|
||||||
|
@ -27,8 +27,8 @@
|
|||||||
#include <linux/usb/gadget.h>
|
#include <linux/usb/gadget.h>
|
||||||
#include <asm/unaligned.h>
|
#include <asm/unaligned.h>
|
||||||
|
|
||||||
#define BRCM_BDC_NAME "bdc_usb3"
|
#define BRCM_BDC_NAME "bdc"
|
||||||
#define BRCM_BDC_DESC "BDC device controller driver"
|
#define BRCM_BDC_DESC "Broadcom USB Device Controller driver"
|
||||||
|
|
||||||
#define DMA_ADDR_INVALID (~(dma_addr_t)0)
|
#define DMA_ADDR_INVALID (~(dma_addr_t)0)
|
||||||
|
|
||||||
@ -83,14 +83,14 @@
|
|||||||
|
|
||||||
#define BDC_DVCSA 0x50
|
#define BDC_DVCSA 0x50
|
||||||
#define BDC_DVCSB 0x54
|
#define BDC_DVCSB 0x54
|
||||||
#define BDC_EPSTS0(n) (0x60 + (n * 0x10))
|
#define BDC_EPSTS0 0x60
|
||||||
#define BDC_EPSTS1(n) (0x64 + (n * 0x10))
|
#define BDC_EPSTS1 0x64
|
||||||
#define BDC_EPSTS2(n) (0x68 + (n * 0x10))
|
#define BDC_EPSTS2 0x68
|
||||||
#define BDC_EPSTS3(n) (0x6c + (n * 0x10))
|
#define BDC_EPSTS3 0x6c
|
||||||
#define BDC_EPSTS4(n) (0x70 + (n * 0x10))
|
#define BDC_EPSTS4 0x70
|
||||||
#define BDC_EPSTS5(n) (0x74 + (n * 0x10))
|
#define BDC_EPSTS5 0x74
|
||||||
#define BDC_EPSTS6(n) (0x78 + (n * 0x10))
|
#define BDC_EPSTS6 0x78
|
||||||
#define BDC_EPSTS7(n) (0x7c + (n * 0x10))
|
#define BDC_EPSTS7 0x7c
|
||||||
#define BDC_SRRBAL(n) (0x200 + (n * 0x10))
|
#define BDC_SRRBAL(n) (0x200 + (n * 0x10))
|
||||||
#define BDC_SRRBAH(n) (0x204 + (n * 0x10))
|
#define BDC_SRRBAH(n) (0x204 + (n * 0x10))
|
||||||
#define BDC_SRRINT(n) (0x208 + (n * 0x10))
|
#define BDC_SRRINT(n) (0x208 + (n * 0x10))
|
||||||
@ -413,6 +413,9 @@ struct bdc {
|
|||||||
/* device lock */
|
/* device lock */
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
|
|
||||||
|
/* generic phy */
|
||||||
|
struct phy **phys;
|
||||||
|
int num_phys;
|
||||||
/* num of endpoints for a particular instantiation of IP */
|
/* num of endpoints for a particular instantiation of IP */
|
||||||
unsigned int num_eps;
|
unsigned int num_eps;
|
||||||
/*
|
/*
|
||||||
@ -454,6 +457,7 @@ struct bdc {
|
|||||||
* Func Wake packet every 2.5 secs. Refer to USB3 spec section 8.5.6.4
|
* Func Wake packet every 2.5 secs. Refer to USB3 spec section 8.5.6.4
|
||||||
*/
|
*/
|
||||||
struct delayed_work func_wake_notify;
|
struct delayed_work func_wake_notify;
|
||||||
|
struct clk *clk;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline u32 bdc_readl(void __iomem *base, u32 offset)
|
static inline u32 bdc_readl(void __iomem *base, u32 offset)
|
||||||
|
@ -24,9 +24,11 @@
|
|||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
#include <linux/dmapool.h>
|
#include <linux/dmapool.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
|
#include <linux/phy/phy.h>
|
||||||
#include <linux/moduleparam.h>
|
#include <linux/moduleparam.h>
|
||||||
#include <linux/usb/ch9.h>
|
#include <linux/usb/ch9.h>
|
||||||
#include <linux/usb/gadget.h>
|
#include <linux/usb/gadget.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
|
|
||||||
#include "bdc.h"
|
#include "bdc.h"
|
||||||
#include "bdc_dbg.h"
|
#include "bdc_dbg.h"
|
||||||
@ -444,6 +446,43 @@ static int bdc_hw_init(struct bdc *bdc)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int bdc_phy_init(struct bdc *bdc)
|
||||||
|
{
|
||||||
|
int phy_num;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
for (phy_num = 0; phy_num < bdc->num_phys; phy_num++) {
|
||||||
|
ret = phy_init(bdc->phys[phy_num]);
|
||||||
|
if (ret)
|
||||||
|
goto err_exit_phy;
|
||||||
|
ret = phy_power_on(bdc->phys[phy_num]);
|
||||||
|
if (ret) {
|
||||||
|
phy_exit(bdc->phys[phy_num]);
|
||||||
|
goto err_exit_phy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_exit_phy:
|
||||||
|
while (--phy_num >= 0) {
|
||||||
|
phy_power_off(bdc->phys[phy_num]);
|
||||||
|
phy_exit(bdc->phys[phy_num]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bdc_phy_exit(struct bdc *bdc)
|
||||||
|
{
|
||||||
|
int phy_num;
|
||||||
|
|
||||||
|
for (phy_num = 0; phy_num < bdc->num_phys; phy_num++) {
|
||||||
|
phy_power_off(bdc->phys[phy_num]);
|
||||||
|
phy_exit(bdc->phys[phy_num]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int bdc_probe(struct platform_device *pdev)
|
static int bdc_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct bdc *bdc;
|
struct bdc *bdc;
|
||||||
@ -452,12 +491,29 @@ static int bdc_probe(struct platform_device *pdev)
|
|||||||
int irq;
|
int irq;
|
||||||
u32 temp;
|
u32 temp;
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
|
struct clk *clk;
|
||||||
|
int phy_num;
|
||||||
|
|
||||||
dev_dbg(dev, "%s()\n", __func__);
|
dev_dbg(dev, "%s()\n", __func__);
|
||||||
|
|
||||||
|
clk = devm_clk_get(dev, "sw_usbd");
|
||||||
|
if (IS_ERR(clk)) {
|
||||||
|
dev_info(dev, "Clock not found in Device Tree\n");
|
||||||
|
clk = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = clk_prepare_enable(clk);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "could not enable clock\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
bdc = devm_kzalloc(dev, sizeof(*bdc), GFP_KERNEL);
|
bdc = devm_kzalloc(dev, sizeof(*bdc), GFP_KERNEL);
|
||||||
if (!bdc)
|
if (!bdc)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
bdc->clk = clk;
|
||||||
|
|
||||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
bdc->regs = devm_ioremap_resource(dev, res);
|
bdc->regs = devm_ioremap_resource(dev, res);
|
||||||
if (IS_ERR(bdc->regs)) {
|
if (IS_ERR(bdc->regs)) {
|
||||||
@ -473,35 +529,66 @@ static int bdc_probe(struct platform_device *pdev)
|
|||||||
platform_set_drvdata(pdev, bdc);
|
platform_set_drvdata(pdev, bdc);
|
||||||
bdc->irq = irq;
|
bdc->irq = irq;
|
||||||
bdc->dev = dev;
|
bdc->dev = dev;
|
||||||
dev_dbg(bdc->dev, "bdc->regs: %p irq=%d\n", bdc->regs, bdc->irq);
|
dev_dbg(dev, "bdc->regs: %p irq=%d\n", bdc->regs, bdc->irq);
|
||||||
|
|
||||||
|
bdc->num_phys = of_count_phandle_with_args(dev->of_node,
|
||||||
|
"phys", "#phy-cells");
|
||||||
|
if (bdc->num_phys > 0) {
|
||||||
|
bdc->phys = devm_kcalloc(dev, bdc->num_phys,
|
||||||
|
sizeof(struct phy *), GFP_KERNEL);
|
||||||
|
if (!bdc->phys)
|
||||||
|
return -ENOMEM;
|
||||||
|
} else {
|
||||||
|
bdc->num_phys = 0;
|
||||||
|
}
|
||||||
|
dev_info(dev, "Using %d phy(s)\n", bdc->num_phys);
|
||||||
|
|
||||||
|
for (phy_num = 0; phy_num < bdc->num_phys; phy_num++) {
|
||||||
|
bdc->phys[phy_num] = devm_of_phy_get_by_index(
|
||||||
|
dev, dev->of_node, phy_num);
|
||||||
|
if (IS_ERR(bdc->phys[phy_num])) {
|
||||||
|
ret = PTR_ERR(bdc->phys[phy_num]);
|
||||||
|
dev_err(bdc->dev,
|
||||||
|
"BDC phy specified but not found:%d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = bdc_phy_init(bdc);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(bdc->dev, "BDC phy init failure:%d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
temp = bdc_readl(bdc->regs, BDC_BDCCAP1);
|
temp = bdc_readl(bdc->regs, BDC_BDCCAP1);
|
||||||
if ((temp & BDC_P64) &&
|
if ((temp & BDC_P64) &&
|
||||||
!dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))) {
|
!dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64))) {
|
||||||
dev_dbg(bdc->dev, "Using 64-bit address\n");
|
dev_dbg(dev, "Using 64-bit address\n");
|
||||||
} else {
|
} else {
|
||||||
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
|
ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(bdc->dev, "No suitable DMA config available, abort\n");
|
dev_err(dev,
|
||||||
|
"No suitable DMA config available, abort\n");
|
||||||
return -ENOTSUPP;
|
return -ENOTSUPP;
|
||||||
}
|
}
|
||||||
dev_dbg(bdc->dev, "Using 32-bit address\n");
|
dev_dbg(dev, "Using 32-bit address\n");
|
||||||
}
|
}
|
||||||
ret = bdc_hw_init(bdc);
|
ret = bdc_hw_init(bdc);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(bdc->dev, "BDC init failure:%d\n", ret);
|
dev_err(dev, "BDC init failure:%d\n", ret);
|
||||||
return ret;
|
goto phycleanup;
|
||||||
}
|
}
|
||||||
ret = bdc_udc_init(bdc);
|
ret = bdc_udc_init(bdc);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(bdc->dev, "BDC Gadget init failure:%d\n", ret);
|
dev_err(dev, "BDC Gadget init failure:%d\n", ret);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
bdc_hw_exit(bdc);
|
bdc_hw_exit(bdc);
|
||||||
|
phycleanup:
|
||||||
|
bdc_phy_exit(bdc);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -513,13 +600,56 @@ static int bdc_remove(struct platform_device *pdev)
|
|||||||
dev_dbg(bdc->dev, "%s ()\n", __func__);
|
dev_dbg(bdc->dev, "%s ()\n", __func__);
|
||||||
bdc_udc_exit(bdc);
|
bdc_udc_exit(bdc);
|
||||||
bdc_hw_exit(bdc);
|
bdc_hw_exit(bdc);
|
||||||
|
bdc_phy_exit(bdc);
|
||||||
|
clk_disable_unprepare(bdc->clk);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
static int bdc_suspend(struct device *dev)
|
||||||
|
{
|
||||||
|
struct bdc *bdc = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
clk_disable_unprepare(bdc->clk);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int bdc_resume(struct device *dev)
|
||||||
|
{
|
||||||
|
struct bdc *bdc = dev_get_drvdata(dev);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = clk_prepare_enable(bdc->clk);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(bdc->dev, "err enabling the clock\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
ret = bdc_reinit(bdc);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(bdc->dev, "err in bdc reinit\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_PM_SLEEP */
|
||||||
|
|
||||||
|
static SIMPLE_DEV_PM_OPS(bdc_pm_ops, bdc_suspend,
|
||||||
|
bdc_resume);
|
||||||
|
|
||||||
|
static const struct of_device_id bdc_of_match[] = {
|
||||||
|
{ .compatible = "brcm,bdc-v0.16" },
|
||||||
|
{ .compatible = "brcm,bdc" },
|
||||||
|
{ /* sentinel */ }
|
||||||
|
};
|
||||||
|
|
||||||
static struct platform_driver bdc_driver = {
|
static struct platform_driver bdc_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = BRCM_BDC_NAME,
|
.name = BRCM_BDC_NAME,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.pm = &bdc_pm_ops,
|
||||||
|
.of_match_table = bdc_of_match,
|
||||||
},
|
},
|
||||||
.probe = bdc_probe,
|
.probe = bdc_probe,
|
||||||
.remove = bdc_remove,
|
.remove = bdc_remove,
|
||||||
|
@ -40,28 +40,28 @@ void bdc_dump_epsts(struct bdc *bdc)
|
|||||||
{
|
{
|
||||||
u32 temp;
|
u32 temp;
|
||||||
|
|
||||||
temp = bdc_readl(bdc->regs, BDC_EPSTS0(0));
|
temp = bdc_readl(bdc->regs, BDC_EPSTS0);
|
||||||
dev_vdbg(bdc->dev, "BDC_EPSTS0:0x%08x\n", temp);
|
dev_vdbg(bdc->dev, "BDC_EPSTS0:0x%08x\n", temp);
|
||||||
|
|
||||||
temp = bdc_readl(bdc->regs, BDC_EPSTS1(0));
|
temp = bdc_readl(bdc->regs, BDC_EPSTS1);
|
||||||
dev_vdbg(bdc->dev, "BDC_EPSTS1:0x%x\n", temp);
|
dev_vdbg(bdc->dev, "BDC_EPSTS1:0x%x\n", temp);
|
||||||
|
|
||||||
temp = bdc_readl(bdc->regs, BDC_EPSTS2(0));
|
temp = bdc_readl(bdc->regs, BDC_EPSTS2);
|
||||||
dev_vdbg(bdc->dev, "BDC_EPSTS2:0x%08x\n", temp);
|
dev_vdbg(bdc->dev, "BDC_EPSTS2:0x%08x\n", temp);
|
||||||
|
|
||||||
temp = bdc_readl(bdc->regs, BDC_EPSTS3(0));
|
temp = bdc_readl(bdc->regs, BDC_EPSTS3);
|
||||||
dev_vdbg(bdc->dev, "BDC_EPSTS3:0x%08x\n", temp);
|
dev_vdbg(bdc->dev, "BDC_EPSTS3:0x%08x\n", temp);
|
||||||
|
|
||||||
temp = bdc_readl(bdc->regs, BDC_EPSTS4(0));
|
temp = bdc_readl(bdc->regs, BDC_EPSTS4);
|
||||||
dev_vdbg(bdc->dev, "BDC_EPSTS4:0x%08x\n", temp);
|
dev_vdbg(bdc->dev, "BDC_EPSTS4:0x%08x\n", temp);
|
||||||
|
|
||||||
temp = bdc_readl(bdc->regs, BDC_EPSTS5(0));
|
temp = bdc_readl(bdc->regs, BDC_EPSTS5);
|
||||||
dev_vdbg(bdc->dev, "BDC_EPSTS5:0x%08x\n", temp);
|
dev_vdbg(bdc->dev, "BDC_EPSTS5:0x%08x\n", temp);
|
||||||
|
|
||||||
temp = bdc_readl(bdc->regs, BDC_EPSTS6(0));
|
temp = bdc_readl(bdc->regs, BDC_EPSTS6);
|
||||||
dev_vdbg(bdc->dev, "BDC_EPSTS6:0x%08x\n", temp);
|
dev_vdbg(bdc->dev, "BDC_EPSTS6:0x%08x\n", temp);
|
||||||
|
|
||||||
temp = bdc_readl(bdc->regs, BDC_EPSTS7(0));
|
temp = bdc_readl(bdc->regs, BDC_EPSTS7);
|
||||||
dev_vdbg(bdc->dev, "BDC_EPSTS7:0x%08x\n", temp);
|
dev_vdbg(bdc->dev, "BDC_EPSTS7:0x%08x\n", temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -777,9 +777,9 @@ static int ep_dequeue(struct bdc_ep *ep, struct bdc_req *req)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* The current hw dequeue pointer */
|
/* The current hw dequeue pointer */
|
||||||
tmp_32 = bdc_readl(bdc->regs, BDC_EPSTS0(0));
|
tmp_32 = bdc_readl(bdc->regs, BDC_EPSTS0);
|
||||||
deq_ptr_64 = tmp_32;
|
deq_ptr_64 = tmp_32;
|
||||||
tmp_32 = bdc_readl(bdc->regs, BDC_EPSTS1(0));
|
tmp_32 = bdc_readl(bdc->regs, BDC_EPSTS1);
|
||||||
deq_ptr_64 |= ((u64)tmp_32 << 32);
|
deq_ptr_64 |= ((u64)tmp_32 << 32);
|
||||||
|
|
||||||
/* we have the dma addr of next bd that will be fetched by hardware */
|
/* we have the dma addr of next bd that will be fetched by hardware */
|
||||||
|
@ -249,6 +249,7 @@ void bdc_sr_uspc(struct bdc *bdc, struct bdc_sr *sreport)
|
|||||||
disconn = true;
|
disconn = true;
|
||||||
else if ((uspc & BDC_PCS) && !BDC_PST(uspc))
|
else if ((uspc & BDC_PCS) && !BDC_PST(uspc))
|
||||||
connected = true;
|
connected = true;
|
||||||
|
clear_flags |= BDC_PCC;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Change in VBus and VBus is present */
|
/* Change in VBus and VBus is present */
|
||||||
@ -259,16 +260,16 @@ void bdc_sr_uspc(struct bdc *bdc, struct bdc_sr *sreport)
|
|||||||
bdc_softconn(bdc);
|
bdc_softconn(bdc);
|
||||||
usb_gadget_set_state(&bdc->gadget, USB_STATE_POWERED);
|
usb_gadget_set_state(&bdc->gadget, USB_STATE_POWERED);
|
||||||
}
|
}
|
||||||
clear_flags = BDC_VBC;
|
clear_flags |= BDC_VBC;
|
||||||
} else if ((uspc & BDC_PRS) || (uspc & BDC_PRC) || disconn) {
|
} else if ((uspc & BDC_PRS) || (uspc & BDC_PRC) || disconn) {
|
||||||
/* Hot reset, warm reset, 2.0 bus reset or disconn */
|
/* Hot reset, warm reset, 2.0 bus reset or disconn */
|
||||||
dev_dbg(bdc->dev, "Port reset or disconn\n");
|
dev_dbg(bdc->dev, "Port reset or disconn\n");
|
||||||
bdc_uspc_disconnected(bdc, disconn);
|
bdc_uspc_disconnected(bdc, disconn);
|
||||||
clear_flags = BDC_PCC|BDC_PCS|BDC_PRS|BDC_PRC;
|
clear_flags |= BDC_PRC;
|
||||||
} else if ((uspc & BDC_PSC) && (uspc & BDC_PCS)) {
|
} else if ((uspc & BDC_PSC) && (uspc & BDC_PCS)) {
|
||||||
/* Change in Link state */
|
/* Change in Link state */
|
||||||
handle_link_state_change(bdc, uspc);
|
handle_link_state_change(bdc, uspc);
|
||||||
clear_flags = BDC_PSC|BDC_PCS;
|
clear_flags |= BDC_PSC;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -812,6 +812,8 @@ int usb_gadget_map_request_by_dev(struct device *dev,
|
|||||||
dev_err(dev, "failed to map buffer\n");
|
dev_err(dev, "failed to map buffer\n");
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
req->dma_mapped = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -836,9 +838,10 @@ void usb_gadget_unmap_request_by_dev(struct device *dev,
|
|||||||
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
|
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
|
||||||
|
|
||||||
req->num_mapped_sgs = 0;
|
req->num_mapped_sgs = 0;
|
||||||
} else {
|
} else if (req->dma_mapped) {
|
||||||
dma_unmap_single(dev, req->dma, req->length,
|
dma_unmap_single(dev, req->dma, req->length,
|
||||||
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
|
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
|
||||||
|
req->dma_mapped = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(usb_gadget_unmap_request_by_dev);
|
EXPORT_SYMBOL_GPL(usb_gadget_unmap_request_by_dev);
|
||||||
@ -1130,6 +1133,7 @@ static int check_pending_gadget_drivers(struct usb_udc *udc)
|
|||||||
* @release: a gadget release function.
|
* @release: a gadget release function.
|
||||||
*
|
*
|
||||||
* Returns zero on success, negative errno otherwise.
|
* Returns zero on success, negative errno otherwise.
|
||||||
|
* Calls the gadget release function in the latter case.
|
||||||
*/
|
*/
|
||||||
int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
|
int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
|
||||||
void (*release)(struct device *dev))
|
void (*release)(struct device *dev))
|
||||||
@ -1137,10 +1141,6 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
|
|||||||
struct usb_udc *udc;
|
struct usb_udc *udc;
|
||||||
int ret = -ENOMEM;
|
int ret = -ENOMEM;
|
||||||
|
|
||||||
udc = kzalloc(sizeof(*udc), GFP_KERNEL);
|
|
||||||
if (!udc)
|
|
||||||
goto err1;
|
|
||||||
|
|
||||||
dev_set_name(&gadget->dev, "gadget");
|
dev_set_name(&gadget->dev, "gadget");
|
||||||
INIT_WORK(&gadget->work, usb_gadget_state_work);
|
INIT_WORK(&gadget->work, usb_gadget_state_work);
|
||||||
gadget->dev.parent = parent;
|
gadget->dev.parent = parent;
|
||||||
@ -1150,7 +1150,13 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget,
|
|||||||
else
|
else
|
||||||
gadget->dev.release = usb_udc_nop_release;
|
gadget->dev.release = usb_udc_nop_release;
|
||||||
|
|
||||||
ret = device_register(&gadget->dev);
|
device_initialize(&gadget->dev);
|
||||||
|
|
||||||
|
udc = kzalloc(sizeof(*udc), GFP_KERNEL);
|
||||||
|
if (!udc)
|
||||||
|
goto err1;
|
||||||
|
|
||||||
|
ret = device_add(&gadget->dev);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err2;
|
goto err2;
|
||||||
|
|
||||||
@ -1197,10 +1203,10 @@ err3:
|
|||||||
device_del(&gadget->dev);
|
device_del(&gadget->dev);
|
||||||
|
|
||||||
err2:
|
err2:
|
||||||
put_device(&gadget->dev);
|
|
||||||
kfree(udc);
|
kfree(udc);
|
||||||
|
|
||||||
err1:
|
err1:
|
||||||
|
put_device(&gadget->dev);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(usb_add_gadget_udc_release);
|
EXPORT_SYMBOL_GPL(usb_add_gadget_udc_release);
|
||||||
|
@ -2776,7 +2776,7 @@ static int __init init(void)
|
|||||||
if (retval < 0) {
|
if (retval < 0) {
|
||||||
i--;
|
i--;
|
||||||
while (i >= 0)
|
while (i >= 0)
|
||||||
platform_device_del(the_udc_pdev[i]);
|
platform_device_del(the_udc_pdev[i--]);
|
||||||
goto err_add_udc;
|
goto err_add_udc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ static const char *const ep_name[] = {
|
|||||||
"ep3",
|
"ep3",
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct usb_endpoint_descriptor qe_ep0_desc = {
|
static const struct usb_endpoint_descriptor qe_ep0_desc = {
|
||||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||||
.bDescriptorType = USB_DT_ENDPOINT,
|
.bDescriptorType = USB_DT_ENDPOINT,
|
||||||
|
|
||||||
|
@ -39,7 +39,6 @@
|
|||||||
#include "mv_udc.h"
|
#include "mv_udc.h"
|
||||||
|
|
||||||
#define DRIVER_DESC "Marvell PXA USB Device Controller driver"
|
#define DRIVER_DESC "Marvell PXA USB Device Controller driver"
|
||||||
#define DRIVER_VERSION "8 Nov 2010"
|
|
||||||
|
|
||||||
#define ep_dir(ep) (((ep)->ep_num == 0) ? \
|
#define ep_dir(ep) (((ep)->ep_num == 0) ? \
|
||||||
((ep)->udc->ep0_dir) : ((ep)->direction))
|
((ep)->udc->ep0_dir) : ((ep)->direction))
|
||||||
@ -2427,5 +2426,4 @@ module_platform_driver(udc_driver);
|
|||||||
MODULE_ALIAS("platform:mv-udc");
|
MODULE_ALIAS("platform:mv-udc");
|
||||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||||
MODULE_AUTHOR("Chao Xie <chao.xie@marvell.com>");
|
MODULE_AUTHOR("Chao Xie <chao.xie@marvell.com>");
|
||||||
MODULE_VERSION(DRIVER_VERSION);
|
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
* the Free Software Foundation; version 2 of the License.
|
* the Free Software Foundation; version 2 of the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/debugfs.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
@ -20,6 +21,8 @@
|
|||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
#include <linux/sizes.h>
|
#include <linux/sizes.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
#include <linux/sys_soc.h>
|
||||||
|
#include <linux/uaccess.h>
|
||||||
#include <linux/usb/ch9.h>
|
#include <linux/usb/ch9.h>
|
||||||
#include <linux/usb/gadget.h>
|
#include <linux/usb/gadget.h>
|
||||||
|
|
||||||
@ -347,6 +350,7 @@ struct renesas_usb3 {
|
|||||||
bool workaround_for_vbus;
|
bool workaround_for_vbus;
|
||||||
bool extcon_host; /* check id and set EXTCON_USB_HOST */
|
bool extcon_host; /* check id and set EXTCON_USB_HOST */
|
||||||
bool extcon_usb; /* check vbus and set EXTCON_USB */
|
bool extcon_usb; /* check vbus and set EXTCON_USB */
|
||||||
|
bool forced_b_device;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define gadget_to_renesas_usb3(_gadget) \
|
#define gadget_to_renesas_usb3(_gadget) \
|
||||||
@ -663,7 +667,9 @@ static void usb3_mode_config(struct renesas_usb3 *usb3, bool host, bool a_dev)
|
|||||||
spin_lock_irqsave(&usb3->lock, flags);
|
spin_lock_irqsave(&usb3->lock, flags);
|
||||||
usb3_set_mode(usb3, host);
|
usb3_set_mode(usb3, host);
|
||||||
usb3_vbus_out(usb3, a_dev);
|
usb3_vbus_out(usb3, a_dev);
|
||||||
if (!host && a_dev) /* for A-Peripheral */
|
/* for A-Peripheral or forced B-device mode */
|
||||||
|
if ((!host && a_dev) ||
|
||||||
|
(usb3->workaround_for_vbus && usb3->forced_b_device))
|
||||||
usb3_connect(usb3);
|
usb3_connect(usb3);
|
||||||
spin_unlock_irqrestore(&usb3->lock, flags);
|
spin_unlock_irqrestore(&usb3->lock, flags);
|
||||||
}
|
}
|
||||||
@ -677,7 +683,7 @@ static void usb3_check_id(struct renesas_usb3 *usb3)
|
|||||||
{
|
{
|
||||||
usb3->extcon_host = usb3_is_a_device(usb3);
|
usb3->extcon_host = usb3_is_a_device(usb3);
|
||||||
|
|
||||||
if (usb3->extcon_host)
|
if (usb3->extcon_host && !usb3->forced_b_device)
|
||||||
usb3_mode_config(usb3, true, true);
|
usb3_mode_config(usb3, true, true);
|
||||||
else
|
else
|
||||||
usb3_mode_config(usb3, false, false);
|
usb3_mode_config(usb3, false, false);
|
||||||
@ -2192,7 +2198,7 @@ static void renesas_usb3_ep_fifo_flush(struct usb_ep *_ep)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct usb_ep_ops renesas_usb3_ep_ops = {
|
static const struct usb_ep_ops renesas_usb3_ep_ops = {
|
||||||
.enable = renesas_usb3_ep_enable,
|
.enable = renesas_usb3_ep_enable,
|
||||||
.disable = renesas_usb3_ep_disable,
|
.disable = renesas_usb3_ep_disable,
|
||||||
|
|
||||||
@ -2283,6 +2289,9 @@ static ssize_t role_store(struct device *dev, struct device_attribute *attr,
|
|||||||
if (!usb3->driver)
|
if (!usb3->driver)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
|
if (usb3->forced_b_device)
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
if (!strncmp(buf, "host", strlen("host")))
|
if (!strncmp(buf, "host", strlen("host")))
|
||||||
new_mode_is_host = true;
|
new_mode_is_host = true;
|
||||||
else if (!strncmp(buf, "peripheral", strlen("peripheral")))
|
else if (!strncmp(buf, "peripheral", strlen("peripheral")))
|
||||||
@ -2310,6 +2319,70 @@ static ssize_t role_show(struct device *dev, struct device_attribute *attr,
|
|||||||
}
|
}
|
||||||
static DEVICE_ATTR_RW(role);
|
static DEVICE_ATTR_RW(role);
|
||||||
|
|
||||||
|
static int renesas_usb3_b_device_show(struct seq_file *s, void *unused)
|
||||||
|
{
|
||||||
|
struct renesas_usb3 *usb3 = s->private;
|
||||||
|
|
||||||
|
seq_printf(s, "%d\n", usb3->forced_b_device);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int renesas_usb3_b_device_open(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
return single_open(file, renesas_usb3_b_device_show, inode->i_private);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t renesas_usb3_b_device_write(struct file *file,
|
||||||
|
const char __user *ubuf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct seq_file *s = file->private_data;
|
||||||
|
struct renesas_usb3 *usb3 = s->private;
|
||||||
|
char buf[32];
|
||||||
|
|
||||||
|
if (!usb3->driver)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
if (!strncmp(buf, "1", 1))
|
||||||
|
usb3->forced_b_device = true;
|
||||||
|
else
|
||||||
|
usb3->forced_b_device = false;
|
||||||
|
|
||||||
|
/* Let this driver call usb3_connect() anyway */
|
||||||
|
usb3_check_id(usb3);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations renesas_usb3_b_device_fops = {
|
||||||
|
.open = renesas_usb3_b_device_open,
|
||||||
|
.write = renesas_usb3_b_device_write,
|
||||||
|
.read = seq_read,
|
||||||
|
.llseek = seq_lseek,
|
||||||
|
.release = single_release,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void renesas_usb3_debugfs_init(struct renesas_usb3 *usb3,
|
||||||
|
struct device *dev)
|
||||||
|
{
|
||||||
|
struct dentry *root, *file;
|
||||||
|
|
||||||
|
root = debugfs_create_dir(dev_name(dev), NULL);
|
||||||
|
if (IS_ERR_OR_NULL(root)) {
|
||||||
|
dev_info(dev, "%s: Can't create the root\n", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
file = debugfs_create_file("b_device", 0644, root, usb3,
|
||||||
|
&renesas_usb3_b_device_fops);
|
||||||
|
if (!file)
|
||||||
|
dev_info(dev, "%s: Can't create debugfs mode\n", __func__);
|
||||||
|
}
|
||||||
|
|
||||||
/*------- platform_driver ------------------------------------------------*/
|
/*------- platform_driver ------------------------------------------------*/
|
||||||
static int renesas_usb3_remove(struct platform_device *pdev)
|
static int renesas_usb3_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
@ -2432,22 +2505,40 @@ static void renesas_usb3_init_ram(struct renesas_usb3 *usb3, struct device *dev,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct renesas_usb3_priv renesas_usb3_priv_r8a7795 = {
|
static const struct renesas_usb3_priv renesas_usb3_priv_r8a7795_es1 = {
|
||||||
.ramsize_per_ramif = SZ_16K,
|
.ramsize_per_ramif = SZ_16K,
|
||||||
.num_ramif = 2,
|
.num_ramif = 2,
|
||||||
.ramsize_per_pipe = SZ_4K,
|
.ramsize_per_pipe = SZ_4K,
|
||||||
.workaround_for_vbus = true,
|
.workaround_for_vbus = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct renesas_usb3_priv renesas_usb3_priv_gen3 = {
|
||||||
|
.ramsize_per_ramif = SZ_16K,
|
||||||
|
.num_ramif = 4,
|
||||||
|
.ramsize_per_pipe = SZ_4K,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct of_device_id usb3_of_match[] = {
|
static const struct of_device_id usb3_of_match[] = {
|
||||||
{
|
{
|
||||||
.compatible = "renesas,r8a7795-usb3-peri",
|
.compatible = "renesas,r8a7795-usb3-peri",
|
||||||
.data = &renesas_usb3_priv_r8a7795,
|
.data = &renesas_usb3_priv_gen3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "renesas,rcar-gen3-usb3-peri",
|
||||||
|
.data = &renesas_usb3_priv_gen3,
|
||||||
},
|
},
|
||||||
{ },
|
{ },
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, usb3_of_match);
|
MODULE_DEVICE_TABLE(of, usb3_of_match);
|
||||||
|
|
||||||
|
static const struct soc_device_attribute renesas_usb3_quirks_match[] = {
|
||||||
|
{
|
||||||
|
.soc_id = "r8a7795", .revision = "ES1.*",
|
||||||
|
.data = &renesas_usb3_priv_r8a7795_es1,
|
||||||
|
},
|
||||||
|
{ /* sentinel */ },
|
||||||
|
};
|
||||||
|
|
||||||
static const unsigned int renesas_usb3_cable[] = {
|
static const unsigned int renesas_usb3_cable[] = {
|
||||||
EXTCON_USB,
|
EXTCON_USB,
|
||||||
EXTCON_USB_HOST,
|
EXTCON_USB_HOST,
|
||||||
@ -2461,15 +2552,23 @@ static int renesas_usb3_probe(struct platform_device *pdev)
|
|||||||
const struct of_device_id *match;
|
const struct of_device_id *match;
|
||||||
int irq, ret;
|
int irq, ret;
|
||||||
const struct renesas_usb3_priv *priv;
|
const struct renesas_usb3_priv *priv;
|
||||||
|
const struct soc_device_attribute *attr;
|
||||||
|
|
||||||
match = of_match_node(usb3_of_match, pdev->dev.of_node);
|
match = of_match_node(usb3_of_match, pdev->dev.of_node);
|
||||||
if (!match)
|
if (!match)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
priv = match->data;
|
|
||||||
|
attr = soc_device_match(renesas_usb3_quirks_match);
|
||||||
|
if (attr)
|
||||||
|
priv = attr->data;
|
||||||
|
else
|
||||||
|
priv = match->data;
|
||||||
|
|
||||||
irq = platform_get_irq(pdev, 0);
|
irq = platform_get_irq(pdev, 0);
|
||||||
if (irq < 0)
|
if (irq < 0) {
|
||||||
return -ENODEV;
|
dev_err(&pdev->dev, "Failed to get IRQ: %d\n", irq);
|
||||||
|
return irq;
|
||||||
|
}
|
||||||
|
|
||||||
usb3 = devm_kzalloc(&pdev->dev, sizeof(*usb3), GFP_KERNEL);
|
usb3 = devm_kzalloc(&pdev->dev, sizeof(*usb3), GFP_KERNEL);
|
||||||
if (!usb3)
|
if (!usb3)
|
||||||
@ -2527,6 +2626,8 @@ static int renesas_usb3_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
usb3->workaround_for_vbus = priv->workaround_for_vbus;
|
usb3->workaround_for_vbus = priv->workaround_for_vbus;
|
||||||
|
|
||||||
|
renesas_usb3_debugfs_init(usb3, &pdev->dev);
|
||||||
|
|
||||||
dev_info(&pdev->dev, "probed\n");
|
dev_info(&pdev->dev, "probed\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -51,7 +51,6 @@
|
|||||||
#include "s3c2410_udc.h"
|
#include "s3c2410_udc.h"
|
||||||
|
|
||||||
#define DRIVER_DESC "S3C2410 USB Device Controller Gadget"
|
#define DRIVER_DESC "S3C2410 USB Device Controller Gadget"
|
||||||
#define DRIVER_VERSION "29 Apr 2007"
|
|
||||||
#define DRIVER_AUTHOR "Herbert Pötzl <herbert@13thfloor.at>, " \
|
#define DRIVER_AUTHOR "Herbert Pötzl <herbert@13thfloor.at>, " \
|
||||||
"Arnaud Patard <arnaud.patard@rtp-net.org>"
|
"Arnaud Patard <arnaud.patard@rtp-net.org>"
|
||||||
|
|
||||||
@ -1996,7 +1995,7 @@ static int __init udc_init(void)
|
|||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
dprintk(DEBUG_NORMAL, "%s: version %s\n", gadget_name, DRIVER_VERSION);
|
dprintk(DEBUG_NORMAL, "%s\n", gadget_name);
|
||||||
|
|
||||||
s3c2410_udc_debugfs_root = debugfs_create_dir(gadget_name, NULL);
|
s3c2410_udc_debugfs_root = debugfs_create_dir(gadget_name, NULL);
|
||||||
if (IS_ERR(s3c2410_udc_debugfs_root)) {
|
if (IS_ERR(s3c2410_udc_debugfs_root)) {
|
||||||
@ -2027,5 +2026,4 @@ module_exit(udc_exit);
|
|||||||
|
|
||||||
MODULE_AUTHOR(DRIVER_AUTHOR);
|
MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||||
MODULE_VERSION(DRIVER_VERSION);
|
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
@ -642,7 +642,7 @@ static int ehci_start_port_reset(struct usb_hcd *hcd, unsigned port)
|
|||||||
#define ehci_start_port_reset NULL
|
#define ehci_start_port_reset NULL
|
||||||
#endif /* CONFIG_USB_OTG */
|
#endif /* CONFIG_USB_OTG */
|
||||||
|
|
||||||
static struct ehci_driver_overrides ehci_fsl_overrides __initdata = {
|
static const struct ehci_driver_overrides ehci_fsl_overrides __initconst = {
|
||||||
.extra_priv_size = sizeof(struct ehci_fsl),
|
.extra_priv_size = sizeof(struct ehci_fsl),
|
||||||
.reset = ehci_fsl_setup,
|
.reset = ehci_fsl_setup,
|
||||||
};
|
};
|
||||||
|
@ -130,8 +130,8 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
irq = platform_get_irq(pdev, 0);
|
irq = platform_get_irq(pdev, 0);
|
||||||
if (irq < 0) {
|
if (irq < 0) {
|
||||||
dev_err(dev, "EHCI irq failed\n");
|
dev_err(dev, "EHCI irq failed: %d\n", irq);
|
||||||
return -ENODEV;
|
return irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
@ -55,8 +55,8 @@ static struct fsl_usb2_dev_data *get_dr_mode_data(struct device_node *np)
|
|||||||
return &dr_mode_data[i];
|
return &dr_mode_data[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pr_warn("%s: Invalid 'dr_mode' property, fallback to host mode\n",
|
pr_warn("%pOF: Invalid 'dr_mode' property, fallback to host mode\n",
|
||||||
np->full_name);
|
np);
|
||||||
return &dr_mode_data[0]; /* mode not specified, use host */
|
return &dr_mode_data[0]; /* mode not specified, use host */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -614,7 +614,7 @@ error:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct hc_driver hwahc_hc_driver = {
|
static const struct hc_driver hwahc_hc_driver = {
|
||||||
.description = "hwa-hcd",
|
.description = "hwa-hcd",
|
||||||
.product_desc = "Wireless USB HWA host controller",
|
.product_desc = "Wireless USB HWA host controller",
|
||||||
.hcd_priv_size = sizeof(struct hwahc) - sizeof(struct usb_hcd),
|
.hcd_priv_size = sizeof(struct hwahc) - sizeof(struct usb_hcd),
|
||||||
@ -860,7 +860,7 @@ static void hwahc_disconnect(struct usb_interface *usb_iface)
|
|||||||
usb_put_hcd(usb_hcd);
|
usb_put_hcd(usb_hcd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct usb_device_id hwahc_id_table[] = {
|
static const struct usb_device_id hwahc_id_table[] = {
|
||||||
/* Alereon 5310 */
|
/* Alereon 5310 */
|
||||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x13dc, 0x5310, 0xe0, 0x02, 0x01),
|
{ USB_DEVICE_AND_INTERFACE_INFO(0x13dc, 0x5310, 0xe0, 0x02, 0x01),
|
||||||
.driver_info = WUSB_QUIRK_ALEREON_HWA_CONCAT_ISOC |
|
.driver_info = WUSB_QUIRK_ALEREON_HWA_CONCAT_ISOC |
|
||||||
|
@ -1779,7 +1779,7 @@ static void imx21_hc_stop(struct usb_hcd *hcd)
|
|||||||
/* Driver glue */
|
/* Driver glue */
|
||||||
/* =========================================== */
|
/* =========================================== */
|
||||||
|
|
||||||
static struct hc_driver imx21_hc_driver = {
|
static const struct hc_driver imx21_hc_driver = {
|
||||||
.description = hcd_name,
|
.description = hcd_name,
|
||||||
.product_desc = "IMX21 USB Host Controller",
|
.product_desc = "IMX21 USB Host Controller",
|
||||||
.hcd_priv_size = sizeof(struct imx21),
|
.hcd_priv_size = sizeof(struct imx21),
|
||||||
@ -1849,8 +1849,10 @@ static int imx21_probe(struct platform_device *pdev)
|
|||||||
if (!res)
|
if (!res)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
irq = platform_get_irq(pdev, 0);
|
irq = platform_get_irq(pdev, 0);
|
||||||
if (irq < 0)
|
if (irq < 0) {
|
||||||
return -ENXIO;
|
dev_err(&pdev->dev, "Failed to get IRQ: %d\n", irq);
|
||||||
|
return irq;
|
||||||
|
}
|
||||||
|
|
||||||
hcd = usb_create_hcd(&imx21_hc_driver,
|
hcd = usb_create_hcd(&imx21_hc_driver,
|
||||||
&pdev->dev, dev_name(&pdev->dev));
|
&pdev->dev, dev_name(&pdev->dev));
|
||||||
|
@ -1511,7 +1511,7 @@ static int isp116x_bus_resume(struct usb_hcd *hcd)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct hc_driver isp116x_hc_driver = {
|
static const struct hc_driver isp116x_hc_driver = {
|
||||||
.description = hcd_name,
|
.description = hcd_name,
|
||||||
.product_desc = "ISP116x Host Controller",
|
.product_desc = "ISP116x Host Controller",
|
||||||
.hcd_priv_size = sizeof(struct isp116x),
|
.hcd_priv_size = sizeof(struct isp116x),
|
||||||
|
@ -2591,7 +2591,7 @@ static int isp1362_hc_start(struct usb_hcd *hcd)
|
|||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static struct hc_driver isp1362_hc_driver = {
|
static const struct hc_driver isp1362_hc_driver = {
|
||||||
.description = hcd_name,
|
.description = hcd_name,
|
||||||
.product_desc = "ISP1362 Host Controller",
|
.product_desc = "ISP1362 Host Controller",
|
||||||
.hcd_priv_size = sizeof(struct isp1362_hcd),
|
.hcd_priv_size = sizeof(struct isp1362_hcd),
|
||||||
|
@ -1811,7 +1811,7 @@ max3421_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct hc_driver max3421_hcd_desc = {
|
static const struct hc_driver max3421_hcd_desc = {
|
||||||
.description = "max3421",
|
.description = "max3421",
|
||||||
.product_desc = DRIVER_DESC,
|
.product_desc = DRIVER_DESC,
|
||||||
.hcd_priv_size = sizeof(struct max3421_hcd),
|
.hcd_priv_size = sizeof(struct max3421_hcd),
|
||||||
|
@ -142,29 +142,30 @@ static int amd_chipset_sb_type_init(struct amd_chipset_info *pinfo)
|
|||||||
pinfo->sb_type.gen = AMD_CHIPSET_SB700;
|
pinfo->sb_type.gen = AMD_CHIPSET_SB700;
|
||||||
else if (rev >= 0x40 && rev <= 0x4f)
|
else if (rev >= 0x40 && rev <= 0x4f)
|
||||||
pinfo->sb_type.gen = AMD_CHIPSET_SB800;
|
pinfo->sb_type.gen = AMD_CHIPSET_SB800;
|
||||||
}
|
|
||||||
pinfo->smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD,
|
|
||||||
0x145c, NULL);
|
|
||||||
if (pinfo->smbus_dev) {
|
|
||||||
pinfo->sb_type.gen = AMD_CHIPSET_TAISHAN;
|
|
||||||
} else {
|
} else {
|
||||||
pinfo->smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD,
|
pinfo->smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD,
|
||||||
PCI_DEVICE_ID_AMD_HUDSON2_SMBUS, NULL);
|
PCI_DEVICE_ID_AMD_HUDSON2_SMBUS, NULL);
|
||||||
|
|
||||||
if (!pinfo->smbus_dev) {
|
if (pinfo->smbus_dev) {
|
||||||
pinfo->sb_type.gen = NOT_AMD_CHIPSET;
|
rev = pinfo->smbus_dev->revision;
|
||||||
return 0;
|
if (rev >= 0x11 && rev <= 0x14)
|
||||||
|
pinfo->sb_type.gen = AMD_CHIPSET_HUDSON2;
|
||||||
|
else if (rev >= 0x15 && rev <= 0x18)
|
||||||
|
pinfo->sb_type.gen = AMD_CHIPSET_BOLTON;
|
||||||
|
else if (rev >= 0x39 && rev <= 0x3a)
|
||||||
|
pinfo->sb_type.gen = AMD_CHIPSET_YANGTZE;
|
||||||
|
} else {
|
||||||
|
pinfo->smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD,
|
||||||
|
0x145c, NULL);
|
||||||
|
if (pinfo->smbus_dev) {
|
||||||
|
rev = pinfo->smbus_dev->revision;
|
||||||
|
pinfo->sb_type.gen = AMD_CHIPSET_TAISHAN;
|
||||||
|
} else {
|
||||||
|
pinfo->sb_type.gen = NOT_AMD_CHIPSET;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rev = pinfo->smbus_dev->revision;
|
|
||||||
if (rev >= 0x11 && rev <= 0x14)
|
|
||||||
pinfo->sb_type.gen = AMD_CHIPSET_HUDSON2;
|
|
||||||
else if (rev >= 0x15 && rev <= 0x18)
|
|
||||||
pinfo->sb_type.gen = AMD_CHIPSET_BOLTON;
|
|
||||||
else if (rev >= 0x39 && rev <= 0x3a)
|
|
||||||
pinfo->sb_type.gen = AMD_CHIPSET_YANGTZE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pinfo->sb_type.rev = rev;
|
pinfo->sb_type.rev = rev;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -2312,7 +2312,7 @@ static int r8a66597_bus_resume(struct usb_hcd *hcd)
|
|||||||
#define r8a66597_bus_resume NULL
|
#define r8a66597_bus_resume NULL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct hc_driver r8a66597_hc_driver = {
|
static const struct hc_driver r8a66597_hc_driver = {
|
||||||
.description = hcd_name,
|
.description = hcd_name,
|
||||||
.hcd_priv_size = sizeof(struct r8a66597),
|
.hcd_priv_size = sizeof(struct r8a66597),
|
||||||
.irq = r8a66597_irq,
|
.irq = r8a66597_irq,
|
||||||
|
@ -1554,7 +1554,7 @@ sl811h_start(struct usb_hcd *hcd)
|
|||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static struct hc_driver sl811h_hc_driver = {
|
static const struct hc_driver sl811h_hc_driver = {
|
||||||
.description = hcd_name,
|
.description = hcd_name,
|
||||||
.hcd_priv_size = sizeof(struct sl811),
|
.hcd_priv_size = sizeof(struct sl811),
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user