Browse Source

Merge tag 'usb-4.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb

Pull USB/PHY updates from Greg KH:
 "Here is the big set of USB and PHY driver updates for 4.15-rc1.

  There is the usual amount of gadget and xhci driver updates, along
  with phy and chipidea enhancements. There's also a lot of SPDX tags
  and license boilerplate cleanups as well, which provide some churn in
  the diffstat.

  Other major thing is the typec code that moved out of staging and into
  the "real" part of the drivers/usb/ tree, which was nice to see
  happen.

  All of these have been in linux-next with no reported issues for a
  while"

* tag 'usb-4.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (263 commits)
  usb: gadget: f_fs: Fix use-after-free in ffs_free_inst
  USB: usbfs: compute urb->actual_length for isochronous
  usb: core: message: remember to reset 'ret' to 0 when necessary
  USB: typec: Remove remaining redundant license text
  USB: typec: add SPDX identifiers to some files
  USB: renesas_usbhs: rcar?.h: add SPDX tags
  USB: chipidea: ci_hdrc_tegra.c: add SPDX line
  USB: host: xhci-debugfs: add SPDX lines
  USB: add SPDX identifiers to all remaining Makefiles
  usb: host: isp1362-hcd: remove a couple of redundant assignments
  USB: adutux: remove redundant variable minor
  usb: core: add a new usb_get_ptm_status() helper
  usb: core: add a 'type' parameter to usb_get_status()
  usb: core: introduce a new usb_get_std_status() helper
  usb: core: rename usb_get_status() 'type' argument to 'recip'
  usb: core: add Status Type definitions
  USB: gadget: Remove redundant license text
  USB: gadget: function: Remove redundant license text
  USB: gadget: udc: Remove redundant license text
  USB: gadget: legacy: Remove redundant license text
  ...
Linus Torvalds 7 years ago
parent
commit
894025f24b
100 changed files with 2430 additions and 558 deletions
  1. 43 0
      Documentation/devicetree/bindings/phy/brcm,brcmstb-usb-phy.txt
  2. 10 1
      Documentation/devicetree/bindings/phy/brcm-sata-phy.txt
  3. 5 2
      Documentation/devicetree/bindings/phy/rcar-gen2-phy.txt
  4. 2 0
      Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt
  5. 2 0
      Documentation/devicetree/bindings/usb/dwc2.txt
  6. 26 0
      Documentation/devicetree/bindings/usb/maxim,max3421.txt
  7. 10 10
      Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt
  8. 10 9
      Documentation/devicetree/bindings/usb/mediatek,mtu3.txt
  9. 4 0
      Documentation/devicetree/bindings/usb/renesas_usb3.txt
  10. 4 1
      Documentation/devicetree/bindings/usb/renesas_usbhs.txt
  11. 1 0
      Documentation/devicetree/bindings/usb/usb-xhci.txt
  12. 32 14
      Documentation/devicetree/bindings/usb/usb251xb.txt
  13. 7 0
      MAINTAINERS
  14. 1 1
      drivers/extcon/extcon-adc-jack.c
  15. 1 1
      drivers/extcon/extcon-arizona.c
  16. 1 1
      drivers/extcon/extcon-axp288.c
  17. 1 1
      drivers/extcon/extcon-gpio.c
  18. 1 1
      drivers/extcon/extcon-intel-cht-wc.c
  19. 1 1
      drivers/extcon/extcon-intel-int3496.c
  20. 2 2
      drivers/extcon/extcon-max14577.c
  21. 1 1
      drivers/extcon/extcon-max3355.c
  22. 1 1
      drivers/extcon/extcon-max77693.c
  23. 80 15
      drivers/extcon/extcon-max77843.c
  24. 1 1
      drivers/extcon/extcon-max8997.c
  25. 1 1
      drivers/extcon/extcon-qcom-spmi-misc.c
  26. 1 1
      drivers/extcon/extcon-rt8973a.c
  27. 1 1
      drivers/extcon/extcon-sm5502.c
  28. 1 1
      drivers/extcon/extcon-usb-gpio.c
  29. 1 1
      drivers/extcon/extcon-usbc-cros-ec.c
  30. 1 1
      drivers/extcon/extcon.c
  31. 1 1
      drivers/extcon/extcon.h
  32. 16 0
      drivers/pci/dwc/pci-dra7xx.c
  33. 2 1
      drivers/phy/allwinner/phy-sun4i-usb.c
  34. 13 0
      drivers/phy/broadcom/Kconfig
  35. 3 0
      drivers/phy/broadcom/Makefile
  36. 1 1
      drivers/phy/broadcom/phy-bcm-ns2-usbdrd.c
  37. 73 1
      drivers/phy/broadcom/phy-brcm-sata.c
  38. 1017 0
      drivers/phy/broadcom/phy-brcm-usb-init.c
  39. 50 0
      drivers/phy/broadcom/phy-brcm-usb-init.h
  40. 459 0
      drivers/phy/broadcom/phy-brcm-usb.c
  41. 0 1
      drivers/phy/marvell/phy-mvebu-cp110-comphy.c
  42. 39 0
      drivers/phy/mediatek/phy-mtk-tphy.c
  43. 15 0
      drivers/phy/phy-core.c
  44. 3 2
      drivers/phy/qualcomm/phy-qcom-ufs-i.h
  45. 27 2
      drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.c
  46. 27 2
      drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.c
  47. 14 28
      drivers/phy/qualcomm/phy-qcom-ufs.c
  48. 47 25
      drivers/phy/renesas/phy-rcar-gen3-usb2.c
  49. 1 1
      drivers/phy/rockchip/phy-rockchip-inno-usb2.c
  50. 175 42
      drivers/phy/rockchip/phy-rockchip-typec.c
  51. 100 1
      drivers/phy/ti/phy-ti-pipe3.c
  52. 1 1
      drivers/power/supply/qcom_smbb.c
  53. 17 22
      drivers/scsi/ufs/ufs-qcom.c
  54. 12 0
      drivers/soc/bcm/brcmstb/common.c
  55. 2 2
      drivers/staging/wlan-ng/hfa384x_usb.c
  56. 5 4
      drivers/usb/Kconfig
  57. 4 18
      drivers/usb/atm/cxacru.c
  58. 5 22
      drivers/usb/atm/speedtch.c
  59. 1 0
      drivers/usb/atm/ueagle-atm.c
  60. 1 15
      drivers/usb/atm/usbatm.c
  61. 1 15
      drivers/usb/atm/usbatm.h
  62. 1 15
      drivers/usb/atm/xusbatm.c
  63. 1 0
      drivers/usb/c67x00/Makefile
  64. 1 15
      drivers/usb/c67x00/c67x00-drv.c
  65. 1 15
      drivers/usb/c67x00/c67x00-hcd.c
  66. 1 15
      drivers/usb/c67x00/c67x00-hcd.h
  67. 1 15
      drivers/usb/c67x00/c67x00-ll-hpi.c
  68. 1 17
      drivers/usb/c67x00/c67x00-sched.c
  69. 1 15
      drivers/usb/c67x00/c67x00.h
  70. 1 1
      drivers/usb/chipidea/Kconfig
  71. 1 4
      drivers/usb/chipidea/bits.h
  72. 1 4
      drivers/usb/chipidea/ci.h
  73. 1 7
      drivers/usb/chipidea/ci_hdrc_imx.c
  74. 1 7
      drivers/usb/chipidea/ci_hdrc_imx.h
  75. 2 6
      drivers/usb/chipidea/ci_hdrc_msm.c
  76. 1 4
      drivers/usb/chipidea/ci_hdrc_pci.c
  77. 1 4
      drivers/usb/chipidea/ci_hdrc_tegra.c
  78. 1 4
      drivers/usb/chipidea/ci_hdrc_usb2.c
  79. 1 5
      drivers/usb/chipidea/ci_hdrc_zevio.c
  80. 1 4
      drivers/usb/chipidea/core.c
  81. 1 13
      drivers/usb/chipidea/host.c
  82. 1 4
      drivers/usb/chipidea/otg.c
  83. 1 4
      drivers/usb/chipidea/otg.h
  84. 1 4
      drivers/usb/chipidea/otg_fsm.c
  85. 1 4
      drivers/usb/chipidea/otg_fsm.h
  86. 5 4
      drivers/usb/chipidea/udc.c
  87. 1 4
      drivers/usb/chipidea/udc.h
  88. 1 9
      drivers/usb/chipidea/ulpi.c
  89. 1 7
      drivers/usb/chipidea/usbmisc_imx.c
  90. 1 0
      drivers/usb/class/Makefile
  91. 1 14
      drivers/usb/class/cdc-acm.c
  92. 1 0
      drivers/usb/class/cdc-wdm.c
  93. 1 16
      drivers/usb/class/usblp.c
  94. 2 13
      drivers/usb/class/usbtmc.c
  95. 1 4
      drivers/usb/common/common.c
  96. 1 5
      drivers/usb/common/led.c
  97. 1 4
      drivers/usb/common/ulpi.c
  98. 1 14
      drivers/usb/common/usb-otg-fsm.c
  99. 1 1
      drivers/usb/core/buffer.c
  100. 1 1
      drivers/usb/core/config.c

+ 43 - 0
Documentation/devicetree/bindings/phy/brcm,brcmstb-usb-phy.txt

@@ -0,0 +1,43 @@
+Broadcom STB USB PHY
+
+Required properties:
+ - compatible: brcm,brcmstb-usb-phy
+ - reg: two offset and length pairs.
+	The first pair specifies a manditory set of memory mapped
+	registers used for general control of the PHY.
+	The second pair specifies optional registers used by some of
+	the SoCs that support USB 3.x
+ - #phy-cells: Shall be 1 as it expects one argument for setting
+	       the type of the PHY. Possible values are:
+	       - PHY_TYPE_USB2 for USB1.1/2.0 PHY
+	       - PHY_TYPE_USB3 for USB3.x PHY
+
+Optional Properties:
+- clocks : clock phandles.
+- clock-names: String, clock name.
+- brcm,ipp: Boolean, Invert Port Power.
+  Possible values are: 0 (Don't invert), 1 (Invert)
+- brcm,ioc: Boolean, Invert Over Current detection.
+  Possible values are: 0 (Don't invert), 1 (Invert)
+NOTE: one or both of the following two properties must be set
+- brcm,has-xhci: Boolean indicating the phy has an XHCI phy.
+- brcm,has-eohci: Boolean indicating the phy has an EHCI/OHCI phy.
+- dr_mode: String, PHY Device mode.
+  Possible values are: "host", "peripheral ", "drd" or "typec-pd"
+  If this property is not defined, the phy will default to "host" mode.
+
+Example:
+
+usbphy_0: usb-phy@f0470200 {
+	reg = <0xf0470200 0xb8>,
+		<0xf0471940 0x6c0>;
+	compatible = "brcm,brcmstb-usb-phy";
+	#phy-cells = <1>;
+	dr_mode = "host"
+	brcm,ioc = <1>;
+	brcm,ipp = <1>;
+	brcm,has-xhci;
+	brcm,has-eohci;
+	clocks = <&usb20>, <&usb30>;
+	clock-names = "sw_usb", "sw_usb3";
+};

+ 10 - 1
Documentation/devicetree/bindings/phy/brcm-sata-phy.txt

@@ -27,7 +27,16 @@ Sub-nodes optional properties:
      This property is not applicable for "brcm,iproc-ns2-sata-phy",
      "brcm,iproc-nsp-sata-phy" and "brcm,iproc-sr-sata-phy".
 
-Example:
+- brcm,rxaeq-mode: string that indicates the desired RX equalizer
+  mode, possible values are:
+	"off" (equivalent to not specifying the property)
+	"auto"
+	"manual" (brcm,rxaeq-value is used in that case)
+
+- brcm,rxaeq-value: when 'rxaeq-mode' is set to "manual", provides the RX
+  equalizer value that should be used. Allowed range is 0..63.
+
+Example
 	sata-phy@f0458100 {
 		compatible = "brcm,bcm7445-sata-phy", "brcm,phy-sata3";
 		reg = <0xf0458100 0x1e00>, <0xf045804c 0x10>;

+ 5 - 2
Documentation/devicetree/bindings/phy/rcar-gen2-phy.txt

@@ -4,10 +4,13 @@ This file provides information on what the device node for the R-Car generation
 2 USB PHY contains.
 
 Required properties:
-- compatible: "renesas,usb-phy-r8a7790" if the device is a part of R8A7790 SoC.
+- compatible: "renesas,usb-phy-r8a7743" if the device is a part of R8A7743 SoC.
+	      "renesas,usb-phy-r8a7745" if the device is a part of R8A7745 SoC.
+	      "renesas,usb-phy-r8a7790" if the device is a part of R8A7790 SoC.
 	      "renesas,usb-phy-r8a7791" if the device is a part of R8A7791 SoC.
 	      "renesas,usb-phy-r8a7794" if the device is a part of R8A7794 SoC.
-	      "renesas,rcar-gen2-usb-phy" for a generic R-Car Gen2 compatible device.
+	      "renesas,rcar-gen2-usb-phy" for a generic R-Car Gen2 or
+					  RZ/G1 compatible device.
 
 	      When compatible with the generic version, nodes must list the
 	      SoC-specific version corresponding to the platform first

+ 2 - 0
Documentation/devicetree/bindings/phy/rcar-gen3-phy-usb2.txt

@@ -8,6 +8,8 @@ Required properties:
 	      SoC.
 	      "renesas,usb2-phy-r8a7796" if the device is a part of an R8A7796
 	      SoC.
+	      "renesas,usb2-phy-r8a77995" if the device is a part of an
+	      R8A77995 SoC.
 	      "renesas,rcar-gen3-usb2-phy" for a generic R-Car Gen3 compatible device.
 
 	      When compatible with the generic version, nodes must list the

+ 2 - 0
Documentation/devicetree/bindings/usb/dwc2.txt

@@ -19,6 +19,8 @@ Required properties:
   configured in FS mode;
   - "st,stm32f4x9-hsotg": The DWC2 USB HS controller instance in STM32F4x9 SoCs
   configured in HS mode;
+  - "st,stm32f7xx-hsotg": The DWC2 USB HS controller instance in STM32F7xx SoCs
+    configured in HS mode;
 - reg : Should contain 1 register range (address and length)
 - interrupts : Should contain 1 interrupt
 - clocks: clock provider specifier

+ 26 - 0
Documentation/devicetree/bindings/usb/maxim,max3421.txt

@@ -0,0 +1,26 @@
+Maxim Integrated SPI-based USB 2.0 host controller MAX3421E
+
+Required properties:
+ - compatible: Should be "maxim,max3421"
+ - spi-max-frequency: maximum frequency for this device must not exceed 26 MHz.
+ - reg: chip select number to which this device is connected.
+ - maxim,vbus-en-pin: <GPOUTx ACTIVE_LEVEL>
+   GPOUTx is the number (1-8) of the GPOUT pin of MAX3421E to drive Vbus.
+   ACTIVE_LEVEL is 0 or 1.
+ - interrupts: the interrupt line description for the interrupt controller.
+   The driver configures MAX3421E for active low level triggered interrupts,
+   configure your interrupt line accordingly.
+
+Optional property:
+ - interrupt-parent: the phandle to the associated interrupt controller.
+
+Example:
+
+	usb@0 {
+		compatible = "maxim,max3421";
+		reg = <0>;
+		maxim,vbus-en-pin = <3 1>;
+		spi-max-frequency = <26000000>;
+		interrupt-parent = <&PIC>;
+		interrupts = <42>;
+	};

+ 10 - 10
Documentation/devicetree/bindings/usb/mediatek,mtk-xhci.txt

@@ -26,10 +26,11 @@ Required properties:
  - clocks : a list of phandle + clock-specifier pairs, one for each
 	entry in clock-names
  - clock-names : must contain
-	"sys_ck": for clock of xHCI MAC
-	"ref_ck": for reference clock of xHCI MAC
-	"wakeup_deb_p0": for USB wakeup debounce clock of port0
-	"wakeup_deb_p1": for USB wakeup debounce clock of port1
+	"sys_ck": controller clock used by normal mode,
+	the following ones are optional:
+	"ref_ck": reference clock used by low power mode etc,
+	"mcu_ck": mcu_bus clock for register access,
+	"dma_ck": dma_bus clock for data transfer by DMA
 
  - phys : a list of phandle + phy specifier pairs
 
@@ -38,6 +39,8 @@ Optional properties:
 	mode;
  - mediatek,syscon-wakeup : phandle to syscon used to access USB wakeup
 	control register, it depends on "mediatek,wakeup-src".
+ - mediatek,u3p-dis-msk : mask to disable u3ports, bit0 for u3port0,
+	bit1 for u3port1, ... etc;
  - vbus-supply : reference to the VBUS regulator;
  - usb3-lpm-capable : supports USB3.0 LPM
  - pinctrl-names : a pinctrl state named "default" must be defined
@@ -55,9 +58,7 @@ usb30: usb@11270000 {
 	clocks = <&topckgen CLK_TOP_USB30_SEL>, <&clk26m>,
 		 <&pericfg CLK_PERI_USB0>,
 		 <&pericfg CLK_PERI_USB1>;
-	clock-names = "sys_ck", "ref_ck",
-		      "wakeup_deb_p0",
-		      "wakeup_deb_p1";
+	clock-names = "sys_ck", "ref_ck";
 	phys = <&phy_port0 PHY_TYPE_USB3>,
 	       <&phy_port1 PHY_TYPE_USB2>;
 	vusb33-supply = <&mt6397_vusb_reg>;
@@ -89,9 +90,8 @@ Required properties:
 
  - clocks : a list of phandle + clock-specifier pairs, one for each
 	entry in clock-names
- - clock-names : must be
-	"sys_ck": for clock of xHCI MAC
-	"ref_ck": for reference clock of xHCI MAC
+ - clock-names : must contain "sys_ck", and the following ones are optional:
+	"ref_ck", "mcu_ck" and "dma_ck"
 
 Optional properties:
  - vbus-supply : reference to the VBUS regulator;

+ 10 - 9
Documentation/devicetree/bindings/usb/mediatek,mtu3.txt

@@ -14,9 +14,9 @@ Required properties:
  - vusb33-supply : regulator of USB avdd3.3v
  - clocks : a list of phandle + clock-specifier pairs, one for each
 	entry in clock-names
- - clock-names : must contain "sys_ck" and "ref_ck" for clock of controller;
-	"wakeup_deb_p0" and "wakeup_deb_p1" are optional, they are
-	depends on "mediatek,enable-wakeup"
+ - clock-names : must contain "sys_ck" for clock of controller,
+	the following clocks are optional:
+	"ref_ck", "mcu_ck" and "dam_ck";
  - phys : a list of phandle + phy specifier pairs
  - dr_mode : should be one of "host", "peripheral" or "otg",
 	refer to usb/generic.txt
@@ -30,9 +30,10 @@ Optional properties:
 	when supports dual-role mode.
  - vbus-supply : reference to the VBUS regulator, needed when supports
 	dual-role mode.
- - pinctl-names : a pinctrl state named "default" must be defined,
-	"id_float" and "id_ground" are optinal which depends on
-	"mediatek,enable-manual-drd"
+ - pinctrl-names : a pinctrl state named "default" is optional, and need be
+	defined if auto drd switch is enabled, that means the property dr_mode
+	is set as "otg", and meanwhile the property "mediatek,enable-manual-drd"
+	is not set.
  - pinctrl-0 : pin control group
 	See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
 
@@ -44,6 +45,8 @@ Optional properties:
  - mediatek,enable-wakeup : supports ip sleep wakeup used by host mode
  - mediatek,syscon-wakeup : phandle to syscon used to access USB wakeup
 	control register, it depends on "mediatek,enable-wakeup".
+ - mediatek,u3p-dis-msk : mask to disable u3ports, bit0 for u3port0,
+	bit1 for u3port1, ... etc;
 
 Sub-nodes:
 The xhci should be added as subnode to mtu3 as shown in the following example
@@ -63,9 +66,7 @@ ssusb: usb@11271000 {
 	clocks = <&topckgen CLK_TOP_USB30_SEL>, <&clk26m>,
 		 <&pericfg CLK_PERI_USB0>,
 		 <&pericfg CLK_PERI_USB1>;
-	clock-names = "sys_ck", "ref_ck",
-		      "wakeup_deb_p0",
-		      "wakeup_deb_p1";
+	clock-names = "sys_ck", "ref_ck";
 	vusb33-supply = <&mt6397_vusb_reg>;
 	vbus-supply = <&usb_p0_vbus>;
 	extcon = <&extcon_usb>;

+ 4 - 0
Documentation/devicetree/bindings/usb/renesas_usb3.txt

@@ -15,6 +15,10 @@ Required properties:
   - interrupts: Interrupt specifier for the USB3.0 Peripheral
   - clocks: clock phandle and specifier pair
 
+Optional properties:
+  - phys: phandle + phy specifier pair
+  - phy-names: must be "usb"
+
 Example of R-Car H3 ES1.x:
 	usb3_peri0: usb@ee020000 {
 		compatible = "renesas,r8a7795-usb3-peri",

+ 4 - 1
Documentation/devicetree/bindings/usb/renesas_usbhs.txt

@@ -3,6 +3,8 @@ Renesas Electronics USBHS driver
 Required properties:
   - compatible: Must contain one or more of the following:
 
+	- "renesas,usbhs-r8a7743" for r8a7743 (RZ/G1M) compatible device
+	- "renesas,usbhs-r8a7745" for r8a7745 (RZ/G1E) compatible device
 	- "renesas,usbhs-r8a7790" for r8a7790 (R-Car H2) compatible device
 	- "renesas,usbhs-r8a7791" for r8a7791 (R-Car M2-W) compatible device
 	- "renesas,usbhs-r8a7792" for r8a7792 (R-Car V2H) compatible device
@@ -10,7 +12,8 @@ Required properties:
 	- "renesas,usbhs-r8a7794" for r8a7794 (R-Car E2) compatible device
 	- "renesas,usbhs-r8a7795" for r8a7795 (R-Car H3) compatible device
 	- "renesas,usbhs-r8a7796" for r8a7796 (R-Car M3-W) compatible device
-	- "renesas,rcar-gen2-usbhs" for R-Car Gen2 compatible device
+	- "renesas,usbhs-r8a77995" for r8a77995 (R-Car D3) compatible device
+	- "renesas,rcar-gen2-usbhs" for R-Car Gen2 or RZ/G1 compatible devices
 	- "renesas,rcar-gen3-usbhs" for R-Car Gen3 compatible device
 
 	When compatible with the generic version, nodes must list the

+ 1 - 0
Documentation/devicetree/bindings/usb/usb-xhci.txt

@@ -26,6 +26,7 @@ Required properties:
 
 Optional properties:
   - clocks: reference to a clock
+  - usb2-lpm-disable: indicate if we don't want to enable USB2 HW LPM
   - usb3-lpm-capable: determines if platform is USB3 LPM capable
   - quirk-broken-port-ped: set if the controller has broken port disable mechanism
 

+ 32 - 14
Documentation/devicetree/bindings/usb/usb251xb.txt

@@ -1,16 +1,17 @@
 Microchip USB 2.0 Hi-Speed Hub Controller
 
-The device node for the configuration of a Microchip USB251xB/xBi USB 2.0
+The device node for the configuration of a Microchip USB251x/xBi USB 2.0
 Hi-Speed Controller.
 
 Required properties :
  - compatible : Should be "microchip,usb251xb" or one of the specific types:
 	"microchip,usb2512b", "microchip,usb2512bi", "microchip,usb2513b",
-	"microchip,usb2513bi", "microchip,usb2514b", "microchip,usb2514bi"
- - reset-gpios : Should specify the gpio for hub reset
+	"microchip,usb2513bi", "microchip,usb2514b", "microchip,usb2514bi",
+	"microchip,usb2517", "microchip,usb2517i"
  - reg : I2C address on the selected bus (default is <0x2C>)
 
 Optional properties :
+ - reset-gpios : Should specify the gpio for hub reset
  - skip-config : Skip Hub configuration, but only send the USB-Attach command
  - vendor-id : Set USB Vendor ID of the hub (16 bit, default is 0x0424)
  - product-id : Set USB Product ID of the hub (16 bit, default depends on type)
@@ -19,29 +20,47 @@ Optional properties :
  - manufacturer : Set USB Manufacturer string (max 31 characters long)
  - product : Set USB Product string (max 31 characters long)
  - serial : Set USB Serial string (max 31 characters long)
- - {bus,self}-powered : selects between self- and bus-powered operation (default
-	is self-powered)
- - disable-hi-speed : disable USB Hi-Speed support
+ - {bus,self}-powered : selects between self- and bus-powered operation
+	(boolean, default is self-powered)
+ - disable-hi-speed : disable USB Hi-Speed support (boolean)
  - {multi,single}-tt : selects between multi- and single-transaction-translator
-	(default is multi-tt)
- - disable-eop : disable End of Packet generation in full-speed mode
+	(boolean, default is multi-tt)
+ - disable-eop : disable End of Packet generation in full-speed mode (boolean)
  - {ganged,individual}-sensing : select over-current sense type in self-powered
-	mode (default is individual)
+	mode (boolean, default is individual)
  - {ganged,individual}-port-switching : select port power switching mode
-	(default is individual)
+	(boolean, default is individual)
  - dynamic-power-switching : enable auto-switching from self- to bus-powered
-	operation if the local power source is removed or unavailable
+	operation if the local power source is removed or unavailable (boolean)
  - oc-delay-us : Delay time (in microseconds) for filtering the over-current
 	sense inputs. Valid values are 100, 4000, 8000 (default) and 16000. If
 	an invalid value is given, the default is used instead.
- - compound-device : indicate the hub is part of a compound device
- - port-mapping-mode : enable port mapping mode
+ - compound-device : indicate the hub is part of a compound device (boolean)
+ - port-mapping-mode : enable port mapping mode (boolean)
+ - led-{usb,speed}-mode : led usb/speed indication mode selection
+	(boolean, default is speed mode)
  - string-support : enable string descriptor support (required for manufacturer,
 	product and serial string configuration)
  - non-removable-ports : Should specify the ports which have a non-removable
 	device connected.
  - sp-disabled-ports : Specifies the ports which will be self-power disabled
  - bp-disabled-ports : Specifies the ports which will be bus-power disabled
+ - sp-max-total-current-microamp: Specifies max current consumed by the hub
+	from VBUS when operating in self-powered hub. It includes the hub
+	silicon along with all associated circuitry including a permanently
+	attached peripheral (range: 0 - 100000 uA, default 1000 uA)
+ - bp-max-total-current-microamp: Specifies max current consumed by the hub
+	from VBUS when operating in self-powered hub. It includes the hub
+	silicon along with all associated circuitry including a permanently
+	attached peripheral (range: 0 - 510000 uA, default 100000 uA)
+ - sp-max-removable-current-microamp: Specifies max current consumed by the hub
+	from VBUS when operating in self-powered hub. It includes the hub
+	silicon along with all associated circuitry excluding a permanently
+	attached peripheral (range: 0 - 100000 uA, default 1000 uA)
+ - bp-max-removable-current-microamp: Specifies max current consumed by the hub
+	from VBUS when operating in self-powered hub. It includes the hub
+	silicon along with all associated circuitry excluding a permanently
+	attached peripheral (range: 0 - 510000 uA, default 100000 uA)
  - power-on-time-ms : Specifies the time it takes from the time the host
 	initiates the power-on sequence to a port until the port has adequate
 	power. The value is given in ms in a 0 - 510 range (default is 100ms).
@@ -56,7 +75,6 @@ Examples:
 	usb2514b@2c {
 		compatible = "microchip,usb2514b";
 		reg = <0x2c>;
-		reset-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
 		vendor-id = /bits/ 16 <0x0000>;
 		product-id = /bits/ 16 <0x0000>;
 		string-support;

+ 7 - 0
MAINTAINERS

@@ -2896,6 +2896,13 @@ S:	Supported
 F:	drivers/gpio/gpio-brcmstb.c
 F:	Documentation/devicetree/bindings/gpio/brcm,brcmstb-gpio.txt
 
+BROADCOM BRCMSTB USB2 and USB3 PHY DRIVER
+M:	Al Cooper <alcooperx@gmail.com>
+L:	linux-kernel@vger.kernel.org
+L:	bcm-kernel-feedback-list@broadcom.com
+S:	Maintained
+F:	drivers/phy/broadcom/phy-brcm-usb*
+
 BROADCOM GENET ETHERNET DRIVER
 M:	Florian Fainelli <f.fainelli@gmail.com>
 L:	netdev@vger.kernel.org

+ 1 - 1
drivers/extcon/extcon-adc-jack.c

@@ -26,7 +26,7 @@
 #include <linux/workqueue.h>
 #include <linux/iio/consumer.h>
 #include <linux/extcon/extcon-adc-jack.h>
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
 
 /**
  * struct adc_jack_data - internal data for adc_jack device driver

+ 1 - 1
drivers/extcon/extcon-arizona.c

@@ -27,7 +27,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/property.h>
 #include <linux/regulator/consumer.h>
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
 
 #include <sound/soc.h>
 

+ 1 - 1
drivers/extcon/extcon-axp288.c

@@ -22,7 +22,7 @@
 #include <linux/platform_device.h>
 #include <linux/property.h>
 #include <linux/notifier.h>
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
 #include <linux/regmap.h>
 #include <linux/gpio.h>
 #include <linux/gpio/consumer.h>

+ 1 - 1
drivers/extcon/extcon-gpio.c

@@ -17,7 +17,7 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
 #include <linux/extcon/extcon-gpio.h>
 #include <linux/gpio.h>
 #include <linux/gpio/consumer.h>

+ 1 - 1
drivers/extcon/extcon-intel-cht-wc.c

@@ -15,7 +15,7 @@
  * more details.
  */
 
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/mfd/intel_soc_pmic.h>

+ 1 - 1
drivers/extcon/extcon-intel-int3496.c

@@ -19,7 +19,7 @@
  */
 
 #include <linux/acpi.h>
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
 #include <linux/gpio.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>

+ 2 - 2
drivers/extcon/extcon-max14577.c

@@ -23,7 +23,7 @@
 #include <linux/platform_device.h>
 #include <linux/mfd/max14577.h>
 #include <linux/mfd/max14577-private.h>
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
 
 #define	DELAY_MS_DEFAULT		17000		/* unit: millisecond */
 
@@ -204,8 +204,8 @@ static int max14577_muic_set_debounce_time(struct max14577_muic_info *info,
 static int max14577_muic_set_path(struct max14577_muic_info *info,
 		u8 val, bool attached)
 {
-	int ret = 0;
 	u8 ctrl1, ctrl2 = 0;
+	int ret;
 
 	/* Set open state to path before changing hw path */
 	ret = max14577_update_reg(info->max14577->regmap,

+ 1 - 1
drivers/extcon/extcon-max3355.c

@@ -9,7 +9,7 @@
  * may be copied, distributed, and modified under those terms.
  */
 
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
 #include <linux/gpio.h>
 #include <linux/gpio/consumer.h>
 #include <linux/interrupt.h>

+ 1 - 1
drivers/extcon/extcon-max77693.c

@@ -26,7 +26,7 @@
 #include <linux/mfd/max77693.h>
 #include <linux/mfd/max77693-common.h>
 #include <linux/mfd/max77693-private.h>
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
 #include <linux/regmap.h>
 #include <linux/irqdomain.h>
 

+ 80 - 15
drivers/extcon/extcon-max77843.c

@@ -11,7 +11,7 @@
  * (at your option) any later version.
  */
 
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
@@ -80,7 +80,7 @@ enum max77843_muic_accessory_type {
 	MAX77843_MUIC_ADC_REMOTE_S12_BUTTON,
 	MAX77843_MUIC_ADC_RESERVED_ACC_1,
 	MAX77843_MUIC_ADC_RESERVED_ACC_2,
-	MAX77843_MUIC_ADC_RESERVED_ACC_3,
+	MAX77843_MUIC_ADC_RESERVED_ACC_3, /* SmartDock */
 	MAX77843_MUIC_ADC_RESERVED_ACC_4,
 	MAX77843_MUIC_ADC_RESERVED_ACC_5,
 	MAX77843_MUIC_ADC_AUDIO_DEVICE_TYPE2,
@@ -119,6 +119,7 @@ enum max77843_muic_charger_type {
 	MAX77843_MUIC_CHG_SPECIAL_BIAS,
 	MAX77843_MUIC_CHG_RESERVED,
 	MAX77843_MUIC_CHG_GND,
+	MAX77843_MUIC_CHG_DOCK,
 };
 
 static const unsigned int max77843_extcon_cable[] = {
@@ -130,6 +131,7 @@ static const unsigned int max77843_extcon_cable[] = {
 	EXTCON_CHG_USB_FAST,
 	EXTCON_CHG_USB_SLOW,
 	EXTCON_DISP_MHL,
+	EXTCON_DOCK,
 	EXTCON_JIG,
 	EXTCON_NONE,
 };
@@ -200,7 +202,7 @@ static const struct regmap_irq_chip max77843_muic_irq_chip = {
 };
 
 static int max77843_muic_set_path(struct max77843_muic_info *info,
-		u8 val, bool attached)
+		u8 val, bool attached, bool nobccomp)
 {
 	struct max77693_dev *max77843 = info->max77843;
 	int ret = 0;
@@ -210,10 +212,16 @@ static int max77843_muic_set_path(struct max77843_muic_info *info,
 		ctrl1 = val;
 	else
 		ctrl1 = MAX77843_MUIC_CONTROL1_SW_OPEN;
+	if (nobccomp) {
+		/* Disable BC1.2 protocol and force manual switch control */
+		ctrl1 |= MAX77843_MUIC_CONTROL1_NOBCCOMP_MASK;
+	}
 
 	ret = regmap_update_bits(max77843->regmap_muic,
 			MAX77843_MUIC_REG_CONTROL1,
-			MAX77843_MUIC_CONTROL1_COM_SW, ctrl1);
+			MAX77843_MUIC_CONTROL1_COM_SW |
+				MAX77843_MUIC_CONTROL1_NOBCCOMP_MASK,
+			ctrl1);
 	if (ret < 0) {
 		dev_err(info->dev, "Cannot switch MUIC port\n");
 		return ret;
@@ -240,6 +248,21 @@ static int max77843_muic_set_path(struct max77843_muic_info *info,
 	return 0;
 }
 
+static void max77843_charger_set_otg_vbus(struct max77843_muic_info *info,
+		 bool on)
+{
+	struct max77693_dev *max77843 = info->max77843;
+	unsigned int cnfg00;
+
+	if (on)
+		cnfg00 = MAX77843_CHG_OTG_MASK | MAX77843_CHG_BOOST_MASK;
+	else
+		cnfg00 = MAX77843_CHG_ENABLE | MAX77843_CHG_BUCK_MASK;
+
+	regmap_update_bits(max77843->regmap_chg, MAX77843_CHG_REG_CHG_CNFG_00,
+			   MAX77843_CHG_MODE_MASK, cnfg00);
+}
+
 static int max77843_muic_get_cable_type(struct max77843_muic_info *info,
 		enum max77843_muic_cable_group group, bool *attached)
 {
@@ -288,6 +311,19 @@ static int max77843_muic_get_cable_type(struct max77843_muic_info *info,
 			break;
 		}
 
+		if (adc == MAX77843_MUIC_ADC_RESERVED_ACC_3) { /* SmartDock */
+			if (chg_type == MAX77843_MUIC_CHG_NONE) {
+				*attached = false;
+				cable_type = info->prev_chg_type;
+				info->prev_chg_type = MAX77843_MUIC_CHG_NONE;
+			} else {
+				*attached = true;
+				cable_type = MAX77843_MUIC_CHG_DOCK;
+				info->prev_chg_type = MAX77843_MUIC_CHG_DOCK;
+			}
+			break;
+		}
+
 		if (chg_type == MAX77843_MUIC_CHG_NONE) {
 			*attached = false;
 			cable_type = info->prev_chg_type;
@@ -350,17 +386,18 @@ static int max77843_muic_adc_gnd_handler(struct max77843_muic_info *info)
 	case MAX77843_MUIC_GND_USB_HOST_VB:
 		ret = max77843_muic_set_path(info,
 					     MAX77843_MUIC_CONTROL1_SW_USB,
-					     attached);
+					     attached, false);
 		if (ret < 0)
 			return ret;
 
 		extcon_set_state_sync(info->edev, EXTCON_USB_HOST, attached);
+		max77843_charger_set_otg_vbus(info, attached);
 		break;
 	case MAX77843_MUIC_GND_MHL_VB:
 	case MAX77843_MUIC_GND_MHL:
 		ret = max77843_muic_set_path(info,
 					     MAX77843_MUIC_CONTROL1_SW_OPEN,
-					     attached);
+					     attached, false);
 		if (ret < 0)
 			return ret;
 
@@ -396,7 +433,7 @@ static int max77843_muic_jig_handler(struct max77843_muic_info *info,
 		return -EINVAL;
 	}
 
-	ret = max77843_muic_set_path(info, path, attached);
+	ret = max77843_muic_set_path(info, path, attached, false);
 	if (ret < 0)
 		return ret;
 
@@ -405,6 +442,26 @@ static int max77843_muic_jig_handler(struct max77843_muic_info *info,
 	return 0;
 }
 
+static int max77843_muic_dock_handler(struct max77843_muic_info *info,
+		bool attached)
+{
+	int ret;
+
+	dev_dbg(info->dev, "external connector is %s (adc: 0x10)\n",
+			attached ? "attached" : "detached");
+
+	ret = max77843_muic_set_path(info, MAX77843_MUIC_CONTROL1_SW_USB,
+				     attached, attached);
+	if (ret < 0)
+		return ret;
+
+	extcon_set_state_sync(info->edev, EXTCON_DISP_MHL, attached);
+	extcon_set_state_sync(info->edev, EXTCON_USB_HOST, attached);
+	extcon_set_state_sync(info->edev, EXTCON_DOCK, attached);
+
+	return 0;
+}
+
 static int max77843_muic_adc_handler(struct max77843_muic_info *info)
 {
 	int ret, cable_type;
@@ -419,6 +476,11 @@ static int max77843_muic_adc_handler(struct max77843_muic_info *info)
 		info->prev_cable_type);
 
 	switch (cable_type) {
+	case MAX77843_MUIC_ADC_RESERVED_ACC_3: /* SmartDock */
+		ret = max77843_muic_dock_handler(info, attached);
+		if (ret < 0)
+			return ret;
+		break;
 	case MAX77843_MUIC_ADC_GROUND:
 		ret = max77843_muic_adc_gnd_handler(info);
 		if (ret < 0)
@@ -446,7 +508,6 @@ static int max77843_muic_adc_handler(struct max77843_muic_info *info)
 	case MAX77843_MUIC_ADC_REMOTE_S12_BUTTON:
 	case MAX77843_MUIC_ADC_RESERVED_ACC_1:
 	case MAX77843_MUIC_ADC_RESERVED_ACC_2:
-	case MAX77843_MUIC_ADC_RESERVED_ACC_3:
 	case MAX77843_MUIC_ADC_RESERVED_ACC_4:
 	case MAX77843_MUIC_ADC_RESERVED_ACC_5:
 	case MAX77843_MUIC_ADC_AUDIO_DEVICE_TYPE2:
@@ -490,7 +551,7 @@ static int max77843_muic_chg_handler(struct max77843_muic_info *info)
 	case MAX77843_MUIC_CHG_USB:
 		ret = max77843_muic_set_path(info,
 					     MAX77843_MUIC_CONTROL1_SW_USB,
-					     attached);
+					     attached, false);
 		if (ret < 0)
 			return ret;
 
@@ -501,7 +562,7 @@ static int max77843_muic_chg_handler(struct max77843_muic_info *info)
 	case MAX77843_MUIC_CHG_DOWNSTREAM:
 		ret = max77843_muic_set_path(info,
 					     MAX77843_MUIC_CONTROL1_SW_OPEN,
-					     attached);
+					     attached, false);
 		if (ret < 0)
 			return ret;
 
@@ -511,7 +572,7 @@ static int max77843_muic_chg_handler(struct max77843_muic_info *info)
 	case MAX77843_MUIC_CHG_DEDICATED:
 		ret = max77843_muic_set_path(info,
 					     MAX77843_MUIC_CONTROL1_SW_OPEN,
-					     attached);
+					     attached, false);
 		if (ret < 0)
 			return ret;
 
@@ -521,7 +582,7 @@ static int max77843_muic_chg_handler(struct max77843_muic_info *info)
 	case MAX77843_MUIC_CHG_SPECIAL_500MA:
 		ret = max77843_muic_set_path(info,
 					     MAX77843_MUIC_CONTROL1_SW_OPEN,
-					     attached);
+					     attached, false);
 		if (ret < 0)
 			return ret;
 
@@ -531,7 +592,7 @@ static int max77843_muic_chg_handler(struct max77843_muic_info *info)
 	case MAX77843_MUIC_CHG_SPECIAL_1A:
 		ret = max77843_muic_set_path(info,
 					     MAX77843_MUIC_CONTROL1_SW_OPEN,
-					     attached);
+					     attached, false);
 		if (ret < 0)
 			return ret;
 
@@ -550,6 +611,9 @@ static int max77843_muic_chg_handler(struct max77843_muic_info *info)
 			extcon_set_state_sync(info->edev, EXTCON_CHG_USB_DCP,
 						false);
 		break;
+	case MAX77843_MUIC_CHG_DOCK:
+		extcon_set_state_sync(info->edev, EXTCON_CHG_USB_DCP, attached);
+		break;
 	case MAX77843_MUIC_CHG_NONE:
 		break;
 	default:
@@ -558,7 +622,7 @@ static int max77843_muic_chg_handler(struct max77843_muic_info *info)
 			attached ? "attached" : "detached", chg_type);
 
 		max77843_muic_set_path(info, MAX77843_MUIC_CONTROL1_SW_OPEN,
-				       attached);
+				       attached, false);
 		return -EINVAL;
 	}
 
@@ -798,7 +862,8 @@ static int max77843_muic_probe(struct platform_device *pdev)
 	max77843_muic_set_debounce_time(info, MAX77843_DEBOUNCE_TIME_25MS);
 
 	/* Set initial path for UART */
-	max77843_muic_set_path(info, MAX77843_MUIC_CONTROL1_SW_UART, true);
+	max77843_muic_set_path(info, MAX77843_MUIC_CONTROL1_SW_UART, true,
+			       false);
 
 	/* Check revision number of MUIC device */
 	ret = regmap_read(max77843->regmap_muic, MAX77843_MUIC_REG_ID, &id);

+ 1 - 1
drivers/extcon/extcon-max8997.c

@@ -25,7 +25,7 @@
 #include <linux/kobject.h>
 #include <linux/mfd/max8997.h>
 #include <linux/mfd/max8997-private.h>
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
 #include <linux/irqdomain.h>
 
 #define	DEV_NAME			"max8997-muic"

+ 1 - 1
drivers/extcon/extcon-qcom-spmi-misc.c

@@ -15,7 +15,7 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>

+ 1 - 1
drivers/extcon/extcon-rt8973a.c

@@ -20,7 +20,7 @@
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
 #include <linux/slab.h>
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
 
 #include "extcon-rt8973a.h"
 

+ 1 - 1
drivers/extcon/extcon-sm5502.c

@@ -19,7 +19,7 @@
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
 #include <linux/slab.h>
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
 
 #include "extcon-sm5502.h"
 

+ 1 - 1
drivers/extcon/extcon-usb-gpio.c

@@ -14,7 +14,7 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
 #include <linux/gpio.h>
 #include <linux/gpio/consumer.h>
 #include <linux/init.h>

+ 1 - 1
drivers/extcon/extcon-usbc-cros-ec.c

@@ -14,7 +14,7 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
 #include <linux/kernel.h>
 #include <linux/mfd/cros_ec.h>
 #include <linux/module.h>

+ 1 - 1
drivers/extcon/extcon.c

@@ -36,7 +36,7 @@
 
 #define SUPPORTED_CABLE_MAX	32
 
-struct __extcon_info {
+static const struct __extcon_info {
 	unsigned int type;
 	unsigned int id;
 	const char *name;

+ 1 - 1
drivers/extcon/extcon.h

@@ -2,7 +2,7 @@
 #ifndef __LINUX_EXTCON_INTERNAL_H__
 #define __LINUX_EXTCON_INTERNAL_H__
 
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
 
 /**
  * struct extcon_dev - An extcon device represents one external connector.

+ 16 - 0
drivers/pci/dwc/pci-dra7xx.c

@@ -11,6 +11,7 @@
  */
 
 #include <linux/delay.h>
+#include <linux/device.h>
 #include <linux/err.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
@@ -594,6 +595,7 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
 	int i;
 	int phy_count;
 	struct phy **phy;
+	struct device_link **link;
 	void __iomem *base;
 	struct resource *res;
 	struct dw_pcie *pci;
@@ -649,11 +651,21 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
 	if (!phy)
 		return -ENOMEM;
 
+	link = devm_kzalloc(dev, sizeof(*link) * phy_count, GFP_KERNEL);
+	if (!link)
+		return -ENOMEM;
+
 	for (i = 0; i < phy_count; i++) {
 		snprintf(name, sizeof(name), "pcie-phy%d", i);
 		phy[i] = devm_phy_get(dev, name);
 		if (IS_ERR(phy[i]))
 			return PTR_ERR(phy[i]);
+
+		link[i] = device_link_add(dev, &phy[i]->dev, DL_FLAG_STATELESS);
+		if (!link[i]) {
+			ret = -EINVAL;
+			goto err_link;
+		}
 	}
 
 	dra7xx->base = base;
@@ -732,6 +744,10 @@ err_get_sync:
 	pm_runtime_disable(dev);
 	dra7xx_pcie_disable_phy(dra7xx);
 
+err_link:
+	while (--i >= 0)
+		device_link_del(link[i]);
+
 	return ret;
 }
 

+ 2 - 1
drivers/phy/allwinner/phy-sun4i-usb.c

@@ -24,7 +24,7 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/err.h>
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
 #include <linux/io.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
@@ -926,6 +926,7 @@ static const struct sun4i_usb_phy_cfg sun8i_v3s_cfg = {
 	.phyctl_offset = REG_PHYCTL_A33,
 	.dedicated_clocks = true,
 	.enable_pmu_unk1 = true,
+	.phy0_dual_route = true,
 };
 
 static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = {

+ 13 - 0
drivers/phy/broadcom/Kconfig

@@ -67,3 +67,16 @@ config PHY_BRCM_SATA
 	help
 	  Enable this to support the Broadcom SATA PHY.
 	  If unsure, say N.
+
+config PHY_BRCM_USB
+	tristate "Broadcom STB USB PHY driver"
+	depends on ARCH_BRCMSTB
+	depends on OF
+	select GENERIC_PHY
+	select SOC_BRCMSTB
+	default ARCH_BRCMSTB
+	help
+	  Enable this to support the Broadcom STB USB PHY.
+	  This driver is required by the USB XHCI, EHCI and OHCI
+	  drivers.
+	  If unsure, say N.

+ 3 - 0
drivers/phy/broadcom/Makefile

@@ -6,3 +6,6 @@ obj-$(CONFIG_PHY_BCM_NS_USB3)		+= phy-bcm-ns-usb3.o
 obj-$(CONFIG_PHY_NS2_PCIE)		+= phy-bcm-ns2-pcie.o
 obj-$(CONFIG_PHY_NS2_USB_DRD)		+= phy-bcm-ns2-usbdrd.o
 obj-$(CONFIG_PHY_BRCM_SATA)		+= phy-brcm-sata.o
+obj-$(CONFIG_PHY_BRCM_USB)		+= phy-brcm-usb-dvr.o
+
+phy-brcm-usb-dvr-objs := phy-brcm-usb.o phy-brcm-usb-init.o

+ 1 - 1
drivers/phy/broadcom/phy-bcm-ns2-usbdrd.c

@@ -12,7 +12,7 @@
  */
 
 #include <linux/delay.h>
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
 #include <linux/gpio.h>
 #include <linux/gpio/consumer.h>
 #include <linux/init.h>

+ 73 - 1
drivers/phy/broadcom/phy-brcm-sata.c

@@ -49,11 +49,29 @@ enum brcm_sata_phy_version {
 	BRCM_SATA_PHY_IPROC_SR,
 };
 
+enum brcm_sata_phy_rxaeq_mode {
+	RXAEQ_MODE_OFF = 0,
+	RXAEQ_MODE_AUTO,
+	RXAEQ_MODE_MANUAL,
+};
+
+static enum brcm_sata_phy_rxaeq_mode rxaeq_to_val(const char *m)
+{
+	if (!strcmp(m, "auto"))
+		return RXAEQ_MODE_AUTO;
+	else if (!strcmp(m, "manual"))
+		return RXAEQ_MODE_MANUAL;
+	else
+		return RXAEQ_MODE_OFF;
+}
+
 struct brcm_sata_port {
 	int portnum;
 	struct phy *phy;
 	struct brcm_sata_phy *phy_priv;
 	bool ssc_en;
+	enum brcm_sata_phy_rxaeq_mode rxaeq_mode;
+	u32 rxaeq_val;
 };
 
 struct brcm_sata_phy {
@@ -93,6 +111,15 @@ enum sata_phy_regs {
 	TX_ACTRL0				= 0x80,
 	TX_ACTRL0_TXPOL_FLIP			= BIT(6),
 
+	AEQRX_REG_BANK_0			= 0xd0,
+	AEQ_CONTROL1				= 0x81,
+	AEQ_CONTROL1_ENABLE			= BIT(2),
+	AEQ_CONTROL1_FREEZE			= BIT(3),
+	AEQ_FRC_EQ				= 0x83,
+	AEQ_FRC_EQ_FORCE			= BIT(0),
+	AEQ_FRC_EQ_FORCE_VAL			= BIT(1),
+	AEQRX_REG_BANK_1			= 0xe0,
+
 	OOB_REG_BANK				= 0x150,
 	OOB1_REG_BANK				= 0x160,
 	OOB_CTRL1				= 0x80,
@@ -190,7 +217,7 @@ static u32 brcm_sata_phy_rd(void __iomem *pcb_base, u32 bank, u32 ofs)
 #define STB_FMAX_VAL_DEFAULT	0x3df
 #define STB_FMAX_VAL_SSC	0x83
 
-static int brcm_stb_sata_init(struct brcm_sata_port *port)
+static void brcm_stb_sata_ssc_init(struct brcm_sata_port *port)
 {
 	void __iomem *base = brcm_sata_pcb_base(port);
 	struct brcm_sata_phy *priv = port->phy_priv;
@@ -215,10 +242,47 @@ static int brcm_stb_sata_init(struct brcm_sata_port *port)
 
 	brcm_sata_phy_wr(base, TXPMD_REG_BANK, TXPMD_TX_FREQ_CTRL_CONTROL3,
 			  ~TXPMD_TX_FREQ_CTRL_CONTROL3_FMAX_MASK, tmp);
+}
+
+#define AEQ_FRC_EQ_VAL_SHIFT	2
+#define AEQ_FRC_EQ_VAL_MASK	0x3f
+
+static int brcm_stb_sata_rxaeq_init(struct brcm_sata_port *port)
+{
+	void __iomem *base = brcm_sata_pcb_base(port);
+	u32 tmp = 0, reg = 0;
+
+	switch (port->rxaeq_mode) {
+	case RXAEQ_MODE_OFF:
+		return 0;
+
+	case RXAEQ_MODE_AUTO:
+		reg = AEQ_CONTROL1;
+		tmp = AEQ_CONTROL1_ENABLE | AEQ_CONTROL1_FREEZE;
+		break;
+
+	case RXAEQ_MODE_MANUAL:
+		reg = AEQ_FRC_EQ;
+		tmp = AEQ_FRC_EQ_FORCE | AEQ_FRC_EQ_FORCE_VAL;
+		if (port->rxaeq_val > AEQ_FRC_EQ_VAL_MASK)
+			return -EINVAL;
+		tmp |= port->rxaeq_val << AEQ_FRC_EQ_VAL_SHIFT;
+		break;
+	}
+
+	brcm_sata_phy_wr(base, AEQRX_REG_BANK_0, reg, ~tmp, tmp);
+	brcm_sata_phy_wr(base, AEQRX_REG_BANK_1, reg, ~tmp, tmp);
 
 	return 0;
 }
 
+static int brcm_stb_sata_init(struct brcm_sata_port *port)
+{
+	brcm_stb_sata_ssc_init(port);
+
+	return brcm_stb_sata_rxaeq_init(port);
+}
+
 /* NS2 SATA PLL1 defaults were characterized by H/W group */
 #define NS2_PLL1_ACTRL2_MAGIC	0x1df8
 #define NS2_PLL1_ACTRL3_MAGIC	0x2b00
@@ -463,6 +527,7 @@ MODULE_DEVICE_TABLE(of, brcm_sata_phy_of_match);
 
 static int brcm_sata_phy_probe(struct platform_device *pdev)
 {
+	const char *rxaeq_mode;
 	struct device *dev = &pdev->dev;
 	struct device_node *dn = dev->of_node, *child;
 	const struct of_device_id *of_id;
@@ -525,6 +590,13 @@ static int brcm_sata_phy_probe(struct platform_device *pdev)
 		port->portnum = id;
 		port->phy_priv = priv;
 		port->phy = devm_phy_create(dev, child, &phy_ops);
+		port->rxaeq_mode = RXAEQ_MODE_OFF;
+		if (!of_property_read_string(child, "brcm,rxaeq-mode",
+					     &rxaeq_mode))
+			port->rxaeq_mode = rxaeq_to_val(rxaeq_mode);
+		if (port->rxaeq_mode == RXAEQ_MODE_MANUAL)
+			of_property_read_u32(child, "brcm,rxaeq-value",
+					     &port->rxaeq_val);
 		port->ssc_en = of_property_read_bool(child, "brcm,enable-ssc");
 		if (IS_ERR(port->phy)) {
 			dev_err(dev, "failed to create PHY\n");

+ 1017 - 0
drivers/phy/broadcom/phy-brcm-usb-init.c

@@ -0,0 +1,1017 @@
+/*
+ * phy-brcm-usb-init.c - Broadcom USB Phy chip specific init functions
+ *
+ * Copyright (C) 2014-2017 Broadcom
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+/*
+ * This module contains USB PHY initialization for power up and S3 resume
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include <linux/soc/brcmstb/brcmstb.h>
+#include "phy-brcm-usb-init.h"
+
+#define PHY_PORTS 2
+#define PHY_PORT_SELECT_0 0
+#define PHY_PORT_SELECT_1 0x1000
+
+/* Register definitions for the USB CTRL block */
+#define USB_CTRL_SETUP			0x00
+#define   USB_CTRL_SETUP_IOC_MASK			0x00000010
+#define   USB_CTRL_SETUP_IPP_MASK			0x00000020
+#define   USB_CTRL_SETUP_BABO_MASK			0x00000001
+#define   USB_CTRL_SETUP_FNHW_MASK			0x00000002
+#define   USB_CTRL_SETUP_FNBO_MASK			0x00000004
+#define   USB_CTRL_SETUP_WABO_MASK			0x00000008
+#define   USB_CTRL_SETUP_SCB_CLIENT_SWAP_MASK		0x00002000 /* option */
+#define   USB_CTRL_SETUP_SCB1_EN_MASK			0x00004000 /* option */
+#define   USB_CTRL_SETUP_SCB2_EN_MASK			0x00008000 /* option */
+#define   USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK		0X00020000 /* option */
+#define   USB_CTRL_SETUP_SS_EHCI64BIT_EN_VAR_MASK	0x00010000 /* option */
+#define   USB_CTRL_SETUP_STRAP_IPP_SEL_MASK		0x02000000 /* option */
+#define   USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK	0x04000000 /* option */
+#define   USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK 0x08000000 /* opt */
+#define   USB_CTRL_SETUP_OC3_DISABLE_MASK		0xc0000000 /* option */
+#define USB_CTRL_PLL_CTL		0x04
+#define   USB_CTRL_PLL_CTL_PLL_SUSPEND_EN_MASK		0x08000000
+#define   USB_CTRL_PLL_CTL_PLL_RESETB_MASK		0x40000000
+#define   USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK		0x80000000 /* option */
+#define USB_CTRL_EBRIDGE		0x0c
+#define   USB_CTRL_EBRIDGE_ESTOP_SCB_REQ_MASK		0x00020000 /* option */
+#define USB_CTRL_MDIO			0x14
+#define USB_CTRL_MDIO2			0x18
+#define USB_CTRL_UTMI_CTL_1		0x2c
+#define   USB_CTRL_UTMI_CTL_1_POWER_UP_FSM_EN_MASK	0x00000800
+#define   USB_CTRL_UTMI_CTL_1_POWER_UP_FSM_EN_P1_MASK	0x08000000
+#define USB_CTRL_USB_PM			0x34
+#define   USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK		0x00800000 /* option */
+#define   USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK		0x00400000 /* option */
+#define   USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK	0x40000000 /* option */
+#define   USB_CTRL_USB_PM_USB_PWRDN_MASK		0x80000000 /* option */
+#define   USB_CTRL_USB_PM_SOFT_RESET_MASK		0x40000000 /* option */
+#define   USB_CTRL_USB_PM_USB20_HC_RESETB_MASK		0x30000000 /* option */
+#define   USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK	0x00300000 /* option */
+#define USB_CTRL_USB30_CTL1		0x60
+#define   USB_CTRL_USB30_CTL1_PHY3_PLL_SEQ_START_MASK	0x00000010
+#define   USB_CTRL_USB30_CTL1_PHY3_RESETB_MASK		0x00010000
+#define   USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK	0x00020000 /* option */
+#define   USB_CTRL_USB30_CTL1_USB3_IOC_MASK		0x10000000 /* option */
+#define   USB_CTRL_USB30_CTL1_USB3_IPP_MASK		0x20000000 /* option */
+#define USB_CTRL_USB30_PCTL		0x70
+#define   USB_CTRL_USB30_PCTL_PHY3_SOFT_RESETB_MASK	0x00000002
+#define   USB_CTRL_USB30_PCTL_PHY3_SOFT_RESETB_P1_MASK	0x00020000
+#define USB_CTRL_USB_DEVICE_CTL1	0x90
+#define   USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK	0x00000003 /* option */
+
+/* Register definitions for the XHCI EC block */
+#define USB_XHCI_EC_IRAADR 0x658
+#define USB_XHCI_EC_IRADAT 0x65c
+
+enum brcm_family_type {
+	BRCM_FAMILY_3390A0,
+	BRCM_FAMILY_7250B0,
+	BRCM_FAMILY_7271A0,
+	BRCM_FAMILY_7364A0,
+	BRCM_FAMILY_7366C0,
+	BRCM_FAMILY_74371A0,
+	BRCM_FAMILY_7439B0,
+	BRCM_FAMILY_7445D0,
+	BRCM_FAMILY_7260A0,
+	BRCM_FAMILY_7278A0,
+	BRCM_FAMILY_COUNT,
+};
+
+#define USB_BRCM_FAMILY(chip) \
+	[BRCM_FAMILY_##chip] = __stringify(chip)
+
+static const char *family_names[BRCM_FAMILY_COUNT] = {
+	USB_BRCM_FAMILY(3390A0),
+	USB_BRCM_FAMILY(7250B0),
+	USB_BRCM_FAMILY(7271A0),
+	USB_BRCM_FAMILY(7364A0),
+	USB_BRCM_FAMILY(7366C0),
+	USB_BRCM_FAMILY(74371A0),
+	USB_BRCM_FAMILY(7439B0),
+	USB_BRCM_FAMILY(7445D0),
+	USB_BRCM_FAMILY(7260A0),
+	USB_BRCM_FAMILY(7278A0),
+};
+
+enum {
+	USB_CTRL_SETUP_SCB1_EN_SELECTOR,
+	USB_CTRL_SETUP_SCB2_EN_SELECTOR,
+	USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR,
+	USB_CTRL_SETUP_STRAP_IPP_SEL_SELECTOR,
+	USB_CTRL_SETUP_OC3_DISABLE_SELECTOR,
+	USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_SELECTOR,
+	USB_CTRL_EBRIDGE_ESTOP_SCB_REQ_SELECTOR,
+	USB_CTRL_USB_PM_BDC_SOFT_RESETB_SELECTOR,
+	USB_CTRL_USB_PM_XHC_SOFT_RESETB_SELECTOR,
+	USB_CTRL_USB_PM_USB_PWRDN_SELECTOR,
+	USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_SELECTOR,
+	USB_CTRL_USB30_CTL1_USB3_IOC_SELECTOR,
+	USB_CTRL_USB30_CTL1_USB3_IPP_SELECTOR,
+	USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_SELECTOR,
+	USB_CTRL_USB_PM_SOFT_RESET_SELECTOR,
+	USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_SELECTOR,
+	USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_SELECTOR,
+	USB_CTRL_USB_PM_USB20_HC_RESETB_SELECTOR,
+	USB_CTRL_SETUP_ENDIAN_SELECTOR,
+	USB_CTRL_SELECTOR_COUNT,
+};
+
+#define USB_CTRL_REG(base, reg)	((void *)base + USB_CTRL_##reg)
+#define USB_XHCI_EC_REG(base, reg) ((void *)base + USB_XHCI_EC_##reg)
+#define USB_CTRL_MASK(reg, field) \
+	USB_CTRL_##reg##_##field##_MASK
+#define USB_CTRL_MASK_FAMILY(params, reg, field)			\
+	(params->usb_reg_bits_map[USB_CTRL_##reg##_##field##_SELECTOR])
+
+#define USB_CTRL_SET_FAMILY(params, reg, field)	\
+	usb_ctrl_set_family(params, USB_CTRL_##reg,	\
+			USB_CTRL_##reg##_##field##_SELECTOR)
+#define USB_CTRL_UNSET_FAMILY(params, reg, field)	\
+	usb_ctrl_unset_family(params, USB_CTRL_##reg,	\
+		USB_CTRL_##reg##_##field##_SELECTOR)
+
+#define USB_CTRL_SET(base, reg, field)	\
+	usb_ctrl_set(USB_CTRL_REG(base, reg),		\
+		     USB_CTRL_##reg##_##field##_MASK)
+#define USB_CTRL_UNSET(base, reg, field)	\
+	usb_ctrl_unset(USB_CTRL_REG(base, reg),		\
+		       USB_CTRL_##reg##_##field##_MASK)
+
+#define MDIO_USB2	0
+#define MDIO_USB3	BIT(31)
+
+#define USB_CTRL_SETUP_ENDIAN_BITS (	\
+		USB_CTRL_MASK(SETUP, BABO) |	\
+		USB_CTRL_MASK(SETUP, FNHW) |	\
+		USB_CTRL_MASK(SETUP, FNBO) |	\
+		USB_CTRL_MASK(SETUP, WABO))
+
+#ifdef __LITTLE_ENDIAN
+#define ENDIAN_SETTINGS (			\
+		USB_CTRL_MASK(SETUP, BABO) |	\
+		USB_CTRL_MASK(SETUP, FNHW))
+#else
+#define ENDIAN_SETTINGS (			\
+		USB_CTRL_MASK(SETUP, FNHW) |	\
+		USB_CTRL_MASK(SETUP, FNBO) |	\
+		USB_CTRL_MASK(SETUP, WABO))
+#endif
+
+struct id_to_type {
+	u32 id;
+	int type;
+};
+
+static const struct id_to_type id_to_type_table[] = {
+	{ 0x33900000, BRCM_FAMILY_3390A0 },
+	{ 0x72500010, BRCM_FAMILY_7250B0 },
+	{ 0x72600000, BRCM_FAMILY_7260A0 },
+	{ 0x72680000, BRCM_FAMILY_7271A0 },
+	{ 0x72710000, BRCM_FAMILY_7271A0 },
+	{ 0x73640000, BRCM_FAMILY_7364A0 },
+	{ 0x73660020, BRCM_FAMILY_7366C0 },
+	{ 0x07437100, BRCM_FAMILY_74371A0 },
+	{ 0x74390010, BRCM_FAMILY_7439B0 },
+	{ 0x74450030, BRCM_FAMILY_7445D0 },
+	{ 0x72780000, BRCM_FAMILY_7278A0 },
+	{ 0, BRCM_FAMILY_7271A0 }, /* default */
+};
+
+static const u32
+usb_reg_bits_map_table[BRCM_FAMILY_COUNT][USB_CTRL_SELECTOR_COUNT] = {
+	/* 3390B0 */
+	[BRCM_FAMILY_3390A0] = {
+		USB_CTRL_SETUP_SCB1_EN_MASK,
+		USB_CTRL_SETUP_SCB2_EN_MASK,
+		USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
+		USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
+		USB_CTRL_SETUP_OC3_DISABLE_MASK,
+		0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
+		USB_CTRL_EBRIDGE_ESTOP_SCB_REQ_MASK,
+		0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
+		USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
+		USB_CTRL_USB_PM_USB_PWRDN_MASK,
+		0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
+		0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
+		0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
+		USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
+		0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
+		0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
+		0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
+		USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
+		ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+	},
+	/* 7250b0 */
+	[BRCM_FAMILY_7250B0] = {
+		USB_CTRL_SETUP_SCB1_EN_MASK,
+		USB_CTRL_SETUP_SCB2_EN_MASK,
+		USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
+		0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
+		USB_CTRL_SETUP_OC3_DISABLE_MASK,
+		USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
+		USB_CTRL_EBRIDGE_ESTOP_SCB_REQ_MASK,
+		0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
+		USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK,
+		0, /* USB_CTRL_USB_PM_USB_PWRDN_MASK */
+		0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
+		0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
+		0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
+		0, /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
+		0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
+		0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
+		0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
+		USB_CTRL_USB_PM_USB20_HC_RESETB_MASK,
+		ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+	},
+	/* 7271a0 */
+	[BRCM_FAMILY_7271A0] = {
+		0, /* USB_CTRL_SETUP_SCB1_EN_MASK */
+		0, /* USB_CTRL_SETUP_SCB2_EN_MASK */
+		USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
+		USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
+		USB_CTRL_SETUP_OC3_DISABLE_MASK,
+		0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
+		USB_CTRL_EBRIDGE_ESTOP_SCB_REQ_MASK,
+		USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
+		USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
+		USB_CTRL_USB_PM_USB_PWRDN_MASK,
+		0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
+		0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
+		0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
+		USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
+		USB_CTRL_USB_PM_SOFT_RESET_MASK,
+		USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK,
+		USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK,
+		USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
+		ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+	},
+	/* 7364a0 */
+	[BRCM_FAMILY_7364A0] = {
+		USB_CTRL_SETUP_SCB1_EN_MASK,
+		USB_CTRL_SETUP_SCB2_EN_MASK,
+		USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
+		0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
+		USB_CTRL_SETUP_OC3_DISABLE_MASK,
+		USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
+		USB_CTRL_EBRIDGE_ESTOP_SCB_REQ_MASK,
+		0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
+		USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK,
+		0, /* USB_CTRL_USB_PM_USB_PWRDN_MASK */
+		0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
+		0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
+		0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
+		0, /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
+		0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
+		0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
+		0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
+		USB_CTRL_USB_PM_USB20_HC_RESETB_MASK,
+		ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+	},
+	/* 7366c0 */
+	[BRCM_FAMILY_7366C0] = {
+		USB_CTRL_SETUP_SCB1_EN_MASK,
+		USB_CTRL_SETUP_SCB2_EN_MASK,
+		USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
+		0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
+		USB_CTRL_SETUP_OC3_DISABLE_MASK,
+		0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
+		USB_CTRL_EBRIDGE_ESTOP_SCB_REQ_MASK,
+		0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
+		USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK,
+		USB_CTRL_USB_PM_USB_PWRDN_MASK,
+		0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
+		0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
+		0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
+		0, /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
+		0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
+		0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
+		0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
+		USB_CTRL_USB_PM_USB20_HC_RESETB_MASK,
+		ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+	},
+	/* 74371A0 */
+	[BRCM_FAMILY_74371A0] = {
+		USB_CTRL_SETUP_SCB1_EN_MASK,
+		USB_CTRL_SETUP_SCB2_EN_MASK,
+		USB_CTRL_SETUP_SS_EHCI64BIT_EN_VAR_MASK,
+		0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
+		0, /* USB_CTRL_SETUP_OC3_DISABLE_MASK */
+		USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
+		0, /* USB_CTRL_EBRIDGE_ESTOP_SCB_REQ_MASK */
+		0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
+		0, /* USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK */
+		0, /* USB_CTRL_USB_PM_USB_PWRDN_MASK */
+		USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK,
+		USB_CTRL_USB30_CTL1_USB3_IOC_MASK,
+		USB_CTRL_USB30_CTL1_USB3_IPP_MASK,
+		0, /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
+		0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
+		0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
+		0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
+		0, /* USB_CTRL_USB_PM_USB20_HC_RESETB_MASK */
+		ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+	},
+	/* 7439B0 */
+	[BRCM_FAMILY_7439B0] = {
+		USB_CTRL_SETUP_SCB1_EN_MASK,
+		USB_CTRL_SETUP_SCB2_EN_MASK,
+		USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
+		USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
+		USB_CTRL_SETUP_OC3_DISABLE_MASK,
+		0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
+		0, /* USB_CTRL_EBRIDGE_ESTOP_SCB_REQ_MASK */
+		USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
+		USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
+		USB_CTRL_USB_PM_USB_PWRDN_MASK,
+		0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
+		0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
+		0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
+		USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
+		0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
+		0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
+		0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
+		USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
+		ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+	},
+	/* 7445d0 */
+	[BRCM_FAMILY_7445D0] = {
+		USB_CTRL_SETUP_SCB1_EN_MASK,
+		USB_CTRL_SETUP_SCB2_EN_MASK,
+		USB_CTRL_SETUP_SS_EHCI64BIT_EN_VAR_MASK,
+		0, /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
+		USB_CTRL_SETUP_OC3_DISABLE_MASK,
+		USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK,
+		0, /* USB_CTRL_EBRIDGE_ESTOP_SCB_REQ_MASK */
+		0, /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
+		0, /* USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK */
+		0, /* USB_CTRL_USB_PM_USB_PWRDN_MASK */
+		USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK,
+		0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
+		0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
+		0, /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
+		0, /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
+		0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
+		0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
+		USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
+		ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+	},
+	/* 7260a0 */
+	[BRCM_FAMILY_7260A0] = {
+		0, /* USB_CTRL_SETUP_SCB1_EN_MASK */
+		0, /* USB_CTRL_SETUP_SCB2_EN_MASK */
+		USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK,
+		USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
+		USB_CTRL_SETUP_OC3_DISABLE_MASK,
+		0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
+		USB_CTRL_EBRIDGE_ESTOP_SCB_REQ_MASK,
+		USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
+		USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
+		USB_CTRL_USB_PM_USB_PWRDN_MASK,
+		0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
+		0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
+		0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
+		USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
+		USB_CTRL_USB_PM_SOFT_RESET_MASK,
+		USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK,
+		USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK,
+		USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK,
+		ENDIAN_SETTINGS, /* USB_CTRL_SETUP ENDIAN bits */
+	},
+	/* 7278a0 */
+	[BRCM_FAMILY_7278A0] = {
+		0, /* USB_CTRL_SETUP_SCB1_EN_MASK */
+		0, /* USB_CTRL_SETUP_SCB2_EN_MASK */
+		0, /*USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK */
+		USB_CTRL_SETUP_STRAP_IPP_SEL_MASK,
+		USB_CTRL_SETUP_OC3_DISABLE_MASK,
+		0, /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
+		USB_CTRL_EBRIDGE_ESTOP_SCB_REQ_MASK,
+		USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK,
+		USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK,
+		USB_CTRL_USB_PM_USB_PWRDN_MASK,
+		0, /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
+		0, /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
+		0, /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
+		USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK,
+		USB_CTRL_USB_PM_SOFT_RESET_MASK,
+		0, /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
+		0, /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
+		0, /* USB_CTRL_USB_PM_USB20_HC_RESETB_MASK */
+		0, /* USB_CTRL_SETUP ENDIAN bits */
+	},
+};
+
+static inline u32 brcmusb_readl(void __iomem *addr)
+{
+	return readl(addr);
+}
+
+static inline void brcmusb_writel(u32 val, void __iomem *addr)
+{
+	writel(val, addr);
+}
+
+static inline
+void usb_ctrl_unset_family(struct brcm_usb_init_params *params,
+			   u32 reg_offset, u32 field)
+{
+	u32 mask;
+	void *reg;
+
+	mask = params->usb_reg_bits_map[field];
+	reg = params->ctrl_regs + reg_offset;
+	brcmusb_writel(brcmusb_readl(reg) & ~mask, reg);
+};
+
+static inline
+void usb_ctrl_set_family(struct brcm_usb_init_params *params,
+			 u32 reg_offset, u32 field)
+{
+	u32 mask;
+	void *reg;
+
+	mask = params->usb_reg_bits_map[field];
+	reg = params->ctrl_regs + reg_offset;
+	brcmusb_writel(brcmusb_readl(reg) | mask, reg);
+};
+
+static inline void usb_ctrl_set(void __iomem *reg, u32 field)
+{
+	u32 value;
+
+	value = brcmusb_readl(reg);
+	brcmusb_writel(value | field, reg);
+}
+
+static inline void usb_ctrl_unset(void __iomem *reg, u32 field)
+{
+	u32 value;
+
+	value = brcmusb_readl(reg);
+	brcmusb_writel(value & ~field, reg);
+}
+
+static u32 brcmusb_usb_mdio_read(void __iomem *ctrl_base, u32 reg, int mode)
+{
+	u32 data;
+
+	data = (reg << 16) | mode;
+	brcmusb_writel(data, USB_CTRL_REG(ctrl_base, MDIO));
+	data |= (1 << 24);
+	brcmusb_writel(data, USB_CTRL_REG(ctrl_base, MDIO));
+	data &= ~(1 << 24);
+	/* wait for the 60MHz parallel to serial shifter */
+	usleep_range(10, 20);
+	brcmusb_writel(data, USB_CTRL_REG(ctrl_base, MDIO));
+	/* wait for the 60MHz parallel to serial shifter */
+	usleep_range(10, 20);
+
+	return brcmusb_readl(USB_CTRL_REG(ctrl_base, MDIO2)) & 0xffff;
+}
+
+static void brcmusb_usb_mdio_write(void __iomem *ctrl_base, u32 reg,
+				   u32 val, int mode)
+{
+	u32 data;
+
+	data = (reg << 16) | val | mode;
+	brcmusb_writel(data, USB_CTRL_REG(ctrl_base, MDIO));
+	data |= (1 << 25);
+	brcmusb_writel(data, USB_CTRL_REG(ctrl_base, MDIO));
+	data &= ~(1 << 25);
+
+	/* wait for the 60MHz parallel to serial shifter */
+	usleep_range(10, 20);
+	brcmusb_writel(data, USB_CTRL_REG(ctrl_base, MDIO));
+	/* wait for the 60MHz parallel to serial shifter */
+	usleep_range(10, 20);
+}
+
+static void brcmusb_usb_phy_ldo_fix(void __iomem *ctrl_base)
+{
+	/* first disable FSM but also leave it that way */
+	/* to allow normal suspend/resume */
+	USB_CTRL_UNSET(ctrl_base, UTMI_CTL_1, POWER_UP_FSM_EN);
+	USB_CTRL_UNSET(ctrl_base, UTMI_CTL_1, POWER_UP_FSM_EN_P1);
+
+	/* reset USB 2.0 PLL */
+	USB_CTRL_UNSET(ctrl_base, PLL_CTL, PLL_RESETB);
+	/* PLL reset period */
+	udelay(1);
+	USB_CTRL_SET(ctrl_base, PLL_CTL, PLL_RESETB);
+	/* Give PLL enough time to lock */
+	usleep_range(1000, 2000);
+}
+
+static void brcmusb_usb2_eye_fix(void __iomem *ctrl_base)
+{
+	/* Increase USB 2.0 TX level to meet spec requirement */
+	brcmusb_usb_mdio_write(ctrl_base, 0x1f, 0x80a0, MDIO_USB2);
+	brcmusb_usb_mdio_write(ctrl_base, 0x0a, 0xc6a0, MDIO_USB2);
+}
+
+static void brcmusb_usb3_pll_fix(void __iomem *ctrl_base)
+{
+	/* Set correct window for PLL lock detect */
+	brcmusb_usb_mdio_write(ctrl_base, 0x1f, 0x8000, MDIO_USB3);
+	brcmusb_usb_mdio_write(ctrl_base, 0x07, 0x1503, MDIO_USB3);
+}
+
+static void brcmusb_usb3_enable_pipe_reset(void __iomem *ctrl_base)
+{
+	u32 val;
+
+	/* Re-enable USB 3.0 pipe reset */
+	brcmusb_usb_mdio_write(ctrl_base, 0x1f, 0x8000, MDIO_USB3);
+	val = brcmusb_usb_mdio_read(ctrl_base, 0x0f, MDIO_USB3) | 0x200;
+	brcmusb_usb_mdio_write(ctrl_base, 0x0f, val, MDIO_USB3);
+}
+
+static void brcmusb_usb3_enable_sigdet(void __iomem *ctrl_base)
+{
+	u32 val, ofs;
+	int ii;
+
+	ofs = 0;
+	for (ii = 0; ii < PHY_PORTS; ++ii) {
+		/* Set correct default for sigdet */
+		brcmusb_usb_mdio_write(ctrl_base, 0x1f, (0x8080 + ofs),
+				       MDIO_USB3);
+		val = brcmusb_usb_mdio_read(ctrl_base, 0x05, MDIO_USB3);
+		val = (val & ~0x800f) | 0x800d;
+		brcmusb_usb_mdio_write(ctrl_base, 0x05, val, MDIO_USB3);
+		ofs = PHY_PORT_SELECT_1;
+	}
+}
+
+static void brcmusb_usb3_enable_skip_align(void __iomem *ctrl_base)
+{
+	u32 val, ofs;
+	int ii;
+
+	ofs = 0;
+	for (ii = 0; ii < PHY_PORTS; ++ii) {
+		/* Set correct default for SKIP align */
+		brcmusb_usb_mdio_write(ctrl_base, 0x1f, (0x8060 + ofs),
+				       MDIO_USB3);
+		val = brcmusb_usb_mdio_read(ctrl_base, 0x01, MDIO_USB3) | 0x200;
+		brcmusb_usb_mdio_write(ctrl_base, 0x01, val, MDIO_USB3);
+		ofs = PHY_PORT_SELECT_1;
+	}
+}
+
+static void brcmusb_usb3_unfreeze_aeq(void __iomem *ctrl_base)
+{
+	u32 val, ofs;
+	int ii;
+
+	ofs = 0;
+	for (ii = 0; ii < PHY_PORTS; ++ii) {
+		/* Let EQ freeze after TSEQ */
+		brcmusb_usb_mdio_write(ctrl_base, 0x1f, (0x80e0 + ofs),
+				       MDIO_USB3);
+		val = brcmusb_usb_mdio_read(ctrl_base, 0x01, MDIO_USB3);
+		val &= ~0x0008;
+		brcmusb_usb_mdio_write(ctrl_base, 0x01, val, MDIO_USB3);
+		ofs = PHY_PORT_SELECT_1;
+	}
+}
+
+static void brcmusb_usb3_pll_54mhz(struct brcm_usb_init_params *params)
+{
+	u32 ofs;
+	int ii;
+	void __iomem *ctrl_base = params->ctrl_regs;
+
+	/*
+	 * On newer B53 based SoC's, the reference clock for the
+	 * 3.0 PLL has been changed from 50MHz to 54MHz so the
+	 * PLL needs to be reprogrammed.
+	 * See SWLINUX-4006.
+	 *
+	 * On the 7364C0, the reference clock for the
+	 * 3.0 PLL has been changed from 50MHz to 54MHz to
+	 * work around a MOCA issue.
+	 * See SWLINUX-4169.
+	 */
+	switch (params->selected_family) {
+	case BRCM_FAMILY_3390A0:
+	case BRCM_FAMILY_7250B0:
+	case BRCM_FAMILY_7366C0:
+	case BRCM_FAMILY_74371A0:
+	case BRCM_FAMILY_7439B0:
+	case BRCM_FAMILY_7445D0:
+	case BRCM_FAMILY_7260A0:
+		return;
+	case BRCM_FAMILY_7364A0:
+		if (BRCM_REV(params->family_id) < 0x20)
+			return;
+		break;
+	}
+
+	/* set USB 3.0 PLL to accept 54Mhz reference clock */
+	USB_CTRL_UNSET(ctrl_base, USB30_CTL1, PHY3_PLL_SEQ_START);
+
+	brcmusb_usb_mdio_write(ctrl_base, 0x1f, 0x8000, MDIO_USB3);
+	brcmusb_usb_mdio_write(ctrl_base, 0x10, 0x5784, MDIO_USB3);
+	brcmusb_usb_mdio_write(ctrl_base, 0x11, 0x01d0, MDIO_USB3);
+	brcmusb_usb_mdio_write(ctrl_base, 0x12, 0x1DE8, MDIO_USB3);
+	brcmusb_usb_mdio_write(ctrl_base, 0x13, 0xAA80, MDIO_USB3);
+	brcmusb_usb_mdio_write(ctrl_base, 0x14, 0x8826, MDIO_USB3);
+	brcmusb_usb_mdio_write(ctrl_base, 0x15, 0x0044, MDIO_USB3);
+	brcmusb_usb_mdio_write(ctrl_base, 0x16, 0x8000, MDIO_USB3);
+	brcmusb_usb_mdio_write(ctrl_base, 0x17, 0x0851, MDIO_USB3);
+	brcmusb_usb_mdio_write(ctrl_base, 0x18, 0x0000, MDIO_USB3);
+
+	/* both ports */
+	ofs = 0;
+	for (ii = 0; ii < PHY_PORTS; ++ii) {
+		brcmusb_usb_mdio_write(ctrl_base, 0x1f, (0x8040 + ofs),
+				       MDIO_USB3);
+		brcmusb_usb_mdio_write(ctrl_base, 0x03, 0x0090, MDIO_USB3);
+		brcmusb_usb_mdio_write(ctrl_base, 0x04, 0x0134, MDIO_USB3);
+		brcmusb_usb_mdio_write(ctrl_base, 0x1f, (0x8020 + ofs),
+				       MDIO_USB3);
+		brcmusb_usb_mdio_write(ctrl_base, 0x01, 0x00e2, MDIO_USB3);
+		ofs = PHY_PORT_SELECT_1;
+	}
+
+	/* restart PLL sequence */
+	USB_CTRL_SET(ctrl_base, USB30_CTL1, PHY3_PLL_SEQ_START);
+	/* Give PLL enough time to lock */
+	usleep_range(1000, 2000);
+}
+
+static void brcmusb_usb3_ssc_enable(void __iomem *ctrl_base)
+{
+	u32 val;
+
+	/* Enable USB 3.0 TX spread spectrum */
+	brcmusb_usb_mdio_write(ctrl_base, 0x1f, 0x8040, MDIO_USB3);
+	val = brcmusb_usb_mdio_read(ctrl_base, 0x01, MDIO_USB3) | 0xf;
+	brcmusb_usb_mdio_write(ctrl_base, 0x01, val, MDIO_USB3);
+
+	/* Currently, USB 3.0 SSC is enabled via port 0 MDIO registers,
+	 * which should have been adequate. However, due to a bug in the
+	 * USB 3.0 PHY, it must be enabled via both ports (HWUSB3DVT-26).
+	 */
+	brcmusb_usb_mdio_write(ctrl_base, 0x1f, 0x9040, MDIO_USB3);
+	val = brcmusb_usb_mdio_read(ctrl_base, 0x01, MDIO_USB3) | 0xf;
+	brcmusb_usb_mdio_write(ctrl_base, 0x01, val, MDIO_USB3);
+}
+
+static void brcmusb_usb3_phy_workarounds(struct brcm_usb_init_params *params)
+{
+	void __iomem *ctrl_base = params->ctrl_regs;
+
+	brcmusb_usb3_pll_fix(ctrl_base);
+	brcmusb_usb3_pll_54mhz(params);
+	brcmusb_usb3_ssc_enable(ctrl_base);
+	brcmusb_usb3_enable_pipe_reset(ctrl_base);
+	brcmusb_usb3_enable_sigdet(ctrl_base);
+	brcmusb_usb3_enable_skip_align(ctrl_base);
+	brcmusb_usb3_unfreeze_aeq(ctrl_base);
+}
+
+static void brcmusb_memc_fix(struct brcm_usb_init_params *params)
+{
+	u32 prid;
+
+	if (params->selected_family != BRCM_FAMILY_7445D0)
+		return;
+	/*
+	 * This is a workaround for HW7445-1869 where a DMA write ends up
+	 * doing a read pre-fetch after the end of the DMA buffer. This
+	 * causes a problem when the DMA buffer is at the end of physical
+	 * memory, causing the pre-fetch read to access non-existent memory,
+	 * and the chip bondout has MEMC2 disabled. When the pre-fetch read
+	 * tries to use the disabled MEMC2, it hangs the bus. The workaround
+	 * is to disable MEMC2 access in the usb controller which avoids
+	 * the hang.
+	 */
+
+	prid = params->product_id & 0xfffff000;
+	switch (prid) {
+	case 0x72520000:
+	case 0x74480000:
+	case 0x74490000:
+	case 0x07252000:
+	case 0x07448000:
+	case 0x07449000:
+		USB_CTRL_UNSET_FAMILY(params, SETUP, SCB2_EN);
+	}
+}
+
+static void brcmusb_usb3_otp_fix(struct brcm_usb_init_params *params)
+{
+	void __iomem *xhci_ec_base = params->xhci_ec_regs;
+	u32 val;
+
+	if (params->family_id != 0x74371000 || xhci_ec_base == 0)
+		return;
+	brcmusb_writel(0xa20c, USB_XHCI_EC_REG(xhci_ec_base, IRAADR));
+	val = brcmusb_readl(USB_XHCI_EC_REG(xhci_ec_base, IRADAT));
+
+	/* set cfg_pick_ss_lock */
+	val |= (1 << 27);
+	brcmusb_writel(val, USB_XHCI_EC_REG(xhci_ec_base, IRADAT));
+
+	/* Reset USB 3.0 PHY for workaround to take effect */
+	USB_CTRL_UNSET(params->ctrl_regs, USB30_CTL1, PHY3_RESETB);
+	USB_CTRL_SET(params->ctrl_regs,	USB30_CTL1, PHY3_RESETB);
+}
+
+static void brcmusb_xhci_soft_reset(struct brcm_usb_init_params *params,
+				    int on_off)
+{
+	/* Assert reset */
+	if (on_off) {
+		if (USB_CTRL_MASK_FAMILY(params, USB_PM, XHC_SOFT_RESETB))
+			USB_CTRL_UNSET_FAMILY(params, USB_PM, XHC_SOFT_RESETB);
+		else
+			USB_CTRL_UNSET_FAMILY(params,
+					      USB30_CTL1, XHC_SOFT_RESETB);
+	} else { /* De-assert reset */
+		if (USB_CTRL_MASK_FAMILY(params, USB_PM, XHC_SOFT_RESETB))
+			USB_CTRL_SET_FAMILY(params, USB_PM, XHC_SOFT_RESETB);
+		else
+			USB_CTRL_SET_FAMILY(params, USB30_CTL1,
+					    XHC_SOFT_RESETB);
+	}
+}
+
+/*
+ * Return the best map table family. The order is:
+ *   - exact match of chip and major rev
+ *   - exact match of chip and closest older major rev
+ *   - default chip/rev.
+ * NOTE: The minor rev is always ignored.
+ */
+static enum brcm_family_type brcmusb_get_family_type(
+	struct brcm_usb_init_params *params)
+{
+	int last_type = -1;
+	u32 last_family = 0;
+	u32 family_no_major;
+	unsigned int x;
+	u32 family;
+
+	family = params->family_id & 0xfffffff0;
+	family_no_major = params->family_id & 0xffffff00;
+	for (x = 0; id_to_type_table[x].id; x++) {
+		if (family == id_to_type_table[x].id)
+			return id_to_type_table[x].type;
+		if (family_no_major == (id_to_type_table[x].id & 0xffffff00))
+			if (family > id_to_type_table[x].id &&
+			    last_family < id_to_type_table[x].id) {
+				last_family = id_to_type_table[x].id;
+				last_type = id_to_type_table[x].type;
+			}
+	}
+
+	/* If no match, return the default family */
+	if (last_type == -1)
+		return id_to_type_table[x].type;
+	return last_type;
+}
+
+void brcm_usb_init_ipp(struct brcm_usb_init_params *params)
+{
+	void __iomem *ctrl = params->ctrl_regs;
+	u32 reg;
+	u32 orig_reg;
+
+	/* Starting with the 7445d0, there are no longer separate 3.0
+	 * versions of IOC and IPP.
+	 */
+	if (USB_CTRL_MASK_FAMILY(params, USB30_CTL1, USB3_IOC)) {
+		if (params->ioc)
+			USB_CTRL_SET_FAMILY(params, USB30_CTL1, USB3_IOC);
+		if (params->ipp == 1)
+			USB_CTRL_SET_FAMILY(params, USB30_CTL1, USB3_IPP);
+	}
+
+	reg = brcmusb_readl(USB_CTRL_REG(ctrl, SETUP));
+	orig_reg = reg;
+	if (USB_CTRL_MASK_FAMILY(params, SETUP, STRAP_CC_DRD_MODE_ENABLE_SEL))
+		/* Never use the strap, it's going away. */
+		reg &= ~(USB_CTRL_MASK_FAMILY(params,
+					      SETUP,
+					      STRAP_CC_DRD_MODE_ENABLE_SEL));
+	if (USB_CTRL_MASK_FAMILY(params, SETUP, STRAP_IPP_SEL))
+		if (params->ipp != 2)
+			/* override ipp strap pin (if it exits) */
+			reg &= ~(USB_CTRL_MASK_FAMILY(params, SETUP,
+						      STRAP_IPP_SEL));
+
+	/* Override the default OC and PP polarity */
+	reg &= ~(USB_CTRL_MASK(SETUP, IPP) | USB_CTRL_MASK(SETUP, IOC));
+	if (params->ioc)
+		reg |= USB_CTRL_MASK(SETUP, IOC);
+	if (params->ipp == 1 && ((reg & USB_CTRL_MASK(SETUP, IPP)) == 0))
+		reg |= USB_CTRL_MASK(SETUP, IPP);
+	brcmusb_writel(reg, USB_CTRL_REG(ctrl, SETUP));
+
+	/*
+	 * If we're changing IPP, make sure power is off long enough
+	 * to turn off any connected devices.
+	 */
+	if (reg != orig_reg)
+		msleep(50);
+}
+
+int brcm_usb_init_get_dual_select(struct brcm_usb_init_params *params)
+{
+	void __iomem *ctrl = params->ctrl_regs;
+	u32 reg = 0;
+
+	if (USB_CTRL_MASK_FAMILY(params, USB_DEVICE_CTL1, PORT_MODE)) {
+		reg = brcmusb_readl(USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
+		reg &= USB_CTRL_MASK_FAMILY(params, USB_DEVICE_CTL1,
+					PORT_MODE);
+	}
+	return reg;
+}
+
+void brcm_usb_init_set_dual_select(struct brcm_usb_init_params *params,
+				   int mode)
+{
+	void __iomem *ctrl = params->ctrl_regs;
+	u32 reg;
+
+	if (USB_CTRL_MASK_FAMILY(params, USB_DEVICE_CTL1, PORT_MODE)) {
+		reg = brcmusb_readl(USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
+		reg &= ~USB_CTRL_MASK_FAMILY(params, USB_DEVICE_CTL1,
+					PORT_MODE);
+		reg |= mode;
+		brcmusb_writel(reg, USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
+	}
+}
+
+void brcm_usb_init_common(struct brcm_usb_init_params *params)
+{
+	u32 reg;
+	void __iomem *ctrl = params->ctrl_regs;
+
+	/* Take USB out of power down */
+	if (USB_CTRL_MASK_FAMILY(params, PLL_CTL, PLL_IDDQ_PWRDN)) {
+		USB_CTRL_UNSET_FAMILY(params, PLL_CTL, PLL_IDDQ_PWRDN);
+		/* 1 millisecond - for USB clocks to settle down */
+		usleep_range(1000, 2000);
+	}
+
+	if (USB_CTRL_MASK_FAMILY(params, USB_PM, USB_PWRDN)) {
+		USB_CTRL_UNSET_FAMILY(params, USB_PM, USB_PWRDN);
+		/* 1 millisecond - for USB clocks to settle down */
+		usleep_range(1000, 2000);
+	}
+
+	if (params->selected_family != BRCM_FAMILY_74371A0 &&
+	    (BRCM_ID(params->family_id) != 0x7364))
+		/*
+		 * HW7439-637: 7439a0 and its derivatives do not have large
+		 * enough descriptor storage for this.
+		 */
+		USB_CTRL_SET_FAMILY(params, SETUP, SS_EHCI64BIT_EN);
+
+	/* Block auto PLL suspend by USB2 PHY (Sasi) */
+	USB_CTRL_SET(ctrl, PLL_CTL, PLL_SUSPEND_EN);
+
+	reg = brcmusb_readl(USB_CTRL_REG(ctrl, SETUP));
+	if (params->selected_family == BRCM_FAMILY_7364A0)
+		/* Suppress overcurrent indication from USB30 ports for A0 */
+		reg |= USB_CTRL_MASK_FAMILY(params, SETUP, OC3_DISABLE);
+
+	brcmusb_usb_phy_ldo_fix(ctrl);
+	brcmusb_usb2_eye_fix(ctrl);
+
+	/*
+	 * Make sure the the second and third memory controller
+	 * interfaces are enabled if they exist.
+	 */
+	if (USB_CTRL_MASK_FAMILY(params, SETUP, SCB1_EN))
+		reg |= USB_CTRL_MASK_FAMILY(params, SETUP, SCB1_EN);
+	if (USB_CTRL_MASK_FAMILY(params, SETUP, SCB2_EN))
+		reg |= USB_CTRL_MASK_FAMILY(params, SETUP, SCB2_EN);
+	brcmusb_writel(reg, USB_CTRL_REG(ctrl, SETUP));
+
+	brcmusb_memc_fix(params);
+
+	if (USB_CTRL_MASK_FAMILY(params, USB_DEVICE_CTL1, PORT_MODE)) {
+		reg = brcmusb_readl(USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
+		reg &= ~USB_CTRL_MASK_FAMILY(params, USB_DEVICE_CTL1,
+					PORT_MODE);
+		reg |= params->mode;
+		brcmusb_writel(reg, USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
+	}
+	if (USB_CTRL_MASK_FAMILY(params, USB_PM, BDC_SOFT_RESETB)) {
+		switch (params->mode) {
+		case USB_CTLR_MODE_HOST:
+			USB_CTRL_UNSET_FAMILY(params, USB_PM, BDC_SOFT_RESETB);
+			break;
+		default:
+			USB_CTRL_SET_FAMILY(params, USB_PM, BDC_SOFT_RESETB);
+		break;
+		}
+	}
+	if (USB_CTRL_MASK_FAMILY(params, SETUP, CC_DRD_MODE_ENABLE)) {
+		if (params->mode == USB_CTLR_MODE_TYPEC_PD)
+			USB_CTRL_SET_FAMILY(params, SETUP, CC_DRD_MODE_ENABLE);
+		else
+			USB_CTRL_UNSET_FAMILY(params, SETUP,
+					      CC_DRD_MODE_ENABLE);
+	}
+}
+
+void brcm_usb_init_eohci(struct brcm_usb_init_params *params)
+{
+	u32 reg;
+	void __iomem *ctrl = params->ctrl_regs;
+
+	if (USB_CTRL_MASK_FAMILY(params, USB_PM, USB20_HC_RESETB))
+		USB_CTRL_SET_FAMILY(params, USB_PM, USB20_HC_RESETB);
+
+	if (params->selected_family == BRCM_FAMILY_7366C0)
+		/*
+		 * Don't enable this so the memory controller doesn't read
+		 * into memory holes. NOTE: This bit is low true on 7366C0.
+		 */
+		USB_CTRL_SET_FAMILY(params, EBRIDGE, ESTOP_SCB_REQ);
+
+	/* Setup the endian bits */
+	reg = brcmusb_readl(USB_CTRL_REG(ctrl, SETUP));
+	reg &= ~USB_CTRL_SETUP_ENDIAN_BITS;
+	reg |= USB_CTRL_MASK_FAMILY(params, SETUP, ENDIAN);
+	brcmusb_writel(reg, USB_CTRL_REG(ctrl, SETUP));
+}
+
+void brcm_usb_init_xhci(struct brcm_usb_init_params *params)
+{
+	void __iomem *ctrl = params->ctrl_regs;
+
+	if (BRCM_ID(params->family_id) == 0x7366) {
+		/*
+		 * The PHY3_SOFT_RESETB bits default to the wrong state.
+		 */
+		USB_CTRL_SET(ctrl, USB30_PCTL, PHY3_SOFT_RESETB);
+		USB_CTRL_SET(ctrl, USB30_PCTL, PHY3_SOFT_RESETB_P1);
+	}
+
+	/*
+	 * Kick start USB3 PHY
+	 * Make sure it's low to insure a rising edge.
+	 */
+	USB_CTRL_UNSET(ctrl, USB30_CTL1, PHY3_PLL_SEQ_START);
+	USB_CTRL_SET(ctrl, USB30_CTL1, PHY3_PLL_SEQ_START);
+
+	brcmusb_usb3_phy_workarounds(params);
+	brcmusb_xhci_soft_reset(params, 0);
+	brcmusb_usb3_otp_fix(params);
+}
+
+void brcm_usb_uninit_common(struct brcm_usb_init_params *params)
+{
+	if (USB_CTRL_MASK_FAMILY(params, USB_PM, USB_PWRDN))
+		USB_CTRL_SET_FAMILY(params, USB_PM, USB_PWRDN);
+
+	if (USB_CTRL_MASK_FAMILY(params, PLL_CTL, PLL_IDDQ_PWRDN))
+		USB_CTRL_SET_FAMILY(params, PLL_CTL, PLL_IDDQ_PWRDN);
+}
+
+void brcm_usb_uninit_eohci(struct brcm_usb_init_params *params)
+{
+	if (USB_CTRL_MASK_FAMILY(params, USB_PM, USB20_HC_RESETB))
+		USB_CTRL_UNSET_FAMILY(params, USB_PM, USB20_HC_RESETB);
+}
+
+void brcm_usb_uninit_xhci(struct brcm_usb_init_params *params)
+{
+	brcmusb_xhci_soft_reset(params, 1);
+}
+
+void brcm_usb_set_family_map(struct brcm_usb_init_params *params)
+{
+	int fam;
+
+	fam = brcmusb_get_family_type(params);
+	params->selected_family = fam;
+	params->usb_reg_bits_map =
+		&usb_reg_bits_map_table[fam][0];
+	params->family_name = family_names[fam];
+}

+ 50 - 0
drivers/phy/broadcom/phy-brcm-usb-init.h

@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2014-2017 Broadcom
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ */
+
+#ifndef _USB_BRCM_COMMON_INIT_H
+#define _USB_BRCM_COMMON_INIT_H
+
+#define USB_CTLR_MODE_HOST 0
+#define USB_CTLR_MODE_DEVICE 1
+#define USB_CTLR_MODE_DRD 2
+#define USB_CTLR_MODE_TYPEC_PD 3
+
+struct  brcm_usb_init_params;
+
+struct  brcm_usb_init_params {
+	void __iomem *ctrl_regs;
+	void __iomem *xhci_ec_regs;
+	int ioc;
+	int ipp;
+	int mode;
+	u32 family_id;
+	u32 product_id;
+	int selected_family;
+	const char *family_name;
+	const u32 *usb_reg_bits_map;
+};
+
+void brcm_usb_set_family_map(struct brcm_usb_init_params *params);
+int brcm_usb_init_get_dual_select(struct brcm_usb_init_params *params);
+void brcm_usb_init_set_dual_select(struct brcm_usb_init_params *params,
+				   int mode);
+
+void brcm_usb_init_ipp(struct brcm_usb_init_params *ini);
+void brcm_usb_init_common(struct brcm_usb_init_params *ini);
+void brcm_usb_init_eohci(struct brcm_usb_init_params *ini);
+void brcm_usb_init_xhci(struct brcm_usb_init_params *ini);
+void brcm_usb_uninit_common(struct brcm_usb_init_params *ini);
+void brcm_usb_uninit_eohci(struct brcm_usb_init_params *ini);
+void brcm_usb_uninit_xhci(struct brcm_usb_init_params *ini);
+
+#endif /* _USB_BRCM_COMMON_INIT_H */

+ 459 - 0
drivers/phy/broadcom/phy-brcm-usb.c

@@ -0,0 +1,459 @@
+/*
+ * phy-brcm-usb.c - Broadcom USB Phy Driver
+ *
+ * Copyright (C) 2015-2017 Broadcom
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/soc/brcmstb/brcmstb.h>
+#include <dt-bindings/phy/phy.h>
+
+#include "phy-brcm-usb-init.h"
+
+static DEFINE_MUTEX(sysfs_lock);
+
+enum brcm_usb_phy_id {
+	BRCM_USB_PHY_2_0 = 0,
+	BRCM_USB_PHY_3_0,
+	BRCM_USB_PHY_ID_MAX
+};
+
+struct value_to_name_map {
+	int value;
+	const char *name;
+};
+
+static struct value_to_name_map brcm_dr_mode_to_name[] = {
+	{ USB_CTLR_MODE_HOST, "host" },
+	{ USB_CTLR_MODE_DEVICE, "peripheral" },
+	{ USB_CTLR_MODE_DRD, "drd" },
+	{ USB_CTLR_MODE_TYPEC_PD, "typec-pd" }
+};
+
+static struct value_to_name_map brcm_dual_mode_to_name[] = {
+	{ 0, "host" },
+	{ 1, "device" },
+	{ 2, "auto" },
+};
+
+struct brcm_usb_phy {
+	struct phy *phy;
+	unsigned int id;
+	bool inited;
+};
+
+struct brcm_usb_phy_data {
+	struct  brcm_usb_init_params ini;
+	bool			has_eohci;
+	bool			has_xhci;
+	struct clk		*usb_20_clk;
+	struct clk		*usb_30_clk;
+	struct mutex		mutex;	/* serialize phy init */
+	int			init_count;
+	struct brcm_usb_phy	phys[BRCM_USB_PHY_ID_MAX];
+};
+
+static int brcm_usb_phy_init(struct phy *gphy)
+{
+	struct brcm_usb_phy *phy = phy_get_drvdata(gphy);
+	struct brcm_usb_phy_data *priv =
+		container_of(phy, struct brcm_usb_phy_data, phys[phy->id]);
+
+	/*
+	 * Use a lock to make sure a second caller waits until
+	 * the base phy is inited before using it.
+	 */
+	mutex_lock(&priv->mutex);
+	if (priv->init_count++ == 0) {
+		clk_enable(priv->usb_20_clk);
+		clk_enable(priv->usb_30_clk);
+		brcm_usb_init_common(&priv->ini);
+	}
+	mutex_unlock(&priv->mutex);
+	if (phy->id == BRCM_USB_PHY_2_0)
+		brcm_usb_init_eohci(&priv->ini);
+	else if (phy->id == BRCM_USB_PHY_3_0)
+		brcm_usb_init_xhci(&priv->ini);
+	phy->inited = true;
+	dev_dbg(&gphy->dev, "INIT, id: %d, total: %d\n", phy->id,
+		priv->init_count);
+
+	return 0;
+}
+
+static int brcm_usb_phy_exit(struct phy *gphy)
+{
+	struct brcm_usb_phy *phy = phy_get_drvdata(gphy);
+	struct brcm_usb_phy_data *priv =
+		container_of(phy, struct brcm_usb_phy_data, phys[phy->id]);
+
+	dev_dbg(&gphy->dev, "EXIT\n");
+	if (phy->id == BRCM_USB_PHY_2_0)
+		brcm_usb_uninit_eohci(&priv->ini);
+	if (phy->id == BRCM_USB_PHY_3_0)
+		brcm_usb_uninit_xhci(&priv->ini);
+
+	/* If both xhci and eohci are gone, reset everything else */
+	mutex_lock(&priv->mutex);
+	if (--priv->init_count == 0) {
+		brcm_usb_uninit_common(&priv->ini);
+		clk_disable(priv->usb_20_clk);
+		clk_disable(priv->usb_30_clk);
+	}
+	mutex_unlock(&priv->mutex);
+	phy->inited = false;
+	return 0;
+}
+
+static struct phy_ops brcm_usb_phy_ops = {
+	.init		= brcm_usb_phy_init,
+	.exit		= brcm_usb_phy_exit,
+	.owner		= THIS_MODULE,
+};
+
+static struct phy *brcm_usb_phy_xlate(struct device *dev,
+				      struct of_phandle_args *args)
+{
+	struct brcm_usb_phy_data *data = dev_get_drvdata(dev);
+
+	/*
+	 * values 0 and 1 are for backward compatibility with
+	 * device tree nodes from older bootloaders.
+	 */
+	switch (args->args[0]) {
+	case 0:
+	case PHY_TYPE_USB2:
+		if (data->phys[BRCM_USB_PHY_2_0].phy)
+			return data->phys[BRCM_USB_PHY_2_0].phy;
+		dev_warn(dev, "Error, 2.0 Phy not found\n");
+		break;
+	case 1:
+	case PHY_TYPE_USB3:
+		if (data->phys[BRCM_USB_PHY_3_0].phy)
+			return data->phys[BRCM_USB_PHY_3_0].phy;
+		dev_warn(dev, "Error, 3.0 Phy not found\n");
+		break;
+	}
+	return ERR_PTR(-ENODEV);
+}
+
+static int name_to_value(struct value_to_name_map *table, int count,
+			 const char *name, int *value)
+{
+	int x;
+
+	*value = 0;
+	for (x = 0; x < count; x++) {
+		if (sysfs_streq(name, table[x].name)) {
+			*value = x;
+			return 0;
+		}
+	}
+	return -EINVAL;
+}
+
+static const char *value_to_name(struct value_to_name_map *table, int count,
+				 int value)
+{
+	if (value >= count)
+		return "unknown";
+	return table[value].name;
+}
+
+static ssize_t dr_mode_show(struct device *dev,
+			    struct device_attribute *attr,
+			    char *buf)
+{
+	struct brcm_usb_phy_data *priv = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%s\n",
+		value_to_name(&brcm_dr_mode_to_name[0],
+			      ARRAY_SIZE(brcm_dr_mode_to_name),
+			      priv->ini.mode));
+}
+static DEVICE_ATTR_RO(dr_mode);
+
+static ssize_t dual_select_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t len)
+{
+	struct brcm_usb_phy_data *priv = dev_get_drvdata(dev);
+	int value;
+	int res;
+
+	mutex_lock(&sysfs_lock);
+	res = name_to_value(&brcm_dual_mode_to_name[0],
+			    ARRAY_SIZE(brcm_dual_mode_to_name), buf, &value);
+	if (!res) {
+		brcm_usb_init_set_dual_select(&priv->ini, value);
+		res = len;
+	}
+	mutex_unlock(&sysfs_lock);
+	return res;
+}
+
+static ssize_t dual_select_show(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	struct brcm_usb_phy_data *priv = dev_get_drvdata(dev);
+	int value;
+
+	mutex_lock(&sysfs_lock);
+	value = brcm_usb_init_get_dual_select(&priv->ini);
+	mutex_unlock(&sysfs_lock);
+	return sprintf(buf, "%s\n",
+		value_to_name(&brcm_dual_mode_to_name[0],
+			      ARRAY_SIZE(brcm_dual_mode_to_name),
+			      value));
+}
+static DEVICE_ATTR_RW(dual_select);
+
+static struct attribute *brcm_usb_phy_attrs[] = {
+	&dev_attr_dr_mode.attr,
+	&dev_attr_dual_select.attr,
+	NULL
+};
+
+static const struct attribute_group brcm_usb_phy_group = {
+	.attrs = brcm_usb_phy_attrs,
+};
+
+static int brcm_usb_phy_dvr_init(struct device *dev,
+				 struct brcm_usb_phy_data *priv,
+				 struct device_node *dn)
+{
+	struct phy *gphy;
+	int err;
+
+	priv->usb_20_clk = of_clk_get_by_name(dn, "sw_usb");
+	if (IS_ERR(priv->usb_20_clk)) {
+		dev_info(dev, "Clock not found in Device Tree\n");
+		priv->usb_20_clk = NULL;
+	}
+	err = clk_prepare_enable(priv->usb_20_clk);
+	if (err)
+		return err;
+
+	if (priv->has_eohci) {
+		gphy = devm_phy_create(dev, NULL, &brcm_usb_phy_ops);
+		if (IS_ERR(gphy)) {
+			dev_err(dev, "failed to create EHCI/OHCI PHY\n");
+			return PTR_ERR(gphy);
+		}
+		priv->phys[BRCM_USB_PHY_2_0].phy = gphy;
+		priv->phys[BRCM_USB_PHY_2_0].id = BRCM_USB_PHY_2_0;
+		phy_set_drvdata(gphy, &priv->phys[BRCM_USB_PHY_2_0]);
+	}
+
+	if (priv->has_xhci) {
+		gphy = devm_phy_create(dev, NULL, &brcm_usb_phy_ops);
+		if (IS_ERR(gphy)) {
+			dev_err(dev, "failed to create XHCI PHY\n");
+			return PTR_ERR(gphy);
+		}
+		priv->phys[BRCM_USB_PHY_3_0].phy = gphy;
+		priv->phys[BRCM_USB_PHY_3_0].id = BRCM_USB_PHY_3_0;
+		phy_set_drvdata(gphy, &priv->phys[BRCM_USB_PHY_3_0]);
+
+		priv->usb_30_clk = of_clk_get_by_name(dn, "sw_usb3");
+		if (IS_ERR(priv->usb_30_clk)) {
+			dev_info(dev,
+				 "USB3.0 clock not found in Device Tree\n");
+			priv->usb_30_clk = NULL;
+		}
+		err = clk_prepare_enable(priv->usb_30_clk);
+		if (err)
+			return err;
+	}
+	return 0;
+}
+
+static int brcm_usb_phy_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct device *dev = &pdev->dev;
+	struct brcm_usb_phy_data *priv;
+	struct phy_provider *phy_provider;
+	struct device_node *dn = pdev->dev.of_node;
+	int err;
+	const char *mode;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, priv);
+
+	priv->ini.family_id = brcmstb_get_family_id();
+	priv->ini.product_id = brcmstb_get_product_id();
+	brcm_usb_set_family_map(&priv->ini);
+	dev_dbg(dev, "Best mapping table is for %s\n",
+		priv->ini.family_name);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "can't get USB_CTRL base address\n");
+		return -EINVAL;
+	}
+	priv->ini.ctrl_regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(priv->ini.ctrl_regs)) {
+		dev_err(dev, "can't map CTRL register space\n");
+		return -EINVAL;
+	}
+
+	/* The XHCI EC registers are optional */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (res) {
+		priv->ini.xhci_ec_regs =
+			devm_ioremap_resource(dev, res);
+		if (IS_ERR(priv->ini.xhci_ec_regs)) {
+			dev_err(dev, "can't map XHCI EC register space\n");
+			return -EINVAL;
+		}
+	}
+
+	of_property_read_u32(dn, "brcm,ipp", &priv->ini.ipp);
+	of_property_read_u32(dn, "brcm,ioc", &priv->ini.ioc);
+
+	priv->ini.mode = USB_CTLR_MODE_HOST;
+	err = of_property_read_string(dn, "dr_mode", &mode);
+	if (err == 0) {
+		name_to_value(&brcm_dr_mode_to_name[0],
+			      ARRAY_SIZE(brcm_dr_mode_to_name),
+			mode, &priv->ini.mode);
+	}
+	if (of_property_read_bool(dn, "brcm,has_xhci"))
+		priv->has_xhci = true;
+	if (of_property_read_bool(dn, "brcm,has_eohci"))
+		priv->has_eohci = true;
+
+	err = brcm_usb_phy_dvr_init(dev, priv, dn);
+	if (err)
+		return err;
+
+	mutex_init(&priv->mutex);
+
+	/* make sure invert settings are correct */
+	brcm_usb_init_ipp(&priv->ini);
+
+	/*
+	 * Create sysfs entries for mode.
+	 * Remove "dual_select" attribute if not in dual mode
+	 */
+	if (priv->ini.mode != USB_CTLR_MODE_DRD)
+		brcm_usb_phy_attrs[1] = NULL;
+	err = sysfs_create_group(&dev->kobj, &brcm_usb_phy_group);
+	if (err)
+		dev_warn(dev, "Error creating sysfs attributes\n");
+
+	/* start with everything off */
+	if (priv->has_xhci)
+		brcm_usb_uninit_xhci(&priv->ini);
+	if (priv->has_eohci)
+		brcm_usb_uninit_eohci(&priv->ini);
+	brcm_usb_uninit_common(&priv->ini);
+	clk_disable(priv->usb_20_clk);
+	clk_disable(priv->usb_30_clk);
+
+	phy_provider = devm_of_phy_provider_register(dev, brcm_usb_phy_xlate);
+	if (IS_ERR(phy_provider))
+		return PTR_ERR(phy_provider);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int brcm_usb_phy_suspend(struct device *dev)
+{
+	struct brcm_usb_phy_data *priv = dev_get_drvdata(dev);
+
+	if (priv->init_count) {
+		clk_disable(priv->usb_20_clk);
+		clk_disable(priv->usb_30_clk);
+	}
+	return 0;
+}
+
+static int brcm_usb_phy_resume(struct device *dev)
+{
+	struct brcm_usb_phy_data *priv = dev_get_drvdata(dev);
+
+	clk_enable(priv->usb_20_clk);
+	clk_enable(priv->usb_30_clk);
+	brcm_usb_init_ipp(&priv->ini);
+
+	/*
+	 * Initialize anything that was previously initialized.
+	 * Uninitialize anything that wasn't previously initialized.
+	 */
+	if (priv->init_count) {
+		brcm_usb_init_common(&priv->ini);
+		if (priv->phys[BRCM_USB_PHY_2_0].inited) {
+			brcm_usb_init_eohci(&priv->ini);
+		} else if (priv->has_eohci) {
+			brcm_usb_uninit_eohci(&priv->ini);
+			clk_disable(priv->usb_20_clk);
+		}
+		if (priv->phys[BRCM_USB_PHY_3_0].inited) {
+			brcm_usb_init_xhci(&priv->ini);
+		} else if (priv->has_xhci) {
+			brcm_usb_uninit_xhci(&priv->ini);
+			clk_disable(priv->usb_30_clk);
+		}
+	} else {
+		if (priv->has_xhci)
+			brcm_usb_uninit_xhci(&priv->ini);
+		if (priv->has_eohci)
+			brcm_usb_uninit_eohci(&priv->ini);
+		brcm_usb_uninit_common(&priv->ini);
+		clk_disable(priv->usb_20_clk);
+		clk_disable(priv->usb_30_clk);
+	}
+
+	return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static const struct dev_pm_ops brcm_usb_phy_pm_ops = {
+	SET_LATE_SYSTEM_SLEEP_PM_OPS(brcm_usb_phy_suspend, brcm_usb_phy_resume)
+};
+
+static const struct of_device_id brcm_usb_dt_ids[] = {
+	{ .compatible = "brcm,brcmstb-usb-phy" },
+	{ /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, brcm_usb_dt_ids);
+
+static struct platform_driver brcm_usb_driver = {
+	.probe		= brcm_usb_phy_probe,
+	.driver		= {
+		.name	= "brcmstb-usb-phy",
+		.owner	= THIS_MODULE,
+		.pm = &brcm_usb_phy_pm_ops,
+		.of_match_table = brcm_usb_dt_ids,
+	},
+};
+
+module_platform_driver(brcm_usb_driver);
+
+MODULE_ALIAS("platform:brcmstb-usb-phy");
+MODULE_AUTHOR("Al Cooper <acooper@broadcom.com>");
+MODULE_DESCRIPTION("BRCM USB PHY driver");
+MODULE_LICENSE("GPL v2");

+ 0 - 1
drivers/phy/marvell/phy-mvebu-cp110-comphy.c

@@ -154,7 +154,6 @@ struct mvebu_comphy_priv {
 	void __iomem *base;
 	struct regmap *regmap;
 	struct device *dev;
-	int modes[MVEBU_COMPHY_LANES];
 };
 
 struct mvebu_comphy_lane {

+ 39 - 0
drivers/phy/mediatek/phy-mtk-tphy.c

@@ -96,9 +96,11 @@
 
 #define U3P_U2PHYDTM1		0x06C
 #define P2C_RG_UART_EN			BIT(16)
+#define P2C_FORCE_IDDIG		BIT(9)
 #define P2C_RG_VBUSVALID		BIT(5)
 #define P2C_RG_SESSEND			BIT(4)
 #define P2C_RG_AVALID			BIT(2)
+#define P2C_RG_IDDIG			BIT(1)
 
 #define U3P_U3_CHIP_GPIO_CTLD		0x0c
 #define P3C_REG_IP_SW_RST		BIT(31)
@@ -585,6 +587,31 @@ static void u2_phy_instance_exit(struct mtk_tphy *tphy,
 	}
 }
 
+static void u2_phy_instance_set_mode(struct mtk_tphy *tphy,
+				     struct mtk_phy_instance *instance,
+				     enum phy_mode mode)
+{
+	struct u2phy_banks *u2_banks = &instance->u2_banks;
+	u32 tmp;
+
+	tmp = readl(u2_banks->com + U3P_U2PHYDTM1);
+	switch (mode) {
+	case PHY_MODE_USB_DEVICE:
+		tmp |= P2C_FORCE_IDDIG | P2C_RG_IDDIG;
+		break;
+	case PHY_MODE_USB_HOST:
+		tmp |= P2C_FORCE_IDDIG;
+		tmp &= ~P2C_RG_IDDIG;
+		break;
+	case PHY_MODE_USB_OTG:
+		tmp &= ~(P2C_FORCE_IDDIG | P2C_RG_IDDIG);
+		break;
+	default:
+		return;
+	}
+	writel(tmp, u2_banks->com + U3P_U2PHYDTM1);
+}
+
 static void pcie_phy_instance_init(struct mtk_tphy *tphy,
 	struct mtk_phy_instance *instance)
 {
@@ -881,6 +908,17 @@ static int mtk_phy_exit(struct phy *phy)
 	return 0;
 }
 
+static int mtk_phy_set_mode(struct phy *phy, enum phy_mode mode)
+{
+	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_set_mode(tphy, instance, mode);
+
+	return 0;
+}
+
 static struct phy *mtk_phy_xlate(struct device *dev,
 					struct of_phandle_args *args)
 {
@@ -931,6 +969,7 @@ static const struct phy_ops mtk_tphy_ops = {
 	.exit		= mtk_phy_exit,
 	.power_on	= mtk_phy_power_on,
 	.power_off	= mtk_phy_power_off,
+	.set_mode	= mtk_phy_set_mode,
 	.owner		= THIS_MODULE,
 };
 

+ 15 - 0
drivers/phy/phy-core.c

@@ -372,6 +372,21 @@ int phy_reset(struct phy *phy)
 }
 EXPORT_SYMBOL_GPL(phy_reset);
 
+int phy_calibrate(struct phy *phy)
+{
+	int ret;
+
+	if (!phy || !phy->ops->calibrate)
+		return 0;
+
+	mutex_lock(&phy->mutex);
+	ret = phy->ops->calibrate(phy);
+	mutex_unlock(&phy->mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(phy_calibrate);
+
 /**
  * _of_phy_get() - lookup and obtain a reference to a phy by phandle
  * @np: device_node for which to get the phy

+ 3 - 2
drivers/phy/qualcomm/phy-qcom-ufs-i.h

@@ -114,14 +114,16 @@ struct ufs_qcom_phy {
 	struct ufs_qcom_phy_calibration *cached_regs;
 	int cached_regs_table_size;
 	bool is_powered_on;
+	bool is_started;
 	struct ufs_qcom_phy_specific_ops *phy_spec_ops;
+
+	enum phy_mode mode;
 };
 
 /**
  * struct ufs_qcom_phy_specific_ops - set of pointers to functions which have a
  * specific implementation per phy. Each UFS phy, should implement
  * those functions according to its spec and requirements
- * @calibrate_phy: pointer to a function that calibrate the phy
  * @start_serdes: pointer to a function that starts the serdes
  * @is_physical_coding_sublayer_ready: pointer to a function that
  * checks pcs readiness. returns 0 for success and non-zero for error.
@@ -130,7 +132,6 @@ struct ufs_qcom_phy {
  * and writes to QSERDES_RX_SIGDET_CNTRL attribute
  */
 struct ufs_qcom_phy_specific_ops {
-	int (*calibrate_phy)(struct ufs_qcom_phy *phy, bool is_rate_B);
 	void (*start_serdes)(struct ufs_qcom_phy *phy);
 	int (*is_physical_coding_sublayer_ready)(struct ufs_qcom_phy *phy);
 	void (*set_tx_lane_enable)(struct ufs_qcom_phy *phy, u32 val);

+ 27 - 2
drivers/phy/qualcomm/phy-qcom-ufs-qmp-14nm.c

@@ -44,7 +44,19 @@ void ufs_qcom_phy_qmp_14nm_advertise_quirks(struct ufs_qcom_phy *phy_common)
 
 static int ufs_qcom_phy_qmp_14nm_init(struct phy *generic_phy)
 {
-	return 0;
+	struct ufs_qcom_phy *phy_common = get_ufs_qcom_phy(generic_phy);
+	bool is_rate_B = false;
+	int ret;
+
+	if (phy_common->mode == PHY_MODE_UFS_HS_B)
+		is_rate_B = true;
+
+	ret = ufs_qcom_phy_qmp_14nm_phy_calibrate(phy_common, is_rate_B);
+	if (!ret)
+		/* phy calibrated, but yet to be started */
+		phy_common->is_started = false;
+
+	return ret;
 }
 
 static int ufs_qcom_phy_qmp_14nm_exit(struct phy *generic_phy)
@@ -52,6 +64,19 @@ static int ufs_qcom_phy_qmp_14nm_exit(struct phy *generic_phy)
 	return 0;
 }
 
+static
+int ufs_qcom_phy_qmp_14nm_set_mode(struct phy *generic_phy, enum phy_mode mode)
+{
+	struct ufs_qcom_phy *phy_common = get_ufs_qcom_phy(generic_phy);
+
+	phy_common->mode = PHY_MODE_INVALID;
+
+	if (mode > 0)
+		phy_common->mode = mode;
+
+	return 0;
+}
+
 static
 void ufs_qcom_phy_qmp_14nm_power_control(struct ufs_qcom_phy *phy, bool val)
 {
@@ -102,11 +127,11 @@ static const struct phy_ops ufs_qcom_phy_qmp_14nm_phy_ops = {
 	.exit		= ufs_qcom_phy_qmp_14nm_exit,
 	.power_on	= ufs_qcom_phy_power_on,
 	.power_off	= ufs_qcom_phy_power_off,
+	.set_mode	= ufs_qcom_phy_qmp_14nm_set_mode,
 	.owner		= THIS_MODULE,
 };
 
 static struct ufs_qcom_phy_specific_ops phy_14nm_ops = {
-	.calibrate_phy		= ufs_qcom_phy_qmp_14nm_phy_calibrate,
 	.start_serdes		= ufs_qcom_phy_qmp_14nm_start_serdes,
 	.is_physical_coding_sublayer_ready = ufs_qcom_phy_qmp_14nm_is_pcs_ready,
 	.set_tx_lane_enable	= ufs_qcom_phy_qmp_14nm_set_tx_lane_enable,

+ 27 - 2
drivers/phy/qualcomm/phy-qcom-ufs-qmp-20nm.c

@@ -63,7 +63,19 @@ void ufs_qcom_phy_qmp_20nm_advertise_quirks(struct ufs_qcom_phy *phy_common)
 
 static int ufs_qcom_phy_qmp_20nm_init(struct phy *generic_phy)
 {
-	return 0;
+	struct ufs_qcom_phy *phy_common = get_ufs_qcom_phy(generic_phy);
+	bool is_rate_B = false;
+	int ret;
+
+	if (phy_common->mode == PHY_MODE_UFS_HS_B)
+		is_rate_B = true;
+
+	ret = ufs_qcom_phy_qmp_20nm_phy_calibrate(phy_common, is_rate_B);
+	if (!ret)
+		/* phy calibrated, but yet to be started */
+		phy_common->is_started = false;
+
+	return ret;
 }
 
 static int ufs_qcom_phy_qmp_20nm_exit(struct phy *generic_phy)
@@ -71,6 +83,19 @@ static int ufs_qcom_phy_qmp_20nm_exit(struct phy *generic_phy)
 	return 0;
 }
 
+static
+int ufs_qcom_phy_qmp_20nm_set_mode(struct phy *generic_phy, enum phy_mode mode)
+{
+	struct ufs_qcom_phy *phy_common = get_ufs_qcom_phy(generic_phy);
+
+	phy_common->mode = PHY_MODE_INVALID;
+
+	if (mode > 0)
+		phy_common->mode = mode;
+
+	return 0;
+}
+
 static
 void ufs_qcom_phy_qmp_20nm_power_control(struct ufs_qcom_phy *phy, bool val)
 {
@@ -160,11 +185,11 @@ static const struct phy_ops ufs_qcom_phy_qmp_20nm_phy_ops = {
 	.exit		= ufs_qcom_phy_qmp_20nm_exit,
 	.power_on	= ufs_qcom_phy_power_on,
 	.power_off	= ufs_qcom_phy_power_off,
+	.set_mode	= ufs_qcom_phy_qmp_20nm_set_mode,
 	.owner		= THIS_MODULE,
 };
 
 static struct ufs_qcom_phy_specific_ops phy_20nm_ops = {
-	.calibrate_phy		= ufs_qcom_phy_qmp_20nm_phy_calibrate,
 	.start_serdes		= ufs_qcom_phy_qmp_20nm_start_serdes,
 	.is_physical_coding_sublayer_ready = ufs_qcom_phy_qmp_20nm_is_pcs_ready,
 	.set_tx_lane_enable	= ufs_qcom_phy_qmp_20nm_set_tx_lane_enable,

+ 14 - 28
drivers/phy/qualcomm/phy-qcom-ufs.c

@@ -518,9 +518,8 @@ void ufs_qcom_phy_disable_iface_clk(struct ufs_qcom_phy *phy)
 	}
 }
 
-int ufs_qcom_phy_start_serdes(struct phy *generic_phy)
+static int ufs_qcom_phy_start_serdes(struct ufs_qcom_phy *ufs_qcom_phy)
 {
-	struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy);
 	int ret = 0;
 
 	if (!ufs_qcom_phy->phy_spec_ops->start_serdes) {
@@ -533,7 +532,6 @@ int ufs_qcom_phy_start_serdes(struct phy *generic_phy)
 
 	return ret;
 }
-EXPORT_SYMBOL_GPL(ufs_qcom_phy_start_serdes);
 
 int ufs_qcom_phy_set_tx_lane_enable(struct phy *generic_phy, u32 tx_lanes)
 {
@@ -564,31 +562,8 @@ void ufs_qcom_phy_save_controller_version(struct phy *generic_phy,
 }
 EXPORT_SYMBOL_GPL(ufs_qcom_phy_save_controller_version);
 
-int ufs_qcom_phy_calibrate_phy(struct phy *generic_phy, bool is_rate_B)
-{
-	struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy);
-	int ret = 0;
-
-	if (!ufs_qcom_phy->phy_spec_ops->calibrate_phy) {
-		dev_err(ufs_qcom_phy->dev, "%s: calibrate_phy() callback is not supported\n",
-			__func__);
-		ret = -ENOTSUPP;
-	} else {
-		ret = ufs_qcom_phy->phy_spec_ops->
-				calibrate_phy(ufs_qcom_phy, is_rate_B);
-		if (ret)
-			dev_err(ufs_qcom_phy->dev, "%s: calibrate_phy() failed %d\n",
-				__func__, ret);
-	}
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(ufs_qcom_phy_calibrate_phy);
-
-int ufs_qcom_phy_is_pcs_ready(struct phy *generic_phy)
+static int ufs_qcom_phy_is_pcs_ready(struct ufs_qcom_phy *ufs_qcom_phy)
 {
-	struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy);
-
 	if (!ufs_qcom_phy->phy_spec_ops->is_physical_coding_sublayer_ready) {
 		dev_err(ufs_qcom_phy->dev, "%s: is_physical_coding_sublayer_ready() callback is not supported\n",
 			__func__);
@@ -598,7 +573,6 @@ int ufs_qcom_phy_is_pcs_ready(struct phy *generic_phy)
 	return ufs_qcom_phy->phy_spec_ops->
 			is_physical_coding_sublayer_ready(ufs_qcom_phy);
 }
-EXPORT_SYMBOL_GPL(ufs_qcom_phy_is_pcs_ready);
 
 int ufs_qcom_phy_power_on(struct phy *generic_phy)
 {
@@ -609,6 +583,18 @@ int ufs_qcom_phy_power_on(struct phy *generic_phy)
 	if (phy_common->is_powered_on)
 		return 0;
 
+	if (!phy_common->is_started) {
+		err = ufs_qcom_phy_start_serdes(phy_common);
+		if (err)
+			return err;
+
+		err = ufs_qcom_phy_is_pcs_ready(phy_common);
+		if (err)
+			return err;
+
+		phy_common->is_started = true;
+	}
+
 	err = ufs_qcom_phy_enable_vreg(dev, &phy_common->vdda_phy);
 	if (err) {
 		dev_err(dev, "%s enable vdda_phy failed, err=%d\n",

+ 47 - 25
drivers/phy/renesas/phy-rcar-gen3-usb2.c

@@ -1,7 +1,7 @@
 /*
  * Renesas R-Car Gen3 for USB2.0 PHY driver
  *
- * Copyright (C) 2015 Renesas Electronics Corporation
+ * Copyright (C) 2015-2017 Renesas Electronics Corporation
  *
  * This is based on the phy-rcar-gen2 driver:
  * Copyright (C) 2014 Renesas Solutions Corp.
@@ -12,16 +12,18 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/of_device.h>
 #include <linux/phy/phy.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/regulator/consumer.h>
+#include <linux/usb/of.h>
 #include <linux/workqueue.h>
 
 /******* USB2.0 Host registers (original offset is +0x200) *******/
@@ -79,6 +81,8 @@
 #define USB2_ADPCTRL_IDPULLUP		BIT(5)	/* 1 = ID sampling is enabled */
 #define USB2_ADPCTRL_DRVVBUS		BIT(4)
 
+#define RCAR_GEN3_PHY_HAS_DEDICATED_PINS	1
+
 struct rcar_gen3_chan {
 	void __iomem *base;
 	struct extcon_dev *extcon;
@@ -86,7 +90,7 @@ struct rcar_gen3_chan {
 	struct regulator *vbus;
 	struct work_struct work;
 	bool extcon_host;
-	bool has_otg;
+	bool has_otg_pins;
 };
 
 static void rcar_gen3_phy_usb2_work(struct work_struct *work)
@@ -218,33 +222,40 @@ static bool rcar_gen3_is_host(struct rcar_gen3_chan *ch)
 	return !(readl(ch->base + USB2_COMMCTRL) & USB2_COMMCTRL_OTG_PERI);
 }
 
+static enum phy_mode rcar_gen3_get_phy_mode(struct rcar_gen3_chan *ch)
+{
+	if (rcar_gen3_is_host(ch))
+		return PHY_MODE_USB_HOST;
+
+	return PHY_MODE_USB_DEVICE;
+}
+
 static ssize_t role_store(struct device *dev, struct device_attribute *attr,
 			  const char *buf, size_t count)
 {
 	struct rcar_gen3_chan *ch = dev_get_drvdata(dev);
-	bool is_b_device, is_host, new_mode_is_host;
+	bool is_b_device;
+	enum phy_mode cur_mode, new_mode;
 
-	if (!ch->has_otg || !ch->phy->init_count)
+	if (!ch->has_otg_pins || !ch->phy->init_count)
 		return -EIO;
 
-	/*
-	 * is_b_device: true is B-Device. false is A-Device.
-	 * If {new_mode_}is_host: true is Host mode. false is Peripheral mode.
-	 */
-	is_b_device = rcar_gen3_check_id(ch);
-	is_host = rcar_gen3_is_host(ch);
 	if (!strncmp(buf, "host", strlen("host")))
-		new_mode_is_host = true;
+		new_mode = PHY_MODE_USB_HOST;
 	else if (!strncmp(buf, "peripheral", strlen("peripheral")))
-		new_mode_is_host = false;
+		new_mode = PHY_MODE_USB_DEVICE;
 	else
 		return -EINVAL;
 
+	/* is_b_device: true is B-Device. false is A-Device. */
+	is_b_device = rcar_gen3_check_id(ch);
+	cur_mode = rcar_gen3_get_phy_mode(ch);
+
 	/* If current and new mode is the same, this returns the error */
-	if (is_host == new_mode_is_host)
+	if (cur_mode == new_mode)
 		return -EINVAL;
 
-	if (new_mode_is_host) {		/* And is_host must be false */
+	if (new_mode == PHY_MODE_USB_HOST) { /* And is_host must be false */
 		if (!is_b_device)	/* A-Peripheral */
 			rcar_gen3_init_from_a_peri_to_a_host(ch);
 		else			/* B-Peripheral */
@@ -264,7 +275,7 @@ static ssize_t role_show(struct device *dev, struct device_attribute *attr,
 {
 	struct rcar_gen3_chan *ch = dev_get_drvdata(dev);
 
-	if (!ch->has_otg || !ch->phy->init_count)
+	if (!ch->has_otg_pins || !ch->phy->init_count)
 		return -EIO;
 
 	return sprintf(buf, "%s\n", rcar_gen3_is_host(ch) ? "host" :
@@ -303,7 +314,7 @@ static int rcar_gen3_phy_usb2_init(struct phy *p)
 	writel(USB2_OC_TIMSET_INIT, usb2_base + USB2_OC_TIMSET);
 
 	/* Initialize otg part */
-	if (channel->has_otg)
+	if (channel->has_otg_pins)
 		rcar_gen3_init_otg(channel);
 
 	return 0;
@@ -377,9 +388,17 @@ static irqreturn_t rcar_gen3_phy_usb2_irq(int irq, void *_ch)
 }
 
 static const struct of_device_id rcar_gen3_phy_usb2_match_table[] = {
-	{ .compatible = "renesas,usb2-phy-r8a7795" },
-	{ .compatible = "renesas,usb2-phy-r8a7796" },
-	{ .compatible = "renesas,rcar-gen3-usb2-phy" },
+	{
+		.compatible = "renesas,usb2-phy-r8a7795",
+		.data = (void *)RCAR_GEN3_PHY_HAS_DEDICATED_PINS,
+	},
+	{
+		.compatible = "renesas,usb2-phy-r8a7796",
+		.data = (void *)RCAR_GEN3_PHY_HAS_DEDICATED_PINS,
+	},
+	{
+		.compatible = "renesas,rcar-gen3-usb2-phy",
+	},
 	{ }
 };
 MODULE_DEVICE_TABLE(of, rcar_gen3_phy_usb2_match_table);
@@ -415,14 +434,17 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
 	/* call request_irq for OTG */
 	irq = platform_get_irq(pdev, 0);
 	if (irq >= 0) {
-		int ret;
-
 		INIT_WORK(&channel->work, rcar_gen3_phy_usb2_work);
 		irq = devm_request_irq(dev, irq, rcar_gen3_phy_usb2_irq,
 				       IRQF_SHARED, dev_name(dev), channel);
 		if (irq < 0)
 			dev_err(dev, "No irq handler (%d)\n", irq);
-		channel->has_otg = true;
+	}
+
+	if (of_usb_get_dr_mode_by_phy(dev->of_node, 0) == USB_DR_MODE_OTG) {
+		int ret;
+
+		channel->has_otg_pins = (uintptr_t)of_device_get_match_data(dev);
 		channel->extcon = devm_extcon_dev_allocate(dev,
 							rcar_gen3_phy_cable);
 		if (IS_ERR(channel->extcon))
@@ -464,7 +486,7 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev)
 		dev_err(dev, "Failed to register PHY provider\n");
 		ret = PTR_ERR(provider);
 		goto error;
-	} else if (channel->has_otg) {
+	} else if (channel->has_otg_pins) {
 		int ret;
 
 		ret = device_create_file(dev, &dev_attr_role);
@@ -484,7 +506,7 @@ static int rcar_gen3_phy_usb2_remove(struct platform_device *pdev)
 {
 	struct rcar_gen3_chan *channel = platform_get_drvdata(pdev);
 
-	if (channel->has_otg)
+	if (channel->has_otg_pins)
 		device_remove_file(&pdev->dev, &dev_attr_role);
 
 	pm_runtime_disable(&pdev->dev);

+ 1 - 1
drivers/phy/rockchip/phy-rockchip-inno-usb2.c

@@ -17,7 +17,7 @@
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/delay.h>
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/gpio/consumer.h>

+ 175 - 42
drivers/phy/rockchip/phy-rockchip-typec.c

@@ -102,9 +102,40 @@
 #define CMN_PLL1_SS_CTRL1		(0xb8 << 2)
 #define CMN_PLL1_SS_CTRL2		(0xb9 << 2)
 #define CMN_RXCAL_OVRD			(0xd1 << 2)
+
 #define CMN_TXPUCAL_CTRL		(0xe0 << 2)
 #define CMN_TXPUCAL_OVRD		(0xe1 << 2)
+#define CMN_TXPDCAL_CTRL		(0xf0 << 2)
 #define CMN_TXPDCAL_OVRD		(0xf1 << 2)
+
+/* For CMN_TXPUCAL_CTRL, CMN_TXPDCAL_CTRL */
+#define CMN_TXPXCAL_START		BIT(15)
+#define CMN_TXPXCAL_DONE		BIT(14)
+#define CMN_TXPXCAL_NO_RESPONSE		BIT(13)
+#define CMN_TXPXCAL_CURRENT_RESPONSE	BIT(12)
+
+#define CMN_TXPU_ADJ_CTRL		(0x108 << 2)
+#define CMN_TXPD_ADJ_CTRL		(0x10c << 2)
+
+/*
+ * For CMN_TXPUCAL_CTRL, CMN_TXPDCAL_CTRL,
+ *     CMN_TXPU_ADJ_CTRL, CMN_TXPDCAL_CTRL
+ *
+ * NOTE: some of these registers are documented to be 2's complement
+ * signed numbers, but then documented to be always positive.  Weird.
+ * In such a case, using CMN_CALIB_CODE_POS() avoids the unnecessary
+ * sign extension.
+ */
+#define CMN_CALIB_CODE_WIDTH	7
+#define CMN_CALIB_CODE_OFFSET	0
+#define CMN_CALIB_CODE_MASK	GENMASK(CMN_CALIB_CODE_WIDTH, 0)
+#define CMN_CALIB_CODE(x)	\
+	sign_extend32((x) >> CMN_CALIB_CODE_OFFSET, CMN_CALIB_CODE_WIDTH)
+
+#define CMN_CALIB_CODE_POS_MASK	GENMASK(CMN_CALIB_CODE_WIDTH - 1, 0)
+#define CMN_CALIB_CODE_POS(x)	\
+	(((x) >> CMN_CALIB_CODE_OFFSET) & CMN_CALIB_CODE_POS_MASK)
+
 #define CMN_DIAG_PLL0_FBH_OVRD		(0x1c0 << 2)
 #define CMN_DIAG_PLL0_FBL_OVRD		(0x1c1 << 2)
 #define CMN_DIAG_PLL0_OVRD		(0x1c2 << 2)
@@ -138,6 +169,15 @@
 #define TX_TXCC_MGNFS_MULT_101(n)	((0x4055 | ((n) << 9)) << 2)
 #define TX_TXCC_MGNFS_MULT_110(n)	((0x4056 | ((n) << 9)) << 2)
 #define TX_TXCC_MGNFS_MULT_111(n)	((0x4057 | ((n) << 9)) << 2)
+#define TX_TXCC_MGNLS_MULT_000(n)	((0x4058 | ((n) << 9)) << 2)
+#define TX_TXCC_MGNLS_MULT_001(n)	((0x4059 | ((n) << 9)) << 2)
+#define TX_TXCC_MGNLS_MULT_010(n)	((0x405a | ((n) << 9)) << 2)
+#define TX_TXCC_MGNLS_MULT_011(n)	((0x405b | ((n) << 9)) << 2)
+#define TX_TXCC_MGNLS_MULT_100(n)	((0x405c | ((n) << 9)) << 2)
+#define TX_TXCC_MGNLS_MULT_101(n)	((0x405d | ((n) << 9)) << 2)
+#define TX_TXCC_MGNLS_MULT_110(n)	((0x405e | ((n) << 9)) << 2)
+#define TX_TXCC_MGNLS_MULT_111(n)	((0x405f | ((n) << 9)) << 2)
+
 #define XCVR_DIAG_PLLDRC_CTRL(n)	((0x40e0 | ((n) << 9)) << 2)
 #define XCVR_DIAG_BIDI_CTRL(n)		((0x40e8 | ((n) << 9)) << 2)
 #define XCVR_DIAG_LANE_FCM_EN_MGN(n)	((0x40f2 | ((n) << 9)) << 2)
@@ -150,10 +190,63 @@
 #define TX_RCVDET_ST_TMR(n)		((0x4123 | ((n) << 9)) << 2)
 #define TX_DIAG_TX_DRV(n)		((0x41e1 | ((n) << 9)) << 2)
 #define TX_DIAG_BGREF_PREDRV_DELAY	(0x41e7 << 2)
+
+/* Use this for "n" in macros like "_MULT_XXX" to target the aux channel */
+#define AUX_CH_LANE			8
+
 #define TX_ANA_CTRL_REG_1		(0x5020 << 2)
+
+#define TXDA_DP_AUX_EN			BIT(15)
+#define AUXDA_SE_EN			BIT(14)
+#define TXDA_CAL_LATCH_EN		BIT(13)
+#define AUXDA_POLARITY			BIT(12)
+#define TXDA_DRV_POWER_ISOLATION_EN	BIT(11)
+#define TXDA_DRV_POWER_EN_PH_2_N	BIT(10)
+#define TXDA_DRV_POWER_EN_PH_1_N	BIT(9)
+#define TXDA_BGREF_EN			BIT(8)
+#define TXDA_DRV_LDO_EN			BIT(7)
+#define TXDA_DECAP_EN_DEL		BIT(6)
+#define TXDA_DECAP_EN			BIT(5)
+#define TXDA_UPHY_SUPPLY_EN_DEL		BIT(4)
+#define TXDA_UPHY_SUPPLY_EN		BIT(3)
+#define TXDA_LOW_LEAKAGE_EN		BIT(2)
+#define TXDA_DRV_IDLE_LOWI_EN		BIT(1)
+#define TXDA_DRV_CMN_MODE_EN		BIT(0)
+
 #define TX_ANA_CTRL_REG_2		(0x5021 << 2)
+
+#define AUXDA_DEBOUNCING_CLK		BIT(15)
+#define TXDA_LPBK_RECOVERED_CLK_EN	BIT(14)
+#define TXDA_LPBK_ISI_GEN_EN		BIT(13)
+#define TXDA_LPBK_SERIAL_EN		BIT(12)
+#define TXDA_LPBK_LINE_EN		BIT(11)
+#define TXDA_DRV_LDO_REDC_SINKIQ	BIT(10)
+#define XCVR_DECAP_EN_DEL		BIT(9)
+#define XCVR_DECAP_EN			BIT(8)
+#define TXDA_MPHY_ENABLE_HS_NT		BIT(7)
+#define TXDA_MPHY_SA_MODE		BIT(6)
+#define TXDA_DRV_LDO_RBYR_FB_EN		BIT(5)
+#define TXDA_DRV_RST_PULL_DOWN		BIT(4)
+#define TXDA_DRV_LDO_BG_FB_EN		BIT(3)
+#define TXDA_DRV_LDO_BG_REF_EN		BIT(2)
+#define TXDA_DRV_PREDRV_EN_DEL		BIT(1)
+#define TXDA_DRV_PREDRV_EN		BIT(0)
+
 #define TXDA_COEFF_CALC_CTRL		(0x5022 << 2)
+
+#define TX_HIGH_Z			BIT(6)
+#define TX_VMARGIN_OFFSET		3
+#define TX_VMARGIN_MASK			0x7
+#define LOW_POWER_SWING_EN		BIT(2)
+#define TX_FCM_DRV_MAIN_EN		BIT(1)
+#define TX_FCM_FULL_MARGIN		BIT(0)
+
 #define TX_DIG_CTRL_REG_2		(0x5024 << 2)
+
+#define TX_HIGH_Z_TM_EN			BIT(15)
+#define TX_RESCAL_CODE_OFFSET		0
+#define TX_RESCAL_CODE_MASK		0x3f
+
 #define TXDA_CYA_AUXDA_CYA		(0x5025 << 2)
 #define TX_ANA_CTRL_REG_3		(0x5026 << 2)
 #define TX_ANA_CTRL_REG_4		(0x5027 << 2)
@@ -456,54 +549,72 @@ static void tcphy_dp_aux_set_flip(struct rockchip_typec_phy *tcphy)
 	 */
 	tx_ana_ctrl_reg_1 = readl(tcphy->base + TX_ANA_CTRL_REG_1);
 	if (!tcphy->flip)
-		tx_ana_ctrl_reg_1 |= BIT(12);
+		tx_ana_ctrl_reg_1 |= AUXDA_POLARITY;
 	else
-		tx_ana_ctrl_reg_1 &= ~BIT(12);
+		tx_ana_ctrl_reg_1 &= ~AUXDA_POLARITY;
 	writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1);
 }
 
 static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy)
 {
+	u16 val;
 	u16 tx_ana_ctrl_reg_1;
-	u16 rdata, rdata2, val;
-
-	/* disable txda_cal_latch_en for rewrite the calibration values */
-	tx_ana_ctrl_reg_1 = readl(tcphy->base + TX_ANA_CTRL_REG_1);
-	tx_ana_ctrl_reg_1 &= ~BIT(13);
-	writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1);
+	u16 tx_ana_ctrl_reg_2;
+	s32 pu_calib_code, pd_calib_code;
+	s32 pu_adj, pd_adj;
+	u16 calib;
 
 	/*
-	 * read a resistor calibration code from CMN_TXPUCAL_CTRL[6:0] and
-	 * write it to TX_DIG_CTRL_REG_2[6:0], and delay 1ms to make sure it
-	 * works.
+	 * Calculate calibration code as per docs: use an average of the
+	 * pull down and pull up.  Then add in adjustments.
 	 */
-	rdata = readl(tcphy->base + TX_DIG_CTRL_REG_2);
-	rdata = rdata & 0xffc0;
+	val = readl(tcphy->base + CMN_TXPUCAL_CTRL);
+	pu_calib_code = CMN_CALIB_CODE_POS(val);
+	val = readl(tcphy->base + CMN_TXPDCAL_CTRL);
+	pd_calib_code = CMN_CALIB_CODE_POS(val);
+	val = readl(tcphy->base + CMN_TXPU_ADJ_CTRL);
+	pu_adj = CMN_CALIB_CODE(val);
+	val = readl(tcphy->base + CMN_TXPD_ADJ_CTRL);
+	pd_adj = CMN_CALIB_CODE(val);
+	calib = (pu_calib_code + pd_calib_code) / 2 + pu_adj + pd_adj;
 
-	rdata2 = readl(tcphy->base + CMN_TXPUCAL_CTRL);
-	rdata2 = rdata2 & 0x3f;
+	/* disable txda_cal_latch_en for rewrite the calibration values */
+	tx_ana_ctrl_reg_1 = readl(tcphy->base + TX_ANA_CTRL_REG_1);
+	tx_ana_ctrl_reg_1 &= ~TXDA_CAL_LATCH_EN;
+	writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1);
 
-	val = rdata | rdata2;
+	/* write the calibration, then delay 10 ms as sample in docs */
+	val = readl(tcphy->base + TX_DIG_CTRL_REG_2);
+	val &= ~(TX_RESCAL_CODE_MASK << TX_RESCAL_CODE_OFFSET);
+	val |= calib << TX_RESCAL_CODE_OFFSET;
 	writel(val, tcphy->base + TX_DIG_CTRL_REG_2);
-	usleep_range(1000, 1050);
+	usleep_range(10000, 10050);
 
 	/*
 	 * Enable signal for latch that sample and holds calibration values.
 	 * Activate this signal for 1 clock cycle to sample new calibration
 	 * values.
 	 */
-	tx_ana_ctrl_reg_1 |= BIT(13);
+	tx_ana_ctrl_reg_1 |= TXDA_CAL_LATCH_EN;
 	writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1);
 	usleep_range(150, 200);
 
 	/* set TX Voltage Level and TX Deemphasis to 0 */
 	writel(0, tcphy->base + PHY_DP_TX_CTL);
+
 	/* re-enable decap */
-	writel(0x100, tcphy->base + TX_ANA_CTRL_REG_2);
-	writel(0x300, tcphy->base + TX_ANA_CTRL_REG_2);
-	tx_ana_ctrl_reg_1 |= BIT(3);
+	tx_ana_ctrl_reg_2 = XCVR_DECAP_EN;
+	writel(tx_ana_ctrl_reg_2, tcphy->base + TX_ANA_CTRL_REG_2);
+	udelay(1);
+	tx_ana_ctrl_reg_2 |= XCVR_DECAP_EN_DEL;
+	writel(tx_ana_ctrl_reg_2, tcphy->base + TX_ANA_CTRL_REG_2);
+
+	writel(0, tcphy->base + TX_ANA_CTRL_REG_3);
+
+	tx_ana_ctrl_reg_1 |= TXDA_UPHY_SUPPLY_EN;
 	writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1);
-	tx_ana_ctrl_reg_1 |= BIT(4);
+	udelay(1);
+	tx_ana_ctrl_reg_1 |= TXDA_UPHY_SUPPLY_EN_DEL;
 	writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1);
 
 	writel(0, tcphy->base + TX_ANA_CTRL_REG_5);
@@ -515,44 +626,66 @@ static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy)
 	writel(0x1001, tcphy->base + TX_ANA_CTRL_REG_4);
 
 	/* re-enables Bandgap reference for LDO */
-	tx_ana_ctrl_reg_1 |= BIT(7);
+	tx_ana_ctrl_reg_1 |= TXDA_DRV_LDO_EN;
 	writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1);
-	tx_ana_ctrl_reg_1 |= BIT(8);
+	udelay(5);
+	tx_ana_ctrl_reg_1 |= TXDA_BGREF_EN;
 	writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1);
 
 	/*
 	 * re-enables the transmitter pre-driver, driver data selection MUX,
 	 * and receiver detect circuits.
 	 */
-	writel(0x301, tcphy->base + TX_ANA_CTRL_REG_2);
-	writel(0x303, tcphy->base + TX_ANA_CTRL_REG_2);
+	tx_ana_ctrl_reg_2 |= TXDA_DRV_PREDRV_EN;
+	writel(tx_ana_ctrl_reg_2, tcphy->base + TX_ANA_CTRL_REG_2);
+	udelay(1);
+	tx_ana_ctrl_reg_2 |= TXDA_DRV_PREDRV_EN_DEL;
+	writel(tx_ana_ctrl_reg_2, tcphy->base + TX_ANA_CTRL_REG_2);
 
 	/*
-	 * Do some magic undocumented stuff, some of which appears to
-	 * undo the "re-enables Bandgap reference for LDO" above.
+	 * Do all the undocumented magic:
+	 * - Turn on TXDA_DP_AUX_EN, whatever that is, even though sample
+	 *   never shows this going on.
+	 * - Turn on TXDA_DECAP_EN (and TXDA_DECAP_EN_DEL) even though
+	 *   docs say for aux it's always 0.
+	 * - Turn off the LDO and BGREF, which we just spent time turning
+	 *   on above (???).
+	 *
+	 * Without this magic, things seem worse.
 	 */
-	tx_ana_ctrl_reg_1 |=  BIT(15);
-	tx_ana_ctrl_reg_1 &= ~BIT(8);
-	tx_ana_ctrl_reg_1 &= ~BIT(7);
-	tx_ana_ctrl_reg_1 |=  BIT(6);
-	tx_ana_ctrl_reg_1 |=  BIT(5);
+	tx_ana_ctrl_reg_1 |= TXDA_DP_AUX_EN;
+	tx_ana_ctrl_reg_1 |= TXDA_DECAP_EN;
+	tx_ana_ctrl_reg_1 &= ~TXDA_DRV_LDO_EN;
+	tx_ana_ctrl_reg_1 &= ~TXDA_BGREF_EN;
+	writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1);
+	udelay(1);
+	tx_ana_ctrl_reg_1 |= TXDA_DECAP_EN_DEL;
 	writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1);
-
-	writel(0, tcphy->base + TX_ANA_CTRL_REG_3);
-	writel(0, tcphy->base + TX_ANA_CTRL_REG_4);
-	writel(0, tcphy->base + TX_ANA_CTRL_REG_5);
 
 	/*
-	 * Controls low_power_swing_en, don't set the voltage swing of the
-	 * driver to 400mv. The values below are peak to peak (differential)
-	 * values.
+	 * Undo the work we did to set the LDO voltage.
+	 * This doesn't seem to help nor hurt, but it kinda goes with the
+	 * undocumented magic above.
 	 */
+	writel(0, tcphy->base + TX_ANA_CTRL_REG_4);
+
+	/* Don't set voltage swing to 400 mV peak to peak (differential) */
 	writel(0, tcphy->base + TXDA_COEFF_CALC_CTRL);
+
+	/* Init TXDA_CYA_AUXDA_CYA for unknown magic reasons */
 	writel(0, tcphy->base + TXDA_CYA_AUXDA_CYA);
 
-	/* Controls tx_high_z_tm_en */
+	/*
+	 * More undocumented magic, presumably the goal of which is to
+	 * make the "auxda_source_aux_oen" be ignored and instead to decide
+	 * about "high impedance state" based on what software puts in the
+	 * register TXDA_COEFF_CALC_CTRL (see TX_HIGH_Z).  Since we only
+	 * program that register once and we don't set the bit TX_HIGH_Z,
+	 * presumably the goal here is that we should never put the analog
+	 * driver in high impedance state.
+	 */
 	val = readl(tcphy->base + TX_DIG_CTRL_REG_2);
-	val |= BIT(15);
+	val |= TX_HIGH_Z_TM_EN;
 	writel(val, tcphy->base + TX_DIG_CTRL_REG_2);
 }
 

+ 100 - 1
drivers/phy/ti/phy-ti-pipe3.c

@@ -68,6 +68,40 @@
 #define PCIE_PCS_MASK			0xFF0000
 #define PCIE_PCS_DELAY_COUNT_SHIFT	0x10
 
+#define PCIEPHYRX_ANA_PROGRAMMABILITY	0x0000000C
+#define INTERFACE_MASK			GENMASK(31, 27)
+#define INTERFACE_SHIFT			27
+#define LOSD_MASK			GENMASK(17, 14)
+#define LOSD_SHIFT			14
+#define MEM_PLLDIV			GENMASK(6, 5)
+
+#define PCIEPHYRX_TRIM			0x0000001C
+#define MEM_DLL_TRIM_SEL		GENMASK(31, 30)
+#define MEM_DLL_TRIM_SHIFT		30
+
+#define PCIEPHYRX_DLL			0x00000024
+#define MEM_DLL_PHINT_RATE		GENMASK(31, 30)
+
+#define PCIEPHYRX_DIGITAL_MODES		0x00000028
+#define MEM_CDR_FASTLOCK		BIT(23)
+#define MEM_CDR_LBW			GENMASK(22, 21)
+#define MEM_CDR_STEPCNT			GENMASK(20, 19)
+#define MEM_CDR_STL_MASK		GENMASK(18, 16)
+#define MEM_CDR_STL_SHIFT		16
+#define MEM_CDR_THR_MASK		GENMASK(15, 13)
+#define MEM_CDR_THR_SHIFT		13
+#define MEM_CDR_THR_MODE		BIT(12)
+#define MEM_CDR_CDR_2NDO_SDM_MODE	BIT(11)
+#define MEM_OVRD_HS_RATE		BIT(26)
+
+#define PCIEPHYRX_EQUALIZER		0x00000038
+#define MEM_EQLEV			GENMASK(31, 16)
+#define MEM_EQFTC			GENMASK(15, 11)
+#define MEM_EQCTL			GENMASK(10, 7)
+#define MEM_EQCTL_SHIFT			7
+#define MEM_OVRD_EQLEV			BIT(2)
+#define MEM_OVRD_EQFTC			BIT(1)
+
 /*
  * This is an Empirical value that works, need to confirm the actual
  * value required for the PIPE3PHY_PLL_CONFIGURATION2.PLL_IDLE status
@@ -91,6 +125,8 @@ struct pipe3_dpll_map {
 
 struct ti_pipe3 {
 	void __iomem		*pll_ctrl_base;
+	void __iomem		*phy_rx;
+	void __iomem		*phy_tx;
 	struct device		*dev;
 	struct device		*control_dev;
 	struct clk		*wkupclk;
@@ -261,6 +297,37 @@ static int ti_pipe3_dpll_program(struct ti_pipe3 *phy)
 	return ti_pipe3_dpll_wait_lock(phy);
 }
 
+static void ti_pipe3_calibrate(struct ti_pipe3 *phy)
+{
+	u32 val;
+
+	val = ti_pipe3_readl(phy->phy_rx, PCIEPHYRX_ANA_PROGRAMMABILITY);
+	val &= ~(INTERFACE_MASK | LOSD_MASK | MEM_PLLDIV);
+	val = (0x1 << INTERFACE_SHIFT | 0xA << LOSD_SHIFT);
+	ti_pipe3_writel(phy->phy_rx, PCIEPHYRX_ANA_PROGRAMMABILITY, val);
+
+	val = ti_pipe3_readl(phy->phy_rx, PCIEPHYRX_DIGITAL_MODES);
+	val &= ~(MEM_CDR_STEPCNT | MEM_CDR_STL_MASK | MEM_CDR_THR_MASK |
+		 MEM_CDR_CDR_2NDO_SDM_MODE | MEM_OVRD_HS_RATE);
+	val |= (MEM_CDR_FASTLOCK | MEM_CDR_LBW | 0x3 << MEM_CDR_STL_SHIFT |
+		0x1 << MEM_CDR_THR_SHIFT | MEM_CDR_THR_MODE);
+	ti_pipe3_writel(phy->phy_rx, PCIEPHYRX_DIGITAL_MODES, val);
+
+	val = ti_pipe3_readl(phy->phy_rx, PCIEPHYRX_TRIM);
+	val &= ~MEM_DLL_TRIM_SEL;
+	val |= 0x2 << MEM_DLL_TRIM_SHIFT;
+	ti_pipe3_writel(phy->phy_rx, PCIEPHYRX_TRIM, val);
+
+	val = ti_pipe3_readl(phy->phy_rx, PCIEPHYRX_DLL);
+	val |= MEM_DLL_PHINT_RATE;
+	ti_pipe3_writel(phy->phy_rx, PCIEPHYRX_DLL, val);
+
+	val = ti_pipe3_readl(phy->phy_rx, PCIEPHYRX_EQUALIZER);
+	val &= ~(MEM_EQLEV | MEM_EQCTL | MEM_OVRD_EQLEV | MEM_OVRD_EQFTC);
+	val |= MEM_EQFTC | 0x1 << MEM_EQCTL_SHIFT;
+	ti_pipe3_writel(phy->phy_rx, PCIEPHYRX_EQUALIZER, val);
+}
+
 static int ti_pipe3_init(struct phy *x)
 {
 	struct ti_pipe3 *phy = phy_get_drvdata(x);
@@ -282,7 +349,12 @@ static int ti_pipe3_init(struct phy *x)
 		val = 0x96 << OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT;
 		ret = regmap_update_bits(phy->pcs_syscon, phy->pcie_pcs_reg,
 					 PCIE_PCS_MASK, val);
-		return ret;
+		if (ret)
+			return ret;
+
+		ti_pipe3_calibrate(phy);
+
+		return 0;
 	}
 
 	/* Bring it out of IDLE if it is IDLE */
@@ -513,6 +585,29 @@ static int ti_pipe3_get_sysctrl(struct ti_pipe3 *phy)
 	return 0;
 }
 
+static int ti_pipe3_get_tx_rx_base(struct ti_pipe3 *phy)
+{
+	struct resource *res;
+	struct device *dev = phy->dev;
+	struct device_node *node = dev->of_node;
+	struct platform_device *pdev = to_platform_device(dev);
+
+	if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie"))
+		return 0;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+					   "phy_rx");
+	phy->phy_rx = devm_ioremap_resource(dev, res);
+	if (IS_ERR(phy->phy_rx))
+		return PTR_ERR(phy->phy_rx);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+					   "phy_tx");
+	phy->phy_tx = devm_ioremap_resource(dev, res);
+
+	return PTR_ERR_OR_ZERO(phy->phy_tx);
+}
+
 static int ti_pipe3_get_pll_base(struct ti_pipe3 *phy)
 {
 	struct resource *res;
@@ -559,6 +654,10 @@ static int ti_pipe3_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+	ret = ti_pipe3_get_tx_rx_base(phy);
+	if (ret)
+		return ret;
+
 	ret = ti_pipe3_get_sysctrl(phy);
 	if (ret)
 		return ret;

+ 1 - 1
drivers/power/supply/qcom_smbb.c

@@ -34,7 +34,7 @@
 #include <linux/power_supply.h>
 #include <linux/regmap.h>
 #include <linux/slab.h>
-#include <linux/extcon.h>
+#include <linux/extcon-provider.h>
 #include <linux/regulator/driver.h>
 
 #define SMBB_CHG_VMAX		0x040

+ 17 - 22
drivers/scsi/ufs/ufs-qcom.c

@@ -273,15 +273,18 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
 	bool is_rate_B = (UFS_QCOM_LIMIT_HS_RATE == PA_HS_MODE_B)
 							? true : false;
 
+	if (is_rate_B)
+		phy_set_mode(phy, PHY_MODE_UFS_HS_B);
+
 	/* Assert PHY reset and apply PHY calibration values */
 	ufs_qcom_assert_reset(hba);
 	/* provide 1ms delay to let the reset pulse propagate */
 	usleep_range(1000, 1100);
 
-	ret = ufs_qcom_phy_calibrate_phy(phy, is_rate_B);
-
+	/* phy initialization - calibrate the phy */
+	ret = phy_init(phy);
 	if (ret) {
-		dev_err(hba->dev, "%s: ufs_qcom_phy_calibrate_phy() failed, ret = %d\n",
+		dev_err(hba->dev, "%s: phy init failed, ret = %d\n",
 			__func__, ret);
 		goto out;
 	}
@@ -294,21 +297,22 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
 	 * voltage, current to settle down before starting serdes.
 	 */
 	usleep_range(1000, 1100);
-	ret = ufs_qcom_phy_start_serdes(phy);
+
+	/* power on phy - start serdes and phy's power and clocks */
+	ret = phy_power_on(phy);
 	if (ret) {
-		dev_err(hba->dev, "%s: ufs_qcom_phy_start_serdes() failed, ret = %d\n",
+		dev_err(hba->dev, "%s: phy power on failed, ret = %d\n",
 			__func__, ret);
-		goto out;
+		goto out_disable_phy;
 	}
 
-	ret = ufs_qcom_phy_is_pcs_ready(phy);
-	if (ret)
-		dev_err(hba->dev,
-			"%s: is_physical_coding_sublayer_ready() failed, ret = %d\n",
-			__func__, ret);
-
 	ufs_qcom_select_unipro_mode(host);
 
+	return 0;
+
+out_disable_phy:
+	ufs_qcom_assert_reset(hba);
+	phy_exit(phy);
 out:
 	return ret;
 }
@@ -1273,14 +1277,9 @@ static int ufs_qcom_init(struct ufs_hba *hba)
 	ufs_qcom_phy_save_controller_version(host->generic_phy,
 		host->hw_ver.major, host->hw_ver.minor, host->hw_ver.step);
 
-	phy_init(host->generic_phy);
-	err = phy_power_on(host->generic_phy);
-	if (err)
-		goto out_unregister_bus;
-
 	err = ufs_qcom_init_lane_clks(host);
 	if (err)
-		goto out_disable_phy;
+		goto out_variant_clear;
 
 	ufs_qcom_set_caps(hba);
 	ufs_qcom_advertise_quirks(hba);
@@ -1301,10 +1300,6 @@ static int ufs_qcom_init(struct ufs_hba *hba)
 
 	goto out;
 
-out_disable_phy:
-	phy_power_off(host->generic_phy);
-out_unregister_bus:
-	phy_exit(host->generic_phy);
 out_variant_clear:
 	ufshcd_set_variant(hba, NULL);
 out:

+ 12 - 0
drivers/soc/bcm/brcmstb/common.c

@@ -40,6 +40,18 @@ bool soc_is_brcmstb(void)
 	return of_match_node(brcmstb_machine_match, root) != NULL;
 }
 
+u32 brcmstb_get_family_id(void)
+{
+	return family_id;
+}
+EXPORT_SYMBOL(brcmstb_get_family_id);
+
+u32 brcmstb_get_product_id(void)
+{
+	return product_id;
+}
+EXPORT_SYMBOL(brcmstb_get_product_id);
+
 static const struct of_device_id sun_top_ctrl_match[] = {
 	{ .compatible = "brcm,bcm7125-sun-top-ctrl", },
 	{ .compatible = "brcm,bcm7346-sun-top-ctrl", },

+ 2 - 2
drivers/staging/wlan-ng/hfa384x_usb.c

@@ -2457,7 +2457,7 @@ int hfa384x_drvr_start(struct hfa384x *hw)
 	 * ok
 	 */
 	result =
-	    usb_get_status(hw->usb, USB_RECIP_ENDPOINT, hw->endp_in, &status);
+	    usb_get_std_status(hw->usb, USB_RECIP_ENDPOINT, hw->endp_in, &status);
 	if (result < 0) {
 		netdev_err(hw->wlandev->netdev, "Cannot get bulk in endpoint status.\n");
 		goto done;
@@ -2466,7 +2466,7 @@ int hfa384x_drvr_start(struct hfa384x *hw)
 		netdev_err(hw->wlandev->netdev, "Failed to reset bulk in endpoint.\n");
 
 	result =
-	    usb_get_status(hw->usb, USB_RECIP_ENDPOINT, hw->endp_out, &status);
+	    usb_get_std_status(hw->usb, USB_RECIP_ENDPOINT, hw->endp_out, &status);
 	if (result < 0) {
 		netdev_err(hw->wlandev->netdev, "Cannot get bulk out endpoint status.\n");
 		goto done;

+ 5 - 4
drivers/usb/Kconfig

@@ -77,11 +77,12 @@ config USB_PCI
 	depends on PCI
 	default y
 	---help---
-	  A lot of embeded system SOC (e.g. freescale T2080) have both
-	  PCI and USB modules. But USB module is controlled by registers
-	  directly, it have no relationship with PCI module.
+	  Many embedded system SOCs (e.g. freescale T2080) have both
+	  PCI and USB modules with the USB module directly controlled by
+	  registers and having no relationship to the PCI module.
 
-	  When say N here it will not build PCI related code in USB driver.
+	  If you have such a device you may say N here and PCI related code
+	  will not be built in the USB driver.
 
 if USB
 

+ 4 - 18
drivers/usb/atm/cxacru.c

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /******************************************************************************
  *  cxacru.c  -  driver for USB ADSL modems based on
  *               Conexant AccessRunner chipset
@@ -6,21 +7,6 @@
  *  Copyright (C) 2005 Duncan Sands, Roman Kagan (rkagan % mail ! ru)
  *  Copyright (C) 2007 Simon Arlott
  *  Copyright (C) 2009 Simon Arlott
- *
- *  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.
- *
- *  You should have received a copy of the GNU General Public License along with
- *  this program; if not, write to the Free Software Foundation, Inc., 59
- *  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- *
  ******************************************************************************/
 
 /*
@@ -424,6 +410,7 @@ static ssize_t cxacru_sysfs_store_adsl_state(struct device *dev,
 		case CXPOLL_STOPPING:
 			/* abort stop request */
 			instance->poll_state = CXPOLL_POLLING;
+			/* fall through */
 		case CXPOLL_POLLING:
 		case CXPOLL_SHUTDOWN:
 			/* don't start polling */
@@ -570,10 +557,8 @@ static int cxacru_start_wait_urb(struct urb *urb, struct completion *done,
 {
 	struct timer_list timer;
 
-	init_timer(&timer);
+	setup_timer(&timer, cxacru_timeout_kill, (unsigned long)urb);
 	timer.expires = jiffies + msecs_to_jiffies(CMD_TIMEOUT);
-	timer.data = (unsigned long) urb;
-	timer.function = cxacru_timeout_kill;
 	add_timer(&timer);
 	wait_for_completion(done);
 	del_timer_sync(&timer);
@@ -797,6 +782,7 @@ static int cxacru_atm_start(struct usbatm_data *usbatm_instance,
 	case CXPOLL_STOPPING:
 		/* abort stop request */
 		instance->poll_state = CXPOLL_POLLING;
+		/* fall through */
 	case CXPOLL_POLLING:
 	case CXPOLL_SHUTDOWN:
 		/* don't start polling */

+ 5 - 22
drivers/usb/atm/speedtch.c

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /******************************************************************************
  *  speedtch.c  -  Alcatel SpeedTouch USB xDSL modem driver
  *
@@ -6,21 +7,6 @@
  *  Copyright (C) 2004, David Woodhouse
  *
  *  Based on "modem_run.c", copyright (C) 2001, Benoit Papillault
- *
- *  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.
- *
- *  You should have received a copy of the GNU General Public License along with
- *  this program; if not, write to the Free Software Foundation, Inc., 59
- *  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- *
  ******************************************************************************/
 
 #include <asm/page.h>
@@ -874,16 +860,13 @@ static int speedtch_bind(struct usbatm_data *usbatm,
 	usbatm->flags |= (use_isoc ? UDSL_USE_ISOC : 0);
 
 	INIT_WORK(&instance->status_check_work, speedtch_check_status);
-	init_timer(&instance->status_check_timer);
-
-	instance->status_check_timer.function = speedtch_status_poll;
-	instance->status_check_timer.data = (unsigned long)instance;
+	setup_timer(&instance->status_check_timer, speedtch_status_poll,
+		    (unsigned long)instance);
 	instance->last_status = 0xff;
 	instance->poll_delay = MIN_POLL_DELAY;
 
-	init_timer(&instance->resubmit_timer);
-	instance->resubmit_timer.function = speedtch_resubmit_int;
-	instance->resubmit_timer.data = (unsigned long)instance;
+	setup_timer(&instance->resubmit_timer, speedtch_resubmit_int,
+		    (unsigned long)instance);
 
 	instance->int_urb = usb_alloc_urb(0, GFP_KERNEL);
 

+ 1 - 0
drivers/usb/atm/ueagle-atm.c

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*-
  * Copyright (c) 2003, 2004
  *	Damien Bergamini <damien.bergamini@free.fr>. All rights reserved.

+ 1 - 15
drivers/usb/atm/usbatm.c

@@ -1,24 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /******************************************************************************
  *  usbatm.c - Generic USB xDSL driver core
  *
  *  Copyright (C) 2001, Alcatel
  *  Copyright (C) 2003, Duncan Sands, SolNegro, Josep Comas
  *  Copyright (C) 2004, David Woodhouse, Roman Kagan
- *
- *  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.
- *
- *  You should have received a copy of the GNU General Public License along with
- *  this program; if not, write to the Free Software Foundation, Inc., 59
- *  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- *
  ******************************************************************************/
 
 /*

+ 1 - 15
drivers/usb/atm/usbatm.h

@@ -1,24 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /******************************************************************************
  *  usbatm.h - Generic USB xDSL driver core
  *
  *  Copyright (C) 2001, Alcatel
  *  Copyright (C) 2003, Duncan Sands, SolNegro, Josep Comas
  *  Copyright (C) 2004, David Woodhouse
- *
- *  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.
- *
- *  You should have received a copy of the GNU General Public License along with
- *  this program; if not, write to the Free Software Foundation, Inc., 59
- *  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- *
  ******************************************************************************/
 
 #ifndef	_USBATM_H_

+ 1 - 15
drivers/usb/atm/xusbatm.c

@@ -1,22 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /******************************************************************************
  *  xusbatm.c -	dumb usbatm-based driver for modems initialized in userspace
  *
  *  Copyright (C) 2005 Duncan Sands, Roman Kagan (rkagan % mail ! ru)
- *
- *  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.
- *
- *  You should have received a copy of the GNU General Public License along with
- *  this program; if not, write to the Free Software Foundation, Inc., 59
- *  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- *
  ******************************************************************************/
 
 #include <linux/module.h>

+ 1 - 0
drivers/usb/c67x00/Makefile

@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # Makefile for Cypress C67X00 USB Controller
 #

+ 1 - 15
drivers/usb/c67x00/c67x00-drv.c

@@ -1,24 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * c67x00-drv.c: Cypress C67X00 USB Common infrastructure
  *
  * Copyright (C) 2006-2008 Barco N.V.
  *    Derived from the Cypress cy7c67200/300 ezusb linux driver and
  *    based on multiple host controller drivers inside the linux kernel.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301  USA.
  */
 
 /*

+ 1 - 15
drivers/usb/c67x00/c67x00-hcd.c

@@ -1,24 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * c67x00-hcd.c: Cypress C67X00 USB Host Controller Driver
  *
  * Copyright (C) 2006-2008 Barco N.V.
  *    Derived from the Cypress cy7c67200/300 ezusb linux driver and
  *    based on multiple host controller drivers inside the linux kernel.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301  USA.
  */
 
 #include <linux/device.h>

+ 1 - 15
drivers/usb/c67x00/c67x00-hcd.h

@@ -1,24 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * c67x00-hcd.h: Cypress C67X00 USB HCD
  *
  * Copyright (C) 2006-2008 Barco N.V.
  *    Derived from the Cypress cy7c67200/300 ezusb linux driver and
  *    based on multiple host controller drivers inside the linux kernel.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301  USA.
  */
 
 #ifndef _USB_C67X00_HCD_H

+ 1 - 15
drivers/usb/c67x00/c67x00-ll-hpi.c

@@ -1,24 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * c67x00-ll-hpi.c: Cypress C67X00 USB Low level interface using HPI
  *
  * Copyright (C) 2006-2008 Barco N.V.
  *    Derived from the Cypress cy7c67200/300 ezusb linux driver and
  *    based on multiple host controller drivers inside the linux kernel.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301  USA.
  */
 
 #include <asm/byteorder.h>

+ 1 - 17
drivers/usb/c67x00/c67x00-sched.c

@@ -1,24 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * c67x00-sched.c: Cypress C67X00 USB Host Controller Driver - TD scheduling
  *
  * Copyright (C) 2006-2008 Barco N.V.
  *    Derived from the Cypress cy7c67200/300 ezusb linux driver and
  *    based on multiple host controller drivers inside the linux kernel.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301  USA.
  */
 
 #include <linux/kthread.h>
@@ -966,13 +952,11 @@ static void c67x00_handle_successful_td(struct c67x00_hcd *c67x00,
 static void c67x00_handle_isoc(struct c67x00_hcd *c67x00, struct c67x00_td *td)
 {
 	struct urb *urb = td->urb;
-	struct c67x00_urb_priv *urbp;
 	int cnt;
 
 	if (!urb)
 		return;
 
-	urbp = urb->hcpriv;
 	cnt = td->privdata;
 
 	if (td->status & TD_ERROR_MASK)

+ 1 - 15
drivers/usb/c67x00/c67x00.h

@@ -1,24 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * c67x00.h: Cypress C67X00 USB register and field definitions
  *
  * Copyright (C) 2006-2008 Barco N.V.
  *    Derived from the Cypress cy7c67200/300 ezusb linux driver and
  *    based on multiple host controller drivers inside the linux kernel.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301  USA.
  */
 
 #ifndef _USB_C67X00_H

+ 1 - 1
drivers/usb/chipidea/Kconfig

@@ -9,7 +9,7 @@ config USB_CHIPIDEA
 	  Dual-role switch (ID, OTG FSM, sysfs), Host-only, and
 	  Peripheral-only.
 
-	  When compiled dynamically, the module will be called ci-hdrc.ko.
+	  When compiled dynamically, the module will be called ci_hdrc.ko.
 
 if USB_CHIPIDEA
 

+ 1 - 4
drivers/usb/chipidea/bits.h

@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * bits.h - register bits of the ChipIdea USB IP core
  *
  * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved.
  *
  * Author: David Lopo
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 
 #ifndef __DRIVERS_USB_CHIPIDEA_BITS_H

+ 1 - 4
drivers/usb/chipidea/ci.h

@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * ci.h - common structures, functions, and macros of the ChipIdea driver
  *
  * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved.
  *
  * Author: David Lopo
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 
 #ifndef __DRIVERS_USB_CHIPIDEA_CI_H

+ 1 - 7
drivers/usb/chipidea/ci_hdrc_imx.c

@@ -1,14 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2012 Freescale Semiconductor, Inc.
  * Copyright (C) 2012 Marek Vasut <marex@denx.de>
  * on behalf of DENX Software Engineering GmbH
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
  */
 
 #include <linux/module.h>

+ 1 - 7
drivers/usb/chipidea/ci_hdrc_imx.h

@@ -1,12 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2012 Freescale Semiconductor, Inc.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
  */
 
 #ifndef __DRIVER_USB_CHIPIDEA_CI_HDRC_IMX_H

+ 2 - 6
drivers/usb/chipidea/ci_hdrc_msm.c

@@ -1,9 +1,5 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- */
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. */
 
 #include <linux/module.h>
 #include <linux/platform_device.h>

+ 1 - 4
drivers/usb/chipidea/ci_hdrc_pci.c

@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * ci_hdrc_pci.c - MIPS USB IP core family device controller
  *
  * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved.
  *
  * Author: David Lopo
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 
 #include <linux/platform_device.h>

+ 1 - 4
drivers/usb/chipidea/ci_hdrc_tegra.c

@@ -1,9 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * 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>

+ 1 - 4
drivers/usb/chipidea/ci_hdrc_usb2.c

@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2014 Marvell Technology Group Ltd.
  *
  * Antoine Tenart <antoine.tenart@free-electrons.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
  */
 
 #include <linux/clk.h>

+ 1 - 5
drivers/usb/chipidea/ci_hdrc_zevio.c

@@ -1,12 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  *	Copyright (C) 2013 Daniel Tang <tangrs@tangrs.id.au>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2, as
- * published by the Free Software Foundation.
- *
  * Based off drivers/usb/chipidea/ci_hdrc_msm.c
- *
  */
 
 #include <linux/module.h>

+ 1 - 4
drivers/usb/chipidea/core.c

@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * core.c - ChipIdea USB IP core family device controller
  *
  * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved.
  *
  * Author: David Lopo
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 
 /*

+ 1 - 13
drivers/usb/chipidea/host.c

@@ -1,22 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * host.c - ChipIdea USB host controller driver
  *
  * Copyright (c) 2012 Intel Corporation
  *
  * Author: Alexander Shishkin
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
 #include <linux/kernel.h>

+ 1 - 4
drivers/usb/chipidea/otg.c

@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * otg.c - ChipIdea USB IP core OTG driver
  *
  * Copyright (C) 2013 Freescale Semiconductor, Inc.
  *
  * Author: Peter Chen
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 
 /*

+ 1 - 4
drivers/usb/chipidea/otg.h

@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2013-2014 Freescale Semiconductor, Inc.
  *
  * Author: Peter Chen
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 
 #ifndef __DRIVERS_USB_CHIPIDEA_OTG_H

+ 1 - 4
drivers/usb/chipidea/otg_fsm.c

@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * otg_fsm.c - ChipIdea USB IP core OTG FSM driver
  *
  * Copyright (C) 2014 Freescale Semiconductor, Inc.
  *
  * Author: Jun Li
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 
 /*

+ 1 - 4
drivers/usb/chipidea/otg_fsm.h

@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2014 Freescale Semiconductor, Inc.
  *
  * Author: Jun Li
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 
 #ifndef __DRIVERS_USB_CHIPIDEA_OTG_FSM_H

+ 5 - 4
drivers/usb/chipidea/udc.c

@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * udc.c - ChipIdea UDC driver
  *
  * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved.
  *
  * Author: David Lopo
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 
 #include <linux/delay.h>
@@ -1526,6 +1523,10 @@ static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
 		gadget_ready = 1;
 	spin_unlock_irqrestore(&ci->lock, flags);
 
+	if (ci->usb_phy)
+		usb_phy_set_charger_state(ci->usb_phy, is_active ?
+			USB_CHARGER_PRESENT : USB_CHARGER_ABSENT);
+
 	if (gadget_ready) {
 		if (is_active) {
 			pm_runtime_get_sync(&_gadget->dev);

+ 1 - 4
drivers/usb/chipidea/udc.h

@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * udc.h - ChipIdea UDC structures
  *
  * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved.
  *
  * Author: David Lopo
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 
 #ifndef __DRIVERS_USB_CHIPIDEA_UDC_H

+ 1 - 9
drivers/usb/chipidea/ulpi.c

@@ -1,14 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2016 Linaro Ltd.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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/device.h>

+ 1 - 7
drivers/usb/chipidea/usbmisc_imx.c

@@ -1,12 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright 2012 Freescale Semiconductor, Inc.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
  */
 
 #include <linux/module.h>

+ 1 - 0
drivers/usb/class/Makefile

@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
 #
 # Makefile for USB Class drivers
 # (one step up from the misc category)

+ 1 - 14
drivers/usb/class/cdc-acm.c

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * cdc-acm.c
  *
@@ -12,20 +13,6 @@
  * USB Abstract Control Model driver for USB modems and ISDN adapters
  *
  * Sponsored by SuSE
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
 #undef DEBUG

+ 1 - 0
drivers/usb/class/cdc-wdm.c

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * cdc-wdm.c
  *

+ 1 - 16
drivers/usb/class/usblp.c

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * usblp.c
  *
@@ -31,22 +32,6 @@
  *      none  - Maintained in Linux kernel after v0.13
  */
 
-/*
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched/signal.h>

+ 2 - 13
drivers/usb/class/usbtmc.c

@@ -1,22 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0+
 /**
  * drivers/usb/class/usbtmc.c - USB Test & Measurement class driver
  *
  * Copyright (C) 2007 Stefan Kopp, Gechingen, Germany
  * Copyright (C) 2008 Novell, Inc.
  * Copyright (C) 2008 Greg Kroah-Hartman <gregkh@suse.de>
- *
- * 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.
- *
- * The GNU General Public License is available at
- * http://www.gnu.org/copyleft/gpl.html.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -1343,6 +1331,7 @@ static void usbtmc_interrupt(struct urb *urb)
 	case -EOVERFLOW:
 		dev_err(dev, "overflow with length %d, actual length is %d\n",
 			data->iin_wMaxPacketSize, urb->actual_length);
+		/* fall through */
 	case -ECONNRESET:
 	case -ENOENT:
 	case -ESHUTDOWN:

+ 1 - 4
drivers/usb/common/common.c

@@ -1,10 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Provides code common for host and device side USB.
  *
- * 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, version 2.
- *
  * If either host side (ie. CONFIG_USB=y) or device side USB stack
  * (ie. CONFIG_USB_GADGET=y) is compiled in the kernel, this module is
  * compiled-in as well.  Otherwise, if either of the two stacks is

+ 1 - 5
drivers/usb/common/led.c

@@ -1,12 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * LED Triggers for USB Activity
  *
  * Copyright 2014 Michal Sojka <sojka@merica.cz>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
  */
 
 #include <linux/module.h>

+ 1 - 4
drivers/usb/common/ulpi.c

@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /**
  * ulpi.c - USB ULPI PHY bus
  *
  * Copyright (C) 2015 Intel Corporation
  *
  * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 
 #include <linux/ulpi/interface.h>

+ 1 - 14
drivers/usb/common/usb-otg-fsm.c

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * OTG Finite State Machine from OTG spec
  *
@@ -5,20 +6,6 @@
  *
  * Author:	Li Yang <LeoLi@freescale.com>
  *		Jerry Huang <Chang-Ming.Huang@freescale.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.
- *
- * You should have received a copy of the  GNU General Public License along
- * with this program; if not, write  to the Free Software Foundation, Inc.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
 #include <linux/module.h>

+ 1 - 1
drivers/usb/core/buffer.c

@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * DMA memory management for framework level HCD code (hc_driver)
  *
@@ -5,7 +6,6 @@
  * and should work with all USB controllers, regardless of bus type.
  *
  * Released under the GPLv2 only.
- * SPDX-License-Identifier: GPL-2.0
  */
 
 #include <linux/module.h>

+ 1 - 1
drivers/usb/core/config.c

@@ -1,6 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Released under the GPLv2 only.
- * SPDX-License-Identifier: GPL-2.0
  */
 
 #include <linux/usb.h>

Some files were not shown because too many files changed in this diff