All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5] Add XHCI, EHCI and OHCI drivers for Broadcom STB SoCs
@ 2018-09-26 22:20 ` Al Cooper
  0 siblings, 0 replies; 29+ messages in thread
From: Al Cooper @ 2018-09-26 22:20 UTC (permalink / raw)
  To: linux-kernel
  Cc: Al Cooper, Greg Kroah-Hartman, Rob Herring, Mark Rutland,
	Alan Stern, Mathias Nyman, Mauro Carvalho Chehab,
	David S. Miller, Andrew Morton, Arnd Bergmann, Dmitry Osipenko,
	Chunfeng Yun, Jianguo Sun, James Hogan, Alban Bedel, Lu Baolu,
	Avi Fishman, Alex Elder, Hans de Goede, linux-usb, devicetree,
	bcm-kernel-feedback-list

Add XHCI, EHCI and OHCI drivers for Broadcom STB SoCs. These drivers
depend on getting access to the new Broadcom STB USB PHY driver
through a device-tree phandle and will fail if the driver is not
available.

Al Cooper (5):
  dt-bindings: Add Broadcom STB OHCI, EHCI and XHCI binding document
  usb: host: Add OHCI driver for Broadcom STB SoCs
  usb: host: Add EHCI driver for Broadcom STB SoCs
  usb: host: Add XHCI driver for Broadcom STB SoCs
  usb: host: Enable building of new Broadcom STB USB drivers

 .../devicetree/bindings/usb/brcm,ehci-brcm.txt     |  22 ++
 .../devicetree/bindings/usb/brcm,ohci-brcm.txt     |  22 ++
 .../devicetree/bindings/usb/brcm,xhci-brcm.txt     |  23 ++
 MAINTAINERS                                        |   9 +
 drivers/usb/host/Kconfig                           |  27 ++
 drivers/usb/host/Makefile                          |   7 +
 drivers/usb/host/ehci-brcm.c                       | 304 +++++++++++++++++++++
 drivers/usb/host/ohci-brcm.c                       | 204 ++++++++++++++
 drivers/usb/host/xhci-brcm.c                       | 294 ++++++++++++++++++++
 9 files changed, 912 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/brcm,ehci-brcm.txt
 create mode 100644 Documentation/devicetree/bindings/usb/brcm,ohci-brcm.txt
 create mode 100644 Documentation/devicetree/bindings/usb/brcm,xhci-brcm.txt
 create mode 100644 drivers/usb/host/ehci-brcm.c
 create mode 100644 drivers/usb/host/ohci-brcm.c
 create mode 100644 drivers/usb/host/xhci-brcm.c

-- 
1.9.0.138.g2de3478


^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH 0/5] Add XHCI, EHCI and OHCI drivers for Broadcom STB SoCs
@ 2018-09-26 22:20 ` Al Cooper
  0 siblings, 0 replies; 29+ messages in thread
From: Al Cooper @ 2018-09-26 22:20 UTC (permalink / raw)
  To: linux-kernel
  Cc: Al Cooper, Greg Kroah-Hartman, Rob Herring, Mark Rutland,
	Alan Stern, Mathias Nyman, Mauro Carvalho Chehab,
	David S. Miller, Andrew Morton, Arnd Bergmann, Dmitry Osipenko,
	Chunfeng Yun, Jianguo Sun, James Hogan, Alban Bedel, Lu Baolu,
	Avi Fishman, Alex Elder, Hans de Goede, linux-usb, dev

Add XHCI, EHCI and OHCI drivers for Broadcom STB SoCs. These drivers
depend on getting access to the new Broadcom STB USB PHY driver
through a device-tree phandle and will fail if the driver is not
available.

Al Cooper (5):
  dt-bindings: Add Broadcom STB OHCI, EHCI and XHCI binding document
  usb: host: Add OHCI driver for Broadcom STB SoCs
  usb: host: Add EHCI driver for Broadcom STB SoCs
  usb: host: Add XHCI driver for Broadcom STB SoCs
  usb: host: Enable building of new Broadcom STB USB drivers

 .../devicetree/bindings/usb/brcm,ehci-brcm.txt     |  22 ++
 .../devicetree/bindings/usb/brcm,ohci-brcm.txt     |  22 ++
 .../devicetree/bindings/usb/brcm,xhci-brcm.txt     |  23 ++
 MAINTAINERS                                        |   9 +
 drivers/usb/host/Kconfig                           |  27 ++
 drivers/usb/host/Makefile                          |   7 +
 drivers/usb/host/ehci-brcm.c                       | 304 +++++++++++++++++++++
 drivers/usb/host/ohci-brcm.c                       | 204 ++++++++++++++
 drivers/usb/host/xhci-brcm.c                       | 294 ++++++++++++++++++++
 9 files changed, 912 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/brcm,ehci-brcm.txt
 create mode 100644 Documentation/devicetree/bindings/usb/brcm,ohci-brcm.txt
 create mode 100644 Documentation/devicetree/bindings/usb/brcm,xhci-brcm.txt
 create mode 100644 drivers/usb/host/ehci-brcm.c
 create mode 100644 drivers/usb/host/ohci-brcm.c
 create mode 100644 drivers/usb/host/xhci-brcm.c

-- 
1.9.0.138.g2de3478

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH 1/5] dt-bindings: Add Broadcom STB OHCI, EHCI and XHCI binding document
  2018-09-26 22:20 ` Al Cooper
  (?)
@ 2018-09-26 22:20   ` Al Cooper
  -1 siblings, 0 replies; 29+ messages in thread
From: Al Cooper @ 2018-09-26 22:20 UTC (permalink / raw)
  To: linux-kernel
  Cc: Al Cooper, Greg Kroah-Hartman, Rob Herring, Mark Rutland,
	Alan Stern, Mathias Nyman, Mauro Carvalho Chehab,
	David S. Miller, Andrew Morton, Arnd Bergmann, Dmitry Osipenko,
	Chunfeng Yun, Jianguo Sun, James Hogan, Alban Bedel, Lu Baolu,
	Avi Fishman, Alex Elder, Hans de Goede, linux-usb, devicetree,
	bcm-kernel-feedback-list

Add DT bindings document for Broadcom STB USB OHCI, EHCI and
XHCI drivers.

Signed-off-by: Al Cooper <alcooperx@gmail.com>
---
 .../devicetree/bindings/usb/brcm,ehci-brcm.txt     | 22 +++++++++++++++++++++
 .../devicetree/bindings/usb/brcm,ohci-brcm.txt     | 22 +++++++++++++++++++++
 .../devicetree/bindings/usb/brcm,xhci-brcm.txt     | 23 ++++++++++++++++++++++
 3 files changed, 67 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/brcm,ehci-brcm.txt
 create mode 100644 Documentation/devicetree/bindings/usb/brcm,ohci-brcm.txt
 create mode 100644 Documentation/devicetree/bindings/usb/brcm,xhci-brcm.txt

diff --git a/Documentation/devicetree/bindings/usb/brcm,ehci-brcm.txt b/Documentation/devicetree/bindings/usb/brcm,ehci-brcm.txt
new file mode 100644
index 000000000000..020b5ec40f5b
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/brcm,ehci-brcm.txt
@@ -0,0 +1,22 @@
+Broadcom STB USB EHCI controller
+
+Required properties:
+- compatible: should be "brcm,ehci-brcm-v2"
+- reg: should contain one register range i.e. start and length
+- interrupts: description of the interrupt line
+- phys: phandle + phy specifier pair
+  The specifier should be 0 for the OHCI/EHCI PHY and 1 for the XHCI PHY
+
+Optional properties:
+- clocks: A list of phandles for the clocks
+
+Example:
+
+ehci@f0b00300 {
+	compatible = "brcm,ehci-brcm-v2";
+	reg = <0xf0b00300 0xa8>;
+	interrupts = <0x0 0x5a 0x0>;
+	interrupt-names = "usb0_ehci_0";
+	phys = <&usbphy_0 0x0>;
+	clocks = <&usb20>
+};
diff --git a/Documentation/devicetree/bindings/usb/brcm,ohci-brcm.txt b/Documentation/devicetree/bindings/usb/brcm,ohci-brcm.txt
new file mode 100644
index 000000000000..c7bb56f30540
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/brcm,ohci-brcm.txt
@@ -0,0 +1,22 @@
+Broadcom STB USB OHCI controller
+
+Required properties:
+- compatible: should be "brcm,ohci-brcm-v2"
+- reg: should contain one register range i.e. start and length
+- interrupts: description of the interrupt line
+- phys: phandle + phy specifier pair
+  The specifier should be 0 for the OHCI/EHCI PHY and 1 for the XHCI PHY
+
+Optional properties:
+- clocks: A list of phandles for the clocks
+
+Example:
+
+ohci@f0b00400 {
+	compatible = "brcm,ohci-brcm-v2";
+	reg = <0xf0b00400 0x58>;
+	interrupts = <0x0 0x5b 0x0>;
+	interrupt-names = "usb0_ohci_0";
+	phys = <&usbphy_0 0x0>;
+	clocks = <&usb20>;
+};
diff --git a/Documentation/devicetree/bindings/usb/brcm,xhci-brcm.txt b/Documentation/devicetree/bindings/usb/brcm,xhci-brcm.txt
new file mode 100644
index 000000000000..7ca5f126c2f6
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/brcm,xhci-brcm.txt
@@ -0,0 +1,23 @@
+Broadcom STB USB XHCI controller
+
+Required properties:
+- compatible: should be "brcm,xhci-brcm-v2"
+- reg: should contain one register range i.e. start and length
+- interrupts: description of the interrupt line
+- phys: phandle + phy specifier pair
+  The specifier should be 0 for the OHCI/EHCI PHY and 1 for the XHCI PHY
+
+Optional properties:
+- clocks: A list of phandles for the clocks
+- usb3-lpm-capable: determines if platform is USB3 LPM capable
+
+Example:
+
+xhci_0_0: xhci@f0b01000 {
+	compatible = "brcm,xhci-brcm-v2";
+	reg = <0xf0b01000 0x1000>;
+	interrupts = <0x0 0x5c 0x0>;
+	interrupt-names = "usb0_xhci_0";
+	phys = <&usbphy_0 0x1>;
+	clocks = <&usb30>;
+};
-- 
1.9.0.138.g2de3478


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 1/5] dt-bindings: Add Broadcom STB OHCI, EHCI and XHCI binding document
@ 2018-09-26 22:20   ` Al Cooper
  0 siblings, 0 replies; 29+ messages in thread
From: Al Cooper @ 2018-09-26 22:20 UTC (permalink / raw)
  To: linux-kernel
  Cc: Al Cooper, Greg Kroah-Hartman, Rob Herring, Mark Rutland,
	Alan Stern, Mathias Nyman, Mauro Carvalho Chehab,
	David S. Miller, Andrew Morton, Arnd Bergmann, Dmitry Osipenko,
	Chunfeng Yun, Jianguo Sun, James Hogan, Alban Bedel, Lu Baolu,
	Avi Fishman, Alex Elder, Hans de Goede, linux-usb, dev

Add DT bindings document for Broadcom STB USB OHCI, EHCI and
XHCI drivers.

Signed-off-by: Al Cooper <alcooperx@gmail.com>
---
 .../devicetree/bindings/usb/brcm,ehci-brcm.txt     | 22 +++++++++++++++++++++
 .../devicetree/bindings/usb/brcm,ohci-brcm.txt     | 22 +++++++++++++++++++++
 .../devicetree/bindings/usb/brcm,xhci-brcm.txt     | 23 ++++++++++++++++++++++
 3 files changed, 67 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/brcm,ehci-brcm.txt
 create mode 100644 Documentation/devicetree/bindings/usb/brcm,ohci-brcm.txt
 create mode 100644 Documentation/devicetree/bindings/usb/brcm,xhci-brcm.txt

diff --git a/Documentation/devicetree/bindings/usb/brcm,ehci-brcm.txt b/Documentation/devicetree/bindings/usb/brcm,ehci-brcm.txt
new file mode 100644
index 000000000000..020b5ec40f5b
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/brcm,ehci-brcm.txt
@@ -0,0 +1,22 @@
+Broadcom STB USB EHCI controller
+
+Required properties:
+- compatible: should be "brcm,ehci-brcm-v2"
+- reg: should contain one register range i.e. start and length
+- interrupts: description of the interrupt line
+- phys: phandle + phy specifier pair
+  The specifier should be 0 for the OHCI/EHCI PHY and 1 for the XHCI PHY
+
+Optional properties:
+- clocks: A list of phandles for the clocks
+
+Example:
+
+ehci@f0b00300 {
+	compatible = "brcm,ehci-brcm-v2";
+	reg = <0xf0b00300 0xa8>;
+	interrupts = <0x0 0x5a 0x0>;
+	interrupt-names = "usb0_ehci_0";
+	phys = <&usbphy_0 0x0>;
+	clocks = <&usb20>
+};
diff --git a/Documentation/devicetree/bindings/usb/brcm,ohci-brcm.txt b/Documentation/devicetree/bindings/usb/brcm,ohci-brcm.txt
new file mode 100644
index 000000000000..c7bb56f30540
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/brcm,ohci-brcm.txt
@@ -0,0 +1,22 @@
+Broadcom STB USB OHCI controller
+
+Required properties:
+- compatible: should be "brcm,ohci-brcm-v2"
+- reg: should contain one register range i.e. start and length
+- interrupts: description of the interrupt line
+- phys: phandle + phy specifier pair
+  The specifier should be 0 for the OHCI/EHCI PHY and 1 for the XHCI PHY
+
+Optional properties:
+- clocks: A list of phandles for the clocks
+
+Example:
+
+ohci@f0b00400 {
+	compatible = "brcm,ohci-brcm-v2";
+	reg = <0xf0b00400 0x58>;
+	interrupts = <0x0 0x5b 0x0>;
+	interrupt-names = "usb0_ohci_0";
+	phys = <&usbphy_0 0x0>;
+	clocks = <&usb20>;
+};
diff --git a/Documentation/devicetree/bindings/usb/brcm,xhci-brcm.txt b/Documentation/devicetree/bindings/usb/brcm,xhci-brcm.txt
new file mode 100644
index 000000000000..7ca5f126c2f6
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/brcm,xhci-brcm.txt
@@ -0,0 +1,23 @@
+Broadcom STB USB XHCI controller
+
+Required properties:
+- compatible: should be "brcm,xhci-brcm-v2"
+- reg: should contain one register range i.e. start and length
+- interrupts: description of the interrupt line
+- phys: phandle + phy specifier pair
+  The specifier should be 0 for the OHCI/EHCI PHY and 1 for the XHCI PHY
+
+Optional properties:
+- clocks: A list of phandles for the clocks
+- usb3-lpm-capable: determines if platform is USB3 LPM capable
+
+Example:
+
+xhci_0_0: xhci@f0b01000 {
+	compatible = "brcm,xhci-brcm-v2";
+	reg = <0xf0b01000 0x1000>;
+	interrupts = <0x0 0x5c 0x0>;
+	interrupt-names = "usb0_xhci_0";
+	phys = <&usbphy_0 0x1>;
+	clocks = <&usb30>;
+};
-- 
1.9.0.138.g2de3478

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [1/5] dt-bindings: Add Broadcom STB OHCI, EHCI and XHCI binding document
@ 2018-09-26 22:20   ` Al Cooper
  0 siblings, 0 replies; 29+ messages in thread
From: Alan Cooper @ 2018-09-26 22:20 UTC (permalink / raw)
  To: linux-kernel
  Cc: Al Cooper, Greg Kroah-Hartman, Rob Herring, Mark Rutland,
	Alan Stern, Mathias Nyman, Mauro Carvalho Chehab,
	David S. Miller, Andrew Morton, Arnd Bergmann, Dmitry Osipenko,
	Chunfeng Yun, Jianguo Sun, James Hogan, Alban Bedel, Lu Baolu,
	Avi Fishman, Alex Elder, Hans de Goede, linux-usb, devicetree,
	bcm-kernel-feedback-list

Add DT bindings document for Broadcom STB USB OHCI, EHCI and
XHCI drivers.

Signed-off-by: Al Cooper <alcooperx@gmail.com>
---
 .../devicetree/bindings/usb/brcm,ehci-brcm.txt     | 22 +++++++++++++++++++++
 .../devicetree/bindings/usb/brcm,ohci-brcm.txt     | 22 +++++++++++++++++++++
 .../devicetree/bindings/usb/brcm,xhci-brcm.txt     | 23 ++++++++++++++++++++++
 3 files changed, 67 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/brcm,ehci-brcm.txt
 create mode 100644 Documentation/devicetree/bindings/usb/brcm,ohci-brcm.txt
 create mode 100644 Documentation/devicetree/bindings/usb/brcm,xhci-brcm.txt

diff --git a/Documentation/devicetree/bindings/usb/brcm,ehci-brcm.txt b/Documentation/devicetree/bindings/usb/brcm,ehci-brcm.txt
new file mode 100644
index 000000000000..020b5ec40f5b
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/brcm,ehci-brcm.txt
@@ -0,0 +1,22 @@
+Broadcom STB USB EHCI controller
+
+Required properties:
+- compatible: should be "brcm,ehci-brcm-v2"
+- reg: should contain one register range i.e. start and length
+- interrupts: description of the interrupt line
+- phys: phandle + phy specifier pair
+  The specifier should be 0 for the OHCI/EHCI PHY and 1 for the XHCI PHY
+
+Optional properties:
+- clocks: A list of phandles for the clocks
+
+Example:
+
+ehci@f0b00300 {
+	compatible = "brcm,ehci-brcm-v2";
+	reg = <0xf0b00300 0xa8>;
+	interrupts = <0x0 0x5a 0x0>;
+	interrupt-names = "usb0_ehci_0";
+	phys = <&usbphy_0 0x0>;
+	clocks = <&usb20>
+};
diff --git a/Documentation/devicetree/bindings/usb/brcm,ohci-brcm.txt b/Documentation/devicetree/bindings/usb/brcm,ohci-brcm.txt
new file mode 100644
index 000000000000..c7bb56f30540
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/brcm,ohci-brcm.txt
@@ -0,0 +1,22 @@
+Broadcom STB USB OHCI controller
+
+Required properties:
+- compatible: should be "brcm,ohci-brcm-v2"
+- reg: should contain one register range i.e. start and length
+- interrupts: description of the interrupt line
+- phys: phandle + phy specifier pair
+  The specifier should be 0 for the OHCI/EHCI PHY and 1 for the XHCI PHY
+
+Optional properties:
+- clocks: A list of phandles for the clocks
+
+Example:
+
+ohci@f0b00400 {
+	compatible = "brcm,ohci-brcm-v2";
+	reg = <0xf0b00400 0x58>;
+	interrupts = <0x0 0x5b 0x0>;
+	interrupt-names = "usb0_ohci_0";
+	phys = <&usbphy_0 0x0>;
+	clocks = <&usb20>;
+};
diff --git a/Documentation/devicetree/bindings/usb/brcm,xhci-brcm.txt b/Documentation/devicetree/bindings/usb/brcm,xhci-brcm.txt
new file mode 100644
index 000000000000..7ca5f126c2f6
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/brcm,xhci-brcm.txt
@@ -0,0 +1,23 @@
+Broadcom STB USB XHCI controller
+
+Required properties:
+- compatible: should be "brcm,xhci-brcm-v2"
+- reg: should contain one register range i.e. start and length
+- interrupts: description of the interrupt line
+- phys: phandle + phy specifier pair
+  The specifier should be 0 for the OHCI/EHCI PHY and 1 for the XHCI PHY
+
+Optional properties:
+- clocks: A list of phandles for the clocks
+- usb3-lpm-capable: determines if platform is USB3 LPM capable
+
+Example:
+
+xhci_0_0: xhci@f0b01000 {
+	compatible = "brcm,xhci-brcm-v2";
+	reg = <0xf0b01000 0x1000>;
+	interrupts = <0x0 0x5c 0x0>;
+	interrupt-names = "usb0_xhci_0";
+	phys = <&usbphy_0 0x1>;
+	clocks = <&usb30>;
+};

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 2/5] usb: host: Add OHCI driver for Broadcom STB SoCs
  2018-09-26 22:20 ` Al Cooper
  (?)
@ 2018-09-26 22:20   ` Al Cooper
  -1 siblings, 0 replies; 29+ messages in thread
From: Al Cooper @ 2018-09-26 22:20 UTC (permalink / raw)
  To: linux-kernel
  Cc: Al Cooper, Greg Kroah-Hartman, Rob Herring, Mark Rutland,
	Alan Stern, Mathias Nyman, Mauro Carvalho Chehab,
	David S. Miller, Andrew Morton, Arnd Bergmann, Dmitry Osipenko,
	Chunfeng Yun, Jianguo Sun, James Hogan, Alban Bedel, Lu Baolu,
	Avi Fishman, Alex Elder, Hans de Goede, linux-usb, devicetree,
	bcm-kernel-feedback-list

This driver enables USB OHCI on Broadcom ARM and MIPS STB SoCs.
The drivers depend on a matching "brcm,brcmstb-usb-phy"
Broadcom STB USB Phy driver.

The standard platform driver can't be used because of differences
in PHY and Clock handling. The standard PHY handling in hcd.c will
do a phy_exit/phy_init on suspend/resume and this will end up
shutting down the PHYs to the point that the host controller
registers are no longer accessible and will cause suspend to crash.
The clocks specified in device tree for these drivers are not
available in mainline so instead of returning EPROBE_DEFER when
the specified clock is not found and eventually failing probe,
the clock pointer is set to NULL which disables all clock handling.

Signed-off-by: Al Cooper <alcooperx@gmail.com>
---
 drivers/usb/host/ohci-brcm.c | 204 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 204 insertions(+)
 create mode 100644 drivers/usb/host/ohci-brcm.c

diff --git a/drivers/usb/host/ohci-brcm.c b/drivers/usb/host/ohci-brcm.c
new file mode 100644
index 000000000000..d4de59a56e2c
--- /dev/null
+++ b/drivers/usb/host/ohci-brcm.c
@@ -0,0 +1,204 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2018, Broadcom */
+
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+
+#include "ohci.h"
+
+#define BRCM_DRIVER_DESC "OHCI Broadcom STB driver"
+
+static const char hcd_name[] = "ohci-brcm";
+
+#define hcd_to_ohci_priv(h) ((struct brcm_priv *)hcd_to_ohci(h)->priv)
+
+struct brcm_priv {
+	struct clk *clk;
+	struct phy *phy;
+};
+
+static struct hc_driver __read_mostly ohci_brcm_hc_driver;
+
+static const struct ohci_driver_overrides brcm_overrides __initconst = {
+	.product_desc =	"Broadcom STB OHCI controller",
+	.extra_priv_size = sizeof(struct brcm_priv),
+};
+
+static int ohci_brcm_probe(struct platform_device *dev)
+{
+	struct usb_hcd *hcd;
+	struct brcm_priv *priv;
+	struct resource *res_mem;
+	int irq;
+	int err;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	err = dma_coerce_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
+	if (err)
+		return err;
+
+	irq = platform_get_irq(dev, 0);
+	if (irq < 0) {
+		dev_err(&dev->dev, "no irq provided");
+		return irq;
+	}
+
+	/* initialize hcd */
+	hcd = usb_create_hcd(&ohci_brcm_hc_driver,
+			&dev->dev, dev_name(&dev->dev));
+	if (!hcd)
+		return -ENOMEM;
+
+	platform_set_drvdata(dev, hcd);
+	priv = hcd_to_ohci_priv(hcd);
+
+	priv->clk = devm_clk_get(&dev->dev, NULL);
+	if (IS_ERR(priv->clk)) {
+		dev_err(&dev->dev, "Clock not found in Device Tree\n");
+		priv->clk = NULL;
+	}
+	err = clk_prepare_enable(priv->clk);
+	if (err)
+		goto err_hcd;
+
+	priv->phy = devm_of_phy_get_by_index(&dev->dev, dev->dev.of_node, 0);
+	if (IS_ERR(priv->phy)) {
+		dev_err(&dev->dev, "USB Phy not found.\n");
+		err = PTR_ERR(priv->phy);
+		goto err_clk;
+	}
+	phy_init(priv->phy);
+
+	pm_runtime_set_active(&dev->dev);
+	pm_runtime_enable(&dev->dev);
+
+	res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	hcd->regs = devm_ioremap_resource(&dev->dev, res_mem);
+	if (IS_ERR(hcd->regs)) {
+		err = PTR_ERR(hcd->regs);
+		goto err_phy;
+	}
+	hcd->rsrc_start = res_mem->start;
+	hcd->rsrc_len = resource_size(res_mem);
+	hcd->skip_phy_initialization = 1;
+	err = usb_add_hcd(hcd, irq, IRQF_SHARED);
+	if (err)
+		goto err_phy;
+
+	device_wakeup_enable(hcd->self.controller);
+
+	platform_set_drvdata(dev, hcd);
+
+	return err;
+
+err_phy:
+	pm_runtime_disable(&dev->dev);
+	phy_exit(priv->phy);
+err_clk:
+	clk_disable_unprepare(priv->clk);
+err_hcd:
+	usb_put_hcd(hcd);
+
+	return err;
+
+}
+
+static int ohci_brcm_remove(struct platform_device *dev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(dev);
+	struct brcm_priv *priv = hcd_to_ohci_priv(hcd);
+
+	pm_runtime_get_sync(&dev->dev);
+	usb_remove_hcd(hcd);
+	phy_exit(priv->phy);
+	clk_disable_unprepare(priv->clk);
+	usb_put_hcd(hcd);
+	pm_runtime_put_sync(&dev->dev);
+	pm_runtime_disable(&dev->dev);
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+
+static int ohci_brcm_suspend(struct device *dev)
+{
+	int ret;
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	struct brcm_priv *priv = hcd_to_ohci_priv(hcd);
+	bool do_wakeup = device_may_wakeup(dev);
+
+	ret = ohci_suspend(hcd, do_wakeup);
+	clk_disable_unprepare(priv->clk);
+	return ret;
+}
+
+static int ohci_brcm_resume(struct device *dev)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	struct brcm_priv *priv = hcd_to_ohci_priv(hcd);
+	int err;
+
+	err = clk_prepare_enable(priv->clk);
+	if (err)
+		return err;
+	ohci_resume(hcd, false);
+	return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static SIMPLE_DEV_PM_OPS(ohci_brcm_pm_ops, ohci_brcm_suspend,
+		ohci_brcm_resume);
+
+#ifdef CONFIG_OF
+static const struct of_device_id brcm_ohci_of_match[] = {
+	{ .compatible = "brcm,ohci-brcm-v2", },
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, brcm_ohci_of_match);
+#endif /* CONFIG_OF */
+
+static struct platform_driver ohci_brcm_driver = {
+	.probe		= ohci_brcm_probe,
+	.remove		= ohci_brcm_remove,
+	.shutdown	= usb_hcd_platform_shutdown,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "ohci-brcm",
+		.pm	= &ohci_brcm_pm_ops,
+		.of_match_table = of_match_ptr(brcm_ohci_of_match),
+	}
+};
+
+static int __init ohci_brcm_init(void)
+{
+	if (usb_disabled())
+		return -ENODEV;
+
+	pr_info("%s: " BRCM_DRIVER_DESC "\n", hcd_name);
+
+	ohci_init_driver(&ohci_brcm_hc_driver, &brcm_overrides);
+	return platform_driver_register(&ohci_brcm_driver);
+}
+module_init(ohci_brcm_init);
+
+static void __exit ohci_brcm_exit(void)
+{
+	platform_driver_unregister(&ohci_brcm_driver);
+}
+module_exit(ohci_brcm_exit);
+
+MODULE_ALIAS("platform:ohci-brcm");
+MODULE_DESCRIPTION(BRCM_DRIVER_DESC);
+MODULE_AUTHOR("Al Cooper");
+MODULE_LICENSE("GPL");
-- 
1.9.0.138.g2de3478


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 2/5] usb: host: Add OHCI driver for Broadcom STB SoCs
@ 2018-09-26 22:20   ` Al Cooper
  0 siblings, 0 replies; 29+ messages in thread
From: Al Cooper @ 2018-09-26 22:20 UTC (permalink / raw)
  To: linux-kernel
  Cc: Al Cooper, Greg Kroah-Hartman, Rob Herring, Mark Rutland,
	Alan Stern, Mathias Nyman, Mauro Carvalho Chehab,
	David S. Miller, Andrew Morton, Arnd Bergmann, Dmitry Osipenko,
	Chunfeng Yun, Jianguo Sun, James Hogan, Alban Bedel, Lu Baolu,
	Avi Fishman, Alex Elder, Hans de Goede, linux-usb, dev

This driver enables USB OHCI on Broadcom ARM and MIPS STB SoCs.
The drivers depend on a matching "brcm,brcmstb-usb-phy"
Broadcom STB USB Phy driver.

The standard platform driver can't be used because of differences
in PHY and Clock handling. The standard PHY handling in hcd.c will
do a phy_exit/phy_init on suspend/resume and this will end up
shutting down the PHYs to the point that the host controller
registers are no longer accessible and will cause suspend to crash.
The clocks specified in device tree for these drivers are not
available in mainline so instead of returning EPROBE_DEFER when
the specified clock is not found and eventually failing probe,
the clock pointer is set to NULL which disables all clock handling.

Signed-off-by: Al Cooper <alcooperx@gmail.com>
---
 drivers/usb/host/ohci-brcm.c | 204 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 204 insertions(+)
 create mode 100644 drivers/usb/host/ohci-brcm.c

diff --git a/drivers/usb/host/ohci-brcm.c b/drivers/usb/host/ohci-brcm.c
new file mode 100644
index 000000000000..d4de59a56e2c
--- /dev/null
+++ b/drivers/usb/host/ohci-brcm.c
@@ -0,0 +1,204 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2018, Broadcom */
+
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+
+#include "ohci.h"
+
+#define BRCM_DRIVER_DESC "OHCI Broadcom STB driver"
+
+static const char hcd_name[] = "ohci-brcm";
+
+#define hcd_to_ohci_priv(h) ((struct brcm_priv *)hcd_to_ohci(h)->priv)
+
+struct brcm_priv {
+	struct clk *clk;
+	struct phy *phy;
+};
+
+static struct hc_driver __read_mostly ohci_brcm_hc_driver;
+
+static const struct ohci_driver_overrides brcm_overrides __initconst = {
+	.product_desc =	"Broadcom STB OHCI controller",
+	.extra_priv_size = sizeof(struct brcm_priv),
+};
+
+static int ohci_brcm_probe(struct platform_device *dev)
+{
+	struct usb_hcd *hcd;
+	struct brcm_priv *priv;
+	struct resource *res_mem;
+	int irq;
+	int err;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	err = dma_coerce_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
+	if (err)
+		return err;
+
+	irq = platform_get_irq(dev, 0);
+	if (irq < 0) {
+		dev_err(&dev->dev, "no irq provided");
+		return irq;
+	}
+
+	/* initialize hcd */
+	hcd = usb_create_hcd(&ohci_brcm_hc_driver,
+			&dev->dev, dev_name(&dev->dev));
+	if (!hcd)
+		return -ENOMEM;
+
+	platform_set_drvdata(dev, hcd);
+	priv = hcd_to_ohci_priv(hcd);
+
+	priv->clk = devm_clk_get(&dev->dev, NULL);
+	if (IS_ERR(priv->clk)) {
+		dev_err(&dev->dev, "Clock not found in Device Tree\n");
+		priv->clk = NULL;
+	}
+	err = clk_prepare_enable(priv->clk);
+	if (err)
+		goto err_hcd;
+
+	priv->phy = devm_of_phy_get_by_index(&dev->dev, dev->dev.of_node, 0);
+	if (IS_ERR(priv->phy)) {
+		dev_err(&dev->dev, "USB Phy not found.\n");
+		err = PTR_ERR(priv->phy);
+		goto err_clk;
+	}
+	phy_init(priv->phy);
+
+	pm_runtime_set_active(&dev->dev);
+	pm_runtime_enable(&dev->dev);
+
+	res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	hcd->regs = devm_ioremap_resource(&dev->dev, res_mem);
+	if (IS_ERR(hcd->regs)) {
+		err = PTR_ERR(hcd->regs);
+		goto err_phy;
+	}
+	hcd->rsrc_start = res_mem->start;
+	hcd->rsrc_len = resource_size(res_mem);
+	hcd->skip_phy_initialization = 1;
+	err = usb_add_hcd(hcd, irq, IRQF_SHARED);
+	if (err)
+		goto err_phy;
+
+	device_wakeup_enable(hcd->self.controller);
+
+	platform_set_drvdata(dev, hcd);
+
+	return err;
+
+err_phy:
+	pm_runtime_disable(&dev->dev);
+	phy_exit(priv->phy);
+err_clk:
+	clk_disable_unprepare(priv->clk);
+err_hcd:
+	usb_put_hcd(hcd);
+
+	return err;
+
+}
+
+static int ohci_brcm_remove(struct platform_device *dev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(dev);
+	struct brcm_priv *priv = hcd_to_ohci_priv(hcd);
+
+	pm_runtime_get_sync(&dev->dev);
+	usb_remove_hcd(hcd);
+	phy_exit(priv->phy);
+	clk_disable_unprepare(priv->clk);
+	usb_put_hcd(hcd);
+	pm_runtime_put_sync(&dev->dev);
+	pm_runtime_disable(&dev->dev);
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+
+static int ohci_brcm_suspend(struct device *dev)
+{
+	int ret;
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	struct brcm_priv *priv = hcd_to_ohci_priv(hcd);
+	bool do_wakeup = device_may_wakeup(dev);
+
+	ret = ohci_suspend(hcd, do_wakeup);
+	clk_disable_unprepare(priv->clk);
+	return ret;
+}
+
+static int ohci_brcm_resume(struct device *dev)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	struct brcm_priv *priv = hcd_to_ohci_priv(hcd);
+	int err;
+
+	err = clk_prepare_enable(priv->clk);
+	if (err)
+		return err;
+	ohci_resume(hcd, false);
+	return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static SIMPLE_DEV_PM_OPS(ohci_brcm_pm_ops, ohci_brcm_suspend,
+		ohci_brcm_resume);
+
+#ifdef CONFIG_OF
+static const struct of_device_id brcm_ohci_of_match[] = {
+	{ .compatible = "brcm,ohci-brcm-v2", },
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, brcm_ohci_of_match);
+#endif /* CONFIG_OF */
+
+static struct platform_driver ohci_brcm_driver = {
+	.probe		= ohci_brcm_probe,
+	.remove		= ohci_brcm_remove,
+	.shutdown	= usb_hcd_platform_shutdown,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "ohci-brcm",
+		.pm	= &ohci_brcm_pm_ops,
+		.of_match_table = of_match_ptr(brcm_ohci_of_match),
+	}
+};
+
+static int __init ohci_brcm_init(void)
+{
+	if (usb_disabled())
+		return -ENODEV;
+
+	pr_info("%s: " BRCM_DRIVER_DESC "\n", hcd_name);
+
+	ohci_init_driver(&ohci_brcm_hc_driver, &brcm_overrides);
+	return platform_driver_register(&ohci_brcm_driver);
+}
+module_init(ohci_brcm_init);
+
+static void __exit ohci_brcm_exit(void)
+{
+	platform_driver_unregister(&ohci_brcm_driver);
+}
+module_exit(ohci_brcm_exit);
+
+MODULE_ALIAS("platform:ohci-brcm");
+MODULE_DESCRIPTION(BRCM_DRIVER_DESC);
+MODULE_AUTHOR("Al Cooper");
+MODULE_LICENSE("GPL");
-- 
1.9.0.138.g2de3478

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [2/5] usb: host: Add OHCI driver for Broadcom STB SoCs
@ 2018-09-26 22:20   ` Al Cooper
  0 siblings, 0 replies; 29+ messages in thread
From: Alan Cooper @ 2018-09-26 22:20 UTC (permalink / raw)
  To: linux-kernel
  Cc: Al Cooper, Greg Kroah-Hartman, Rob Herring, Mark Rutland,
	Alan Stern, Mathias Nyman, Mauro Carvalho Chehab,
	David S. Miller, Andrew Morton, Arnd Bergmann, Dmitry Osipenko,
	Chunfeng Yun, Jianguo Sun, James Hogan, Alban Bedel, Lu Baolu,
	Avi Fishman, Alex Elder, Hans de Goede, linux-usb, devicetree,
	bcm-kernel-feedback-list

This driver enables USB OHCI on Broadcom ARM and MIPS STB SoCs.
The drivers depend on a matching "brcm,brcmstb-usb-phy"
Broadcom STB USB Phy driver.

The standard platform driver can't be used because of differences
in PHY and Clock handling. The standard PHY handling in hcd.c will
do a phy_exit/phy_init on suspend/resume and this will end up
shutting down the PHYs to the point that the host controller
registers are no longer accessible and will cause suspend to crash.
The clocks specified in device tree for these drivers are not
available in mainline so instead of returning EPROBE_DEFER when
the specified clock is not found and eventually failing probe,
the clock pointer is set to NULL which disables all clock handling.

Signed-off-by: Al Cooper <alcooperx@gmail.com>
---
 drivers/usb/host/ohci-brcm.c | 204 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 204 insertions(+)
 create mode 100644 drivers/usb/host/ohci-brcm.c

diff --git a/drivers/usb/host/ohci-brcm.c b/drivers/usb/host/ohci-brcm.c
new file mode 100644
index 000000000000..d4de59a56e2c
--- /dev/null
+++ b/drivers/usb/host/ohci-brcm.c
@@ -0,0 +1,204 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2018, Broadcom */
+
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+
+#include "ohci.h"
+
+#define BRCM_DRIVER_DESC "OHCI Broadcom STB driver"
+
+static const char hcd_name[] = "ohci-brcm";
+
+#define hcd_to_ohci_priv(h) ((struct brcm_priv *)hcd_to_ohci(h)->priv)
+
+struct brcm_priv {
+	struct clk *clk;
+	struct phy *phy;
+};
+
+static struct hc_driver __read_mostly ohci_brcm_hc_driver;
+
+static const struct ohci_driver_overrides brcm_overrides __initconst = {
+	.product_desc =	"Broadcom STB OHCI controller",
+	.extra_priv_size = sizeof(struct brcm_priv),
+};
+
+static int ohci_brcm_probe(struct platform_device *dev)
+{
+	struct usb_hcd *hcd;
+	struct brcm_priv *priv;
+	struct resource *res_mem;
+	int irq;
+	int err;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	err = dma_coerce_mask_and_coherent(&dev->dev, DMA_BIT_MASK(32));
+	if (err)
+		return err;
+
+	irq = platform_get_irq(dev, 0);
+	if (irq < 0) {
+		dev_err(&dev->dev, "no irq provided");
+		return irq;
+	}
+
+	/* initialize hcd */
+	hcd = usb_create_hcd(&ohci_brcm_hc_driver,
+			&dev->dev, dev_name(&dev->dev));
+	if (!hcd)
+		return -ENOMEM;
+
+	platform_set_drvdata(dev, hcd);
+	priv = hcd_to_ohci_priv(hcd);
+
+	priv->clk = devm_clk_get(&dev->dev, NULL);
+	if (IS_ERR(priv->clk)) {
+		dev_err(&dev->dev, "Clock not found in Device Tree\n");
+		priv->clk = NULL;
+	}
+	err = clk_prepare_enable(priv->clk);
+	if (err)
+		goto err_hcd;
+
+	priv->phy = devm_of_phy_get_by_index(&dev->dev, dev->dev.of_node, 0);
+	if (IS_ERR(priv->phy)) {
+		dev_err(&dev->dev, "USB Phy not found.\n");
+		err = PTR_ERR(priv->phy);
+		goto err_clk;
+	}
+	phy_init(priv->phy);
+
+	pm_runtime_set_active(&dev->dev);
+	pm_runtime_enable(&dev->dev);
+
+	res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	hcd->regs = devm_ioremap_resource(&dev->dev, res_mem);
+	if (IS_ERR(hcd->regs)) {
+		err = PTR_ERR(hcd->regs);
+		goto err_phy;
+	}
+	hcd->rsrc_start = res_mem->start;
+	hcd->rsrc_len = resource_size(res_mem);
+	hcd->skip_phy_initialization = 1;
+	err = usb_add_hcd(hcd, irq, IRQF_SHARED);
+	if (err)
+		goto err_phy;
+
+	device_wakeup_enable(hcd->self.controller);
+
+	platform_set_drvdata(dev, hcd);
+
+	return err;
+
+err_phy:
+	pm_runtime_disable(&dev->dev);
+	phy_exit(priv->phy);
+err_clk:
+	clk_disable_unprepare(priv->clk);
+err_hcd:
+	usb_put_hcd(hcd);
+
+	return err;
+
+}
+
+static int ohci_brcm_remove(struct platform_device *dev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(dev);
+	struct brcm_priv *priv = hcd_to_ohci_priv(hcd);
+
+	pm_runtime_get_sync(&dev->dev);
+	usb_remove_hcd(hcd);
+	phy_exit(priv->phy);
+	clk_disable_unprepare(priv->clk);
+	usb_put_hcd(hcd);
+	pm_runtime_put_sync(&dev->dev);
+	pm_runtime_disable(&dev->dev);
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+
+static int ohci_brcm_suspend(struct device *dev)
+{
+	int ret;
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	struct brcm_priv *priv = hcd_to_ohci_priv(hcd);
+	bool do_wakeup = device_may_wakeup(dev);
+
+	ret = ohci_suspend(hcd, do_wakeup);
+	clk_disable_unprepare(priv->clk);
+	return ret;
+}
+
+static int ohci_brcm_resume(struct device *dev)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	struct brcm_priv *priv = hcd_to_ohci_priv(hcd);
+	int err;
+
+	err = clk_prepare_enable(priv->clk);
+	if (err)
+		return err;
+	ohci_resume(hcd, false);
+	return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static SIMPLE_DEV_PM_OPS(ohci_brcm_pm_ops, ohci_brcm_suspend,
+		ohci_brcm_resume);
+
+#ifdef CONFIG_OF
+static const struct of_device_id brcm_ohci_of_match[] = {
+	{ .compatible = "brcm,ohci-brcm-v2", },
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, brcm_ohci_of_match);
+#endif /* CONFIG_OF */
+
+static struct platform_driver ohci_brcm_driver = {
+	.probe		= ohci_brcm_probe,
+	.remove		= ohci_brcm_remove,
+	.shutdown	= usb_hcd_platform_shutdown,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "ohci-brcm",
+		.pm	= &ohci_brcm_pm_ops,
+		.of_match_table = of_match_ptr(brcm_ohci_of_match),
+	}
+};
+
+static int __init ohci_brcm_init(void)
+{
+	if (usb_disabled())
+		return -ENODEV;
+
+	pr_info("%s: " BRCM_DRIVER_DESC "\n", hcd_name);
+
+	ohci_init_driver(&ohci_brcm_hc_driver, &brcm_overrides);
+	return platform_driver_register(&ohci_brcm_driver);
+}
+module_init(ohci_brcm_init);
+
+static void __exit ohci_brcm_exit(void)
+{
+	platform_driver_unregister(&ohci_brcm_driver);
+}
+module_exit(ohci_brcm_exit);
+
+MODULE_ALIAS("platform:ohci-brcm");
+MODULE_DESCRIPTION(BRCM_DRIVER_DESC);
+MODULE_AUTHOR("Al Cooper");
+MODULE_LICENSE("GPL");

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 3/5] usb: host: Add EHCI driver for Broadcom STB SoCs
  2018-09-26 22:20 ` Al Cooper
  (?)
@ 2018-09-26 22:20   ` Al Cooper
  -1 siblings, 0 replies; 29+ messages in thread
From: Al Cooper @ 2018-09-26 22:20 UTC (permalink / raw)
  To: linux-kernel
  Cc: Al Cooper, Greg Kroah-Hartman, Rob Herring, Mark Rutland,
	Alan Stern, Mathias Nyman, Mauro Carvalho Chehab,
	David S. Miller, Andrew Morton, Arnd Bergmann, Dmitry Osipenko,
	Chunfeng Yun, Jianguo Sun, James Hogan, Alban Bedel, Lu Baolu,
	Avi Fishman, Alex Elder, Hans de Goede, linux-usb, devicetree,
	bcm-kernel-feedback-list

This driver enables USB EHCI on Broadcom ARM and MIPS STB SoCs.
The drivers depend on a matching "brcm,brcmstb-usb-phy"
Broadcom STB USB Phy driver.

The standard platform driver can't be used because of differences
in PHY and Clock handling. The standard PHY handling in hcd.c will
do a phy_exit/phy_init on suspend/resume and this will end up
shutting down the PHYs to the point that the host controller
registers are no longer accessible and will cause suspend to crash.
The clocks specified in device tree for these drivers are not
available in mainline so instead of returning EPROBE_DEFER when
the specified clock is not found and eventually failing probe,
the clock pointer is set to NULL which disables all clock handling.

Signed-off-by: Al Cooper <alcooperx@gmail.com>
---
 drivers/usb/host/ehci-brcm.c | 304 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 304 insertions(+)
 create mode 100644 drivers/usb/host/ehci-brcm.c

diff --git a/drivers/usb/host/ehci-brcm.c b/drivers/usb/host/ehci-brcm.c
new file mode 100644
index 000000000000..6bee4e0e2cbb
--- /dev/null
+++ b/drivers/usb/host/ehci-brcm.c
@@ -0,0 +1,304 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2018, Broadcom */
+
+#include <linux/acpi.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/kernel.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/usb.h>
+#include <linux/usb/hcd.h>
+
+#include "ehci.h"
+
+#define BRCM_DRIVER_DESC "EHCI Broadcom STB driver"
+
+#define hcd_to_ehci_priv(h) ((struct brcm_priv *)hcd_to_ehci(h)->priv)
+
+struct brcm_priv {
+	struct clk *clk;
+	struct phy *phy;
+};
+
+static const char brcm_hcd_name[] = "ehci-brcm";
+
+static int (*org_hub_control)(struct usb_hcd *hcd,
+			u16 typeReq, u16 wValue, u16 wIndex,
+			char *buf, u16 wLength);
+
+/* ehci_brcm_wait_for_sof
+ * Wait for start of next microframe, then wait extra delay microseconds
+ */
+static inline void ehci_brcm_wait_for_sof(struct ehci_hcd *ehci, u32 delay)
+{
+	int frame_idx = ehci_readl(ehci, &ehci->regs->frame_index);
+
+	while (frame_idx == ehci_readl(ehci, &ehci->regs->frame_index))
+		;
+	udelay(delay);
+}
+
+/*
+ * ehci_brcm_hub_control
+ * Intercept echi-hcd request to complete RESUME and align it to the start
+ * of the next microframe.
+ * If RESUME is complete too late in the microframe, host controller
+ * detects babble on suspended port and resets the port afterwards.
+ * This s/w workaround allows to avoid this problem.
+ * See SWLINUX-1909 for more details
+ */
+static int ehci_brcm_hub_control(
+	struct usb_hcd	*hcd,
+	u16		typeReq,
+	u16		wValue,
+	u16		wIndex,
+	char		*buf,
+	u16		wLength)
+{
+	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
+	int		ports = HCS_N_PORTS(ehci->hcs_params);
+	u32 __iomem	*status_reg = &ehci->regs->port_status[
+				(wIndex & 0xff) - 1];
+	unsigned long flags;
+	int retval, irq_disabled = 0;
+
+	/*
+	 * RESUME is cleared when GetPortStatus() is called 20ms after start
+	 * of RESUME
+	 */
+	if ((typeReq == GetPortStatus) &&
+	    (wIndex && wIndex <= ports) &&
+	    ehci->reset_done[wIndex-1] &&
+	    time_after_eq(jiffies, ehci->reset_done[wIndex-1]) &&
+	    (ehci_readl(ehci, status_reg) & PORT_RESUME)) {
+
+		/*
+		 * to make sure we are not interrupted until RESUME bit
+		 * is cleared, disable interrupts on current CPU
+		 */
+		ehci_dbg(ehci, "SOF alignment workaround\n");
+		irq_disabled = 1;
+		local_irq_save(flags);
+		ehci_brcm_wait_for_sof(ehci, 5);
+	}
+	retval = (*org_hub_control)(hcd, typeReq, wValue, wIndex, buf, wLength);
+	if (irq_disabled)
+		local_irq_restore(flags);
+	return retval;
+}
+
+static int ehci_brcm_reset(struct usb_hcd *hcd)
+{
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+
+	ehci->big_endian_mmio = 1;
+
+	ehci->caps = (struct ehci_caps *) hcd->regs;
+	ehci->regs = (struct ehci_regs *) (hcd->regs +
+		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)));
+
+	/* This fixes the lockup during reboot due to prior interrupts */
+	ehci_writel(ehci, CMD_RESET, &ehci->regs->command);
+	mdelay(10);
+
+	/*
+	 * SWLINUX-1705: Avoid OUT packet underflows during high memory
+	 *   bus usage
+	 * port_status[0x0f] = Broadcom-proprietary USB_EHCI_INSNREG00 @ 0x90
+	 */
+	ehci_writel(ehci, 0x00800040, &ehci->regs->port_status[0x10]);
+	ehci_writel(ehci, 0x00000001, &ehci->regs->port_status[0x12]);
+
+	return ehci_setup(hcd);
+}
+
+static struct hc_driver __read_mostly ehci_brcm_hc_driver;
+
+static const struct ehci_driver_overrides brcm_overrides __initconst = {
+
+	.reset =	ehci_brcm_reset,
+	.extra_priv_size = sizeof(struct brcm_priv),
+};
+
+static int ehci_brcm_probe(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd;
+	struct resource *res_mem;
+	struct brcm_priv *priv;
+	int irq;
+	int err;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	err = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+	if (err)
+		return err;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "no irq provided");
+		return irq;
+	}
+
+	/* Hook the hub control routine to work around a bug */
+	if (org_hub_control == NULL)
+		org_hub_control = ehci_brcm_hc_driver.hub_control;
+	ehci_brcm_hc_driver.hub_control = ehci_brcm_hub_control;
+
+	/* initialize hcd */
+	hcd = usb_create_hcd(&ehci_brcm_hc_driver,
+			&pdev->dev, dev_name(&pdev->dev));
+	if (!hcd)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, hcd);
+	priv = hcd_to_ehci_priv(hcd);
+
+	priv->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(priv->clk)) {
+		dev_err(&pdev->dev, "Clock not found in Device Tree\n");
+		priv->clk = NULL;
+	}
+	err = clk_prepare_enable(priv->clk);
+	if (err)
+		goto err_hcd;
+
+	priv->phy = devm_of_phy_get_by_index(&pdev->dev, pdev->dev.of_node, 0);
+	if (IS_ERR(priv->phy)) {
+		dev_err(&pdev->dev, "USB Phy not found.\n");
+		err = PTR_ERR(priv->phy);
+		goto err_clk;
+	}
+	phy_init(priv->phy);
+
+	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	hcd->regs = devm_ioremap_resource(&pdev->dev, res_mem);
+	if (IS_ERR(hcd->regs)) {
+		err = PTR_ERR(hcd->regs);
+		goto err_phy;
+	}
+	hcd->rsrc_start = res_mem->start;
+	hcd->rsrc_len = resource_size(res_mem);
+	hcd->skip_phy_initialization = 1;
+	err = usb_add_hcd(hcd, irq, IRQF_SHARED);
+	if (err)
+		goto err_phy;
+
+	device_wakeup_enable(hcd->self.controller);
+	device_enable_async_suspend(hcd->self.controller);
+	platform_set_drvdata(pdev, hcd);
+
+	return err;
+
+err_phy:
+	phy_exit(priv->phy);
+err_clk:
+	clk_disable_unprepare(priv->clk);
+err_hcd:
+	usb_put_hcd(hcd);
+
+	return err;
+}
+
+static int ehci_brcm_remove(struct platform_device *dev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(dev);
+	struct brcm_priv *priv = hcd_to_ehci_priv(hcd);
+
+	usb_remove_hcd(hcd);
+	phy_exit(priv->phy);
+	clk_disable_unprepare(priv->clk);
+	usb_put_hcd(hcd);
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+
+static int ehci_brcm_suspend(struct device *dev)
+{
+	int ret;
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	struct brcm_priv *priv = hcd_to_ehci_priv(hcd);
+	bool do_wakeup = device_may_wakeup(dev);
+
+	ret = ehci_suspend(hcd, do_wakeup);
+	clk_disable_unprepare(priv->clk);
+	return ret;
+}
+
+static int ehci_brcm_resume(struct device *dev)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	struct brcm_priv *priv = hcd_to_ehci_priv(hcd);
+	int err;
+
+	err = clk_prepare_enable(priv->clk);
+	if (err)
+		return err;
+	/*
+	 * SWLINUX-1705: Avoid OUT packet underflows during high memory
+	 *   bus usage
+	 * port_status[0x0f] = Broadcom-proprietary USB_EHCI_INSNREG00
+	 * @ 0x90
+	 */
+	ehci_writel(ehci, 0x00800040, &ehci->regs->port_status[0x10]);
+	ehci_writel(ehci, 0x00000001, &ehci->regs->port_status[0x12]);
+
+	ehci_resume(hcd, false);
+	return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static SIMPLE_DEV_PM_OPS(ehci_brcm_pm_ops, ehci_brcm_suspend,
+		ehci_brcm_resume);
+
+#ifdef CONFIG_OF
+static const struct of_device_id brcm_ehci_of_match[] = {
+	{ .compatible = "brcm,ehci-brcm-v2", },
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, brcm_ehci_of_match);
+#endif /* CONFIG_OF */
+
+static struct platform_driver ehci_brcm_driver = {
+	.probe		= ehci_brcm_probe,
+	.remove		= ehci_brcm_remove,
+	.shutdown	= usb_hcd_platform_shutdown,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "ehci-brcm",
+		.pm	= &ehci_brcm_pm_ops,
+		.of_match_table = of_match_ptr(brcm_ehci_of_match),
+	}
+};
+
+static int __init ehci_brcm_init(void)
+{
+	if (usb_disabled())
+		return -ENODEV;
+
+	pr_info("%s: " BRCM_DRIVER_DESC "\n", brcm_hcd_name);
+
+	ehci_init_driver(&ehci_brcm_hc_driver, &brcm_overrides);
+	return platform_driver_register(&ehci_brcm_driver);
+}
+module_init(ehci_brcm_init);
+
+static void __exit ehci_brcm_exit(void)
+{
+	platform_driver_unregister(&ehci_brcm_driver);
+}
+module_exit(ehci_brcm_exit);
+
+MODULE_ALIAS("platform:ehci-brcm");
+MODULE_DESCRIPTION(BRCM_DRIVER_DESC);
+MODULE_AUTHOR("Al Cooper");
+MODULE_LICENSE("GPL");
-- 
1.9.0.138.g2de3478


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 3/5] usb: host: Add EHCI driver for Broadcom STB SoCs
@ 2018-09-26 22:20   ` Al Cooper
  0 siblings, 0 replies; 29+ messages in thread
From: Al Cooper @ 2018-09-26 22:20 UTC (permalink / raw)
  To: linux-kernel
  Cc: Al Cooper, Greg Kroah-Hartman, Rob Herring, Mark Rutland,
	Alan Stern, Mathias Nyman, Mauro Carvalho Chehab,
	David S. Miller, Andrew Morton, Arnd Bergmann, Dmitry Osipenko,
	Chunfeng Yun, Jianguo Sun, James Hogan, Alban Bedel, Lu Baolu,
	Avi Fishman, Alex Elder, Hans de Goede, linux-usb, dev

This driver enables USB EHCI on Broadcom ARM and MIPS STB SoCs.
The drivers depend on a matching "brcm,brcmstb-usb-phy"
Broadcom STB USB Phy driver.

The standard platform driver can't be used because of differences
in PHY and Clock handling. The standard PHY handling in hcd.c will
do a phy_exit/phy_init on suspend/resume and this will end up
shutting down the PHYs to the point that the host controller
registers are no longer accessible and will cause suspend to crash.
The clocks specified in device tree for these drivers are not
available in mainline so instead of returning EPROBE_DEFER when
the specified clock is not found and eventually failing probe,
the clock pointer is set to NULL which disables all clock handling.

Signed-off-by: Al Cooper <alcooperx@gmail.com>
---
 drivers/usb/host/ehci-brcm.c | 304 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 304 insertions(+)
 create mode 100644 drivers/usb/host/ehci-brcm.c

diff --git a/drivers/usb/host/ehci-brcm.c b/drivers/usb/host/ehci-brcm.c
new file mode 100644
index 000000000000..6bee4e0e2cbb
--- /dev/null
+++ b/drivers/usb/host/ehci-brcm.c
@@ -0,0 +1,304 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2018, Broadcom */
+
+#include <linux/acpi.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/kernel.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/usb.h>
+#include <linux/usb/hcd.h>
+
+#include "ehci.h"
+
+#define BRCM_DRIVER_DESC "EHCI Broadcom STB driver"
+
+#define hcd_to_ehci_priv(h) ((struct brcm_priv *)hcd_to_ehci(h)->priv)
+
+struct brcm_priv {
+	struct clk *clk;
+	struct phy *phy;
+};
+
+static const char brcm_hcd_name[] = "ehci-brcm";
+
+static int (*org_hub_control)(struct usb_hcd *hcd,
+			u16 typeReq, u16 wValue, u16 wIndex,
+			char *buf, u16 wLength);
+
+/* ehci_brcm_wait_for_sof
+ * Wait for start of next microframe, then wait extra delay microseconds
+ */
+static inline void ehci_brcm_wait_for_sof(struct ehci_hcd *ehci, u32 delay)
+{
+	int frame_idx = ehci_readl(ehci, &ehci->regs->frame_index);
+
+	while (frame_idx == ehci_readl(ehci, &ehci->regs->frame_index))
+		;
+	udelay(delay);
+}
+
+/*
+ * ehci_brcm_hub_control
+ * Intercept echi-hcd request to complete RESUME and align it to the start
+ * of the next microframe.
+ * If RESUME is complete too late in the microframe, host controller
+ * detects babble on suspended port and resets the port afterwards.
+ * This s/w workaround allows to avoid this problem.
+ * See SWLINUX-1909 for more details
+ */
+static int ehci_brcm_hub_control(
+	struct usb_hcd	*hcd,
+	u16		typeReq,
+	u16		wValue,
+	u16		wIndex,
+	char		*buf,
+	u16		wLength)
+{
+	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
+	int		ports = HCS_N_PORTS(ehci->hcs_params);
+	u32 __iomem	*status_reg = &ehci->regs->port_status[
+				(wIndex & 0xff) - 1];
+	unsigned long flags;
+	int retval, irq_disabled = 0;
+
+	/*
+	 * RESUME is cleared when GetPortStatus() is called 20ms after start
+	 * of RESUME
+	 */
+	if ((typeReq == GetPortStatus) &&
+	    (wIndex && wIndex <= ports) &&
+	    ehci->reset_done[wIndex-1] &&
+	    time_after_eq(jiffies, ehci->reset_done[wIndex-1]) &&
+	    (ehci_readl(ehci, status_reg) & PORT_RESUME)) {
+
+		/*
+		 * to make sure we are not interrupted until RESUME bit
+		 * is cleared, disable interrupts on current CPU
+		 */
+		ehci_dbg(ehci, "SOF alignment workaround\n");
+		irq_disabled = 1;
+		local_irq_save(flags);
+		ehci_brcm_wait_for_sof(ehci, 5);
+	}
+	retval = (*org_hub_control)(hcd, typeReq, wValue, wIndex, buf, wLength);
+	if (irq_disabled)
+		local_irq_restore(flags);
+	return retval;
+}
+
+static int ehci_brcm_reset(struct usb_hcd *hcd)
+{
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+
+	ehci->big_endian_mmio = 1;
+
+	ehci->caps = (struct ehci_caps *) hcd->regs;
+	ehci->regs = (struct ehci_regs *) (hcd->regs +
+		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)));
+
+	/* This fixes the lockup during reboot due to prior interrupts */
+	ehci_writel(ehci, CMD_RESET, &ehci->regs->command);
+	mdelay(10);
+
+	/*
+	 * SWLINUX-1705: Avoid OUT packet underflows during high memory
+	 *   bus usage
+	 * port_status[0x0f] = Broadcom-proprietary USB_EHCI_INSNREG00 @ 0x90
+	 */
+	ehci_writel(ehci, 0x00800040, &ehci->regs->port_status[0x10]);
+	ehci_writel(ehci, 0x00000001, &ehci->regs->port_status[0x12]);
+
+	return ehci_setup(hcd);
+}
+
+static struct hc_driver __read_mostly ehci_brcm_hc_driver;
+
+static const struct ehci_driver_overrides brcm_overrides __initconst = {
+
+	.reset =	ehci_brcm_reset,
+	.extra_priv_size = sizeof(struct brcm_priv),
+};
+
+static int ehci_brcm_probe(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd;
+	struct resource *res_mem;
+	struct brcm_priv *priv;
+	int irq;
+	int err;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	err = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+	if (err)
+		return err;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "no irq provided");
+		return irq;
+	}
+
+	/* Hook the hub control routine to work around a bug */
+	if (org_hub_control == NULL)
+		org_hub_control = ehci_brcm_hc_driver.hub_control;
+	ehci_brcm_hc_driver.hub_control = ehci_brcm_hub_control;
+
+	/* initialize hcd */
+	hcd = usb_create_hcd(&ehci_brcm_hc_driver,
+			&pdev->dev, dev_name(&pdev->dev));
+	if (!hcd)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, hcd);
+	priv = hcd_to_ehci_priv(hcd);
+
+	priv->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(priv->clk)) {
+		dev_err(&pdev->dev, "Clock not found in Device Tree\n");
+		priv->clk = NULL;
+	}
+	err = clk_prepare_enable(priv->clk);
+	if (err)
+		goto err_hcd;
+
+	priv->phy = devm_of_phy_get_by_index(&pdev->dev, pdev->dev.of_node, 0);
+	if (IS_ERR(priv->phy)) {
+		dev_err(&pdev->dev, "USB Phy not found.\n");
+		err = PTR_ERR(priv->phy);
+		goto err_clk;
+	}
+	phy_init(priv->phy);
+
+	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	hcd->regs = devm_ioremap_resource(&pdev->dev, res_mem);
+	if (IS_ERR(hcd->regs)) {
+		err = PTR_ERR(hcd->regs);
+		goto err_phy;
+	}
+	hcd->rsrc_start = res_mem->start;
+	hcd->rsrc_len = resource_size(res_mem);
+	hcd->skip_phy_initialization = 1;
+	err = usb_add_hcd(hcd, irq, IRQF_SHARED);
+	if (err)
+		goto err_phy;
+
+	device_wakeup_enable(hcd->self.controller);
+	device_enable_async_suspend(hcd->self.controller);
+	platform_set_drvdata(pdev, hcd);
+
+	return err;
+
+err_phy:
+	phy_exit(priv->phy);
+err_clk:
+	clk_disable_unprepare(priv->clk);
+err_hcd:
+	usb_put_hcd(hcd);
+
+	return err;
+}
+
+static int ehci_brcm_remove(struct platform_device *dev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(dev);
+	struct brcm_priv *priv = hcd_to_ehci_priv(hcd);
+
+	usb_remove_hcd(hcd);
+	phy_exit(priv->phy);
+	clk_disable_unprepare(priv->clk);
+	usb_put_hcd(hcd);
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+
+static int ehci_brcm_suspend(struct device *dev)
+{
+	int ret;
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	struct brcm_priv *priv = hcd_to_ehci_priv(hcd);
+	bool do_wakeup = device_may_wakeup(dev);
+
+	ret = ehci_suspend(hcd, do_wakeup);
+	clk_disable_unprepare(priv->clk);
+	return ret;
+}
+
+static int ehci_brcm_resume(struct device *dev)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	struct brcm_priv *priv = hcd_to_ehci_priv(hcd);
+	int err;
+
+	err = clk_prepare_enable(priv->clk);
+	if (err)
+		return err;
+	/*
+	 * SWLINUX-1705: Avoid OUT packet underflows during high memory
+	 *   bus usage
+	 * port_status[0x0f] = Broadcom-proprietary USB_EHCI_INSNREG00
+	 * @ 0x90
+	 */
+	ehci_writel(ehci, 0x00800040, &ehci->regs->port_status[0x10]);
+	ehci_writel(ehci, 0x00000001, &ehci->regs->port_status[0x12]);
+
+	ehci_resume(hcd, false);
+	return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static SIMPLE_DEV_PM_OPS(ehci_brcm_pm_ops, ehci_brcm_suspend,
+		ehci_brcm_resume);
+
+#ifdef CONFIG_OF
+static const struct of_device_id brcm_ehci_of_match[] = {
+	{ .compatible = "brcm,ehci-brcm-v2", },
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, brcm_ehci_of_match);
+#endif /* CONFIG_OF */
+
+static struct platform_driver ehci_brcm_driver = {
+	.probe		= ehci_brcm_probe,
+	.remove		= ehci_brcm_remove,
+	.shutdown	= usb_hcd_platform_shutdown,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "ehci-brcm",
+		.pm	= &ehci_brcm_pm_ops,
+		.of_match_table = of_match_ptr(brcm_ehci_of_match),
+	}
+};
+
+static int __init ehci_brcm_init(void)
+{
+	if (usb_disabled())
+		return -ENODEV;
+
+	pr_info("%s: " BRCM_DRIVER_DESC "\n", brcm_hcd_name);
+
+	ehci_init_driver(&ehci_brcm_hc_driver, &brcm_overrides);
+	return platform_driver_register(&ehci_brcm_driver);
+}
+module_init(ehci_brcm_init);
+
+static void __exit ehci_brcm_exit(void)
+{
+	platform_driver_unregister(&ehci_brcm_driver);
+}
+module_exit(ehci_brcm_exit);
+
+MODULE_ALIAS("platform:ehci-brcm");
+MODULE_DESCRIPTION(BRCM_DRIVER_DESC);
+MODULE_AUTHOR("Al Cooper");
+MODULE_LICENSE("GPL");
-- 
1.9.0.138.g2de3478

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [3/5] usb: host: Add EHCI driver for Broadcom STB SoCs
@ 2018-09-26 22:20   ` Al Cooper
  0 siblings, 0 replies; 29+ messages in thread
From: Alan Cooper @ 2018-09-26 22:20 UTC (permalink / raw)
  To: linux-kernel
  Cc: Al Cooper, Greg Kroah-Hartman, Rob Herring, Mark Rutland,
	Alan Stern, Mathias Nyman, Mauro Carvalho Chehab,
	David S. Miller, Andrew Morton, Arnd Bergmann, Dmitry Osipenko,
	Chunfeng Yun, Jianguo Sun, James Hogan, Alban Bedel, Lu Baolu,
	Avi Fishman, Alex Elder, Hans de Goede, linux-usb, devicetree,
	bcm-kernel-feedback-list

This driver enables USB EHCI on Broadcom ARM and MIPS STB SoCs.
The drivers depend on a matching "brcm,brcmstb-usb-phy"
Broadcom STB USB Phy driver.

The standard platform driver can't be used because of differences
in PHY and Clock handling. The standard PHY handling in hcd.c will
do a phy_exit/phy_init on suspend/resume and this will end up
shutting down the PHYs to the point that the host controller
registers are no longer accessible and will cause suspend to crash.
The clocks specified in device tree for these drivers are not
available in mainline so instead of returning EPROBE_DEFER when
the specified clock is not found and eventually failing probe,
the clock pointer is set to NULL which disables all clock handling.

Signed-off-by: Al Cooper <alcooperx@gmail.com>
---
 drivers/usb/host/ehci-brcm.c | 304 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 304 insertions(+)
 create mode 100644 drivers/usb/host/ehci-brcm.c

diff --git a/drivers/usb/host/ehci-brcm.c b/drivers/usb/host/ehci-brcm.c
new file mode 100644
index 000000000000..6bee4e0e2cbb
--- /dev/null
+++ b/drivers/usb/host/ehci-brcm.c
@@ -0,0 +1,304 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2018, Broadcom */
+
+#include <linux/acpi.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/kernel.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/usb.h>
+#include <linux/usb/hcd.h>
+
+#include "ehci.h"
+
+#define BRCM_DRIVER_DESC "EHCI Broadcom STB driver"
+
+#define hcd_to_ehci_priv(h) ((struct brcm_priv *)hcd_to_ehci(h)->priv)
+
+struct brcm_priv {
+	struct clk *clk;
+	struct phy *phy;
+};
+
+static const char brcm_hcd_name[] = "ehci-brcm";
+
+static int (*org_hub_control)(struct usb_hcd *hcd,
+			u16 typeReq, u16 wValue, u16 wIndex,
+			char *buf, u16 wLength);
+
+/* ehci_brcm_wait_for_sof
+ * Wait for start of next microframe, then wait extra delay microseconds
+ */
+static inline void ehci_brcm_wait_for_sof(struct ehci_hcd *ehci, u32 delay)
+{
+	int frame_idx = ehci_readl(ehci, &ehci->regs->frame_index);
+
+	while (frame_idx == ehci_readl(ehci, &ehci->regs->frame_index))
+		;
+	udelay(delay);
+}
+
+/*
+ * ehci_brcm_hub_control
+ * Intercept echi-hcd request to complete RESUME and align it to the start
+ * of the next microframe.
+ * If RESUME is complete too late in the microframe, host controller
+ * detects babble on suspended port and resets the port afterwards.
+ * This s/w workaround allows to avoid this problem.
+ * See SWLINUX-1909 for more details
+ */
+static int ehci_brcm_hub_control(
+	struct usb_hcd	*hcd,
+	u16		typeReq,
+	u16		wValue,
+	u16		wIndex,
+	char		*buf,
+	u16		wLength)
+{
+	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
+	int		ports = HCS_N_PORTS(ehci->hcs_params);
+	u32 __iomem	*status_reg = &ehci->regs->port_status[
+				(wIndex & 0xff) - 1];
+	unsigned long flags;
+	int retval, irq_disabled = 0;
+
+	/*
+	 * RESUME is cleared when GetPortStatus() is called 20ms after start
+	 * of RESUME
+	 */
+	if ((typeReq == GetPortStatus) &&
+	    (wIndex && wIndex <= ports) &&
+	    ehci->reset_done[wIndex-1] &&
+	    time_after_eq(jiffies, ehci->reset_done[wIndex-1]) &&
+	    (ehci_readl(ehci, status_reg) & PORT_RESUME)) {
+
+		/*
+		 * to make sure we are not interrupted until RESUME bit
+		 * is cleared, disable interrupts on current CPU
+		 */
+		ehci_dbg(ehci, "SOF alignment workaround\n");
+		irq_disabled = 1;
+		local_irq_save(flags);
+		ehci_brcm_wait_for_sof(ehci, 5);
+	}
+	retval = (*org_hub_control)(hcd, typeReq, wValue, wIndex, buf, wLength);
+	if (irq_disabled)
+		local_irq_restore(flags);
+	return retval;
+}
+
+static int ehci_brcm_reset(struct usb_hcd *hcd)
+{
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+
+	ehci->big_endian_mmio = 1;
+
+	ehci->caps = (struct ehci_caps *) hcd->regs;
+	ehci->regs = (struct ehci_regs *) (hcd->regs +
+		HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)));
+
+	/* This fixes the lockup during reboot due to prior interrupts */
+	ehci_writel(ehci, CMD_RESET, &ehci->regs->command);
+	mdelay(10);
+
+	/*
+	 * SWLINUX-1705: Avoid OUT packet underflows during high memory
+	 *   bus usage
+	 * port_status[0x0f] = Broadcom-proprietary USB_EHCI_INSNREG00 @ 0x90
+	 */
+	ehci_writel(ehci, 0x00800040, &ehci->regs->port_status[0x10]);
+	ehci_writel(ehci, 0x00000001, &ehci->regs->port_status[0x12]);
+
+	return ehci_setup(hcd);
+}
+
+static struct hc_driver __read_mostly ehci_brcm_hc_driver;
+
+static const struct ehci_driver_overrides brcm_overrides __initconst = {
+
+	.reset =	ehci_brcm_reset,
+	.extra_priv_size = sizeof(struct brcm_priv),
+};
+
+static int ehci_brcm_probe(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd;
+	struct resource *res_mem;
+	struct brcm_priv *priv;
+	int irq;
+	int err;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	err = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+	if (err)
+		return err;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "no irq provided");
+		return irq;
+	}
+
+	/* Hook the hub control routine to work around a bug */
+	if (org_hub_control == NULL)
+		org_hub_control = ehci_brcm_hc_driver.hub_control;
+	ehci_brcm_hc_driver.hub_control = ehci_brcm_hub_control;
+
+	/* initialize hcd */
+	hcd = usb_create_hcd(&ehci_brcm_hc_driver,
+			&pdev->dev, dev_name(&pdev->dev));
+	if (!hcd)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, hcd);
+	priv = hcd_to_ehci_priv(hcd);
+
+	priv->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(priv->clk)) {
+		dev_err(&pdev->dev, "Clock not found in Device Tree\n");
+		priv->clk = NULL;
+	}
+	err = clk_prepare_enable(priv->clk);
+	if (err)
+		goto err_hcd;
+
+	priv->phy = devm_of_phy_get_by_index(&pdev->dev, pdev->dev.of_node, 0);
+	if (IS_ERR(priv->phy)) {
+		dev_err(&pdev->dev, "USB Phy not found.\n");
+		err = PTR_ERR(priv->phy);
+		goto err_clk;
+	}
+	phy_init(priv->phy);
+
+	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	hcd->regs = devm_ioremap_resource(&pdev->dev, res_mem);
+	if (IS_ERR(hcd->regs)) {
+		err = PTR_ERR(hcd->regs);
+		goto err_phy;
+	}
+	hcd->rsrc_start = res_mem->start;
+	hcd->rsrc_len = resource_size(res_mem);
+	hcd->skip_phy_initialization = 1;
+	err = usb_add_hcd(hcd, irq, IRQF_SHARED);
+	if (err)
+		goto err_phy;
+
+	device_wakeup_enable(hcd->self.controller);
+	device_enable_async_suspend(hcd->self.controller);
+	platform_set_drvdata(pdev, hcd);
+
+	return err;
+
+err_phy:
+	phy_exit(priv->phy);
+err_clk:
+	clk_disable_unprepare(priv->clk);
+err_hcd:
+	usb_put_hcd(hcd);
+
+	return err;
+}
+
+static int ehci_brcm_remove(struct platform_device *dev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(dev);
+	struct brcm_priv *priv = hcd_to_ehci_priv(hcd);
+
+	usb_remove_hcd(hcd);
+	phy_exit(priv->phy);
+	clk_disable_unprepare(priv->clk);
+	usb_put_hcd(hcd);
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+
+static int ehci_brcm_suspend(struct device *dev)
+{
+	int ret;
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	struct brcm_priv *priv = hcd_to_ehci_priv(hcd);
+	bool do_wakeup = device_may_wakeup(dev);
+
+	ret = ehci_suspend(hcd, do_wakeup);
+	clk_disable_unprepare(priv->clk);
+	return ret;
+}
+
+static int ehci_brcm_resume(struct device *dev)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	struct brcm_priv *priv = hcd_to_ehci_priv(hcd);
+	int err;
+
+	err = clk_prepare_enable(priv->clk);
+	if (err)
+		return err;
+	/*
+	 * SWLINUX-1705: Avoid OUT packet underflows during high memory
+	 *   bus usage
+	 * port_status[0x0f] = Broadcom-proprietary USB_EHCI_INSNREG00
+	 * @ 0x90
+	 */
+	ehci_writel(ehci, 0x00800040, &ehci->regs->port_status[0x10]);
+	ehci_writel(ehci, 0x00000001, &ehci->regs->port_status[0x12]);
+
+	ehci_resume(hcd, false);
+	return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static SIMPLE_DEV_PM_OPS(ehci_brcm_pm_ops, ehci_brcm_suspend,
+		ehci_brcm_resume);
+
+#ifdef CONFIG_OF
+static const struct of_device_id brcm_ehci_of_match[] = {
+	{ .compatible = "brcm,ehci-brcm-v2", },
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, brcm_ehci_of_match);
+#endif /* CONFIG_OF */
+
+static struct platform_driver ehci_brcm_driver = {
+	.probe		= ehci_brcm_probe,
+	.remove		= ehci_brcm_remove,
+	.shutdown	= usb_hcd_platform_shutdown,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "ehci-brcm",
+		.pm	= &ehci_brcm_pm_ops,
+		.of_match_table = of_match_ptr(brcm_ehci_of_match),
+	}
+};
+
+static int __init ehci_brcm_init(void)
+{
+	if (usb_disabled())
+		return -ENODEV;
+
+	pr_info("%s: " BRCM_DRIVER_DESC "\n", brcm_hcd_name);
+
+	ehci_init_driver(&ehci_brcm_hc_driver, &brcm_overrides);
+	return platform_driver_register(&ehci_brcm_driver);
+}
+module_init(ehci_brcm_init);
+
+static void __exit ehci_brcm_exit(void)
+{
+	platform_driver_unregister(&ehci_brcm_driver);
+}
+module_exit(ehci_brcm_exit);
+
+MODULE_ALIAS("platform:ehci-brcm");
+MODULE_DESCRIPTION(BRCM_DRIVER_DESC);
+MODULE_AUTHOR("Al Cooper");
+MODULE_LICENSE("GPL");

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 4/5] usb: host: Add XHCI driver for Broadcom STB SoCs
  2018-09-26 22:20 ` Al Cooper
  (?)
@ 2018-09-26 22:20   ` Al Cooper
  -1 siblings, 0 replies; 29+ messages in thread
From: Al Cooper @ 2018-09-26 22:20 UTC (permalink / raw)
  To: linux-kernel
  Cc: Al Cooper, Greg Kroah-Hartman, Rob Herring, Mark Rutland,
	Alan Stern, Mathias Nyman, Mauro Carvalho Chehab,
	David S. Miller, Andrew Morton, Arnd Bergmann, Dmitry Osipenko,
	Chunfeng Yun, Jianguo Sun, James Hogan, Alban Bedel, Lu Baolu,
	Avi Fishman, Alex Elder, Hans de Goede, linux-usb, devicetree,
	bcm-kernel-feedback-list

This driver enables USB XHCI on Broadcom ARM STB SoCs.
The drivers depend on a matching "brcm,brcmstb-usb-phy"
Broadcom STB USB Phy driver.

The standard platform driver can't be used because of differences
in PHY and Clock handling. The standard PHY handling in hcd.c will
do a phy_exit/phy_init on suspend/resume and this will end up
shutting down the PHYs to the point that the host controller
registers are no longer accessible and will cause suspend to crash.
The clocks specified in device tree for these drivers are not
available in mainline so instead of returning EPROBE_DEFER when
the specified clock is not found and eventually failing probe,
the clock pointer is set to NULL which disables all clock handling.

Signed-off-by: Al Cooper <alcooperx@gmail.com>
---
 drivers/usb/host/xhci-brcm.c | 294 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 294 insertions(+)
 create mode 100644 drivers/usb/host/xhci-brcm.c

diff --git a/drivers/usb/host/xhci-brcm.c b/drivers/usb/host/xhci-brcm.c
new file mode 100644
index 000000000000..1a7578b8ef6a
--- /dev/null
+++ b/drivers/usb/host/xhci-brcm.c
@@ -0,0 +1,294 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2018, Broadcom */
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <linux/phy/phy.h>
+
+#include "xhci.h"
+
+static struct hc_driver __read_mostly xhci_brcm_hc_driver;
+
+#define BRCM_DRIVER_DESC "xHCI Broadcom STB driver"
+#define BRCM_DRIVER_NAME "xhci-brcm"
+
+#define hcd_to_xhci_priv(h) ((struct brcm_priv *)hcd_to_xhci(h)->priv)
+
+struct brcm_priv {
+	struct phy *phy;
+};
+
+static void xhci_brcm_quirks(struct device *dev, struct xhci_hcd *xhci)
+{
+	/*
+	 * As of now platform drivers don't provide MSI support so we ensure
+	 * here that the generic code does not try to make a pci_dev from our
+	 * dev struct in order to setup MSI
+	 */
+	xhci->quirks |= XHCI_PLAT;
+
+	/*
+	 * The Broadcom XHCI core does not support save/restore state
+	 * so we need to reset on resume.
+	 */
+	xhci->quirks |= XHCI_RESET_ON_RESUME;
+}
+
+/* called during probe() after chip reset completes */
+static int xhci_brcm_setup(struct usb_hcd *hcd)
+{
+	return xhci_gen_setup(hcd, xhci_brcm_quirks);
+}
+
+static const struct xhci_driver_overrides brcm_overrides __initconst = {
+
+	.extra_priv_size = sizeof(struct brcm_priv),
+	.reset = xhci_brcm_setup,
+};
+
+static int xhci_brcm_probe(struct platform_device *pdev)
+{
+	const struct hc_driver	*driver;
+	struct brcm_priv	*priv;
+	struct xhci_hcd		*xhci;
+	struct resource         *res;
+	struct usb_hcd		*hcd;
+	int			ret;
+	int			irq;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	driver = &xhci_brcm_hc_driver;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return -ENODEV;
+
+	/* Try to set 64-bit DMA first */
+	if (WARN_ON(!pdev->dev.dma_mask))
+		/* Platform did not initialize dma_mask */
+		ret = dma_coerce_mask_and_coherent(&pdev->dev,
+						   DMA_BIT_MASK(64));
+	else
+		ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+
+	/* If seting 64-bit DMA mask fails, fall back to 32-bit DMA mask */
+	if (ret) {
+		ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+		if (ret)
+			return ret;
+	}
+
+	pm_runtime_set_active(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+	pm_runtime_get_noresume(&pdev->dev);
+
+	hcd = __usb_create_hcd(driver, &pdev->dev, &pdev->dev,
+			       dev_name(&pdev->dev), NULL);
+	if (!hcd) {
+		return -ENOMEM;
+		goto disable_runtime;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	hcd->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(hcd->regs)) {
+		ret = PTR_ERR(hcd->regs);
+		goto put_hcd;
+	}
+
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = resource_size(res);
+
+	/*
+	 * Not all platforms have a clk so it is not an error if the
+	 * clock does not exists.
+	 */
+	xhci = hcd_to_xhci(hcd);
+	xhci->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(xhci->clk)) {
+		dev_err(&pdev->dev, "Clock not found in Device Tree\n");
+		xhci->clk = NULL;
+	}
+	device_wakeup_enable(hcd->self.controller);
+
+	xhci->main_hcd = hcd;
+	xhci->shared_hcd = __usb_create_hcd(driver, &pdev->dev, &pdev->dev,
+					    dev_name(&pdev->dev), hcd);
+	if (!xhci->shared_hcd) {
+		ret = -ENOMEM;
+		goto disable_clk;
+	}
+
+	if (device_property_read_bool(&pdev->dev, "usb3-lpm-capable"))
+		xhci->quirks |= XHCI_LPM_SUPPORT;
+
+	priv = hcd_to_xhci_priv(hcd);
+	priv->phy = devm_of_phy_get_by_index(&pdev->dev, pdev->dev.of_node, 0);
+	if (IS_ERR(priv->phy)) {
+		dev_err(&pdev->dev, "USB Phy not found.\n");
+		ret = PTR_ERR(priv->phy);
+		goto put_usb3_hcd;
+	}
+	ret = phy_init(priv->phy);
+	if (ret)
+		goto put_usb3_hcd;
+
+	hcd->skip_phy_initialization = 1;
+	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
+	if (ret)
+		goto disable_usb_phy;
+
+	if (HCC_MAX_PSA(xhci->hcc_params) >= 4)
+		xhci->shared_hcd->can_do_streams = 1;
+
+	ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
+	if (ret)
+		goto dealloc_usb2_hcd;
+
+	device_enable_async_suspend(&pdev->dev);
+	pm_runtime_put_noidle(&pdev->dev);
+
+	/*
+	 * Prevent runtime pm from being on as default, users should enable
+	 * runtime pm using power/control in sysfs.
+	 */
+	pm_runtime_forbid(&pdev->dev);
+
+	return 0;
+
+dealloc_usb2_hcd:
+	usb_remove_hcd(hcd);
+
+disable_usb_phy:
+	phy_exit(priv->phy);
+
+put_usb3_hcd:
+	usb_put_hcd(xhci->shared_hcd);
+
+disable_clk:
+	if (!IS_ERR(xhci->clk))
+		clk_disable_unprepare(xhci->clk);
+
+put_hcd:
+	usb_put_hcd(hcd);
+
+disable_runtime:
+	pm_runtime_put_noidle(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+
+	return ret;
+}
+
+static int xhci_brcm_remove(struct platform_device *dev)
+{
+	struct usb_hcd	*hcd = platform_get_drvdata(dev);
+	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
+	struct brcm_priv *priv = hcd_to_xhci_priv(hcd);
+
+	xhci->xhc_state |= XHCI_STATE_REMOVING;
+
+	usb_remove_hcd(xhci->shared_hcd);
+	usb_remove_hcd(hcd);
+	usb_put_hcd(xhci->shared_hcd);
+	phy_exit(priv->phy);
+	clk_disable_unprepare(xhci->clk);
+	usb_put_hcd(hcd);
+
+	pm_runtime_set_suspended(&dev->dev);
+	pm_runtime_disable(&dev->dev);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int xhci_brcm_suspend(struct device *dev)
+{
+	int ret;
+	struct usb_hcd	*hcd = dev_get_drvdata(dev);
+	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
+
+	ret = xhci_suspend(xhci, device_may_wakeup(dev));
+	clk_disable_unprepare(xhci->clk);
+	return ret;
+}
+
+static int xhci_brcm_resume(struct device *dev)
+{
+	struct usb_hcd	*hcd = dev_get_drvdata(dev);
+	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
+	int err;
+
+	err = clk_prepare_enable(xhci->clk);
+	if (err)
+		return err;
+	return xhci_resume(xhci, 0);
+}
+
+static int xhci_brcm_runtime_suspend(struct device *dev)
+{
+	struct usb_hcd	*hcd = dev_get_drvdata(dev);
+	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
+
+	return xhci_suspend(xhci, true);
+}
+
+static int xhci_brcm_runtime_resume(struct device *dev)
+{
+	struct usb_hcd	*hcd = dev_get_drvdata(dev);
+	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
+
+	return xhci_resume(xhci, 0);
+}
+
+#endif /* CONFIG_PM_SLEEP */
+
+
+static const struct dev_pm_ops xhci_brcm_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(xhci_brcm_suspend, xhci_brcm_resume)
+
+	SET_RUNTIME_PM_OPS(xhci_brcm_runtime_suspend,
+			   xhci_brcm_runtime_resume,
+			   NULL)
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id brcm_xhci_of_match[] = {
+	{ .compatible = "brcm,xhci-brcm-v2" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, brcm_xhci_of_match);
+#endif
+
+static struct platform_driver xhci_brcm_driver = {
+	.probe	= xhci_brcm_probe,
+	.remove	= xhci_brcm_remove,
+	.driver	= {
+		.name = BRCM_DRIVER_NAME,
+		.pm = &xhci_brcm_pm_ops,
+		.of_match_table = of_match_ptr(brcm_xhci_of_match),
+	},
+};
+
+static int __init xhci_brcm_init(void)
+{
+	pr_info("%s: " BRCM_DRIVER_DESC "\n", BRCM_DRIVER_NAME);
+	xhci_init_driver(&xhci_brcm_hc_driver, &brcm_overrides);
+	return platform_driver_register(&xhci_brcm_driver);
+}
+module_init(xhci_brcm_init);
+
+static void __exit xhci_brcm_exit(void)
+{
+	platform_driver_unregister(&xhci_brcm_driver);
+}
+module_exit(xhci_brcm_exit);
+
+MODULE_ALIAS("platform:xhci-brcm");
+MODULE_DESCRIPTION(BRCM_DRIVER_DESC);
+MODULE_AUTHOR("Al Cooper");
+MODULE_LICENSE("GPL");
-- 
1.9.0.138.g2de3478


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 4/5] usb: host: Add XHCI driver for Broadcom STB SoCs
@ 2018-09-26 22:20   ` Al Cooper
  0 siblings, 0 replies; 29+ messages in thread
From: Al Cooper @ 2018-09-26 22:20 UTC (permalink / raw)
  To: linux-kernel
  Cc: Al Cooper, Greg Kroah-Hartman, Rob Herring, Mark Rutland,
	Alan Stern, Mathias Nyman, Mauro Carvalho Chehab,
	David S. Miller, Andrew Morton, Arnd Bergmann, Dmitry Osipenko,
	Chunfeng Yun, Jianguo Sun, James Hogan, Alban Bedel, Lu Baolu,
	Avi Fishman, Alex Elder, Hans de Goede, linux-usb, dev

This driver enables USB XHCI on Broadcom ARM STB SoCs.
The drivers depend on a matching "brcm,brcmstb-usb-phy"
Broadcom STB USB Phy driver.

The standard platform driver can't be used because of differences
in PHY and Clock handling. The standard PHY handling in hcd.c will
do a phy_exit/phy_init on suspend/resume and this will end up
shutting down the PHYs to the point that the host controller
registers are no longer accessible and will cause suspend to crash.
The clocks specified in device tree for these drivers are not
available in mainline so instead of returning EPROBE_DEFER when
the specified clock is not found and eventually failing probe,
the clock pointer is set to NULL which disables all clock handling.

Signed-off-by: Al Cooper <alcooperx@gmail.com>
---
 drivers/usb/host/xhci-brcm.c | 294 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 294 insertions(+)
 create mode 100644 drivers/usb/host/xhci-brcm.c

diff --git a/drivers/usb/host/xhci-brcm.c b/drivers/usb/host/xhci-brcm.c
new file mode 100644
index 000000000000..1a7578b8ef6a
--- /dev/null
+++ b/drivers/usb/host/xhci-brcm.c
@@ -0,0 +1,294 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2018, Broadcom */
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <linux/phy/phy.h>
+
+#include "xhci.h"
+
+static struct hc_driver __read_mostly xhci_brcm_hc_driver;
+
+#define BRCM_DRIVER_DESC "xHCI Broadcom STB driver"
+#define BRCM_DRIVER_NAME "xhci-brcm"
+
+#define hcd_to_xhci_priv(h) ((struct brcm_priv *)hcd_to_xhci(h)->priv)
+
+struct brcm_priv {
+	struct phy *phy;
+};
+
+static void xhci_brcm_quirks(struct device *dev, struct xhci_hcd *xhci)
+{
+	/*
+	 * As of now platform drivers don't provide MSI support so we ensure
+	 * here that the generic code does not try to make a pci_dev from our
+	 * dev struct in order to setup MSI
+	 */
+	xhci->quirks |= XHCI_PLAT;
+
+	/*
+	 * The Broadcom XHCI core does not support save/restore state
+	 * so we need to reset on resume.
+	 */
+	xhci->quirks |= XHCI_RESET_ON_RESUME;
+}
+
+/* called during probe() after chip reset completes */
+static int xhci_brcm_setup(struct usb_hcd *hcd)
+{
+	return xhci_gen_setup(hcd, xhci_brcm_quirks);
+}
+
+static const struct xhci_driver_overrides brcm_overrides __initconst = {
+
+	.extra_priv_size = sizeof(struct brcm_priv),
+	.reset = xhci_brcm_setup,
+};
+
+static int xhci_brcm_probe(struct platform_device *pdev)
+{
+	const struct hc_driver	*driver;
+	struct brcm_priv	*priv;
+	struct xhci_hcd		*xhci;
+	struct resource         *res;
+	struct usb_hcd		*hcd;
+	int			ret;
+	int			irq;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	driver = &xhci_brcm_hc_driver;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return -ENODEV;
+
+	/* Try to set 64-bit DMA first */
+	if (WARN_ON(!pdev->dev.dma_mask))
+		/* Platform did not initialize dma_mask */
+		ret = dma_coerce_mask_and_coherent(&pdev->dev,
+						   DMA_BIT_MASK(64));
+	else
+		ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+
+	/* If seting 64-bit DMA mask fails, fall back to 32-bit DMA mask */
+	if (ret) {
+		ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+		if (ret)
+			return ret;
+	}
+
+	pm_runtime_set_active(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+	pm_runtime_get_noresume(&pdev->dev);
+
+	hcd = __usb_create_hcd(driver, &pdev->dev, &pdev->dev,
+			       dev_name(&pdev->dev), NULL);
+	if (!hcd) {
+		return -ENOMEM;
+		goto disable_runtime;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	hcd->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(hcd->regs)) {
+		ret = PTR_ERR(hcd->regs);
+		goto put_hcd;
+	}
+
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = resource_size(res);
+
+	/*
+	 * Not all platforms have a clk so it is not an error if the
+	 * clock does not exists.
+	 */
+	xhci = hcd_to_xhci(hcd);
+	xhci->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(xhci->clk)) {
+		dev_err(&pdev->dev, "Clock not found in Device Tree\n");
+		xhci->clk = NULL;
+	}
+	device_wakeup_enable(hcd->self.controller);
+
+	xhci->main_hcd = hcd;
+	xhci->shared_hcd = __usb_create_hcd(driver, &pdev->dev, &pdev->dev,
+					    dev_name(&pdev->dev), hcd);
+	if (!xhci->shared_hcd) {
+		ret = -ENOMEM;
+		goto disable_clk;
+	}
+
+	if (device_property_read_bool(&pdev->dev, "usb3-lpm-capable"))
+		xhci->quirks |= XHCI_LPM_SUPPORT;
+
+	priv = hcd_to_xhci_priv(hcd);
+	priv->phy = devm_of_phy_get_by_index(&pdev->dev, pdev->dev.of_node, 0);
+	if (IS_ERR(priv->phy)) {
+		dev_err(&pdev->dev, "USB Phy not found.\n");
+		ret = PTR_ERR(priv->phy);
+		goto put_usb3_hcd;
+	}
+	ret = phy_init(priv->phy);
+	if (ret)
+		goto put_usb3_hcd;
+
+	hcd->skip_phy_initialization = 1;
+	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
+	if (ret)
+		goto disable_usb_phy;
+
+	if (HCC_MAX_PSA(xhci->hcc_params) >= 4)
+		xhci->shared_hcd->can_do_streams = 1;
+
+	ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
+	if (ret)
+		goto dealloc_usb2_hcd;
+
+	device_enable_async_suspend(&pdev->dev);
+	pm_runtime_put_noidle(&pdev->dev);
+
+	/*
+	 * Prevent runtime pm from being on as default, users should enable
+	 * runtime pm using power/control in sysfs.
+	 */
+	pm_runtime_forbid(&pdev->dev);
+
+	return 0;
+
+dealloc_usb2_hcd:
+	usb_remove_hcd(hcd);
+
+disable_usb_phy:
+	phy_exit(priv->phy);
+
+put_usb3_hcd:
+	usb_put_hcd(xhci->shared_hcd);
+
+disable_clk:
+	if (!IS_ERR(xhci->clk))
+		clk_disable_unprepare(xhci->clk);
+
+put_hcd:
+	usb_put_hcd(hcd);
+
+disable_runtime:
+	pm_runtime_put_noidle(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+
+	return ret;
+}
+
+static int xhci_brcm_remove(struct platform_device *dev)
+{
+	struct usb_hcd	*hcd = platform_get_drvdata(dev);
+	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
+	struct brcm_priv *priv = hcd_to_xhci_priv(hcd);
+
+	xhci->xhc_state |= XHCI_STATE_REMOVING;
+
+	usb_remove_hcd(xhci->shared_hcd);
+	usb_remove_hcd(hcd);
+	usb_put_hcd(xhci->shared_hcd);
+	phy_exit(priv->phy);
+	clk_disable_unprepare(xhci->clk);
+	usb_put_hcd(hcd);
+
+	pm_runtime_set_suspended(&dev->dev);
+	pm_runtime_disable(&dev->dev);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int xhci_brcm_suspend(struct device *dev)
+{
+	int ret;
+	struct usb_hcd	*hcd = dev_get_drvdata(dev);
+	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
+
+	ret = xhci_suspend(xhci, device_may_wakeup(dev));
+	clk_disable_unprepare(xhci->clk);
+	return ret;
+}
+
+static int xhci_brcm_resume(struct device *dev)
+{
+	struct usb_hcd	*hcd = dev_get_drvdata(dev);
+	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
+	int err;
+
+	err = clk_prepare_enable(xhci->clk);
+	if (err)
+		return err;
+	return xhci_resume(xhci, 0);
+}
+
+static int xhci_brcm_runtime_suspend(struct device *dev)
+{
+	struct usb_hcd	*hcd = dev_get_drvdata(dev);
+	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
+
+	return xhci_suspend(xhci, true);
+}
+
+static int xhci_brcm_runtime_resume(struct device *dev)
+{
+	struct usb_hcd	*hcd = dev_get_drvdata(dev);
+	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
+
+	return xhci_resume(xhci, 0);
+}
+
+#endif /* CONFIG_PM_SLEEP */
+
+
+static const struct dev_pm_ops xhci_brcm_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(xhci_brcm_suspend, xhci_brcm_resume)
+
+	SET_RUNTIME_PM_OPS(xhci_brcm_runtime_suspend,
+			   xhci_brcm_runtime_resume,
+			   NULL)
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id brcm_xhci_of_match[] = {
+	{ .compatible = "brcm,xhci-brcm-v2" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, brcm_xhci_of_match);
+#endif
+
+static struct platform_driver xhci_brcm_driver = {
+	.probe	= xhci_brcm_probe,
+	.remove	= xhci_brcm_remove,
+	.driver	= {
+		.name = BRCM_DRIVER_NAME,
+		.pm = &xhci_brcm_pm_ops,
+		.of_match_table = of_match_ptr(brcm_xhci_of_match),
+	},
+};
+
+static int __init xhci_brcm_init(void)
+{
+	pr_info("%s: " BRCM_DRIVER_DESC "\n", BRCM_DRIVER_NAME);
+	xhci_init_driver(&xhci_brcm_hc_driver, &brcm_overrides);
+	return platform_driver_register(&xhci_brcm_driver);
+}
+module_init(xhci_brcm_init);
+
+static void __exit xhci_brcm_exit(void)
+{
+	platform_driver_unregister(&xhci_brcm_driver);
+}
+module_exit(xhci_brcm_exit);
+
+MODULE_ALIAS("platform:xhci-brcm");
+MODULE_DESCRIPTION(BRCM_DRIVER_DESC);
+MODULE_AUTHOR("Al Cooper");
+MODULE_LICENSE("GPL");
-- 
1.9.0.138.g2de3478

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [4/5] usb: host: Add XHCI driver for Broadcom STB SoCs
@ 2018-09-26 22:20   ` Al Cooper
  0 siblings, 0 replies; 29+ messages in thread
From: Alan Cooper @ 2018-09-26 22:20 UTC (permalink / raw)
  To: linux-kernel
  Cc: Al Cooper, Greg Kroah-Hartman, Rob Herring, Mark Rutland,
	Alan Stern, Mathias Nyman, Mauro Carvalho Chehab,
	David S. Miller, Andrew Morton, Arnd Bergmann, Dmitry Osipenko,
	Chunfeng Yun, Jianguo Sun, James Hogan, Alban Bedel, Lu Baolu,
	Avi Fishman, Alex Elder, Hans de Goede, linux-usb, devicetree,
	bcm-kernel-feedback-list

This driver enables USB XHCI on Broadcom ARM STB SoCs.
The drivers depend on a matching "brcm,brcmstb-usb-phy"
Broadcom STB USB Phy driver.

The standard platform driver can't be used because of differences
in PHY and Clock handling. The standard PHY handling in hcd.c will
do a phy_exit/phy_init on suspend/resume and this will end up
shutting down the PHYs to the point that the host controller
registers are no longer accessible and will cause suspend to crash.
The clocks specified in device tree for these drivers are not
available in mainline so instead of returning EPROBE_DEFER when
the specified clock is not found and eventually failing probe,
the clock pointer is set to NULL which disables all clock handling.

Signed-off-by: Al Cooper <alcooperx@gmail.com>
---
 drivers/usb/host/xhci-brcm.c | 294 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 294 insertions(+)
 create mode 100644 drivers/usb/host/xhci-brcm.c

diff --git a/drivers/usb/host/xhci-brcm.c b/drivers/usb/host/xhci-brcm.c
new file mode 100644
index 000000000000..1a7578b8ef6a
--- /dev/null
+++ b/drivers/usb/host/xhci-brcm.c
@@ -0,0 +1,294 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2018, Broadcom */
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <linux/phy/phy.h>
+
+#include "xhci.h"
+
+static struct hc_driver __read_mostly xhci_brcm_hc_driver;
+
+#define BRCM_DRIVER_DESC "xHCI Broadcom STB driver"
+#define BRCM_DRIVER_NAME "xhci-brcm"
+
+#define hcd_to_xhci_priv(h) ((struct brcm_priv *)hcd_to_xhci(h)->priv)
+
+struct brcm_priv {
+	struct phy *phy;
+};
+
+static void xhci_brcm_quirks(struct device *dev, struct xhci_hcd *xhci)
+{
+	/*
+	 * As of now platform drivers don't provide MSI support so we ensure
+	 * here that the generic code does not try to make a pci_dev from our
+	 * dev struct in order to setup MSI
+	 */
+	xhci->quirks |= XHCI_PLAT;
+
+	/*
+	 * The Broadcom XHCI core does not support save/restore state
+	 * so we need to reset on resume.
+	 */
+	xhci->quirks |= XHCI_RESET_ON_RESUME;
+}
+
+/* called during probe() after chip reset completes */
+static int xhci_brcm_setup(struct usb_hcd *hcd)
+{
+	return xhci_gen_setup(hcd, xhci_brcm_quirks);
+}
+
+static const struct xhci_driver_overrides brcm_overrides __initconst = {
+
+	.extra_priv_size = sizeof(struct brcm_priv),
+	.reset = xhci_brcm_setup,
+};
+
+static int xhci_brcm_probe(struct platform_device *pdev)
+{
+	const struct hc_driver	*driver;
+	struct brcm_priv	*priv;
+	struct xhci_hcd		*xhci;
+	struct resource         *res;
+	struct usb_hcd		*hcd;
+	int			ret;
+	int			irq;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	driver = &xhci_brcm_hc_driver;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return -ENODEV;
+
+	/* Try to set 64-bit DMA first */
+	if (WARN_ON(!pdev->dev.dma_mask))
+		/* Platform did not initialize dma_mask */
+		ret = dma_coerce_mask_and_coherent(&pdev->dev,
+						   DMA_BIT_MASK(64));
+	else
+		ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+
+	/* If seting 64-bit DMA mask fails, fall back to 32-bit DMA mask */
+	if (ret) {
+		ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+		if (ret)
+			return ret;
+	}
+
+	pm_runtime_set_active(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+	pm_runtime_get_noresume(&pdev->dev);
+
+	hcd = __usb_create_hcd(driver, &pdev->dev, &pdev->dev,
+			       dev_name(&pdev->dev), NULL);
+	if (!hcd) {
+		return -ENOMEM;
+		goto disable_runtime;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	hcd->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(hcd->regs)) {
+		ret = PTR_ERR(hcd->regs);
+		goto put_hcd;
+	}
+
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = resource_size(res);
+
+	/*
+	 * Not all platforms have a clk so it is not an error if the
+	 * clock does not exists.
+	 */
+	xhci = hcd_to_xhci(hcd);
+	xhci->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(xhci->clk)) {
+		dev_err(&pdev->dev, "Clock not found in Device Tree\n");
+		xhci->clk = NULL;
+	}
+	device_wakeup_enable(hcd->self.controller);
+
+	xhci->main_hcd = hcd;
+	xhci->shared_hcd = __usb_create_hcd(driver, &pdev->dev, &pdev->dev,
+					    dev_name(&pdev->dev), hcd);
+	if (!xhci->shared_hcd) {
+		ret = -ENOMEM;
+		goto disable_clk;
+	}
+
+	if (device_property_read_bool(&pdev->dev, "usb3-lpm-capable"))
+		xhci->quirks |= XHCI_LPM_SUPPORT;
+
+	priv = hcd_to_xhci_priv(hcd);
+	priv->phy = devm_of_phy_get_by_index(&pdev->dev, pdev->dev.of_node, 0);
+	if (IS_ERR(priv->phy)) {
+		dev_err(&pdev->dev, "USB Phy not found.\n");
+		ret = PTR_ERR(priv->phy);
+		goto put_usb3_hcd;
+	}
+	ret = phy_init(priv->phy);
+	if (ret)
+		goto put_usb3_hcd;
+
+	hcd->skip_phy_initialization = 1;
+	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
+	if (ret)
+		goto disable_usb_phy;
+
+	if (HCC_MAX_PSA(xhci->hcc_params) >= 4)
+		xhci->shared_hcd->can_do_streams = 1;
+
+	ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
+	if (ret)
+		goto dealloc_usb2_hcd;
+
+	device_enable_async_suspend(&pdev->dev);
+	pm_runtime_put_noidle(&pdev->dev);
+
+	/*
+	 * Prevent runtime pm from being on as default, users should enable
+	 * runtime pm using power/control in sysfs.
+	 */
+	pm_runtime_forbid(&pdev->dev);
+
+	return 0;
+
+dealloc_usb2_hcd:
+	usb_remove_hcd(hcd);
+
+disable_usb_phy:
+	phy_exit(priv->phy);
+
+put_usb3_hcd:
+	usb_put_hcd(xhci->shared_hcd);
+
+disable_clk:
+	if (!IS_ERR(xhci->clk))
+		clk_disable_unprepare(xhci->clk);
+
+put_hcd:
+	usb_put_hcd(hcd);
+
+disable_runtime:
+	pm_runtime_put_noidle(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+
+	return ret;
+}
+
+static int xhci_brcm_remove(struct platform_device *dev)
+{
+	struct usb_hcd	*hcd = platform_get_drvdata(dev);
+	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
+	struct brcm_priv *priv = hcd_to_xhci_priv(hcd);
+
+	xhci->xhc_state |= XHCI_STATE_REMOVING;
+
+	usb_remove_hcd(xhci->shared_hcd);
+	usb_remove_hcd(hcd);
+	usb_put_hcd(xhci->shared_hcd);
+	phy_exit(priv->phy);
+	clk_disable_unprepare(xhci->clk);
+	usb_put_hcd(hcd);
+
+	pm_runtime_set_suspended(&dev->dev);
+	pm_runtime_disable(&dev->dev);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int xhci_brcm_suspend(struct device *dev)
+{
+	int ret;
+	struct usb_hcd	*hcd = dev_get_drvdata(dev);
+	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
+
+	ret = xhci_suspend(xhci, device_may_wakeup(dev));
+	clk_disable_unprepare(xhci->clk);
+	return ret;
+}
+
+static int xhci_brcm_resume(struct device *dev)
+{
+	struct usb_hcd	*hcd = dev_get_drvdata(dev);
+	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
+	int err;
+
+	err = clk_prepare_enable(xhci->clk);
+	if (err)
+		return err;
+	return xhci_resume(xhci, 0);
+}
+
+static int xhci_brcm_runtime_suspend(struct device *dev)
+{
+	struct usb_hcd	*hcd = dev_get_drvdata(dev);
+	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
+
+	return xhci_suspend(xhci, true);
+}
+
+static int xhci_brcm_runtime_resume(struct device *dev)
+{
+	struct usb_hcd	*hcd = dev_get_drvdata(dev);
+	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
+
+	return xhci_resume(xhci, 0);
+}
+
+#endif /* CONFIG_PM_SLEEP */
+
+
+static const struct dev_pm_ops xhci_brcm_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(xhci_brcm_suspend, xhci_brcm_resume)
+
+	SET_RUNTIME_PM_OPS(xhci_brcm_runtime_suspend,
+			   xhci_brcm_runtime_resume,
+			   NULL)
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id brcm_xhci_of_match[] = {
+	{ .compatible = "brcm,xhci-brcm-v2" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, brcm_xhci_of_match);
+#endif
+
+static struct platform_driver xhci_brcm_driver = {
+	.probe	= xhci_brcm_probe,
+	.remove	= xhci_brcm_remove,
+	.driver	= {
+		.name = BRCM_DRIVER_NAME,
+		.pm = &xhci_brcm_pm_ops,
+		.of_match_table = of_match_ptr(brcm_xhci_of_match),
+	},
+};
+
+static int __init xhci_brcm_init(void)
+{
+	pr_info("%s: " BRCM_DRIVER_DESC "\n", BRCM_DRIVER_NAME);
+	xhci_init_driver(&xhci_brcm_hc_driver, &brcm_overrides);
+	return platform_driver_register(&xhci_brcm_driver);
+}
+module_init(xhci_brcm_init);
+
+static void __exit xhci_brcm_exit(void)
+{
+	platform_driver_unregister(&xhci_brcm_driver);
+}
+module_exit(xhci_brcm_exit);
+
+MODULE_ALIAS("platform:xhci-brcm");
+MODULE_DESCRIPTION(BRCM_DRIVER_DESC);
+MODULE_AUTHOR("Al Cooper");
+MODULE_LICENSE("GPL");

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 5/5] usb: host: Enable building of new Broadcom STB USB drivers
  2018-09-26 22:20 ` Al Cooper
  (?)
@ 2018-09-26 22:20   ` Al Cooper
  -1 siblings, 0 replies; 29+ messages in thread
From: Al Cooper @ 2018-09-26 22:20 UTC (permalink / raw)
  To: linux-kernel
  Cc: Al Cooper, Greg Kroah-Hartman, Rob Herring, Mark Rutland,
	Alan Stern, Mathias Nyman, Mauro Carvalho Chehab,
	David S. Miller, Andrew Morton, Arnd Bergmann, Dmitry Osipenko,
	Chunfeng Yun, Jianguo Sun, James Hogan, Alban Bedel, Lu Baolu,
	Avi Fishman, Alex Elder, Hans de Goede, linux-usb, devicetree,
	bcm-kernel-feedback-list

Changes to Makefile and Kconfig to enable building of the new
Broadcom STB OHCI, EHCI and XHCI drivers. Also update MAINTAINERS.

Signed-off-by: Al Cooper <alcooperx@gmail.com>
---
 MAINTAINERS               |  9 +++++++++
 drivers/usb/host/Kconfig  | 27 +++++++++++++++++++++++++++
 drivers/usb/host/Makefile |  7 +++++++
 3 files changed, 43 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 02a39617ec82..9b8e7caad2ba 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3007,6 +3007,15 @@ S:	Supported
 F:	drivers/gpio/gpio-brcmstb.c
 F:	Documentation/devicetree/bindings/gpio/brcm,brcmstb-gpio.txt
 
+BROADCOM BRCMSTB USB XHCI, EHCI and OHCI DRIVERS
+M:	Al Cooper <alcooperx@gmail.com>
+L:	linux-usb@vger.kernel.org
+L:	bcm-kernel-feedback-list@broadcom.com
+S:	Maintained
+F:	drivers/usb/host/xhci-brcm.c
+F:	drivers/usb/host/ehci-brcm.c
+F:	drivers/usb/host/ohci-brcm.c
+
 BROADCOM BRCMSTB USB2 and USB3 PHY DRIVER
 M:	Al Cooper <alcooperx@gmail.com>
 L:	linux-kernel@vger.kernel.org
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 1a4ea98cac2a..1693a5076980 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -798,3 +798,30 @@ config USB_HCD_TEST_MODE
 	  This option is of interest only to developers who need to validate
 	  their USB hardware designs.  It is not needed for normal use.  If
 	  unsure, say N.
+
+config USB_OHCI_BRCM
+       tristate
+
+config USB_EHCI_BRCM
+       tristate
+
+config USB_XHCI_BRCM
+       tristate
+
+config BRCM_USB_PHY
+       tristate
+
+config USB_BRCM
+	tristate "Broadcom STB USB support"
+	depends on ARCH_BRCMSTB
+	select USB_OHCI_BRCM if USB_OHCI_HCD
+	select USB_EHCI_BRCM if USB_EHCI_HCD
+	select USB_XHCI_BRCM if USB_XHCI_HCD
+	select BRCM_USB_PHY if USB_OHCI_HCD || USB_EHCI_HCD || USB_XHCI_HCD
+	select GENERIC_PHY if BRCM_USB_PHY
+	default ARCH_BRCMSTB
+	help
+	  Say Y to enable the drivers for the onchip USB controllers.
+
+	  If your chipset supports power management, disabling this driver
+	  will keep the device permanently powered down.
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index e6235269c151..13e4f45a3a1d 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -91,3 +91,10 @@ obj-$(CONFIG_USB_HCD_BCMA)	+= bcma-hcd.o
 obj-$(CONFIG_USB_HCD_SSB)	+= ssb-hcd.o
 obj-$(CONFIG_USB_FOTG210_HCD)	+= fotg210-hcd.o
 obj-$(CONFIG_USB_MAX3421_HCD)	+= max3421-hcd.o
+
+# The order is important here because it controls the order that
+# the drivers will be initialized and we always need to init
+# the drivers in the order XHCI, EHCI and OHCI.
+obj-$(CONFIG_USB_XHCI_BRCM)	+= xhci-brcm.o
+obj-$(CONFIG_USB_EHCI_BRCM)	+= ehci-brcm.o
+obj-$(CONFIG_USB_OHCI_BRCM)	+= ohci-brcm.o
-- 
1.9.0.138.g2de3478


^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [PATCH 5/5] usb: host: Enable building of new Broadcom STB USB drivers
@ 2018-09-26 22:20   ` Al Cooper
  0 siblings, 0 replies; 29+ messages in thread
From: Al Cooper @ 2018-09-26 22:20 UTC (permalink / raw)
  To: linux-kernel
  Cc: Al Cooper, Greg Kroah-Hartman, Rob Herring, Mark Rutland,
	Alan Stern, Mathias Nyman, Mauro Carvalho Chehab,
	David S. Miller, Andrew Morton, Arnd Bergmann, Dmitry Osipenko,
	Chunfeng Yun, Jianguo Sun, James Hogan, Alban Bedel, Lu Baolu,
	Avi Fishman, Alex Elder, Hans de Goede, linux-usb, dev

Changes to Makefile and Kconfig to enable building of the new
Broadcom STB OHCI, EHCI and XHCI drivers. Also update MAINTAINERS.

Signed-off-by: Al Cooper <alcooperx@gmail.com>
---
 MAINTAINERS               |  9 +++++++++
 drivers/usb/host/Kconfig  | 27 +++++++++++++++++++++++++++
 drivers/usb/host/Makefile |  7 +++++++
 3 files changed, 43 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 02a39617ec82..9b8e7caad2ba 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3007,6 +3007,15 @@ S:	Supported
 F:	drivers/gpio/gpio-brcmstb.c
 F:	Documentation/devicetree/bindings/gpio/brcm,brcmstb-gpio.txt
 
+BROADCOM BRCMSTB USB XHCI, EHCI and OHCI DRIVERS
+M:	Al Cooper <alcooperx@gmail.com>
+L:	linux-usb@vger.kernel.org
+L:	bcm-kernel-feedback-list@broadcom.com
+S:	Maintained
+F:	drivers/usb/host/xhci-brcm.c
+F:	drivers/usb/host/ehci-brcm.c
+F:	drivers/usb/host/ohci-brcm.c
+
 BROADCOM BRCMSTB USB2 and USB3 PHY DRIVER
 M:	Al Cooper <alcooperx@gmail.com>
 L:	linux-kernel@vger.kernel.org
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 1a4ea98cac2a..1693a5076980 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -798,3 +798,30 @@ config USB_HCD_TEST_MODE
 	  This option is of interest only to developers who need to validate
 	  their USB hardware designs.  It is not needed for normal use.  If
 	  unsure, say N.
+
+config USB_OHCI_BRCM
+       tristate
+
+config USB_EHCI_BRCM
+       tristate
+
+config USB_XHCI_BRCM
+       tristate
+
+config BRCM_USB_PHY
+       tristate
+
+config USB_BRCM
+	tristate "Broadcom STB USB support"
+	depends on ARCH_BRCMSTB
+	select USB_OHCI_BRCM if USB_OHCI_HCD
+	select USB_EHCI_BRCM if USB_EHCI_HCD
+	select USB_XHCI_BRCM if USB_XHCI_HCD
+	select BRCM_USB_PHY if USB_OHCI_HCD || USB_EHCI_HCD || USB_XHCI_HCD
+	select GENERIC_PHY if BRCM_USB_PHY
+	default ARCH_BRCMSTB
+	help
+	  Say Y to enable the drivers for the onchip USB controllers.
+
+	  If your chipset supports power management, disabling this driver
+	  will keep the device permanently powered down.
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index e6235269c151..13e4f45a3a1d 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -91,3 +91,10 @@ obj-$(CONFIG_USB_HCD_BCMA)	+= bcma-hcd.o
 obj-$(CONFIG_USB_HCD_SSB)	+= ssb-hcd.o
 obj-$(CONFIG_USB_FOTG210_HCD)	+= fotg210-hcd.o
 obj-$(CONFIG_USB_MAX3421_HCD)	+= max3421-hcd.o
+
+# The order is important here because it controls the order that
+# the drivers will be initialized and we always need to init
+# the drivers in the order XHCI, EHCI and OHCI.
+obj-$(CONFIG_USB_XHCI_BRCM)	+= xhci-brcm.o
+obj-$(CONFIG_USB_EHCI_BRCM)	+= ehci-brcm.o
+obj-$(CONFIG_USB_OHCI_BRCM)	+= ohci-brcm.o
-- 
1.9.0.138.g2de3478

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [5/5] usb: host: Enable building of new Broadcom STB USB drivers
@ 2018-09-26 22:20   ` Al Cooper
  0 siblings, 0 replies; 29+ messages in thread
From: Alan Cooper @ 2018-09-26 22:20 UTC (permalink / raw)
  To: linux-kernel
  Cc: Al Cooper, Greg Kroah-Hartman, Rob Herring, Mark Rutland,
	Alan Stern, Mathias Nyman, Mauro Carvalho Chehab,
	David S. Miller, Andrew Morton, Arnd Bergmann, Dmitry Osipenko,
	Chunfeng Yun, Jianguo Sun, James Hogan, Alban Bedel, Lu Baolu,
	Avi Fishman, Alex Elder, Hans de Goede, linux-usb, devicetree,
	bcm-kernel-feedback-list

Changes to Makefile and Kconfig to enable building of the new
Broadcom STB OHCI, EHCI and XHCI drivers. Also update MAINTAINERS.

Signed-off-by: Al Cooper <alcooperx@gmail.com>
---
 MAINTAINERS               |  9 +++++++++
 drivers/usb/host/Kconfig  | 27 +++++++++++++++++++++++++++
 drivers/usb/host/Makefile |  7 +++++++
 3 files changed, 43 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 02a39617ec82..9b8e7caad2ba 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3007,6 +3007,15 @@ S:	Supported
 F:	drivers/gpio/gpio-brcmstb.c
 F:	Documentation/devicetree/bindings/gpio/brcm,brcmstb-gpio.txt
 
+BROADCOM BRCMSTB USB XHCI, EHCI and OHCI DRIVERS
+M:	Al Cooper <alcooperx@gmail.com>
+L:	linux-usb@vger.kernel.org
+L:	bcm-kernel-feedback-list@broadcom.com
+S:	Maintained
+F:	drivers/usb/host/xhci-brcm.c
+F:	drivers/usb/host/ehci-brcm.c
+F:	drivers/usb/host/ohci-brcm.c
+
 BROADCOM BRCMSTB USB2 and USB3 PHY DRIVER
 M:	Al Cooper <alcooperx@gmail.com>
 L:	linux-kernel@vger.kernel.org
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 1a4ea98cac2a..1693a5076980 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -798,3 +798,30 @@ config USB_HCD_TEST_MODE
 	  This option is of interest only to developers who need to validate
 	  their USB hardware designs.  It is not needed for normal use.  If
 	  unsure, say N.
+
+config USB_OHCI_BRCM
+       tristate
+
+config USB_EHCI_BRCM
+       tristate
+
+config USB_XHCI_BRCM
+       tristate
+
+config BRCM_USB_PHY
+       tristate
+
+config USB_BRCM
+	tristate "Broadcom STB USB support"
+	depends on ARCH_BRCMSTB
+	select USB_OHCI_BRCM if USB_OHCI_HCD
+	select USB_EHCI_BRCM if USB_EHCI_HCD
+	select USB_XHCI_BRCM if USB_XHCI_HCD
+	select BRCM_USB_PHY if USB_OHCI_HCD || USB_EHCI_HCD || USB_XHCI_HCD
+	select GENERIC_PHY if BRCM_USB_PHY
+	default ARCH_BRCMSTB
+	help
+	  Say Y to enable the drivers for the onchip USB controllers.
+
+	  If your chipset supports power management, disabling this driver
+	  will keep the device permanently powered down.
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index e6235269c151..13e4f45a3a1d 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -91,3 +91,10 @@ obj-$(CONFIG_USB_HCD_BCMA)	+= bcma-hcd.o
 obj-$(CONFIG_USB_HCD_SSB)	+= ssb-hcd.o
 obj-$(CONFIG_USB_FOTG210_HCD)	+= fotg210-hcd.o
 obj-$(CONFIG_USB_MAX3421_HCD)	+= max3421-hcd.o
+
+# The order is important here because it controls the order that
+# the drivers will be initialized and we always need to init
+# the drivers in the order XHCI, EHCI and OHCI.
+obj-$(CONFIG_USB_XHCI_BRCM)	+= xhci-brcm.o
+obj-$(CONFIG_USB_EHCI_BRCM)	+= ehci-brcm.o
+obj-$(CONFIG_USB_OHCI_BRCM)	+= ohci-brcm.o

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* Re: [PATCH 4/5] usb: host: Add XHCI driver for Broadcom STB SoCs
  2018-09-26 22:20   ` [PATCH 4/5] " Al Cooper
  (?)
@ 2018-09-27  5:51     ` Chunfeng Yun
  -1 siblings, 0 replies; 29+ messages in thread
From: Chunfeng Yun @ 2018-09-27  5:51 UTC (permalink / raw)
  To: Al Cooper
  Cc: linux-kernel, Greg Kroah-Hartman, Rob Herring, Mark Rutland,
	Alan Stern, Mathias Nyman, Mauro Carvalho Chehab,
	David S. Miller, Andrew Morton, Arnd Bergmann, Dmitry Osipenko,
	Jianguo Sun, James Hogan, Alban Bedel, Lu Baolu, Avi Fishman,
	Alex Elder, Hans de Goede, linux-usb, devicetree,
	bcm-kernel-feedback-list

Hi,

On Wed, 2018-09-26 at 18:20 -0400, Al Cooper wrote:
> This driver enables USB XHCI on Broadcom ARM STB SoCs.
> The drivers depend on a matching "brcm,brcmstb-usb-phy"
> Broadcom STB USB Phy driver.
> 
> The standard platform driver can't be used because of differences
> in PHY and Clock handling. The standard PHY handling in hcd.c will
> do a phy_exit/phy_init on suspend/resume and this will end up
> shutting down the PHYs to the point that the host controller
> registers are no longer accessible and will cause suspend to crash.
You can avoid hcd.c to do a phy_exit/phy_init on suspend/resume by
device_init_wakeup(dev, true);

> The clocks specified in device tree for these drivers are not
> available in mainline so instead of returning EPROBE_DEFER when
> the specified clock is not found and eventually failing probe,
> the clock pointer is set to NULL which disables all clock handling.
Try to use a fixed-clock as dummy clock if the clock is optional?

> 
> Signed-off-by: Al Cooper <alcooperx@gmail.com>
> ---
>  drivers/usb/host/xhci-brcm.c | 294 +++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 294 insertions(+)
>  create mode 100644 drivers/usb/host/xhci-brcm.c
> 
> diff --git a/drivers/usb/host/xhci-brcm.c b/drivers/usb/host/xhci-brcm.c
> new file mode 100644
> index 000000000000..1a7578b8ef6a
> --- /dev/null
> +++ b/drivers/usb/host/xhci-brcm.c
> @@ -0,0 +1,294 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (c) 2018, Broadcom */
> +
> +#include <linux/platform_device.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/clk.h>
> +#include <linux/phy/phy.h>
> +
> +#include "xhci.h"
> +
> +static struct hc_driver __read_mostly xhci_brcm_hc_driver;
> +
> +#define BRCM_DRIVER_DESC "xHCI Broadcom STB driver"
> +#define BRCM_DRIVER_NAME "xhci-brcm"
> +
> +#define hcd_to_xhci_priv(h) ((struct brcm_priv *)hcd_to_xhci(h)->priv)
> +
> +struct brcm_priv {
> +	struct phy *phy;
> +};
> +
> +static void xhci_brcm_quirks(struct device *dev, struct xhci_hcd *xhci)
> +{
> +	/*
> +	 * As of now platform drivers don't provide MSI support so we ensure
> +	 * here that the generic code does not try to make a pci_dev from our
> +	 * dev struct in order to setup MSI
> +	 */
> +	xhci->quirks |= XHCI_PLAT;
> +
> +	/*
> +	 * The Broadcom XHCI core does not support save/restore state
> +	 * so we need to reset on resume.
> +	 */
> +	xhci->quirks |= XHCI_RESET_ON_RESUME;
> +}
> +
> +/* called during probe() after chip reset completes */
> +static int xhci_brcm_setup(struct usb_hcd *hcd)
> +{
> +	return xhci_gen_setup(hcd, xhci_brcm_quirks);
> +}
> +
> +static const struct xhci_driver_overrides brcm_overrides __initconst = {
> +
> +	.extra_priv_size = sizeof(struct brcm_priv),
> +	.reset = xhci_brcm_setup,
> +};
> +
> +static int xhci_brcm_probe(struct platform_device *pdev)
> +{
> +	const struct hc_driver	*driver;
> +	struct brcm_priv	*priv;
> +	struct xhci_hcd		*xhci;
> +	struct resource         *res;
> +	struct usb_hcd		*hcd;
> +	int			ret;
> +	int			irq;
> +
> +	if (usb_disabled())
> +		return -ENODEV;
> +
> +	driver = &xhci_brcm_hc_driver;
> +
> +	irq = platform_get_irq(pdev, 0);
> +	if (irq < 0)
> +		return -ENODEV;
> +
> +	/* Try to set 64-bit DMA first */
> +	if (WARN_ON(!pdev->dev.dma_mask))
> +		/* Platform did not initialize dma_mask */
> +		ret = dma_coerce_mask_and_coherent(&pdev->dev,
> +						   DMA_BIT_MASK(64));
> +	else
> +		ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
> +
> +	/* If seting 64-bit DMA mask fails, fall back to 32-bit DMA mask */
> +	if (ret) {
> +		ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
> +		if (ret)
> +			return ret;
> +	}
> +
> +	pm_runtime_set_active(&pdev->dev);
> +	pm_runtime_enable(&pdev->dev);
> +	pm_runtime_get_noresume(&pdev->dev);
> +
> +	hcd = __usb_create_hcd(driver, &pdev->dev, &pdev->dev,
> +			       dev_name(&pdev->dev), NULL);
> +	if (!hcd) {
> +		return -ENOMEM;
> +		goto disable_runtime;
> +	}
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	hcd->regs = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(hcd->regs)) {
> +		ret = PTR_ERR(hcd->regs);
> +		goto put_hcd;
> +	}
> +
> +	hcd->rsrc_start = res->start;
> +	hcd->rsrc_len = resource_size(res);
> +
> +	/*
> +	 * Not all platforms have a clk so it is not an error if the
> +	 * clock does not exists.
> +	 */
> +	xhci = hcd_to_xhci(hcd);
> +	xhci->clk = devm_clk_get(&pdev->dev, NULL);
> +	if (IS_ERR(xhci->clk)) {
> +		dev_err(&pdev->dev, "Clock not found in Device Tree\n");
> +		xhci->clk = NULL;
> +	}
> +	device_wakeup_enable(hcd->self.controller);
> +
> +	xhci->main_hcd = hcd;
> +	xhci->shared_hcd = __usb_create_hcd(driver, &pdev->dev, &pdev->dev,
> +					    dev_name(&pdev->dev), hcd);
> +	if (!xhci->shared_hcd) {
> +		ret = -ENOMEM;
> +		goto disable_clk;
> +	}
> +
> +	if (device_property_read_bool(&pdev->dev, "usb3-lpm-capable"))
> +		xhci->quirks |= XHCI_LPM_SUPPORT;
> +
> +	priv = hcd_to_xhci_priv(hcd);
> +	priv->phy = devm_of_phy_get_by_index(&pdev->dev, pdev->dev.of_node, 0);
> +	if (IS_ERR(priv->phy)) {
> +		dev_err(&pdev->dev, "USB Phy not found.\n");
> +		ret = PTR_ERR(priv->phy);
> +		goto put_usb3_hcd;
> +	}
> +	ret = phy_init(priv->phy);
> +	if (ret)
> +		goto put_usb3_hcd;
> +
> +	hcd->skip_phy_initialization = 1;
> +	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
> +	if (ret)
> +		goto disable_usb_phy;
> +
> +	if (HCC_MAX_PSA(xhci->hcc_params) >= 4)
> +		xhci->shared_hcd->can_do_streams = 1;
> +
> +	ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
> +	if (ret)
> +		goto dealloc_usb2_hcd;
> +
> +	device_enable_async_suspend(&pdev->dev);
> +	pm_runtime_put_noidle(&pdev->dev);
> +
> +	/*
> +	 * Prevent runtime pm from being on as default, users should enable
> +	 * runtime pm using power/control in sysfs.
> +	 */
> +	pm_runtime_forbid(&pdev->dev);
> +
> +	return 0;
> +
> +dealloc_usb2_hcd:
> +	usb_remove_hcd(hcd);
> +
> +disable_usb_phy:
> +	phy_exit(priv->phy);
> +
> +put_usb3_hcd:
> +	usb_put_hcd(xhci->shared_hcd);
> +
> +disable_clk:
> +	if (!IS_ERR(xhci->clk))
> +		clk_disable_unprepare(xhci->clk);
> +
> +put_hcd:
> +	usb_put_hcd(hcd);
> +
> +disable_runtime:
> +	pm_runtime_put_noidle(&pdev->dev);
> +	pm_runtime_disable(&pdev->dev);
> +
> +	return ret;
> +}
> +
> +static int xhci_brcm_remove(struct platform_device *dev)
> +{
> +	struct usb_hcd	*hcd = platform_get_drvdata(dev);
> +	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
> +	struct brcm_priv *priv = hcd_to_xhci_priv(hcd);
> +
> +	xhci->xhc_state |= XHCI_STATE_REMOVING;
> +
> +	usb_remove_hcd(xhci->shared_hcd);
> +	usb_remove_hcd(hcd);
> +	usb_put_hcd(xhci->shared_hcd);
> +	phy_exit(priv->phy);
> +	clk_disable_unprepare(xhci->clk);
> +	usb_put_hcd(hcd);
> +
> +	pm_runtime_set_suspended(&dev->dev);
> +	pm_runtime_disable(&dev->dev);
> +
> +	return 0;
> +}
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int xhci_brcm_suspend(struct device *dev)
> +{
> +	int ret;
> +	struct usb_hcd	*hcd = dev_get_drvdata(dev);
> +	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
> +
> +	ret = xhci_suspend(xhci, device_may_wakeup(dev));
> +	clk_disable_unprepare(xhci->clk);
> +	return ret;
> +}
> +
> +static int xhci_brcm_resume(struct device *dev)
> +{
> +	struct usb_hcd	*hcd = dev_get_drvdata(dev);
> +	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
> +	int err;
> +
> +	err = clk_prepare_enable(xhci->clk);
> +	if (err)
> +		return err;
> +	return xhci_resume(xhci, 0);
> +}
> +
> +static int xhci_brcm_runtime_suspend(struct device *dev)
> +{
> +	struct usb_hcd	*hcd = dev_get_drvdata(dev);
> +	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
> +
> +	return xhci_suspend(xhci, true);
> +}
> +
> +static int xhci_brcm_runtime_resume(struct device *dev)
> +{
> +	struct usb_hcd	*hcd = dev_get_drvdata(dev);
> +	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
> +
> +	return xhci_resume(xhci, 0);
> +}
> +
> +#endif /* CONFIG_PM_SLEEP */
> +
> +
> +static const struct dev_pm_ops xhci_brcm_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(xhci_brcm_suspend, xhci_brcm_resume)
> +
> +	SET_RUNTIME_PM_OPS(xhci_brcm_runtime_suspend,
> +			   xhci_brcm_runtime_resume,
> +			   NULL)
> +};
> +
> +#ifdef CONFIG_OF
> +static const struct of_device_id brcm_xhci_of_match[] = {
> +	{ .compatible = "brcm,xhci-brcm-v2" },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, brcm_xhci_of_match);
> +#endif
> +
> +static struct platform_driver xhci_brcm_driver = {
> +	.probe	= xhci_brcm_probe,
> +	.remove	= xhci_brcm_remove,
> +	.driver	= {
> +		.name = BRCM_DRIVER_NAME,
> +		.pm = &xhci_brcm_pm_ops,
> +		.of_match_table = of_match_ptr(brcm_xhci_of_match),
> +	},
> +};
> +
> +static int __init xhci_brcm_init(void)
> +{
> +	pr_info("%s: " BRCM_DRIVER_DESC "\n", BRCM_DRIVER_NAME);
> +	xhci_init_driver(&xhci_brcm_hc_driver, &brcm_overrides);
> +	return platform_driver_register(&xhci_brcm_driver);
> +}
> +module_init(xhci_brcm_init);
> +
> +static void __exit xhci_brcm_exit(void)
> +{
> +	platform_driver_unregister(&xhci_brcm_driver);
> +}
> +module_exit(xhci_brcm_exit);
> +
> +MODULE_ALIAS("platform:xhci-brcm");
> +MODULE_DESCRIPTION(BRCM_DRIVER_DESC);
> +MODULE_AUTHOR("Al Cooper");
> +MODULE_LICENSE("GPL");



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 4/5] usb: host: Add XHCI driver for Broadcom STB SoCs
@ 2018-09-27  5:51     ` Chunfeng Yun
  0 siblings, 0 replies; 29+ messages in thread
From: Chunfeng Yun @ 2018-09-27  5:51 UTC (permalink / raw)
  To: Al Cooper
  Cc: linux-kernel, Greg Kroah-Hartman, Rob Herring, Mark Rutland,
	Alan Stern, Mathias Nyman, Mauro Carvalho Chehab,
	David S. Miller, Andrew Morton, Arnd Bergmann, Dmitry Osipenko,
	Jianguo Sun, James Hogan, Alban Bedel, Lu Baolu, Avi Fishman,
	Alex Elder, Hans de Goede, linux-usb, devicetree, bcm-kerne

Hi,

On Wed, 2018-09-26 at 18:20 -0400, Al Cooper wrote:
> This driver enables USB XHCI on Broadcom ARM STB SoCs.
> The drivers depend on a matching "brcm,brcmstb-usb-phy"
> Broadcom STB USB Phy driver.
> 
> The standard platform driver can't be used because of differences
> in PHY and Clock handling. The standard PHY handling in hcd.c will
> do a phy_exit/phy_init on suspend/resume and this will end up
> shutting down the PHYs to the point that the host controller
> registers are no longer accessible and will cause suspend to crash.
You can avoid hcd.c to do a phy_exit/phy_init on suspend/resume by
device_init_wakeup(dev, true);

> The clocks specified in device tree for these drivers are not
> available in mainline so instead of returning EPROBE_DEFER when
> the specified clock is not found and eventually failing probe,
> the clock pointer is set to NULL which disables all clock handling.
Try to use a fixed-clock as dummy clock if the clock is optional?

> 
> Signed-off-by: Al Cooper <alcooperx@gmail.com>
> ---
>  drivers/usb/host/xhci-brcm.c | 294 +++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 294 insertions(+)
>  create mode 100644 drivers/usb/host/xhci-brcm.c
> 
> diff --git a/drivers/usb/host/xhci-brcm.c b/drivers/usb/host/xhci-brcm.c
> new file mode 100644
> index 000000000000..1a7578b8ef6a
> --- /dev/null
> +++ b/drivers/usb/host/xhci-brcm.c
> @@ -0,0 +1,294 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (c) 2018, Broadcom */
> +
> +#include <linux/platform_device.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/clk.h>
> +#include <linux/phy/phy.h>
> +
> +#include "xhci.h"
> +
> +static struct hc_driver __read_mostly xhci_brcm_hc_driver;
> +
> +#define BRCM_DRIVER_DESC "xHCI Broadcom STB driver"
> +#define BRCM_DRIVER_NAME "xhci-brcm"
> +
> +#define hcd_to_xhci_priv(h) ((struct brcm_priv *)hcd_to_xhci(h)->priv)
> +
> +struct brcm_priv {
> +	struct phy *phy;
> +};
> +
> +static void xhci_brcm_quirks(struct device *dev, struct xhci_hcd *xhci)
> +{
> +	/*
> +	 * As of now platform drivers don't provide MSI support so we ensure
> +	 * here that the generic code does not try to make a pci_dev from our
> +	 * dev struct in order to setup MSI
> +	 */
> +	xhci->quirks |= XHCI_PLAT;
> +
> +	/*
> +	 * The Broadcom XHCI core does not support save/restore state
> +	 * so we need to reset on resume.
> +	 */
> +	xhci->quirks |= XHCI_RESET_ON_RESUME;
> +}
> +
> +/* called during probe() after chip reset completes */
> +static int xhci_brcm_setup(struct usb_hcd *hcd)
> +{
> +	return xhci_gen_setup(hcd, xhci_brcm_quirks);
> +}
> +
> +static const struct xhci_driver_overrides brcm_overrides __initconst = {
> +
> +	.extra_priv_size = sizeof(struct brcm_priv),
> +	.reset = xhci_brcm_setup,
> +};
> +
> +static int xhci_brcm_probe(struct platform_device *pdev)
> +{
> +	const struct hc_driver	*driver;
> +	struct brcm_priv	*priv;
> +	struct xhci_hcd		*xhci;
> +	struct resource         *res;
> +	struct usb_hcd		*hcd;
> +	int			ret;
> +	int			irq;
> +
> +	if (usb_disabled())
> +		return -ENODEV;
> +
> +	driver = &xhci_brcm_hc_driver;
> +
> +	irq = platform_get_irq(pdev, 0);
> +	if (irq < 0)
> +		return -ENODEV;
> +
> +	/* Try to set 64-bit DMA first */
> +	if (WARN_ON(!pdev->dev.dma_mask))
> +		/* Platform did not initialize dma_mask */
> +		ret = dma_coerce_mask_and_coherent(&pdev->dev,
> +						   DMA_BIT_MASK(64));
> +	else
> +		ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
> +
> +	/* If seting 64-bit DMA mask fails, fall back to 32-bit DMA mask */
> +	if (ret) {
> +		ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
> +		if (ret)
> +			return ret;
> +	}
> +
> +	pm_runtime_set_active(&pdev->dev);
> +	pm_runtime_enable(&pdev->dev);
> +	pm_runtime_get_noresume(&pdev->dev);
> +
> +	hcd = __usb_create_hcd(driver, &pdev->dev, &pdev->dev,
> +			       dev_name(&pdev->dev), NULL);
> +	if (!hcd) {
> +		return -ENOMEM;
> +		goto disable_runtime;
> +	}
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	hcd->regs = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(hcd->regs)) {
> +		ret = PTR_ERR(hcd->regs);
> +		goto put_hcd;
> +	}
> +
> +	hcd->rsrc_start = res->start;
> +	hcd->rsrc_len = resource_size(res);
> +
> +	/*
> +	 * Not all platforms have a clk so it is not an error if the
> +	 * clock does not exists.
> +	 */
> +	xhci = hcd_to_xhci(hcd);
> +	xhci->clk = devm_clk_get(&pdev->dev, NULL);
> +	if (IS_ERR(xhci->clk)) {
> +		dev_err(&pdev->dev, "Clock not found in Device Tree\n");
> +		xhci->clk = NULL;
> +	}
> +	device_wakeup_enable(hcd->self.controller);
> +
> +	xhci->main_hcd = hcd;
> +	xhci->shared_hcd = __usb_create_hcd(driver, &pdev->dev, &pdev->dev,
> +					    dev_name(&pdev->dev), hcd);
> +	if (!xhci->shared_hcd) {
> +		ret = -ENOMEM;
> +		goto disable_clk;
> +	}
> +
> +	if (device_property_read_bool(&pdev->dev, "usb3-lpm-capable"))
> +		xhci->quirks |= XHCI_LPM_SUPPORT;
> +
> +	priv = hcd_to_xhci_priv(hcd);
> +	priv->phy = devm_of_phy_get_by_index(&pdev->dev, pdev->dev.of_node, 0);
> +	if (IS_ERR(priv->phy)) {
> +		dev_err(&pdev->dev, "USB Phy not found.\n");
> +		ret = PTR_ERR(priv->phy);
> +		goto put_usb3_hcd;
> +	}
> +	ret = phy_init(priv->phy);
> +	if (ret)
> +		goto put_usb3_hcd;
> +
> +	hcd->skip_phy_initialization = 1;
> +	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
> +	if (ret)
> +		goto disable_usb_phy;
> +
> +	if (HCC_MAX_PSA(xhci->hcc_params) >= 4)
> +		xhci->shared_hcd->can_do_streams = 1;
> +
> +	ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
> +	if (ret)
> +		goto dealloc_usb2_hcd;
> +
> +	device_enable_async_suspend(&pdev->dev);
> +	pm_runtime_put_noidle(&pdev->dev);
> +
> +	/*
> +	 * Prevent runtime pm from being on as default, users should enable
> +	 * runtime pm using power/control in sysfs.
> +	 */
> +	pm_runtime_forbid(&pdev->dev);
> +
> +	return 0;
> +
> +dealloc_usb2_hcd:
> +	usb_remove_hcd(hcd);
> +
> +disable_usb_phy:
> +	phy_exit(priv->phy);
> +
> +put_usb3_hcd:
> +	usb_put_hcd(xhci->shared_hcd);
> +
> +disable_clk:
> +	if (!IS_ERR(xhci->clk))
> +		clk_disable_unprepare(xhci->clk);
> +
> +put_hcd:
> +	usb_put_hcd(hcd);
> +
> +disable_runtime:
> +	pm_runtime_put_noidle(&pdev->dev);
> +	pm_runtime_disable(&pdev->dev);
> +
> +	return ret;
> +}
> +
> +static int xhci_brcm_remove(struct platform_device *dev)
> +{
> +	struct usb_hcd	*hcd = platform_get_drvdata(dev);
> +	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
> +	struct brcm_priv *priv = hcd_to_xhci_priv(hcd);
> +
> +	xhci->xhc_state |= XHCI_STATE_REMOVING;
> +
> +	usb_remove_hcd(xhci->shared_hcd);
> +	usb_remove_hcd(hcd);
> +	usb_put_hcd(xhci->shared_hcd);
> +	phy_exit(priv->phy);
> +	clk_disable_unprepare(xhci->clk);
> +	usb_put_hcd(hcd);
> +
> +	pm_runtime_set_suspended(&dev->dev);
> +	pm_runtime_disable(&dev->dev);
> +
> +	return 0;
> +}
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int xhci_brcm_suspend(struct device *dev)
> +{
> +	int ret;
> +	struct usb_hcd	*hcd = dev_get_drvdata(dev);
> +	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
> +
> +	ret = xhci_suspend(xhci, device_may_wakeup(dev));
> +	clk_disable_unprepare(xhci->clk);
> +	return ret;
> +}
> +
> +static int xhci_brcm_resume(struct device *dev)
> +{
> +	struct usb_hcd	*hcd = dev_get_drvdata(dev);
> +	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
> +	int err;
> +
> +	err = clk_prepare_enable(xhci->clk);
> +	if (err)
> +		return err;
> +	return xhci_resume(xhci, 0);
> +}
> +
> +static int xhci_brcm_runtime_suspend(struct device *dev)
> +{
> +	struct usb_hcd	*hcd = dev_get_drvdata(dev);
> +	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
> +
> +	return xhci_suspend(xhci, true);
> +}
> +
> +static int xhci_brcm_runtime_resume(struct device *dev)
> +{
> +	struct usb_hcd	*hcd = dev_get_drvdata(dev);
> +	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
> +
> +	return xhci_resume(xhci, 0);
> +}
> +
> +#endif /* CONFIG_PM_SLEEP */
> +
> +
> +static const struct dev_pm_ops xhci_brcm_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(xhci_brcm_suspend, xhci_brcm_resume)
> +
> +	SET_RUNTIME_PM_OPS(xhci_brcm_runtime_suspend,
> +			   xhci_brcm_runtime_resume,
> +			   NULL)
> +};
> +
> +#ifdef CONFIG_OF
> +static const struct of_device_id brcm_xhci_of_match[] = {
> +	{ .compatible = "brcm,xhci-brcm-v2" },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, brcm_xhci_of_match);
> +#endif
> +
> +static struct platform_driver xhci_brcm_driver = {
> +	.probe	= xhci_brcm_probe,
> +	.remove	= xhci_brcm_remove,
> +	.driver	= {
> +		.name = BRCM_DRIVER_NAME,
> +		.pm = &xhci_brcm_pm_ops,
> +		.of_match_table = of_match_ptr(brcm_xhci_of_match),
> +	},
> +};
> +
> +static int __init xhci_brcm_init(void)
> +{
> +	pr_info("%s: " BRCM_DRIVER_DESC "\n", BRCM_DRIVER_NAME);
> +	xhci_init_driver(&xhci_brcm_hc_driver, &brcm_overrides);
> +	return platform_driver_register(&xhci_brcm_driver);
> +}
> +module_init(xhci_brcm_init);
> +
> +static void __exit xhci_brcm_exit(void)
> +{
> +	platform_driver_unregister(&xhci_brcm_driver);
> +}
> +module_exit(xhci_brcm_exit);
> +
> +MODULE_ALIAS("platform:xhci-brcm");
> +MODULE_DESCRIPTION(BRCM_DRIVER_DESC);
> +MODULE_AUTHOR("Al Cooper");
> +MODULE_LICENSE("GPL");

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [4/5] usb: host: Add XHCI driver for Broadcom STB SoCs
@ 2018-09-27  5:51     ` Chunfeng Yun
  0 siblings, 0 replies; 29+ messages in thread
From: Chunfeng Yun @ 2018-09-27  5:51 UTC (permalink / raw)
  To: Al Cooper
  Cc: linux-kernel, Greg Kroah-Hartman, Rob Herring, Mark Rutland,
	Alan Stern, Mathias Nyman, Mauro Carvalho Chehab,
	David S. Miller, Andrew Morton, Arnd Bergmann, Dmitry Osipenko,
	Jianguo Sun, James Hogan, Alban Bedel, Lu Baolu, Avi Fishman,
	Alex Elder, Hans de Goede, linux-usb, devicetree,
	bcm-kernel-feedback-list

Hi,

On Wed, 2018-09-26 at 18:20 -0400, Al Cooper wrote:
> This driver enables USB XHCI on Broadcom ARM STB SoCs.
> The drivers depend on a matching "brcm,brcmstb-usb-phy"
> Broadcom STB USB Phy driver.
> 
> The standard platform driver can't be used because of differences
> in PHY and Clock handling. The standard PHY handling in hcd.c will
> do a phy_exit/phy_init on suspend/resume and this will end up
> shutting down the PHYs to the point that the host controller
> registers are no longer accessible and will cause suspend to crash.
You can avoid hcd.c to do a phy_exit/phy_init on suspend/resume by
device_init_wakeup(dev, true);

> The clocks specified in device tree for these drivers are not
> available in mainline so instead of returning EPROBE_DEFER when
> the specified clock is not found and eventually failing probe,
> the clock pointer is set to NULL which disables all clock handling.
Try to use a fixed-clock as dummy clock if the clock is optional?

> 
> Signed-off-by: Al Cooper <alcooperx@gmail.com>
> ---
>  drivers/usb/host/xhci-brcm.c | 294 +++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 294 insertions(+)
>  create mode 100644 drivers/usb/host/xhci-brcm.c
> 
> diff --git a/drivers/usb/host/xhci-brcm.c b/drivers/usb/host/xhci-brcm.c
> new file mode 100644
> index 000000000000..1a7578b8ef6a
> --- /dev/null
> +++ b/drivers/usb/host/xhci-brcm.c
> @@ -0,0 +1,294 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (c) 2018, Broadcom */
> +
> +#include <linux/platform_device.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/clk.h>
> +#include <linux/phy/phy.h>
> +
> +#include "xhci.h"
> +
> +static struct hc_driver __read_mostly xhci_brcm_hc_driver;
> +
> +#define BRCM_DRIVER_DESC "xHCI Broadcom STB driver"
> +#define BRCM_DRIVER_NAME "xhci-brcm"
> +
> +#define hcd_to_xhci_priv(h) ((struct brcm_priv *)hcd_to_xhci(h)->priv)
> +
> +struct brcm_priv {
> +	struct phy *phy;
> +};
> +
> +static void xhci_brcm_quirks(struct device *dev, struct xhci_hcd *xhci)
> +{
> +	/*
> +	 * As of now platform drivers don't provide MSI support so we ensure
> +	 * here that the generic code does not try to make a pci_dev from our
> +	 * dev struct in order to setup MSI
> +	 */
> +	xhci->quirks |= XHCI_PLAT;
> +
> +	/*
> +	 * The Broadcom XHCI core does not support save/restore state
> +	 * so we need to reset on resume.
> +	 */
> +	xhci->quirks |= XHCI_RESET_ON_RESUME;
> +}
> +
> +/* called during probe() after chip reset completes */
> +static int xhci_brcm_setup(struct usb_hcd *hcd)
> +{
> +	return xhci_gen_setup(hcd, xhci_brcm_quirks);
> +}
> +
> +static const struct xhci_driver_overrides brcm_overrides __initconst = {
> +
> +	.extra_priv_size = sizeof(struct brcm_priv),
> +	.reset = xhci_brcm_setup,
> +};
> +
> +static int xhci_brcm_probe(struct platform_device *pdev)
> +{
> +	const struct hc_driver	*driver;
> +	struct brcm_priv	*priv;
> +	struct xhci_hcd		*xhci;
> +	struct resource         *res;
> +	struct usb_hcd		*hcd;
> +	int			ret;
> +	int			irq;
> +
> +	if (usb_disabled())
> +		return -ENODEV;
> +
> +	driver = &xhci_brcm_hc_driver;
> +
> +	irq = platform_get_irq(pdev, 0);
> +	if (irq < 0)
> +		return -ENODEV;
> +
> +	/* Try to set 64-bit DMA first */
> +	if (WARN_ON(!pdev->dev.dma_mask))
> +		/* Platform did not initialize dma_mask */
> +		ret = dma_coerce_mask_and_coherent(&pdev->dev,
> +						   DMA_BIT_MASK(64));
> +	else
> +		ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
> +
> +	/* If seting 64-bit DMA mask fails, fall back to 32-bit DMA mask */
> +	if (ret) {
> +		ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
> +		if (ret)
> +			return ret;
> +	}
> +
> +	pm_runtime_set_active(&pdev->dev);
> +	pm_runtime_enable(&pdev->dev);
> +	pm_runtime_get_noresume(&pdev->dev);
> +
> +	hcd = __usb_create_hcd(driver, &pdev->dev, &pdev->dev,
> +			       dev_name(&pdev->dev), NULL);
> +	if (!hcd) {
> +		return -ENOMEM;
> +		goto disable_runtime;
> +	}
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	hcd->regs = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(hcd->regs)) {
> +		ret = PTR_ERR(hcd->regs);
> +		goto put_hcd;
> +	}
> +
> +	hcd->rsrc_start = res->start;
> +	hcd->rsrc_len = resource_size(res);
> +
> +	/*
> +	 * Not all platforms have a clk so it is not an error if the
> +	 * clock does not exists.
> +	 */
> +	xhci = hcd_to_xhci(hcd);
> +	xhci->clk = devm_clk_get(&pdev->dev, NULL);
> +	if (IS_ERR(xhci->clk)) {
> +		dev_err(&pdev->dev, "Clock not found in Device Tree\n");
> +		xhci->clk = NULL;
> +	}
> +	device_wakeup_enable(hcd->self.controller);
> +
> +	xhci->main_hcd = hcd;
> +	xhci->shared_hcd = __usb_create_hcd(driver, &pdev->dev, &pdev->dev,
> +					    dev_name(&pdev->dev), hcd);
> +	if (!xhci->shared_hcd) {
> +		ret = -ENOMEM;
> +		goto disable_clk;
> +	}
> +
> +	if (device_property_read_bool(&pdev->dev, "usb3-lpm-capable"))
> +		xhci->quirks |= XHCI_LPM_SUPPORT;
> +
> +	priv = hcd_to_xhci_priv(hcd);
> +	priv->phy = devm_of_phy_get_by_index(&pdev->dev, pdev->dev.of_node, 0);
> +	if (IS_ERR(priv->phy)) {
> +		dev_err(&pdev->dev, "USB Phy not found.\n");
> +		ret = PTR_ERR(priv->phy);
> +		goto put_usb3_hcd;
> +	}
> +	ret = phy_init(priv->phy);
> +	if (ret)
> +		goto put_usb3_hcd;
> +
> +	hcd->skip_phy_initialization = 1;
> +	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
> +	if (ret)
> +		goto disable_usb_phy;
> +
> +	if (HCC_MAX_PSA(xhci->hcc_params) >= 4)
> +		xhci->shared_hcd->can_do_streams = 1;
> +
> +	ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
> +	if (ret)
> +		goto dealloc_usb2_hcd;
> +
> +	device_enable_async_suspend(&pdev->dev);
> +	pm_runtime_put_noidle(&pdev->dev);
> +
> +	/*
> +	 * Prevent runtime pm from being on as default, users should enable
> +	 * runtime pm using power/control in sysfs.
> +	 */
> +	pm_runtime_forbid(&pdev->dev);
> +
> +	return 0;
> +
> +dealloc_usb2_hcd:
> +	usb_remove_hcd(hcd);
> +
> +disable_usb_phy:
> +	phy_exit(priv->phy);
> +
> +put_usb3_hcd:
> +	usb_put_hcd(xhci->shared_hcd);
> +
> +disable_clk:
> +	if (!IS_ERR(xhci->clk))
> +		clk_disable_unprepare(xhci->clk);
> +
> +put_hcd:
> +	usb_put_hcd(hcd);
> +
> +disable_runtime:
> +	pm_runtime_put_noidle(&pdev->dev);
> +	pm_runtime_disable(&pdev->dev);
> +
> +	return ret;
> +}
> +
> +static int xhci_brcm_remove(struct platform_device *dev)
> +{
> +	struct usb_hcd	*hcd = platform_get_drvdata(dev);
> +	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
> +	struct brcm_priv *priv = hcd_to_xhci_priv(hcd);
> +
> +	xhci->xhc_state |= XHCI_STATE_REMOVING;
> +
> +	usb_remove_hcd(xhci->shared_hcd);
> +	usb_remove_hcd(hcd);
> +	usb_put_hcd(xhci->shared_hcd);
> +	phy_exit(priv->phy);
> +	clk_disable_unprepare(xhci->clk);
> +	usb_put_hcd(hcd);
> +
> +	pm_runtime_set_suspended(&dev->dev);
> +	pm_runtime_disable(&dev->dev);
> +
> +	return 0;
> +}
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int xhci_brcm_suspend(struct device *dev)
> +{
> +	int ret;
> +	struct usb_hcd	*hcd = dev_get_drvdata(dev);
> +	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
> +
> +	ret = xhci_suspend(xhci, device_may_wakeup(dev));
> +	clk_disable_unprepare(xhci->clk);
> +	return ret;
> +}
> +
> +static int xhci_brcm_resume(struct device *dev)
> +{
> +	struct usb_hcd	*hcd = dev_get_drvdata(dev);
> +	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
> +	int err;
> +
> +	err = clk_prepare_enable(xhci->clk);
> +	if (err)
> +		return err;
> +	return xhci_resume(xhci, 0);
> +}
> +
> +static int xhci_brcm_runtime_suspend(struct device *dev)
> +{
> +	struct usb_hcd	*hcd = dev_get_drvdata(dev);
> +	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
> +
> +	return xhci_suspend(xhci, true);
> +}
> +
> +static int xhci_brcm_runtime_resume(struct device *dev)
> +{
> +	struct usb_hcd	*hcd = dev_get_drvdata(dev);
> +	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
> +
> +	return xhci_resume(xhci, 0);
> +}
> +
> +#endif /* CONFIG_PM_SLEEP */
> +
> +
> +static const struct dev_pm_ops xhci_brcm_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(xhci_brcm_suspend, xhci_brcm_resume)
> +
> +	SET_RUNTIME_PM_OPS(xhci_brcm_runtime_suspend,
> +			   xhci_brcm_runtime_resume,
> +			   NULL)
> +};
> +
> +#ifdef CONFIG_OF
> +static const struct of_device_id brcm_xhci_of_match[] = {
> +	{ .compatible = "brcm,xhci-brcm-v2" },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, brcm_xhci_of_match);
> +#endif
> +
> +static struct platform_driver xhci_brcm_driver = {
> +	.probe	= xhci_brcm_probe,
> +	.remove	= xhci_brcm_remove,
> +	.driver	= {
> +		.name = BRCM_DRIVER_NAME,
> +		.pm = &xhci_brcm_pm_ops,
> +		.of_match_table = of_match_ptr(brcm_xhci_of_match),
> +	},
> +};
> +
> +static int __init xhci_brcm_init(void)
> +{
> +	pr_info("%s: " BRCM_DRIVER_DESC "\n", BRCM_DRIVER_NAME);
> +	xhci_init_driver(&xhci_brcm_hc_driver, &brcm_overrides);
> +	return platform_driver_register(&xhci_brcm_driver);
> +}
> +module_init(xhci_brcm_init);
> +
> +static void __exit xhci_brcm_exit(void)
> +{
> +	platform_driver_unregister(&xhci_brcm_driver);
> +}
> +module_exit(xhci_brcm_exit);
> +
> +MODULE_ALIAS("platform:xhci-brcm");
> +MODULE_DESCRIPTION(BRCM_DRIVER_DESC);
> +MODULE_AUTHOR("Al Cooper");
> +MODULE_LICENSE("GPL");

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 4/5] usb: host: Add XHCI driver for Broadcom STB SoCs
  2018-09-26 22:20   ` [PATCH 4/5] " Al Cooper
  (?)
@ 2018-09-27  5:57     ` Felipe Balbi
  -1 siblings, 0 replies; 29+ messages in thread
From: Felipe Balbi @ 2018-09-27  5:57 UTC (permalink / raw)
  To: Al Cooper, linux-kernel
  Cc: Al Cooper, Greg Kroah-Hartman, Rob Herring, Mark Rutland,
	Alan Stern, Mathias Nyman, Mauro Carvalho Chehab,
	David S. Miller, Andrew Morton, Arnd Bergmann, Dmitry Osipenko,
	Chunfeng Yun, Jianguo Sun, James Hogan, Alban Bedel, Lu Baolu,
	Avi Fishman, Alex Elder, Hans de Goede, linux-usb, devicetree,
	bcm-kernel-feedback-list


Hi,

Al Cooper <alcooperx@gmail.com> writes:

> This driver enables USB XHCI on Broadcom ARM STB SoCs.
> The drivers depend on a matching "brcm,brcmstb-usb-phy"
> Broadcom STB USB Phy driver.
>
> The standard platform driver can't be used because of differences
> in PHY and Clock handling. The standard PHY handling in hcd.c will
> do a phy_exit/phy_init on suspend/resume and this will end up
> shutting down the PHYs to the point that the host controller
> registers are no longer accessible and will cause suspend to crash.
> The clocks specified in device tree for these drivers are not
> available in mainline so instead of returning EPROBE_DEFER when
> the specified clock is not found and eventually failing probe,
> the clock pointer is set to NULL which disables all clock handling.
>
> Signed-off-by: Al Cooper <alcooperx@gmail.com>
> ---
>  drivers/usb/host/xhci-brcm.c | 294 +++++++++++++++++++++++++++++++++++++++++++

this looks a lot like xhci-plat.c, why don't you use that instead?

- 
balbi

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 4/5] usb: host: Add XHCI driver for Broadcom STB SoCs
@ 2018-09-27  5:57     ` Felipe Balbi
  0 siblings, 0 replies; 29+ messages in thread
From: Felipe Balbi @ 2018-09-27  5:57 UTC (permalink / raw)
  To: linux-kernel
  Cc: Al Cooper, Greg Kroah-Hartman, Rob Herring, Mark Rutland,
	Alan Stern, Mathias Nyman, Mauro Carvalho Chehab,
	David S. Miller, Andrew Morton, Arnd Bergmann, Dmitry Osipenko,
	Chunfeng Yun, Jianguo Sun, James Hogan, Alban Bedel, Lu Baolu,
	Avi Fishman, Alex Elder, Hans de Goede, linux-usb, dev


Hi,

Al Cooper <alcooperx@gmail.com> writes:

> This driver enables USB XHCI on Broadcom ARM STB SoCs.
> The drivers depend on a matching "brcm,brcmstb-usb-phy"
> Broadcom STB USB Phy driver.
>
> The standard platform driver can't be used because of differences
> in PHY and Clock handling. The standard PHY handling in hcd.c will
> do a phy_exit/phy_init on suspend/resume and this will end up
> shutting down the PHYs to the point that the host controller
> registers are no longer accessible and will cause suspend to crash.
> The clocks specified in device tree for these drivers are not
> available in mainline so instead of returning EPROBE_DEFER when
> the specified clock is not found and eventually failing probe,
> the clock pointer is set to NULL which disables all clock handling.
>
> Signed-off-by: Al Cooper <alcooperx@gmail.com>
> ---
>  drivers/usb/host/xhci-brcm.c | 294 +++++++++++++++++++++++++++++++++++++++++++

this looks a lot like xhci-plat.c, why don't you use that instead?

- 
balbi

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [4/5] usb: host: Add XHCI driver for Broadcom STB SoCs
@ 2018-09-27  5:57     ` Felipe Balbi
  0 siblings, 0 replies; 29+ messages in thread
From: Felipe Balbi @ 2018-09-27  5:57 UTC (permalink / raw)
  To: Al Cooper, linux-kernel
  Cc: Greg Kroah-Hartman, Rob Herring, Mark Rutland, Alan Stern,
	Mathias Nyman, Mauro Carvalho Chehab, David S. Miller,
	Andrew Morton, Arnd Bergmann, Dmitry Osipenko, Chunfeng Yun,
	Jianguo Sun, James Hogan, Alban Bedel, Lu Baolu, Avi Fishman,
	Alex Elder, Hans de Goede, linux-usb, devicetree,
	bcm-kernel-feedback-list

Hi,

Al Cooper <alcooperx@gmail.com> writes:

> This driver enables USB XHCI on Broadcom ARM STB SoCs.
> The drivers depend on a matching "brcm,brcmstb-usb-phy"
> Broadcom STB USB Phy driver.
>
> The standard platform driver can't be used because of differences
> in PHY and Clock handling. The standard PHY handling in hcd.c will
> do a phy_exit/phy_init on suspend/resume and this will end up
> shutting down the PHYs to the point that the host controller
> registers are no longer accessible and will cause suspend to crash.
> The clocks specified in device tree for these drivers are not
> available in mainline so instead of returning EPROBE_DEFER when
> the specified clock is not found and eventually failing probe,
> the clock pointer is set to NULL which disables all clock handling.
>
> Signed-off-by: Al Cooper <alcooperx@gmail.com>
> ---
>  drivers/usb/host/xhci-brcm.c | 294 +++++++++++++++++++++++++++++++++++++++++++

this looks a lot like xhci-plat.c, why don't you use that instead?

- 
balbi

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 2/5] usb: host: Add OHCI driver for Broadcom STB SoCs
  2018-09-26 22:20   ` [PATCH 2/5] " Al Cooper
  (?)
@ 2018-09-27  9:08     ` Arnd Bergmann
  -1 siblings, 0 replies; 29+ messages in thread
From: Arnd Bergmann @ 2018-09-27  9:08 UTC (permalink / raw)
  To: Al Cooper
  Cc: Linux Kernel Mailing List, gregkh, Rob Herring, Mark Rutland,
	Alan Stern, Mathias Nyman, Mauro Carvalho Chehab, David Miller,
	Andrew Morton, Dmitry Osipenko, Chunfeng Yun, sunjianguo1,
	James Hogan, Alban Bedel, Lu Baolu, Avi Fishman, Alex Elder,
	Hans de Goede, USB list, DTML, bcm-kernel-feedback-list

On Thu, Sep 27, 2018 at 12:20 AM Al Cooper <alcooperx@gmail.com> wrote:
>
> This driver enables USB OHCI on Broadcom ARM and MIPS STB SoCs.
> The drivers depend on a matching "brcm,brcmstb-usb-phy"
> Broadcom STB USB Phy driver.
>
> The standard platform driver can't be used because of differences
> in PHY and Clock handling. The standard PHY handling in hcd.c will
> do a phy_exit/phy_init on suspend/resume and this will end up
> shutting down the PHYs to the point that the host controller
> registers are no longer accessible and will cause suspend to crash.
> The clocks specified in device tree for these drivers are not
> available in mainline so instead of returning EPROBE_DEFER when
> the specified clock is not found and eventually failing probe,
> the clock pointer is set to NULL which disables all clock handling.

Both of these sound like fairly minor differences, I wonder if the
generic code could be adapted to have a special case for these
rather than duplicating it.

        Arnd

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 2/5] usb: host: Add OHCI driver for Broadcom STB SoCs
@ 2018-09-27  9:08     ` Arnd Bergmann
  0 siblings, 0 replies; 29+ messages in thread
From: Arnd Bergmann @ 2018-09-27  9:08 UTC (permalink / raw)
  To: Al Cooper
  Cc: Linux Kernel Mailing List, gregkh, Rob Herring, Mark Rutland,
	Alan Stern, Mathias Nyman, Mauro Carvalho Chehab, David Miller,
	Andrew Morton, Dmitry Osipenko, Chunfeng Yun, sunjianguo1,
	James Hogan, Alban Bedel, Lu Baolu, Avi Fishman, Alex Elder,
	Hans de Goede, USB list, DTML

On Thu, Sep 27, 2018 at 12:20 AM Al Cooper <alcooperx@gmail.com> wrote:
>
> This driver enables USB OHCI on Broadcom ARM and MIPS STB SoCs.
> The drivers depend on a matching "brcm,brcmstb-usb-phy"
> Broadcom STB USB Phy driver.
>
> The standard platform driver can't be used because of differences
> in PHY and Clock handling. The standard PHY handling in hcd.c will
> do a phy_exit/phy_init on suspend/resume and this will end up
> shutting down the PHYs to the point that the host controller
> registers are no longer accessible and will cause suspend to crash.
> The clocks specified in device tree for these drivers are not
> available in mainline so instead of returning EPROBE_DEFER when
> the specified clock is not found and eventually failing probe,
> the clock pointer is set to NULL which disables all clock handling.

Both of these sound like fairly minor differences, I wonder if the
generic code could be adapted to have a special case for these
rather than duplicating it.

        Arnd

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [2/5] usb: host: Add OHCI driver for Broadcom STB SoCs
@ 2018-09-27  9:08     ` Arnd Bergmann
  0 siblings, 0 replies; 29+ messages in thread
From: Arnd Bergmann @ 2018-09-27  9:08 UTC (permalink / raw)
  To: Al Cooper
  Cc: Linux Kernel Mailing List, gregkh, Rob Herring, Mark Rutland,
	Alan Stern, Mathias Nyman, Mauro Carvalho Chehab, David Miller,
	Andrew Morton, Dmitry Osipenko, Chunfeng Yun, sunjianguo1,
	James Hogan, Alban Bedel, Lu Baolu, Avi Fishman, Alex Elder,
	Hans de Goede, USB list, DTML, bcm-kernel-feedback-list

On Thu, Sep 27, 2018 at 12:20 AM Al Cooper <alcooperx@gmail.com> wrote:
>
> This driver enables USB OHCI on Broadcom ARM and MIPS STB SoCs.
> The drivers depend on a matching "brcm,brcmstb-usb-phy"
> Broadcom STB USB Phy driver.
>
> The standard platform driver can't be used because of differences
> in PHY and Clock handling. The standard PHY handling in hcd.c will
> do a phy_exit/phy_init on suspend/resume and this will end up
> shutting down the PHYs to the point that the host controller
> registers are no longer accessible and will cause suspend to crash.
> The clocks specified in device tree for these drivers are not
> available in mainline so instead of returning EPROBE_DEFER when
> the specified clock is not found and eventually failing probe,
> the clock pointer is set to NULL which disables all clock handling.

Both of these sound like fairly minor differences, I wonder if the
generic code could be adapted to have a special case for these
rather than duplicating it.

        Arnd

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 1/5] dt-bindings: Add Broadcom STB OHCI, EHCI and XHCI binding document
  2018-09-26 22:20   ` [PATCH 1/5] " Al Cooper
  (?)
@ 2018-10-15 18:22     ` Rob Herring
  -1 siblings, 0 replies; 29+ messages in thread
From: Rob Herring @ 2018-10-15 18:22 UTC (permalink / raw)
  To: Al Cooper
  Cc: linux-kernel, Greg Kroah-Hartman, Mark Rutland, Alan Stern,
	Mathias Nyman, Mauro Carvalho Chehab, David S. Miller,
	Andrew Morton, Arnd Bergmann, Dmitry Osipenko, Chunfeng Yun,
	Jianguo Sun, James Hogan, Alban Bedel, Lu Baolu, Avi Fishman,
	Alex Elder, Hans de Goede, linux-usb, devicetree,
	bcm-kernel-feedback-list

On Wed, Sep 26, 2018 at 06:20:10PM -0400, Al Cooper wrote:
> Add DT bindings document for Broadcom STB USB OHCI, EHCI and
> XHCI drivers.
> 
> Signed-off-by: Al Cooper <alcooperx@gmail.com>
> ---
>  .../devicetree/bindings/usb/brcm,ehci-brcm.txt     | 22 +++++++++++++++++++++
>  .../devicetree/bindings/usb/brcm,ohci-brcm.txt     | 22 +++++++++++++++++++++
>  .../devicetree/bindings/usb/brcm,xhci-brcm.txt     | 23 ++++++++++++++++++++++
>  3 files changed, 67 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/usb/brcm,ehci-brcm.txt
>  create mode 100644 Documentation/devicetree/bindings/usb/brcm,ohci-brcm.txt
>  create mode 100644 Documentation/devicetree/bindings/usb/brcm,xhci-brcm.txt
> 
> diff --git a/Documentation/devicetree/bindings/usb/brcm,ehci-brcm.txt b/Documentation/devicetree/bindings/usb/brcm,ehci-brcm.txt
> new file mode 100644
> index 000000000000..020b5ec40f5b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/usb/brcm,ehci-brcm.txt
> @@ -0,0 +1,22 @@
> +Broadcom STB USB EHCI controller
> +
> +Required properties:
> +- compatible: should be "brcm,ehci-brcm-v2"

Needs an SoC specific compatible string.

> +- reg: should contain one register range i.e. start and length
> +- interrupts: description of the interrupt line
> +- phys: phandle + phy specifier pair
> +  The specifier should be 0 for the OHCI/EHCI PHY and 1 for the XHCI PHY

0 or 1 depends on the phy binding. This binding just needs to say how 
many phy specifiers there are.

> +
> +Optional properties:
> +- clocks: A list of phandles for the clocks

Need to say how many and the order.

> +
> +Example:
> +
> +ehci@f0b00300 {
> +	compatible = "brcm,ehci-brcm-v2";
> +	reg = <0xf0b00300 0xa8>;
> +	interrupts = <0x0 0x5a 0x0>;
> +	interrupt-names = "usb0_ehci_0";
> +	phys = <&usbphy_0 0x0>;
> +	clocks = <&usb20>
> +};

Similar comments in the other 2 files.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH 1/5] dt-bindings: Add Broadcom STB OHCI, EHCI and XHCI binding document
@ 2018-10-15 18:22     ` Rob Herring
  0 siblings, 0 replies; 29+ messages in thread
From: Rob Herring @ 2018-10-15 18:22 UTC (permalink / raw)
  To: Al Cooper
  Cc: linux-kernel, Greg Kroah-Hartman, Mark Rutland, Alan Stern,
	Mathias Nyman, Mauro Carvalho Chehab, David S. Miller,
	Andrew Morton, Arnd Bergmann, Dmitry Osipenko, Chunfeng Yun,
	Jianguo Sun, James Hogan, Alban Bedel, Lu Baolu, Avi Fishman,
	Alex Elder, Hans de Goede, linux-usb, devicetree, bcm-kernel-f

On Wed, Sep 26, 2018 at 06:20:10PM -0400, Al Cooper wrote:
> Add DT bindings document for Broadcom STB USB OHCI, EHCI and
> XHCI drivers.
> 
> Signed-off-by: Al Cooper <alcooperx@gmail.com>
> ---
>  .../devicetree/bindings/usb/brcm,ehci-brcm.txt     | 22 +++++++++++++++++++++
>  .../devicetree/bindings/usb/brcm,ohci-brcm.txt     | 22 +++++++++++++++++++++
>  .../devicetree/bindings/usb/brcm,xhci-brcm.txt     | 23 ++++++++++++++++++++++
>  3 files changed, 67 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/usb/brcm,ehci-brcm.txt
>  create mode 100644 Documentation/devicetree/bindings/usb/brcm,ohci-brcm.txt
>  create mode 100644 Documentation/devicetree/bindings/usb/brcm,xhci-brcm.txt
> 
> diff --git a/Documentation/devicetree/bindings/usb/brcm,ehci-brcm.txt b/Documentation/devicetree/bindings/usb/brcm,ehci-brcm.txt
> new file mode 100644
> index 000000000000..020b5ec40f5b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/usb/brcm,ehci-brcm.txt
> @@ -0,0 +1,22 @@
> +Broadcom STB USB EHCI controller
> +
> +Required properties:
> +- compatible: should be "brcm,ehci-brcm-v2"

Needs an SoC specific compatible string.

> +- reg: should contain one register range i.e. start and length
> +- interrupts: description of the interrupt line
> +- phys: phandle + phy specifier pair
> +  The specifier should be 0 for the OHCI/EHCI PHY and 1 for the XHCI PHY

0 or 1 depends on the phy binding. This binding just needs to say how 
many phy specifiers there are.

> +
> +Optional properties:
> +- clocks: A list of phandles for the clocks

Need to say how many and the order.

> +
> +Example:
> +
> +ehci@f0b00300 {
> +	compatible = "brcm,ehci-brcm-v2";
> +	reg = <0xf0b00300 0xa8>;
> +	interrupts = <0x0 0x5a 0x0>;
> +	interrupt-names = "usb0_ehci_0";
> +	phys = <&usbphy_0 0x0>;
> +	clocks = <&usb20>
> +};

Similar comments in the other 2 files.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [1/5] dt-bindings: Add Broadcom STB OHCI, EHCI and XHCI binding document
@ 2018-10-15 18:22     ` Rob Herring
  0 siblings, 0 replies; 29+ messages in thread
From: Rob Herring @ 2018-10-15 18:22 UTC (permalink / raw)
  To: Al Cooper
  Cc: linux-kernel, Greg Kroah-Hartman, Mark Rutland, Alan Stern,
	Mathias Nyman, Mauro Carvalho Chehab, David S. Miller,
	Andrew Morton, Arnd Bergmann, Dmitry Osipenko, Chunfeng Yun,
	Jianguo Sun, James Hogan, Alban Bedel, Lu Baolu, Avi Fishman,
	Alex Elder, Hans de Goede, linux-usb, devicetree,
	bcm-kernel-feedback-list

On Wed, Sep 26, 2018 at 06:20:10PM -0400, Al Cooper wrote:
> Add DT bindings document for Broadcom STB USB OHCI, EHCI and
> XHCI drivers.
> 
> Signed-off-by: Al Cooper <alcooperx@gmail.com>
> ---
>  .../devicetree/bindings/usb/brcm,ehci-brcm.txt     | 22 +++++++++++++++++++++
>  .../devicetree/bindings/usb/brcm,ohci-brcm.txt     | 22 +++++++++++++++++++++
>  .../devicetree/bindings/usb/brcm,xhci-brcm.txt     | 23 ++++++++++++++++++++++
>  3 files changed, 67 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/usb/brcm,ehci-brcm.txt
>  create mode 100644 Documentation/devicetree/bindings/usb/brcm,ohci-brcm.txt
>  create mode 100644 Documentation/devicetree/bindings/usb/brcm,xhci-brcm.txt
> 
> diff --git a/Documentation/devicetree/bindings/usb/brcm,ehci-brcm.txt b/Documentation/devicetree/bindings/usb/brcm,ehci-brcm.txt
> new file mode 100644
> index 000000000000..020b5ec40f5b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/usb/brcm,ehci-brcm.txt
> @@ -0,0 +1,22 @@
> +Broadcom STB USB EHCI controller
> +
> +Required properties:
> +- compatible: should be "brcm,ehci-brcm-v2"

Needs an SoC specific compatible string.

> +- reg: should contain one register range i.e. start and length
> +- interrupts: description of the interrupt line
> +- phys: phandle + phy specifier pair
> +  The specifier should be 0 for the OHCI/EHCI PHY and 1 for the XHCI PHY

0 or 1 depends on the phy binding. This binding just needs to say how 
many phy specifiers there are.

> +
> +Optional properties:
> +- clocks: A list of phandles for the clocks

Need to say how many and the order.

> +
> +Example:
> +
> +ehci@f0b00300 {
> +	compatible = "brcm,ehci-brcm-v2";
> +	reg = <0xf0b00300 0xa8>;
> +	interrupts = <0x0 0x5a 0x0>;
> +	interrupt-names = "usb0_ehci_0";
> +	phys = <&usbphy_0 0x0>;
> +	clocks = <&usb20>
> +};

Similar comments in the other 2 files.

^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2018-10-15 18:22 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-09-26 22:20 [PATCH 0/5] Add XHCI, EHCI and OHCI drivers for Broadcom STB SoCs Al Cooper
2018-09-26 22:20 ` Al Cooper
2018-09-26 22:20 ` [PATCH 1/5] dt-bindings: Add Broadcom STB OHCI, EHCI and XHCI binding document Al Cooper
2018-09-26 22:20   ` [1/5] " Alan Cooper
2018-09-26 22:20   ` [PATCH 1/5] " Al Cooper
2018-10-15 18:22   ` Rob Herring
2018-10-15 18:22     ` [1/5] " Rob Herring
2018-10-15 18:22     ` [PATCH 1/5] " Rob Herring
2018-09-26 22:20 ` [PATCH 2/5] usb: host: Add OHCI driver for Broadcom STB SoCs Al Cooper
2018-09-26 22:20   ` [2/5] " Alan Cooper
2018-09-26 22:20   ` [PATCH 2/5] " Al Cooper
2018-09-27  9:08   ` Arnd Bergmann
2018-09-27  9:08     ` [2/5] " Arnd Bergmann
2018-09-27  9:08     ` [PATCH 2/5] " Arnd Bergmann
2018-09-26 22:20 ` [PATCH 3/5] usb: host: Add EHCI " Al Cooper
2018-09-26 22:20   ` [3/5] " Alan Cooper
2018-09-26 22:20   ` [PATCH 3/5] " Al Cooper
2018-09-26 22:20 ` [PATCH 4/5] usb: host: Add XHCI " Al Cooper
2018-09-26 22:20   ` [4/5] " Alan Cooper
2018-09-26 22:20   ` [PATCH 4/5] " Al Cooper
2018-09-27  5:51   ` Chunfeng Yun
2018-09-27  5:51     ` [4/5] " Chunfeng Yun
2018-09-27  5:51     ` [PATCH 4/5] " Chunfeng Yun
2018-09-27  5:57   ` Felipe Balbi
2018-09-27  5:57     ` [4/5] " Felipe Balbi
2018-09-27  5:57     ` [PATCH 4/5] " Felipe Balbi
2018-09-26 22:20 ` [PATCH 5/5] usb: host: Enable building of new Broadcom STB USB drivers Al Cooper
2018-09-26 22:20   ` [5/5] " Alan Cooper
2018-09-26 22:20   ` [PATCH 5/5] " Al Cooper

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.