All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/9] Tegra xHCI support
@ 2014-08-18 17:08 ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-18 17:08 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, linux-tegra
  Cc: Mark Rutland, devicetree, linux-usb, Russell King, Mathias Nyman,
	Pawel Moll, Ian Campbell, Andrew Bresticker, Greg Kroah-Hartman,
	Linus Walleij, Jassi Brar, linux-kernel, Kishon Vijay Abraham I,
	Rob Herring, Alan Stern, linux-arm-kernel, Kumar Gala,
	Grant Likely, Arnd Bergmann

This series adds support for xHCI on NVIDIA Tegra SoCs.  This includes:
 - adding a driver for the mailbox used to communicate with the xHCI
   controller's firmware,
 - extending the XUSB pad controller driver to support the USB PHY
   types (UTMI, HSIC, and USB3), and
 - adding a xHCI host-controller driver.

Based on 3.17-rc1, Jassi Brar's common mailbox framework [0], and my
xHCI modules series [1].

Tested on Venice2, Jetson TK1, and Big with a variety of USB2.0 and
USB3.0 memory sticks and ethernet dongles using controller firmware from
the ChromiumOS tree [2].  I've asked NVIDIA to submit firmware to the
linux-firmware package.

Notes:
 - HSIC support is mostly untested and I think there are still some issues
   to work out there.  I do have a Tegra124 board with a HSIC hub so I'll
   try to sort those out later.
 - The XUSB padctl driver doesn't play nice with the existing Tegra USB2.0
   PHY driver, so all ports should be assigned to the XHCI controller.

Based on work by:
  a lot of people, but from what I can tell from the L4T tree [3], the
  original authors of the Tegra xHCI driver are:
    Ajay Gupta <ajayg@nvidia.com>
    Bharath Yadav <byadav@nvidia.com>

Changes from v1:
 - Converted mailbox driver to use the common mailbox framework.
 - Fixed up host driver so that it can now be built and used as a module.
 - Addressed Stephen's review comments.
 - Misc. cleanups.

Changes from RFC:
 - Dropped Tegra114 support.
 - Split out mailbox into separate driver.
 - Stopped using child xhci-plat device in xHCI host-controller driver.
 - Added PHY support to Thierry's XUSB padctl driver instead of in a separate
   USB PHY driver.
 - Added Jetson TK1 support.
 - Misc. cleanups.

[0] https://lkml.org/lkml/2014/8/1/200
[1] https://lkml.org/lkml/2014/8/18/504
[2] http://commondatastorage.googleapis.com/chromeos-localmirror/distfiles/xhci-firmware-2014.05.09.00.00.tbz2
[3] git://nv-tegra.nvidia.com/linux-3.10.git

Andrew Bresticker (9):
  of: Add NVIDIA Tegra XUSB mailbox binding
  mailbox: Add NVIDIA Tegra XUSB mailbox driver
  of: Update Tegra XUSB pad controller binding for USB
  pinctrl: tegra-xusb: Add USB PHY support
  of: Add NVIDIA Tegra xHCI controller binding
  usb: xhci: Add NVIDIA Tegra xHCI host-controller driver
  ARM: tegra: Add Tegra124 XUSB mailbox and xHCI controller
  ARM: tegra: jetson-tk1: Add xHCI support
  ARM: tegra: venice2: Add xHCI support

 .../bindings/mailbox/nvidia,tegra124-xusb-mbox.txt |   30 +
 .../pinctrl/nvidia,tegra124-xusb-padctl.txt        |   52 +-
 .../bindings/usb/nvidia,tegra124-xhci.txt          |  101 ++
 arch/arm/boot/dts/tegra124-jetson-tk1.dts          |   48 +-
 arch/arm/boot/dts/tegra124-venice2.dts             |   79 +-
 arch/arm/boot/dts/tegra124.dtsi                    |   40 +
 drivers/mailbox/Kconfig                            |    3 +
 drivers/mailbox/Makefile                           |    2 +
 drivers/mailbox/tegra-xusb-mailbox.c               |  279 +++++
 drivers/pinctrl/Kconfig                            |    1 +
 drivers/pinctrl/pinctrl-tegra-xusb.c               | 1170 +++++++++++++++++++-
 drivers/usb/host/Kconfig                           |    9 +
 drivers/usb/host/Makefile                          |    1 +
 drivers/usb/host/xhci-tegra.c                      |  893 +++++++++++++++
 include/dt-bindings/mailbox/tegra-xusb-mailbox.h   |    7 +
 include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h   |   20 +
 include/soc/tegra/xusb.h                           |   52 +
 17 files changed, 2706 insertions(+), 81 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mailbox/nvidia,tegra124-xusb-mbox.txt
 create mode 100644 Documentation/devicetree/bindings/usb/nvidia,tegra124-xhci.txt
 create mode 100644 drivers/mailbox/tegra-xusb-mailbox.c
 create mode 100644 drivers/usb/host/xhci-tegra.c
 create mode 100644 include/dt-bindings/mailbox/tegra-xusb-mailbox.h
 create mode 100644 include/soc/tegra/xusb.h

-- 
2.1.0.rc2.206.gedb03e5

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

* [PATCH v2 0/9] Tegra xHCI support
@ 2014-08-18 17:08 ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-18 17:08 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, linux-tegra
  Cc: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Jassi Brar, Linus Walleij, Greg Kroah-Hartman,
	Mathias Nyman, Grant Likely, Alan Stern, Arnd Bergmann,
	Kishon Vijay Abraham I, devicetree, linux-kernel,
	linux-arm-kernel, linux-usb, Andrew Bresticker

This series adds support for xHCI on NVIDIA Tegra SoCs.  This includes:
 - adding a driver for the mailbox used to communicate with the xHCI
   controller's firmware,
 - extending the XUSB pad controller driver to support the USB PHY
   types (UTMI, HSIC, and USB3), and
 - adding a xHCI host-controller driver.

Based on 3.17-rc1, Jassi Brar's common mailbox framework [0], and my
xHCI modules series [1].

Tested on Venice2, Jetson TK1, and Big with a variety of USB2.0 and
USB3.0 memory sticks and ethernet dongles using controller firmware from
the ChromiumOS tree [2].  I've asked NVIDIA to submit firmware to the
linux-firmware package.

Notes:
 - HSIC support is mostly untested and I think there are still some issues
   to work out there.  I do have a Tegra124 board with a HSIC hub so I'll
   try to sort those out later.
 - The XUSB padctl driver doesn't play nice with the existing Tegra USB2.0
   PHY driver, so all ports should be assigned to the XHCI controller.

Based on work by:
  a lot of people, but from what I can tell from the L4T tree [3], the
  original authors of the Tegra xHCI driver are:
    Ajay Gupta <ajayg@nvidia.com>
    Bharath Yadav <byadav@nvidia.com>

Changes from v1:
 - Converted mailbox driver to use the common mailbox framework.
 - Fixed up host driver so that it can now be built and used as a module.
 - Addressed Stephen's review comments.
 - Misc. cleanups.

Changes from RFC:
 - Dropped Tegra114 support.
 - Split out mailbox into separate driver.
 - Stopped using child xhci-plat device in xHCI host-controller driver.
 - Added PHY support to Thierry's XUSB padctl driver instead of in a separate
   USB PHY driver.
 - Added Jetson TK1 support.
 - Misc. cleanups.

[0] https://lkml.org/lkml/2014/8/1/200
[1] https://lkml.org/lkml/2014/8/18/504
[2] http://commondatastorage.googleapis.com/chromeos-localmirror/distfiles/xhci-firmware-2014.05.09.00.00.tbz2
[3] git://nv-tegra.nvidia.com/linux-3.10.git

Andrew Bresticker (9):
  of: Add NVIDIA Tegra XUSB mailbox binding
  mailbox: Add NVIDIA Tegra XUSB mailbox driver
  of: Update Tegra XUSB pad controller binding for USB
  pinctrl: tegra-xusb: Add USB PHY support
  of: Add NVIDIA Tegra xHCI controller binding
  usb: xhci: Add NVIDIA Tegra xHCI host-controller driver
  ARM: tegra: Add Tegra124 XUSB mailbox and xHCI controller
  ARM: tegra: jetson-tk1: Add xHCI support
  ARM: tegra: venice2: Add xHCI support

 .../bindings/mailbox/nvidia,tegra124-xusb-mbox.txt |   30 +
 .../pinctrl/nvidia,tegra124-xusb-padctl.txt        |   52 +-
 .../bindings/usb/nvidia,tegra124-xhci.txt          |  101 ++
 arch/arm/boot/dts/tegra124-jetson-tk1.dts          |   48 +-
 arch/arm/boot/dts/tegra124-venice2.dts             |   79 +-
 arch/arm/boot/dts/tegra124.dtsi                    |   40 +
 drivers/mailbox/Kconfig                            |    3 +
 drivers/mailbox/Makefile                           |    2 +
 drivers/mailbox/tegra-xusb-mailbox.c               |  279 +++++
 drivers/pinctrl/Kconfig                            |    1 +
 drivers/pinctrl/pinctrl-tegra-xusb.c               | 1170 +++++++++++++++++++-
 drivers/usb/host/Kconfig                           |    9 +
 drivers/usb/host/Makefile                          |    1 +
 drivers/usb/host/xhci-tegra.c                      |  893 +++++++++++++++
 include/dt-bindings/mailbox/tegra-xusb-mailbox.h   |    7 +
 include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h   |   20 +
 include/soc/tegra/xusb.h                           |   52 +
 17 files changed, 2706 insertions(+), 81 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mailbox/nvidia,tegra124-xusb-mbox.txt
 create mode 100644 Documentation/devicetree/bindings/usb/nvidia,tegra124-xhci.txt
 create mode 100644 drivers/mailbox/tegra-xusb-mailbox.c
 create mode 100644 drivers/usb/host/xhci-tegra.c
 create mode 100644 include/dt-bindings/mailbox/tegra-xusb-mailbox.h
 create mode 100644 include/soc/tegra/xusb.h

-- 
2.1.0.rc2.206.gedb03e5


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

* [PATCH v2 0/9] Tegra xHCI support
@ 2014-08-18 17:08 ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-18 17:08 UTC (permalink / raw)
  To: linux-arm-kernel

This series adds support for xHCI on NVIDIA Tegra SoCs.  This includes:
 - adding a driver for the mailbox used to communicate with the xHCI
   controller's firmware,
 - extending the XUSB pad controller driver to support the USB PHY
   types (UTMI, HSIC, and USB3), and
 - adding a xHCI host-controller driver.

Based on 3.17-rc1, Jassi Brar's common mailbox framework [0], and my
xHCI modules series [1].

Tested on Venice2, Jetson TK1, and Big with a variety of USB2.0 and
USB3.0 memory sticks and ethernet dongles using controller firmware from
the ChromiumOS tree [2].  I've asked NVIDIA to submit firmware to the
linux-firmware package.

Notes:
 - HSIC support is mostly untested and I think there are still some issues
   to work out there.  I do have a Tegra124 board with a HSIC hub so I'll
   try to sort those out later.
 - The XUSB padctl driver doesn't play nice with the existing Tegra USB2.0
   PHY driver, so all ports should be assigned to the XHCI controller.

Based on work by:
  a lot of people, but from what I can tell from the L4T tree [3], the
  original authors of the Tegra xHCI driver are:
    Ajay Gupta <ajayg@nvidia.com>
    Bharath Yadav <byadav@nvidia.com>

Changes from v1:
 - Converted mailbox driver to use the common mailbox framework.
 - Fixed up host driver so that it can now be built and used as a module.
 - Addressed Stephen's review comments.
 - Misc. cleanups.

Changes from RFC:
 - Dropped Tegra114 support.
 - Split out mailbox into separate driver.
 - Stopped using child xhci-plat device in xHCI host-controller driver.
 - Added PHY support to Thierry's XUSB padctl driver instead of in a separate
   USB PHY driver.
 - Added Jetson TK1 support.
 - Misc. cleanups.

[0] https://lkml.org/lkml/2014/8/1/200
[1] https://lkml.org/lkml/2014/8/18/504
[2] http://commondatastorage.googleapis.com/chromeos-localmirror/distfiles/xhci-firmware-2014.05.09.00.00.tbz2
[3] git://nv-tegra.nvidia.com/linux-3.10.git

Andrew Bresticker (9):
  of: Add NVIDIA Tegra XUSB mailbox binding
  mailbox: Add NVIDIA Tegra XUSB mailbox driver
  of: Update Tegra XUSB pad controller binding for USB
  pinctrl: tegra-xusb: Add USB PHY support
  of: Add NVIDIA Tegra xHCI controller binding
  usb: xhci: Add NVIDIA Tegra xHCI host-controller driver
  ARM: tegra: Add Tegra124 XUSB mailbox and xHCI controller
  ARM: tegra: jetson-tk1: Add xHCI support
  ARM: tegra: venice2: Add xHCI support

 .../bindings/mailbox/nvidia,tegra124-xusb-mbox.txt |   30 +
 .../pinctrl/nvidia,tegra124-xusb-padctl.txt        |   52 +-
 .../bindings/usb/nvidia,tegra124-xhci.txt          |  101 ++
 arch/arm/boot/dts/tegra124-jetson-tk1.dts          |   48 +-
 arch/arm/boot/dts/tegra124-venice2.dts             |   79 +-
 arch/arm/boot/dts/tegra124.dtsi                    |   40 +
 drivers/mailbox/Kconfig                            |    3 +
 drivers/mailbox/Makefile                           |    2 +
 drivers/mailbox/tegra-xusb-mailbox.c               |  279 +++++
 drivers/pinctrl/Kconfig                            |    1 +
 drivers/pinctrl/pinctrl-tegra-xusb.c               | 1170 +++++++++++++++++++-
 drivers/usb/host/Kconfig                           |    9 +
 drivers/usb/host/Makefile                          |    1 +
 drivers/usb/host/xhci-tegra.c                      |  893 +++++++++++++++
 include/dt-bindings/mailbox/tegra-xusb-mailbox.h   |    7 +
 include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h   |   20 +
 include/soc/tegra/xusb.h                           |   52 +
 17 files changed, 2706 insertions(+), 81 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mailbox/nvidia,tegra124-xusb-mbox.txt
 create mode 100644 Documentation/devicetree/bindings/usb/nvidia,tegra124-xhci.txt
 create mode 100644 drivers/mailbox/tegra-xusb-mailbox.c
 create mode 100644 drivers/usb/host/xhci-tegra.c
 create mode 100644 include/dt-bindings/mailbox/tegra-xusb-mailbox.h
 create mode 100644 include/soc/tegra/xusb.h

-- 
2.1.0.rc2.206.gedb03e5

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

* [PATCH v2 1/9] of: Add NVIDIA Tegra XUSB mailbox binding
  2014-08-18 17:08 ` Andrew Bresticker
  (?)
@ 2014-08-18 17:08     ` Andrew Bresticker
  -1 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-18 17:08 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, linux-tegra-u79uwXL29TY76Z2rM5mHXA
  Cc: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Jassi Brar, Linus Walleij, Greg Kroah-Hartman,
	Mathias Nyman, Grant Likely, Alan Stern, Arnd Bergmann,
	Kishon Vijay Abraham I, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA, Andrew Bresticker

Add device-tree bindings for the Tegra XUSB mailbox which will be used
for communication between the Tegra xHCI controller's firmware and the
host processor.

Signed-off-by: Andrew Bresticker <abrestic-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
---
Changes from v1:
 - Updated to use common mailbox bindings.
---
 .../bindings/mailbox/nvidia,tegra124-xusb-mbox.txt | 30 ++++++++++++++++++++++
 include/dt-bindings/mailbox/tegra-xusb-mailbox.h   |  7 +++++
 2 files changed, 37 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mailbox/nvidia,tegra124-xusb-mbox.txt
 create mode 100644 include/dt-bindings/mailbox/tegra-xusb-mailbox.h

diff --git a/Documentation/devicetree/bindings/mailbox/nvidia,tegra124-xusb-mbox.txt b/Documentation/devicetree/bindings/mailbox/nvidia,tegra124-xusb-mbox.txt
new file mode 100644
index 0000000..c46219b
--- /dev/null
+++ b/Documentation/devicetree/bindings/mailbox/nvidia,tegra124-xusb-mbox.txt
@@ -0,0 +1,30 @@
+NVIDIA Tegra XUSB mailbox
+=========================
+
+The Tegra XUSB mailbox is used by the Tegra xHCI controller's firmware to
+communicate requests to the host and PHY drivers.
+
+Required properties:
+--------------------
+ - compatible: Should be "nvidia,tegra124-xusb-mbox".
+ - reg: Address and length of the XUSB FPCI registers.
+ - interrupts: XUSB mailbox interrupt.
+ - #mbox-cells: Should be 1.  The specifier is the index of the mailbox to
+   reference.  See <dt-bindings/mailbox/tegra-xusb-mailbox.h> for the list
+   of valid values.
+
+Example:
+--------
+	mbox: mailbox@0,70098000 {
+		compatible = "nvidia,tegra124-xusb-mbox";
+		reg = <0x0 0x70098000 0x0 0x1000>;
+		interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+
+		#mbox-cells = <1>;
+	};
+
+	usb@0,70090000 {
+		...
+		mboxes = <&mbox TEGRA_XUSB_MBOX_CHAN_HOST>;
+		...
+	};
diff --git a/include/dt-bindings/mailbox/tegra-xusb-mailbox.h b/include/dt-bindings/mailbox/tegra-xusb-mailbox.h
new file mode 100644
index 0000000..59de6b0
--- /dev/null
+++ b/include/dt-bindings/mailbox/tegra-xusb-mailbox.h
@@ -0,0 +1,7 @@
+#ifndef _DT_BINDINGS_TEGRA_XUSB_MAILBOX_H
+#define _DT_BINDINGS_TEGRA_XUSB_MAILBOX_H
+
+#define TEGRA_XUSB_MBOX_CHAN_HOST	0
+#define TEGRA_XUSB_MBOX_CHAN_PHY	1
+
+#endif /* _DT_BINDINGS_TEGRA_XUSB_MAILBOX_H */
-- 
2.1.0.rc2.206.gedb03e5

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

* [PATCH v2 1/9] of: Add NVIDIA Tegra XUSB mailbox binding
@ 2014-08-18 17:08     ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-18 17:08 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, linux-tegra
  Cc: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Jassi Brar, Linus Walleij, Greg Kroah-Hartman,
	Mathias Nyman, Grant Likely, Alan Stern, Arnd Bergmann,
	Kishon Vijay Abraham I, devicetree, linux-kernel,
	linux-arm-kernel, linux-usb, Andrew Bresticker

Add device-tree bindings for the Tegra XUSB mailbox which will be used
for communication between the Tegra xHCI controller's firmware and the
host processor.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
---
Changes from v1:
 - Updated to use common mailbox bindings.
---
 .../bindings/mailbox/nvidia,tegra124-xusb-mbox.txt | 30 ++++++++++++++++++++++
 include/dt-bindings/mailbox/tegra-xusb-mailbox.h   |  7 +++++
 2 files changed, 37 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mailbox/nvidia,tegra124-xusb-mbox.txt
 create mode 100644 include/dt-bindings/mailbox/tegra-xusb-mailbox.h

diff --git a/Documentation/devicetree/bindings/mailbox/nvidia,tegra124-xusb-mbox.txt b/Documentation/devicetree/bindings/mailbox/nvidia,tegra124-xusb-mbox.txt
new file mode 100644
index 0000000..c46219b
--- /dev/null
+++ b/Documentation/devicetree/bindings/mailbox/nvidia,tegra124-xusb-mbox.txt
@@ -0,0 +1,30 @@
+NVIDIA Tegra XUSB mailbox
+=========================
+
+The Tegra XUSB mailbox is used by the Tegra xHCI controller's firmware to
+communicate requests to the host and PHY drivers.
+
+Required properties:
+--------------------
+ - compatible: Should be "nvidia,tegra124-xusb-mbox".
+ - reg: Address and length of the XUSB FPCI registers.
+ - interrupts: XUSB mailbox interrupt.
+ - #mbox-cells: Should be 1.  The specifier is the index of the mailbox to
+   reference.  See <dt-bindings/mailbox/tegra-xusb-mailbox.h> for the list
+   of valid values.
+
+Example:
+--------
+	mbox: mailbox@0,70098000 {
+		compatible = "nvidia,tegra124-xusb-mbox";
+		reg = <0x0 0x70098000 0x0 0x1000>;
+		interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+
+		#mbox-cells = <1>;
+	};
+
+	usb@0,70090000 {
+		...
+		mboxes = <&mbox TEGRA_XUSB_MBOX_CHAN_HOST>;
+		...
+	};
diff --git a/include/dt-bindings/mailbox/tegra-xusb-mailbox.h b/include/dt-bindings/mailbox/tegra-xusb-mailbox.h
new file mode 100644
index 0000000..59de6b0
--- /dev/null
+++ b/include/dt-bindings/mailbox/tegra-xusb-mailbox.h
@@ -0,0 +1,7 @@
+#ifndef _DT_BINDINGS_TEGRA_XUSB_MAILBOX_H
+#define _DT_BINDINGS_TEGRA_XUSB_MAILBOX_H
+
+#define TEGRA_XUSB_MBOX_CHAN_HOST	0
+#define TEGRA_XUSB_MBOX_CHAN_PHY	1
+
+#endif /* _DT_BINDINGS_TEGRA_XUSB_MAILBOX_H */
-- 
2.1.0.rc2.206.gedb03e5


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

* [PATCH v2 1/9] of: Add NVIDIA Tegra XUSB mailbox binding
@ 2014-08-18 17:08     ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-18 17:08 UTC (permalink / raw)
  To: linux-arm-kernel

Add device-tree bindings for the Tegra XUSB mailbox which will be used
for communication between the Tegra xHCI controller's firmware and the
host processor.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
---
Changes from v1:
 - Updated to use common mailbox bindings.
---
 .../bindings/mailbox/nvidia,tegra124-xusb-mbox.txt | 30 ++++++++++++++++++++++
 include/dt-bindings/mailbox/tegra-xusb-mailbox.h   |  7 +++++
 2 files changed, 37 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mailbox/nvidia,tegra124-xusb-mbox.txt
 create mode 100644 include/dt-bindings/mailbox/tegra-xusb-mailbox.h

diff --git a/Documentation/devicetree/bindings/mailbox/nvidia,tegra124-xusb-mbox.txt b/Documentation/devicetree/bindings/mailbox/nvidia,tegra124-xusb-mbox.txt
new file mode 100644
index 0000000..c46219b
--- /dev/null
+++ b/Documentation/devicetree/bindings/mailbox/nvidia,tegra124-xusb-mbox.txt
@@ -0,0 +1,30 @@
+NVIDIA Tegra XUSB mailbox
+=========================
+
+The Tegra XUSB mailbox is used by the Tegra xHCI controller's firmware to
+communicate requests to the host and PHY drivers.
+
+Required properties:
+--------------------
+ - compatible: Should be "nvidia,tegra124-xusb-mbox".
+ - reg: Address and length of the XUSB FPCI registers.
+ - interrupts: XUSB mailbox interrupt.
+ - #mbox-cells: Should be 1.  The specifier is the index of the mailbox to
+   reference.  See <dt-bindings/mailbox/tegra-xusb-mailbox.h> for the list
+   of valid values.
+
+Example:
+--------
+	mbox: mailbox at 0,70098000 {
+		compatible = "nvidia,tegra124-xusb-mbox";
+		reg = <0x0 0x70098000 0x0 0x1000>;
+		interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+
+		#mbox-cells = <1>;
+	};
+
+	usb at 0,70090000 {
+		...
+		mboxes = <&mbox TEGRA_XUSB_MBOX_CHAN_HOST>;
+		...
+	};
diff --git a/include/dt-bindings/mailbox/tegra-xusb-mailbox.h b/include/dt-bindings/mailbox/tegra-xusb-mailbox.h
new file mode 100644
index 0000000..59de6b0
--- /dev/null
+++ b/include/dt-bindings/mailbox/tegra-xusb-mailbox.h
@@ -0,0 +1,7 @@
+#ifndef _DT_BINDINGS_TEGRA_XUSB_MAILBOX_H
+#define _DT_BINDINGS_TEGRA_XUSB_MAILBOX_H
+
+#define TEGRA_XUSB_MBOX_CHAN_HOST	0
+#define TEGRA_XUSB_MBOX_CHAN_PHY	1
+
+#endif /* _DT_BINDINGS_TEGRA_XUSB_MAILBOX_H */
-- 
2.1.0.rc2.206.gedb03e5

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

* [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
  2014-08-18 17:08 ` Andrew Bresticker
  (?)
@ 2014-08-18 17:08   ` Andrew Bresticker
  -1 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-18 17:08 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, linux-tegra
  Cc: Mark Rutland, devicetree, linux-usb, Russell King, Mathias Nyman,
	Pawel Moll, Ian Campbell, Andrew Bresticker, Greg Kroah-Hartman,
	Linus Walleij, Jassi Brar, linux-kernel, Kishon Vijay Abraham I,
	Rob Herring, Alan Stern, linux-arm-kernel, Kumar Gala,
	Grant Likely, Arnd Bergmann

The Tegra xHCI controller's firmware communicates requests to the host
processor through a mailbox interface.  While there is only a single
communication channel, messages sent by the controller can be divided
into two groups: those intended for the PHY driver and those intended
for the host-controller driver.  This mailbox driver exposes the two
channels and routes incoming messages to the appropriate channel based
on the command encoded in the message.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
---
Changes from v1:
 - Converted to common mailbox framework.
 - Removed useless polling sequences in TX path.
 - Moved xusb include from linux/ to soc/tegra/
---
 drivers/mailbox/Kconfig              |   3 +
 drivers/mailbox/Makefile             |   2 +
 drivers/mailbox/tegra-xusb-mailbox.c | 279 +++++++++++++++++++++++++++++++++++
 include/soc/tegra/xusb.h             |  45 ++++++
 4 files changed, 329 insertions(+)
 create mode 100644 drivers/mailbox/tegra-xusb-mailbox.c
 create mode 100644 include/soc/tegra/xusb.h

diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index 9fd9c67..97369c2 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -33,4 +33,7 @@ config OMAP_MBOX_KFIFO_SIZE
 	  Specify the default size of mailbox's kfifo buffers (bytes).
 	  This can also be changed at runtime (via the mbox_kfifo_size
 	  module parameter).
+
+config TEGRA_XUSB_MBOX
+	def_bool y if ARCH_TEGRA
 endif
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index 94ed7ce..7f0af9c 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -5,3 +5,5 @@ obj-$(CONFIG_MAILBOX)		+= mailbox.o
 obj-$(CONFIG_PL320_MBOX)	+= pl320-ipc.o
 
 obj-$(CONFIG_OMAP2PLUS_MBOX)	+= omap-mailbox.o
+
+obj-$(CONFIG_TEGRA_XUSB_MBOX)	+= tegra-xusb-mailbox.o
diff --git a/drivers/mailbox/tegra-xusb-mailbox.c b/drivers/mailbox/tegra-xusb-mailbox.c
new file mode 100644
index 0000000..917d48e7
--- /dev/null
+++ b/drivers/mailbox/tegra-xusb-mailbox.c
@@ -0,0 +1,279 @@
+/*
+ * NVIDIA Tegra XUSB mailbox driver
+ *
+ * Copyright (C) 2014 NVIDIA Corporation
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mailbox_controller.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <soc/tegra/xusb.h>
+
+#include <dt-bindings/mailbox/tegra-xusb-mailbox.h>
+
+#define XUSB_CFG_ARU_MBOX_CMD			0xe4
+#define  MBOX_FALC_INT_EN			BIT(27)
+#define  MBOX_PME_INT_EN			BIT(28)
+#define  MBOX_SMI_INT_EN			BIT(29)
+#define  MBOX_XHCI_INT_EN			BIT(30)
+#define  MBOX_INT_EN				BIT(31)
+#define XUSB_CFG_ARU_MBOX_DATA_IN		0xe8
+#define  CMD_DATA_SHIFT				0
+#define  CMD_DATA_MASK				0xffffff
+#define  CMD_TYPE_SHIFT				24
+#define  CMD_TYPE_MASK				0xff
+#define XUSB_CFG_ARU_MBOX_DATA_OUT		0xec
+#define XUSB_CFG_ARU_MBOX_OWNER			0xf0
+#define  MBOX_OWNER_NONE			0
+#define  MBOX_OWNER_FW				1
+#define  MBOX_OWNER_SW				2
+#define XUSB_CFG_ARU_SMI_INTR			0x428
+#define  MBOX_SMI_INTR_FW_HANG			BIT(1)
+#define  MBOX_SMI_INTR_EN			BIT(3)
+
+#define XUSB_MBOX_IDLE_TIMEOUT		20
+#define XUSB_MBOX_ACQUIRE_TIMEOUT	10
+
+struct tegra_xusb_mbox {
+	struct mbox_controller mbox;
+	int irq;
+	void __iomem *regs;
+	spinlock_t lock;
+};
+
+static inline u32 mbox_readl(struct tegra_xusb_mbox *mbox, unsigned long offset)
+{
+	return readl(mbox->regs + offset);
+}
+
+static inline void mbox_writel(struct tegra_xusb_mbox *mbox, u32 val,
+			       unsigned long offset)
+{
+	writel(val, mbox->regs + offset);
+}
+
+static inline u32 mbox_pack_msg(struct tegra_xusb_mbox_msg *msg)
+{
+	u32 val;
+
+	val = (msg->cmd & CMD_TYPE_MASK) << CMD_TYPE_SHIFT;
+	val |= (msg->data & CMD_DATA_MASK) << CMD_DATA_SHIFT;
+
+	return val;
+}
+
+static inline void mbox_unpack_msg(u32 val, struct tegra_xusb_mbox_msg *msg)
+{
+	msg->cmd = (val >> CMD_TYPE_SHIFT) & CMD_TYPE_MASK;
+	msg->data = (val >> CMD_DATA_SHIFT) & CMD_DATA_MASK;
+}
+
+static struct mbox_chan *mbox_cmd_to_chan(struct tegra_xusb_mbox *mbox, u32 cmd)
+{
+	switch (cmd) {
+	case MBOX_CMD_INC_FALC_CLOCK:
+	case MBOX_CMD_DEC_FALC_CLOCK:
+	case MBOX_CMD_INC_SSPI_CLOCK:
+	case MBOX_CMD_DEC_SSPI_CLOCK:
+	case MBOX_CMD_SET_BW:
+		return &mbox->mbox.chans[TEGRA_XUSB_MBOX_CHAN_HOST];
+	case MBOX_CMD_SAVE_DFE_CTLE_CTX:
+	case MBOX_CMD_START_HSIC_IDLE:
+	case MBOX_CMD_STOP_HSIC_IDLE:
+		return &mbox->mbox.chans[TEGRA_XUSB_MBOX_CHAN_PHY];
+	default:
+		return NULL;
+	}
+}
+
+static int tegra_xusb_mbox_send_data(struct mbox_chan *chan, void *data)
+{
+	struct tegra_xusb_mbox *mbox = dev_get_drvdata(chan->mbox->dev);
+	struct tegra_xusb_mbox_msg *msg = data;
+	unsigned long flags;
+	u32 reg, owner;
+
+	dev_dbg(mbox->mbox.dev, "TX message 0x%x:0x%x\n", msg->cmd, msg->data);
+
+	/* ACK/NAK must be sent with the controller as the mailbox owner */
+	if (msg->cmd == MBOX_CMD_ACK || msg->cmd == MBOX_CMD_NAK)
+		owner = MBOX_OWNER_FW;
+	else
+		owner = MBOX_OWNER_SW;
+
+	spin_lock_irqsave(&mbox->lock, flags);
+
+	/* Acquire mailbox */
+	if (mbox_readl(mbox, XUSB_CFG_ARU_MBOX_OWNER) != MBOX_OWNER_NONE) {
+		dev_err(mbox->mbox.dev, "Mailbox not idle\n");
+		goto busy;
+	}
+	mbox_writel(mbox, owner, XUSB_CFG_ARU_MBOX_OWNER);
+	if (mbox_readl(mbox, XUSB_CFG_ARU_MBOX_OWNER) != owner) {
+		dev_err(mbox->mbox.dev, "Failed to acquire mailbox");
+		goto busy;
+	}
+
+	mbox_writel(mbox, mbox_pack_msg(msg), XUSB_CFG_ARU_MBOX_DATA_IN);
+	reg = mbox_readl(mbox, XUSB_CFG_ARU_MBOX_CMD);
+	reg |= MBOX_INT_EN | MBOX_FALC_INT_EN;
+	mbox_writel(mbox, reg, XUSB_CFG_ARU_MBOX_CMD);
+
+	spin_unlock_irqrestore(&mbox->lock, flags);
+
+	return 0;
+busy:
+	spin_unlock_irqrestore(&mbox->lock, flags);
+	return -EBUSY;
+}
+
+static int tegra_xusb_mbox_startup(struct mbox_chan *chan)
+{
+	return 0;
+}
+
+static void tegra_xusb_mbox_shutdown(struct mbox_chan *chan)
+{
+}
+
+static bool tegra_xusb_mbox_last_tx_done(struct mbox_chan *chan)
+{
+	/*
+	 * Transmissions are assumed to be completed as soon as they are
+	 * written to the mailbox.
+	 */
+	return true;
+}
+
+static struct mbox_chan_ops tegra_xusb_mbox_chan_ops = {
+	.send_data = tegra_xusb_mbox_send_data,
+	.startup = tegra_xusb_mbox_startup,
+	.shutdown = tegra_xusb_mbox_shutdown,
+	.last_tx_done = tegra_xusb_mbox_last_tx_done,
+};
+
+static irqreturn_t tegra_xusb_mbox_irq(int irq, void *p)
+{
+	struct tegra_xusb_mbox *mbox = (struct tegra_xusb_mbox *)p;
+	struct mbox_chan *chan;
+	struct tegra_xusb_mbox_msg msg;
+	u32 reg;
+
+	spin_lock(&mbox->lock);
+
+	/* Clear mbox interrupts */
+	reg = mbox_readl(mbox, XUSB_CFG_ARU_SMI_INTR);
+	if (reg & MBOX_SMI_INTR_FW_HANG)
+		dev_err(mbox->mbox.dev, "Controller firmware hang\n");
+	mbox_writel(mbox, reg, XUSB_CFG_ARU_SMI_INTR);
+
+	reg = mbox_readl(mbox, XUSB_CFG_ARU_MBOX_DATA_OUT);
+	mbox_unpack_msg(reg, &msg);
+
+	/*
+	 * Set the mailbox back to idle.  The recipient of the message is
+	 * responsible for sending an ACK/NAK, if necessary.
+	 */
+	reg = mbox_readl(mbox, XUSB_CFG_ARU_MBOX_CMD);
+	reg &= ~MBOX_SMI_INT_EN;
+	mbox_writel(mbox, reg, XUSB_CFG_ARU_MBOX_CMD);
+	mbox_writel(mbox, MBOX_OWNER_NONE, XUSB_CFG_ARU_MBOX_OWNER);
+
+	spin_unlock(&mbox->lock);
+
+	dev_dbg(mbox->mbox.dev, "RX message 0x%x:0x%x\n", msg.cmd, msg.data);
+	chan = mbox_cmd_to_chan(mbox, msg.cmd);
+	if (chan)
+		mbox_chan_received_data(chan, &msg);
+	else
+		dev_err(mbox->mbox.dev, "Unexpected message: 0x%x:0x%x\n",
+			msg.cmd, msg.data);
+
+	return IRQ_HANDLED;
+}
+
+static struct of_device_id tegra_xusb_mbox_of_match[] = {
+	{ .compatible = "nvidia,tegra124-xusb-mbox" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, tegra_xusb_mbox_of_match);
+
+static int tegra_xusb_mbox_probe(struct platform_device *pdev)
+{
+	struct tegra_xusb_mbox *mbox;
+	struct resource *res;
+	int ret;
+
+	mbox = devm_kzalloc(&pdev->dev, sizeof(*mbox), GFP_KERNEL);
+	if (!mbox)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, mbox);
+	spin_lock_init(&mbox->lock);
+
+	mbox->mbox.dev = &pdev->dev;
+	mbox->mbox.chans = devm_kcalloc(&pdev->dev, TEGRA_XUSB_MBOX_NUM_CHANS,
+					sizeof(*mbox->mbox.chans), GFP_KERNEL);
+	if (!mbox->mbox.chans)
+		return -ENOMEM;
+	mbox->mbox.num_chans = TEGRA_XUSB_MBOX_NUM_CHANS;
+	mbox->mbox.ops = &tegra_xusb_mbox_chan_ops;
+	mbox->mbox.txdone_poll = true;
+	mbox->mbox.txpoll_period = 0; /* no need to actually poll */
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+	mbox->regs = devm_ioremap_nocache(&pdev->dev, res->start,
+					  resource_size(res));
+	if (!mbox->regs)
+		return -ENOMEM;
+
+	mbox->irq = platform_get_irq(pdev, 0);
+	if (mbox->irq < 0)
+		return mbox->irq;
+	ret = devm_request_irq(&pdev->dev, mbox->irq, tegra_xusb_mbox_irq, 0,
+			       dev_name(&pdev->dev), mbox);
+	if (ret < 0)
+		return ret;
+
+	ret = mbox_controller_register(&mbox->mbox);
+	if (ret < 0)
+		dev_err(&pdev->dev, "failed to register mailbox: %d\n", ret);
+
+	return ret;
+}
+
+static int tegra_xusb_mbox_remove(struct platform_device *pdev)
+{
+	struct tegra_xusb_mbox *mbox = platform_get_drvdata(pdev);
+
+	mbox_controller_unregister(&mbox->mbox);
+
+	return 0;
+}
+
+static struct platform_driver tegra_xusb_mbox_driver = {
+	.probe	= tegra_xusb_mbox_probe,
+	.remove	= tegra_xusb_mbox_remove,
+	.driver	= {
+		.name = "tegra-xusb-mbox",
+		.of_match_table = of_match_ptr(tegra_xusb_mbox_of_match),
+	},
+};
+module_platform_driver(tegra_xusb_mbox_driver);
+
+MODULE_AUTHOR("Andrew Bresticker <abrestic@chromium.org>");
+MODULE_DESCRIPTION("NVIDIA Tegra XUSB mailbox driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:tegra-xusb-mailbox");
diff --git a/include/soc/tegra/xusb.h b/include/soc/tegra/xusb.h
new file mode 100644
index 0000000..8efef8c
--- /dev/null
+++ b/include/soc/tegra/xusb.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2014 NVIDIA Corporation
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#ifndef __SOC_TEGRA_XUSB_H__
+#define __SOC_TEGRA_XUSB_H__
+
+#define TEGRA_XUSB_MBOX_NUM_CHANS 2 /* host + phy */
+
+/* Command requests from the firmware */
+enum tegra_xusb_mbox_cmd {
+	MBOX_CMD_MSG_ENABLED = 1,
+	MBOX_CMD_INC_FALC_CLOCK,
+	MBOX_CMD_DEC_FALC_CLOCK,
+	MBOX_CMD_INC_SSPI_CLOCK,
+	MBOX_CMD_DEC_SSPI_CLOCK,
+	MBOX_CMD_SET_BW, /* no ACK/NAK required */
+	MBOX_CMD_SET_SS_PWR_GATING,
+	MBOX_CMD_SET_SS_PWR_UNGATING,
+	MBOX_CMD_SAVE_DFE_CTLE_CTX,
+	MBOX_CMD_AIRPLANE_MODE_ENABLED, /* unused */
+	MBOX_CMD_AIRPLANE_MODE_DISABLED, /* unused */
+	MBOX_CMD_START_HSIC_IDLE,
+	MBOX_CMD_STOP_HSIC_IDLE,
+	MBOX_CMD_DBC_WAKE_STACK, /* unused */
+	MBOX_CMD_HSIC_PRETEND_CONNECT,
+
+	MBOX_CMD_MAX,
+
+	/* Response message to above commands */
+	MBOX_CMD_ACK = 128,
+	MBOX_CMD_NAK
+};
+
+struct tegra_xusb_mbox_msg {
+	u32 cmd;
+	u32 data;
+};
+
+#endif /* __SOC_TEGRA_XUSB_H__ */
-- 
2.1.0.rc2.206.gedb03e5

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

* [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-18 17:08   ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-18 17:08 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, linux-tegra
  Cc: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Jassi Brar, Linus Walleij, Greg Kroah-Hartman,
	Mathias Nyman, Grant Likely, Alan Stern, Arnd Bergmann,
	Kishon Vijay Abraham I, devicetree, linux-kernel,
	linux-arm-kernel, linux-usb, Andrew Bresticker

The Tegra xHCI controller's firmware communicates requests to the host
processor through a mailbox interface.  While there is only a single
communication channel, messages sent by the controller can be divided
into two groups: those intended for the PHY driver and those intended
for the host-controller driver.  This mailbox driver exposes the two
channels and routes incoming messages to the appropriate channel based
on the command encoded in the message.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
---
Changes from v1:
 - Converted to common mailbox framework.
 - Removed useless polling sequences in TX path.
 - Moved xusb include from linux/ to soc/tegra/
---
 drivers/mailbox/Kconfig              |   3 +
 drivers/mailbox/Makefile             |   2 +
 drivers/mailbox/tegra-xusb-mailbox.c | 279 +++++++++++++++++++++++++++++++++++
 include/soc/tegra/xusb.h             |  45 ++++++
 4 files changed, 329 insertions(+)
 create mode 100644 drivers/mailbox/tegra-xusb-mailbox.c
 create mode 100644 include/soc/tegra/xusb.h

diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index 9fd9c67..97369c2 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -33,4 +33,7 @@ config OMAP_MBOX_KFIFO_SIZE
 	  Specify the default size of mailbox's kfifo buffers (bytes).
 	  This can also be changed at runtime (via the mbox_kfifo_size
 	  module parameter).
+
+config TEGRA_XUSB_MBOX
+	def_bool y if ARCH_TEGRA
 endif
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index 94ed7ce..7f0af9c 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -5,3 +5,5 @@ obj-$(CONFIG_MAILBOX)		+= mailbox.o
 obj-$(CONFIG_PL320_MBOX)	+= pl320-ipc.o
 
 obj-$(CONFIG_OMAP2PLUS_MBOX)	+= omap-mailbox.o
+
+obj-$(CONFIG_TEGRA_XUSB_MBOX)	+= tegra-xusb-mailbox.o
diff --git a/drivers/mailbox/tegra-xusb-mailbox.c b/drivers/mailbox/tegra-xusb-mailbox.c
new file mode 100644
index 0000000..917d48e7
--- /dev/null
+++ b/drivers/mailbox/tegra-xusb-mailbox.c
@@ -0,0 +1,279 @@
+/*
+ * NVIDIA Tegra XUSB mailbox driver
+ *
+ * Copyright (C) 2014 NVIDIA Corporation
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mailbox_controller.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <soc/tegra/xusb.h>
+
+#include <dt-bindings/mailbox/tegra-xusb-mailbox.h>
+
+#define XUSB_CFG_ARU_MBOX_CMD			0xe4
+#define  MBOX_FALC_INT_EN			BIT(27)
+#define  MBOX_PME_INT_EN			BIT(28)
+#define  MBOX_SMI_INT_EN			BIT(29)
+#define  MBOX_XHCI_INT_EN			BIT(30)
+#define  MBOX_INT_EN				BIT(31)
+#define XUSB_CFG_ARU_MBOX_DATA_IN		0xe8
+#define  CMD_DATA_SHIFT				0
+#define  CMD_DATA_MASK				0xffffff
+#define  CMD_TYPE_SHIFT				24
+#define  CMD_TYPE_MASK				0xff
+#define XUSB_CFG_ARU_MBOX_DATA_OUT		0xec
+#define XUSB_CFG_ARU_MBOX_OWNER			0xf0
+#define  MBOX_OWNER_NONE			0
+#define  MBOX_OWNER_FW				1
+#define  MBOX_OWNER_SW				2
+#define XUSB_CFG_ARU_SMI_INTR			0x428
+#define  MBOX_SMI_INTR_FW_HANG			BIT(1)
+#define  MBOX_SMI_INTR_EN			BIT(3)
+
+#define XUSB_MBOX_IDLE_TIMEOUT		20
+#define XUSB_MBOX_ACQUIRE_TIMEOUT	10
+
+struct tegra_xusb_mbox {
+	struct mbox_controller mbox;
+	int irq;
+	void __iomem *regs;
+	spinlock_t lock;
+};
+
+static inline u32 mbox_readl(struct tegra_xusb_mbox *mbox, unsigned long offset)
+{
+	return readl(mbox->regs + offset);
+}
+
+static inline void mbox_writel(struct tegra_xusb_mbox *mbox, u32 val,
+			       unsigned long offset)
+{
+	writel(val, mbox->regs + offset);
+}
+
+static inline u32 mbox_pack_msg(struct tegra_xusb_mbox_msg *msg)
+{
+	u32 val;
+
+	val = (msg->cmd & CMD_TYPE_MASK) << CMD_TYPE_SHIFT;
+	val |= (msg->data & CMD_DATA_MASK) << CMD_DATA_SHIFT;
+
+	return val;
+}
+
+static inline void mbox_unpack_msg(u32 val, struct tegra_xusb_mbox_msg *msg)
+{
+	msg->cmd = (val >> CMD_TYPE_SHIFT) & CMD_TYPE_MASK;
+	msg->data = (val >> CMD_DATA_SHIFT) & CMD_DATA_MASK;
+}
+
+static struct mbox_chan *mbox_cmd_to_chan(struct tegra_xusb_mbox *mbox, u32 cmd)
+{
+	switch (cmd) {
+	case MBOX_CMD_INC_FALC_CLOCK:
+	case MBOX_CMD_DEC_FALC_CLOCK:
+	case MBOX_CMD_INC_SSPI_CLOCK:
+	case MBOX_CMD_DEC_SSPI_CLOCK:
+	case MBOX_CMD_SET_BW:
+		return &mbox->mbox.chans[TEGRA_XUSB_MBOX_CHAN_HOST];
+	case MBOX_CMD_SAVE_DFE_CTLE_CTX:
+	case MBOX_CMD_START_HSIC_IDLE:
+	case MBOX_CMD_STOP_HSIC_IDLE:
+		return &mbox->mbox.chans[TEGRA_XUSB_MBOX_CHAN_PHY];
+	default:
+		return NULL;
+	}
+}
+
+static int tegra_xusb_mbox_send_data(struct mbox_chan *chan, void *data)
+{
+	struct tegra_xusb_mbox *mbox = dev_get_drvdata(chan->mbox->dev);
+	struct tegra_xusb_mbox_msg *msg = data;
+	unsigned long flags;
+	u32 reg, owner;
+
+	dev_dbg(mbox->mbox.dev, "TX message 0x%x:0x%x\n", msg->cmd, msg->data);
+
+	/* ACK/NAK must be sent with the controller as the mailbox owner */
+	if (msg->cmd == MBOX_CMD_ACK || msg->cmd == MBOX_CMD_NAK)
+		owner = MBOX_OWNER_FW;
+	else
+		owner = MBOX_OWNER_SW;
+
+	spin_lock_irqsave(&mbox->lock, flags);
+
+	/* Acquire mailbox */
+	if (mbox_readl(mbox, XUSB_CFG_ARU_MBOX_OWNER) != MBOX_OWNER_NONE) {
+		dev_err(mbox->mbox.dev, "Mailbox not idle\n");
+		goto busy;
+	}
+	mbox_writel(mbox, owner, XUSB_CFG_ARU_MBOX_OWNER);
+	if (mbox_readl(mbox, XUSB_CFG_ARU_MBOX_OWNER) != owner) {
+		dev_err(mbox->mbox.dev, "Failed to acquire mailbox");
+		goto busy;
+	}
+
+	mbox_writel(mbox, mbox_pack_msg(msg), XUSB_CFG_ARU_MBOX_DATA_IN);
+	reg = mbox_readl(mbox, XUSB_CFG_ARU_MBOX_CMD);
+	reg |= MBOX_INT_EN | MBOX_FALC_INT_EN;
+	mbox_writel(mbox, reg, XUSB_CFG_ARU_MBOX_CMD);
+
+	spin_unlock_irqrestore(&mbox->lock, flags);
+
+	return 0;
+busy:
+	spin_unlock_irqrestore(&mbox->lock, flags);
+	return -EBUSY;
+}
+
+static int tegra_xusb_mbox_startup(struct mbox_chan *chan)
+{
+	return 0;
+}
+
+static void tegra_xusb_mbox_shutdown(struct mbox_chan *chan)
+{
+}
+
+static bool tegra_xusb_mbox_last_tx_done(struct mbox_chan *chan)
+{
+	/*
+	 * Transmissions are assumed to be completed as soon as they are
+	 * written to the mailbox.
+	 */
+	return true;
+}
+
+static struct mbox_chan_ops tegra_xusb_mbox_chan_ops = {
+	.send_data = tegra_xusb_mbox_send_data,
+	.startup = tegra_xusb_mbox_startup,
+	.shutdown = tegra_xusb_mbox_shutdown,
+	.last_tx_done = tegra_xusb_mbox_last_tx_done,
+};
+
+static irqreturn_t tegra_xusb_mbox_irq(int irq, void *p)
+{
+	struct tegra_xusb_mbox *mbox = (struct tegra_xusb_mbox *)p;
+	struct mbox_chan *chan;
+	struct tegra_xusb_mbox_msg msg;
+	u32 reg;
+
+	spin_lock(&mbox->lock);
+
+	/* Clear mbox interrupts */
+	reg = mbox_readl(mbox, XUSB_CFG_ARU_SMI_INTR);
+	if (reg & MBOX_SMI_INTR_FW_HANG)
+		dev_err(mbox->mbox.dev, "Controller firmware hang\n");
+	mbox_writel(mbox, reg, XUSB_CFG_ARU_SMI_INTR);
+
+	reg = mbox_readl(mbox, XUSB_CFG_ARU_MBOX_DATA_OUT);
+	mbox_unpack_msg(reg, &msg);
+
+	/*
+	 * Set the mailbox back to idle.  The recipient of the message is
+	 * responsible for sending an ACK/NAK, if necessary.
+	 */
+	reg = mbox_readl(mbox, XUSB_CFG_ARU_MBOX_CMD);
+	reg &= ~MBOX_SMI_INT_EN;
+	mbox_writel(mbox, reg, XUSB_CFG_ARU_MBOX_CMD);
+	mbox_writel(mbox, MBOX_OWNER_NONE, XUSB_CFG_ARU_MBOX_OWNER);
+
+	spin_unlock(&mbox->lock);
+
+	dev_dbg(mbox->mbox.dev, "RX message 0x%x:0x%x\n", msg.cmd, msg.data);
+	chan = mbox_cmd_to_chan(mbox, msg.cmd);
+	if (chan)
+		mbox_chan_received_data(chan, &msg);
+	else
+		dev_err(mbox->mbox.dev, "Unexpected message: 0x%x:0x%x\n",
+			msg.cmd, msg.data);
+
+	return IRQ_HANDLED;
+}
+
+static struct of_device_id tegra_xusb_mbox_of_match[] = {
+	{ .compatible = "nvidia,tegra124-xusb-mbox" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, tegra_xusb_mbox_of_match);
+
+static int tegra_xusb_mbox_probe(struct platform_device *pdev)
+{
+	struct tegra_xusb_mbox *mbox;
+	struct resource *res;
+	int ret;
+
+	mbox = devm_kzalloc(&pdev->dev, sizeof(*mbox), GFP_KERNEL);
+	if (!mbox)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, mbox);
+	spin_lock_init(&mbox->lock);
+
+	mbox->mbox.dev = &pdev->dev;
+	mbox->mbox.chans = devm_kcalloc(&pdev->dev, TEGRA_XUSB_MBOX_NUM_CHANS,
+					sizeof(*mbox->mbox.chans), GFP_KERNEL);
+	if (!mbox->mbox.chans)
+		return -ENOMEM;
+	mbox->mbox.num_chans = TEGRA_XUSB_MBOX_NUM_CHANS;
+	mbox->mbox.ops = &tegra_xusb_mbox_chan_ops;
+	mbox->mbox.txdone_poll = true;
+	mbox->mbox.txpoll_period = 0; /* no need to actually poll */
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+	mbox->regs = devm_ioremap_nocache(&pdev->dev, res->start,
+					  resource_size(res));
+	if (!mbox->regs)
+		return -ENOMEM;
+
+	mbox->irq = platform_get_irq(pdev, 0);
+	if (mbox->irq < 0)
+		return mbox->irq;
+	ret = devm_request_irq(&pdev->dev, mbox->irq, tegra_xusb_mbox_irq, 0,
+			       dev_name(&pdev->dev), mbox);
+	if (ret < 0)
+		return ret;
+
+	ret = mbox_controller_register(&mbox->mbox);
+	if (ret < 0)
+		dev_err(&pdev->dev, "failed to register mailbox: %d\n", ret);
+
+	return ret;
+}
+
+static int tegra_xusb_mbox_remove(struct platform_device *pdev)
+{
+	struct tegra_xusb_mbox *mbox = platform_get_drvdata(pdev);
+
+	mbox_controller_unregister(&mbox->mbox);
+
+	return 0;
+}
+
+static struct platform_driver tegra_xusb_mbox_driver = {
+	.probe	= tegra_xusb_mbox_probe,
+	.remove	= tegra_xusb_mbox_remove,
+	.driver	= {
+		.name = "tegra-xusb-mbox",
+		.of_match_table = of_match_ptr(tegra_xusb_mbox_of_match),
+	},
+};
+module_platform_driver(tegra_xusb_mbox_driver);
+
+MODULE_AUTHOR("Andrew Bresticker <abrestic@chromium.org>");
+MODULE_DESCRIPTION("NVIDIA Tegra XUSB mailbox driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:tegra-xusb-mailbox");
diff --git a/include/soc/tegra/xusb.h b/include/soc/tegra/xusb.h
new file mode 100644
index 0000000..8efef8c
--- /dev/null
+++ b/include/soc/tegra/xusb.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2014 NVIDIA Corporation
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#ifndef __SOC_TEGRA_XUSB_H__
+#define __SOC_TEGRA_XUSB_H__
+
+#define TEGRA_XUSB_MBOX_NUM_CHANS 2 /* host + phy */
+
+/* Command requests from the firmware */
+enum tegra_xusb_mbox_cmd {
+	MBOX_CMD_MSG_ENABLED = 1,
+	MBOX_CMD_INC_FALC_CLOCK,
+	MBOX_CMD_DEC_FALC_CLOCK,
+	MBOX_CMD_INC_SSPI_CLOCK,
+	MBOX_CMD_DEC_SSPI_CLOCK,
+	MBOX_CMD_SET_BW, /* no ACK/NAK required */
+	MBOX_CMD_SET_SS_PWR_GATING,
+	MBOX_CMD_SET_SS_PWR_UNGATING,
+	MBOX_CMD_SAVE_DFE_CTLE_CTX,
+	MBOX_CMD_AIRPLANE_MODE_ENABLED, /* unused */
+	MBOX_CMD_AIRPLANE_MODE_DISABLED, /* unused */
+	MBOX_CMD_START_HSIC_IDLE,
+	MBOX_CMD_STOP_HSIC_IDLE,
+	MBOX_CMD_DBC_WAKE_STACK, /* unused */
+	MBOX_CMD_HSIC_PRETEND_CONNECT,
+
+	MBOX_CMD_MAX,
+
+	/* Response message to above commands */
+	MBOX_CMD_ACK = 128,
+	MBOX_CMD_NAK
+};
+
+struct tegra_xusb_mbox_msg {
+	u32 cmd;
+	u32 data;
+};
+
+#endif /* __SOC_TEGRA_XUSB_H__ */
-- 
2.1.0.rc2.206.gedb03e5


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

* [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-18 17:08   ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-18 17:08 UTC (permalink / raw)
  To: linux-arm-kernel

The Tegra xHCI controller's firmware communicates requests to the host
processor through a mailbox interface.  While there is only a single
communication channel, messages sent by the controller can be divided
into two groups: those intended for the PHY driver and those intended
for the host-controller driver.  This mailbox driver exposes the two
channels and routes incoming messages to the appropriate channel based
on the command encoded in the message.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
---
Changes from v1:
 - Converted to common mailbox framework.
 - Removed useless polling sequences in TX path.
 - Moved xusb include from linux/ to soc/tegra/
---
 drivers/mailbox/Kconfig              |   3 +
 drivers/mailbox/Makefile             |   2 +
 drivers/mailbox/tegra-xusb-mailbox.c | 279 +++++++++++++++++++++++++++++++++++
 include/soc/tegra/xusb.h             |  45 ++++++
 4 files changed, 329 insertions(+)
 create mode 100644 drivers/mailbox/tegra-xusb-mailbox.c
 create mode 100644 include/soc/tegra/xusb.h

diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index 9fd9c67..97369c2 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -33,4 +33,7 @@ config OMAP_MBOX_KFIFO_SIZE
 	  Specify the default size of mailbox's kfifo buffers (bytes).
 	  This can also be changed at runtime (via the mbox_kfifo_size
 	  module parameter).
+
+config TEGRA_XUSB_MBOX
+	def_bool y if ARCH_TEGRA
 endif
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index 94ed7ce..7f0af9c 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -5,3 +5,5 @@ obj-$(CONFIG_MAILBOX)		+= mailbox.o
 obj-$(CONFIG_PL320_MBOX)	+= pl320-ipc.o
 
 obj-$(CONFIG_OMAP2PLUS_MBOX)	+= omap-mailbox.o
+
+obj-$(CONFIG_TEGRA_XUSB_MBOX)	+= tegra-xusb-mailbox.o
diff --git a/drivers/mailbox/tegra-xusb-mailbox.c b/drivers/mailbox/tegra-xusb-mailbox.c
new file mode 100644
index 0000000..917d48e7
--- /dev/null
+++ b/drivers/mailbox/tegra-xusb-mailbox.c
@@ -0,0 +1,279 @@
+/*
+ * NVIDIA Tegra XUSB mailbox driver
+ *
+ * Copyright (C) 2014 NVIDIA Corporation
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mailbox_controller.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <soc/tegra/xusb.h>
+
+#include <dt-bindings/mailbox/tegra-xusb-mailbox.h>
+
+#define XUSB_CFG_ARU_MBOX_CMD			0xe4
+#define  MBOX_FALC_INT_EN			BIT(27)
+#define  MBOX_PME_INT_EN			BIT(28)
+#define  MBOX_SMI_INT_EN			BIT(29)
+#define  MBOX_XHCI_INT_EN			BIT(30)
+#define  MBOX_INT_EN				BIT(31)
+#define XUSB_CFG_ARU_MBOX_DATA_IN		0xe8
+#define  CMD_DATA_SHIFT				0
+#define  CMD_DATA_MASK				0xffffff
+#define  CMD_TYPE_SHIFT				24
+#define  CMD_TYPE_MASK				0xff
+#define XUSB_CFG_ARU_MBOX_DATA_OUT		0xec
+#define XUSB_CFG_ARU_MBOX_OWNER			0xf0
+#define  MBOX_OWNER_NONE			0
+#define  MBOX_OWNER_FW				1
+#define  MBOX_OWNER_SW				2
+#define XUSB_CFG_ARU_SMI_INTR			0x428
+#define  MBOX_SMI_INTR_FW_HANG			BIT(1)
+#define  MBOX_SMI_INTR_EN			BIT(3)
+
+#define XUSB_MBOX_IDLE_TIMEOUT		20
+#define XUSB_MBOX_ACQUIRE_TIMEOUT	10
+
+struct tegra_xusb_mbox {
+	struct mbox_controller mbox;
+	int irq;
+	void __iomem *regs;
+	spinlock_t lock;
+};
+
+static inline u32 mbox_readl(struct tegra_xusb_mbox *mbox, unsigned long offset)
+{
+	return readl(mbox->regs + offset);
+}
+
+static inline void mbox_writel(struct tegra_xusb_mbox *mbox, u32 val,
+			       unsigned long offset)
+{
+	writel(val, mbox->regs + offset);
+}
+
+static inline u32 mbox_pack_msg(struct tegra_xusb_mbox_msg *msg)
+{
+	u32 val;
+
+	val = (msg->cmd & CMD_TYPE_MASK) << CMD_TYPE_SHIFT;
+	val |= (msg->data & CMD_DATA_MASK) << CMD_DATA_SHIFT;
+
+	return val;
+}
+
+static inline void mbox_unpack_msg(u32 val, struct tegra_xusb_mbox_msg *msg)
+{
+	msg->cmd = (val >> CMD_TYPE_SHIFT) & CMD_TYPE_MASK;
+	msg->data = (val >> CMD_DATA_SHIFT) & CMD_DATA_MASK;
+}
+
+static struct mbox_chan *mbox_cmd_to_chan(struct tegra_xusb_mbox *mbox, u32 cmd)
+{
+	switch (cmd) {
+	case MBOX_CMD_INC_FALC_CLOCK:
+	case MBOX_CMD_DEC_FALC_CLOCK:
+	case MBOX_CMD_INC_SSPI_CLOCK:
+	case MBOX_CMD_DEC_SSPI_CLOCK:
+	case MBOX_CMD_SET_BW:
+		return &mbox->mbox.chans[TEGRA_XUSB_MBOX_CHAN_HOST];
+	case MBOX_CMD_SAVE_DFE_CTLE_CTX:
+	case MBOX_CMD_START_HSIC_IDLE:
+	case MBOX_CMD_STOP_HSIC_IDLE:
+		return &mbox->mbox.chans[TEGRA_XUSB_MBOX_CHAN_PHY];
+	default:
+		return NULL;
+	}
+}
+
+static int tegra_xusb_mbox_send_data(struct mbox_chan *chan, void *data)
+{
+	struct tegra_xusb_mbox *mbox = dev_get_drvdata(chan->mbox->dev);
+	struct tegra_xusb_mbox_msg *msg = data;
+	unsigned long flags;
+	u32 reg, owner;
+
+	dev_dbg(mbox->mbox.dev, "TX message 0x%x:0x%x\n", msg->cmd, msg->data);
+
+	/* ACK/NAK must be sent with the controller as the mailbox owner */
+	if (msg->cmd == MBOX_CMD_ACK || msg->cmd == MBOX_CMD_NAK)
+		owner = MBOX_OWNER_FW;
+	else
+		owner = MBOX_OWNER_SW;
+
+	spin_lock_irqsave(&mbox->lock, flags);
+
+	/* Acquire mailbox */
+	if (mbox_readl(mbox, XUSB_CFG_ARU_MBOX_OWNER) != MBOX_OWNER_NONE) {
+		dev_err(mbox->mbox.dev, "Mailbox not idle\n");
+		goto busy;
+	}
+	mbox_writel(mbox, owner, XUSB_CFG_ARU_MBOX_OWNER);
+	if (mbox_readl(mbox, XUSB_CFG_ARU_MBOX_OWNER) != owner) {
+		dev_err(mbox->mbox.dev, "Failed to acquire mailbox");
+		goto busy;
+	}
+
+	mbox_writel(mbox, mbox_pack_msg(msg), XUSB_CFG_ARU_MBOX_DATA_IN);
+	reg = mbox_readl(mbox, XUSB_CFG_ARU_MBOX_CMD);
+	reg |= MBOX_INT_EN | MBOX_FALC_INT_EN;
+	mbox_writel(mbox, reg, XUSB_CFG_ARU_MBOX_CMD);
+
+	spin_unlock_irqrestore(&mbox->lock, flags);
+
+	return 0;
+busy:
+	spin_unlock_irqrestore(&mbox->lock, flags);
+	return -EBUSY;
+}
+
+static int tegra_xusb_mbox_startup(struct mbox_chan *chan)
+{
+	return 0;
+}
+
+static void tegra_xusb_mbox_shutdown(struct mbox_chan *chan)
+{
+}
+
+static bool tegra_xusb_mbox_last_tx_done(struct mbox_chan *chan)
+{
+	/*
+	 * Transmissions are assumed to be completed as soon as they are
+	 * written to the mailbox.
+	 */
+	return true;
+}
+
+static struct mbox_chan_ops tegra_xusb_mbox_chan_ops = {
+	.send_data = tegra_xusb_mbox_send_data,
+	.startup = tegra_xusb_mbox_startup,
+	.shutdown = tegra_xusb_mbox_shutdown,
+	.last_tx_done = tegra_xusb_mbox_last_tx_done,
+};
+
+static irqreturn_t tegra_xusb_mbox_irq(int irq, void *p)
+{
+	struct tegra_xusb_mbox *mbox = (struct tegra_xusb_mbox *)p;
+	struct mbox_chan *chan;
+	struct tegra_xusb_mbox_msg msg;
+	u32 reg;
+
+	spin_lock(&mbox->lock);
+
+	/* Clear mbox interrupts */
+	reg = mbox_readl(mbox, XUSB_CFG_ARU_SMI_INTR);
+	if (reg & MBOX_SMI_INTR_FW_HANG)
+		dev_err(mbox->mbox.dev, "Controller firmware hang\n");
+	mbox_writel(mbox, reg, XUSB_CFG_ARU_SMI_INTR);
+
+	reg = mbox_readl(mbox, XUSB_CFG_ARU_MBOX_DATA_OUT);
+	mbox_unpack_msg(reg, &msg);
+
+	/*
+	 * Set the mailbox back to idle.  The recipient of the message is
+	 * responsible for sending an ACK/NAK, if necessary.
+	 */
+	reg = mbox_readl(mbox, XUSB_CFG_ARU_MBOX_CMD);
+	reg &= ~MBOX_SMI_INT_EN;
+	mbox_writel(mbox, reg, XUSB_CFG_ARU_MBOX_CMD);
+	mbox_writel(mbox, MBOX_OWNER_NONE, XUSB_CFG_ARU_MBOX_OWNER);
+
+	spin_unlock(&mbox->lock);
+
+	dev_dbg(mbox->mbox.dev, "RX message 0x%x:0x%x\n", msg.cmd, msg.data);
+	chan = mbox_cmd_to_chan(mbox, msg.cmd);
+	if (chan)
+		mbox_chan_received_data(chan, &msg);
+	else
+		dev_err(mbox->mbox.dev, "Unexpected message: 0x%x:0x%x\n",
+			msg.cmd, msg.data);
+
+	return IRQ_HANDLED;
+}
+
+static struct of_device_id tegra_xusb_mbox_of_match[] = {
+	{ .compatible = "nvidia,tegra124-xusb-mbox" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, tegra_xusb_mbox_of_match);
+
+static int tegra_xusb_mbox_probe(struct platform_device *pdev)
+{
+	struct tegra_xusb_mbox *mbox;
+	struct resource *res;
+	int ret;
+
+	mbox = devm_kzalloc(&pdev->dev, sizeof(*mbox), GFP_KERNEL);
+	if (!mbox)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, mbox);
+	spin_lock_init(&mbox->lock);
+
+	mbox->mbox.dev = &pdev->dev;
+	mbox->mbox.chans = devm_kcalloc(&pdev->dev, TEGRA_XUSB_MBOX_NUM_CHANS,
+					sizeof(*mbox->mbox.chans), GFP_KERNEL);
+	if (!mbox->mbox.chans)
+		return -ENOMEM;
+	mbox->mbox.num_chans = TEGRA_XUSB_MBOX_NUM_CHANS;
+	mbox->mbox.ops = &tegra_xusb_mbox_chan_ops;
+	mbox->mbox.txdone_poll = true;
+	mbox->mbox.txpoll_period = 0; /* no need to actually poll */
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+	mbox->regs = devm_ioremap_nocache(&pdev->dev, res->start,
+					  resource_size(res));
+	if (!mbox->regs)
+		return -ENOMEM;
+
+	mbox->irq = platform_get_irq(pdev, 0);
+	if (mbox->irq < 0)
+		return mbox->irq;
+	ret = devm_request_irq(&pdev->dev, mbox->irq, tegra_xusb_mbox_irq, 0,
+			       dev_name(&pdev->dev), mbox);
+	if (ret < 0)
+		return ret;
+
+	ret = mbox_controller_register(&mbox->mbox);
+	if (ret < 0)
+		dev_err(&pdev->dev, "failed to register mailbox: %d\n", ret);
+
+	return ret;
+}
+
+static int tegra_xusb_mbox_remove(struct platform_device *pdev)
+{
+	struct tegra_xusb_mbox *mbox = platform_get_drvdata(pdev);
+
+	mbox_controller_unregister(&mbox->mbox);
+
+	return 0;
+}
+
+static struct platform_driver tegra_xusb_mbox_driver = {
+	.probe	= tegra_xusb_mbox_probe,
+	.remove	= tegra_xusb_mbox_remove,
+	.driver	= {
+		.name = "tegra-xusb-mbox",
+		.of_match_table = of_match_ptr(tegra_xusb_mbox_of_match),
+	},
+};
+module_platform_driver(tegra_xusb_mbox_driver);
+
+MODULE_AUTHOR("Andrew Bresticker <abrestic@chromium.org>");
+MODULE_DESCRIPTION("NVIDIA Tegra XUSB mailbox driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:tegra-xusb-mailbox");
diff --git a/include/soc/tegra/xusb.h b/include/soc/tegra/xusb.h
new file mode 100644
index 0000000..8efef8c
--- /dev/null
+++ b/include/soc/tegra/xusb.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2014 NVIDIA Corporation
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#ifndef __SOC_TEGRA_XUSB_H__
+#define __SOC_TEGRA_XUSB_H__
+
+#define TEGRA_XUSB_MBOX_NUM_CHANS 2 /* host + phy */
+
+/* Command requests from the firmware */
+enum tegra_xusb_mbox_cmd {
+	MBOX_CMD_MSG_ENABLED = 1,
+	MBOX_CMD_INC_FALC_CLOCK,
+	MBOX_CMD_DEC_FALC_CLOCK,
+	MBOX_CMD_INC_SSPI_CLOCK,
+	MBOX_CMD_DEC_SSPI_CLOCK,
+	MBOX_CMD_SET_BW, /* no ACK/NAK required */
+	MBOX_CMD_SET_SS_PWR_GATING,
+	MBOX_CMD_SET_SS_PWR_UNGATING,
+	MBOX_CMD_SAVE_DFE_CTLE_CTX,
+	MBOX_CMD_AIRPLANE_MODE_ENABLED, /* unused */
+	MBOX_CMD_AIRPLANE_MODE_DISABLED, /* unused */
+	MBOX_CMD_START_HSIC_IDLE,
+	MBOX_CMD_STOP_HSIC_IDLE,
+	MBOX_CMD_DBC_WAKE_STACK, /* unused */
+	MBOX_CMD_HSIC_PRETEND_CONNECT,
+
+	MBOX_CMD_MAX,
+
+	/* Response message to above commands */
+	MBOX_CMD_ACK = 128,
+	MBOX_CMD_NAK
+};
+
+struct tegra_xusb_mbox_msg {
+	u32 cmd;
+	u32 data;
+};
+
+#endif /* __SOC_TEGRA_XUSB_H__ */
-- 
2.1.0.rc2.206.gedb03e5

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

* [PATCH v2 3/9] of: Update Tegra XUSB pad controller binding for USB
  2014-08-18 17:08 ` Andrew Bresticker
  (?)
@ 2014-08-18 17:08   ` Andrew Bresticker
  -1 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-18 17:08 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, linux-tegra
  Cc: Mark Rutland, devicetree, linux-usb, Russell King, Mathias Nyman,
	Pawel Moll, Ian Campbell, Andrew Bresticker, Greg Kroah-Hartman,
	Linus Walleij, Jassi Brar, linux-kernel, Kishon Vijay Abraham I,
	Rob Herring, Alan Stern, linux-arm-kernel, Kumar Gala,
	Grant Likely, Arnd Bergmann

Add new bindings used for USB support by the Tegra XUSB pad controller.
This includes additional PHY types, USB-specific pinconfig properties, etc.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
---
Changes from v1:
 - Updated to use common mailbox bindings.
 - Made USB3 port-to-lane mappins a top-level binding rather than a pinconfig
   binding.
 - Add #defines for the padctl lanes.
---
 .../pinctrl/nvidia,tegra124-xusb-padctl.txt        | 52 ++++++++++++++++++++--
 include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h   | 20 +++++++++
 2 files changed, 68 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt
index 2f9c0bd..606a5db 100644
--- a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt
@@ -21,6 +21,16 @@ Required properties:
   - padctl
 - #phy-cells: Should be 1. The specifier is the index of the PHY to reference.
   See <dt-bindings/pinctrl/pinctrl-tegra-xusb.h> for the list of valid values.
+- mboxes: Must contain an entry for the XUSB PHY mailbox channel.
+  See ../mailbox/mailbox.txt for details.
+
+Optional properties:
+-------------------
+- vbus-otg-{0,1,2}-supply: VBUS regulator for the corresponding UTMI pad.
+- vddio-hsic-supply: VDDIO regulator for the HSIC pads.
+- nvidia,usb3-port-{0,1}-lane: PCIe/SATA lane to which the corresponding USB3
+  port is mapped.  See <dt-bindings/pinctrl/pinctrl-tegra-xusb.h> for the list
+  of valid values.
 
 Lane muxing:
 ------------
@@ -50,6 +60,15 @@ Optional properties:
   pin or group should be assigned to. Valid values for function names are
   listed below.
 - nvidia,iddq: Enables IDDQ mode of the lane. (0: no, 1: yes)
+- nvidia,usb2-port-num: USB2 port (0, 1, or 2) to which the lane is mapped.
+- nvidia,hsic-strobe-trim: HSIC strobe trimmer value.
+- nvidia,hsic-rx-strobe-trim: HSIC RX strobe trimmer value.
+- nvidia,hsic-rx-data-trim: HSIC RX data trimmer value.
+- nvidia,hsic-tx-rtune-n: HSIC TX RTUNEN value.
+- nvidia,hsic-tx-rtune-p: HSIC TX RTUNEP value.
+- nvidia,hsic-tx-slew-n: HSIC TX SLEWN value.
+- nvidia,hsic-tx-slew-p: HSIC TX SLEWP value.
+- nvidia,hsic-auto-term: Enables HSIC AUTO_TERM. (0: no, 1: yes)
 
 Note that not all of these properties are valid for all lanes. Lanes can be
 divided into three groups:
@@ -58,18 +77,22 @@ divided into three groups:
 
     Valid functions for this group are: "snps", "xusb", "uart", "rsvd".
 
-    The nvidia,iddq property does not apply to this group.
+    None of the other properties apply to this group.
 
   - ulpi-0, hsic-0, hsic-1:
 
     Valid functions for this group are: "snps", "xusb".
 
-    The nvidia,iddq property does not apply to this group.
+    The nvidia,hsic-* properties apply only to the pins hsic-{0,1} when
+    the function is xusb.
 
   - pcie-0, pcie-1, pcie-2, pcie-3, pcie-4, sata-0:
 
     Valid functions for this group are: "pcie", "usb3", "sata", "rsvd".
 
+    The nvidia,usb2-port-num property only applies and is required when
+    the function is usb3.
+
 
 Example:
 ========
@@ -82,6 +105,7 @@ SoC file extract:
 		reg = <0x0 0x7009f000 0x0 0x1000>;
 		resets = <&tegra_car 142>;
 		reset-names = "padctl";
+		mboxes = <&mbox TEGRA_XUSB_MBOX_CHAN_PHY>;
 
 		#phy-cells = <1>;
 	};
@@ -100,15 +124,35 @@ Board file extract:
 
 	...
 
+	usb@0,70090000 {
+		...
+
+		phys = <&padctl 5>, <&padctl 6>, <&padctl 7>;
+		phy-names = "utmi-1", "utmi-2", "usb3-0";
+
+		...
+	}
+
+	...
+
 	padctl: padctl@0,7009f000 {
 		pinctrl-0 = <&padctl_default>;
 		pinctrl-names = "default";
 
+		nvidia,usb3-port-0-lane = <TEGRA_XUSB_PADCTL_PIN_PCIE_0>;
+		vbus-otg-2-supply = <&vdd_usb3_vbus>;
+
 		padctl_default: pinmux {
-			usb3 {
-				nvidia,lanes = "pcie-0", "pcie-1";
+			otg {
+				nvidia,lanes = "otg-1", "otg-2";
+				nvidia,function = "xusb";
+			};
+
+			usb3p0 {
+				nvidia,lanes = "pcie-0";
 				nvidia,function = "usb3";
 				nvidia,iddq = <0>;
+				nvidia,usb2-port-num = <2>;
 			};
 
 			pcie {
diff --git a/include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h b/include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h
index 914d56d..17b1aab 100644
--- a/include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h
+++ b/include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h
@@ -3,5 +3,25 @@
 
 #define TEGRA_XUSB_PADCTL_PCIE 0
 #define TEGRA_XUSB_PADCTL_SATA 1
+#define TEGRA_XUSB_PADCTL_USB3_P0 2
+#define TEGRA_XUSB_PADCTL_USB3_P1 3
+#define TEGRA_XUSB_PADCTL_UTMI_P0 4
+#define TEGRA_XUSB_PADCTL_UTMI_P1 5
+#define TEGRA_XUSB_PADCTL_UTMI_P2 6
+#define TEGRA_XUSB_PADCTL_HSIC_P0 7
+#define TEGRA_XUSB_PADCTL_HSIC_P1 8
+
+#define TEGRA_XUSB_PADCTL_PIN_OTG_0   0
+#define TEGRA_XUSB_PADCTL_PIN_OTG_1   1
+#define TEGRA_XUSB_PADCTL_PIN_OTG_2   2
+#define TEGRA_XUSB_PADCTL_PIN_ULPI_0  3
+#define TEGRA_XUSB_PADCTL_PIN_HSIC_0  4
+#define TEGRA_XUSB_PADCTL_PIN_HSIC_1  5
+#define TEGRA_XUSB_PADCTL_PIN_PCIE_0  6
+#define TEGRA_XUSB_PADCTL_PIN_PCIE_1  7
+#define TEGRA_XUSB_PADCTL_PIN_PCIE_2  8
+#define TEGRA_XUSB_PADCTL_PIN_PCIE_3  9
+#define TEGRA_XUSB_PADCTL_PIN_PCIE_4 10
+#define TEGRA_XUSB_PADCTL_PIN_SATA_0 11
 
 #endif /* _DT_BINDINGS_PINCTRL_TEGRA_XUSB_H */
-- 
2.1.0.rc2.206.gedb03e5

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

* [PATCH v2 3/9] of: Update Tegra XUSB pad controller binding for USB
@ 2014-08-18 17:08   ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-18 17:08 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, linux-tegra
  Cc: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Jassi Brar, Linus Walleij, Greg Kroah-Hartman,
	Mathias Nyman, Grant Likely, Alan Stern, Arnd Bergmann,
	Kishon Vijay Abraham I, devicetree, linux-kernel,
	linux-arm-kernel, linux-usb, Andrew Bresticker

Add new bindings used for USB support by the Tegra XUSB pad controller.
This includes additional PHY types, USB-specific pinconfig properties, etc.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
---
Changes from v1:
 - Updated to use common mailbox bindings.
 - Made USB3 port-to-lane mappins a top-level binding rather than a pinconfig
   binding.
 - Add #defines for the padctl lanes.
---
 .../pinctrl/nvidia,tegra124-xusb-padctl.txt        | 52 ++++++++++++++++++++--
 include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h   | 20 +++++++++
 2 files changed, 68 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt
index 2f9c0bd..606a5db 100644
--- a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt
@@ -21,6 +21,16 @@ Required properties:
   - padctl
 - #phy-cells: Should be 1. The specifier is the index of the PHY to reference.
   See <dt-bindings/pinctrl/pinctrl-tegra-xusb.h> for the list of valid values.
+- mboxes: Must contain an entry for the XUSB PHY mailbox channel.
+  See ../mailbox/mailbox.txt for details.
+
+Optional properties:
+-------------------
+- vbus-otg-{0,1,2}-supply: VBUS regulator for the corresponding UTMI pad.
+- vddio-hsic-supply: VDDIO regulator for the HSIC pads.
+- nvidia,usb3-port-{0,1}-lane: PCIe/SATA lane to which the corresponding USB3
+  port is mapped.  See <dt-bindings/pinctrl/pinctrl-tegra-xusb.h> for the list
+  of valid values.
 
 Lane muxing:
 ------------
@@ -50,6 +60,15 @@ Optional properties:
   pin or group should be assigned to. Valid values for function names are
   listed below.
 - nvidia,iddq: Enables IDDQ mode of the lane. (0: no, 1: yes)
+- nvidia,usb2-port-num: USB2 port (0, 1, or 2) to which the lane is mapped.
+- nvidia,hsic-strobe-trim: HSIC strobe trimmer value.
+- nvidia,hsic-rx-strobe-trim: HSIC RX strobe trimmer value.
+- nvidia,hsic-rx-data-trim: HSIC RX data trimmer value.
+- nvidia,hsic-tx-rtune-n: HSIC TX RTUNEN value.
+- nvidia,hsic-tx-rtune-p: HSIC TX RTUNEP value.
+- nvidia,hsic-tx-slew-n: HSIC TX SLEWN value.
+- nvidia,hsic-tx-slew-p: HSIC TX SLEWP value.
+- nvidia,hsic-auto-term: Enables HSIC AUTO_TERM. (0: no, 1: yes)
 
 Note that not all of these properties are valid for all lanes. Lanes can be
 divided into three groups:
@@ -58,18 +77,22 @@ divided into three groups:
 
     Valid functions for this group are: "snps", "xusb", "uart", "rsvd".
 
-    The nvidia,iddq property does not apply to this group.
+    None of the other properties apply to this group.
 
   - ulpi-0, hsic-0, hsic-1:
 
     Valid functions for this group are: "snps", "xusb".
 
-    The nvidia,iddq property does not apply to this group.
+    The nvidia,hsic-* properties apply only to the pins hsic-{0,1} when
+    the function is xusb.
 
   - pcie-0, pcie-1, pcie-2, pcie-3, pcie-4, sata-0:
 
     Valid functions for this group are: "pcie", "usb3", "sata", "rsvd".
 
+    The nvidia,usb2-port-num property only applies and is required when
+    the function is usb3.
+
 
 Example:
 ========
@@ -82,6 +105,7 @@ SoC file extract:
 		reg = <0x0 0x7009f000 0x0 0x1000>;
 		resets = <&tegra_car 142>;
 		reset-names = "padctl";
+		mboxes = <&mbox TEGRA_XUSB_MBOX_CHAN_PHY>;
 
 		#phy-cells = <1>;
 	};
@@ -100,15 +124,35 @@ Board file extract:
 
 	...
 
+	usb@0,70090000 {
+		...
+
+		phys = <&padctl 5>, <&padctl 6>, <&padctl 7>;
+		phy-names = "utmi-1", "utmi-2", "usb3-0";
+
+		...
+	}
+
+	...
+
 	padctl: padctl@0,7009f000 {
 		pinctrl-0 = <&padctl_default>;
 		pinctrl-names = "default";
 
+		nvidia,usb3-port-0-lane = <TEGRA_XUSB_PADCTL_PIN_PCIE_0>;
+		vbus-otg-2-supply = <&vdd_usb3_vbus>;
+
 		padctl_default: pinmux {
-			usb3 {
-				nvidia,lanes = "pcie-0", "pcie-1";
+			otg {
+				nvidia,lanes = "otg-1", "otg-2";
+				nvidia,function = "xusb";
+			};
+
+			usb3p0 {
+				nvidia,lanes = "pcie-0";
 				nvidia,function = "usb3";
 				nvidia,iddq = <0>;
+				nvidia,usb2-port-num = <2>;
 			};
 
 			pcie {
diff --git a/include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h b/include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h
index 914d56d..17b1aab 100644
--- a/include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h
+++ b/include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h
@@ -3,5 +3,25 @@
 
 #define TEGRA_XUSB_PADCTL_PCIE 0
 #define TEGRA_XUSB_PADCTL_SATA 1
+#define TEGRA_XUSB_PADCTL_USB3_P0 2
+#define TEGRA_XUSB_PADCTL_USB3_P1 3
+#define TEGRA_XUSB_PADCTL_UTMI_P0 4
+#define TEGRA_XUSB_PADCTL_UTMI_P1 5
+#define TEGRA_XUSB_PADCTL_UTMI_P2 6
+#define TEGRA_XUSB_PADCTL_HSIC_P0 7
+#define TEGRA_XUSB_PADCTL_HSIC_P1 8
+
+#define TEGRA_XUSB_PADCTL_PIN_OTG_0   0
+#define TEGRA_XUSB_PADCTL_PIN_OTG_1   1
+#define TEGRA_XUSB_PADCTL_PIN_OTG_2   2
+#define TEGRA_XUSB_PADCTL_PIN_ULPI_0  3
+#define TEGRA_XUSB_PADCTL_PIN_HSIC_0  4
+#define TEGRA_XUSB_PADCTL_PIN_HSIC_1  5
+#define TEGRA_XUSB_PADCTL_PIN_PCIE_0  6
+#define TEGRA_XUSB_PADCTL_PIN_PCIE_1  7
+#define TEGRA_XUSB_PADCTL_PIN_PCIE_2  8
+#define TEGRA_XUSB_PADCTL_PIN_PCIE_3  9
+#define TEGRA_XUSB_PADCTL_PIN_PCIE_4 10
+#define TEGRA_XUSB_PADCTL_PIN_SATA_0 11
 
 #endif /* _DT_BINDINGS_PINCTRL_TEGRA_XUSB_H */
-- 
2.1.0.rc2.206.gedb03e5


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

* [PATCH v2 3/9] of: Update Tegra XUSB pad controller binding for USB
@ 2014-08-18 17:08   ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-18 17:08 UTC (permalink / raw)
  To: linux-arm-kernel

Add new bindings used for USB support by the Tegra XUSB pad controller.
This includes additional PHY types, USB-specific pinconfig properties, etc.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
---
Changes from v1:
 - Updated to use common mailbox bindings.
 - Made USB3 port-to-lane mappins a top-level binding rather than a pinconfig
   binding.
 - Add #defines for the padctl lanes.
---
 .../pinctrl/nvidia,tegra124-xusb-padctl.txt        | 52 ++++++++++++++++++++--
 include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h   | 20 +++++++++
 2 files changed, 68 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt
index 2f9c0bd..606a5db 100644
--- a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt
@@ -21,6 +21,16 @@ Required properties:
   - padctl
 - #phy-cells: Should be 1. The specifier is the index of the PHY to reference.
   See <dt-bindings/pinctrl/pinctrl-tegra-xusb.h> for the list of valid values.
+- mboxes: Must contain an entry for the XUSB PHY mailbox channel.
+  See ../mailbox/mailbox.txt for details.
+
+Optional properties:
+-------------------
+- vbus-otg-{0,1,2}-supply: VBUS regulator for the corresponding UTMI pad.
+- vddio-hsic-supply: VDDIO regulator for the HSIC pads.
+- nvidia,usb3-port-{0,1}-lane: PCIe/SATA lane to which the corresponding USB3
+  port is mapped.  See <dt-bindings/pinctrl/pinctrl-tegra-xusb.h> for the list
+  of valid values.
 
 Lane muxing:
 ------------
@@ -50,6 +60,15 @@ Optional properties:
   pin or group should be assigned to. Valid values for function names are
   listed below.
 - nvidia,iddq: Enables IDDQ mode of the lane. (0: no, 1: yes)
+- nvidia,usb2-port-num: USB2 port (0, 1, or 2) to which the lane is mapped.
+- nvidia,hsic-strobe-trim: HSIC strobe trimmer value.
+- nvidia,hsic-rx-strobe-trim: HSIC RX strobe trimmer value.
+- nvidia,hsic-rx-data-trim: HSIC RX data trimmer value.
+- nvidia,hsic-tx-rtune-n: HSIC TX RTUNEN value.
+- nvidia,hsic-tx-rtune-p: HSIC TX RTUNEP value.
+- nvidia,hsic-tx-slew-n: HSIC TX SLEWN value.
+- nvidia,hsic-tx-slew-p: HSIC TX SLEWP value.
+- nvidia,hsic-auto-term: Enables HSIC AUTO_TERM. (0: no, 1: yes)
 
 Note that not all of these properties are valid for all lanes. Lanes can be
 divided into three groups:
@@ -58,18 +77,22 @@ divided into three groups:
 
     Valid functions for this group are: "snps", "xusb", "uart", "rsvd".
 
-    The nvidia,iddq property does not apply to this group.
+    None of the other properties apply to this group.
 
   - ulpi-0, hsic-0, hsic-1:
 
     Valid functions for this group are: "snps", "xusb".
 
-    The nvidia,iddq property does not apply to this group.
+    The nvidia,hsic-* properties apply only to the pins hsic-{0,1} when
+    the function is xusb.
 
   - pcie-0, pcie-1, pcie-2, pcie-3, pcie-4, sata-0:
 
     Valid functions for this group are: "pcie", "usb3", "sata", "rsvd".
 
+    The nvidia,usb2-port-num property only applies and is required when
+    the function is usb3.
+
 
 Example:
 ========
@@ -82,6 +105,7 @@ SoC file extract:
 		reg = <0x0 0x7009f000 0x0 0x1000>;
 		resets = <&tegra_car 142>;
 		reset-names = "padctl";
+		mboxes = <&mbox TEGRA_XUSB_MBOX_CHAN_PHY>;
 
 		#phy-cells = <1>;
 	};
@@ -100,15 +124,35 @@ Board file extract:
 
 	...
 
+	usb at 0,70090000 {
+		...
+
+		phys = <&padctl 5>, <&padctl 6>, <&padctl 7>;
+		phy-names = "utmi-1", "utmi-2", "usb3-0";
+
+		...
+	}
+
+	...
+
 	padctl: padctl at 0,7009f000 {
 		pinctrl-0 = <&padctl_default>;
 		pinctrl-names = "default";
 
+		nvidia,usb3-port-0-lane = <TEGRA_XUSB_PADCTL_PIN_PCIE_0>;
+		vbus-otg-2-supply = <&vdd_usb3_vbus>;
+
 		padctl_default: pinmux {
-			usb3 {
-				nvidia,lanes = "pcie-0", "pcie-1";
+			otg {
+				nvidia,lanes = "otg-1", "otg-2";
+				nvidia,function = "xusb";
+			};
+
+			usb3p0 {
+				nvidia,lanes = "pcie-0";
 				nvidia,function = "usb3";
 				nvidia,iddq = <0>;
+				nvidia,usb2-port-num = <2>;
 			};
 
 			pcie {
diff --git a/include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h b/include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h
index 914d56d..17b1aab 100644
--- a/include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h
+++ b/include/dt-bindings/pinctrl/pinctrl-tegra-xusb.h
@@ -3,5 +3,25 @@
 
 #define TEGRA_XUSB_PADCTL_PCIE 0
 #define TEGRA_XUSB_PADCTL_SATA 1
+#define TEGRA_XUSB_PADCTL_USB3_P0 2
+#define TEGRA_XUSB_PADCTL_USB3_P1 3
+#define TEGRA_XUSB_PADCTL_UTMI_P0 4
+#define TEGRA_XUSB_PADCTL_UTMI_P1 5
+#define TEGRA_XUSB_PADCTL_UTMI_P2 6
+#define TEGRA_XUSB_PADCTL_HSIC_P0 7
+#define TEGRA_XUSB_PADCTL_HSIC_P1 8
+
+#define TEGRA_XUSB_PADCTL_PIN_OTG_0   0
+#define TEGRA_XUSB_PADCTL_PIN_OTG_1   1
+#define TEGRA_XUSB_PADCTL_PIN_OTG_2   2
+#define TEGRA_XUSB_PADCTL_PIN_ULPI_0  3
+#define TEGRA_XUSB_PADCTL_PIN_HSIC_0  4
+#define TEGRA_XUSB_PADCTL_PIN_HSIC_1  5
+#define TEGRA_XUSB_PADCTL_PIN_PCIE_0  6
+#define TEGRA_XUSB_PADCTL_PIN_PCIE_1  7
+#define TEGRA_XUSB_PADCTL_PIN_PCIE_2  8
+#define TEGRA_XUSB_PADCTL_PIN_PCIE_3  9
+#define TEGRA_XUSB_PADCTL_PIN_PCIE_4 10
+#define TEGRA_XUSB_PADCTL_PIN_SATA_0 11
 
 #endif /* _DT_BINDINGS_PINCTRL_TEGRA_XUSB_H */
-- 
2.1.0.rc2.206.gedb03e5

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

* [PATCH v2 4/9] pinctrl: tegra-xusb: Add USB PHY support
  2014-08-18 17:08 ` Andrew Bresticker
@ 2014-08-18 17:08   ` Andrew Bresticker
  -1 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-18 17:08 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, linux-tegra
  Cc: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Jassi Brar, Linus Walleij, Greg Kroah-Hartman,
	Mathias Nyman, Grant Likely, Alan Stern, Arnd Bergmann,
	Kishon Vijay Abraham I, devicetree, linux-kernel,
	linux-arm-kernel, linux-usb, Andrew Bresticker

In addition to the PCIe and SATA PHYs, the XUSB pad controller also
supports 3 UTMI, 2 HSIC, and 2 USB3 PHYs.  Each USB3 PHY uses a single
PCIe or SATA lane and is mapped to one of the three UTMI ports.

The xHCI controller will also send messages intended for the PHY driver,
so request and listen for messages on the mailbox's PHY channel.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
---
Changes from v1:
 - Updated to use common mailbox API.
 - Added SATA PHY enable sequence for USB3 ports using the SATA lane.
 - Made USB3 port-to-lane mappins a top-level binding rather than a pinconfig
   binding.
---
 drivers/pinctrl/Kconfig              |    1 +
 drivers/pinctrl/pinctrl-tegra-xusb.c | 1170 +++++++++++++++++++++++++++++++++-
 include/soc/tegra/xusb.h             |    7 +
 3 files changed, 1150 insertions(+), 28 deletions(-)

diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index bfd2c2e..d5bc4f5 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -265,6 +265,7 @@ config PINCTRL_TEGRA_XUSB
 	select GENERIC_PHY
 	select PINCONF
 	select PINMUX
+	select MAILBOX
 
 config PINCTRL_TZ1090
 	bool "Toumaz Xenif TZ1090 pin control driver"
diff --git a/drivers/pinctrl/pinctrl-tegra-xusb.c b/drivers/pinctrl/pinctrl-tegra-xusb.c
index a066204..1091ce7 100644
--- a/drivers/pinctrl/pinctrl-tegra-xusb.c
+++ b/drivers/pinctrl/pinctrl-tegra-xusb.c
@@ -13,23 +13,53 @@
 
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/mailbox_client.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/phy/phy.h>
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/pinctrl/pinmux.h>
 #include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
 #include <linux/reset.h>
 
+#include <soc/tegra/fuse.h>
+#include <soc/tegra/xusb.h>
+
 #include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
 
 #include "core.h"
 #include "pinctrl-utils.h"
 
+#define FUSE_SKU_CALIB_HS_CURR_LEVEL_PADX_SHIFT(x) ((x) ? 15 : 0)
+#define FUSE_SKU_CALIB_HS_CURR_LEVEL_PAD_MASK 0x3f
+#define FUSE_SKU_CALIB_HS_IREF_CAP_SHIFT 13
+#define FUSE_SKU_CALIB_HS_IREF_CAP_MASK 0x3
+#define FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_SHIFT 11
+#define FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_MASK 0x3
+#define FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_SHIFT 7
+#define FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_MASK 0xf
+
+#define XUSB_PADCTL_USB2_PORT_CAP 0x008
+#define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_SHIFT(x) ((x) * 4)
+#define XUSB_PADCTL_USB2_PORT_CAP_PORT_CAP_MASK 0x3
+#define XUSB_PADCTL_USB2_PORT_CAP_DISABLED 0x0
+#define XUSB_PADCTL_USB2_PORT_CAP_HOST 0x1
+#define XUSB_PADCTL_USB2_PORT_CAP_DEVICE 0x2
+#define XUSB_PADCTL_USB2_PORT_CAP_OTG 0x3
+
+#define XUSB_PADCTL_SS_PORT_MAP 0x014
+#define XUSB_PADCTL_SS_PORT_MAP_PORTX_SHIFT(x) ((x) * 4)
+#define XUSB_PADCTL_SS_PORT_MAP_PORT_MASK 0x7
+
 #define XUSB_PADCTL_ELPG_PROGRAM 0x01c
 #define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26)
 #define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25)
 #define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24)
+#define XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_VCORE_DOWN(x) (1 << (18 + (x) * 4))
+#define XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN_EARLY(x) \
+							(1 << (17 + (x) * 4))
+#define XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN(x) (1 << (16 + (x) * 4))
 
 #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x040
 #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19)
@@ -41,17 +71,136 @@
 #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5)
 #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4)
 
+#define XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(x) (0x058 + (x) * 4)
+#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_SHIFT 24
+#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_MASK 0xff
+#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT 16
+#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_MASK 0x3f
+#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT 8
+#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_MASK 0x3f
+#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_SHIFT 8
+#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_MASK 0xffff
+#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_SHIFT 4
+#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_MASK 0x7
+
+#define XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(x) (0x068 + (x) * 4)
+#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT 24
+#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_MASK 0x1f
+#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT 16
+#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_MASK 0x7f
+
+#define XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL2(x) ((x) < 2 ? 0x078 + (x) * 4 : \
+					       0x0f8 + (x) * 4)
+#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_SHIFT 28
+#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_MASK 0x3
+
+#define XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL5(x) ((x) < 2 ? 0x090 + (x) * 4 : \
+					       0x11c + (x) * 4)
+#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL5_RX_QEYE_EN (1 << 8)
+
+#define XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL6(x) ((x) < 2 ? 0x098 + (x) * 4 : \
+					       0x128 + (x) * 4)
+#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT 24
+#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_G_Z_MASK 0x3f
+#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_TAP_MASK 0x1f
+#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_AMP_MASK 0x7f
+#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT 16
+#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK 0xff
+#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_G_Z 0x21
+#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_TAP 0x32
+#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_AMP 0x33
+#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_CTLE_Z 0x48
+#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_LATCH_G_Z 0xa1
+
+#define XUSB_PADCTL_USB2_OTG_PADX_CTL0(x) (0x0a0 + (x) * 4)
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI (1 << 21)
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 (1 << 20)
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD (1 << 19)
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_SHIFT 14
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_MASK 0x3
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_SHIFT 6
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_MASK 0x3f
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT 0
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK 0x3f
+
+#define XUSB_PADCTL_USB2_OTG_PADX_CTL1(x) (0x0ac + (x) * 4)
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_SHIFT 9
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_MASK 0x3
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT 3
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_MASK 0x7
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR (1 << 2)
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_FORCE_POWERUP (1 << 1)
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_FORCE_POWERUP (1 << 0)
+
+#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0 0x0b8
+#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD (1 << 12)
+#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT 2
+#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_MASK 0x7
+#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT 0
+#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_MASK 0x3
+
+#define XUSB_PADCTL_HSIC_PADX_CTL0(x) (0x0c0 + (x) * 4)
+#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_SHIFT 12
+#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_MASK 0x7
+#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_SHIFT 8
+#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_MASK 0x7
+#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_SHIFT 4
+#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_MASK 0x7
+#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_SHIFT 0
+#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_MASK 0x7
+
+#define XUSB_PADCTL_HSIC_PADX_CTL1(x) (0x0c8 + (x) * 4)
+#define XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE (1 << 10)
+#define XUSB_PADCTL_HSIC_PAD_CTL1_RPU_DATA (1 << 9)
+#define XUSB_PADCTL_HSIC_PAD_CTL1_RPD_STROBE (1 << 8)
+#define XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA (1 << 7)
+#define XUSB_PADCTL_HSIC_PAD_CTL1_PD_ZI (1 << 5)
+#define XUSB_PADCTL_HSIC_PAD_CTL1_PD_RX (1 << 4)
+#define XUSB_PADCTL_HSIC_PAD_CTL1_PD_TRX (1 << 3)
+#define XUSB_PADCTL_HSIC_PAD_CTL1_PD_TX (1 << 2)
+#define XUSB_PADCTL_HSIC_PAD_CTL1_AUTO_TERM_EN (1 << 0)
+
+#define XUSB_PADCTL_HSIC_PADX_CTL2(x) (0x0d0 + (x) * 4)
+#define XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT 4
+#define XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_MASK 0x7
+#define XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT 0
+#define XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_MASK 0x7
+
+#define XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL 0x0e0
+#define XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL_STRB_TRIM_MASK 0x1f
+
 #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138
 #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27)
 #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24)
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_SHIFT 20
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_MASK 0x3
 #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD (1 << 3)
 #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST (1 << 1)
 #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ (1 << 0)
 
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2 0x13c
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_SHIFT 20
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_MASK 0xf
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_SHIFT 16
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_MASK 0xf
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TCLKOUT_EN (1 << 12)
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TXCLKREF_SEL (1 << 4)
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_SHIFT 0
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_MASK 0x7
+
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL3 0x140
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL3_RCAL_BYPASS (1 << 7)
+
 #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1 0x148
 #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD (1 << 1)
 #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ (1 << 0)
 
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL2 0x14c
+
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL5 0x158
+
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL6 0x15c
+
 struct tegra_xusb_padctl_function {
 	const char *name;
 	const char * const *groups;
@@ -72,6 +221,16 @@ struct tegra_xusb_padctl_soc {
 
 	const struct tegra_xusb_padctl_lane *lanes;
 	unsigned int num_lanes;
+
+	u32 rx_wander;
+	u32 rx_eq;
+	u32 cdr_cntl;
+	u32 dfe_cntl;
+	u32 hs_slew;
+	u32 ls_rslew[TEGRA_XUSB_UTMI_PHYS];
+	u32 hs_discon_level;
+	u32 spare_in;
+	int hsic_port_offset;
 };
 
 struct tegra_xusb_padctl_lane {
@@ -86,6 +245,22 @@ struct tegra_xusb_padctl_lane {
 	unsigned int num_funcs;
 };
 
+struct tegra_xusb_fuse_calibration {
+	u32 hs_curr_level[TEGRA_XUSB_UTMI_PHYS];
+	u32 hs_iref_cap;
+	u32 hs_term_range_adj;
+	u32 hs_squelch_level;
+};
+
+struct tegra_xusb_usb3_port {
+	int lane;
+	bool context_saved;
+	u32 tap1_val;
+	u32 amp_val;
+	u32 ctle_z_val;
+	u32 ctle_g_val;
+};
+
 struct tegra_xusb_padctl {
 	struct device *dev;
 	void __iomem *regs;
@@ -93,13 +268,22 @@ struct tegra_xusb_padctl {
 	struct reset_control *rst;
 
 	const struct tegra_xusb_padctl_soc *soc;
+	struct tegra_xusb_fuse_calibration calib;
 	struct pinctrl_dev *pinctrl;
 	struct pinctrl_desc desc;
 
 	struct phy_provider *provider;
-	struct phy *phys[2];
+	struct phy *phys[TEGRA_XUSB_NUM_PHYS];
 
 	unsigned int enable;
+
+	struct mbox_client mbox_client;
+	struct mbox_chan *mbox_chan;
+
+	struct tegra_xusb_usb3_port usb3_ports[TEGRA_XUSB_USB3_PHYS];
+	unsigned int utmi_enable;
+	struct regulator *vbus[TEGRA_XUSB_UTMI_PHYS];
+	struct regulator *vddio_hsic;
 };
 
 static inline void padctl_writel(struct tegra_xusb_padctl *padctl, u32 value,
@@ -114,6 +298,31 @@ static inline u32 padctl_readl(struct tegra_xusb_padctl *padctl,
 	return readl(padctl->regs + offset);
 }
 
+static inline bool is_hsic_lane(unsigned int lane)
+{
+	return lane >= TEGRA_XUSB_PADCTL_PIN_HSIC_0 &&
+		lane <= TEGRA_XUSB_PADCTL_PIN_HSIC_1;
+}
+
+static inline bool is_pcie_or_sata_lane(unsigned int lane)
+{
+	return lane >= TEGRA_XUSB_PADCTL_PIN_PCIE_0 &&
+		lane <= TEGRA_XUSB_PADCTL_PIN_SATA_0;
+}
+
+static int lane_to_usb3_port(struct tegra_xusb_padctl *padctl,
+			     unsigned int lane)
+{
+	int i;
+
+	for (i = 0; i < TEGRA_XUSB_USB3_PHYS; i++) {
+		if (padctl->usb3_ports[i].lane == lane)
+			return i;
+	}
+
+	return -1;
+}
+
 static int tegra_xusb_padctl_get_groups_count(struct pinctrl_dev *pinctrl)
 {
 	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
@@ -131,6 +340,15 @@ static const char *tegra_xusb_padctl_get_group_name(struct pinctrl_dev *pinctrl,
 
 enum tegra_xusb_padctl_param {
 	TEGRA_XUSB_PADCTL_IDDQ,
+	TEGRA_XUSB_PADCTL_USB2_PORT_NUM,
+	TEGRA_XUSB_PADCTL_HSIC_STROBE_TRIM,
+	TEGRA_XUSB_PADCTL_HSIC_RX_STROBE_TRIM,
+	TEGRA_XUSB_PADCTL_HSIC_RX_DATA_TRIM,
+	TEGRA_XUSB_PADCTL_HSIC_TX_RTUNEN,
+	TEGRA_XUSB_PADCTL_HSIC_TX_RTUNEP,
+	TEGRA_XUSB_PADCTL_HSIC_TX_RSLEWN,
+	TEGRA_XUSB_PADCTL_HSIC_TX_RSLEWP,
+	TEGRA_XUSB_PADCTL_HSIC_AUTO_TERM,
 };
 
 static const struct tegra_xusb_padctl_property {
@@ -138,6 +356,15 @@ static const struct tegra_xusb_padctl_property {
 	enum tegra_xusb_padctl_param param;
 } properties[] = {
 	{ "nvidia,iddq", TEGRA_XUSB_PADCTL_IDDQ },
+	{ "nvidia,usb2-port-num", TEGRA_XUSB_PADCTL_USB2_PORT_NUM },
+	{ "nvidia,hsic-strobe-trim", TEGRA_XUSB_PADCTL_HSIC_STROBE_TRIM },
+	{ "nvidia,hsic-rx-strobe-trim", TEGRA_XUSB_PADCTL_HSIC_RX_STROBE_TRIM },
+	{ "nvidia,hsic-rx-data-trim", TEGRA_XUSB_PADCTL_HSIC_RX_DATA_TRIM },
+	{ "nvidia,hsic-tx-rtune-n", TEGRA_XUSB_PADCTL_HSIC_TX_RTUNEN },
+	{ "nvidia,hsic-tx-rtune-p", TEGRA_XUSB_PADCTL_HSIC_TX_RTUNEP },
+	{ "nvidia,hsic-tx-rslew-n", TEGRA_XUSB_PADCTL_HSIC_TX_RSLEWN },
+	{ "nvidia,hsic-tx-rslew-p", TEGRA_XUSB_PADCTL_HSIC_TX_RSLEWP },
+	{ "nvidia,hsic-auto-term", TEGRA_XUSB_PADCTL_HSIC_AUTO_TERM },
 };
 
 #define TEGRA_XUSB_PADCTL_PACK(param, value) ((param) << 16 | (value))
@@ -321,6 +548,7 @@ static int tegra_xusb_padctl_pinconf_group_get(struct pinctrl_dev *pinctrl,
 	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
 	const struct tegra_xusb_padctl_lane *lane;
 	enum tegra_xusb_padctl_param param;
+	int port;
 	u32 value;
 
 	param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(*config);
@@ -338,8 +566,116 @@ static int tegra_xusb_padctl_pinconf_group_get(struct pinctrl_dev *pinctrl,
 			value = 0;
 		else
 			value = 1;
+		break;
 
-		*config = TEGRA_XUSB_PADCTL_PACK(param, value);
+	case TEGRA_XUSB_PADCTL_USB2_PORT_NUM:
+		port = lane_to_usb3_port(padctl, group);
+		if (port < 0) {
+			dev_err(padctl->dev,
+				"Pin %d not mapped to USB3 port\n", group);
+			return -EINVAL;
+		}
+
+		value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP) >>
+			XUSB_PADCTL_SS_PORT_MAP_PORTX_SHIFT(port);
+		value &= XUSB_PADCTL_SS_PORT_MAP_PORT_MASK;
+		break;
+
+	case TEGRA_XUSB_PADCTL_HSIC_STROBE_TRIM:
+		if (!is_hsic_lane(group)) {
+			dev_err(padctl->dev, "Pin %d not an HSIC\n", group);
+			return -EINVAL;
+		}
+
+		value = padctl_readl(padctl,
+				     XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL);
+		value &= XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL_STRB_TRIM_MASK;
+		break;
+
+	case TEGRA_XUSB_PADCTL_HSIC_RX_STROBE_TRIM:
+		if (!is_hsic_lane(group)) {
+			dev_err(padctl->dev, "Pin %d not an HSIC\n", group);
+			return -EINVAL;
+		}
+
+		port = group - TEGRA_XUSB_PADCTL_PIN_HSIC_0;
+		value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL2(port)) >>
+			XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT;
+		value &= XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_MASK;
+		break;
+
+	case TEGRA_XUSB_PADCTL_HSIC_RX_DATA_TRIM:
+		if (!is_hsic_lane(group)) {
+			dev_err(padctl->dev, "Pin %d not an HSIC\n", group);
+			return -EINVAL;
+		}
+
+		port = group - TEGRA_XUSB_PADCTL_PIN_HSIC_0;
+		value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL2(port)) >>
+			XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT;
+		value &= XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_MASK;
+		break;
+
+	case TEGRA_XUSB_PADCTL_HSIC_TX_RTUNEN:
+		if (!is_hsic_lane(group)) {
+			dev_err(padctl->dev, "Pin %d not an HSIC\n", group);
+			return -EINVAL;
+		}
+
+		port = group - TEGRA_XUSB_PADCTL_PIN_HSIC_0;
+		value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL0(port)) >>
+			XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_SHIFT;
+		value &= XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_MASK;
+		break;
+
+	case TEGRA_XUSB_PADCTL_HSIC_TX_RTUNEP:
+		if (!is_hsic_lane(group)) {
+			dev_err(padctl->dev, "Pin %d not an HSIC\n", group);
+			return -EINVAL;
+		}
+
+		port = group - TEGRA_XUSB_PADCTL_PIN_HSIC_0;
+		value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL0(port)) >>
+			XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_SHIFT;
+		value &= XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_MASK;
+		break;
+
+	case TEGRA_XUSB_PADCTL_HSIC_TX_RSLEWN:
+		if (!is_hsic_lane(group)) {
+			dev_err(padctl->dev, "Pin %d not an HSIC\n", group);
+			return -EINVAL;
+		}
+
+		port = group - TEGRA_XUSB_PADCTL_PIN_HSIC_0;
+		value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL0(port)) >>
+			XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_SHIFT;
+		value &= XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_MASK;
+		break;
+
+	case TEGRA_XUSB_PADCTL_HSIC_TX_RSLEWP:
+		if (!is_hsic_lane(group)) {
+			dev_err(padctl->dev, "Pin %d not an HSIC\n", group);
+			return -EINVAL;
+		}
+
+		port = group - TEGRA_XUSB_PADCTL_PIN_HSIC_0;
+		value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL0(port)) >>
+			XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_SHIFT;
+		value &= XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_MASK;
+		break;
+
+	case TEGRA_XUSB_PADCTL_HSIC_AUTO_TERM:
+		if (!is_hsic_lane(group)) {
+			dev_err(padctl->dev, "Pin %d not an HSIC\n", group);
+			return -EINVAL;
+		}
+
+		port = group - TEGRA_XUSB_PADCTL_PIN_HSIC_0;
+		value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(port));
+		if (value & XUSB_PADCTL_HSIC_PAD_CTL1_AUTO_TERM_EN)
+			value = 1;
+		else
+			value = 0;
 		break;
 
 	default:
@@ -348,6 +684,7 @@ static int tegra_xusb_padctl_pinconf_group_get(struct pinctrl_dev *pinctrl,
 		return -ENOTSUPP;
 	}
 
+	*config = TEGRA_XUSB_PADCTL_PACK(param, value);
 	return 0;
 }
 
@@ -362,6 +699,7 @@ static int tegra_xusb_padctl_pinconf_group_set(struct pinctrl_dev *pinctrl,
 	unsigned long value;
 	unsigned int i;
 	u32 regval;
+	int port;
 
 	lane = &padctl->soc->lanes[group];
 
@@ -385,6 +723,178 @@ static int tegra_xusb_padctl_pinconf_group_set(struct pinctrl_dev *pinctrl,
 			padctl_writel(padctl, regval, lane->offset);
 			break;
 
+		case TEGRA_XUSB_PADCTL_USB2_PORT_NUM:
+			if (value >= TEGRA_XUSB_UTMI_PHYS) {
+				dev_err(padctl->dev, "Invalid USB2 port: %lu\n",
+					value);
+				return -EINVAL;
+			}
+			if (!is_pcie_or_sata_lane(group)) {
+				dev_err(padctl->dev,
+					"USB2 port not applicable for pin %d\n",
+					group);
+				return -EINVAL;
+			}
+			port = lane_to_usb3_port(padctl, group);
+			if (port < 0) {
+				dev_err(padctl->dev,
+					"Pin %d not mapped to USB3 port\n",
+					group);
+				return -EINVAL;
+			}
+
+			regval = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP);
+			regval &= ~(XUSB_PADCTL_SS_PORT_MAP_PORT_MASK <<
+				    XUSB_PADCTL_SS_PORT_MAP_PORTX_SHIFT(port));
+			regval |= value <<
+				XUSB_PADCTL_SS_PORT_MAP_PORTX_SHIFT(port);
+			padctl_writel(padctl, regval, XUSB_PADCTL_SS_PORT_MAP);
+			break;
+
+		case TEGRA_XUSB_PADCTL_HSIC_STROBE_TRIM:
+			if (!is_hsic_lane(group)) {
+				dev_err(padctl->dev, "Pin %d not an HSIC\n",
+					group);
+				return -EINVAL;
+			}
+
+			value &= XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL_STRB_TRIM_MASK;
+			padctl_writel(padctl, value,
+				      XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL);
+			break;
+
+		case TEGRA_XUSB_PADCTL_HSIC_RX_STROBE_TRIM:
+			if (!is_hsic_lane(group)) {
+				dev_err(padctl->dev, "Pin %d not an HSIC\n",
+					group);
+				return -EINVAL;
+			}
+
+			port = group - TEGRA_XUSB_PADCTL_PIN_HSIC_0;
+			value &= XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_MASK;
+			regval = padctl_readl(padctl,
+					      XUSB_PADCTL_HSIC_PADX_CTL2(port));
+			regval &= ~(XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_MASK <<
+				    XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT);
+			regval |= value <<
+				XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT;
+			padctl_writel(padctl, regval,
+				      XUSB_PADCTL_HSIC_PADX_CTL2(port));
+			break;
+
+		case TEGRA_XUSB_PADCTL_HSIC_RX_DATA_TRIM:
+			if (!is_hsic_lane(group)) {
+				dev_err(padctl->dev, "Pin %d not an HSIC\n",
+					group);
+				return -EINVAL;
+			}
+
+			port = group - TEGRA_XUSB_PADCTL_PIN_HSIC_0;
+			value &= XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_MASK;
+			regval = padctl_readl(padctl,
+					      XUSB_PADCTL_HSIC_PADX_CTL2(port));
+			regval &= ~(XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_MASK <<
+				    XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT);
+			regval |= value <<
+				XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT;
+			padctl_writel(padctl, regval,
+				      XUSB_PADCTL_HSIC_PADX_CTL2(port));
+			break;
+
+		case TEGRA_XUSB_PADCTL_HSIC_TX_RTUNEN:
+			if (!is_hsic_lane(group)) {
+				dev_err(padctl->dev, "Pin %d not an HSIC\n",
+					group);
+				return -EINVAL;
+			}
+
+			port = group - TEGRA_XUSB_PADCTL_PIN_HSIC_0;
+			value &= XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_MASK;
+			regval = padctl_readl(padctl,
+					      XUSB_PADCTL_HSIC_PADX_CTL0(port));
+			regval &= ~(XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_MASK <<
+				    XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_SHIFT);
+			regval |= value <<
+				XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_SHIFT;
+			padctl_writel(padctl, regval,
+				      XUSB_PADCTL_HSIC_PADX_CTL0(port));
+			break;
+
+		case TEGRA_XUSB_PADCTL_HSIC_TX_RTUNEP:
+			if (!is_hsic_lane(group)) {
+				dev_err(padctl->dev, "Pin %d not an HSIC\n",
+					group);
+				return -EINVAL;
+			}
+
+			port = group - TEGRA_XUSB_PADCTL_PIN_HSIC_0;
+			value &= XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_MASK;
+			regval = padctl_readl(padctl,
+					      XUSB_PADCTL_HSIC_PADX_CTL0(port));
+			regval &= ~(XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_MASK <<
+				    XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_SHIFT);
+			regval |= value <<
+				XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_SHIFT;
+			padctl_writel(padctl, regval,
+				      XUSB_PADCTL_HSIC_PADX_CTL0(port));
+			break;
+
+		case TEGRA_XUSB_PADCTL_HSIC_TX_RSLEWN:
+			if (!is_hsic_lane(group)) {
+				dev_err(padctl->dev, "Pin %d not an HSIC\n",
+					group);
+				return -EINVAL;
+			}
+
+			port = group - TEGRA_XUSB_PADCTL_PIN_HSIC_0;
+			value &= XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_MASK;
+			regval = padctl_readl(padctl,
+					      XUSB_PADCTL_HSIC_PADX_CTL0(port));
+			regval &= ~(XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_MASK <<
+				    XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_SHIFT);
+			regval |= value <<
+				XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_SHIFT;
+			padctl_writel(padctl, regval,
+				      XUSB_PADCTL_HSIC_PADX_CTL0(port));
+			break;
+
+		case TEGRA_XUSB_PADCTL_HSIC_TX_RSLEWP:
+			if (!is_hsic_lane(group)) {
+				dev_err(padctl->dev, "Pin %d not an HSIC\n",
+					group);
+				return -EINVAL;
+			}
+
+			port = group - TEGRA_XUSB_PADCTL_PIN_HSIC_0;
+			value &= XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_MASK;
+			regval = padctl_readl(padctl,
+					      XUSB_PADCTL_HSIC_PADX_CTL0(port));
+			regval &= ~(XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_MASK <<
+				    XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_SHIFT);
+			regval |= value <<
+				XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_SHIFT;
+			padctl_writel(padctl, regval,
+				      XUSB_PADCTL_HSIC_PADX_CTL0(port));
+			break;
+
+		case TEGRA_XUSB_PADCTL_HSIC_AUTO_TERM:
+			if (!is_hsic_lane(group)) {
+				dev_err(padctl->dev, "Pin %d not an HSIC\n",
+					group);
+				return -EINVAL;
+			}
+
+			port = group - TEGRA_XUSB_PADCTL_PIN_HSIC_0;
+			regval = padctl_readl(padctl,
+					      XUSB_PADCTL_HSIC_PADX_CTL1(port));
+			if (!value)
+				regval &= ~XUSB_PADCTL_HSIC_PAD_CTL1_AUTO_TERM_EN;
+			else
+				regval |= XUSB_PADCTL_HSIC_PAD_CTL1_AUTO_TERM_EN;
+			padctl_writel(padctl, regval,
+				      XUSB_PADCTL_HSIC_PADX_CTL1(port));
+			break;
+
 		default:
 			dev_err(padctl->dev,
 				"invalid configuration parameter: %04x\n",
@@ -671,6 +1181,506 @@ static const struct phy_ops sata_phy_ops = {
 	.owner = THIS_MODULE,
 };
 
+static int usb3_phy_to_port(struct phy *phy)
+{
+	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+	int i;
+
+	for (i = 0; i < TEGRA_XUSB_USB3_PHYS; i++) {
+		if (phy == padctl->phys[TEGRA_XUSB_PADCTL_USB3_P0 + i])
+			break;
+	}
+	BUG_ON(i == TEGRA_XUSB_USB3_PHYS);
+
+	return i;
+}
+
+static int usb3_phy_power_on(struct phy *phy)
+{
+	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+	int port = usb3_phy_to_port(phy);
+	int lane = padctl->usb3_ports[port].lane;
+	u32 value, offset;
+
+	if (!is_pcie_or_sata_lane(lane)) {
+		dev_err(padctl->dev, "USB3 PHY %d mapped to invalid lane: %d\n",
+			port, lane);
+		return -EINVAL;
+	}
+
+	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(port));
+	value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_MASK <<
+		    XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_SHIFT) |
+		   (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_MASK <<
+		    XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_SHIFT) |
+		   (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_MASK <<
+		    XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_SHIFT));
+	value |= (padctl->soc->rx_wander <<
+		  XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_SHIFT) |
+		 (padctl->soc->cdr_cntl <<
+		  XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_SHIFT) |
+		 (padctl->soc->rx_eq <<
+		  XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_SHIFT);
+	if (padctl->usb3_ports[port].context_saved) {
+		value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_MASK <<
+			    XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) |
+			   (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_MASK <<
+			    XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT));
+		value |= (padctl->usb3_ports[port].ctle_g_val <<
+			  XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) |
+			 (padctl->usb3_ports[port].ctle_z_val <<
+			  XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT);
+	}
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(port));
+
+	value = padctl->soc->dfe_cntl;
+	if (padctl->usb3_ports[port].context_saved) {
+		value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_MASK <<
+			    XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) |
+			   (XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_MASK <<
+			    XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT));
+		value |= (padctl->usb3_ports[port].tap1_val <<
+			  XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) |
+			 (padctl->usb3_ports[port].amp_val <<
+			  XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT);
+	}
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(port));
+
+	offset = (lane == TEGRA_XUSB_PADCTL_PIN_SATA_0) ?
+		XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL2 :
+		XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL2(lane -
+						TEGRA_XUSB_PADCTL_PIN_PCIE_0);
+	value = padctl_readl(padctl, offset);
+	value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_MASK <<
+		   XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_SHIFT);
+	value |= padctl->soc->spare_in <<
+		XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_SHIFT;
+	padctl_writel(padctl, value, offset);
+
+	offset = (lane == TEGRA_XUSB_PADCTL_PIN_SATA_0) ?
+		XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL5 :
+		XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL5(lane -
+						TEGRA_XUSB_PADCTL_PIN_PCIE_0);
+	value = padctl_readl(padctl, offset);
+	value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL5_RX_QEYE_EN;
+	padctl_writel(padctl, value, offset);
+
+	/* Enable SATA PHY when SATA lane is used */
+	if (lane == TEGRA_XUSB_PADCTL_PIN_SATA_0) {
+		value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+		value &= ~(XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_MASK <<
+			   XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_SHIFT);
+		value |= 0x2 <<
+			XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_SHIFT;
+		padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+		value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL2);
+		value &= ~((XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_MASK <<
+			    XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_SHIFT) |
+			   (XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_MASK <<
+			    XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_SHIFT) |
+			   (XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_MASK <<
+			    XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_SHIFT) |
+			   XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TCLKOUT_EN);
+		value |= (0x7 <<
+			  XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_SHIFT) |
+			 (0x8 <<
+			  XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_SHIFT) |
+			 (0x8 <<
+			  XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_SHIFT) |
+			 XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TXCLKREF_SEL;
+		padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL2);
+
+		value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL3);
+		value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL3_RCAL_BYPASS;
+		padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL3);
+	}
+
+	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+	value &= ~XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN_EARLY(port);
+	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+	usleep_range(100, 200);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+	value &= ~XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN_EARLY(port);
+	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+	value &= ~XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_VCORE_DOWN(port);
+	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+	return 0;
+}
+
+static int usb3_phy_power_off(struct phy *phy)
+{
+	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+	int port = usb3_phy_to_port(phy);
+	u32 value;
+
+	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+	value |= XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN_EARLY(port);
+	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+	usleep_range(100, 200);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+	value |= XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN_EARLY(port);
+	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+	usleep_range(250, 350);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+	value |= XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_VCORE_DOWN(port);
+	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+	return 0;
+}
+
+static void usb3_phy_save_context(struct tegra_xusb_padctl *padctl, int port)
+{
+	int lane = padctl->usb3_ports[port].lane;
+	u32 value, offset;
+
+	padctl->usb3_ports[port].context_saved = true;
+
+	offset = (lane == TEGRA_XUSB_PADCTL_PIN_SATA_0) ?
+		XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL6 :
+		XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL6(lane -
+						TEGRA_XUSB_PADCTL_PIN_PCIE_0);
+
+	value = padctl_readl(padctl, offset);
+	value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK <<
+		   XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT);
+	value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_TAP <<
+		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT;
+	padctl_writel(padctl, value, offset);
+
+	value = padctl_readl(padctl, offset) >>
+		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT;
+	padctl->usb3_ports[port].tap1_val = value &
+		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_TAP_MASK;
+
+	value = padctl_readl(padctl, offset);
+	value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK <<
+		   XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT);
+	value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_AMP <<
+		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT;
+	padctl_writel(padctl, value, offset);
+
+	value = padctl_readl(padctl, offset) >>
+		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT;
+	padctl->usb3_ports[port].amp_val = value &
+		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_AMP_MASK;
+
+	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(port));
+	value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_MASK <<
+		    XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) |
+		   (XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_MASK <<
+		    XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT));
+	value |= (padctl->usb3_ports[port].tap1_val <<
+		  XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) |
+		 (padctl->usb3_ports[port].amp_val <<
+		  XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT);
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(port));
+
+	value = padctl_readl(padctl, offset);
+	value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK <<
+		   XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT);
+	value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_LATCH_G_Z <<
+		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT;
+	padctl_writel(padctl, value, offset);
+
+	value = padctl_readl(padctl, offset);
+	value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK <<
+		   XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT);
+	value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_G_Z <<
+		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT;
+	padctl_writel(padctl, value, offset);
+
+	value = padctl_readl(padctl, offset) >>
+		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT;
+	padctl->usb3_ports[port].ctle_g_val = value &
+		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_G_Z_MASK;
+
+	value = padctl_readl(padctl, offset);
+	value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK <<
+		   XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT);
+	value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_CTLE_Z <<
+		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT;
+	padctl_writel(padctl, value, offset);
+
+	value = padctl_readl(padctl, offset) >>
+		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT;
+	padctl->usb3_ports[port].ctle_z_val = value &
+		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_G_Z_MASK;
+
+	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(port));
+	value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_MASK <<
+		    XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) |
+		   (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_MASK <<
+		    XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT));
+	value |= (padctl->usb3_ports[port].ctle_g_val <<
+		  XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) |
+		 (padctl->usb3_ports[port].ctle_z_val <<
+		  XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT);
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(port));
+}
+
+static const struct phy_ops usb3_phy_ops = {
+	.init = tegra_xusb_phy_init,
+	.exit = tegra_xusb_phy_exit,
+	.power_on = usb3_phy_power_on,
+	.power_off = usb3_phy_power_off,
+	.owner = THIS_MODULE,
+};
+
+static int utmi_phy_to_port(struct phy *phy)
+{
+	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+	int i;
+
+	for (i = 0; i < TEGRA_XUSB_UTMI_PHYS; i++) {
+		if (phy == padctl->phys[TEGRA_XUSB_PADCTL_UTMI_P0 + i])
+			break;
+	}
+	BUG_ON(i == TEGRA_XUSB_UTMI_PHYS);
+
+	return i;
+}
+
+static int utmi_phy_power_on(struct phy *phy)
+{
+	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+	int port = utmi_phy_to_port(phy);
+	int ret;
+	u32 value;
+
+	value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
+	value &= ~((XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_MASK <<
+		    XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT) |
+		   (XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_MASK <<
+		    XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT));
+	value |= (padctl->calib.hs_squelch_level <<
+		  XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT) |
+		 (padctl->soc->hs_discon_level <<
+		  XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT);
+	padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_USB2_PORT_CAP);
+	value &= ~(XUSB_PADCTL_USB2_PORT_CAP_PORT_CAP_MASK <<
+		   XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_SHIFT(port));
+	value |= XUSB_PADCTL_USB2_PORT_CAP_HOST <<
+		XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_SHIFT(port);
+	padctl_writel(padctl, value, XUSB_PADCTL_USB2_PORT_CAP);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL0(port));
+	value &= ~((XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK <<
+		    XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT) |
+		   (XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_MASK <<
+		    XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_SHIFT) |
+		   (XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_MASK <<
+		    XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_SHIFT) |
+		   XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD |
+		   XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 |
+		   XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI);
+	value |= padctl->calib.hs_curr_level[port] <<
+		XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT;
+	value |= padctl->soc->hs_slew <<
+		XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_SHIFT;
+	value |= padctl->soc->ls_rslew[port] <<
+		XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_SHIFT;
+	padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL0(port));
+
+	value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL1(port));
+	value &= ~((XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_MASK <<
+		    XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT) |
+		   (XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_MASK <<
+		    XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_SHIFT) |
+		   XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR |
+		   XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_FORCE_POWERUP |
+		   XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_FORCE_POWERUP);
+	value |= (padctl->calib.hs_term_range_adj <<
+		  XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT) |
+		 (padctl->calib.hs_iref_cap <<
+		  XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_SHIFT);
+	padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL1(port));
+
+	ret = regulator_enable(padctl->vbus[port]);
+	if (ret)
+		return ret;
+
+	mutex_lock(&padctl->lock);
+
+	if (padctl->utmi_enable++ > 0)
+		goto out;
+
+	value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
+	value &= ~XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD;
+	padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
+
+out:
+	mutex_unlock(&padctl->lock);
+	return 0;
+}
+
+static int utmi_phy_power_off(struct phy *phy)
+{
+	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+	int port = utmi_phy_to_port(phy);
+	u32 value;
+
+	regulator_disable(padctl->vbus[port]);
+
+	mutex_lock(&padctl->lock);
+
+	if (WARN_ON(padctl->utmi_enable == 0))
+		goto out;
+
+	if (--padctl->utmi_enable > 0)
+		goto out;
+
+	value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
+	value |= XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD;
+	padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
+
+out:
+	mutex_unlock(&padctl->lock);
+	return 0;
+}
+
+static const struct phy_ops utmi_phy_ops = {
+	.init = tegra_xusb_phy_init,
+	.exit = tegra_xusb_phy_exit,
+	.power_on = utmi_phy_power_on,
+	.power_off = utmi_phy_power_off,
+	.owner = THIS_MODULE,
+};
+
+static int hsic_phy_to_port(struct phy *phy)
+{
+	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+	int i;
+
+	for (i = 0; i < TEGRA_XUSB_HSIC_PHYS; i++) {
+		if (phy == padctl->phys[TEGRA_XUSB_PADCTL_HSIC_P0 + i])
+			break;
+	}
+	BUG_ON(i == TEGRA_XUSB_HSIC_PHYS);
+
+	return i;
+}
+
+static int hsic_phy_power_on(struct phy *phy)
+{
+	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+	int port = hsic_phy_to_port(phy);
+	int ret;
+	u32 value;
+
+	ret = regulator_enable(padctl->vddio_hsic);
+	if (ret)
+		return ret;
+
+	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(port));
+	value &= ~(XUSB_PADCTL_HSIC_PAD_CTL1_RPD_STROBE |
+		   XUSB_PADCTL_HSIC_PAD_CTL1_RPU_DATA |
+		   XUSB_PADCTL_HSIC_PAD_CTL1_PD_RX |
+		   XUSB_PADCTL_HSIC_PAD_CTL1_PD_ZI |
+		   XUSB_PADCTL_HSIC_PAD_CTL1_PD_TRX |
+		   XUSB_PADCTL_HSIC_PAD_CTL1_PD_TX);
+	value |= XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA |
+		 XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE;
+	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(port));
+
+	return 0;
+}
+
+static int hsic_phy_power_off(struct phy *phy)
+{
+	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+	int port = hsic_phy_to_port(phy);
+	u32 value;
+
+	regulator_disable(padctl->vddio_hsic);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(port));
+	value |= XUSB_PADCTL_HSIC_PAD_CTL1_PD_RX |
+		 XUSB_PADCTL_HSIC_PAD_CTL1_PD_ZI |
+		 XUSB_PADCTL_HSIC_PAD_CTL1_PD_TRX |
+		 XUSB_PADCTL_HSIC_PAD_CTL1_PD_TX;
+	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(port));
+
+	return 0;
+}
+
+static void hsic_phy_set_idle(struct tegra_xusb_padctl *padctl, int port,
+			      bool set)
+{
+	u32 value;
+
+	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(port));
+	if (set)
+		value |= XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA |
+			 XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE;
+	else
+		value &= ~(XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA |
+			   XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE);
+	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(port));
+}
+
+static const struct phy_ops hsic_phy_ops = {
+	.init = tegra_xusb_phy_init,
+	.exit = tegra_xusb_phy_exit,
+	.power_on = hsic_phy_power_on,
+	.power_off = hsic_phy_power_off,
+	.owner = THIS_MODULE,
+};
+
+static void tegra_xusb_phy_mbox_rx(struct mbox_client *cl, void *data)
+{
+	struct tegra_xusb_padctl *padctl = dev_get_drvdata(cl->dev);
+	struct tegra_xusb_mbox_msg *msg = data;
+	struct tegra_xusb_mbox_msg resp;
+	u32 ports;
+	int i;
+
+	switch (msg->cmd) {
+	case MBOX_CMD_SAVE_DFE_CTLE_CTX:
+		resp.data = msg->data;
+		if (msg->data > TEGRA_XUSB_USB3_PHYS) {
+			resp.cmd = MBOX_CMD_NAK;
+		} else {
+			usb3_phy_save_context(padctl, msg->data);
+			resp.cmd = MBOX_CMD_ACK;
+		}
+		break;
+	case MBOX_CMD_START_HSIC_IDLE:
+	case MBOX_CMD_STOP_HSIC_IDLE:
+		ports = msg->data >> (padctl->soc->hsic_port_offset + 1);
+		resp.data = msg->data;
+		resp.cmd = MBOX_CMD_ACK;
+		for (i = 0; i < TEGRA_XUSB_HSIC_PHYS; i++) {
+			if (!(ports & BIT(i)))
+				continue;
+			if (msg->cmd == MBOX_CMD_START_HSIC_IDLE)
+				hsic_phy_set_idle(padctl, i, true);
+			else
+				hsic_phy_set_idle(padctl, i, false);
+		}
+		break;
+	default:
+		dev_err(padctl->dev, "Unexpected message: 0x%x:0x%x\n",
+			msg->cmd, msg->data);
+		resp.data = 0;
+		resp.cmd = MBOX_CMD_NAK;
+		break;
+	}
+
+	mbox_send_message(padctl->mbox_chan, &resp);
+}
+
 static struct phy *tegra_xusb_padctl_xlate(struct device *dev,
 					   struct of_phandle_args *args)
 {
@@ -686,32 +1696,19 @@ static struct phy *tegra_xusb_padctl_xlate(struct device *dev,
 	return padctl->phys[index];
 }
 
-#define PIN_OTG_0   0
-#define PIN_OTG_1   1
-#define PIN_OTG_2   2
-#define PIN_ULPI_0  3
-#define PIN_HSIC_0  4
-#define PIN_HSIC_1  5
-#define PIN_PCIE_0  6
-#define PIN_PCIE_1  7
-#define PIN_PCIE_2  8
-#define PIN_PCIE_3  9
-#define PIN_PCIE_4 10
-#define PIN_SATA_0 11
-
 static const struct pinctrl_pin_desc tegra124_pins[] = {
-	PINCTRL_PIN(PIN_OTG_0,  "otg-0"),
-	PINCTRL_PIN(PIN_OTG_1,  "otg-1"),
-	PINCTRL_PIN(PIN_OTG_2,  "otg-2"),
-	PINCTRL_PIN(PIN_ULPI_0, "ulpi-0"),
-	PINCTRL_PIN(PIN_HSIC_0, "hsic-0"),
-	PINCTRL_PIN(PIN_HSIC_1, "hsic-1"),
-	PINCTRL_PIN(PIN_PCIE_0, "pcie-0"),
-	PINCTRL_PIN(PIN_PCIE_1, "pcie-1"),
-	PINCTRL_PIN(PIN_PCIE_2, "pcie-2"),
-	PINCTRL_PIN(PIN_PCIE_3, "pcie-3"),
-	PINCTRL_PIN(PIN_PCIE_4, "pcie-4"),
-	PINCTRL_PIN(PIN_SATA_0, "sata-0"),
+	PINCTRL_PIN(TEGRA_XUSB_PADCTL_PIN_OTG_0,  "otg-0"),
+	PINCTRL_PIN(TEGRA_XUSB_PADCTL_PIN_OTG_1,  "otg-1"),
+	PINCTRL_PIN(TEGRA_XUSB_PADCTL_PIN_OTG_2,  "otg-2"),
+	PINCTRL_PIN(TEGRA_XUSB_PADCTL_PIN_ULPI_0, "ulpi-0"),
+	PINCTRL_PIN(TEGRA_XUSB_PADCTL_PIN_HSIC_0, "hsic-0"),
+	PINCTRL_PIN(TEGRA_XUSB_PADCTL_PIN_HSIC_1, "hsic-1"),
+	PINCTRL_PIN(TEGRA_XUSB_PADCTL_PIN_PCIE_0, "pcie-0"),
+	PINCTRL_PIN(TEGRA_XUSB_PADCTL_PIN_PCIE_1, "pcie-1"),
+	PINCTRL_PIN(TEGRA_XUSB_PADCTL_PIN_PCIE_2, "pcie-2"),
+	PINCTRL_PIN(TEGRA_XUSB_PADCTL_PIN_PCIE_3, "pcie-3"),
+	PINCTRL_PIN(TEGRA_XUSB_PADCTL_PIN_PCIE_4, "pcie-4"),
+	PINCTRL_PIN(TEGRA_XUSB_PADCTL_PIN_SATA_0, "sata-0"),
 };
 
 static const char * const tegra124_snps_groups[] = {
@@ -856,6 +1853,15 @@ static const struct tegra_xusb_padctl_soc tegra124_soc = {
 	.functions = tegra124_functions,
 	.num_lanes = ARRAY_SIZE(tegra124_lanes),
 	.lanes = tegra124_lanes,
+	.rx_wander = 0xf,
+	.rx_eq = 0xf070,
+	.cdr_cntl = 0x24,
+	.dfe_cntl = 0x002008ee,
+	.hs_slew = 0xe,
+	.ls_rslew = {0x3, 0x0, 0x0},
+	.hs_discon_level = 0x5,
+	.spare_in = 0x1,
+	.hsic_port_offset = 6,
 };
 
 static const struct of_device_id tegra_xusb_padctl_of_match[] = {
@@ -864,13 +1870,40 @@ static const struct of_device_id tegra_xusb_padctl_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, tegra_xusb_padctl_of_match);
 
+static int tegra_xusb_read_fuse_calibration(struct tegra_xusb_padctl *padctl)
+{
+	int i, ret;
+	u32 value;
+
+	ret = tegra_fuse_readl(TEGRA_FUSE_SKU_CALIB_0, &value);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < TEGRA_XUSB_UTMI_PHYS; i++) {
+		padctl->calib.hs_curr_level[i] =
+			(value >> FUSE_SKU_CALIB_HS_CURR_LEVEL_PADX_SHIFT(i)) &
+			FUSE_SKU_CALIB_HS_CURR_LEVEL_PAD_MASK;
+	}
+	padctl->calib.hs_iref_cap =
+		(value >> FUSE_SKU_CALIB_HS_IREF_CAP_SHIFT) &
+		FUSE_SKU_CALIB_HS_IREF_CAP_MASK;
+	padctl->calib.hs_term_range_adj =
+		(value >> FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_SHIFT) &
+		FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_MASK;
+	padctl->calib.hs_squelch_level =
+		(value >> FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_SHIFT) &
+		FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_MASK;
+
+	return 0;
+}
+
 static int tegra_xusb_padctl_probe(struct platform_device *pdev)
 {
 	struct tegra_xusb_padctl *padctl;
 	const struct of_device_id *match;
 	struct resource *res;
 	struct phy *phy;
-	int err;
+	int err, i;
 
 	padctl = devm_kzalloc(&pdev->dev, sizeof(*padctl), GFP_KERNEL);
 	if (!padctl)
@@ -888,6 +1921,10 @@ static int tegra_xusb_padctl_probe(struct platform_device *pdev)
 	if (IS_ERR(padctl->regs))
 		return PTR_ERR(padctl->regs);
 
+	err = tegra_xusb_read_fuse_calibration(padctl);
+	if (err < 0)
+		return err;
+
 	padctl->rst = devm_reset_control_get(&pdev->dev, NULL);
 	if (IS_ERR(padctl->rst))
 		return PTR_ERR(padctl->rst);
@@ -896,6 +1933,22 @@ static int tegra_xusb_padctl_probe(struct platform_device *pdev)
 	if (err < 0)
 		return err;
 
+	for (i = 0; i < TEGRA_XUSB_USB3_PHYS; i++) {
+		char prop[sizeof("nvidia,usb3-port-N-lane")];
+		u32 lane;
+
+		sprintf(prop, "nvidia,usb3-port-%d-lane", i);
+		if (!of_property_read_u32(pdev->dev.of_node, prop, &lane)) {
+			if (!is_pcie_or_sata_lane(lane)) {
+				err = -EINVAL;
+				goto unregister;
+			}
+			padctl->usb3_ports[i].lane = lane;
+		} else {
+			padctl->usb3_ports[i].lane = -EINVAL;
+		}
+	}
+
 	memset(&padctl->desc, 0, sizeof(padctl->desc));
 	padctl->desc.name = dev_name(padctl->dev);
 	padctl->desc.pctlops = &tegra_xusb_padctl_pinctrl_ops;
@@ -928,6 +1981,54 @@ static int tegra_xusb_padctl_probe(struct platform_device *pdev)
 	padctl->phys[TEGRA_XUSB_PADCTL_SATA] = phy;
 	phy_set_drvdata(phy, padctl);
 
+	for (i = 0; i < TEGRA_XUSB_USB3_PHYS; i++) {
+		phy = devm_phy_create(&pdev->dev, NULL, &usb3_phy_ops, NULL);
+		if (IS_ERR(phy)) {
+			err = PTR_ERR(phy);
+			goto unregister;
+		}
+
+		padctl->phys[TEGRA_XUSB_PADCTL_USB3_P0 + i] = phy;
+		phy_set_drvdata(phy, padctl);
+	}
+
+	for (i = 0; i < TEGRA_XUSB_UTMI_PHYS; i++) {
+		char reg_name[sizeof("vbus-otg-N")];
+
+		sprintf(reg_name, "vbus-otg-%d", i);
+		padctl->vbus[i] = devm_regulator_get(&pdev->dev, reg_name);
+		if (IS_ERR(padctl->vbus[i])) {
+			err = PTR_ERR(padctl->vbus[i]);
+			goto unregister;
+		}
+
+		phy = devm_phy_create(&pdev->dev, NULL, &utmi_phy_ops, NULL);
+		if (IS_ERR(phy)) {
+			err = PTR_ERR(phy);
+			goto unregister;
+		}
+
+		padctl->phys[TEGRA_XUSB_PADCTL_UTMI_P0 + i] = phy;
+		phy_set_drvdata(phy, padctl);
+	}
+
+	padctl->vddio_hsic = devm_regulator_get(&pdev->dev, "vddio-hsic");
+	if (IS_ERR(padctl->vddio_hsic)) {
+		err = PTR_ERR(padctl->vddio_hsic);
+		goto unregister;
+	}
+
+	for (i = 0; i < TEGRA_XUSB_HSIC_PHYS; i++) {
+		phy = devm_phy_create(&pdev->dev, NULL, &hsic_phy_ops, NULL);
+		if (IS_ERR(phy)) {
+			err = PTR_ERR(phy);
+			goto unregister;
+		}
+
+		padctl->phys[TEGRA_XUSB_PADCTL_HSIC_P0 + i] = phy;
+		phy_set_drvdata(phy, padctl);
+	}
+
 	padctl->provider = devm_of_phy_provider_register(&pdev->dev,
 							 tegra_xusb_padctl_xlate);
 	if (err < 0) {
@@ -935,6 +2036,17 @@ static int tegra_xusb_padctl_probe(struct platform_device *pdev)
 		goto unregister;
 	}
 
+	padctl->mbox_client.dev = &pdev->dev;
+	padctl->mbox_client.tx_block = true;
+	padctl->mbox_client.tx_tout = 0;
+	padctl->mbox_client.rx_callback = tegra_xusb_phy_mbox_rx;
+	padctl->mbox_chan = mbox_request_channel(&padctl->mbox_client, 0);
+	if (IS_ERR(padctl->mbox_chan)) {
+		err = PTR_ERR(padctl->mbox_chan);
+		dev_err(&pdev->dev, "failed to request mailbox: %d\n", err);
+		goto unregister;
+	}
+
 	return 0;
 
 unregister:
@@ -949,6 +2061,8 @@ static int tegra_xusb_padctl_remove(struct platform_device *pdev)
 	struct tegra_xusb_padctl *padctl = platform_get_drvdata(pdev);
 	int err;
 
+	mbox_free_channel(padctl->mbox_chan);
+
 	pinctrl_unregister(padctl->pinctrl);
 
 	err = reset_control_assert(padctl->rst);
diff --git a/include/soc/tegra/xusb.h b/include/soc/tegra/xusb.h
index 8efef8c..1bac2ab 100644
--- a/include/soc/tegra/xusb.h
+++ b/include/soc/tegra/xusb.h
@@ -10,6 +10,13 @@
 #ifndef __SOC_TEGRA_XUSB_H__
 #define __SOC_TEGRA_XUSB_H__
 
+#define TEGRA_XUSB_USB3_PHYS 2
+#define TEGRA_XUSB_UTMI_PHYS 3
+#define TEGRA_XUSB_HSIC_PHYS 2
+#define TEGRA_XUSB_NUM_USB_PHYS (TEGRA_XUSB_USB3_PHYS + TEGRA_XUSB_UTMI_PHYS + \
+				 TEGRA_XUSB_HSIC_PHYS)
+#define TEGRA_XUSB_NUM_PHYS (TEGRA_XUSB_NUM_USB_PHYS + 2) /* + SATA & PCIe */
+
 #define TEGRA_XUSB_MBOX_NUM_CHANS 2 /* host + phy */
 
 /* Command requests from the firmware */
-- 
2.1.0.rc2.206.gedb03e5

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

* [PATCH v2 4/9] pinctrl: tegra-xusb: Add USB PHY support
@ 2014-08-18 17:08   ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-18 17:08 UTC (permalink / raw)
  To: linux-arm-kernel

In addition to the PCIe and SATA PHYs, the XUSB pad controller also
supports 3 UTMI, 2 HSIC, and 2 USB3 PHYs.  Each USB3 PHY uses a single
PCIe or SATA lane and is mapped to one of the three UTMI ports.

The xHCI controller will also send messages intended for the PHY driver,
so request and listen for messages on the mailbox's PHY channel.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
---
Changes from v1:
 - Updated to use common mailbox API.
 - Added SATA PHY enable sequence for USB3 ports using the SATA lane.
 - Made USB3 port-to-lane mappins a top-level binding rather than a pinconfig
   binding.
---
 drivers/pinctrl/Kconfig              |    1 +
 drivers/pinctrl/pinctrl-tegra-xusb.c | 1170 +++++++++++++++++++++++++++++++++-
 include/soc/tegra/xusb.h             |    7 +
 3 files changed, 1150 insertions(+), 28 deletions(-)

diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index bfd2c2e..d5bc4f5 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -265,6 +265,7 @@ config PINCTRL_TEGRA_XUSB
 	select GENERIC_PHY
 	select PINCONF
 	select PINMUX
+	select MAILBOX
 
 config PINCTRL_TZ1090
 	bool "Toumaz Xenif TZ1090 pin control driver"
diff --git a/drivers/pinctrl/pinctrl-tegra-xusb.c b/drivers/pinctrl/pinctrl-tegra-xusb.c
index a066204..1091ce7 100644
--- a/drivers/pinctrl/pinctrl-tegra-xusb.c
+++ b/drivers/pinctrl/pinctrl-tegra-xusb.c
@@ -13,23 +13,53 @@
 
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/mailbox_client.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/phy/phy.h>
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/pinctrl/pinmux.h>
 #include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
 #include <linux/reset.h>
 
+#include <soc/tegra/fuse.h>
+#include <soc/tegra/xusb.h>
+
 #include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
 
 #include "core.h"
 #include "pinctrl-utils.h"
 
+#define FUSE_SKU_CALIB_HS_CURR_LEVEL_PADX_SHIFT(x) ((x) ? 15 : 0)
+#define FUSE_SKU_CALIB_HS_CURR_LEVEL_PAD_MASK 0x3f
+#define FUSE_SKU_CALIB_HS_IREF_CAP_SHIFT 13
+#define FUSE_SKU_CALIB_HS_IREF_CAP_MASK 0x3
+#define FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_SHIFT 11
+#define FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_MASK 0x3
+#define FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_SHIFT 7
+#define FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_MASK 0xf
+
+#define XUSB_PADCTL_USB2_PORT_CAP 0x008
+#define XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_SHIFT(x) ((x) * 4)
+#define XUSB_PADCTL_USB2_PORT_CAP_PORT_CAP_MASK 0x3
+#define XUSB_PADCTL_USB2_PORT_CAP_DISABLED 0x0
+#define XUSB_PADCTL_USB2_PORT_CAP_HOST 0x1
+#define XUSB_PADCTL_USB2_PORT_CAP_DEVICE 0x2
+#define XUSB_PADCTL_USB2_PORT_CAP_OTG 0x3
+
+#define XUSB_PADCTL_SS_PORT_MAP 0x014
+#define XUSB_PADCTL_SS_PORT_MAP_PORTX_SHIFT(x) ((x) * 4)
+#define XUSB_PADCTL_SS_PORT_MAP_PORT_MASK 0x7
+
 #define XUSB_PADCTL_ELPG_PROGRAM 0x01c
 #define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26)
 #define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25)
 #define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24)
+#define XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_VCORE_DOWN(x) (1 << (18 + (x) * 4))
+#define XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN_EARLY(x) \
+							(1 << (17 + (x) * 4))
+#define XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN(x) (1 << (16 + (x) * 4))
 
 #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x040
 #define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19)
@@ -41,17 +71,136 @@
 #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5)
 #define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4)
 
+#define XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(x) (0x058 + (x) * 4)
+#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_SHIFT 24
+#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_MASK 0xff
+#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT 16
+#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_MASK 0x3f
+#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT 8
+#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_MASK 0x3f
+#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_SHIFT 8
+#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_MASK 0xffff
+#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_SHIFT 4
+#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_MASK 0x7
+
+#define XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(x) (0x068 + (x) * 4)
+#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT 24
+#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_MASK 0x1f
+#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT 16
+#define XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_MASK 0x7f
+
+#define XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL2(x) ((x) < 2 ? 0x078 + (x) * 4 : \
+					       0x0f8 + (x) * 4)
+#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_SHIFT 28
+#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_MASK 0x3
+
+#define XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL5(x) ((x) < 2 ? 0x090 + (x) * 4 : \
+					       0x11c + (x) * 4)
+#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL5_RX_QEYE_EN (1 << 8)
+
+#define XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL6(x) ((x) < 2 ? 0x098 + (x) * 4 : \
+					       0x128 + (x) * 4)
+#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT 24
+#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_G_Z_MASK 0x3f
+#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_TAP_MASK 0x1f
+#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_AMP_MASK 0x7f
+#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT 16
+#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK 0xff
+#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_G_Z 0x21
+#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_TAP 0x32
+#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_AMP 0x33
+#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_CTLE_Z 0x48
+#define XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_LATCH_G_Z 0xa1
+
+#define XUSB_PADCTL_USB2_OTG_PADX_CTL0(x) (0x0a0 + (x) * 4)
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI (1 << 21)
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 (1 << 20)
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD (1 << 19)
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_SHIFT 14
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_MASK 0x3
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_SHIFT 6
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_MASK 0x3f
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT 0
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK 0x3f
+
+#define XUSB_PADCTL_USB2_OTG_PADX_CTL1(x) (0x0ac + (x) * 4)
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_SHIFT 9
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_MASK 0x3
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT 3
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_MASK 0x7
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR (1 << 2)
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_FORCE_POWERUP (1 << 1)
+#define XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_FORCE_POWERUP (1 << 0)
+
+#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0 0x0b8
+#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD (1 << 12)
+#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT 2
+#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_MASK 0x7
+#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT 0
+#define XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_MASK 0x3
+
+#define XUSB_PADCTL_HSIC_PADX_CTL0(x) (0x0c0 + (x) * 4)
+#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_SHIFT 12
+#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_MASK 0x7
+#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_SHIFT 8
+#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_MASK 0x7
+#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_SHIFT 4
+#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_MASK 0x7
+#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_SHIFT 0
+#define XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_MASK 0x7
+
+#define XUSB_PADCTL_HSIC_PADX_CTL1(x) (0x0c8 + (x) * 4)
+#define XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE (1 << 10)
+#define XUSB_PADCTL_HSIC_PAD_CTL1_RPU_DATA (1 << 9)
+#define XUSB_PADCTL_HSIC_PAD_CTL1_RPD_STROBE (1 << 8)
+#define XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA (1 << 7)
+#define XUSB_PADCTL_HSIC_PAD_CTL1_PD_ZI (1 << 5)
+#define XUSB_PADCTL_HSIC_PAD_CTL1_PD_RX (1 << 4)
+#define XUSB_PADCTL_HSIC_PAD_CTL1_PD_TRX (1 << 3)
+#define XUSB_PADCTL_HSIC_PAD_CTL1_PD_TX (1 << 2)
+#define XUSB_PADCTL_HSIC_PAD_CTL1_AUTO_TERM_EN (1 << 0)
+
+#define XUSB_PADCTL_HSIC_PADX_CTL2(x) (0x0d0 + (x) * 4)
+#define XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT 4
+#define XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_MASK 0x7
+#define XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT 0
+#define XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_MASK 0x7
+
+#define XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL 0x0e0
+#define XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL_STRB_TRIM_MASK 0x1f
+
 #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138
 #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27)
 #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24)
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_SHIFT 20
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_MASK 0x3
 #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD (1 << 3)
 #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST (1 << 1)
 #define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ (1 << 0)
 
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2 0x13c
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_SHIFT 20
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_MASK 0xf
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_SHIFT 16
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_MASK 0xf
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TCLKOUT_EN (1 << 12)
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TXCLKREF_SEL (1 << 4)
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_SHIFT 0
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_MASK 0x7
+
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL3 0x140
+#define XUSB_PADCTL_IOPHY_PLL_S0_CTL3_RCAL_BYPASS (1 << 7)
+
 #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1 0x148
 #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD (1 << 1)
 #define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ (1 << 0)
 
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL2 0x14c
+
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL5 0x158
+
+#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL6 0x15c
+
 struct tegra_xusb_padctl_function {
 	const char *name;
 	const char * const *groups;
@@ -72,6 +221,16 @@ struct tegra_xusb_padctl_soc {
 
 	const struct tegra_xusb_padctl_lane *lanes;
 	unsigned int num_lanes;
+
+	u32 rx_wander;
+	u32 rx_eq;
+	u32 cdr_cntl;
+	u32 dfe_cntl;
+	u32 hs_slew;
+	u32 ls_rslew[TEGRA_XUSB_UTMI_PHYS];
+	u32 hs_discon_level;
+	u32 spare_in;
+	int hsic_port_offset;
 };
 
 struct tegra_xusb_padctl_lane {
@@ -86,6 +245,22 @@ struct tegra_xusb_padctl_lane {
 	unsigned int num_funcs;
 };
 
+struct tegra_xusb_fuse_calibration {
+	u32 hs_curr_level[TEGRA_XUSB_UTMI_PHYS];
+	u32 hs_iref_cap;
+	u32 hs_term_range_adj;
+	u32 hs_squelch_level;
+};
+
+struct tegra_xusb_usb3_port {
+	int lane;
+	bool context_saved;
+	u32 tap1_val;
+	u32 amp_val;
+	u32 ctle_z_val;
+	u32 ctle_g_val;
+};
+
 struct tegra_xusb_padctl {
 	struct device *dev;
 	void __iomem *regs;
@@ -93,13 +268,22 @@ struct tegra_xusb_padctl {
 	struct reset_control *rst;
 
 	const struct tegra_xusb_padctl_soc *soc;
+	struct tegra_xusb_fuse_calibration calib;
 	struct pinctrl_dev *pinctrl;
 	struct pinctrl_desc desc;
 
 	struct phy_provider *provider;
-	struct phy *phys[2];
+	struct phy *phys[TEGRA_XUSB_NUM_PHYS];
 
 	unsigned int enable;
+
+	struct mbox_client mbox_client;
+	struct mbox_chan *mbox_chan;
+
+	struct tegra_xusb_usb3_port usb3_ports[TEGRA_XUSB_USB3_PHYS];
+	unsigned int utmi_enable;
+	struct regulator *vbus[TEGRA_XUSB_UTMI_PHYS];
+	struct regulator *vddio_hsic;
 };
 
 static inline void padctl_writel(struct tegra_xusb_padctl *padctl, u32 value,
@@ -114,6 +298,31 @@ static inline u32 padctl_readl(struct tegra_xusb_padctl *padctl,
 	return readl(padctl->regs + offset);
 }
 
+static inline bool is_hsic_lane(unsigned int lane)
+{
+	return lane >= TEGRA_XUSB_PADCTL_PIN_HSIC_0 &&
+		lane <= TEGRA_XUSB_PADCTL_PIN_HSIC_1;
+}
+
+static inline bool is_pcie_or_sata_lane(unsigned int lane)
+{
+	return lane >= TEGRA_XUSB_PADCTL_PIN_PCIE_0 &&
+		lane <= TEGRA_XUSB_PADCTL_PIN_SATA_0;
+}
+
+static int lane_to_usb3_port(struct tegra_xusb_padctl *padctl,
+			     unsigned int lane)
+{
+	int i;
+
+	for (i = 0; i < TEGRA_XUSB_USB3_PHYS; i++) {
+		if (padctl->usb3_ports[i].lane == lane)
+			return i;
+	}
+
+	return -1;
+}
+
 static int tegra_xusb_padctl_get_groups_count(struct pinctrl_dev *pinctrl)
 {
 	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
@@ -131,6 +340,15 @@ static const char *tegra_xusb_padctl_get_group_name(struct pinctrl_dev *pinctrl,
 
 enum tegra_xusb_padctl_param {
 	TEGRA_XUSB_PADCTL_IDDQ,
+	TEGRA_XUSB_PADCTL_USB2_PORT_NUM,
+	TEGRA_XUSB_PADCTL_HSIC_STROBE_TRIM,
+	TEGRA_XUSB_PADCTL_HSIC_RX_STROBE_TRIM,
+	TEGRA_XUSB_PADCTL_HSIC_RX_DATA_TRIM,
+	TEGRA_XUSB_PADCTL_HSIC_TX_RTUNEN,
+	TEGRA_XUSB_PADCTL_HSIC_TX_RTUNEP,
+	TEGRA_XUSB_PADCTL_HSIC_TX_RSLEWN,
+	TEGRA_XUSB_PADCTL_HSIC_TX_RSLEWP,
+	TEGRA_XUSB_PADCTL_HSIC_AUTO_TERM,
 };
 
 static const struct tegra_xusb_padctl_property {
@@ -138,6 +356,15 @@ static const struct tegra_xusb_padctl_property {
 	enum tegra_xusb_padctl_param param;
 } properties[] = {
 	{ "nvidia,iddq", TEGRA_XUSB_PADCTL_IDDQ },
+	{ "nvidia,usb2-port-num", TEGRA_XUSB_PADCTL_USB2_PORT_NUM },
+	{ "nvidia,hsic-strobe-trim", TEGRA_XUSB_PADCTL_HSIC_STROBE_TRIM },
+	{ "nvidia,hsic-rx-strobe-trim", TEGRA_XUSB_PADCTL_HSIC_RX_STROBE_TRIM },
+	{ "nvidia,hsic-rx-data-trim", TEGRA_XUSB_PADCTL_HSIC_RX_DATA_TRIM },
+	{ "nvidia,hsic-tx-rtune-n", TEGRA_XUSB_PADCTL_HSIC_TX_RTUNEN },
+	{ "nvidia,hsic-tx-rtune-p", TEGRA_XUSB_PADCTL_HSIC_TX_RTUNEP },
+	{ "nvidia,hsic-tx-rslew-n", TEGRA_XUSB_PADCTL_HSIC_TX_RSLEWN },
+	{ "nvidia,hsic-tx-rslew-p", TEGRA_XUSB_PADCTL_HSIC_TX_RSLEWP },
+	{ "nvidia,hsic-auto-term", TEGRA_XUSB_PADCTL_HSIC_AUTO_TERM },
 };
 
 #define TEGRA_XUSB_PADCTL_PACK(param, value) ((param) << 16 | (value))
@@ -321,6 +548,7 @@ static int tegra_xusb_padctl_pinconf_group_get(struct pinctrl_dev *pinctrl,
 	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
 	const struct tegra_xusb_padctl_lane *lane;
 	enum tegra_xusb_padctl_param param;
+	int port;
 	u32 value;
 
 	param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(*config);
@@ -338,8 +566,116 @@ static int tegra_xusb_padctl_pinconf_group_get(struct pinctrl_dev *pinctrl,
 			value = 0;
 		else
 			value = 1;
+		break;
 
-		*config = TEGRA_XUSB_PADCTL_PACK(param, value);
+	case TEGRA_XUSB_PADCTL_USB2_PORT_NUM:
+		port = lane_to_usb3_port(padctl, group);
+		if (port < 0) {
+			dev_err(padctl->dev,
+				"Pin %d not mapped to USB3 port\n", group);
+			return -EINVAL;
+		}
+
+		value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP) >>
+			XUSB_PADCTL_SS_PORT_MAP_PORTX_SHIFT(port);
+		value &= XUSB_PADCTL_SS_PORT_MAP_PORT_MASK;
+		break;
+
+	case TEGRA_XUSB_PADCTL_HSIC_STROBE_TRIM:
+		if (!is_hsic_lane(group)) {
+			dev_err(padctl->dev, "Pin %d not an HSIC\n", group);
+			return -EINVAL;
+		}
+
+		value = padctl_readl(padctl,
+				     XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL);
+		value &= XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL_STRB_TRIM_MASK;
+		break;
+
+	case TEGRA_XUSB_PADCTL_HSIC_RX_STROBE_TRIM:
+		if (!is_hsic_lane(group)) {
+			dev_err(padctl->dev, "Pin %d not an HSIC\n", group);
+			return -EINVAL;
+		}
+
+		port = group - TEGRA_XUSB_PADCTL_PIN_HSIC_0;
+		value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL2(port)) >>
+			XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT;
+		value &= XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_MASK;
+		break;
+
+	case TEGRA_XUSB_PADCTL_HSIC_RX_DATA_TRIM:
+		if (!is_hsic_lane(group)) {
+			dev_err(padctl->dev, "Pin %d not an HSIC\n", group);
+			return -EINVAL;
+		}
+
+		port = group - TEGRA_XUSB_PADCTL_PIN_HSIC_0;
+		value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL2(port)) >>
+			XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT;
+		value &= XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_MASK;
+		break;
+
+	case TEGRA_XUSB_PADCTL_HSIC_TX_RTUNEN:
+		if (!is_hsic_lane(group)) {
+			dev_err(padctl->dev, "Pin %d not an HSIC\n", group);
+			return -EINVAL;
+		}
+
+		port = group - TEGRA_XUSB_PADCTL_PIN_HSIC_0;
+		value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL0(port)) >>
+			XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_SHIFT;
+		value &= XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_MASK;
+		break;
+
+	case TEGRA_XUSB_PADCTL_HSIC_TX_RTUNEP:
+		if (!is_hsic_lane(group)) {
+			dev_err(padctl->dev, "Pin %d not an HSIC\n", group);
+			return -EINVAL;
+		}
+
+		port = group - TEGRA_XUSB_PADCTL_PIN_HSIC_0;
+		value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL0(port)) >>
+			XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_SHIFT;
+		value &= XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_MASK;
+		break;
+
+	case TEGRA_XUSB_PADCTL_HSIC_TX_RSLEWN:
+		if (!is_hsic_lane(group)) {
+			dev_err(padctl->dev, "Pin %d not an HSIC\n", group);
+			return -EINVAL;
+		}
+
+		port = group - TEGRA_XUSB_PADCTL_PIN_HSIC_0;
+		value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL0(port)) >>
+			XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_SHIFT;
+		value &= XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_MASK;
+		break;
+
+	case TEGRA_XUSB_PADCTL_HSIC_TX_RSLEWP:
+		if (!is_hsic_lane(group)) {
+			dev_err(padctl->dev, "Pin %d not an HSIC\n", group);
+			return -EINVAL;
+		}
+
+		port = group - TEGRA_XUSB_PADCTL_PIN_HSIC_0;
+		value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL0(port)) >>
+			XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_SHIFT;
+		value &= XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_MASK;
+		break;
+
+	case TEGRA_XUSB_PADCTL_HSIC_AUTO_TERM:
+		if (!is_hsic_lane(group)) {
+			dev_err(padctl->dev, "Pin %d not an HSIC\n", group);
+			return -EINVAL;
+		}
+
+		port = group - TEGRA_XUSB_PADCTL_PIN_HSIC_0;
+		value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(port));
+		if (value & XUSB_PADCTL_HSIC_PAD_CTL1_AUTO_TERM_EN)
+			value = 1;
+		else
+			value = 0;
 		break;
 
 	default:
@@ -348,6 +684,7 @@ static int tegra_xusb_padctl_pinconf_group_get(struct pinctrl_dev *pinctrl,
 		return -ENOTSUPP;
 	}
 
+	*config = TEGRA_XUSB_PADCTL_PACK(param, value);
 	return 0;
 }
 
@@ -362,6 +699,7 @@ static int tegra_xusb_padctl_pinconf_group_set(struct pinctrl_dev *pinctrl,
 	unsigned long value;
 	unsigned int i;
 	u32 regval;
+	int port;
 
 	lane = &padctl->soc->lanes[group];
 
@@ -385,6 +723,178 @@ static int tegra_xusb_padctl_pinconf_group_set(struct pinctrl_dev *pinctrl,
 			padctl_writel(padctl, regval, lane->offset);
 			break;
 
+		case TEGRA_XUSB_PADCTL_USB2_PORT_NUM:
+			if (value >= TEGRA_XUSB_UTMI_PHYS) {
+				dev_err(padctl->dev, "Invalid USB2 port: %lu\n",
+					value);
+				return -EINVAL;
+			}
+			if (!is_pcie_or_sata_lane(group)) {
+				dev_err(padctl->dev,
+					"USB2 port not applicable for pin %d\n",
+					group);
+				return -EINVAL;
+			}
+			port = lane_to_usb3_port(padctl, group);
+			if (port < 0) {
+				dev_err(padctl->dev,
+					"Pin %d not mapped to USB3 port\n",
+					group);
+				return -EINVAL;
+			}
+
+			regval = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP);
+			regval &= ~(XUSB_PADCTL_SS_PORT_MAP_PORT_MASK <<
+				    XUSB_PADCTL_SS_PORT_MAP_PORTX_SHIFT(port));
+			regval |= value <<
+				XUSB_PADCTL_SS_PORT_MAP_PORTX_SHIFT(port);
+			padctl_writel(padctl, regval, XUSB_PADCTL_SS_PORT_MAP);
+			break;
+
+		case TEGRA_XUSB_PADCTL_HSIC_STROBE_TRIM:
+			if (!is_hsic_lane(group)) {
+				dev_err(padctl->dev, "Pin %d not an HSIC\n",
+					group);
+				return -EINVAL;
+			}
+
+			value &= XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL_STRB_TRIM_MASK;
+			padctl_writel(padctl, value,
+				      XUSB_PADCTL_HSIC_STRB_TRIM_CONTROL);
+			break;
+
+		case TEGRA_XUSB_PADCTL_HSIC_RX_STROBE_TRIM:
+			if (!is_hsic_lane(group)) {
+				dev_err(padctl->dev, "Pin %d not an HSIC\n",
+					group);
+				return -EINVAL;
+			}
+
+			port = group - TEGRA_XUSB_PADCTL_PIN_HSIC_0;
+			value &= XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_MASK;
+			regval = padctl_readl(padctl,
+					      XUSB_PADCTL_HSIC_PADX_CTL2(port));
+			regval &= ~(XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_MASK <<
+				    XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT);
+			regval |= value <<
+				XUSB_PADCTL_HSIC_PAD_CTL2_RX_STROBE_TRIM_SHIFT;
+			padctl_writel(padctl, regval,
+				      XUSB_PADCTL_HSIC_PADX_CTL2(port));
+			break;
+
+		case TEGRA_XUSB_PADCTL_HSIC_RX_DATA_TRIM:
+			if (!is_hsic_lane(group)) {
+				dev_err(padctl->dev, "Pin %d not an HSIC\n",
+					group);
+				return -EINVAL;
+			}
+
+			port = group - TEGRA_XUSB_PADCTL_PIN_HSIC_0;
+			value &= XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_MASK;
+			regval = padctl_readl(padctl,
+					      XUSB_PADCTL_HSIC_PADX_CTL2(port));
+			regval &= ~(XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_MASK <<
+				    XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT);
+			regval |= value <<
+				XUSB_PADCTL_HSIC_PAD_CTL2_RX_DATA_TRIM_SHIFT;
+			padctl_writel(padctl, regval,
+				      XUSB_PADCTL_HSIC_PADX_CTL2(port));
+			break;
+
+		case TEGRA_XUSB_PADCTL_HSIC_TX_RTUNEN:
+			if (!is_hsic_lane(group)) {
+				dev_err(padctl->dev, "Pin %d not an HSIC\n",
+					group);
+				return -EINVAL;
+			}
+
+			port = group - TEGRA_XUSB_PADCTL_PIN_HSIC_0;
+			value &= XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_MASK;
+			regval = padctl_readl(padctl,
+					      XUSB_PADCTL_HSIC_PADX_CTL0(port));
+			regval &= ~(XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_MASK <<
+				    XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_SHIFT);
+			regval |= value <<
+				XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEN_SHIFT;
+			padctl_writel(padctl, regval,
+				      XUSB_PADCTL_HSIC_PADX_CTL0(port));
+			break;
+
+		case TEGRA_XUSB_PADCTL_HSIC_TX_RTUNEP:
+			if (!is_hsic_lane(group)) {
+				dev_err(padctl->dev, "Pin %d not an HSIC\n",
+					group);
+				return -EINVAL;
+			}
+
+			port = group - TEGRA_XUSB_PADCTL_PIN_HSIC_0;
+			value &= XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_MASK;
+			regval = padctl_readl(padctl,
+					      XUSB_PADCTL_HSIC_PADX_CTL0(port));
+			regval &= ~(XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_MASK <<
+				    XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_SHIFT);
+			regval |= value <<
+				XUSB_PADCTL_HSIC_PAD_CTL0_TX_RTUNEP_SHIFT;
+			padctl_writel(padctl, regval,
+				      XUSB_PADCTL_HSIC_PADX_CTL0(port));
+			break;
+
+		case TEGRA_XUSB_PADCTL_HSIC_TX_RSLEWN:
+			if (!is_hsic_lane(group)) {
+				dev_err(padctl->dev, "Pin %d not an HSIC\n",
+					group);
+				return -EINVAL;
+			}
+
+			port = group - TEGRA_XUSB_PADCTL_PIN_HSIC_0;
+			value &= XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_MASK;
+			regval = padctl_readl(padctl,
+					      XUSB_PADCTL_HSIC_PADX_CTL0(port));
+			regval &= ~(XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_MASK <<
+				    XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_SHIFT);
+			regval |= value <<
+				XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWN_SHIFT;
+			padctl_writel(padctl, regval,
+				      XUSB_PADCTL_HSIC_PADX_CTL0(port));
+			break;
+
+		case TEGRA_XUSB_PADCTL_HSIC_TX_RSLEWP:
+			if (!is_hsic_lane(group)) {
+				dev_err(padctl->dev, "Pin %d not an HSIC\n",
+					group);
+				return -EINVAL;
+			}
+
+			port = group - TEGRA_XUSB_PADCTL_PIN_HSIC_0;
+			value &= XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_MASK;
+			regval = padctl_readl(padctl,
+					      XUSB_PADCTL_HSIC_PADX_CTL0(port));
+			regval &= ~(XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_MASK <<
+				    XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_SHIFT);
+			regval |= value <<
+				XUSB_PADCTL_HSIC_PAD_CTL0_TX_RSLEWP_SHIFT;
+			padctl_writel(padctl, regval,
+				      XUSB_PADCTL_HSIC_PADX_CTL0(port));
+			break;
+
+		case TEGRA_XUSB_PADCTL_HSIC_AUTO_TERM:
+			if (!is_hsic_lane(group)) {
+				dev_err(padctl->dev, "Pin %d not an HSIC\n",
+					group);
+				return -EINVAL;
+			}
+
+			port = group - TEGRA_XUSB_PADCTL_PIN_HSIC_0;
+			regval = padctl_readl(padctl,
+					      XUSB_PADCTL_HSIC_PADX_CTL1(port));
+			if (!value)
+				regval &= ~XUSB_PADCTL_HSIC_PAD_CTL1_AUTO_TERM_EN;
+			else
+				regval |= XUSB_PADCTL_HSIC_PAD_CTL1_AUTO_TERM_EN;
+			padctl_writel(padctl, regval,
+				      XUSB_PADCTL_HSIC_PADX_CTL1(port));
+			break;
+
 		default:
 			dev_err(padctl->dev,
 				"invalid configuration parameter: %04x\n",
@@ -671,6 +1181,506 @@ static const struct phy_ops sata_phy_ops = {
 	.owner = THIS_MODULE,
 };
 
+static int usb3_phy_to_port(struct phy *phy)
+{
+	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+	int i;
+
+	for (i = 0; i < TEGRA_XUSB_USB3_PHYS; i++) {
+		if (phy == padctl->phys[TEGRA_XUSB_PADCTL_USB3_P0 + i])
+			break;
+	}
+	BUG_ON(i == TEGRA_XUSB_USB3_PHYS);
+
+	return i;
+}
+
+static int usb3_phy_power_on(struct phy *phy)
+{
+	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+	int port = usb3_phy_to_port(phy);
+	int lane = padctl->usb3_ports[port].lane;
+	u32 value, offset;
+
+	if (!is_pcie_or_sata_lane(lane)) {
+		dev_err(padctl->dev, "USB3 PHY %d mapped to invalid lane: %d\n",
+			port, lane);
+		return -EINVAL;
+	}
+
+	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(port));
+	value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_MASK <<
+		    XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_SHIFT) |
+		   (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_MASK <<
+		    XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_SHIFT) |
+		   (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_MASK <<
+		    XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_SHIFT));
+	value |= (padctl->soc->rx_wander <<
+		  XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_WANDER_SHIFT) |
+		 (padctl->soc->cdr_cntl <<
+		  XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_CDR_CNTL_SHIFT) |
+		 (padctl->soc->rx_eq <<
+		  XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_SHIFT);
+	if (padctl->usb3_ports[port].context_saved) {
+		value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_MASK <<
+			    XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) |
+			   (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_MASK <<
+			    XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT));
+		value |= (padctl->usb3_ports[port].ctle_g_val <<
+			  XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) |
+			 (padctl->usb3_ports[port].ctle_z_val <<
+			  XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT);
+	}
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(port));
+
+	value = padctl->soc->dfe_cntl;
+	if (padctl->usb3_ports[port].context_saved) {
+		value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_MASK <<
+			    XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) |
+			   (XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_MASK <<
+			    XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT));
+		value |= (padctl->usb3_ports[port].tap1_val <<
+			  XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) |
+			 (padctl->usb3_ports[port].amp_val <<
+			  XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT);
+	}
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(port));
+
+	offset = (lane == TEGRA_XUSB_PADCTL_PIN_SATA_0) ?
+		XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL2 :
+		XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL2(lane -
+						TEGRA_XUSB_PADCTL_PIN_PCIE_0);
+	value = padctl_readl(padctl, offset);
+	value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_MASK <<
+		   XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_SHIFT);
+	value |= padctl->soc->spare_in <<
+		XUSB_PADCTL_IOPHY_MISC_PAD_CTL2_SPARE_IN_SHIFT;
+	padctl_writel(padctl, value, offset);
+
+	offset = (lane == TEGRA_XUSB_PADCTL_PIN_SATA_0) ?
+		XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL5 :
+		XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL5(lane -
+						TEGRA_XUSB_PADCTL_PIN_PCIE_0);
+	value = padctl_readl(padctl, offset);
+	value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL5_RX_QEYE_EN;
+	padctl_writel(padctl, value, offset);
+
+	/* Enable SATA PHY when SATA lane is used */
+	if (lane == TEGRA_XUSB_PADCTL_PIN_SATA_0) {
+		value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+		value &= ~(XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_MASK <<
+			   XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_SHIFT);
+		value |= 0x2 <<
+			XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL0_REFCLK_NDIV_SHIFT;
+		padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
+
+		value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL2);
+		value &= ~((XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_MASK <<
+			    XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_SHIFT) |
+			   (XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_MASK <<
+			    XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_SHIFT) |
+			   (XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_MASK <<
+			    XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_SHIFT) |
+			   XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TCLKOUT_EN);
+		value |= (0x7 <<
+			  XUSB_PADCTL_IOPHY_PLL_S0_CTL2_XDIGCLK_SEL_SHIFT) |
+			 (0x8 <<
+			  XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL1_CP_CNTL_SHIFT) |
+			 (0x8 <<
+			  XUSB_PADCTL_IOPHY_PLL_S0_CTL2_PLL0_CP_CNTL_SHIFT) |
+			 XUSB_PADCTL_IOPHY_PLL_S0_CTL2_TXCLKREF_SEL;
+		padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL2);
+
+		value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL3);
+		value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL3_RCAL_BYPASS;
+		padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL3);
+	}
+
+	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+	value &= ~XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN_EARLY(port);
+	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+	usleep_range(100, 200);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+	value &= ~XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN_EARLY(port);
+	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+	value &= ~XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_VCORE_DOWN(port);
+	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+	return 0;
+}
+
+static int usb3_phy_power_off(struct phy *phy)
+{
+	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+	int port = usb3_phy_to_port(phy);
+	u32 value;
+
+	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+	value |= XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN_EARLY(port);
+	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+	usleep_range(100, 200);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+	value |= XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_CLAMP_EN_EARLY(port);
+	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+	usleep_range(250, 350);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
+	value |= XUSB_PADCTL_ELPG_PROGRAM_SSPX_ELPG_VCORE_DOWN(port);
+	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
+
+	return 0;
+}
+
+static void usb3_phy_save_context(struct tegra_xusb_padctl *padctl, int port)
+{
+	int lane = padctl->usb3_ports[port].lane;
+	u32 value, offset;
+
+	padctl->usb3_ports[port].context_saved = true;
+
+	offset = (lane == TEGRA_XUSB_PADCTL_PIN_SATA_0) ?
+		XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL6 :
+		XUSB_PADCTL_IOPHY_MISC_PAD_PX_CTL6(lane -
+						TEGRA_XUSB_PADCTL_PIN_PCIE_0);
+
+	value = padctl_readl(padctl, offset);
+	value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK <<
+		   XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT);
+	value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_TAP <<
+		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT;
+	padctl_writel(padctl, value, offset);
+
+	value = padctl_readl(padctl, offset) >>
+		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT;
+	padctl->usb3_ports[port].tap1_val = value &
+		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_TAP_MASK;
+
+	value = padctl_readl(padctl, offset);
+	value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK <<
+		   XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT);
+	value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_AMP <<
+		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT;
+	padctl_writel(padctl, value, offset);
+
+	value = padctl_readl(padctl, offset) >>
+		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT;
+	padctl->usb3_ports[port].amp_val = value &
+		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_AMP_MASK;
+
+	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(port));
+	value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_MASK <<
+		    XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) |
+		   (XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_MASK <<
+		    XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT));
+	value |= (padctl->usb3_ports[port].tap1_val <<
+		  XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_TAP_SHIFT) |
+		 (padctl->usb3_ports[port].amp_val <<
+		  XUSB_PADCTL_IOPHY_USB3_PAD_CTL4_DFE_CNTL_AMP_SHIFT);
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL4(port));
+
+	value = padctl_readl(padctl, offset);
+	value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK <<
+		   XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT);
+	value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_LATCH_G_Z <<
+		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT;
+	padctl_writel(padctl, value, offset);
+
+	value = padctl_readl(padctl, offset);
+	value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK <<
+		   XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT);
+	value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_G_Z <<
+		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT;
+	padctl_writel(padctl, value, offset);
+
+	value = padctl_readl(padctl, offset) >>
+		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT;
+	padctl->usb3_ports[port].ctle_g_val = value &
+		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_G_Z_MASK;
+
+	value = padctl_readl(padctl, offset);
+	value &= ~(XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_MASK <<
+		   XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT);
+	value |= XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_CTLE_Z <<
+		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SEL_SHIFT;
+	padctl_writel(padctl, value, offset);
+
+	value = padctl_readl(padctl, offset) >>
+		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_SHIFT;
+	padctl->usb3_ports[port].ctle_z_val = value &
+		XUSB_PADCTL_IOPHY_MISC_PAD_CTL6_MISC_OUT_G_Z_MASK;
+
+	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(port));
+	value &= ~((XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_MASK <<
+		    XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) |
+		   (XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_MASK <<
+		    XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT));
+	value |= (padctl->usb3_ports[port].ctle_g_val <<
+		  XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_G_SHIFT) |
+		 (padctl->usb3_ports[port].ctle_z_val <<
+		  XUSB_PADCTL_IOPHY_USB3_PAD_CTL2_RX_EQ_Z_SHIFT);
+	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_USB3_PADX_CTL2(port));
+}
+
+static const struct phy_ops usb3_phy_ops = {
+	.init = tegra_xusb_phy_init,
+	.exit = tegra_xusb_phy_exit,
+	.power_on = usb3_phy_power_on,
+	.power_off = usb3_phy_power_off,
+	.owner = THIS_MODULE,
+};
+
+static int utmi_phy_to_port(struct phy *phy)
+{
+	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+	int i;
+
+	for (i = 0; i < TEGRA_XUSB_UTMI_PHYS; i++) {
+		if (phy == padctl->phys[TEGRA_XUSB_PADCTL_UTMI_P0 + i])
+			break;
+	}
+	BUG_ON(i == TEGRA_XUSB_UTMI_PHYS);
+
+	return i;
+}
+
+static int utmi_phy_power_on(struct phy *phy)
+{
+	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+	int port = utmi_phy_to_port(phy);
+	int ret;
+	u32 value;
+
+	value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
+	value &= ~((XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_MASK <<
+		    XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT) |
+		   (XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_MASK <<
+		    XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT));
+	value |= (padctl->calib.hs_squelch_level <<
+		  XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT) |
+		 (padctl->soc->hs_discon_level <<
+		  XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_DISCON_LEVEL_SHIFT);
+	padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_USB2_PORT_CAP);
+	value &= ~(XUSB_PADCTL_USB2_PORT_CAP_PORT_CAP_MASK <<
+		   XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_SHIFT(port));
+	value |= XUSB_PADCTL_USB2_PORT_CAP_HOST <<
+		XUSB_PADCTL_USB2_PORT_CAP_PORTX_CAP_SHIFT(port);
+	padctl_writel(padctl, value, XUSB_PADCTL_USB2_PORT_CAP);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL0(port));
+	value &= ~((XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK <<
+		    XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT) |
+		   (XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_MASK <<
+		    XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_SHIFT) |
+		   (XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_MASK <<
+		    XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_SHIFT) |
+		   XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD |
+		   XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 |
+		   XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI);
+	value |= padctl->calib.hs_curr_level[port] <<
+		XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT;
+	value |= padctl->soc->hs_slew <<
+		XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_SHIFT;
+	value |= padctl->soc->ls_rslew[port] <<
+		XUSB_PADCTL_USB2_OTG_PAD_CTL0_LS_RSLEW_SHIFT;
+	padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL0(port));
+
+	value = padctl_readl(padctl, XUSB_PADCTL_USB2_OTG_PADX_CTL1(port));
+	value &= ~((XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_MASK <<
+		    XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT) |
+		   (XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_MASK <<
+		    XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_SHIFT) |
+		   XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DR |
+		   XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_CHRP_FORCE_POWERUP |
+		   XUSB_PADCTL_USB2_OTG_PAD_CTL1_PD_DISC_FORCE_POWERUP);
+	value |= (padctl->calib.hs_term_range_adj <<
+		  XUSB_PADCTL_USB2_OTG_PAD_CTL1_TERM_RANGE_ADJ_SHIFT) |
+		 (padctl->calib.hs_iref_cap <<
+		  XUSB_PADCTL_USB2_OTG_PAD_CTL1_HS_IREF_CAP_SHIFT);
+	padctl_writel(padctl, value, XUSB_PADCTL_USB2_OTG_PADX_CTL1(port));
+
+	ret = regulator_enable(padctl->vbus[port]);
+	if (ret)
+		return ret;
+
+	mutex_lock(&padctl->lock);
+
+	if (padctl->utmi_enable++ > 0)
+		goto out;
+
+	value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
+	value &= ~XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD;
+	padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
+
+out:
+	mutex_unlock(&padctl->lock);
+	return 0;
+}
+
+static int utmi_phy_power_off(struct phy *phy)
+{
+	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+	int port = utmi_phy_to_port(phy);
+	u32 value;
+
+	regulator_disable(padctl->vbus[port]);
+
+	mutex_lock(&padctl->lock);
+
+	if (WARN_ON(padctl->utmi_enable == 0))
+		goto out;
+
+	if (--padctl->utmi_enable > 0)
+		goto out;
+
+	value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
+	value |= XUSB_PADCTL_USB2_BIAS_PAD_CTL0_PD;
+	padctl_writel(padctl, value, XUSB_PADCTL_USB2_BIAS_PAD_CTL0);
+
+out:
+	mutex_unlock(&padctl->lock);
+	return 0;
+}
+
+static const struct phy_ops utmi_phy_ops = {
+	.init = tegra_xusb_phy_init,
+	.exit = tegra_xusb_phy_exit,
+	.power_on = utmi_phy_power_on,
+	.power_off = utmi_phy_power_off,
+	.owner = THIS_MODULE,
+};
+
+static int hsic_phy_to_port(struct phy *phy)
+{
+	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+	int i;
+
+	for (i = 0; i < TEGRA_XUSB_HSIC_PHYS; i++) {
+		if (phy == padctl->phys[TEGRA_XUSB_PADCTL_HSIC_P0 + i])
+			break;
+	}
+	BUG_ON(i == TEGRA_XUSB_HSIC_PHYS);
+
+	return i;
+}
+
+static int hsic_phy_power_on(struct phy *phy)
+{
+	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+	int port = hsic_phy_to_port(phy);
+	int ret;
+	u32 value;
+
+	ret = regulator_enable(padctl->vddio_hsic);
+	if (ret)
+		return ret;
+
+	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(port));
+	value &= ~(XUSB_PADCTL_HSIC_PAD_CTL1_RPD_STROBE |
+		   XUSB_PADCTL_HSIC_PAD_CTL1_RPU_DATA |
+		   XUSB_PADCTL_HSIC_PAD_CTL1_PD_RX |
+		   XUSB_PADCTL_HSIC_PAD_CTL1_PD_ZI |
+		   XUSB_PADCTL_HSIC_PAD_CTL1_PD_TRX |
+		   XUSB_PADCTL_HSIC_PAD_CTL1_PD_TX);
+	value |= XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA |
+		 XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE;
+	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(port));
+
+	return 0;
+}
+
+static int hsic_phy_power_off(struct phy *phy)
+{
+	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
+	int port = hsic_phy_to_port(phy);
+	u32 value;
+
+	regulator_disable(padctl->vddio_hsic);
+
+	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(port));
+	value |= XUSB_PADCTL_HSIC_PAD_CTL1_PD_RX |
+		 XUSB_PADCTL_HSIC_PAD_CTL1_PD_ZI |
+		 XUSB_PADCTL_HSIC_PAD_CTL1_PD_TRX |
+		 XUSB_PADCTL_HSIC_PAD_CTL1_PD_TX;
+	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(port));
+
+	return 0;
+}
+
+static void hsic_phy_set_idle(struct tegra_xusb_padctl *padctl, int port,
+			      bool set)
+{
+	u32 value;
+
+	value = padctl_readl(padctl, XUSB_PADCTL_HSIC_PADX_CTL1(port));
+	if (set)
+		value |= XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA |
+			 XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE;
+	else
+		value &= ~(XUSB_PADCTL_HSIC_PAD_CTL1_RPD_DATA |
+			   XUSB_PADCTL_HSIC_PAD_CTL1_RPU_STROBE);
+	padctl_writel(padctl, value, XUSB_PADCTL_HSIC_PADX_CTL1(port));
+}
+
+static const struct phy_ops hsic_phy_ops = {
+	.init = tegra_xusb_phy_init,
+	.exit = tegra_xusb_phy_exit,
+	.power_on = hsic_phy_power_on,
+	.power_off = hsic_phy_power_off,
+	.owner = THIS_MODULE,
+};
+
+static void tegra_xusb_phy_mbox_rx(struct mbox_client *cl, void *data)
+{
+	struct tegra_xusb_padctl *padctl = dev_get_drvdata(cl->dev);
+	struct tegra_xusb_mbox_msg *msg = data;
+	struct tegra_xusb_mbox_msg resp;
+	u32 ports;
+	int i;
+
+	switch (msg->cmd) {
+	case MBOX_CMD_SAVE_DFE_CTLE_CTX:
+		resp.data = msg->data;
+		if (msg->data > TEGRA_XUSB_USB3_PHYS) {
+			resp.cmd = MBOX_CMD_NAK;
+		} else {
+			usb3_phy_save_context(padctl, msg->data);
+			resp.cmd = MBOX_CMD_ACK;
+		}
+		break;
+	case MBOX_CMD_START_HSIC_IDLE:
+	case MBOX_CMD_STOP_HSIC_IDLE:
+		ports = msg->data >> (padctl->soc->hsic_port_offset + 1);
+		resp.data = msg->data;
+		resp.cmd = MBOX_CMD_ACK;
+		for (i = 0; i < TEGRA_XUSB_HSIC_PHYS; i++) {
+			if (!(ports & BIT(i)))
+				continue;
+			if (msg->cmd == MBOX_CMD_START_HSIC_IDLE)
+				hsic_phy_set_idle(padctl, i, true);
+			else
+				hsic_phy_set_idle(padctl, i, false);
+		}
+		break;
+	default:
+		dev_err(padctl->dev, "Unexpected message: 0x%x:0x%x\n",
+			msg->cmd, msg->data);
+		resp.data = 0;
+		resp.cmd = MBOX_CMD_NAK;
+		break;
+	}
+
+	mbox_send_message(padctl->mbox_chan, &resp);
+}
+
 static struct phy *tegra_xusb_padctl_xlate(struct device *dev,
 					   struct of_phandle_args *args)
 {
@@ -686,32 +1696,19 @@ static struct phy *tegra_xusb_padctl_xlate(struct device *dev,
 	return padctl->phys[index];
 }
 
-#define PIN_OTG_0   0
-#define PIN_OTG_1   1
-#define PIN_OTG_2   2
-#define PIN_ULPI_0  3
-#define PIN_HSIC_0  4
-#define PIN_HSIC_1  5
-#define PIN_PCIE_0  6
-#define PIN_PCIE_1  7
-#define PIN_PCIE_2  8
-#define PIN_PCIE_3  9
-#define PIN_PCIE_4 10
-#define PIN_SATA_0 11
-
 static const struct pinctrl_pin_desc tegra124_pins[] = {
-	PINCTRL_PIN(PIN_OTG_0,  "otg-0"),
-	PINCTRL_PIN(PIN_OTG_1,  "otg-1"),
-	PINCTRL_PIN(PIN_OTG_2,  "otg-2"),
-	PINCTRL_PIN(PIN_ULPI_0, "ulpi-0"),
-	PINCTRL_PIN(PIN_HSIC_0, "hsic-0"),
-	PINCTRL_PIN(PIN_HSIC_1, "hsic-1"),
-	PINCTRL_PIN(PIN_PCIE_0, "pcie-0"),
-	PINCTRL_PIN(PIN_PCIE_1, "pcie-1"),
-	PINCTRL_PIN(PIN_PCIE_2, "pcie-2"),
-	PINCTRL_PIN(PIN_PCIE_3, "pcie-3"),
-	PINCTRL_PIN(PIN_PCIE_4, "pcie-4"),
-	PINCTRL_PIN(PIN_SATA_0, "sata-0"),
+	PINCTRL_PIN(TEGRA_XUSB_PADCTL_PIN_OTG_0,  "otg-0"),
+	PINCTRL_PIN(TEGRA_XUSB_PADCTL_PIN_OTG_1,  "otg-1"),
+	PINCTRL_PIN(TEGRA_XUSB_PADCTL_PIN_OTG_2,  "otg-2"),
+	PINCTRL_PIN(TEGRA_XUSB_PADCTL_PIN_ULPI_0, "ulpi-0"),
+	PINCTRL_PIN(TEGRA_XUSB_PADCTL_PIN_HSIC_0, "hsic-0"),
+	PINCTRL_PIN(TEGRA_XUSB_PADCTL_PIN_HSIC_1, "hsic-1"),
+	PINCTRL_PIN(TEGRA_XUSB_PADCTL_PIN_PCIE_0, "pcie-0"),
+	PINCTRL_PIN(TEGRA_XUSB_PADCTL_PIN_PCIE_1, "pcie-1"),
+	PINCTRL_PIN(TEGRA_XUSB_PADCTL_PIN_PCIE_2, "pcie-2"),
+	PINCTRL_PIN(TEGRA_XUSB_PADCTL_PIN_PCIE_3, "pcie-3"),
+	PINCTRL_PIN(TEGRA_XUSB_PADCTL_PIN_PCIE_4, "pcie-4"),
+	PINCTRL_PIN(TEGRA_XUSB_PADCTL_PIN_SATA_0, "sata-0"),
 };
 
 static const char * const tegra124_snps_groups[] = {
@@ -856,6 +1853,15 @@ static const struct tegra_xusb_padctl_soc tegra124_soc = {
 	.functions = tegra124_functions,
 	.num_lanes = ARRAY_SIZE(tegra124_lanes),
 	.lanes = tegra124_lanes,
+	.rx_wander = 0xf,
+	.rx_eq = 0xf070,
+	.cdr_cntl = 0x24,
+	.dfe_cntl = 0x002008ee,
+	.hs_slew = 0xe,
+	.ls_rslew = {0x3, 0x0, 0x0},
+	.hs_discon_level = 0x5,
+	.spare_in = 0x1,
+	.hsic_port_offset = 6,
 };
 
 static const struct of_device_id tegra_xusb_padctl_of_match[] = {
@@ -864,13 +1870,40 @@ static const struct of_device_id tegra_xusb_padctl_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, tegra_xusb_padctl_of_match);
 
+static int tegra_xusb_read_fuse_calibration(struct tegra_xusb_padctl *padctl)
+{
+	int i, ret;
+	u32 value;
+
+	ret = tegra_fuse_readl(TEGRA_FUSE_SKU_CALIB_0, &value);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < TEGRA_XUSB_UTMI_PHYS; i++) {
+		padctl->calib.hs_curr_level[i] =
+			(value >> FUSE_SKU_CALIB_HS_CURR_LEVEL_PADX_SHIFT(i)) &
+			FUSE_SKU_CALIB_HS_CURR_LEVEL_PAD_MASK;
+	}
+	padctl->calib.hs_iref_cap =
+		(value >> FUSE_SKU_CALIB_HS_IREF_CAP_SHIFT) &
+		FUSE_SKU_CALIB_HS_IREF_CAP_MASK;
+	padctl->calib.hs_term_range_adj =
+		(value >> FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_SHIFT) &
+		FUSE_SKU_CALIB_HS_TERM_RANGE_ADJ_MASK;
+	padctl->calib.hs_squelch_level =
+		(value >> FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_SHIFT) &
+		FUSE_SKU_CALIB_HS_SQUELCH_LEVEL_MASK;
+
+	return 0;
+}
+
 static int tegra_xusb_padctl_probe(struct platform_device *pdev)
 {
 	struct tegra_xusb_padctl *padctl;
 	const struct of_device_id *match;
 	struct resource *res;
 	struct phy *phy;
-	int err;
+	int err, i;
 
 	padctl = devm_kzalloc(&pdev->dev, sizeof(*padctl), GFP_KERNEL);
 	if (!padctl)
@@ -888,6 +1921,10 @@ static int tegra_xusb_padctl_probe(struct platform_device *pdev)
 	if (IS_ERR(padctl->regs))
 		return PTR_ERR(padctl->regs);
 
+	err = tegra_xusb_read_fuse_calibration(padctl);
+	if (err < 0)
+		return err;
+
 	padctl->rst = devm_reset_control_get(&pdev->dev, NULL);
 	if (IS_ERR(padctl->rst))
 		return PTR_ERR(padctl->rst);
@@ -896,6 +1933,22 @@ static int tegra_xusb_padctl_probe(struct platform_device *pdev)
 	if (err < 0)
 		return err;
 
+	for (i = 0; i < TEGRA_XUSB_USB3_PHYS; i++) {
+		char prop[sizeof("nvidia,usb3-port-N-lane")];
+		u32 lane;
+
+		sprintf(prop, "nvidia,usb3-port-%d-lane", i);
+		if (!of_property_read_u32(pdev->dev.of_node, prop, &lane)) {
+			if (!is_pcie_or_sata_lane(lane)) {
+				err = -EINVAL;
+				goto unregister;
+			}
+			padctl->usb3_ports[i].lane = lane;
+		} else {
+			padctl->usb3_ports[i].lane = -EINVAL;
+		}
+	}
+
 	memset(&padctl->desc, 0, sizeof(padctl->desc));
 	padctl->desc.name = dev_name(padctl->dev);
 	padctl->desc.pctlops = &tegra_xusb_padctl_pinctrl_ops;
@@ -928,6 +1981,54 @@ static int tegra_xusb_padctl_probe(struct platform_device *pdev)
 	padctl->phys[TEGRA_XUSB_PADCTL_SATA] = phy;
 	phy_set_drvdata(phy, padctl);
 
+	for (i = 0; i < TEGRA_XUSB_USB3_PHYS; i++) {
+		phy = devm_phy_create(&pdev->dev, NULL, &usb3_phy_ops, NULL);
+		if (IS_ERR(phy)) {
+			err = PTR_ERR(phy);
+			goto unregister;
+		}
+
+		padctl->phys[TEGRA_XUSB_PADCTL_USB3_P0 + i] = phy;
+		phy_set_drvdata(phy, padctl);
+	}
+
+	for (i = 0; i < TEGRA_XUSB_UTMI_PHYS; i++) {
+		char reg_name[sizeof("vbus-otg-N")];
+
+		sprintf(reg_name, "vbus-otg-%d", i);
+		padctl->vbus[i] = devm_regulator_get(&pdev->dev, reg_name);
+		if (IS_ERR(padctl->vbus[i])) {
+			err = PTR_ERR(padctl->vbus[i]);
+			goto unregister;
+		}
+
+		phy = devm_phy_create(&pdev->dev, NULL, &utmi_phy_ops, NULL);
+		if (IS_ERR(phy)) {
+			err = PTR_ERR(phy);
+			goto unregister;
+		}
+
+		padctl->phys[TEGRA_XUSB_PADCTL_UTMI_P0 + i] = phy;
+		phy_set_drvdata(phy, padctl);
+	}
+
+	padctl->vddio_hsic = devm_regulator_get(&pdev->dev, "vddio-hsic");
+	if (IS_ERR(padctl->vddio_hsic)) {
+		err = PTR_ERR(padctl->vddio_hsic);
+		goto unregister;
+	}
+
+	for (i = 0; i < TEGRA_XUSB_HSIC_PHYS; i++) {
+		phy = devm_phy_create(&pdev->dev, NULL, &hsic_phy_ops, NULL);
+		if (IS_ERR(phy)) {
+			err = PTR_ERR(phy);
+			goto unregister;
+		}
+
+		padctl->phys[TEGRA_XUSB_PADCTL_HSIC_P0 + i] = phy;
+		phy_set_drvdata(phy, padctl);
+	}
+
 	padctl->provider = devm_of_phy_provider_register(&pdev->dev,
 							 tegra_xusb_padctl_xlate);
 	if (err < 0) {
@@ -935,6 +2036,17 @@ static int tegra_xusb_padctl_probe(struct platform_device *pdev)
 		goto unregister;
 	}
 
+	padctl->mbox_client.dev = &pdev->dev;
+	padctl->mbox_client.tx_block = true;
+	padctl->mbox_client.tx_tout = 0;
+	padctl->mbox_client.rx_callback = tegra_xusb_phy_mbox_rx;
+	padctl->mbox_chan = mbox_request_channel(&padctl->mbox_client, 0);
+	if (IS_ERR(padctl->mbox_chan)) {
+		err = PTR_ERR(padctl->mbox_chan);
+		dev_err(&pdev->dev, "failed to request mailbox: %d\n", err);
+		goto unregister;
+	}
+
 	return 0;
 
 unregister:
@@ -949,6 +2061,8 @@ static int tegra_xusb_padctl_remove(struct platform_device *pdev)
 	struct tegra_xusb_padctl *padctl = platform_get_drvdata(pdev);
 	int err;
 
+	mbox_free_channel(padctl->mbox_chan);
+
 	pinctrl_unregister(padctl->pinctrl);
 
 	err = reset_control_assert(padctl->rst);
diff --git a/include/soc/tegra/xusb.h b/include/soc/tegra/xusb.h
index 8efef8c..1bac2ab 100644
--- a/include/soc/tegra/xusb.h
+++ b/include/soc/tegra/xusb.h
@@ -10,6 +10,13 @@
 #ifndef __SOC_TEGRA_XUSB_H__
 #define __SOC_TEGRA_XUSB_H__
 
+#define TEGRA_XUSB_USB3_PHYS 2
+#define TEGRA_XUSB_UTMI_PHYS 3
+#define TEGRA_XUSB_HSIC_PHYS 2
+#define TEGRA_XUSB_NUM_USB_PHYS (TEGRA_XUSB_USB3_PHYS + TEGRA_XUSB_UTMI_PHYS + \
+				 TEGRA_XUSB_HSIC_PHYS)
+#define TEGRA_XUSB_NUM_PHYS (TEGRA_XUSB_NUM_USB_PHYS + 2) /* + SATA & PCIe */
+
 #define TEGRA_XUSB_MBOX_NUM_CHANS 2 /* host + phy */
 
 /* Command requests from the firmware */
-- 
2.1.0.rc2.206.gedb03e5

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

* [PATCH v2 5/9] of: Add NVIDIA Tegra xHCI controller binding
  2014-08-18 17:08 ` Andrew Bresticker
  (?)
@ 2014-08-18 17:08   ` Andrew Bresticker
  -1 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-18 17:08 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, linux-tegra
  Cc: Mark Rutland, devicetree, linux-usb, Russell King, Mathias Nyman,
	Pawel Moll, Ian Campbell, Andrew Bresticker, Greg Kroah-Hartman,
	Linus Walleij, Jassi Brar, linux-kernel, Kishon Vijay Abraham I,
	Rob Herring, Alan Stern, linux-arm-kernel, Kumar Gala,
	Grant Likely, Arnd Bergmann

Add device-tree binding documentation for the xHCI controller present
on Tegra124 and later SoCs.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
---
Changes from v1:
 - Updated to use common mailbox bindings.
 - Added remaining XUSB-related clocks and resets.
 - Updated list of power supplies to be more accurate wrt to the hardware.
---
 .../bindings/usb/nvidia,tegra124-xhci.txt          | 101 +++++++++++++++++++++
 1 file changed, 101 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/nvidia,tegra124-xhci.txt

diff --git a/Documentation/devicetree/bindings/usb/nvidia,tegra124-xhci.txt b/Documentation/devicetree/bindings/usb/nvidia,tegra124-xhci.txt
new file mode 100644
index 0000000..ed1f8cd
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/nvidia,tegra124-xhci.txt
@@ -0,0 +1,101 @@
+NVIDIA Tegra xHCI controller
+============================
+
+The Tegra xHCI controller supports both USB2 and USB3 interfaces exposed
+by the Tegra XUSB pad controller.
+
+Required properties:
+--------------------
+ - compatible: Should be "nvidia,tegra124-xhci".
+ - reg: Address and length of the register sets.  There should be three
+   entries in the following order: xHCI host registers, FPCI registers, and
+   IPFS registers.
+ - interrupts: xHCI host interrupt.
+ - clocks: Must contain an entry for each entry in clock-names.
+   See ../clock/clock-bindings.txt for details.
+ - clock-names: Must include the following entries:
+    - xusb_host
+    - xusb_host_src
+    - xusb_dev
+    - xusb_dev_src
+    - xusb_falcon_src
+    - xusb_ss
+    - xusb_ss_src
+    - xusb_ss_div2
+    - xusb_hs_src
+    - xusb_fs_src
+    - pll_u_480m
+    - clk_m
+    - pll_e
+ - resets: Must contain an entry for each entry in reset-names.
+   See ../reset/reset.txt for details.
+ - reset-names: Must include the following entries:
+   - xusb_host
+   - xusb_dev
+   - xusb_ss
+   - xusb
+   Note that xusb_dev is the shared reset for xusb_dev and xusb_dev_src and
+   that xusb is the shared reset for xusb_{ss,hs,fs,falcon,host}_src.
+ - mboxes: Must contain an entry for the XUSB host mailbox channel.
+   See ../mailbox/mailbox.txt for details.
+
+Optional properties:
+--------------------
+ - phys: Must contain an entry for each entry in phy-names.
+   See ../phy/phy-bindings.txt for details.
+ - phy-names: Should include an entry for each PHY used by the controller.
+   May be a subset of the following:
+    - utmi-{0,1,2}
+    - hsic-{0,1}
+    - usb3-{0,1}
+ - avddio-pex-supply: PCIe/USB3 analog logic power supply.  Must supply 1.05V.
+ - dvddio-pex-supply: PCIe/USB3 digital logic power supply.  Must supply 1.05V.
+ - avdd-usb-supply: USB controller power supply.  Must supply 3.3V.
+ - avdd-pll-utmip-supply: UTMI PLL power supply.  Must supply 1.8V.
+ - avdd-pll-erefe-supply: PLLE reference PLL power supply.  Must supply 1.05V.
+ - avdd-pex-pll-supply: PCIe/USB3 PLL power supply.  Must supply 1.05V.
+ - hvdd-pex-supply: High-voltage PCIe/USB3 power supply.  Must supply 3.3V.
+ - hvdd-pex-plle-supply: High-voltage PLLE power supply.  Must supply 3.3V.
+
+Example:
+--------
+	usb@0,70090000 {
+		compatible = "nvidia,tegra124-xhci";
+		reg = <0x0 0x70090000 0x0 0x8000>,
+		      <0x0 0x70098000 0x0 0x1000>,
+		      <0x0 0x70099000 0x0 0x1000>;
+		interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&tegra_car TEGRA124_CLK_XUSB_HOST>,
+			 <&tegra_car TEGRA124_CLK_XUSB_HOST_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_DEV>,
+			 <&tegra_car TEGRA124_CLK_XUSB_DEV_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_FALCON_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_SS>,
+			 <&tegra_car TEGRA124_CLK_XUSB_SS_DIV2>,
+			 <&tegra_car TEGRA124_CLK_XUSB_SS_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_HS_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_FS_SRC>,
+			 <&tegra_car TEGRA124_CLK_PLL_U_480M>,
+			 <&tegra_car TEGRA124_CLK_CLK_M>,
+			 <&tegra_car TEGRA124_CLK_PLL_E>;
+		clock-names = "xusb_host", "xusb_host_src", "xusb_dev",
+			      "xusb_dev_src", "xusb_falcon_src", "xusb_ss",
+			      "xusb_ss_div2", "xusb_ss_src", "xusb_hs_src",
+			      "xusb_fs_src", "pll_u_480m", "clk_m", "pll_e";
+		resets = <&tegra_car 89>, <&tegra_car 95>, <&tegra_car 156>,
+			 <&tegra_car 143>;
+		reset-names = "xusb_host", "xusb_dev", "xusb_ss", "xusb";
+		mboxes = <&mbox TEGRA_XUSB_MBOX_CHAN_HOST>;
+		phys = <&padctl TEGRA_XUSB_PADCTL_UTMI_P1>, /* mini-PCIe USB */
+		       <&padctl TEGRA_XUSB_PADCTL_UTMI_P2>, /* USB A */
+		       <&padctl TEGRA_XUSB_PADCTL_USB3_P0>; /* USB A */
+		phy-names = "utmi-1", "utmi-2", "usb3-0";
+		avddio-pex-supply = <&vdd_1v05_run>;
+		dvddio-pex-supply = <&vdd_1v05_run>;
+		avdd-usb-supply = <&vdd_3v3_lp0>;
+		avdd-pll-utmip-supply = <&vddio_1v8>;
+		avdd-pll-erefe-supply = <&avdd_1v05_run>;
+		avdd-pex-pll-supply = <&vdd_1v05_run>;
+		hvdd-pex-supply = <&vdd_3v3_lp0>;
+		hvdd-pex-plle-supply = <&vdd_3v3_lp0>;
+	};
-- 
2.1.0.rc2.206.gedb03e5

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

* [PATCH v2 5/9] of: Add NVIDIA Tegra xHCI controller binding
@ 2014-08-18 17:08   ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-18 17:08 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, linux-tegra
  Cc: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Jassi Brar, Linus Walleij, Greg Kroah-Hartman,
	Mathias Nyman, Grant Likely, Alan Stern, Arnd Bergmann,
	Kishon Vijay Abraham I, devicetree, linux-kernel,
	linux-arm-kernel, linux-usb, Andrew Bresticker

Add device-tree binding documentation for the xHCI controller present
on Tegra124 and later SoCs.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
---
Changes from v1:
 - Updated to use common mailbox bindings.
 - Added remaining XUSB-related clocks and resets.
 - Updated list of power supplies to be more accurate wrt to the hardware.
---
 .../bindings/usb/nvidia,tegra124-xhci.txt          | 101 +++++++++++++++++++++
 1 file changed, 101 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/nvidia,tegra124-xhci.txt

diff --git a/Documentation/devicetree/bindings/usb/nvidia,tegra124-xhci.txt b/Documentation/devicetree/bindings/usb/nvidia,tegra124-xhci.txt
new file mode 100644
index 0000000..ed1f8cd
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/nvidia,tegra124-xhci.txt
@@ -0,0 +1,101 @@
+NVIDIA Tegra xHCI controller
+============================
+
+The Tegra xHCI controller supports both USB2 and USB3 interfaces exposed
+by the Tegra XUSB pad controller.
+
+Required properties:
+--------------------
+ - compatible: Should be "nvidia,tegra124-xhci".
+ - reg: Address and length of the register sets.  There should be three
+   entries in the following order: xHCI host registers, FPCI registers, and
+   IPFS registers.
+ - interrupts: xHCI host interrupt.
+ - clocks: Must contain an entry for each entry in clock-names.
+   See ../clock/clock-bindings.txt for details.
+ - clock-names: Must include the following entries:
+    - xusb_host
+    - xusb_host_src
+    - xusb_dev
+    - xusb_dev_src
+    - xusb_falcon_src
+    - xusb_ss
+    - xusb_ss_src
+    - xusb_ss_div2
+    - xusb_hs_src
+    - xusb_fs_src
+    - pll_u_480m
+    - clk_m
+    - pll_e
+ - resets: Must contain an entry for each entry in reset-names.
+   See ../reset/reset.txt for details.
+ - reset-names: Must include the following entries:
+   - xusb_host
+   - xusb_dev
+   - xusb_ss
+   - xusb
+   Note that xusb_dev is the shared reset for xusb_dev and xusb_dev_src and
+   that xusb is the shared reset for xusb_{ss,hs,fs,falcon,host}_src.
+ - mboxes: Must contain an entry for the XUSB host mailbox channel.
+   See ../mailbox/mailbox.txt for details.
+
+Optional properties:
+--------------------
+ - phys: Must contain an entry for each entry in phy-names.
+   See ../phy/phy-bindings.txt for details.
+ - phy-names: Should include an entry for each PHY used by the controller.
+   May be a subset of the following:
+    - utmi-{0,1,2}
+    - hsic-{0,1}
+    - usb3-{0,1}
+ - avddio-pex-supply: PCIe/USB3 analog logic power supply.  Must supply 1.05V.
+ - dvddio-pex-supply: PCIe/USB3 digital logic power supply.  Must supply 1.05V.
+ - avdd-usb-supply: USB controller power supply.  Must supply 3.3V.
+ - avdd-pll-utmip-supply: UTMI PLL power supply.  Must supply 1.8V.
+ - avdd-pll-erefe-supply: PLLE reference PLL power supply.  Must supply 1.05V.
+ - avdd-pex-pll-supply: PCIe/USB3 PLL power supply.  Must supply 1.05V.
+ - hvdd-pex-supply: High-voltage PCIe/USB3 power supply.  Must supply 3.3V.
+ - hvdd-pex-plle-supply: High-voltage PLLE power supply.  Must supply 3.3V.
+
+Example:
+--------
+	usb@0,70090000 {
+		compatible = "nvidia,tegra124-xhci";
+		reg = <0x0 0x70090000 0x0 0x8000>,
+		      <0x0 0x70098000 0x0 0x1000>,
+		      <0x0 0x70099000 0x0 0x1000>;
+		interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&tegra_car TEGRA124_CLK_XUSB_HOST>,
+			 <&tegra_car TEGRA124_CLK_XUSB_HOST_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_DEV>,
+			 <&tegra_car TEGRA124_CLK_XUSB_DEV_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_FALCON_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_SS>,
+			 <&tegra_car TEGRA124_CLK_XUSB_SS_DIV2>,
+			 <&tegra_car TEGRA124_CLK_XUSB_SS_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_HS_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_FS_SRC>,
+			 <&tegra_car TEGRA124_CLK_PLL_U_480M>,
+			 <&tegra_car TEGRA124_CLK_CLK_M>,
+			 <&tegra_car TEGRA124_CLK_PLL_E>;
+		clock-names = "xusb_host", "xusb_host_src", "xusb_dev",
+			      "xusb_dev_src", "xusb_falcon_src", "xusb_ss",
+			      "xusb_ss_div2", "xusb_ss_src", "xusb_hs_src",
+			      "xusb_fs_src", "pll_u_480m", "clk_m", "pll_e";
+		resets = <&tegra_car 89>, <&tegra_car 95>, <&tegra_car 156>,
+			 <&tegra_car 143>;
+		reset-names = "xusb_host", "xusb_dev", "xusb_ss", "xusb";
+		mboxes = <&mbox TEGRA_XUSB_MBOX_CHAN_HOST>;
+		phys = <&padctl TEGRA_XUSB_PADCTL_UTMI_P1>, /* mini-PCIe USB */
+		       <&padctl TEGRA_XUSB_PADCTL_UTMI_P2>, /* USB A */
+		       <&padctl TEGRA_XUSB_PADCTL_USB3_P0>; /* USB A */
+		phy-names = "utmi-1", "utmi-2", "usb3-0";
+		avddio-pex-supply = <&vdd_1v05_run>;
+		dvddio-pex-supply = <&vdd_1v05_run>;
+		avdd-usb-supply = <&vdd_3v3_lp0>;
+		avdd-pll-utmip-supply = <&vddio_1v8>;
+		avdd-pll-erefe-supply = <&avdd_1v05_run>;
+		avdd-pex-pll-supply = <&vdd_1v05_run>;
+		hvdd-pex-supply = <&vdd_3v3_lp0>;
+		hvdd-pex-plle-supply = <&vdd_3v3_lp0>;
+	};
-- 
2.1.0.rc2.206.gedb03e5


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

* [PATCH v2 5/9] of: Add NVIDIA Tegra xHCI controller binding
@ 2014-08-18 17:08   ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-18 17:08 UTC (permalink / raw)
  To: linux-arm-kernel

Add device-tree binding documentation for the xHCI controller present
on Tegra124 and later SoCs.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
---
Changes from v1:
 - Updated to use common mailbox bindings.
 - Added remaining XUSB-related clocks and resets.
 - Updated list of power supplies to be more accurate wrt to the hardware.
---
 .../bindings/usb/nvidia,tegra124-xhci.txt          | 101 +++++++++++++++++++++
 1 file changed, 101 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/nvidia,tegra124-xhci.txt

diff --git a/Documentation/devicetree/bindings/usb/nvidia,tegra124-xhci.txt b/Documentation/devicetree/bindings/usb/nvidia,tegra124-xhci.txt
new file mode 100644
index 0000000..ed1f8cd
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/nvidia,tegra124-xhci.txt
@@ -0,0 +1,101 @@
+NVIDIA Tegra xHCI controller
+============================
+
+The Tegra xHCI controller supports both USB2 and USB3 interfaces exposed
+by the Tegra XUSB pad controller.
+
+Required properties:
+--------------------
+ - compatible: Should be "nvidia,tegra124-xhci".
+ - reg: Address and length of the register sets.  There should be three
+   entries in the following order: xHCI host registers, FPCI registers, and
+   IPFS registers.
+ - interrupts: xHCI host interrupt.
+ - clocks: Must contain an entry for each entry in clock-names.
+   See ../clock/clock-bindings.txt for details.
+ - clock-names: Must include the following entries:
+    - xusb_host
+    - xusb_host_src
+    - xusb_dev
+    - xusb_dev_src
+    - xusb_falcon_src
+    - xusb_ss
+    - xusb_ss_src
+    - xusb_ss_div2
+    - xusb_hs_src
+    - xusb_fs_src
+    - pll_u_480m
+    - clk_m
+    - pll_e
+ - resets: Must contain an entry for each entry in reset-names.
+   See ../reset/reset.txt for details.
+ - reset-names: Must include the following entries:
+   - xusb_host
+   - xusb_dev
+   - xusb_ss
+   - xusb
+   Note that xusb_dev is the shared reset for xusb_dev and xusb_dev_src and
+   that xusb is the shared reset for xusb_{ss,hs,fs,falcon,host}_src.
+ - mboxes: Must contain an entry for the XUSB host mailbox channel.
+   See ../mailbox/mailbox.txt for details.
+
+Optional properties:
+--------------------
+ - phys: Must contain an entry for each entry in phy-names.
+   See ../phy/phy-bindings.txt for details.
+ - phy-names: Should include an entry for each PHY used by the controller.
+   May be a subset of the following:
+    - utmi-{0,1,2}
+    - hsic-{0,1}
+    - usb3-{0,1}
+ - avddio-pex-supply: PCIe/USB3 analog logic power supply.  Must supply 1.05V.
+ - dvddio-pex-supply: PCIe/USB3 digital logic power supply.  Must supply 1.05V.
+ - avdd-usb-supply: USB controller power supply.  Must supply 3.3V.
+ - avdd-pll-utmip-supply: UTMI PLL power supply.  Must supply 1.8V.
+ - avdd-pll-erefe-supply: PLLE reference PLL power supply.  Must supply 1.05V.
+ - avdd-pex-pll-supply: PCIe/USB3 PLL power supply.  Must supply 1.05V.
+ - hvdd-pex-supply: High-voltage PCIe/USB3 power supply.  Must supply 3.3V.
+ - hvdd-pex-plle-supply: High-voltage PLLE power supply.  Must supply 3.3V.
+
+Example:
+--------
+	usb at 0,70090000 {
+		compatible = "nvidia,tegra124-xhci";
+		reg = <0x0 0x70090000 0x0 0x8000>,
+		      <0x0 0x70098000 0x0 0x1000>,
+		      <0x0 0x70099000 0x0 0x1000>;
+		interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&tegra_car TEGRA124_CLK_XUSB_HOST>,
+			 <&tegra_car TEGRA124_CLK_XUSB_HOST_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_DEV>,
+			 <&tegra_car TEGRA124_CLK_XUSB_DEV_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_FALCON_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_SS>,
+			 <&tegra_car TEGRA124_CLK_XUSB_SS_DIV2>,
+			 <&tegra_car TEGRA124_CLK_XUSB_SS_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_HS_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_FS_SRC>,
+			 <&tegra_car TEGRA124_CLK_PLL_U_480M>,
+			 <&tegra_car TEGRA124_CLK_CLK_M>,
+			 <&tegra_car TEGRA124_CLK_PLL_E>;
+		clock-names = "xusb_host", "xusb_host_src", "xusb_dev",
+			      "xusb_dev_src", "xusb_falcon_src", "xusb_ss",
+			      "xusb_ss_div2", "xusb_ss_src", "xusb_hs_src",
+			      "xusb_fs_src", "pll_u_480m", "clk_m", "pll_e";
+		resets = <&tegra_car 89>, <&tegra_car 95>, <&tegra_car 156>,
+			 <&tegra_car 143>;
+		reset-names = "xusb_host", "xusb_dev", "xusb_ss", "xusb";
+		mboxes = <&mbox TEGRA_XUSB_MBOX_CHAN_HOST>;
+		phys = <&padctl TEGRA_XUSB_PADCTL_UTMI_P1>, /* mini-PCIe USB */
+		       <&padctl TEGRA_XUSB_PADCTL_UTMI_P2>, /* USB A */
+		       <&padctl TEGRA_XUSB_PADCTL_USB3_P0>; /* USB A */
+		phy-names = "utmi-1", "utmi-2", "usb3-0";
+		avddio-pex-supply = <&vdd_1v05_run>;
+		dvddio-pex-supply = <&vdd_1v05_run>;
+		avdd-usb-supply = <&vdd_3v3_lp0>;
+		avdd-pll-utmip-supply = <&vddio_1v8>;
+		avdd-pll-erefe-supply = <&avdd_1v05_run>;
+		avdd-pex-pll-supply = <&vdd_1v05_run>;
+		hvdd-pex-supply = <&vdd_3v3_lp0>;
+		hvdd-pex-plle-supply = <&vdd_3v3_lp0>;
+	};
-- 
2.1.0.rc2.206.gedb03e5

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

* [PATCH v2 6/9] usb: xhci: Add NVIDIA Tegra xHCI host-controller driver
  2014-08-18 17:08 ` Andrew Bresticker
  (?)
@ 2014-08-18 17:08   ` Andrew Bresticker
  -1 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-18 17:08 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, linux-tegra
  Cc: Mark Rutland, devicetree, linux-usb, Russell King, Mathias Nyman,
	Pawel Moll, Ian Campbell, Andrew Bresticker, Greg Kroah-Hartman,
	Linus Walleij, Jassi Brar, linux-kernel, Kishon Vijay Abraham I,
	Rob Herring, Alan Stern, linux-arm-kernel, Kumar Gala,
	Grant Likely, Arnd Bergmann

Add support for the on-chip xHCI host controller present on Tegra SoCs.

The driver is currently very basic: it loads the controller with its
firmware, starts the controller, and is able to service messages sent
by the controller's firmware.  The hardware supports device mode as
well as lower-power operating modes, but support for these is not yet
implemented here.

Based on work by:
  Ajay Gupta <ajayg@nvidia.com>
  Bharath Yadav <byadav@nvidia.com>

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
---
Changes from v1:
 - Updated to use common mailbox API.
 - Fixed up so that the driver can be built and used as a module.
 - Incorporated review feedback from Stephen.
 - Misc. cleanups.
---
 drivers/usb/host/Kconfig      |   9 +
 drivers/usb/host/Makefile     |   1 +
 drivers/usb/host/xhci-tegra.c | 893 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 903 insertions(+)
 create mode 100644 drivers/usb/host/xhci-tegra.c

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index f5a5831..1fffbed 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -50,6 +50,15 @@ config USB_XHCI_RCAR
 	  Say 'Y' to enable the support for the xHCI host controller
 	  found in Renesas R-Car ARM SoCs.
 
+config USB_XHCI_TEGRA
+	tristate "NVIDIA Tegra XHCI support"
+	depends on ARCH_TEGRA
+	select MAILBOX
+	select FW_LOADER
+	---help---
+	  Say 'Y' to enable the support for the xHCI host controller
+	  found in NVIDIA Tegra124 and later SoCs.
+
 endif # USB_XHCI_HCD
 
 config USB_EHCI_HCD
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 702d9b7..0a30e26 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_PCI)		+= pci-quirks.o
 
 obj-$(CONFIG_USB_XHCI_PCI)	+= xhci-pci.o
 obj-$(CONFIG_USB_XHCI_PLATFORM) += xhci-plat-hcd.o
+obj-$(CONFIG_USB_XHCI_TEGRA)	+= xhci-tegra.o
 
 obj-$(CONFIG_USB_EHCI_HCD)	+= ehci-hcd.o
 obj-$(CONFIG_USB_EHCI_PCI)	+= ehci-pci.o
diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
new file mode 100644
index 0000000..515aa49
--- /dev/null
+++ b/drivers/usb/host/xhci-tegra.c
@@ -0,0 +1,893 @@
+/*
+ * NVIDIA Tegra xHCI host controller driver
+ *
+ * Copyright (C) 2014 NVIDIA Corporation
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/firmware.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mailbox_client.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+
+#include <soc/tegra/xusb.h>
+
+#include "xhci.h"
+
+#define TEGRA_XHCI_SS_CLK_HIGH_SPEED 120000000
+#define TEGRA_XHCI_SS_CLK_LOW_SPEED 12000000
+
+/* FPCI CFG registers */
+#define XUSB_CFG_1				0x004
+#define  XUSB_IO_SPACE_EN			BIT(0)
+#define  XUSB_MEM_SPACE_EN			BIT(1)
+#define  XUSB_BUS_MASTER_EN			BIT(2)
+#define XUSB_CFG_4				0x010
+#define  XUSB_BASE_ADDR_SHIFT			15
+#define  XUSB_BASE_ADDR_MASK			0x1ffff
+#define XUSB_CFG_ARU_C11_CSBRANGE		0x41c
+#define XUSB_CFG_CSB_BASE_ADDR			0x800
+
+/* IPFS registers */
+#define IPFS_XUSB_HOST_CONFIGURATION_0		0x180
+#define  IPFS_EN_FPCI				BIT(0)
+#define IPFS_XUSB_HOST_INTR_MASK_0		0x188
+#define  IPFS_IP_INT_MASK			BIT(16)
+#define IPFS_XUSB_HOST_CLKGATE_HYSTERESIS_0	0x1bc
+
+#define CSB_PAGE_SELECT_MASK			0x7fffff
+#define CSB_PAGE_SELECT_SHIFT			9
+#define CSB_PAGE_OFFSET_MASK			0x1ff
+#define CSB_PAGE_SELECT(addr)	((addr) >> (CSB_PAGE_SELECT_SHIFT) &	\
+				 CSB_PAGE_SELECT_MASK)
+#define CSB_PAGE_OFFSET(addr)	((addr) & CSB_PAGE_OFFSET_MASK)
+
+/* Falcon CSB registers */
+#define XUSB_FALC_CPUCTL			0x100
+#define  CPUCTL_STARTCPU			BIT(1)
+#define  CPUCTL_STATE_HALTED			BIT(4)
+#define XUSB_FALC_BOOTVEC			0x104
+#define XUSB_FALC_DMACTL			0x10c
+#define XUSB_FALC_IMFILLRNG1			0x154
+#define  IMFILLRNG1_TAG_MASK			0xffff
+#define  IMFILLRNG1_TAG_LO_SHIFT		0
+#define  IMFILLRNG1_TAG_HI_SHIFT		16
+#define XUSB_FALC_IMFILLCTL			0x158
+
+/* MP CSB registers */
+#define XUSB_CSB_MP_ILOAD_ATTR			0x101a00
+#define XUSB_CSB_MP_ILOAD_BASE_LO		0x101a04
+#define XUSB_CSB_MP_ILOAD_BASE_HI		0x101a08
+#define XUSB_CSB_MP_L2IMEMOP_SIZE		0x101a10
+#define  L2IMEMOP_SIZE_SRC_OFFSET_SHIFT		8
+#define  L2IMEMOP_SIZE_SRC_OFFSET_MASK		0x3ff
+#define  L2IMEMOP_SIZE_SRC_COUNT_SHIFT		24
+#define  L2IMEMOP_SIZE_SRC_COUNT_MASK		0xff
+#define XUSB_CSB_MP_L2IMEMOP_TRIG		0x101a14
+#define  L2IMEMOP_ACTION_SHIFT			24
+#define  L2IMEMOP_INVALIDATE_ALL		(0x40 << L2IMEMOP_ACTION_SHIFT)
+#define  L2IMEMOP_LOAD_LOCKED_RESULT		(0x11 << L2IMEMOP_ACTION_SHIFT)
+#define XUSB_CSB_MP_APMAP			0x10181c
+#define  APMAP_BOOTPATH				BIT(31)
+
+#define IMEM_BLOCK_SIZE				256
+
+struct tegra_xhci_fw_cfgtbl {
+	u32 boot_loadaddr_in_imem;
+	u32 boot_codedfi_offset;
+	u32 boot_codetag;
+	u32 boot_codesize;
+	u32 phys_memaddr;
+	u16 reqphys_memsize;
+	u16 alloc_phys_memsize;
+	u32 rodata_img_offset;
+	u32 rodata_section_start;
+	u32 rodata_section_end;
+	u32 main_fnaddr;
+	u32 fwimg_cksum;
+	u32 fwimg_created_time;
+	u32 imem_resident_start;
+	u32 imem_resident_end;
+	u32 idirect_start;
+	u32 idirect_end;
+	u32 l2_imem_start;
+	u32 l2_imem_end;
+	u32 version_id;
+	u8 init_ddirect;
+	u8 reserved[3];
+	u32 phys_addr_log_buffer;
+	u32 total_log_entries;
+	u32 dequeue_ptr;
+	u32 dummy_var[2];
+	u32 fwimg_len;
+	u8 magic[8];
+	u32 ss_low_power_entry_timeout;
+	u8 num_hsic_port;
+	u8 padding[139]; /* Padding to make 256-bytes cfgtbl */
+};
+
+struct tegra_xhci_soc_config {
+	const char *firmware_file;
+};
+
+#define TEGRA_XHCI_NUM_SUPPLIES 8
+static const char *tegra_xhci_supply_names[TEGRA_XHCI_NUM_SUPPLIES] = {
+	"avddio-pex",
+	"dvddio-pex",
+	"avdd-usb",
+	"avdd-pll-utmip",
+	"avdd-pll-erefe",
+	"avdd-pex-pll",
+	"hvdd-pex",
+	"hvdd-pex-plle",
+};
+
+static const struct {
+	const char *name;
+	int num;
+} tegra_xhci_phy_types[] = {
+	{
+		.name = "usb3",
+		.num = TEGRA_XUSB_USB3_PHYS,
+	}, {
+		.name = "utmi",
+		.num = TEGRA_XUSB_UTMI_PHYS,
+	}, {
+		.name = "hsic",
+		.num = TEGRA_XUSB_HSIC_PHYS,
+	},
+};
+
+struct tegra_xhci_hcd {
+	struct device *dev;
+	struct usb_hcd *hcd;
+
+	int irq;
+
+	void __iomem *fpci_base;
+	void __iomem *ipfs_base;
+
+	const struct tegra_xhci_soc_config *soc_config;
+
+	struct regulator_bulk_data supplies[TEGRA_XHCI_NUM_SUPPLIES];
+
+	struct clk *host_clk;
+	struct clk *falc_clk;
+	struct clk *ss_clk;
+	struct clk *ss_src_clk;
+	struct clk *hs_src_clk;
+	struct clk *fs_src_clk;
+	struct clk *pll_u_480m;
+	struct clk *clk_m;
+	struct clk *pll_e;
+
+	struct reset_control *host_rst;
+	struct reset_control *ss_rst;
+
+	struct phy *phys[TEGRA_XUSB_NUM_USB_PHYS];
+
+	struct work_struct mbox_req_work;
+	struct tegra_xusb_mbox_msg mbox_req;
+	struct mbox_client mbox_client;
+	struct mbox_chan *mbox_chan;
+
+	/* Firmware loading related */
+	void *fw_data;
+	size_t fw_size;
+	dma_addr_t fw_dma_addr;
+	bool fw_loaded;
+};
+
+static struct hc_driver __read_mostly tegra_xhci_hc_driver;
+
+static inline u32 fpci_readl(struct tegra_xhci_hcd *tegra, u32 addr)
+{
+	return readl(tegra->fpci_base + addr);
+}
+
+static inline void fpci_writel(struct tegra_xhci_hcd *tegra, u32 val, u32 addr)
+{
+	writel(val, tegra->fpci_base + addr);
+}
+
+static inline u32 ipfs_readl(struct tegra_xhci_hcd *tegra, u32 addr)
+{
+	return readl(tegra->ipfs_base + addr);
+}
+
+static inline void ipfs_writel(struct tegra_xhci_hcd *tegra, u32 val, u32 addr)
+{
+	writel(val, tegra->ipfs_base + addr);
+}
+
+static u32 csb_readl(struct tegra_xhci_hcd *tegra, u32 addr)
+{
+	u32 page, offset;
+
+	page = CSB_PAGE_SELECT(addr);
+	offset = CSB_PAGE_OFFSET(addr);
+	fpci_writel(tegra, page, XUSB_CFG_ARU_C11_CSBRANGE);
+	return fpci_readl(tegra, XUSB_CFG_CSB_BASE_ADDR + offset);
+}
+
+static void csb_writel(struct tegra_xhci_hcd *tegra, u32 val, u32 addr)
+{
+	u32 page, offset;
+
+	page = CSB_PAGE_SELECT(addr);
+	offset = CSB_PAGE_OFFSET(addr);
+	fpci_writel(tegra, page, XUSB_CFG_ARU_C11_CSBRANGE);
+	fpci_writel(tegra, val, XUSB_CFG_CSB_BASE_ADDR + offset);
+}
+
+static void tegra_xhci_cfg(struct tegra_xhci_hcd *tegra)
+{
+	u32 reg;
+
+	reg = ipfs_readl(tegra, IPFS_XUSB_HOST_CONFIGURATION_0);
+	reg |= IPFS_EN_FPCI;
+	ipfs_writel(tegra, reg, IPFS_XUSB_HOST_CONFIGURATION_0);
+	udelay(10);
+
+	/* Program Bar0 Space */
+	reg = fpci_readl(tegra, XUSB_CFG_4);
+	reg &= ~(XUSB_BASE_ADDR_MASK << XUSB_BASE_ADDR_SHIFT);
+	reg |= tegra->hcd->rsrc_start & (XUSB_BASE_ADDR_MASK <<
+					 XUSB_BASE_ADDR_SHIFT);
+	fpci_writel(tegra, reg, XUSB_CFG_4);
+	usleep_range(100, 200);
+
+	/* Enable Bus Master */
+	reg = fpci_readl(tegra, XUSB_CFG_1);
+	reg |= XUSB_IO_SPACE_EN | XUSB_MEM_SPACE_EN | XUSB_BUS_MASTER_EN;
+	fpci_writel(tegra, reg, XUSB_CFG_1);
+
+	/* Set intr mask to enable intr assertion */
+	reg = ipfs_readl(tegra, IPFS_XUSB_HOST_INTR_MASK_0);
+	reg |= IPFS_IP_INT_MASK;
+	ipfs_writel(tegra, reg, IPFS_XUSB_HOST_INTR_MASK_0);
+
+	/* Set hysteris to 0x80 */
+	ipfs_writel(tegra, 0x80, IPFS_XUSB_HOST_CLKGATE_HYSTERESIS_0);
+}
+
+static int tegra_xhci_load_firmware(struct tegra_xhci_hcd *tegra)
+{
+	struct device *dev = tegra->dev;
+	struct tegra_xhci_fw_cfgtbl *cfg_tbl;
+	u64 fw_base;
+	u32 val, code_tag_blocks, code_size_blocks;
+	time_t fw_time;
+	struct tm fw_tm;
+
+	if (csb_readl(tegra, XUSB_CSB_MP_ILOAD_BASE_LO) != 0) {
+		dev_info(dev, "Firmware already loaded, Falcon state 0x%x\n",
+			 csb_readl(tegra, XUSB_FALC_CPUCTL));
+		return 0;
+	}
+
+	cfg_tbl = (struct tegra_xhci_fw_cfgtbl *)tegra->fw_data;
+
+	/* Program the size of DFI into ILOAD_ATTR. */
+	csb_writel(tegra, tegra->fw_size, XUSB_CSB_MP_ILOAD_ATTR);
+
+	/*
+	 * Boot code of the firmware reads the ILOAD_BASE registers
+	 * to get to the start of the DFI in system memory.
+	 */
+	fw_base = tegra->fw_dma_addr + sizeof(*cfg_tbl);
+	csb_writel(tegra, fw_base, XUSB_CSB_MP_ILOAD_BASE_LO);
+	csb_writel(tegra, fw_base >> 32, XUSB_CSB_MP_ILOAD_BASE_HI);
+
+	/* Set BOOTPATH to 1 in APMAP. */
+	csb_writel(tegra, APMAP_BOOTPATH, XUSB_CSB_MP_APMAP);
+
+	/* Invalidate L2IMEM. */
+	csb_writel(tegra, L2IMEMOP_INVALIDATE_ALL, XUSB_CSB_MP_L2IMEMOP_TRIG);
+
+	/*
+	 * Initiate fetch of bootcode from system memory into L2IMEM.
+	 * Program bootcode location and size in system memory.
+	 */
+	code_tag_blocks = DIV_ROUND_UP(le32_to_cpu(cfg_tbl->boot_codetag),
+				       IMEM_BLOCK_SIZE);
+	code_size_blocks = DIV_ROUND_UP(le32_to_cpu(cfg_tbl->boot_codesize),
+					IMEM_BLOCK_SIZE);
+	val = ((code_tag_blocks & L2IMEMOP_SIZE_SRC_OFFSET_MASK) <<
+	       L2IMEMOP_SIZE_SRC_OFFSET_SHIFT) |
+	      ((code_size_blocks & L2IMEMOP_SIZE_SRC_COUNT_MASK) <<
+	       L2IMEMOP_SIZE_SRC_COUNT_SHIFT);
+	csb_writel(tegra, val, XUSB_CSB_MP_L2IMEMOP_SIZE);
+
+	/* Trigger L2IMEM Load operation. */
+	csb_writel(tegra, L2IMEMOP_LOAD_LOCKED_RESULT,
+		   XUSB_CSB_MP_L2IMEMOP_TRIG);
+
+	/* Setup Falcon Auto-fill. */
+	csb_writel(tegra, code_size_blocks, XUSB_FALC_IMFILLCTL);
+
+	val = ((code_tag_blocks & IMFILLRNG1_TAG_MASK) <<
+	       IMFILLRNG1_TAG_LO_SHIFT) |
+	      (((code_size_blocks + code_tag_blocks) & IMFILLRNG1_TAG_MASK) <<
+	       IMFILLRNG1_TAG_HI_SHIFT);
+	csb_writel(tegra, val, XUSB_FALC_IMFILLRNG1);
+
+	csb_writel(tegra, 0, XUSB_FALC_DMACTL);
+	msleep(50);
+
+	csb_writel(tegra, le32_to_cpu(cfg_tbl->boot_codetag),
+		   XUSB_FALC_BOOTVEC);
+
+	/* Start Falcon CPU. */
+	csb_writel(tegra, CPUCTL_STARTCPU, XUSB_FALC_CPUCTL);
+	usleep_range(1000, 2000);
+
+	fw_time = le32_to_cpu(cfg_tbl->fwimg_created_time);
+	time_to_tm(fw_time, 0, &fw_tm);
+	dev_info(dev,
+		 "Firmware timestamp: %ld-%02d-%02d %02d:%02d:%02d UTC, "
+		 "Falcon state 0x%x\n", fw_tm.tm_year + 1900,
+		 fw_tm.tm_mon + 1, fw_tm.tm_mday, fw_tm.tm_hour,
+		 fw_tm.tm_min, fw_tm.tm_sec,
+		 csb_readl(tegra, XUSB_FALC_CPUCTL));
+
+	/* Make sure Falcon CPU is now running. */
+	if (csb_readl(tegra, XUSB_FALC_CPUCTL) == CPUCTL_STATE_HALTED)
+		return -EIO;
+
+	return 0;
+}
+
+static int tegra_xhci_set_ss_clk(struct tegra_xhci_hcd *tegra,
+				 unsigned long rate)
+{
+	unsigned long new_parent_rate, old_parent_rate;
+	int ret, div;
+	struct clk *clk = tegra->ss_src_clk;
+
+	if (clk_get_rate(clk) == rate)
+		return 0;
+
+	switch (rate) {
+	case TEGRA_XHCI_SS_CLK_HIGH_SPEED:
+		/*
+		 * Reparent to PLLU_480M. Set divider first to avoid
+		 * overclocking.
+		 */
+		old_parent_rate = clk_get_rate(clk_get_parent(clk));
+		new_parent_rate = clk_get_rate(tegra->pll_u_480m);
+		div = new_parent_rate / rate;
+		ret = clk_set_rate(clk, old_parent_rate / div);
+		if (ret)
+			return ret;
+		ret = clk_set_parent(clk, tegra->pll_u_480m);
+		if (ret)
+			return ret;
+		/*
+		 * The rate should already be correct, but set it again just
+		 * to be sure.
+		 */
+		ret = clk_set_rate(clk, rate);
+		if (ret)
+			return ret;
+		break;
+	case TEGRA_XHCI_SS_CLK_LOW_SPEED:
+		/* Reparent to CLK_M */
+		ret = clk_set_parent(clk, tegra->clk_m);
+		if (ret)
+			return ret;
+		ret = clk_set_rate(clk, rate);
+		if (ret)
+			return ret;
+		break;
+	default:
+		dev_err(tegra->dev, "Invalid SS rate: %lu\n", rate);
+		return -EINVAL;
+	}
+
+	if (clk_get_rate(clk) != rate) {
+		dev_err(tegra->dev, "SS clock doesn't match requested rate\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int tegra_xhci_clk_enable(struct tegra_xhci_hcd *tegra)
+{
+	clk_prepare_enable(tegra->pll_e);
+	clk_prepare_enable(tegra->host_clk);
+	clk_prepare_enable(tegra->ss_clk);
+	clk_prepare_enable(tegra->falc_clk);
+	clk_prepare_enable(tegra->fs_src_clk);
+	clk_prepare_enable(tegra->hs_src_clk);
+
+	return tegra_xhci_set_ss_clk(tegra, TEGRA_XHCI_SS_CLK_HIGH_SPEED);
+}
+
+static void tegra_xhci_clk_disable(struct tegra_xhci_hcd *tegra)
+{
+	clk_disable_unprepare(tegra->pll_e);
+	clk_disable_unprepare(tegra->host_clk);
+	clk_disable_unprepare(tegra->ss_clk);
+	clk_disable_unprepare(tegra->falc_clk);
+	clk_disable_unprepare(tegra->fs_src_clk);
+	clk_disable_unprepare(tegra->hs_src_clk);
+}
+
+static int tegra_xhci_phy_enable(struct tegra_xhci_hcd *tegra)
+{
+	int ret;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(tegra->phys); i++) {
+		ret = phy_init(tegra->phys[i]);
+		if (ret)
+			goto disable_phy;
+		ret = phy_power_on(tegra->phys[i]);
+		if (ret) {
+			phy_exit(tegra->phys[i]);
+			goto disable_phy;
+		}
+	}
+
+	return 0;
+disable_phy:
+	for (i = i - 1; i >= 0; i--) {
+		phy_power_off(tegra->phys[i]);
+		phy_exit(tegra->phys[i]);
+	}
+	return ret;
+}
+
+static void tegra_xhci_phy_disable(struct tegra_xhci_hcd *tegra)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(tegra->phys); i++) {
+		phy_power_off(tegra->phys[i]);
+		phy_exit(tegra->phys[i]);
+	}
+}
+
+static void tegra_xhci_mbox_work(struct work_struct *work)
+{
+	struct tegra_xhci_hcd *tegra = container_of(work, struct tegra_xhci_hcd,
+						    mbox_req_work);
+	struct tegra_xusb_mbox_msg resp;
+	int ret;
+
+	switch (tegra->mbox_req.cmd) {
+	case MBOX_CMD_INC_SSPI_CLOCK:
+	case MBOX_CMD_DEC_SSPI_CLOCK:
+		ret = tegra_xhci_set_ss_clk(tegra, tegra->mbox_req.data * 1000);
+		resp.data = clk_get_rate(tegra->ss_src_clk) / 1000;
+		if (ret)
+			resp.cmd = MBOX_CMD_NAK;
+		else
+			resp.cmd = MBOX_CMD_ACK;
+		break;
+	case MBOX_CMD_INC_FALC_CLOCK:
+	case MBOX_CMD_DEC_FALC_CLOCK:
+		resp.data = clk_get_rate(tegra->falc_clk) / 1000;
+		if (resp.data != tegra->mbox_req.data)
+			resp.cmd = MBOX_CMD_NAK;
+		else
+			resp.cmd = MBOX_CMD_ACK;
+		break;
+	case MBOX_CMD_SET_BW:
+		/* TODO: Request bandwidth once EMC scaling is supported. */
+		/* SET_BW messages do not require an ACK/NAK. */
+		resp.data = 0;
+		resp.cmd = 0;
+		break;
+	default:
+		resp.data = 0;
+		resp.cmd = MBOX_CMD_NAK;
+		dev_err(tegra->dev, "Unexpected message 0x%x:0x%x\n",
+			tegra->mbox_req.cmd, tegra->mbox_req.data);
+		break;
+	}
+
+	if (resp.cmd)
+		mbox_send_message(tegra->mbox_chan, &resp);
+}
+
+static void tegra_xhci_mbox_rx(struct mbox_client *cl, void *data)
+{
+	struct tegra_xhci_hcd *tegra = dev_get_drvdata(cl->dev);
+	struct tegra_xusb_mbox_msg *msg = data;
+
+	tegra->mbox_req = *msg;
+	schedule_work(&tegra->mbox_req_work);
+}
+
+static void tegra_xhci_quirks(struct device *dev, struct xhci_hcd *xhci)
+{
+	xhci->quirks |= XHCI_PLAT;
+}
+
+static int tegra_xhci_setup(struct usb_hcd *hcd)
+{
+	return xhci_gen_setup(hcd, tegra_xhci_quirks);
+}
+
+static const struct tegra_xhci_soc_config tegra124_soc_config = {
+	.firmware_file = "nvidia/tegra124/xusb.bin",
+};
+MODULE_FIRMWARE("nvidia/tegra124/xusb.bin");
+
+static struct of_device_id tegra_xhci_of_match[] = {
+	{ .compatible = "nvidia,tegra124-xhci", .data = &tegra124_soc_config },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, tegra_xhci_of_match);
+
+static void tegra_xhci_probe_finish(const struct firmware *fw, void *context)
+{
+	struct tegra_xhci_hcd *tegra = context;
+	struct device *dev = tegra->dev;
+	struct xhci_hcd *xhci = NULL;
+	struct tegra_xhci_fw_cfgtbl *cfg_tbl;
+	struct tegra_xusb_mbox_msg msg;
+	int ret;
+
+	if (!fw)
+		goto put_usb2_hcd;
+
+	/* Load Falcon controller with its firmware. */
+	cfg_tbl = (struct tegra_xhci_fw_cfgtbl *)fw->data;
+	tegra->fw_size = le32_to_cpu(cfg_tbl->fwimg_len);
+	tegra->fw_data = dma_alloc_coherent(dev, tegra->fw_size,
+					    &tegra->fw_dma_addr,
+					    GFP_KERNEL);
+	if (!tegra->fw_data)
+		goto put_usb2_hcd;
+	memcpy(tegra->fw_data, fw->data, tegra->fw_size);
+
+	ret = tegra_xhci_load_firmware(tegra);
+	if (ret < 0)
+		goto put_usb2_hcd;
+
+	ret = usb_add_hcd(tegra->hcd, tegra->irq, IRQF_SHARED);
+	if (ret < 0)
+		goto put_usb2_hcd;
+	device_wakeup_enable(tegra->hcd->self.controller);
+
+	/*
+	 * USB 2.0 roothub is stored in drvdata now. Swap it with the Tegra HCD.
+	 */
+	tegra->hcd = dev_get_drvdata(dev);
+	dev_set_drvdata(dev, tegra);
+	xhci = hcd_to_xhci(tegra->hcd);
+	xhci->shared_hcd = usb_create_shared_hcd(&tegra_xhci_hc_driver,
+						 dev, dev_name(dev),
+						 tegra->hcd);
+	if (!xhci->shared_hcd)
+		goto dealloc_usb2_hcd;
+
+	/*
+	 * Set the xHCI pointer before xhci_plat_setup() (aka hcd_driver.reset)
+	 * is called by usb_add_hcd().
+	 */
+	*((struct xhci_hcd **) xhci->shared_hcd->hcd_priv) = xhci;
+	ret = usb_add_hcd(xhci->shared_hcd, tegra->irq, IRQF_SHARED);
+	if (ret < 0)
+		goto put_usb3_hcd;
+
+	/* Enable firmware messages from controller. */
+	msg.cmd = MBOX_CMD_MSG_ENABLED;
+	msg.data = 0;
+	ret = mbox_send_message(tegra->mbox_chan, &msg);
+	if (ret < 0)
+		goto dealloc_usb3_hcd;
+
+	tegra->fw_loaded = true;
+	release_firmware(fw);
+	return;
+
+	/* Free up as much as we can and wait to be unbound. */
+dealloc_usb3_hcd:
+	usb_remove_hcd(xhci->shared_hcd);
+put_usb3_hcd:
+	usb_put_hcd(xhci->shared_hcd);
+dealloc_usb2_hcd:
+	usb_remove_hcd(tegra->hcd);
+	kfree(xhci);
+put_usb2_hcd:
+	usb_put_hcd(tegra->hcd);
+	tegra->hcd = NULL;
+	release_firmware(fw);
+}
+
+static int tegra_xhci_probe(struct platform_device *pdev)
+{
+	struct tegra_xhci_hcd *tegra;
+	struct usb_hcd *hcd;
+	struct resource	*res;
+	struct phy *phy;
+	const struct of_device_id *match;
+	int ret, i, j, k;
+
+	BUILD_BUG_ON(sizeof(struct tegra_xhci_fw_cfgtbl) != 256);
+
+	tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL);
+	if (!tegra)
+		return -ENOMEM;
+	tegra->dev = &pdev->dev;
+	platform_set_drvdata(pdev, tegra);
+
+	match = of_match_device(tegra_xhci_of_match, &pdev->dev);
+	if (!match) {
+		dev_err(&pdev->dev, "No device match found\n");
+		return -ENODEV;
+	}
+	tegra->soc_config = match->data;
+
+	/*
+	 * Right now device-tree probed devices don't get dma_mask set.
+	 * Since shared usb code relies on it, set it here for now.
+	 * Once we have dma capability bindings this can go away.
+	 */
+	ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+	if (ret)
+		return ret;
+
+	hcd = usb_create_hcd(&tegra_xhci_hc_driver, &pdev->dev,
+				    dev_name(&pdev->dev));
+	if (!hcd)
+		return -ENOMEM;
+	tegra->hcd = hcd;
+
+	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);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	tegra->fpci_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(tegra->fpci_base)) {
+		ret = PTR_ERR(tegra->fpci_base);
+		goto put_hcd;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+	tegra->ipfs_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(tegra->ipfs_base)) {
+		ret = PTR_ERR(tegra->ipfs_base);
+		goto put_hcd;
+	}
+
+	tegra->irq = platform_get_irq(pdev, 0);
+	if (tegra->irq < 0) {
+		ret = tegra->irq;
+		goto put_hcd;
+	}
+
+	tegra->host_rst = devm_reset_control_get(&pdev->dev, "xusb_host");
+	if (IS_ERR(tegra->host_rst)) {
+		ret = PTR_ERR(tegra->host_rst);
+		goto put_hcd;
+	}
+	tegra->ss_rst = devm_reset_control_get(&pdev->dev, "xusb_ss");
+	if (IS_ERR(tegra->ss_rst)) {
+		ret = PTR_ERR(tegra->ss_rst);
+		goto put_hcd;
+	}
+
+	tegra->host_clk = devm_clk_get(&pdev->dev, "xusb_host");
+	if (IS_ERR(tegra->host_clk)) {
+		ret = PTR_ERR(tegra->host_clk);
+		goto put_hcd;
+	}
+	tegra->falc_clk = devm_clk_get(&pdev->dev, "xusb_falcon_src");
+	if (IS_ERR(tegra->falc_clk)) {
+		ret = PTR_ERR(tegra->falc_clk);
+		goto put_hcd;
+	}
+	tegra->ss_clk = devm_clk_get(&pdev->dev, "xusb_ss");
+	if (IS_ERR(tegra->ss_clk)) {
+		ret = PTR_ERR(tegra->ss_clk);
+		goto put_hcd;
+	}
+	tegra->ss_src_clk = devm_clk_get(&pdev->dev, "xusb_ss_src");
+	if (IS_ERR(tegra->ss_src_clk)) {
+		ret = PTR_ERR(tegra->ss_src_clk);
+		goto put_hcd;
+	}
+	tegra->hs_src_clk = devm_clk_get(&pdev->dev, "xusb_hs_src");
+	if (IS_ERR(tegra->hs_src_clk)) {
+		ret = PTR_ERR(tegra->hs_src_clk);
+		goto put_hcd;
+	}
+	tegra->fs_src_clk = devm_clk_get(&pdev->dev, "xusb_fs_src");
+	if (IS_ERR(tegra->fs_src_clk)) {
+		ret = PTR_ERR(tegra->fs_src_clk);
+		goto put_hcd;
+	}
+	tegra->pll_u_480m = devm_clk_get(&pdev->dev, "pll_u_480m");
+	if (IS_ERR(tegra->pll_u_480m)) {
+		ret = PTR_ERR(tegra->pll_u_480m);
+		goto put_hcd;
+	}
+	tegra->clk_m = devm_clk_get(&pdev->dev, "clk_m");
+	if (IS_ERR(tegra->clk_m)) {
+		ret = PTR_ERR(tegra->clk_m);
+		goto put_hcd;
+	}
+	tegra->pll_e = devm_clk_get(&pdev->dev, "pll_e");
+	if (IS_ERR(tegra->pll_e)) {
+		ret = PTR_ERR(tegra->pll_e);
+		goto put_hcd;
+	}
+	ret = tegra_xhci_clk_enable(tegra);
+	if (ret)
+		goto put_hcd;
+
+	for (i = 0; i < ARRAY_SIZE(tegra->supplies); i++)
+		tegra->supplies[i].supply = tegra_xhci_supply_names[i];
+	ret = devm_regulator_bulk_get(&pdev->dev, ARRAY_SIZE(tegra->supplies),
+				      tegra->supplies);
+	if (ret)
+		goto disable_clk;
+	ret = regulator_bulk_enable(ARRAY_SIZE(tegra->supplies),
+				    tegra->supplies);
+	if (ret)
+		goto disable_clk;
+
+	INIT_WORK(&tegra->mbox_req_work, tegra_xhci_mbox_work);
+	tegra->mbox_client.dev = &pdev->dev;
+	tegra->mbox_client.tx_block = true;
+	tegra->mbox_client.tx_tout = 0;
+	tegra->mbox_client.rx_callback = tegra_xhci_mbox_rx;
+	tegra->mbox_chan = mbox_request_channel(&tegra->mbox_client, 0);
+	if (IS_ERR(tegra->mbox_chan)) {
+		ret = PTR_ERR(tegra->mbox_chan);
+		goto disable_regulator;
+	}
+
+	k = 0;
+	for (i = 0; i < ARRAY_SIZE(tegra_xhci_phy_types); i++) {
+		char prop[8];
+
+		BUG_ON(sizeof(prop) < strlen(tegra_xhci_phy_types[i].name) + 3);
+		for (j = 0; j < tegra_xhci_phy_types[i].num; j++) {
+			sprintf(prop, "%s-%d", tegra_xhci_phy_types[i].name, j);
+			phy = devm_phy_optional_get(&pdev->dev, prop);
+			if (IS_ERR(phy)) {
+				ret = PTR_ERR(phy);
+				goto put_mbox;
+			}
+			tegra->phys[k++] = phy;
+		}
+	}
+
+	/* Setup IPFS access and BAR0 space. */
+	tegra_xhci_cfg(tegra);
+
+	ret = tegra_xhci_phy_enable(tegra);
+	if (ret < 0)
+		goto put_mbox;
+
+	ret = request_firmware_nowait(THIS_MODULE, true,
+				      tegra->soc_config->firmware_file,
+				      tegra->dev, GFP_KERNEL, tegra,
+				      tegra_xhci_probe_finish);
+	if (ret < 0)
+		goto disable_phy;
+
+	return 0;
+
+disable_phy:
+	tegra_xhci_phy_disable(tegra);
+put_mbox:
+	mbox_free_channel(tegra->mbox_chan);
+disable_regulator:
+	regulator_bulk_disable(ARRAY_SIZE(tegra->supplies), tegra->supplies);
+disable_clk:
+	tegra_xhci_clk_disable(tegra);
+put_hcd:
+	usb_put_hcd(hcd);
+	return ret;
+}
+
+static int tegra_xhci_remove(struct platform_device *pdev)
+{
+	struct tegra_xhci_hcd *tegra = platform_get_drvdata(pdev);
+	struct usb_hcd *hcd = tegra->hcd;
+	struct xhci_hcd *xhci;
+
+	if (tegra->fw_loaded) {
+		xhci = hcd_to_xhci(hcd);
+		usb_remove_hcd(xhci->shared_hcd);
+		usb_put_hcd(xhci->shared_hcd);
+		usb_remove_hcd(hcd);
+		usb_put_hcd(hcd);
+		kfree(xhci);
+	} else if (hcd) {
+		/* Unbound after probe(), but before firmware loading. */
+		usb_put_hcd(hcd);
+	}
+
+	if (tegra->fw_data)
+		dma_free_coherent(tegra->dev, tegra->fw_size, tegra->fw_data,
+				  tegra->fw_dma_addr);
+
+	cancel_work_sync(&tegra->mbox_req_work);
+	mbox_free_channel(tegra->mbox_chan);
+	tegra_xhci_phy_disable(tegra);
+	regulator_bulk_disable(ARRAY_SIZE(tegra->supplies), tegra->supplies);
+	tegra_xhci_clk_disable(tegra);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int tegra_xhci_suspend(struct device *dev)
+{
+	struct tegra_xhci_hcd *tegra = dev_get_drvdata(dev);
+	struct xhci_hcd *xhci = hcd_to_xhci(tegra->hcd);
+
+	return xhci_suspend(xhci);
+}
+
+static int tegra_xhci_resume(struct device *dev)
+{
+	struct tegra_xhci_hcd *tegra = dev_get_drvdata(dev);
+	struct xhci_hcd *xhci = hcd_to_xhci(tegra->hcd);
+
+	return xhci_resume(xhci, 0);
+}
+#endif
+
+static const struct dev_pm_ops tegra_xhci_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(tegra_xhci_suspend, tegra_xhci_resume)
+};
+
+static struct platform_driver tegra_xhci_driver = {
+	.probe	= tegra_xhci_probe,
+	.remove	= tegra_xhci_remove,
+	.driver	= {
+		.name = "xhci-tegra",
+		.pm = &tegra_xhci_pm_ops,
+		.of_match_table = of_match_ptr(tegra_xhci_of_match),
+	},
+};
+
+static int __init tegra_xhci_init(void)
+{
+	xhci_init_driver(&tegra_xhci_hc_driver, tegra_xhci_setup);
+	return platform_driver_register(&tegra_xhci_driver);
+}
+module_init(tegra_xhci_init);
+
+static void __exit tegra_xhci_exit(void)
+{
+	platform_driver_unregister(&tegra_xhci_driver);
+}
+module_exit(tegra_xhci_exit);
+
+MODULE_AUTHOR("Andrew Bresticker <abrestic@chromium.org>");
+MODULE_DESCRIPTION("NVIDIA Tegra xHCI host-controller driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:xhci-tegra");
-- 
2.1.0.rc2.206.gedb03e5

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

* [PATCH v2 6/9] usb: xhci: Add NVIDIA Tegra xHCI host-controller driver
@ 2014-08-18 17:08   ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-18 17:08 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, linux-tegra
  Cc: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Jassi Brar, Linus Walleij, Greg Kroah-Hartman,
	Mathias Nyman, Grant Likely, Alan Stern, Arnd Bergmann,
	Kishon Vijay Abraham I, devicetree, linux-kernel,
	linux-arm-kernel, linux-usb, Andrew Bresticker

Add support for the on-chip xHCI host controller present on Tegra SoCs.

The driver is currently very basic: it loads the controller with its
firmware, starts the controller, and is able to service messages sent
by the controller's firmware.  The hardware supports device mode as
well as lower-power operating modes, but support for these is not yet
implemented here.

Based on work by:
  Ajay Gupta <ajayg@nvidia.com>
  Bharath Yadav <byadav@nvidia.com>

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
---
Changes from v1:
 - Updated to use common mailbox API.
 - Fixed up so that the driver can be built and used as a module.
 - Incorporated review feedback from Stephen.
 - Misc. cleanups.
---
 drivers/usb/host/Kconfig      |   9 +
 drivers/usb/host/Makefile     |   1 +
 drivers/usb/host/xhci-tegra.c | 893 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 903 insertions(+)
 create mode 100644 drivers/usb/host/xhci-tegra.c

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index f5a5831..1fffbed 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -50,6 +50,15 @@ config USB_XHCI_RCAR
 	  Say 'Y' to enable the support for the xHCI host controller
 	  found in Renesas R-Car ARM SoCs.
 
+config USB_XHCI_TEGRA
+	tristate "NVIDIA Tegra XHCI support"
+	depends on ARCH_TEGRA
+	select MAILBOX
+	select FW_LOADER
+	---help---
+	  Say 'Y' to enable the support for the xHCI host controller
+	  found in NVIDIA Tegra124 and later SoCs.
+
 endif # USB_XHCI_HCD
 
 config USB_EHCI_HCD
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 702d9b7..0a30e26 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_PCI)		+= pci-quirks.o
 
 obj-$(CONFIG_USB_XHCI_PCI)	+= xhci-pci.o
 obj-$(CONFIG_USB_XHCI_PLATFORM) += xhci-plat-hcd.o
+obj-$(CONFIG_USB_XHCI_TEGRA)	+= xhci-tegra.o
 
 obj-$(CONFIG_USB_EHCI_HCD)	+= ehci-hcd.o
 obj-$(CONFIG_USB_EHCI_PCI)	+= ehci-pci.o
diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
new file mode 100644
index 0000000..515aa49
--- /dev/null
+++ b/drivers/usb/host/xhci-tegra.c
@@ -0,0 +1,893 @@
+/*
+ * NVIDIA Tegra xHCI host controller driver
+ *
+ * Copyright (C) 2014 NVIDIA Corporation
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/firmware.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mailbox_client.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+
+#include <soc/tegra/xusb.h>
+
+#include "xhci.h"
+
+#define TEGRA_XHCI_SS_CLK_HIGH_SPEED 120000000
+#define TEGRA_XHCI_SS_CLK_LOW_SPEED 12000000
+
+/* FPCI CFG registers */
+#define XUSB_CFG_1				0x004
+#define  XUSB_IO_SPACE_EN			BIT(0)
+#define  XUSB_MEM_SPACE_EN			BIT(1)
+#define  XUSB_BUS_MASTER_EN			BIT(2)
+#define XUSB_CFG_4				0x010
+#define  XUSB_BASE_ADDR_SHIFT			15
+#define  XUSB_BASE_ADDR_MASK			0x1ffff
+#define XUSB_CFG_ARU_C11_CSBRANGE		0x41c
+#define XUSB_CFG_CSB_BASE_ADDR			0x800
+
+/* IPFS registers */
+#define IPFS_XUSB_HOST_CONFIGURATION_0		0x180
+#define  IPFS_EN_FPCI				BIT(0)
+#define IPFS_XUSB_HOST_INTR_MASK_0		0x188
+#define  IPFS_IP_INT_MASK			BIT(16)
+#define IPFS_XUSB_HOST_CLKGATE_HYSTERESIS_0	0x1bc
+
+#define CSB_PAGE_SELECT_MASK			0x7fffff
+#define CSB_PAGE_SELECT_SHIFT			9
+#define CSB_PAGE_OFFSET_MASK			0x1ff
+#define CSB_PAGE_SELECT(addr)	((addr) >> (CSB_PAGE_SELECT_SHIFT) &	\
+				 CSB_PAGE_SELECT_MASK)
+#define CSB_PAGE_OFFSET(addr)	((addr) & CSB_PAGE_OFFSET_MASK)
+
+/* Falcon CSB registers */
+#define XUSB_FALC_CPUCTL			0x100
+#define  CPUCTL_STARTCPU			BIT(1)
+#define  CPUCTL_STATE_HALTED			BIT(4)
+#define XUSB_FALC_BOOTVEC			0x104
+#define XUSB_FALC_DMACTL			0x10c
+#define XUSB_FALC_IMFILLRNG1			0x154
+#define  IMFILLRNG1_TAG_MASK			0xffff
+#define  IMFILLRNG1_TAG_LO_SHIFT		0
+#define  IMFILLRNG1_TAG_HI_SHIFT		16
+#define XUSB_FALC_IMFILLCTL			0x158
+
+/* MP CSB registers */
+#define XUSB_CSB_MP_ILOAD_ATTR			0x101a00
+#define XUSB_CSB_MP_ILOAD_BASE_LO		0x101a04
+#define XUSB_CSB_MP_ILOAD_BASE_HI		0x101a08
+#define XUSB_CSB_MP_L2IMEMOP_SIZE		0x101a10
+#define  L2IMEMOP_SIZE_SRC_OFFSET_SHIFT		8
+#define  L2IMEMOP_SIZE_SRC_OFFSET_MASK		0x3ff
+#define  L2IMEMOP_SIZE_SRC_COUNT_SHIFT		24
+#define  L2IMEMOP_SIZE_SRC_COUNT_MASK		0xff
+#define XUSB_CSB_MP_L2IMEMOP_TRIG		0x101a14
+#define  L2IMEMOP_ACTION_SHIFT			24
+#define  L2IMEMOP_INVALIDATE_ALL		(0x40 << L2IMEMOP_ACTION_SHIFT)
+#define  L2IMEMOP_LOAD_LOCKED_RESULT		(0x11 << L2IMEMOP_ACTION_SHIFT)
+#define XUSB_CSB_MP_APMAP			0x10181c
+#define  APMAP_BOOTPATH				BIT(31)
+
+#define IMEM_BLOCK_SIZE				256
+
+struct tegra_xhci_fw_cfgtbl {
+	u32 boot_loadaddr_in_imem;
+	u32 boot_codedfi_offset;
+	u32 boot_codetag;
+	u32 boot_codesize;
+	u32 phys_memaddr;
+	u16 reqphys_memsize;
+	u16 alloc_phys_memsize;
+	u32 rodata_img_offset;
+	u32 rodata_section_start;
+	u32 rodata_section_end;
+	u32 main_fnaddr;
+	u32 fwimg_cksum;
+	u32 fwimg_created_time;
+	u32 imem_resident_start;
+	u32 imem_resident_end;
+	u32 idirect_start;
+	u32 idirect_end;
+	u32 l2_imem_start;
+	u32 l2_imem_end;
+	u32 version_id;
+	u8 init_ddirect;
+	u8 reserved[3];
+	u32 phys_addr_log_buffer;
+	u32 total_log_entries;
+	u32 dequeue_ptr;
+	u32 dummy_var[2];
+	u32 fwimg_len;
+	u8 magic[8];
+	u32 ss_low_power_entry_timeout;
+	u8 num_hsic_port;
+	u8 padding[139]; /* Padding to make 256-bytes cfgtbl */
+};
+
+struct tegra_xhci_soc_config {
+	const char *firmware_file;
+};
+
+#define TEGRA_XHCI_NUM_SUPPLIES 8
+static const char *tegra_xhci_supply_names[TEGRA_XHCI_NUM_SUPPLIES] = {
+	"avddio-pex",
+	"dvddio-pex",
+	"avdd-usb",
+	"avdd-pll-utmip",
+	"avdd-pll-erefe",
+	"avdd-pex-pll",
+	"hvdd-pex",
+	"hvdd-pex-plle",
+};
+
+static const struct {
+	const char *name;
+	int num;
+} tegra_xhci_phy_types[] = {
+	{
+		.name = "usb3",
+		.num = TEGRA_XUSB_USB3_PHYS,
+	}, {
+		.name = "utmi",
+		.num = TEGRA_XUSB_UTMI_PHYS,
+	}, {
+		.name = "hsic",
+		.num = TEGRA_XUSB_HSIC_PHYS,
+	},
+};
+
+struct tegra_xhci_hcd {
+	struct device *dev;
+	struct usb_hcd *hcd;
+
+	int irq;
+
+	void __iomem *fpci_base;
+	void __iomem *ipfs_base;
+
+	const struct tegra_xhci_soc_config *soc_config;
+
+	struct regulator_bulk_data supplies[TEGRA_XHCI_NUM_SUPPLIES];
+
+	struct clk *host_clk;
+	struct clk *falc_clk;
+	struct clk *ss_clk;
+	struct clk *ss_src_clk;
+	struct clk *hs_src_clk;
+	struct clk *fs_src_clk;
+	struct clk *pll_u_480m;
+	struct clk *clk_m;
+	struct clk *pll_e;
+
+	struct reset_control *host_rst;
+	struct reset_control *ss_rst;
+
+	struct phy *phys[TEGRA_XUSB_NUM_USB_PHYS];
+
+	struct work_struct mbox_req_work;
+	struct tegra_xusb_mbox_msg mbox_req;
+	struct mbox_client mbox_client;
+	struct mbox_chan *mbox_chan;
+
+	/* Firmware loading related */
+	void *fw_data;
+	size_t fw_size;
+	dma_addr_t fw_dma_addr;
+	bool fw_loaded;
+};
+
+static struct hc_driver __read_mostly tegra_xhci_hc_driver;
+
+static inline u32 fpci_readl(struct tegra_xhci_hcd *tegra, u32 addr)
+{
+	return readl(tegra->fpci_base + addr);
+}
+
+static inline void fpci_writel(struct tegra_xhci_hcd *tegra, u32 val, u32 addr)
+{
+	writel(val, tegra->fpci_base + addr);
+}
+
+static inline u32 ipfs_readl(struct tegra_xhci_hcd *tegra, u32 addr)
+{
+	return readl(tegra->ipfs_base + addr);
+}
+
+static inline void ipfs_writel(struct tegra_xhci_hcd *tegra, u32 val, u32 addr)
+{
+	writel(val, tegra->ipfs_base + addr);
+}
+
+static u32 csb_readl(struct tegra_xhci_hcd *tegra, u32 addr)
+{
+	u32 page, offset;
+
+	page = CSB_PAGE_SELECT(addr);
+	offset = CSB_PAGE_OFFSET(addr);
+	fpci_writel(tegra, page, XUSB_CFG_ARU_C11_CSBRANGE);
+	return fpci_readl(tegra, XUSB_CFG_CSB_BASE_ADDR + offset);
+}
+
+static void csb_writel(struct tegra_xhci_hcd *tegra, u32 val, u32 addr)
+{
+	u32 page, offset;
+
+	page = CSB_PAGE_SELECT(addr);
+	offset = CSB_PAGE_OFFSET(addr);
+	fpci_writel(tegra, page, XUSB_CFG_ARU_C11_CSBRANGE);
+	fpci_writel(tegra, val, XUSB_CFG_CSB_BASE_ADDR + offset);
+}
+
+static void tegra_xhci_cfg(struct tegra_xhci_hcd *tegra)
+{
+	u32 reg;
+
+	reg = ipfs_readl(tegra, IPFS_XUSB_HOST_CONFIGURATION_0);
+	reg |= IPFS_EN_FPCI;
+	ipfs_writel(tegra, reg, IPFS_XUSB_HOST_CONFIGURATION_0);
+	udelay(10);
+
+	/* Program Bar0 Space */
+	reg = fpci_readl(tegra, XUSB_CFG_4);
+	reg &= ~(XUSB_BASE_ADDR_MASK << XUSB_BASE_ADDR_SHIFT);
+	reg |= tegra->hcd->rsrc_start & (XUSB_BASE_ADDR_MASK <<
+					 XUSB_BASE_ADDR_SHIFT);
+	fpci_writel(tegra, reg, XUSB_CFG_4);
+	usleep_range(100, 200);
+
+	/* Enable Bus Master */
+	reg = fpci_readl(tegra, XUSB_CFG_1);
+	reg |= XUSB_IO_SPACE_EN | XUSB_MEM_SPACE_EN | XUSB_BUS_MASTER_EN;
+	fpci_writel(tegra, reg, XUSB_CFG_1);
+
+	/* Set intr mask to enable intr assertion */
+	reg = ipfs_readl(tegra, IPFS_XUSB_HOST_INTR_MASK_0);
+	reg |= IPFS_IP_INT_MASK;
+	ipfs_writel(tegra, reg, IPFS_XUSB_HOST_INTR_MASK_0);
+
+	/* Set hysteris to 0x80 */
+	ipfs_writel(tegra, 0x80, IPFS_XUSB_HOST_CLKGATE_HYSTERESIS_0);
+}
+
+static int tegra_xhci_load_firmware(struct tegra_xhci_hcd *tegra)
+{
+	struct device *dev = tegra->dev;
+	struct tegra_xhci_fw_cfgtbl *cfg_tbl;
+	u64 fw_base;
+	u32 val, code_tag_blocks, code_size_blocks;
+	time_t fw_time;
+	struct tm fw_tm;
+
+	if (csb_readl(tegra, XUSB_CSB_MP_ILOAD_BASE_LO) != 0) {
+		dev_info(dev, "Firmware already loaded, Falcon state 0x%x\n",
+			 csb_readl(tegra, XUSB_FALC_CPUCTL));
+		return 0;
+	}
+
+	cfg_tbl = (struct tegra_xhci_fw_cfgtbl *)tegra->fw_data;
+
+	/* Program the size of DFI into ILOAD_ATTR. */
+	csb_writel(tegra, tegra->fw_size, XUSB_CSB_MP_ILOAD_ATTR);
+
+	/*
+	 * Boot code of the firmware reads the ILOAD_BASE registers
+	 * to get to the start of the DFI in system memory.
+	 */
+	fw_base = tegra->fw_dma_addr + sizeof(*cfg_tbl);
+	csb_writel(tegra, fw_base, XUSB_CSB_MP_ILOAD_BASE_LO);
+	csb_writel(tegra, fw_base >> 32, XUSB_CSB_MP_ILOAD_BASE_HI);
+
+	/* Set BOOTPATH to 1 in APMAP. */
+	csb_writel(tegra, APMAP_BOOTPATH, XUSB_CSB_MP_APMAP);
+
+	/* Invalidate L2IMEM. */
+	csb_writel(tegra, L2IMEMOP_INVALIDATE_ALL, XUSB_CSB_MP_L2IMEMOP_TRIG);
+
+	/*
+	 * Initiate fetch of bootcode from system memory into L2IMEM.
+	 * Program bootcode location and size in system memory.
+	 */
+	code_tag_blocks = DIV_ROUND_UP(le32_to_cpu(cfg_tbl->boot_codetag),
+				       IMEM_BLOCK_SIZE);
+	code_size_blocks = DIV_ROUND_UP(le32_to_cpu(cfg_tbl->boot_codesize),
+					IMEM_BLOCK_SIZE);
+	val = ((code_tag_blocks & L2IMEMOP_SIZE_SRC_OFFSET_MASK) <<
+	       L2IMEMOP_SIZE_SRC_OFFSET_SHIFT) |
+	      ((code_size_blocks & L2IMEMOP_SIZE_SRC_COUNT_MASK) <<
+	       L2IMEMOP_SIZE_SRC_COUNT_SHIFT);
+	csb_writel(tegra, val, XUSB_CSB_MP_L2IMEMOP_SIZE);
+
+	/* Trigger L2IMEM Load operation. */
+	csb_writel(tegra, L2IMEMOP_LOAD_LOCKED_RESULT,
+		   XUSB_CSB_MP_L2IMEMOP_TRIG);
+
+	/* Setup Falcon Auto-fill. */
+	csb_writel(tegra, code_size_blocks, XUSB_FALC_IMFILLCTL);
+
+	val = ((code_tag_blocks & IMFILLRNG1_TAG_MASK) <<
+	       IMFILLRNG1_TAG_LO_SHIFT) |
+	      (((code_size_blocks + code_tag_blocks) & IMFILLRNG1_TAG_MASK) <<
+	       IMFILLRNG1_TAG_HI_SHIFT);
+	csb_writel(tegra, val, XUSB_FALC_IMFILLRNG1);
+
+	csb_writel(tegra, 0, XUSB_FALC_DMACTL);
+	msleep(50);
+
+	csb_writel(tegra, le32_to_cpu(cfg_tbl->boot_codetag),
+		   XUSB_FALC_BOOTVEC);
+
+	/* Start Falcon CPU. */
+	csb_writel(tegra, CPUCTL_STARTCPU, XUSB_FALC_CPUCTL);
+	usleep_range(1000, 2000);
+
+	fw_time = le32_to_cpu(cfg_tbl->fwimg_created_time);
+	time_to_tm(fw_time, 0, &fw_tm);
+	dev_info(dev,
+		 "Firmware timestamp: %ld-%02d-%02d %02d:%02d:%02d UTC, "
+		 "Falcon state 0x%x\n", fw_tm.tm_year + 1900,
+		 fw_tm.tm_mon + 1, fw_tm.tm_mday, fw_tm.tm_hour,
+		 fw_tm.tm_min, fw_tm.tm_sec,
+		 csb_readl(tegra, XUSB_FALC_CPUCTL));
+
+	/* Make sure Falcon CPU is now running. */
+	if (csb_readl(tegra, XUSB_FALC_CPUCTL) == CPUCTL_STATE_HALTED)
+		return -EIO;
+
+	return 0;
+}
+
+static int tegra_xhci_set_ss_clk(struct tegra_xhci_hcd *tegra,
+				 unsigned long rate)
+{
+	unsigned long new_parent_rate, old_parent_rate;
+	int ret, div;
+	struct clk *clk = tegra->ss_src_clk;
+
+	if (clk_get_rate(clk) == rate)
+		return 0;
+
+	switch (rate) {
+	case TEGRA_XHCI_SS_CLK_HIGH_SPEED:
+		/*
+		 * Reparent to PLLU_480M. Set divider first to avoid
+		 * overclocking.
+		 */
+		old_parent_rate = clk_get_rate(clk_get_parent(clk));
+		new_parent_rate = clk_get_rate(tegra->pll_u_480m);
+		div = new_parent_rate / rate;
+		ret = clk_set_rate(clk, old_parent_rate / div);
+		if (ret)
+			return ret;
+		ret = clk_set_parent(clk, tegra->pll_u_480m);
+		if (ret)
+			return ret;
+		/*
+		 * The rate should already be correct, but set it again just
+		 * to be sure.
+		 */
+		ret = clk_set_rate(clk, rate);
+		if (ret)
+			return ret;
+		break;
+	case TEGRA_XHCI_SS_CLK_LOW_SPEED:
+		/* Reparent to CLK_M */
+		ret = clk_set_parent(clk, tegra->clk_m);
+		if (ret)
+			return ret;
+		ret = clk_set_rate(clk, rate);
+		if (ret)
+			return ret;
+		break;
+	default:
+		dev_err(tegra->dev, "Invalid SS rate: %lu\n", rate);
+		return -EINVAL;
+	}
+
+	if (clk_get_rate(clk) != rate) {
+		dev_err(tegra->dev, "SS clock doesn't match requested rate\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int tegra_xhci_clk_enable(struct tegra_xhci_hcd *tegra)
+{
+	clk_prepare_enable(tegra->pll_e);
+	clk_prepare_enable(tegra->host_clk);
+	clk_prepare_enable(tegra->ss_clk);
+	clk_prepare_enable(tegra->falc_clk);
+	clk_prepare_enable(tegra->fs_src_clk);
+	clk_prepare_enable(tegra->hs_src_clk);
+
+	return tegra_xhci_set_ss_clk(tegra, TEGRA_XHCI_SS_CLK_HIGH_SPEED);
+}
+
+static void tegra_xhci_clk_disable(struct tegra_xhci_hcd *tegra)
+{
+	clk_disable_unprepare(tegra->pll_e);
+	clk_disable_unprepare(tegra->host_clk);
+	clk_disable_unprepare(tegra->ss_clk);
+	clk_disable_unprepare(tegra->falc_clk);
+	clk_disable_unprepare(tegra->fs_src_clk);
+	clk_disable_unprepare(tegra->hs_src_clk);
+}
+
+static int tegra_xhci_phy_enable(struct tegra_xhci_hcd *tegra)
+{
+	int ret;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(tegra->phys); i++) {
+		ret = phy_init(tegra->phys[i]);
+		if (ret)
+			goto disable_phy;
+		ret = phy_power_on(tegra->phys[i]);
+		if (ret) {
+			phy_exit(tegra->phys[i]);
+			goto disable_phy;
+		}
+	}
+
+	return 0;
+disable_phy:
+	for (i = i - 1; i >= 0; i--) {
+		phy_power_off(tegra->phys[i]);
+		phy_exit(tegra->phys[i]);
+	}
+	return ret;
+}
+
+static void tegra_xhci_phy_disable(struct tegra_xhci_hcd *tegra)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(tegra->phys); i++) {
+		phy_power_off(tegra->phys[i]);
+		phy_exit(tegra->phys[i]);
+	}
+}
+
+static void tegra_xhci_mbox_work(struct work_struct *work)
+{
+	struct tegra_xhci_hcd *tegra = container_of(work, struct tegra_xhci_hcd,
+						    mbox_req_work);
+	struct tegra_xusb_mbox_msg resp;
+	int ret;
+
+	switch (tegra->mbox_req.cmd) {
+	case MBOX_CMD_INC_SSPI_CLOCK:
+	case MBOX_CMD_DEC_SSPI_CLOCK:
+		ret = tegra_xhci_set_ss_clk(tegra, tegra->mbox_req.data * 1000);
+		resp.data = clk_get_rate(tegra->ss_src_clk) / 1000;
+		if (ret)
+			resp.cmd = MBOX_CMD_NAK;
+		else
+			resp.cmd = MBOX_CMD_ACK;
+		break;
+	case MBOX_CMD_INC_FALC_CLOCK:
+	case MBOX_CMD_DEC_FALC_CLOCK:
+		resp.data = clk_get_rate(tegra->falc_clk) / 1000;
+		if (resp.data != tegra->mbox_req.data)
+			resp.cmd = MBOX_CMD_NAK;
+		else
+			resp.cmd = MBOX_CMD_ACK;
+		break;
+	case MBOX_CMD_SET_BW:
+		/* TODO: Request bandwidth once EMC scaling is supported. */
+		/* SET_BW messages do not require an ACK/NAK. */
+		resp.data = 0;
+		resp.cmd = 0;
+		break;
+	default:
+		resp.data = 0;
+		resp.cmd = MBOX_CMD_NAK;
+		dev_err(tegra->dev, "Unexpected message 0x%x:0x%x\n",
+			tegra->mbox_req.cmd, tegra->mbox_req.data);
+		break;
+	}
+
+	if (resp.cmd)
+		mbox_send_message(tegra->mbox_chan, &resp);
+}
+
+static void tegra_xhci_mbox_rx(struct mbox_client *cl, void *data)
+{
+	struct tegra_xhci_hcd *tegra = dev_get_drvdata(cl->dev);
+	struct tegra_xusb_mbox_msg *msg = data;
+
+	tegra->mbox_req = *msg;
+	schedule_work(&tegra->mbox_req_work);
+}
+
+static void tegra_xhci_quirks(struct device *dev, struct xhci_hcd *xhci)
+{
+	xhci->quirks |= XHCI_PLAT;
+}
+
+static int tegra_xhci_setup(struct usb_hcd *hcd)
+{
+	return xhci_gen_setup(hcd, tegra_xhci_quirks);
+}
+
+static const struct tegra_xhci_soc_config tegra124_soc_config = {
+	.firmware_file = "nvidia/tegra124/xusb.bin",
+};
+MODULE_FIRMWARE("nvidia/tegra124/xusb.bin");
+
+static struct of_device_id tegra_xhci_of_match[] = {
+	{ .compatible = "nvidia,tegra124-xhci", .data = &tegra124_soc_config },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, tegra_xhci_of_match);
+
+static void tegra_xhci_probe_finish(const struct firmware *fw, void *context)
+{
+	struct tegra_xhci_hcd *tegra = context;
+	struct device *dev = tegra->dev;
+	struct xhci_hcd *xhci = NULL;
+	struct tegra_xhci_fw_cfgtbl *cfg_tbl;
+	struct tegra_xusb_mbox_msg msg;
+	int ret;
+
+	if (!fw)
+		goto put_usb2_hcd;
+
+	/* Load Falcon controller with its firmware. */
+	cfg_tbl = (struct tegra_xhci_fw_cfgtbl *)fw->data;
+	tegra->fw_size = le32_to_cpu(cfg_tbl->fwimg_len);
+	tegra->fw_data = dma_alloc_coherent(dev, tegra->fw_size,
+					    &tegra->fw_dma_addr,
+					    GFP_KERNEL);
+	if (!tegra->fw_data)
+		goto put_usb2_hcd;
+	memcpy(tegra->fw_data, fw->data, tegra->fw_size);
+
+	ret = tegra_xhci_load_firmware(tegra);
+	if (ret < 0)
+		goto put_usb2_hcd;
+
+	ret = usb_add_hcd(tegra->hcd, tegra->irq, IRQF_SHARED);
+	if (ret < 0)
+		goto put_usb2_hcd;
+	device_wakeup_enable(tegra->hcd->self.controller);
+
+	/*
+	 * USB 2.0 roothub is stored in drvdata now. Swap it with the Tegra HCD.
+	 */
+	tegra->hcd = dev_get_drvdata(dev);
+	dev_set_drvdata(dev, tegra);
+	xhci = hcd_to_xhci(tegra->hcd);
+	xhci->shared_hcd = usb_create_shared_hcd(&tegra_xhci_hc_driver,
+						 dev, dev_name(dev),
+						 tegra->hcd);
+	if (!xhci->shared_hcd)
+		goto dealloc_usb2_hcd;
+
+	/*
+	 * Set the xHCI pointer before xhci_plat_setup() (aka hcd_driver.reset)
+	 * is called by usb_add_hcd().
+	 */
+	*((struct xhci_hcd **) xhci->shared_hcd->hcd_priv) = xhci;
+	ret = usb_add_hcd(xhci->shared_hcd, tegra->irq, IRQF_SHARED);
+	if (ret < 0)
+		goto put_usb3_hcd;
+
+	/* Enable firmware messages from controller. */
+	msg.cmd = MBOX_CMD_MSG_ENABLED;
+	msg.data = 0;
+	ret = mbox_send_message(tegra->mbox_chan, &msg);
+	if (ret < 0)
+		goto dealloc_usb3_hcd;
+
+	tegra->fw_loaded = true;
+	release_firmware(fw);
+	return;
+
+	/* Free up as much as we can and wait to be unbound. */
+dealloc_usb3_hcd:
+	usb_remove_hcd(xhci->shared_hcd);
+put_usb3_hcd:
+	usb_put_hcd(xhci->shared_hcd);
+dealloc_usb2_hcd:
+	usb_remove_hcd(tegra->hcd);
+	kfree(xhci);
+put_usb2_hcd:
+	usb_put_hcd(tegra->hcd);
+	tegra->hcd = NULL;
+	release_firmware(fw);
+}
+
+static int tegra_xhci_probe(struct platform_device *pdev)
+{
+	struct tegra_xhci_hcd *tegra;
+	struct usb_hcd *hcd;
+	struct resource	*res;
+	struct phy *phy;
+	const struct of_device_id *match;
+	int ret, i, j, k;
+
+	BUILD_BUG_ON(sizeof(struct tegra_xhci_fw_cfgtbl) != 256);
+
+	tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL);
+	if (!tegra)
+		return -ENOMEM;
+	tegra->dev = &pdev->dev;
+	platform_set_drvdata(pdev, tegra);
+
+	match = of_match_device(tegra_xhci_of_match, &pdev->dev);
+	if (!match) {
+		dev_err(&pdev->dev, "No device match found\n");
+		return -ENODEV;
+	}
+	tegra->soc_config = match->data;
+
+	/*
+	 * Right now device-tree probed devices don't get dma_mask set.
+	 * Since shared usb code relies on it, set it here for now.
+	 * Once we have dma capability bindings this can go away.
+	 */
+	ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+	if (ret)
+		return ret;
+
+	hcd = usb_create_hcd(&tegra_xhci_hc_driver, &pdev->dev,
+				    dev_name(&pdev->dev));
+	if (!hcd)
+		return -ENOMEM;
+	tegra->hcd = hcd;
+
+	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);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	tegra->fpci_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(tegra->fpci_base)) {
+		ret = PTR_ERR(tegra->fpci_base);
+		goto put_hcd;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+	tegra->ipfs_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(tegra->ipfs_base)) {
+		ret = PTR_ERR(tegra->ipfs_base);
+		goto put_hcd;
+	}
+
+	tegra->irq = platform_get_irq(pdev, 0);
+	if (tegra->irq < 0) {
+		ret = tegra->irq;
+		goto put_hcd;
+	}
+
+	tegra->host_rst = devm_reset_control_get(&pdev->dev, "xusb_host");
+	if (IS_ERR(tegra->host_rst)) {
+		ret = PTR_ERR(tegra->host_rst);
+		goto put_hcd;
+	}
+	tegra->ss_rst = devm_reset_control_get(&pdev->dev, "xusb_ss");
+	if (IS_ERR(tegra->ss_rst)) {
+		ret = PTR_ERR(tegra->ss_rst);
+		goto put_hcd;
+	}
+
+	tegra->host_clk = devm_clk_get(&pdev->dev, "xusb_host");
+	if (IS_ERR(tegra->host_clk)) {
+		ret = PTR_ERR(tegra->host_clk);
+		goto put_hcd;
+	}
+	tegra->falc_clk = devm_clk_get(&pdev->dev, "xusb_falcon_src");
+	if (IS_ERR(tegra->falc_clk)) {
+		ret = PTR_ERR(tegra->falc_clk);
+		goto put_hcd;
+	}
+	tegra->ss_clk = devm_clk_get(&pdev->dev, "xusb_ss");
+	if (IS_ERR(tegra->ss_clk)) {
+		ret = PTR_ERR(tegra->ss_clk);
+		goto put_hcd;
+	}
+	tegra->ss_src_clk = devm_clk_get(&pdev->dev, "xusb_ss_src");
+	if (IS_ERR(tegra->ss_src_clk)) {
+		ret = PTR_ERR(tegra->ss_src_clk);
+		goto put_hcd;
+	}
+	tegra->hs_src_clk = devm_clk_get(&pdev->dev, "xusb_hs_src");
+	if (IS_ERR(tegra->hs_src_clk)) {
+		ret = PTR_ERR(tegra->hs_src_clk);
+		goto put_hcd;
+	}
+	tegra->fs_src_clk = devm_clk_get(&pdev->dev, "xusb_fs_src");
+	if (IS_ERR(tegra->fs_src_clk)) {
+		ret = PTR_ERR(tegra->fs_src_clk);
+		goto put_hcd;
+	}
+	tegra->pll_u_480m = devm_clk_get(&pdev->dev, "pll_u_480m");
+	if (IS_ERR(tegra->pll_u_480m)) {
+		ret = PTR_ERR(tegra->pll_u_480m);
+		goto put_hcd;
+	}
+	tegra->clk_m = devm_clk_get(&pdev->dev, "clk_m");
+	if (IS_ERR(tegra->clk_m)) {
+		ret = PTR_ERR(tegra->clk_m);
+		goto put_hcd;
+	}
+	tegra->pll_e = devm_clk_get(&pdev->dev, "pll_e");
+	if (IS_ERR(tegra->pll_e)) {
+		ret = PTR_ERR(tegra->pll_e);
+		goto put_hcd;
+	}
+	ret = tegra_xhci_clk_enable(tegra);
+	if (ret)
+		goto put_hcd;
+
+	for (i = 0; i < ARRAY_SIZE(tegra->supplies); i++)
+		tegra->supplies[i].supply = tegra_xhci_supply_names[i];
+	ret = devm_regulator_bulk_get(&pdev->dev, ARRAY_SIZE(tegra->supplies),
+				      tegra->supplies);
+	if (ret)
+		goto disable_clk;
+	ret = regulator_bulk_enable(ARRAY_SIZE(tegra->supplies),
+				    tegra->supplies);
+	if (ret)
+		goto disable_clk;
+
+	INIT_WORK(&tegra->mbox_req_work, tegra_xhci_mbox_work);
+	tegra->mbox_client.dev = &pdev->dev;
+	tegra->mbox_client.tx_block = true;
+	tegra->mbox_client.tx_tout = 0;
+	tegra->mbox_client.rx_callback = tegra_xhci_mbox_rx;
+	tegra->mbox_chan = mbox_request_channel(&tegra->mbox_client, 0);
+	if (IS_ERR(tegra->mbox_chan)) {
+		ret = PTR_ERR(tegra->mbox_chan);
+		goto disable_regulator;
+	}
+
+	k = 0;
+	for (i = 0; i < ARRAY_SIZE(tegra_xhci_phy_types); i++) {
+		char prop[8];
+
+		BUG_ON(sizeof(prop) < strlen(tegra_xhci_phy_types[i].name) + 3);
+		for (j = 0; j < tegra_xhci_phy_types[i].num; j++) {
+			sprintf(prop, "%s-%d", tegra_xhci_phy_types[i].name, j);
+			phy = devm_phy_optional_get(&pdev->dev, prop);
+			if (IS_ERR(phy)) {
+				ret = PTR_ERR(phy);
+				goto put_mbox;
+			}
+			tegra->phys[k++] = phy;
+		}
+	}
+
+	/* Setup IPFS access and BAR0 space. */
+	tegra_xhci_cfg(tegra);
+
+	ret = tegra_xhci_phy_enable(tegra);
+	if (ret < 0)
+		goto put_mbox;
+
+	ret = request_firmware_nowait(THIS_MODULE, true,
+				      tegra->soc_config->firmware_file,
+				      tegra->dev, GFP_KERNEL, tegra,
+				      tegra_xhci_probe_finish);
+	if (ret < 0)
+		goto disable_phy;
+
+	return 0;
+
+disable_phy:
+	tegra_xhci_phy_disable(tegra);
+put_mbox:
+	mbox_free_channel(tegra->mbox_chan);
+disable_regulator:
+	regulator_bulk_disable(ARRAY_SIZE(tegra->supplies), tegra->supplies);
+disable_clk:
+	tegra_xhci_clk_disable(tegra);
+put_hcd:
+	usb_put_hcd(hcd);
+	return ret;
+}
+
+static int tegra_xhci_remove(struct platform_device *pdev)
+{
+	struct tegra_xhci_hcd *tegra = platform_get_drvdata(pdev);
+	struct usb_hcd *hcd = tegra->hcd;
+	struct xhci_hcd *xhci;
+
+	if (tegra->fw_loaded) {
+		xhci = hcd_to_xhci(hcd);
+		usb_remove_hcd(xhci->shared_hcd);
+		usb_put_hcd(xhci->shared_hcd);
+		usb_remove_hcd(hcd);
+		usb_put_hcd(hcd);
+		kfree(xhci);
+	} else if (hcd) {
+		/* Unbound after probe(), but before firmware loading. */
+		usb_put_hcd(hcd);
+	}
+
+	if (tegra->fw_data)
+		dma_free_coherent(tegra->dev, tegra->fw_size, tegra->fw_data,
+				  tegra->fw_dma_addr);
+
+	cancel_work_sync(&tegra->mbox_req_work);
+	mbox_free_channel(tegra->mbox_chan);
+	tegra_xhci_phy_disable(tegra);
+	regulator_bulk_disable(ARRAY_SIZE(tegra->supplies), tegra->supplies);
+	tegra_xhci_clk_disable(tegra);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int tegra_xhci_suspend(struct device *dev)
+{
+	struct tegra_xhci_hcd *tegra = dev_get_drvdata(dev);
+	struct xhci_hcd *xhci = hcd_to_xhci(tegra->hcd);
+
+	return xhci_suspend(xhci);
+}
+
+static int tegra_xhci_resume(struct device *dev)
+{
+	struct tegra_xhci_hcd *tegra = dev_get_drvdata(dev);
+	struct xhci_hcd *xhci = hcd_to_xhci(tegra->hcd);
+
+	return xhci_resume(xhci, 0);
+}
+#endif
+
+static const struct dev_pm_ops tegra_xhci_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(tegra_xhci_suspend, tegra_xhci_resume)
+};
+
+static struct platform_driver tegra_xhci_driver = {
+	.probe	= tegra_xhci_probe,
+	.remove	= tegra_xhci_remove,
+	.driver	= {
+		.name = "xhci-tegra",
+		.pm = &tegra_xhci_pm_ops,
+		.of_match_table = of_match_ptr(tegra_xhci_of_match),
+	},
+};
+
+static int __init tegra_xhci_init(void)
+{
+	xhci_init_driver(&tegra_xhci_hc_driver, tegra_xhci_setup);
+	return platform_driver_register(&tegra_xhci_driver);
+}
+module_init(tegra_xhci_init);
+
+static void __exit tegra_xhci_exit(void)
+{
+	platform_driver_unregister(&tegra_xhci_driver);
+}
+module_exit(tegra_xhci_exit);
+
+MODULE_AUTHOR("Andrew Bresticker <abrestic@chromium.org>");
+MODULE_DESCRIPTION("NVIDIA Tegra xHCI host-controller driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:xhci-tegra");
-- 
2.1.0.rc2.206.gedb03e5


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

* [PATCH v2 6/9] usb: xhci: Add NVIDIA Tegra xHCI host-controller driver
@ 2014-08-18 17:08   ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-18 17:08 UTC (permalink / raw)
  To: linux-arm-kernel

Add support for the on-chip xHCI host controller present on Tegra SoCs.

The driver is currently very basic: it loads the controller with its
firmware, starts the controller, and is able to service messages sent
by the controller's firmware.  The hardware supports device mode as
well as lower-power operating modes, but support for these is not yet
implemented here.

Based on work by:
  Ajay Gupta <ajayg@nvidia.com>
  Bharath Yadav <byadav@nvidia.com>

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
---
Changes from v1:
 - Updated to use common mailbox API.
 - Fixed up so that the driver can be built and used as a module.
 - Incorporated review feedback from Stephen.
 - Misc. cleanups.
---
 drivers/usb/host/Kconfig      |   9 +
 drivers/usb/host/Makefile     |   1 +
 drivers/usb/host/xhci-tegra.c | 893 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 903 insertions(+)
 create mode 100644 drivers/usb/host/xhci-tegra.c

diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index f5a5831..1fffbed 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -50,6 +50,15 @@ config USB_XHCI_RCAR
 	  Say 'Y' to enable the support for the xHCI host controller
 	  found in Renesas R-Car ARM SoCs.
 
+config USB_XHCI_TEGRA
+	tristate "NVIDIA Tegra XHCI support"
+	depends on ARCH_TEGRA
+	select MAILBOX
+	select FW_LOADER
+	---help---
+	  Say 'Y' to enable the support for the xHCI host controller
+	  found in NVIDIA Tegra124 and later SoCs.
+
 endif # USB_XHCI_HCD
 
 config USB_EHCI_HCD
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 702d9b7..0a30e26 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_PCI)		+= pci-quirks.o
 
 obj-$(CONFIG_USB_XHCI_PCI)	+= xhci-pci.o
 obj-$(CONFIG_USB_XHCI_PLATFORM) += xhci-plat-hcd.o
+obj-$(CONFIG_USB_XHCI_TEGRA)	+= xhci-tegra.o
 
 obj-$(CONFIG_USB_EHCI_HCD)	+= ehci-hcd.o
 obj-$(CONFIG_USB_EHCI_PCI)	+= ehci-pci.o
diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
new file mode 100644
index 0000000..515aa49
--- /dev/null
+++ b/drivers/usb/host/xhci-tegra.c
@@ -0,0 +1,893 @@
+/*
+ * NVIDIA Tegra xHCI host controller driver
+ *
+ * Copyright (C) 2014 NVIDIA Corporation
+ * Copyright (C) 2014 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/firmware.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mailbox_client.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+
+#include <soc/tegra/xusb.h>
+
+#include "xhci.h"
+
+#define TEGRA_XHCI_SS_CLK_HIGH_SPEED 120000000
+#define TEGRA_XHCI_SS_CLK_LOW_SPEED 12000000
+
+/* FPCI CFG registers */
+#define XUSB_CFG_1				0x004
+#define  XUSB_IO_SPACE_EN			BIT(0)
+#define  XUSB_MEM_SPACE_EN			BIT(1)
+#define  XUSB_BUS_MASTER_EN			BIT(2)
+#define XUSB_CFG_4				0x010
+#define  XUSB_BASE_ADDR_SHIFT			15
+#define  XUSB_BASE_ADDR_MASK			0x1ffff
+#define XUSB_CFG_ARU_C11_CSBRANGE		0x41c
+#define XUSB_CFG_CSB_BASE_ADDR			0x800
+
+/* IPFS registers */
+#define IPFS_XUSB_HOST_CONFIGURATION_0		0x180
+#define  IPFS_EN_FPCI				BIT(0)
+#define IPFS_XUSB_HOST_INTR_MASK_0		0x188
+#define  IPFS_IP_INT_MASK			BIT(16)
+#define IPFS_XUSB_HOST_CLKGATE_HYSTERESIS_0	0x1bc
+
+#define CSB_PAGE_SELECT_MASK			0x7fffff
+#define CSB_PAGE_SELECT_SHIFT			9
+#define CSB_PAGE_OFFSET_MASK			0x1ff
+#define CSB_PAGE_SELECT(addr)	((addr) >> (CSB_PAGE_SELECT_SHIFT) &	\
+				 CSB_PAGE_SELECT_MASK)
+#define CSB_PAGE_OFFSET(addr)	((addr) & CSB_PAGE_OFFSET_MASK)
+
+/* Falcon CSB registers */
+#define XUSB_FALC_CPUCTL			0x100
+#define  CPUCTL_STARTCPU			BIT(1)
+#define  CPUCTL_STATE_HALTED			BIT(4)
+#define XUSB_FALC_BOOTVEC			0x104
+#define XUSB_FALC_DMACTL			0x10c
+#define XUSB_FALC_IMFILLRNG1			0x154
+#define  IMFILLRNG1_TAG_MASK			0xffff
+#define  IMFILLRNG1_TAG_LO_SHIFT		0
+#define  IMFILLRNG1_TAG_HI_SHIFT		16
+#define XUSB_FALC_IMFILLCTL			0x158
+
+/* MP CSB registers */
+#define XUSB_CSB_MP_ILOAD_ATTR			0x101a00
+#define XUSB_CSB_MP_ILOAD_BASE_LO		0x101a04
+#define XUSB_CSB_MP_ILOAD_BASE_HI		0x101a08
+#define XUSB_CSB_MP_L2IMEMOP_SIZE		0x101a10
+#define  L2IMEMOP_SIZE_SRC_OFFSET_SHIFT		8
+#define  L2IMEMOP_SIZE_SRC_OFFSET_MASK		0x3ff
+#define  L2IMEMOP_SIZE_SRC_COUNT_SHIFT		24
+#define  L2IMEMOP_SIZE_SRC_COUNT_MASK		0xff
+#define XUSB_CSB_MP_L2IMEMOP_TRIG		0x101a14
+#define  L2IMEMOP_ACTION_SHIFT			24
+#define  L2IMEMOP_INVALIDATE_ALL		(0x40 << L2IMEMOP_ACTION_SHIFT)
+#define  L2IMEMOP_LOAD_LOCKED_RESULT		(0x11 << L2IMEMOP_ACTION_SHIFT)
+#define XUSB_CSB_MP_APMAP			0x10181c
+#define  APMAP_BOOTPATH				BIT(31)
+
+#define IMEM_BLOCK_SIZE				256
+
+struct tegra_xhci_fw_cfgtbl {
+	u32 boot_loadaddr_in_imem;
+	u32 boot_codedfi_offset;
+	u32 boot_codetag;
+	u32 boot_codesize;
+	u32 phys_memaddr;
+	u16 reqphys_memsize;
+	u16 alloc_phys_memsize;
+	u32 rodata_img_offset;
+	u32 rodata_section_start;
+	u32 rodata_section_end;
+	u32 main_fnaddr;
+	u32 fwimg_cksum;
+	u32 fwimg_created_time;
+	u32 imem_resident_start;
+	u32 imem_resident_end;
+	u32 idirect_start;
+	u32 idirect_end;
+	u32 l2_imem_start;
+	u32 l2_imem_end;
+	u32 version_id;
+	u8 init_ddirect;
+	u8 reserved[3];
+	u32 phys_addr_log_buffer;
+	u32 total_log_entries;
+	u32 dequeue_ptr;
+	u32 dummy_var[2];
+	u32 fwimg_len;
+	u8 magic[8];
+	u32 ss_low_power_entry_timeout;
+	u8 num_hsic_port;
+	u8 padding[139]; /* Padding to make 256-bytes cfgtbl */
+};
+
+struct tegra_xhci_soc_config {
+	const char *firmware_file;
+};
+
+#define TEGRA_XHCI_NUM_SUPPLIES 8
+static const char *tegra_xhci_supply_names[TEGRA_XHCI_NUM_SUPPLIES] = {
+	"avddio-pex",
+	"dvddio-pex",
+	"avdd-usb",
+	"avdd-pll-utmip",
+	"avdd-pll-erefe",
+	"avdd-pex-pll",
+	"hvdd-pex",
+	"hvdd-pex-plle",
+};
+
+static const struct {
+	const char *name;
+	int num;
+} tegra_xhci_phy_types[] = {
+	{
+		.name = "usb3",
+		.num = TEGRA_XUSB_USB3_PHYS,
+	}, {
+		.name = "utmi",
+		.num = TEGRA_XUSB_UTMI_PHYS,
+	}, {
+		.name = "hsic",
+		.num = TEGRA_XUSB_HSIC_PHYS,
+	},
+};
+
+struct tegra_xhci_hcd {
+	struct device *dev;
+	struct usb_hcd *hcd;
+
+	int irq;
+
+	void __iomem *fpci_base;
+	void __iomem *ipfs_base;
+
+	const struct tegra_xhci_soc_config *soc_config;
+
+	struct regulator_bulk_data supplies[TEGRA_XHCI_NUM_SUPPLIES];
+
+	struct clk *host_clk;
+	struct clk *falc_clk;
+	struct clk *ss_clk;
+	struct clk *ss_src_clk;
+	struct clk *hs_src_clk;
+	struct clk *fs_src_clk;
+	struct clk *pll_u_480m;
+	struct clk *clk_m;
+	struct clk *pll_e;
+
+	struct reset_control *host_rst;
+	struct reset_control *ss_rst;
+
+	struct phy *phys[TEGRA_XUSB_NUM_USB_PHYS];
+
+	struct work_struct mbox_req_work;
+	struct tegra_xusb_mbox_msg mbox_req;
+	struct mbox_client mbox_client;
+	struct mbox_chan *mbox_chan;
+
+	/* Firmware loading related */
+	void *fw_data;
+	size_t fw_size;
+	dma_addr_t fw_dma_addr;
+	bool fw_loaded;
+};
+
+static struct hc_driver __read_mostly tegra_xhci_hc_driver;
+
+static inline u32 fpci_readl(struct tegra_xhci_hcd *tegra, u32 addr)
+{
+	return readl(tegra->fpci_base + addr);
+}
+
+static inline void fpci_writel(struct tegra_xhci_hcd *tegra, u32 val, u32 addr)
+{
+	writel(val, tegra->fpci_base + addr);
+}
+
+static inline u32 ipfs_readl(struct tegra_xhci_hcd *tegra, u32 addr)
+{
+	return readl(tegra->ipfs_base + addr);
+}
+
+static inline void ipfs_writel(struct tegra_xhci_hcd *tegra, u32 val, u32 addr)
+{
+	writel(val, tegra->ipfs_base + addr);
+}
+
+static u32 csb_readl(struct tegra_xhci_hcd *tegra, u32 addr)
+{
+	u32 page, offset;
+
+	page = CSB_PAGE_SELECT(addr);
+	offset = CSB_PAGE_OFFSET(addr);
+	fpci_writel(tegra, page, XUSB_CFG_ARU_C11_CSBRANGE);
+	return fpci_readl(tegra, XUSB_CFG_CSB_BASE_ADDR + offset);
+}
+
+static void csb_writel(struct tegra_xhci_hcd *tegra, u32 val, u32 addr)
+{
+	u32 page, offset;
+
+	page = CSB_PAGE_SELECT(addr);
+	offset = CSB_PAGE_OFFSET(addr);
+	fpci_writel(tegra, page, XUSB_CFG_ARU_C11_CSBRANGE);
+	fpci_writel(tegra, val, XUSB_CFG_CSB_BASE_ADDR + offset);
+}
+
+static void tegra_xhci_cfg(struct tegra_xhci_hcd *tegra)
+{
+	u32 reg;
+
+	reg = ipfs_readl(tegra, IPFS_XUSB_HOST_CONFIGURATION_0);
+	reg |= IPFS_EN_FPCI;
+	ipfs_writel(tegra, reg, IPFS_XUSB_HOST_CONFIGURATION_0);
+	udelay(10);
+
+	/* Program Bar0 Space */
+	reg = fpci_readl(tegra, XUSB_CFG_4);
+	reg &= ~(XUSB_BASE_ADDR_MASK << XUSB_BASE_ADDR_SHIFT);
+	reg |= tegra->hcd->rsrc_start & (XUSB_BASE_ADDR_MASK <<
+					 XUSB_BASE_ADDR_SHIFT);
+	fpci_writel(tegra, reg, XUSB_CFG_4);
+	usleep_range(100, 200);
+
+	/* Enable Bus Master */
+	reg = fpci_readl(tegra, XUSB_CFG_1);
+	reg |= XUSB_IO_SPACE_EN | XUSB_MEM_SPACE_EN | XUSB_BUS_MASTER_EN;
+	fpci_writel(tegra, reg, XUSB_CFG_1);
+
+	/* Set intr mask to enable intr assertion */
+	reg = ipfs_readl(tegra, IPFS_XUSB_HOST_INTR_MASK_0);
+	reg |= IPFS_IP_INT_MASK;
+	ipfs_writel(tegra, reg, IPFS_XUSB_HOST_INTR_MASK_0);
+
+	/* Set hysteris to 0x80 */
+	ipfs_writel(tegra, 0x80, IPFS_XUSB_HOST_CLKGATE_HYSTERESIS_0);
+}
+
+static int tegra_xhci_load_firmware(struct tegra_xhci_hcd *tegra)
+{
+	struct device *dev = tegra->dev;
+	struct tegra_xhci_fw_cfgtbl *cfg_tbl;
+	u64 fw_base;
+	u32 val, code_tag_blocks, code_size_blocks;
+	time_t fw_time;
+	struct tm fw_tm;
+
+	if (csb_readl(tegra, XUSB_CSB_MP_ILOAD_BASE_LO) != 0) {
+		dev_info(dev, "Firmware already loaded, Falcon state 0x%x\n",
+			 csb_readl(tegra, XUSB_FALC_CPUCTL));
+		return 0;
+	}
+
+	cfg_tbl = (struct tegra_xhci_fw_cfgtbl *)tegra->fw_data;
+
+	/* Program the size of DFI into ILOAD_ATTR. */
+	csb_writel(tegra, tegra->fw_size, XUSB_CSB_MP_ILOAD_ATTR);
+
+	/*
+	 * Boot code of the firmware reads the ILOAD_BASE registers
+	 * to get to the start of the DFI in system memory.
+	 */
+	fw_base = tegra->fw_dma_addr + sizeof(*cfg_tbl);
+	csb_writel(tegra, fw_base, XUSB_CSB_MP_ILOAD_BASE_LO);
+	csb_writel(tegra, fw_base >> 32, XUSB_CSB_MP_ILOAD_BASE_HI);
+
+	/* Set BOOTPATH to 1 in APMAP. */
+	csb_writel(tegra, APMAP_BOOTPATH, XUSB_CSB_MP_APMAP);
+
+	/* Invalidate L2IMEM. */
+	csb_writel(tegra, L2IMEMOP_INVALIDATE_ALL, XUSB_CSB_MP_L2IMEMOP_TRIG);
+
+	/*
+	 * Initiate fetch of bootcode from system memory into L2IMEM.
+	 * Program bootcode location and size in system memory.
+	 */
+	code_tag_blocks = DIV_ROUND_UP(le32_to_cpu(cfg_tbl->boot_codetag),
+				       IMEM_BLOCK_SIZE);
+	code_size_blocks = DIV_ROUND_UP(le32_to_cpu(cfg_tbl->boot_codesize),
+					IMEM_BLOCK_SIZE);
+	val = ((code_tag_blocks & L2IMEMOP_SIZE_SRC_OFFSET_MASK) <<
+	       L2IMEMOP_SIZE_SRC_OFFSET_SHIFT) |
+	      ((code_size_blocks & L2IMEMOP_SIZE_SRC_COUNT_MASK) <<
+	       L2IMEMOP_SIZE_SRC_COUNT_SHIFT);
+	csb_writel(tegra, val, XUSB_CSB_MP_L2IMEMOP_SIZE);
+
+	/* Trigger L2IMEM Load operation. */
+	csb_writel(tegra, L2IMEMOP_LOAD_LOCKED_RESULT,
+		   XUSB_CSB_MP_L2IMEMOP_TRIG);
+
+	/* Setup Falcon Auto-fill. */
+	csb_writel(tegra, code_size_blocks, XUSB_FALC_IMFILLCTL);
+
+	val = ((code_tag_blocks & IMFILLRNG1_TAG_MASK) <<
+	       IMFILLRNG1_TAG_LO_SHIFT) |
+	      (((code_size_blocks + code_tag_blocks) & IMFILLRNG1_TAG_MASK) <<
+	       IMFILLRNG1_TAG_HI_SHIFT);
+	csb_writel(tegra, val, XUSB_FALC_IMFILLRNG1);
+
+	csb_writel(tegra, 0, XUSB_FALC_DMACTL);
+	msleep(50);
+
+	csb_writel(tegra, le32_to_cpu(cfg_tbl->boot_codetag),
+		   XUSB_FALC_BOOTVEC);
+
+	/* Start Falcon CPU. */
+	csb_writel(tegra, CPUCTL_STARTCPU, XUSB_FALC_CPUCTL);
+	usleep_range(1000, 2000);
+
+	fw_time = le32_to_cpu(cfg_tbl->fwimg_created_time);
+	time_to_tm(fw_time, 0, &fw_tm);
+	dev_info(dev,
+		 "Firmware timestamp: %ld-%02d-%02d %02d:%02d:%02d UTC, "
+		 "Falcon state 0x%x\n", fw_tm.tm_year + 1900,
+		 fw_tm.tm_mon + 1, fw_tm.tm_mday, fw_tm.tm_hour,
+		 fw_tm.tm_min, fw_tm.tm_sec,
+		 csb_readl(tegra, XUSB_FALC_CPUCTL));
+
+	/* Make sure Falcon CPU is now running. */
+	if (csb_readl(tegra, XUSB_FALC_CPUCTL) == CPUCTL_STATE_HALTED)
+		return -EIO;
+
+	return 0;
+}
+
+static int tegra_xhci_set_ss_clk(struct tegra_xhci_hcd *tegra,
+				 unsigned long rate)
+{
+	unsigned long new_parent_rate, old_parent_rate;
+	int ret, div;
+	struct clk *clk = tegra->ss_src_clk;
+
+	if (clk_get_rate(clk) == rate)
+		return 0;
+
+	switch (rate) {
+	case TEGRA_XHCI_SS_CLK_HIGH_SPEED:
+		/*
+		 * Reparent to PLLU_480M. Set divider first to avoid
+		 * overclocking.
+		 */
+		old_parent_rate = clk_get_rate(clk_get_parent(clk));
+		new_parent_rate = clk_get_rate(tegra->pll_u_480m);
+		div = new_parent_rate / rate;
+		ret = clk_set_rate(clk, old_parent_rate / div);
+		if (ret)
+			return ret;
+		ret = clk_set_parent(clk, tegra->pll_u_480m);
+		if (ret)
+			return ret;
+		/*
+		 * The rate should already be correct, but set it again just
+		 * to be sure.
+		 */
+		ret = clk_set_rate(clk, rate);
+		if (ret)
+			return ret;
+		break;
+	case TEGRA_XHCI_SS_CLK_LOW_SPEED:
+		/* Reparent to CLK_M */
+		ret = clk_set_parent(clk, tegra->clk_m);
+		if (ret)
+			return ret;
+		ret = clk_set_rate(clk, rate);
+		if (ret)
+			return ret;
+		break;
+	default:
+		dev_err(tegra->dev, "Invalid SS rate: %lu\n", rate);
+		return -EINVAL;
+	}
+
+	if (clk_get_rate(clk) != rate) {
+		dev_err(tegra->dev, "SS clock doesn't match requested rate\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int tegra_xhci_clk_enable(struct tegra_xhci_hcd *tegra)
+{
+	clk_prepare_enable(tegra->pll_e);
+	clk_prepare_enable(tegra->host_clk);
+	clk_prepare_enable(tegra->ss_clk);
+	clk_prepare_enable(tegra->falc_clk);
+	clk_prepare_enable(tegra->fs_src_clk);
+	clk_prepare_enable(tegra->hs_src_clk);
+
+	return tegra_xhci_set_ss_clk(tegra, TEGRA_XHCI_SS_CLK_HIGH_SPEED);
+}
+
+static void tegra_xhci_clk_disable(struct tegra_xhci_hcd *tegra)
+{
+	clk_disable_unprepare(tegra->pll_e);
+	clk_disable_unprepare(tegra->host_clk);
+	clk_disable_unprepare(tegra->ss_clk);
+	clk_disable_unprepare(tegra->falc_clk);
+	clk_disable_unprepare(tegra->fs_src_clk);
+	clk_disable_unprepare(tegra->hs_src_clk);
+}
+
+static int tegra_xhci_phy_enable(struct tegra_xhci_hcd *tegra)
+{
+	int ret;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(tegra->phys); i++) {
+		ret = phy_init(tegra->phys[i]);
+		if (ret)
+			goto disable_phy;
+		ret = phy_power_on(tegra->phys[i]);
+		if (ret) {
+			phy_exit(tegra->phys[i]);
+			goto disable_phy;
+		}
+	}
+
+	return 0;
+disable_phy:
+	for (i = i - 1; i >= 0; i--) {
+		phy_power_off(tegra->phys[i]);
+		phy_exit(tegra->phys[i]);
+	}
+	return ret;
+}
+
+static void tegra_xhci_phy_disable(struct tegra_xhci_hcd *tegra)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(tegra->phys); i++) {
+		phy_power_off(tegra->phys[i]);
+		phy_exit(tegra->phys[i]);
+	}
+}
+
+static void tegra_xhci_mbox_work(struct work_struct *work)
+{
+	struct tegra_xhci_hcd *tegra = container_of(work, struct tegra_xhci_hcd,
+						    mbox_req_work);
+	struct tegra_xusb_mbox_msg resp;
+	int ret;
+
+	switch (tegra->mbox_req.cmd) {
+	case MBOX_CMD_INC_SSPI_CLOCK:
+	case MBOX_CMD_DEC_SSPI_CLOCK:
+		ret = tegra_xhci_set_ss_clk(tegra, tegra->mbox_req.data * 1000);
+		resp.data = clk_get_rate(tegra->ss_src_clk) / 1000;
+		if (ret)
+			resp.cmd = MBOX_CMD_NAK;
+		else
+			resp.cmd = MBOX_CMD_ACK;
+		break;
+	case MBOX_CMD_INC_FALC_CLOCK:
+	case MBOX_CMD_DEC_FALC_CLOCK:
+		resp.data = clk_get_rate(tegra->falc_clk) / 1000;
+		if (resp.data != tegra->mbox_req.data)
+			resp.cmd = MBOX_CMD_NAK;
+		else
+			resp.cmd = MBOX_CMD_ACK;
+		break;
+	case MBOX_CMD_SET_BW:
+		/* TODO: Request bandwidth once EMC scaling is supported. */
+		/* SET_BW messages do not require an ACK/NAK. */
+		resp.data = 0;
+		resp.cmd = 0;
+		break;
+	default:
+		resp.data = 0;
+		resp.cmd = MBOX_CMD_NAK;
+		dev_err(tegra->dev, "Unexpected message 0x%x:0x%x\n",
+			tegra->mbox_req.cmd, tegra->mbox_req.data);
+		break;
+	}
+
+	if (resp.cmd)
+		mbox_send_message(tegra->mbox_chan, &resp);
+}
+
+static void tegra_xhci_mbox_rx(struct mbox_client *cl, void *data)
+{
+	struct tegra_xhci_hcd *tegra = dev_get_drvdata(cl->dev);
+	struct tegra_xusb_mbox_msg *msg = data;
+
+	tegra->mbox_req = *msg;
+	schedule_work(&tegra->mbox_req_work);
+}
+
+static void tegra_xhci_quirks(struct device *dev, struct xhci_hcd *xhci)
+{
+	xhci->quirks |= XHCI_PLAT;
+}
+
+static int tegra_xhci_setup(struct usb_hcd *hcd)
+{
+	return xhci_gen_setup(hcd, tegra_xhci_quirks);
+}
+
+static const struct tegra_xhci_soc_config tegra124_soc_config = {
+	.firmware_file = "nvidia/tegra124/xusb.bin",
+};
+MODULE_FIRMWARE("nvidia/tegra124/xusb.bin");
+
+static struct of_device_id tegra_xhci_of_match[] = {
+	{ .compatible = "nvidia,tegra124-xhci", .data = &tegra124_soc_config },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, tegra_xhci_of_match);
+
+static void tegra_xhci_probe_finish(const struct firmware *fw, void *context)
+{
+	struct tegra_xhci_hcd *tegra = context;
+	struct device *dev = tegra->dev;
+	struct xhci_hcd *xhci = NULL;
+	struct tegra_xhci_fw_cfgtbl *cfg_tbl;
+	struct tegra_xusb_mbox_msg msg;
+	int ret;
+
+	if (!fw)
+		goto put_usb2_hcd;
+
+	/* Load Falcon controller with its firmware. */
+	cfg_tbl = (struct tegra_xhci_fw_cfgtbl *)fw->data;
+	tegra->fw_size = le32_to_cpu(cfg_tbl->fwimg_len);
+	tegra->fw_data = dma_alloc_coherent(dev, tegra->fw_size,
+					    &tegra->fw_dma_addr,
+					    GFP_KERNEL);
+	if (!tegra->fw_data)
+		goto put_usb2_hcd;
+	memcpy(tegra->fw_data, fw->data, tegra->fw_size);
+
+	ret = tegra_xhci_load_firmware(tegra);
+	if (ret < 0)
+		goto put_usb2_hcd;
+
+	ret = usb_add_hcd(tegra->hcd, tegra->irq, IRQF_SHARED);
+	if (ret < 0)
+		goto put_usb2_hcd;
+	device_wakeup_enable(tegra->hcd->self.controller);
+
+	/*
+	 * USB 2.0 roothub is stored in drvdata now. Swap it with the Tegra HCD.
+	 */
+	tegra->hcd = dev_get_drvdata(dev);
+	dev_set_drvdata(dev, tegra);
+	xhci = hcd_to_xhci(tegra->hcd);
+	xhci->shared_hcd = usb_create_shared_hcd(&tegra_xhci_hc_driver,
+						 dev, dev_name(dev),
+						 tegra->hcd);
+	if (!xhci->shared_hcd)
+		goto dealloc_usb2_hcd;
+
+	/*
+	 * Set the xHCI pointer before xhci_plat_setup() (aka hcd_driver.reset)
+	 * is called by usb_add_hcd().
+	 */
+	*((struct xhci_hcd **) xhci->shared_hcd->hcd_priv) = xhci;
+	ret = usb_add_hcd(xhci->shared_hcd, tegra->irq, IRQF_SHARED);
+	if (ret < 0)
+		goto put_usb3_hcd;
+
+	/* Enable firmware messages from controller. */
+	msg.cmd = MBOX_CMD_MSG_ENABLED;
+	msg.data = 0;
+	ret = mbox_send_message(tegra->mbox_chan, &msg);
+	if (ret < 0)
+		goto dealloc_usb3_hcd;
+
+	tegra->fw_loaded = true;
+	release_firmware(fw);
+	return;
+
+	/* Free up as much as we can and wait to be unbound. */
+dealloc_usb3_hcd:
+	usb_remove_hcd(xhci->shared_hcd);
+put_usb3_hcd:
+	usb_put_hcd(xhci->shared_hcd);
+dealloc_usb2_hcd:
+	usb_remove_hcd(tegra->hcd);
+	kfree(xhci);
+put_usb2_hcd:
+	usb_put_hcd(tegra->hcd);
+	tegra->hcd = NULL;
+	release_firmware(fw);
+}
+
+static int tegra_xhci_probe(struct platform_device *pdev)
+{
+	struct tegra_xhci_hcd *tegra;
+	struct usb_hcd *hcd;
+	struct resource	*res;
+	struct phy *phy;
+	const struct of_device_id *match;
+	int ret, i, j, k;
+
+	BUILD_BUG_ON(sizeof(struct tegra_xhci_fw_cfgtbl) != 256);
+
+	tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL);
+	if (!tegra)
+		return -ENOMEM;
+	tegra->dev = &pdev->dev;
+	platform_set_drvdata(pdev, tegra);
+
+	match = of_match_device(tegra_xhci_of_match, &pdev->dev);
+	if (!match) {
+		dev_err(&pdev->dev, "No device match found\n");
+		return -ENODEV;
+	}
+	tegra->soc_config = match->data;
+
+	/*
+	 * Right now device-tree probed devices don't get dma_mask set.
+	 * Since shared usb code relies on it, set it here for now.
+	 * Once we have dma capability bindings this can go away.
+	 */
+	ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+	if (ret)
+		return ret;
+
+	hcd = usb_create_hcd(&tegra_xhci_hc_driver, &pdev->dev,
+				    dev_name(&pdev->dev));
+	if (!hcd)
+		return -ENOMEM;
+	tegra->hcd = hcd;
+
+	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);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	tegra->fpci_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(tegra->fpci_base)) {
+		ret = PTR_ERR(tegra->fpci_base);
+		goto put_hcd;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+	tegra->ipfs_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(tegra->ipfs_base)) {
+		ret = PTR_ERR(tegra->ipfs_base);
+		goto put_hcd;
+	}
+
+	tegra->irq = platform_get_irq(pdev, 0);
+	if (tegra->irq < 0) {
+		ret = tegra->irq;
+		goto put_hcd;
+	}
+
+	tegra->host_rst = devm_reset_control_get(&pdev->dev, "xusb_host");
+	if (IS_ERR(tegra->host_rst)) {
+		ret = PTR_ERR(tegra->host_rst);
+		goto put_hcd;
+	}
+	tegra->ss_rst = devm_reset_control_get(&pdev->dev, "xusb_ss");
+	if (IS_ERR(tegra->ss_rst)) {
+		ret = PTR_ERR(tegra->ss_rst);
+		goto put_hcd;
+	}
+
+	tegra->host_clk = devm_clk_get(&pdev->dev, "xusb_host");
+	if (IS_ERR(tegra->host_clk)) {
+		ret = PTR_ERR(tegra->host_clk);
+		goto put_hcd;
+	}
+	tegra->falc_clk = devm_clk_get(&pdev->dev, "xusb_falcon_src");
+	if (IS_ERR(tegra->falc_clk)) {
+		ret = PTR_ERR(tegra->falc_clk);
+		goto put_hcd;
+	}
+	tegra->ss_clk = devm_clk_get(&pdev->dev, "xusb_ss");
+	if (IS_ERR(tegra->ss_clk)) {
+		ret = PTR_ERR(tegra->ss_clk);
+		goto put_hcd;
+	}
+	tegra->ss_src_clk = devm_clk_get(&pdev->dev, "xusb_ss_src");
+	if (IS_ERR(tegra->ss_src_clk)) {
+		ret = PTR_ERR(tegra->ss_src_clk);
+		goto put_hcd;
+	}
+	tegra->hs_src_clk = devm_clk_get(&pdev->dev, "xusb_hs_src");
+	if (IS_ERR(tegra->hs_src_clk)) {
+		ret = PTR_ERR(tegra->hs_src_clk);
+		goto put_hcd;
+	}
+	tegra->fs_src_clk = devm_clk_get(&pdev->dev, "xusb_fs_src");
+	if (IS_ERR(tegra->fs_src_clk)) {
+		ret = PTR_ERR(tegra->fs_src_clk);
+		goto put_hcd;
+	}
+	tegra->pll_u_480m = devm_clk_get(&pdev->dev, "pll_u_480m");
+	if (IS_ERR(tegra->pll_u_480m)) {
+		ret = PTR_ERR(tegra->pll_u_480m);
+		goto put_hcd;
+	}
+	tegra->clk_m = devm_clk_get(&pdev->dev, "clk_m");
+	if (IS_ERR(tegra->clk_m)) {
+		ret = PTR_ERR(tegra->clk_m);
+		goto put_hcd;
+	}
+	tegra->pll_e = devm_clk_get(&pdev->dev, "pll_e");
+	if (IS_ERR(tegra->pll_e)) {
+		ret = PTR_ERR(tegra->pll_e);
+		goto put_hcd;
+	}
+	ret = tegra_xhci_clk_enable(tegra);
+	if (ret)
+		goto put_hcd;
+
+	for (i = 0; i < ARRAY_SIZE(tegra->supplies); i++)
+		tegra->supplies[i].supply = tegra_xhci_supply_names[i];
+	ret = devm_regulator_bulk_get(&pdev->dev, ARRAY_SIZE(tegra->supplies),
+				      tegra->supplies);
+	if (ret)
+		goto disable_clk;
+	ret = regulator_bulk_enable(ARRAY_SIZE(tegra->supplies),
+				    tegra->supplies);
+	if (ret)
+		goto disable_clk;
+
+	INIT_WORK(&tegra->mbox_req_work, tegra_xhci_mbox_work);
+	tegra->mbox_client.dev = &pdev->dev;
+	tegra->mbox_client.tx_block = true;
+	tegra->mbox_client.tx_tout = 0;
+	tegra->mbox_client.rx_callback = tegra_xhci_mbox_rx;
+	tegra->mbox_chan = mbox_request_channel(&tegra->mbox_client, 0);
+	if (IS_ERR(tegra->mbox_chan)) {
+		ret = PTR_ERR(tegra->mbox_chan);
+		goto disable_regulator;
+	}
+
+	k = 0;
+	for (i = 0; i < ARRAY_SIZE(tegra_xhci_phy_types); i++) {
+		char prop[8];
+
+		BUG_ON(sizeof(prop) < strlen(tegra_xhci_phy_types[i].name) + 3);
+		for (j = 0; j < tegra_xhci_phy_types[i].num; j++) {
+			sprintf(prop, "%s-%d", tegra_xhci_phy_types[i].name, j);
+			phy = devm_phy_optional_get(&pdev->dev, prop);
+			if (IS_ERR(phy)) {
+				ret = PTR_ERR(phy);
+				goto put_mbox;
+			}
+			tegra->phys[k++] = phy;
+		}
+	}
+
+	/* Setup IPFS access and BAR0 space. */
+	tegra_xhci_cfg(tegra);
+
+	ret = tegra_xhci_phy_enable(tegra);
+	if (ret < 0)
+		goto put_mbox;
+
+	ret = request_firmware_nowait(THIS_MODULE, true,
+				      tegra->soc_config->firmware_file,
+				      tegra->dev, GFP_KERNEL, tegra,
+				      tegra_xhci_probe_finish);
+	if (ret < 0)
+		goto disable_phy;
+
+	return 0;
+
+disable_phy:
+	tegra_xhci_phy_disable(tegra);
+put_mbox:
+	mbox_free_channel(tegra->mbox_chan);
+disable_regulator:
+	regulator_bulk_disable(ARRAY_SIZE(tegra->supplies), tegra->supplies);
+disable_clk:
+	tegra_xhci_clk_disable(tegra);
+put_hcd:
+	usb_put_hcd(hcd);
+	return ret;
+}
+
+static int tegra_xhci_remove(struct platform_device *pdev)
+{
+	struct tegra_xhci_hcd *tegra = platform_get_drvdata(pdev);
+	struct usb_hcd *hcd = tegra->hcd;
+	struct xhci_hcd *xhci;
+
+	if (tegra->fw_loaded) {
+		xhci = hcd_to_xhci(hcd);
+		usb_remove_hcd(xhci->shared_hcd);
+		usb_put_hcd(xhci->shared_hcd);
+		usb_remove_hcd(hcd);
+		usb_put_hcd(hcd);
+		kfree(xhci);
+	} else if (hcd) {
+		/* Unbound after probe(), but before firmware loading. */
+		usb_put_hcd(hcd);
+	}
+
+	if (tegra->fw_data)
+		dma_free_coherent(tegra->dev, tegra->fw_size, tegra->fw_data,
+				  tegra->fw_dma_addr);
+
+	cancel_work_sync(&tegra->mbox_req_work);
+	mbox_free_channel(tegra->mbox_chan);
+	tegra_xhci_phy_disable(tegra);
+	regulator_bulk_disable(ARRAY_SIZE(tegra->supplies), tegra->supplies);
+	tegra_xhci_clk_disable(tegra);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int tegra_xhci_suspend(struct device *dev)
+{
+	struct tegra_xhci_hcd *tegra = dev_get_drvdata(dev);
+	struct xhci_hcd *xhci = hcd_to_xhci(tegra->hcd);
+
+	return xhci_suspend(xhci);
+}
+
+static int tegra_xhci_resume(struct device *dev)
+{
+	struct tegra_xhci_hcd *tegra = dev_get_drvdata(dev);
+	struct xhci_hcd *xhci = hcd_to_xhci(tegra->hcd);
+
+	return xhci_resume(xhci, 0);
+}
+#endif
+
+static const struct dev_pm_ops tegra_xhci_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(tegra_xhci_suspend, tegra_xhci_resume)
+};
+
+static struct platform_driver tegra_xhci_driver = {
+	.probe	= tegra_xhci_probe,
+	.remove	= tegra_xhci_remove,
+	.driver	= {
+		.name = "xhci-tegra",
+		.pm = &tegra_xhci_pm_ops,
+		.of_match_table = of_match_ptr(tegra_xhci_of_match),
+	},
+};
+
+static int __init tegra_xhci_init(void)
+{
+	xhci_init_driver(&tegra_xhci_hc_driver, tegra_xhci_setup);
+	return platform_driver_register(&tegra_xhci_driver);
+}
+module_init(tegra_xhci_init);
+
+static void __exit tegra_xhci_exit(void)
+{
+	platform_driver_unregister(&tegra_xhci_driver);
+}
+module_exit(tegra_xhci_exit);
+
+MODULE_AUTHOR("Andrew Bresticker <abrestic@chromium.org>");
+MODULE_DESCRIPTION("NVIDIA Tegra xHCI host-controller driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:xhci-tegra");
-- 
2.1.0.rc2.206.gedb03e5

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

* [PATCH v2 7/9] ARM: tegra: Add Tegra124 XUSB mailbox and xHCI controller
  2014-08-18 17:08 ` Andrew Bresticker
@ 2014-08-18 17:08   ` Andrew Bresticker
  -1 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-18 17:08 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, linux-tegra
  Cc: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Jassi Brar, Linus Walleij, Greg Kroah-Hartman,
	Mathias Nyman, Grant Likely, Alan Stern, Arnd Bergmann,
	Kishon Vijay Abraham I, devicetree, linux-kernel,
	linux-arm-kernel, linux-usb, Andrew Bresticker

Add nodes for the Tegra XUSB mailbox and Tegra xHCI controller and
add the PHY mailbox channel to the XUSB padctl node.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
---
Changes from v1:
 - Updated to use common mailbox bindings.
 - Added remaining clocks/resets.
---
 arch/arm/boot/dts/tegra124.dtsi | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi
index 03916ef..98b8340 100644
--- a/arch/arm/boot/dts/tegra124.dtsi
+++ b/arch/arm/boot/dts/tegra124.dtsi
@@ -3,6 +3,7 @@
 #include <dt-bindings/pinctrl/pinctrl-tegra.h>
 #include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/mailbox/tegra-xusb-mailbox.h>
 
 #include "skeleton.dtsi"
 
@@ -495,11 +496,50 @@
 		status = "disabled";
 	};
 
+	usb@0,70090000 {
+		compatible = "nvidia,tegra124-xhci";
+		reg = <0x0 0x70090000 0x0 0x8000>,
+		      <0x0 0x70098000 0x0 0x1000>,
+		      <0x0 0x70099000 0x0 0x1000>;
+		interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&tegra_car TEGRA124_CLK_XUSB_HOST>,
+			 <&tegra_car TEGRA124_CLK_XUSB_HOST_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_DEV>,
+			 <&tegra_car TEGRA124_CLK_XUSB_DEV_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_FALCON_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_SS>,
+			 <&tegra_car TEGRA124_CLK_XUSB_SS_DIV2>,
+			 <&tegra_car TEGRA124_CLK_XUSB_SS_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_HS_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_FS_SRC>,
+			 <&tegra_car TEGRA124_CLK_PLL_U_480M>,
+			 <&tegra_car TEGRA124_CLK_CLK_M>,
+			 <&tegra_car TEGRA124_CLK_PLL_E>;
+		clock-names = "xusb_host", "xusb_host_src", "xusb_dev",
+			      "xusb_dev_src", "xusb_falcon_src", "xusb_ss",
+			      "xusb_ss_div2", "xusb_ss_src", "xusb_hs_src",
+			      "xusb_fs_src", "pll_u_480m", "clk_m", "pll_e";
+		resets = <&tegra_car 89>, <&tegra_car 95>, <&tegra_car 156>,
+			 <&tegra_car 143>;
+		reset-names = "xusb_host", "xusb_dev", "xusb_ss", "xusb";
+		mboxes = <&mbox TEGRA_XUSB_MBOX_CHAN_HOST>;
+		status = "disabled";
+	};
+
+	mbox: mailbox@0,70098000 {
+		compatible = "nvidia,tegra124-xusb-mbox";
+		reg = <0x0 0x70098000 0x0 0x1000>;
+		interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+
+		#mbox-cells = <1>;
+	};
+
 	padctl: padctl@0,7009f000 {
 		compatible = "nvidia,tegra124-xusb-padctl";
 		reg = <0x0 0x7009f000 0x0 0x1000>;
 		resets = <&tegra_car 142>;
 		reset-names = "padctl";
+		mboxes = <&mbox TEGRA_XUSB_MBOX_CHAN_PHY>;
 
 		#phy-cells = <1>;
 	};
-- 
2.1.0.rc2.206.gedb03e5

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

* [PATCH v2 7/9] ARM: tegra: Add Tegra124 XUSB mailbox and xHCI controller
@ 2014-08-18 17:08   ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-18 17:08 UTC (permalink / raw)
  To: linux-arm-kernel

Add nodes for the Tegra XUSB mailbox and Tegra xHCI controller and
add the PHY mailbox channel to the XUSB padctl node.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
---
Changes from v1:
 - Updated to use common mailbox bindings.
 - Added remaining clocks/resets.
---
 arch/arm/boot/dts/tegra124.dtsi | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi
index 03916ef..98b8340 100644
--- a/arch/arm/boot/dts/tegra124.dtsi
+++ b/arch/arm/boot/dts/tegra124.dtsi
@@ -3,6 +3,7 @@
 #include <dt-bindings/pinctrl/pinctrl-tegra.h>
 #include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/mailbox/tegra-xusb-mailbox.h>
 
 #include "skeleton.dtsi"
 
@@ -495,11 +496,50 @@
 		status = "disabled";
 	};
 
+	usb at 0,70090000 {
+		compatible = "nvidia,tegra124-xhci";
+		reg = <0x0 0x70090000 0x0 0x8000>,
+		      <0x0 0x70098000 0x0 0x1000>,
+		      <0x0 0x70099000 0x0 0x1000>;
+		interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&tegra_car TEGRA124_CLK_XUSB_HOST>,
+			 <&tegra_car TEGRA124_CLK_XUSB_HOST_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_DEV>,
+			 <&tegra_car TEGRA124_CLK_XUSB_DEV_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_FALCON_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_SS>,
+			 <&tegra_car TEGRA124_CLK_XUSB_SS_DIV2>,
+			 <&tegra_car TEGRA124_CLK_XUSB_SS_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_HS_SRC>,
+			 <&tegra_car TEGRA124_CLK_XUSB_FS_SRC>,
+			 <&tegra_car TEGRA124_CLK_PLL_U_480M>,
+			 <&tegra_car TEGRA124_CLK_CLK_M>,
+			 <&tegra_car TEGRA124_CLK_PLL_E>;
+		clock-names = "xusb_host", "xusb_host_src", "xusb_dev",
+			      "xusb_dev_src", "xusb_falcon_src", "xusb_ss",
+			      "xusb_ss_div2", "xusb_ss_src", "xusb_hs_src",
+			      "xusb_fs_src", "pll_u_480m", "clk_m", "pll_e";
+		resets = <&tegra_car 89>, <&tegra_car 95>, <&tegra_car 156>,
+			 <&tegra_car 143>;
+		reset-names = "xusb_host", "xusb_dev", "xusb_ss", "xusb";
+		mboxes = <&mbox TEGRA_XUSB_MBOX_CHAN_HOST>;
+		status = "disabled";
+	};
+
+	mbox: mailbox at 0,70098000 {
+		compatible = "nvidia,tegra124-xusb-mbox";
+		reg = <0x0 0x70098000 0x0 0x1000>;
+		interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+
+		#mbox-cells = <1>;
+	};
+
 	padctl: padctl at 0,7009f000 {
 		compatible = "nvidia,tegra124-xusb-padctl";
 		reg = <0x0 0x7009f000 0x0 0x1000>;
 		resets = <&tegra_car 142>;
 		reset-names = "padctl";
+		mboxes = <&mbox TEGRA_XUSB_MBOX_CHAN_PHY>;
 
 		#phy-cells = <1>;
 	};
-- 
2.1.0.rc2.206.gedb03e5

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

* [PATCH v2 8/9] ARM: tegra: jetson-tk1: Add xHCI support
  2014-08-18 17:08 ` Andrew Bresticker
  (?)
@ 2014-08-18 17:08   ` Andrew Bresticker
  -1 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-18 17:08 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, linux-tegra
  Cc: Mark Rutland, devicetree, linux-usb, Russell King, Mathias Nyman,
	Pawel Moll, Ian Campbell, Andrew Bresticker, Greg Kroah-Hartman,
	Linus Walleij, Jassi Brar, linux-kernel, Kishon Vijay Abraham I,
	Rob Herring, Alan Stern, linux-arm-kernel, Kumar Gala,
	Grant Likely, Arnd Bergmann

Assign USB ports previously owned by the EHCI controllers to the xHCI
controller.  There is a mini-PCIe USB port (UTMI port 1) and a USB A
connector (UTMI port 2, USB3 port 0).  PCIe lane 0 is used for USB3
port 0.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
---
Changes from v1:
 - Updated USB power supplies.
---
 arch/arm/boot/dts/tegra124-jetson-tk1.dts | 48 +++++++++++++++++--------------
 1 file changed, 27 insertions(+), 21 deletions(-)

diff --git a/arch/arm/boot/dts/tegra124-jetson-tk1.dts b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
index 624b0fb..dbaf554 100644
--- a/arch/arm/boot/dts/tegra124-jetson-tk1.dts
+++ b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
@@ -1515,7 +1515,7 @@
 					regulator-always-on;
 				};
 
-				ldo0 {
+				avdd_1v05_run: ldo0 {
 					regulator-name = "+1.05V_RUN_AVDD";
 					regulator-min-microvolt = <1050000>;
 					regulator-max-microvolt = <1050000>;
@@ -1619,15 +1619,40 @@
 		nvidia,sys-clock-req-active-high;
 	};
 
+	usb@0,70090000 {
+		status = "okay";
+		phys = <&padctl TEGRA_XUSB_PADCTL_UTMI_P1>, /* mini-PCIe USB */
+		       <&padctl TEGRA_XUSB_PADCTL_UTMI_P2>, /* USB A */
+		       <&padctl TEGRA_XUSB_PADCTL_USB3_P0>; /* USB A */
+		phy-names = "utmi-1", "utmi-2", "usb3-0";
+		avddio-pex-supply = <&vdd_1v05_run>;
+		dvddio-pex-supply = <&vdd_1v05_run>;
+		avdd-usb-supply = <&vdd_3v3_lp0>;
+		avdd-pll-utmip-supply = <&vddio_1v8>;
+		avdd-pll-erefe-supply = <&avdd_1v05_run>;
+		avdd-pex-pll-supply = <&vdd_1v05_run>;
+		hvdd-pex-supply = <&vdd_3v3_lp0>;
+		hvdd-pex-plle-supply = <&vdd_3v3_lp0>;
+	};
+
 	padctl@0,7009f000 {
 		pinctrl-0 = <&padctl_default>;
 		pinctrl-names = "default";
 
+		vbus-otg-2-supply = <&vdd_usb3_vbus>;
+		nvidia,usb3-port-0-lane = <TEGRA_XUSB_PADCTL_PIN_PCIE_0>;
+
 		padctl_default: pinmux {
+			otg {
+				nvidia,lanes = "otg-1", "otg-2";
+				nvidia,function = "xusb";
+			};
+
 			usb3 {
-				nvidia,lanes = "pcie-0", "pcie-1";
+				nvidia,lanes = "pcie-0";
 				nvidia,function = "usb3";
 				nvidia,iddq = <0>;
+				nvidia,usb2-port-num = <2>;
 			};
 
 			pcie {
@@ -1668,25 +1693,6 @@
 		};
 	};
 
-	/* mini-PCIe USB */
-	usb@0,7d004000 {
-		status = "okay";
-	};
-
-	usb-phy@0,7d004000 {
-		status = "okay";
-	};
-
-	/* USB A connector */
-	usb@0,7d008000 {
-		status = "okay";
-	};
-
-	usb-phy@0,7d008000 {
-		status = "okay";
-		vbus-supply = <&vdd_usb3_vbus>;
-	};
-
 	clocks {
 		compatible = "simple-bus";
 		#address-cells = <1>;
-- 
2.1.0.rc2.206.gedb03e5

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

* [PATCH v2 8/9] ARM: tegra: jetson-tk1: Add xHCI support
@ 2014-08-18 17:08   ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-18 17:08 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, linux-tegra
  Cc: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Jassi Brar, Linus Walleij, Greg Kroah-Hartman,
	Mathias Nyman, Grant Likely, Alan Stern, Arnd Bergmann,
	Kishon Vijay Abraham I, devicetree, linux-kernel,
	linux-arm-kernel, linux-usb, Andrew Bresticker

Assign USB ports previously owned by the EHCI controllers to the xHCI
controller.  There is a mini-PCIe USB port (UTMI port 1) and a USB A
connector (UTMI port 2, USB3 port 0).  PCIe lane 0 is used for USB3
port 0.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
---
Changes from v1:
 - Updated USB power supplies.
---
 arch/arm/boot/dts/tegra124-jetson-tk1.dts | 48 +++++++++++++++++--------------
 1 file changed, 27 insertions(+), 21 deletions(-)

diff --git a/arch/arm/boot/dts/tegra124-jetson-tk1.dts b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
index 624b0fb..dbaf554 100644
--- a/arch/arm/boot/dts/tegra124-jetson-tk1.dts
+++ b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
@@ -1515,7 +1515,7 @@
 					regulator-always-on;
 				};
 
-				ldo0 {
+				avdd_1v05_run: ldo0 {
 					regulator-name = "+1.05V_RUN_AVDD";
 					regulator-min-microvolt = <1050000>;
 					regulator-max-microvolt = <1050000>;
@@ -1619,15 +1619,40 @@
 		nvidia,sys-clock-req-active-high;
 	};
 
+	usb@0,70090000 {
+		status = "okay";
+		phys = <&padctl TEGRA_XUSB_PADCTL_UTMI_P1>, /* mini-PCIe USB */
+		       <&padctl TEGRA_XUSB_PADCTL_UTMI_P2>, /* USB A */
+		       <&padctl TEGRA_XUSB_PADCTL_USB3_P0>; /* USB A */
+		phy-names = "utmi-1", "utmi-2", "usb3-0";
+		avddio-pex-supply = <&vdd_1v05_run>;
+		dvddio-pex-supply = <&vdd_1v05_run>;
+		avdd-usb-supply = <&vdd_3v3_lp0>;
+		avdd-pll-utmip-supply = <&vddio_1v8>;
+		avdd-pll-erefe-supply = <&avdd_1v05_run>;
+		avdd-pex-pll-supply = <&vdd_1v05_run>;
+		hvdd-pex-supply = <&vdd_3v3_lp0>;
+		hvdd-pex-plle-supply = <&vdd_3v3_lp0>;
+	};
+
 	padctl@0,7009f000 {
 		pinctrl-0 = <&padctl_default>;
 		pinctrl-names = "default";
 
+		vbus-otg-2-supply = <&vdd_usb3_vbus>;
+		nvidia,usb3-port-0-lane = <TEGRA_XUSB_PADCTL_PIN_PCIE_0>;
+
 		padctl_default: pinmux {
+			otg {
+				nvidia,lanes = "otg-1", "otg-2";
+				nvidia,function = "xusb";
+			};
+
 			usb3 {
-				nvidia,lanes = "pcie-0", "pcie-1";
+				nvidia,lanes = "pcie-0";
 				nvidia,function = "usb3";
 				nvidia,iddq = <0>;
+				nvidia,usb2-port-num = <2>;
 			};
 
 			pcie {
@@ -1668,25 +1693,6 @@
 		};
 	};
 
-	/* mini-PCIe USB */
-	usb@0,7d004000 {
-		status = "okay";
-	};
-
-	usb-phy@0,7d004000 {
-		status = "okay";
-	};
-
-	/* USB A connector */
-	usb@0,7d008000 {
-		status = "okay";
-	};
-
-	usb-phy@0,7d008000 {
-		status = "okay";
-		vbus-supply = <&vdd_usb3_vbus>;
-	};
-
 	clocks {
 		compatible = "simple-bus";
 		#address-cells = <1>;
-- 
2.1.0.rc2.206.gedb03e5


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

* [PATCH v2 8/9] ARM: tegra: jetson-tk1: Add xHCI support
@ 2014-08-18 17:08   ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-18 17:08 UTC (permalink / raw)
  To: linux-arm-kernel

Assign USB ports previously owned by the EHCI controllers to the xHCI
controller.  There is a mini-PCIe USB port (UTMI port 1) and a USB A
connector (UTMI port 2, USB3 port 0).  PCIe lane 0 is used for USB3
port 0.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
---
Changes from v1:
 - Updated USB power supplies.
---
 arch/arm/boot/dts/tegra124-jetson-tk1.dts | 48 +++++++++++++++++--------------
 1 file changed, 27 insertions(+), 21 deletions(-)

diff --git a/arch/arm/boot/dts/tegra124-jetson-tk1.dts b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
index 624b0fb..dbaf554 100644
--- a/arch/arm/boot/dts/tegra124-jetson-tk1.dts
+++ b/arch/arm/boot/dts/tegra124-jetson-tk1.dts
@@ -1515,7 +1515,7 @@
 					regulator-always-on;
 				};
 
-				ldo0 {
+				avdd_1v05_run: ldo0 {
 					regulator-name = "+1.05V_RUN_AVDD";
 					regulator-min-microvolt = <1050000>;
 					regulator-max-microvolt = <1050000>;
@@ -1619,15 +1619,40 @@
 		nvidia,sys-clock-req-active-high;
 	};
 
+	usb at 0,70090000 {
+		status = "okay";
+		phys = <&padctl TEGRA_XUSB_PADCTL_UTMI_P1>, /* mini-PCIe USB */
+		       <&padctl TEGRA_XUSB_PADCTL_UTMI_P2>, /* USB A */
+		       <&padctl TEGRA_XUSB_PADCTL_USB3_P0>; /* USB A */
+		phy-names = "utmi-1", "utmi-2", "usb3-0";
+		avddio-pex-supply = <&vdd_1v05_run>;
+		dvddio-pex-supply = <&vdd_1v05_run>;
+		avdd-usb-supply = <&vdd_3v3_lp0>;
+		avdd-pll-utmip-supply = <&vddio_1v8>;
+		avdd-pll-erefe-supply = <&avdd_1v05_run>;
+		avdd-pex-pll-supply = <&vdd_1v05_run>;
+		hvdd-pex-supply = <&vdd_3v3_lp0>;
+		hvdd-pex-plle-supply = <&vdd_3v3_lp0>;
+	};
+
 	padctl at 0,7009f000 {
 		pinctrl-0 = <&padctl_default>;
 		pinctrl-names = "default";
 
+		vbus-otg-2-supply = <&vdd_usb3_vbus>;
+		nvidia,usb3-port-0-lane = <TEGRA_XUSB_PADCTL_PIN_PCIE_0>;
+
 		padctl_default: pinmux {
+			otg {
+				nvidia,lanes = "otg-1", "otg-2";
+				nvidia,function = "xusb";
+			};
+
 			usb3 {
-				nvidia,lanes = "pcie-0", "pcie-1";
+				nvidia,lanes = "pcie-0";
 				nvidia,function = "usb3";
 				nvidia,iddq = <0>;
+				nvidia,usb2-port-num = <2>;
 			};
 
 			pcie {
@@ -1668,25 +1693,6 @@
 		};
 	};
 
-	/* mini-PCIe USB */
-	usb at 0,7d004000 {
-		status = "okay";
-	};
-
-	usb-phy at 0,7d004000 {
-		status = "okay";
-	};
-
-	/* USB A connector */
-	usb at 0,7d008000 {
-		status = "okay";
-	};
-
-	usb-phy at 0,7d008000 {
-		status = "okay";
-		vbus-supply = <&vdd_usb3_vbus>;
-	};
-
 	clocks {
 		compatible = "simple-bus";
 		#address-cells = <1>;
-- 
2.1.0.rc2.206.gedb03e5

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

* [PATCH v2 9/9] ARM: tegra: venice2: Add xHCI support
  2014-08-18 17:08 ` Andrew Bresticker
  (?)
@ 2014-08-18 17:08     ` Andrew Bresticker
  -1 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-18 17:08 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, linux-tegra-u79uwXL29TY76Z2rM5mHXA
  Cc: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Jassi Brar, Linus Walleij, Greg Kroah-Hartman,
	Mathias Nyman, Grant Likely, Alan Stern, Arnd Bergmann,
	Kishon Vijay Abraham I, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA, Andrew Bresticker

Assign ports previously owned by the EHCI controllers to the xHCI
controller.  There are two external USB ports (UTMI ports 0/2 and
USB3 ports 0/1) and an internal USB port (UTMI port 1).  PCIe lanes
0 and 1 are used by the USB3 ports.

Signed-off-by: Andrew Bresticker <abrestic-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
---
Changes from v1:
 - Updated USB power supplies.
---
 arch/arm/boot/dts/tegra124-venice2.dts | 79 ++++++++++++++++++++++------------
 1 file changed, 51 insertions(+), 28 deletions(-)

diff --git a/arch/arm/boot/dts/tegra124-venice2.dts b/arch/arm/boot/dts/tegra124-venice2.dts
index 70ad91d..3f706ff 100644
--- a/arch/arm/boot/dts/tegra124-venice2.dts
+++ b/arch/arm/boot/dts/tegra124-venice2.dts
@@ -736,7 +736,7 @@
 					regulator-always-on;
 				};
 
-				ldo0 {
+				avdd_1v05_run: ldo0 {
 					regulator-name = "+1.05V_RUN_AVDD";
 					regulator-min-microvolt = <1050000>;
 					regulator-max-microvolt = <1050000>;
@@ -878,6 +878,56 @@
 		status = "okay";
 	};
 
+	usb@0,70090000 {
+		status = "okay";
+		phys = <&padctl TEGRA_XUSB_PADCTL_UTMI_P0>, /* 1st USB A */
+		       <&padctl TEGRA_XUSB_PADCTL_UTMI_P1>, /* Internal USB */
+		       <&padctl TEGRA_XUSB_PADCTL_UTMI_P2>, /* 2nd USB A */
+		       <&padctl TEGRA_XUSB_PADCTL_USB3_P0>, /* 1st USB A */
+		       <&padctl TEGRA_XUSB_PADCTL_USB3_P1>; /* 2nd USB A */
+		phy-names = "utmi-0", "utmi-1", "utmi-2", "usb3-0", "usb3-1";
+		avddio-pex-supply = <&vdd_1v05_run>;
+		dvddio-pex-supply = <&vdd_1v05_run>;
+		avdd-usb-supply = <&vdd_3v3_lp0>;
+		avdd-pll-utmip-supply = <&vddio_1v8>;
+		avdd-pll-erefe-supply = <&avdd_1v05_run>;
+		avdd-pex-pll-supply = <&vdd_1v05_run>;
+		hvdd-pex-supply = <&vdd_3v3_lp0>;
+		hvdd-pex-plle-supply = <&vdd_3v3_lp0>;
+	};
+
+	padctl@0,7009f000 {
+		pinctrl-0 = <&padctl_default>;
+		pinctrl-names = "default";
+
+		vbus-otg-0-supply = <&vdd_usb1_vbus>;
+		vbus-otg-1-supply = <&vdd_run_cam>;
+		vbus-otg-2-supply = <&vdd_usb3_vbus>;
+		nvidia,usb3-port-0-lane = <TEGRA_XUSB_PADCTL_PIN_PCIE_0>;
+		nvidia,usb3-port-1-lane = <TEGRA_XUSB_PADCTL_PIN_PCIE_1>;
+
+		padctl_default: pinmux {
+			otg {
+				nvidia,lanes = "otg-0", "otg-1", "otg-2";
+				nvidia,function = "xusb";
+			};
+
+			usb3p0 {
+				nvidia,lanes = "pcie-0";
+				nvidia,function = "usb3";
+				nvidia,iddq = <0>;
+				nvidia,usb2-port-num = <0>;
+			};
+
+			usb3p1 {
+				nvidia,lanes = "pcie-1";
+				nvidia,function = "usb3";
+				nvidia,iddq = <0>;
+				nvidia,usb2-port-num = <2>;
+			};
+		};
+	};
+
 	sdhci@0,700b0400 {
 		cd-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>;
 		power-gpios = <&gpio TEGRA_GPIO(R, 0) GPIO_ACTIVE_HIGH>;
@@ -898,33 +948,6 @@
 		};
 	};
 
-	usb@0,7d000000 {
-		status = "okay";
-	};
-
-	usb-phy@0,7d000000 {
-		status = "okay";
-		vbus-supply = <&vdd_usb1_vbus>;
-	};
-
-	usb@0,7d004000 {
-		status = "okay";
-	};
-
-	usb-phy@0,7d004000 {
-		status = "okay";
-		vbus-supply = <&vdd_run_cam>;
-	};
-
-	usb@0,7d008000 {
-		status = "okay";
-	};
-
-	usb-phy@0,7d008000 {
-		status = "okay";
-		vbus-supply = <&vdd_usb3_vbus>;
-	};
-
 	backlight: backlight {
 		compatible = "pwm-backlight";
 
-- 
2.1.0.rc2.206.gedb03e5

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v2 9/9] ARM: tegra: venice2: Add xHCI support
@ 2014-08-18 17:08     ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-18 17:08 UTC (permalink / raw)
  To: Stephen Warren, Thierry Reding, linux-tegra
  Cc: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Jassi Brar, Linus Walleij, Greg Kroah-Hartman,
	Mathias Nyman, Grant Likely, Alan Stern, Arnd Bergmann,
	Kishon Vijay Abraham I, devicetree, linux-kernel,
	linux-arm-kernel, linux-usb, Andrew Bresticker

Assign ports previously owned by the EHCI controllers to the xHCI
controller.  There are two external USB ports (UTMI ports 0/2 and
USB3 ports 0/1) and an internal USB port (UTMI port 1).  PCIe lanes
0 and 1 are used by the USB3 ports.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
---
Changes from v1:
 - Updated USB power supplies.
---
 arch/arm/boot/dts/tegra124-venice2.dts | 79 ++++++++++++++++++++++------------
 1 file changed, 51 insertions(+), 28 deletions(-)

diff --git a/arch/arm/boot/dts/tegra124-venice2.dts b/arch/arm/boot/dts/tegra124-venice2.dts
index 70ad91d..3f706ff 100644
--- a/arch/arm/boot/dts/tegra124-venice2.dts
+++ b/arch/arm/boot/dts/tegra124-venice2.dts
@@ -736,7 +736,7 @@
 					regulator-always-on;
 				};
 
-				ldo0 {
+				avdd_1v05_run: ldo0 {
 					regulator-name = "+1.05V_RUN_AVDD";
 					regulator-min-microvolt = <1050000>;
 					regulator-max-microvolt = <1050000>;
@@ -878,6 +878,56 @@
 		status = "okay";
 	};
 
+	usb@0,70090000 {
+		status = "okay";
+		phys = <&padctl TEGRA_XUSB_PADCTL_UTMI_P0>, /* 1st USB A */
+		       <&padctl TEGRA_XUSB_PADCTL_UTMI_P1>, /* Internal USB */
+		       <&padctl TEGRA_XUSB_PADCTL_UTMI_P2>, /* 2nd USB A */
+		       <&padctl TEGRA_XUSB_PADCTL_USB3_P0>, /* 1st USB A */
+		       <&padctl TEGRA_XUSB_PADCTL_USB3_P1>; /* 2nd USB A */
+		phy-names = "utmi-0", "utmi-1", "utmi-2", "usb3-0", "usb3-1";
+		avddio-pex-supply = <&vdd_1v05_run>;
+		dvddio-pex-supply = <&vdd_1v05_run>;
+		avdd-usb-supply = <&vdd_3v3_lp0>;
+		avdd-pll-utmip-supply = <&vddio_1v8>;
+		avdd-pll-erefe-supply = <&avdd_1v05_run>;
+		avdd-pex-pll-supply = <&vdd_1v05_run>;
+		hvdd-pex-supply = <&vdd_3v3_lp0>;
+		hvdd-pex-plle-supply = <&vdd_3v3_lp0>;
+	};
+
+	padctl@0,7009f000 {
+		pinctrl-0 = <&padctl_default>;
+		pinctrl-names = "default";
+
+		vbus-otg-0-supply = <&vdd_usb1_vbus>;
+		vbus-otg-1-supply = <&vdd_run_cam>;
+		vbus-otg-2-supply = <&vdd_usb3_vbus>;
+		nvidia,usb3-port-0-lane = <TEGRA_XUSB_PADCTL_PIN_PCIE_0>;
+		nvidia,usb3-port-1-lane = <TEGRA_XUSB_PADCTL_PIN_PCIE_1>;
+
+		padctl_default: pinmux {
+			otg {
+				nvidia,lanes = "otg-0", "otg-1", "otg-2";
+				nvidia,function = "xusb";
+			};
+
+			usb3p0 {
+				nvidia,lanes = "pcie-0";
+				nvidia,function = "usb3";
+				nvidia,iddq = <0>;
+				nvidia,usb2-port-num = <0>;
+			};
+
+			usb3p1 {
+				nvidia,lanes = "pcie-1";
+				nvidia,function = "usb3";
+				nvidia,iddq = <0>;
+				nvidia,usb2-port-num = <2>;
+			};
+		};
+	};
+
 	sdhci@0,700b0400 {
 		cd-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>;
 		power-gpios = <&gpio TEGRA_GPIO(R, 0) GPIO_ACTIVE_HIGH>;
@@ -898,33 +948,6 @@
 		};
 	};
 
-	usb@0,7d000000 {
-		status = "okay";
-	};
-
-	usb-phy@0,7d000000 {
-		status = "okay";
-		vbus-supply = <&vdd_usb1_vbus>;
-	};
-
-	usb@0,7d004000 {
-		status = "okay";
-	};
-
-	usb-phy@0,7d004000 {
-		status = "okay";
-		vbus-supply = <&vdd_run_cam>;
-	};
-
-	usb@0,7d008000 {
-		status = "okay";
-	};
-
-	usb-phy@0,7d008000 {
-		status = "okay";
-		vbus-supply = <&vdd_usb3_vbus>;
-	};
-
 	backlight: backlight {
 		compatible = "pwm-backlight";
 
-- 
2.1.0.rc2.206.gedb03e5


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

* [PATCH v2 9/9] ARM: tegra: venice2: Add xHCI support
@ 2014-08-18 17:08     ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-18 17:08 UTC (permalink / raw)
  To: linux-arm-kernel

Assign ports previously owned by the EHCI controllers to the xHCI
controller.  There are two external USB ports (UTMI ports 0/2 and
USB3 ports 0/1) and an internal USB port (UTMI port 1).  PCIe lanes
0 and 1 are used by the USB3 ports.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
---
Changes from v1:
 - Updated USB power supplies.
---
 arch/arm/boot/dts/tegra124-venice2.dts | 79 ++++++++++++++++++++++------------
 1 file changed, 51 insertions(+), 28 deletions(-)

diff --git a/arch/arm/boot/dts/tegra124-venice2.dts b/arch/arm/boot/dts/tegra124-venice2.dts
index 70ad91d..3f706ff 100644
--- a/arch/arm/boot/dts/tegra124-venice2.dts
+++ b/arch/arm/boot/dts/tegra124-venice2.dts
@@ -736,7 +736,7 @@
 					regulator-always-on;
 				};
 
-				ldo0 {
+				avdd_1v05_run: ldo0 {
 					regulator-name = "+1.05V_RUN_AVDD";
 					regulator-min-microvolt = <1050000>;
 					regulator-max-microvolt = <1050000>;
@@ -878,6 +878,56 @@
 		status = "okay";
 	};
 
+	usb at 0,70090000 {
+		status = "okay";
+		phys = <&padctl TEGRA_XUSB_PADCTL_UTMI_P0>, /* 1st USB A */
+		       <&padctl TEGRA_XUSB_PADCTL_UTMI_P1>, /* Internal USB */
+		       <&padctl TEGRA_XUSB_PADCTL_UTMI_P2>, /* 2nd USB A */
+		       <&padctl TEGRA_XUSB_PADCTL_USB3_P0>, /* 1st USB A */
+		       <&padctl TEGRA_XUSB_PADCTL_USB3_P1>; /* 2nd USB A */
+		phy-names = "utmi-0", "utmi-1", "utmi-2", "usb3-0", "usb3-1";
+		avddio-pex-supply = <&vdd_1v05_run>;
+		dvddio-pex-supply = <&vdd_1v05_run>;
+		avdd-usb-supply = <&vdd_3v3_lp0>;
+		avdd-pll-utmip-supply = <&vddio_1v8>;
+		avdd-pll-erefe-supply = <&avdd_1v05_run>;
+		avdd-pex-pll-supply = <&vdd_1v05_run>;
+		hvdd-pex-supply = <&vdd_3v3_lp0>;
+		hvdd-pex-plle-supply = <&vdd_3v3_lp0>;
+	};
+
+	padctl at 0,7009f000 {
+		pinctrl-0 = <&padctl_default>;
+		pinctrl-names = "default";
+
+		vbus-otg-0-supply = <&vdd_usb1_vbus>;
+		vbus-otg-1-supply = <&vdd_run_cam>;
+		vbus-otg-2-supply = <&vdd_usb3_vbus>;
+		nvidia,usb3-port-0-lane = <TEGRA_XUSB_PADCTL_PIN_PCIE_0>;
+		nvidia,usb3-port-1-lane = <TEGRA_XUSB_PADCTL_PIN_PCIE_1>;
+
+		padctl_default: pinmux {
+			otg {
+				nvidia,lanes = "otg-0", "otg-1", "otg-2";
+				nvidia,function = "xusb";
+			};
+
+			usb3p0 {
+				nvidia,lanes = "pcie-0";
+				nvidia,function = "usb3";
+				nvidia,iddq = <0>;
+				nvidia,usb2-port-num = <0>;
+			};
+
+			usb3p1 {
+				nvidia,lanes = "pcie-1";
+				nvidia,function = "usb3";
+				nvidia,iddq = <0>;
+				nvidia,usb2-port-num = <2>;
+			};
+		};
+	};
+
 	sdhci at 0,700b0400 {
 		cd-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>;
 		power-gpios = <&gpio TEGRA_GPIO(R, 0) GPIO_ACTIVE_HIGH>;
@@ -898,33 +948,6 @@
 		};
 	};
 
-	usb at 0,7d000000 {
-		status = "okay";
-	};
-
-	usb-phy at 0,7d000000 {
-		status = "okay";
-		vbus-supply = <&vdd_usb1_vbus>;
-	};
-
-	usb at 0,7d004000 {
-		status = "okay";
-	};
-
-	usb-phy at 0,7d004000 {
-		status = "okay";
-		vbus-supply = <&vdd_run_cam>;
-	};
-
-	usb at 0,7d008000 {
-		status = "okay";
-	};
-
-	usb-phy at 0,7d008000 {
-		status = "okay";
-		vbus-supply = <&vdd_usb3_vbus>;
-	};
-
 	backlight: backlight {
 		compatible = "pwm-backlight";
 
-- 
2.1.0.rc2.206.gedb03e5

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

* Re: [PATCH v2 0/9] Tegra xHCI support
  2014-08-18 17:08 ` Andrew Bresticker
  (?)
@ 2014-08-18 17:30     ` Stephen Warren
  -1 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-18 17:30 UTC (permalink / raw)
  To: Andrew Bresticker, Thierry Reding, linux-tegra-u79uwXL29TY76Z2rM5mHXA
  Cc: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Jassi Brar, Linus Walleij, Greg Kroah-Hartman,
	Mathias Nyman, Grant Likely, Alan Stern, Arnd Bergmann,
	Kishon Vijay Abraham I, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA

On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> This series adds support for xHCI on NVIDIA Tegra SoCs.  This includes:
>   - adding a driver for the mailbox used to communicate with the xHCI
>     controller's firmware,
>   - extending the XUSB pad controller driver to support the USB PHY
>     types (UTMI, HSIC, and USB3), and
>   - adding a xHCI host-controller driver.

Can you please remind us what dependencies exist between the patches? In 
other words, is it possible to apply parts of the series to their usual 
subsystem branches, or does the whole thing need to go into a single 
topic branch in order to avoid compile-time problems, or run-time 
problems in features unrelated to the new functionality? Thanks.
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 0/9] Tegra xHCI support
@ 2014-08-18 17:30     ` Stephen Warren
  0 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-18 17:30 UTC (permalink / raw)
  To: Andrew Bresticker, Thierry Reding, linux-tegra
  Cc: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Jassi Brar, Linus Walleij, Greg Kroah-Hartman,
	Mathias Nyman, Grant Likely, Alan Stern, Arnd Bergmann,
	Kishon Vijay Abraham I, devicetree, linux-kernel,
	linux-arm-kernel, linux-usb

On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> This series adds support for xHCI on NVIDIA Tegra SoCs.  This includes:
>   - adding a driver for the mailbox used to communicate with the xHCI
>     controller's firmware,
>   - extending the XUSB pad controller driver to support the USB PHY
>     types (UTMI, HSIC, and USB3), and
>   - adding a xHCI host-controller driver.

Can you please remind us what dependencies exist between the patches? In 
other words, is it possible to apply parts of the series to their usual 
subsystem branches, or does the whole thing need to go into a single 
topic branch in order to avoid compile-time problems, or run-time 
problems in features unrelated to the new functionality? Thanks.

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

* [PATCH v2 0/9] Tegra xHCI support
@ 2014-08-18 17:30     ` Stephen Warren
  0 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-18 17:30 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> This series adds support for xHCI on NVIDIA Tegra SoCs.  This includes:
>   - adding a driver for the mailbox used to communicate with the xHCI
>     controller's firmware,
>   - extending the XUSB pad controller driver to support the USB PHY
>     types (UTMI, HSIC, and USB3), and
>   - adding a xHCI host-controller driver.

Can you please remind us what dependencies exist between the patches? In 
other words, is it possible to apply parts of the series to their usual 
subsystem branches, or does the whole thing need to go into a single 
topic branch in order to avoid compile-time problems, or run-time 
problems in features unrelated to the new functionality? Thanks.

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

* Re: [PATCH v2 0/9] Tegra xHCI support
  2014-08-18 17:30     ` Stephen Warren
  (?)
@ 2014-08-18 19:35         ` Andrew Bresticker
  -1 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-18 19:35 UTC (permalink / raw)
  To: Stephen Warren
  Cc: Thierry Reding, linux-tegra-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Jassi Brar, Linus Walleij, Greg Kroah-Hartman, Mathias Nyman,
	Grant Likely, Alan Stern, Arnd Bergmann, Kishon Vijay Abraham I,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TbrhsbdSgBK9A

On Mon, Aug 18, 2014 at 10:30 AM, Stephen Warren <swarren-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org> wrote:
> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>
>> This series adds support for xHCI on NVIDIA Tegra SoCs.  This includes:
>>   - adding a driver for the mailbox used to communicate with the xHCI
>>     controller's firmware,
>>   - extending the XUSB pad controller driver to support the USB PHY
>>     types (UTMI, HSIC, and USB3), and
>>   - adding a xHCI host-controller driver.
>
>
> Can you please remind us what dependencies exist between the patches? In
> other words, is it possible to apply parts of the series to their usual
> subsystem branches, or does the whole thing need to go into a single topic
> branch in order to avoid compile-time problems, or run-time problems in
> features unrelated to the new functionality? Thanks.

The whole thing will probably need to go into one branch.  Patch 4/9
("pinctrl: tegra-xusb: Add USB PHY support") has compile-time
dependencies on patch 2/9 ("mailbox: Add NVIDIA Tegra XUSB mailbox
driver") and patch 6/9 ("usb: xhci: Add NVIDIA Tegra xHCI
host-controller driver") has compile-time dependencies on both patches
2/9 and 4/9.
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 0/9] Tegra xHCI support
@ 2014-08-18 19:35         ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-18 19:35 UTC (permalink / raw)
  To: Stephen Warren
  Cc: Thierry Reding, linux-tegra, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King, Jassi Brar,
	Linus Walleij, Greg Kroah-Hartman, Mathias Nyman, Grant Likely,
	Alan Stern, Arnd Bergmann, Kishon Vijay Abraham I, devicetree,
	linux-kernel, linux-arm-kernel, linux-usb

On Mon, Aug 18, 2014 at 10:30 AM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>
>> This series adds support for xHCI on NVIDIA Tegra SoCs.  This includes:
>>   - adding a driver for the mailbox used to communicate with the xHCI
>>     controller's firmware,
>>   - extending the XUSB pad controller driver to support the USB PHY
>>     types (UTMI, HSIC, and USB3), and
>>   - adding a xHCI host-controller driver.
>
>
> Can you please remind us what dependencies exist between the patches? In
> other words, is it possible to apply parts of the series to their usual
> subsystem branches, or does the whole thing need to go into a single topic
> branch in order to avoid compile-time problems, or run-time problems in
> features unrelated to the new functionality? Thanks.

The whole thing will probably need to go into one branch.  Patch 4/9
("pinctrl: tegra-xusb: Add USB PHY support") has compile-time
dependencies on patch 2/9 ("mailbox: Add NVIDIA Tegra XUSB mailbox
driver") and patch 6/9 ("usb: xhci: Add NVIDIA Tegra xHCI
host-controller driver") has compile-time dependencies on both patches
2/9 and 4/9.

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

* [PATCH v2 0/9] Tegra xHCI support
@ 2014-08-18 19:35         ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-18 19:35 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Aug 18, 2014 at 10:30 AM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>
>> This series adds support for xHCI on NVIDIA Tegra SoCs.  This includes:
>>   - adding a driver for the mailbox used to communicate with the xHCI
>>     controller's firmware,
>>   - extending the XUSB pad controller driver to support the USB PHY
>>     types (UTMI, HSIC, and USB3), and
>>   - adding a xHCI host-controller driver.
>
>
> Can you please remind us what dependencies exist between the patches? In
> other words, is it possible to apply parts of the series to their usual
> subsystem branches, or does the whole thing need to go into a single topic
> branch in order to avoid compile-time problems, or run-time problems in
> features unrelated to the new functionality? Thanks.

The whole thing will probably need to go into one branch.  Patch 4/9
("pinctrl: tegra-xusb: Add USB PHY support") has compile-time
dependencies on patch 2/9 ("mailbox: Add NVIDIA Tegra XUSB mailbox
driver") and patch 6/9 ("usb: xhci: Add NVIDIA Tegra xHCI
host-controller driver") has compile-time dependencies on both patches
2/9 and 4/9.

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

* Re: [PATCH v2 0/9] Tegra xHCI support
  2014-08-18 17:08 ` Andrew Bresticker
@ 2014-08-21 13:34   ` Tomeu Vizoso
  -1 siblings, 0 replies; 141+ messages in thread
From: Tomeu Vizoso @ 2014-08-21 13:34 UTC (permalink / raw)
  To: Andrew Bresticker
  Cc: Stephen Warren, Thierry Reding, linux-tegra, Mark Rutland,
	devicetree, linux-usb, Russell King, Mathias Nyman, Pawel Moll,
	Ian Campbell, Greg Kroah-Hartman, Linus Walleij, Jassi Brar,
	linux-kernel, Kishon Vijay Abraham I, Rob Herring, Alan Stern,
	linux-arm-kernel, Kumar Gala, Grant Likely, Arnd Bergmann

On 18 August 2014 19:08, Andrew Bresticker <abrestic@chromium.org> wrote:
>
> Tested on Venice2, Jetson TK1, and Big with a variety of USB2.0 and
> USB3.0 memory sticks and ethernet dongles using controller firmware from
> the ChromiumOS tree [2].

Hi Andrew,

do you have any information regarding the port assignments for the
Blaze board? Would like to test this there.

Thanks,

Tomeu

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

* [PATCH v2 0/9] Tegra xHCI support
@ 2014-08-21 13:34   ` Tomeu Vizoso
  0 siblings, 0 replies; 141+ messages in thread
From: Tomeu Vizoso @ 2014-08-21 13:34 UTC (permalink / raw)
  To: linux-arm-kernel

On 18 August 2014 19:08, Andrew Bresticker <abrestic@chromium.org> wrote:
>
> Tested on Venice2, Jetson TK1, and Big with a variety of USB2.0 and
> USB3.0 memory sticks and ethernet dongles using controller firmware from
> the ChromiumOS tree [2].

Hi Andrew,

do you have any information regarding the port assignments for the
Blaze board? Would like to test this there.

Thanks,

Tomeu

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

* Re: [PATCH v2 0/9] Tegra xHCI support
  2014-08-21 13:34   ` Tomeu Vizoso
  (?)
@ 2014-08-21 17:26       ` Andrew Bresticker
  -1 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-21 17:26 UTC (permalink / raw)
  To: Tomeu Vizoso
  Cc: Stephen Warren, Thierry Reding,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA, Mark Rutland,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-usb-u79uwXL29TY76Z2rM5mHXA, Russell King, Mathias Nyman,
	Pawel Moll, Ian Campbell, Greg Kroah-Hartman, Linus Walleij,
	Jassi Brar, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	Kishon Vijay Abraham I, Rob Herring, Alan Stern,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Kumar Gala

On Thu, Aug 21, 2014 at 6:34 AM, Tomeu Vizoso <tomeu-XCtybt49RKsYaV1qd6yewg@public.gmane.org> wrote:
> On 18 August 2014 19:08, Andrew Bresticker <abrestic-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org> wrote:
>>
>> Tested on Venice2, Jetson TK1, and Big with a variety of USB2.0 and
>> USB3.0 memory sticks and ethernet dongles using controller firmware from
>> the ChromiumOS tree [2].
>
> Hi Andrew,
>
> do you have any information regarding the port assignments for the
> Blaze board? Would like to test this there.

Sure:
- USB3 port 0 (using PCIe lane 0) and UTMI port 0 are connected to the
USB A connector on the left side,
- UTMI port 1 is connected to an internal hub, which is in turn
connected to the camera, the LTE modem (if present), and one of the
USB A connectors on the right side, and
- UTMI port 2 is connected to the other USB A connector on the right side.
The mapping of ports on the right side varies by SKU (i.e. the one on
the internal hub may be the front or rear USB A port).

The USB3 device tree bits for Venice2 should work just fine for Blaze;
the only real difference is that USB3 port 1/PCIe lane 1 are unused.

Also, because of the board design on Blaze, the fused HS_CURR_LEVEL
values need to be adjusted before being programmed into
USB2_OTG_PAD*_CTL0.  This only affects UTMI ports 0 and 2, so ports
connected to the internal hub should still work.  I'll add a pinconfig
property to address this in the likely event I need to re-spin this
series.  Or, if you like, I can send a follow-on patch to this set to
add the property.

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

* Re: [PATCH v2 0/9] Tegra xHCI support
@ 2014-08-21 17:26       ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-21 17:26 UTC (permalink / raw)
  To: Tomeu Vizoso
  Cc: Stephen Warren, Thierry Reding, linux-tegra, Mark Rutland,
	devicetree, linux-usb, Russell King, Mathias Nyman, Pawel Moll,
	Ian Campbell, Greg Kroah-Hartman, Linus Walleij, Jassi Brar,
	linux-kernel, Kishon Vijay Abraham I, Rob Herring, Alan Stern,
	linux-arm-kernel, Kumar Gala, Grant Likely, Arnd Bergmann

On Thu, Aug 21, 2014 at 6:34 AM, Tomeu Vizoso <tomeu@tomeuvizoso.net> wrote:
> On 18 August 2014 19:08, Andrew Bresticker <abrestic@chromium.org> wrote:
>>
>> Tested on Venice2, Jetson TK1, and Big with a variety of USB2.0 and
>> USB3.0 memory sticks and ethernet dongles using controller firmware from
>> the ChromiumOS tree [2].
>
> Hi Andrew,
>
> do you have any information regarding the port assignments for the
> Blaze board? Would like to test this there.

Sure:
- USB3 port 0 (using PCIe lane 0) and UTMI port 0 are connected to the
USB A connector on the left side,
- UTMI port 1 is connected to an internal hub, which is in turn
connected to the camera, the LTE modem (if present), and one of the
USB A connectors on the right side, and
- UTMI port 2 is connected to the other USB A connector on the right side.
The mapping of ports on the right side varies by SKU (i.e. the one on
the internal hub may be the front or rear USB A port).

The USB3 device tree bits for Venice2 should work just fine for Blaze;
the only real difference is that USB3 port 1/PCIe lane 1 are unused.

Also, because of the board design on Blaze, the fused HS_CURR_LEVEL
values need to be adjusted before being programmed into
USB2_OTG_PAD*_CTL0.  This only affects UTMI ports 0 and 2, so ports
connected to the internal hub should still work.  I'll add a pinconfig
property to address this in the likely event I need to re-spin this
series.  Or, if you like, I can send a follow-on patch to this set to
add the property.

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

* [PATCH v2 0/9] Tegra xHCI support
@ 2014-08-21 17:26       ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-21 17:26 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Aug 21, 2014 at 6:34 AM, Tomeu Vizoso <tomeu@tomeuvizoso.net> wrote:
> On 18 August 2014 19:08, Andrew Bresticker <abrestic@chromium.org> wrote:
>>
>> Tested on Venice2, Jetson TK1, and Big with a variety of USB2.0 and
>> USB3.0 memory sticks and ethernet dongles using controller firmware from
>> the ChromiumOS tree [2].
>
> Hi Andrew,
>
> do you have any information regarding the port assignments for the
> Blaze board? Would like to test this there.

Sure:
- USB3 port 0 (using PCIe lane 0) and UTMI port 0 are connected to the
USB A connector on the left side,
- UTMI port 1 is connected to an internal hub, which is in turn
connected to the camera, the LTE modem (if present), and one of the
USB A connectors on the right side, and
- UTMI port 2 is connected to the other USB A connector on the right side.
The mapping of ports on the right side varies by SKU (i.e. the one on
the internal hub may be the front or rear USB A port).

The USB3 device tree bits for Venice2 should work just fine for Blaze;
the only real difference is that USB3 port 1/PCIe lane 1 are unused.

Also, because of the board design on Blaze, the fused HS_CURR_LEVEL
values need to be adjusted before being programmed into
USB2_OTG_PAD*_CTL0.  This only affects UTMI ports 0 and 2, so ports
connected to the internal hub should still work.  I'll add a pinconfig
property to address this in the likely event I need to re-spin this
series.  Or, if you like, I can send a follow-on patch to this set to
add the property.

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

* Re: [PATCH v2 0/9] Tegra xHCI support
  2014-08-21 17:26       ` Andrew Bresticker
  (?)
@ 2014-08-22 11:23           ` Tomeu Vizoso
  -1 siblings, 0 replies; 141+ messages in thread
From: Tomeu Vizoso @ 2014-08-22 11:23 UTC (permalink / raw)
  To: Andrew Bresticker
  Cc: Stephen Warren, Thierry Reding,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA, Mark Rutland,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-usb-u79uwXL29TY76Z2rM5mHXA, Russell King, Mathias Nyman,
	Pawel Moll, Ian Campbell, Greg Kroah-Hartman, Linus Walleij,
	Jassi Brar, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	Kishon Vijay Abraham I, Rob Herring, Alan Stern,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Kumar Gala

On 21 August 2014 19:26, Andrew Bresticker <abrestic-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org> wrote:
> On Thu, Aug 21, 2014 at 6:34 AM, Tomeu Vizoso <tomeu-XCtybt49RKsYaV1qd6yewg@public.gmane.org> wrote:
>> On 18 August 2014 19:08, Andrew Bresticker <abrestic-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org> wrote:
>>>
>>> Tested on Venice2, Jetson TK1, and Big with a variety of USB2.0 and
>>> USB3.0 memory sticks and ethernet dongles using controller firmware from
>>> the ChromiumOS tree [2].
>>
>> Hi Andrew,
>>
>> do you have any information regarding the port assignments for the
>> Blaze board? Would like to test this there.
>
> Sure:
> - USB3 port 0 (using PCIe lane 0) and UTMI port 0 are connected to the
> USB A connector on the left side,
> - UTMI port 1 is connected to an internal hub, which is in turn
> connected to the camera, the LTE modem (if present), and one of the
> USB A connectors on the right side, and
> - UTMI port 2 is connected to the other USB A connector on the right side.
> The mapping of ports on the right side varies by SKU (i.e. the one on
> the internal hub may be the front or rear USB A port).
>
> The USB3 device tree bits for Venice2 should work just fine for Blaze;
> the only real difference is that USB3 port 1/PCIe lane 1 are unused.
>
> Also, because of the board design on Blaze, the fused HS_CURR_LEVEL
> values need to be adjusted before being programmed into
> USB2_OTG_PAD*_CTL0.  This only affects UTMI ports 0 and 2, so ports
> connected to the internal hub should still work.  I'll add a pinconfig
> property to address this in the likely event I need to re-spin this
> series.  Or, if you like, I can send a follow-on patch to this set to
> add the property.

Yeah, that would be great, if it's not too much trouble for you. So
far the internal camera is working so I'm able to do some
experimenting with it already.

Thanks,

Tomeu

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

* Re: [PATCH v2 0/9] Tegra xHCI support
@ 2014-08-22 11:23           ` Tomeu Vizoso
  0 siblings, 0 replies; 141+ messages in thread
From: Tomeu Vizoso @ 2014-08-22 11:23 UTC (permalink / raw)
  To: Andrew Bresticker
  Cc: Stephen Warren, Thierry Reding, linux-tegra, Mark Rutland,
	devicetree, linux-usb, Russell King, Mathias Nyman, Pawel Moll,
	Ian Campbell, Greg Kroah-Hartman, Linus Walleij, Jassi Brar,
	linux-kernel, Kishon Vijay Abraham I, Rob Herring, Alan Stern,
	linux-arm-kernel, Kumar Gala, Grant Likely, Arnd Bergmann

On 21 August 2014 19:26, Andrew Bresticker <abrestic@chromium.org> wrote:
> On Thu, Aug 21, 2014 at 6:34 AM, Tomeu Vizoso <tomeu@tomeuvizoso.net> wrote:
>> On 18 August 2014 19:08, Andrew Bresticker <abrestic@chromium.org> wrote:
>>>
>>> Tested on Venice2, Jetson TK1, and Big with a variety of USB2.0 and
>>> USB3.0 memory sticks and ethernet dongles using controller firmware from
>>> the ChromiumOS tree [2].
>>
>> Hi Andrew,
>>
>> do you have any information regarding the port assignments for the
>> Blaze board? Would like to test this there.
>
> Sure:
> - USB3 port 0 (using PCIe lane 0) and UTMI port 0 are connected to the
> USB A connector on the left side,
> - UTMI port 1 is connected to an internal hub, which is in turn
> connected to the camera, the LTE modem (if present), and one of the
> USB A connectors on the right side, and
> - UTMI port 2 is connected to the other USB A connector on the right side.
> The mapping of ports on the right side varies by SKU (i.e. the one on
> the internal hub may be the front or rear USB A port).
>
> The USB3 device tree bits for Venice2 should work just fine for Blaze;
> the only real difference is that USB3 port 1/PCIe lane 1 are unused.
>
> Also, because of the board design on Blaze, the fused HS_CURR_LEVEL
> values need to be adjusted before being programmed into
> USB2_OTG_PAD*_CTL0.  This only affects UTMI ports 0 and 2, so ports
> connected to the internal hub should still work.  I'll add a pinconfig
> property to address this in the likely event I need to re-spin this
> series.  Or, if you like, I can send a follow-on patch to this set to
> add the property.

Yeah, that would be great, if it's not too much trouble for you. So
far the internal camera is working so I'm able to do some
experimenting with it already.

Thanks,

Tomeu

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

* [PATCH v2 0/9] Tegra xHCI support
@ 2014-08-22 11:23           ` Tomeu Vizoso
  0 siblings, 0 replies; 141+ messages in thread
From: Tomeu Vizoso @ 2014-08-22 11:23 UTC (permalink / raw)
  To: linux-arm-kernel

On 21 August 2014 19:26, Andrew Bresticker <abrestic@chromium.org> wrote:
> On Thu, Aug 21, 2014 at 6:34 AM, Tomeu Vizoso <tomeu@tomeuvizoso.net> wrote:
>> On 18 August 2014 19:08, Andrew Bresticker <abrestic@chromium.org> wrote:
>>>
>>> Tested on Venice2, Jetson TK1, and Big with a variety of USB2.0 and
>>> USB3.0 memory sticks and ethernet dongles using controller firmware from
>>> the ChromiumOS tree [2].
>>
>> Hi Andrew,
>>
>> do you have any information regarding the port assignments for the
>> Blaze board? Would like to test this there.
>
> Sure:
> - USB3 port 0 (using PCIe lane 0) and UTMI port 0 are connected to the
> USB A connector on the left side,
> - UTMI port 1 is connected to an internal hub, which is in turn
> connected to the camera, the LTE modem (if present), and one of the
> USB A connectors on the right side, and
> - UTMI port 2 is connected to the other USB A connector on the right side.
> The mapping of ports on the right side varies by SKU (i.e. the one on
> the internal hub may be the front or rear USB A port).
>
> The USB3 device tree bits for Venice2 should work just fine for Blaze;
> the only real difference is that USB3 port 1/PCIe lane 1 are unused.
>
> Also, because of the board design on Blaze, the fused HS_CURR_LEVEL
> values need to be adjusted before being programmed into
> USB2_OTG_PAD*_CTL0.  This only affects UTMI ports 0 and 2, so ports
> connected to the internal hub should still work.  I'll add a pinconfig
> property to address this in the likely event I need to re-spin this
> series.  Or, if you like, I can send a follow-on patch to this set to
> add the property.

Yeah, that would be great, if it's not too much trouble for you. So
far the internal camera is working so I'm able to do some
experimenting with it already.

Thanks,

Tomeu

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

* [PATCH 10/9] pinctrl: tegra-xusb: Support adjusted HS_CURR_LEVEL
       [not found] ` <1408381705-3623-1-git-send-email-abrestic-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
                     ` (2 preceding siblings ...)
  2014-08-18 17:30     ` Stephen Warren
@ 2014-08-22 18:28   ` Andrew Bresticker
       [not found]     ` <1408732088-28010-1-git-send-email-abrestic-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
  3 siblings, 1 reply; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-22 18:28 UTC (permalink / raw)
  To: Tomeu Vizoso, Stephen Warren, Thierry Reding
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, Andrew Bresticker

On some boards, e.g. Blaze, the fused per-UTMI pad HS_CURR_LEVEL value
must be adjusted before being applied.  Add support for a new pinconfig
property "nvidia,otg-hs-curr-level-offset" which will apply the specified
offset to the fused HS_CURR_LEVEL value.

Signed-off-by: Andrew Bresticker <abrestic-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
---
On Blaze, the OTG pads should be configured like this:
...
	otgp0 {
		nvidia,lanes = "otg-0";
		nvidia,function = "xusb";
		nvidia,otg-hs-curr-level-offset = <4>;
	};
	otgp1 {
		nvidia,lanes = "otg-1";
		nvidia,function = "xusb";
	};
	otgp2 {
		nvidia,lanes = "otg-2";
		nvidia,function = "xusb";
		nvidia,otg-hs-curr-level-offset = <2>;
	};
...
It is otherwise compatible with the Venice2 XUSB/XHCI DT bits.
---
 .../pinctrl/nvidia,tegra124-xusb-padctl.txt        |  4 ++-
 drivers/pinctrl/pinctrl-tegra-xusb.c               | 36 +++++++++++++++++++++-
 2 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt
index 606a5db..23df0bc 100644
--- a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt
@@ -69,6 +69,8 @@ Optional properties:
 - nvidia,hsic-tx-slew-n: HSIC TX SLEWN value.
 - nvidia,hsic-tx-slew-p: HSIC TX SLEWP value.
 - nvidia,hsic-auto-term: Enables HSIC AUTO_TERM. (0: no, 1: yes)
+- nvidia,otg-hs-curr-level-offset: Offset to be applied to the pad's fused
+  HS_CURR_LEVEL value.
 
 Note that not all of these properties are valid for all lanes. Lanes can be
 divided into three groups:
@@ -77,7 +79,7 @@ divided into three groups:
 
     Valid functions for this group are: "snps", "xusb", "uart", "rsvd".
 
-    None of the other properties apply to this group.
+    The nvidia,otg-hs-curr-level-offset property only applies.
 
   - ulpi-0, hsic-0, hsic-1:
 
diff --git a/drivers/pinctrl/pinctrl-tegra-xusb.c b/drivers/pinctrl/pinctrl-tegra-xusb.c
index 1091ce7..46ee0f1 100644
--- a/drivers/pinctrl/pinctrl-tegra-xusb.c
+++ b/drivers/pinctrl/pinctrl-tegra-xusb.c
@@ -282,6 +282,7 @@ struct tegra_xusb_padctl {
 
 	struct tegra_xusb_usb3_port usb3_ports[TEGRA_XUSB_USB3_PHYS];
 	unsigned int utmi_enable;
+	unsigned int hs_curr_level_offset[TEGRA_XUSB_UTMI_PHYS];
 	struct regulator *vbus[TEGRA_XUSB_UTMI_PHYS];
 	struct regulator *vddio_hsic;
 };
@@ -298,6 +299,12 @@ static inline u32 padctl_readl(struct tegra_xusb_padctl *padctl,
 	return readl(padctl->regs + offset);
 }
 
+static inline bool is_otg_lane(unsigned int lane)
+{
+	return lane >= TEGRA_XUSB_PADCTL_PIN_OTG_0 &&
+		lane <= TEGRA_XUSB_PADCTL_PIN_OTG_2;
+}
+
 static inline bool is_hsic_lane(unsigned int lane)
 {
 	return lane >= TEGRA_XUSB_PADCTL_PIN_HSIC_0 &&
@@ -349,6 +356,7 @@ enum tegra_xusb_padctl_param {
 	TEGRA_XUSB_PADCTL_HSIC_TX_RSLEWN,
 	TEGRA_XUSB_PADCTL_HSIC_TX_RSLEWP,
 	TEGRA_XUSB_PADCTL_HSIC_AUTO_TERM,
+	TEGRA_XUSB_PADCTL_OTG_HS_CURR_LEVEL_OFFSET,
 };
 
 static const struct tegra_xusb_padctl_property {
@@ -365,6 +373,8 @@ static const struct tegra_xusb_padctl_property {
 	{ "nvidia,hsic-tx-rslew-n", TEGRA_XUSB_PADCTL_HSIC_TX_RSLEWN },
 	{ "nvidia,hsic-tx-rslew-p", TEGRA_XUSB_PADCTL_HSIC_TX_RSLEWP },
 	{ "nvidia,hsic-auto-term", TEGRA_XUSB_PADCTL_HSIC_AUTO_TERM },
+	{ "nvidia,otg-hs-curr-level-offset",
+	  TEGRA_XUSB_PADCTL_OTG_HS_CURR_LEVEL_OFFSET },
 };
 
 #define TEGRA_XUSB_PADCTL_PACK(param, value) ((param) << 16 | (value))
@@ -678,6 +688,17 @@ static int tegra_xusb_padctl_pinconf_group_get(struct pinctrl_dev *pinctrl,
 			value = 0;
 		break;
 
+	case TEGRA_XUSB_PADCTL_OTG_HS_CURR_LEVEL_OFFSET:
+		if (!is_otg_lane(group)) {
+			dev_err(padctl->dev, "Pin %d is not an OTG pad\n",
+				group);
+			return -EINVAL;
+		}
+
+		port = group - TEGRA_XUSB_PADCTL_PIN_OTG_0;
+		value = padctl->hs_curr_level_offset[port];
+		break;
+
 	default:
 		dev_err(padctl->dev, "invalid configuration parameter: %04x\n",
 			param);
@@ -895,6 +916,18 @@ static int tegra_xusb_padctl_pinconf_group_set(struct pinctrl_dev *pinctrl,
 				      XUSB_PADCTL_HSIC_PADX_CTL1(port));
 			break;
 
+		case TEGRA_XUSB_PADCTL_OTG_HS_CURR_LEVEL_OFFSET:
+			if (!is_otg_lane(group)) {
+				dev_err(padctl->dev,
+					"Pin %d is not an OTG pad\n", group);
+				return -EINVAL;
+			}
+
+			port = group - TEGRA_XUSB_PADCTL_PIN_OTG_0;
+			value &= XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_MASK;
+			padctl->hs_curr_level_offset[port] = value;
+			break;
+
 		default:
 			dev_err(padctl->dev,
 				"invalid configuration parameter: %04x\n",
@@ -1485,7 +1518,8 @@ static int utmi_phy_power_on(struct phy *phy)
 		   XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD |
 		   XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD2 |
 		   XUSB_PADCTL_USB2_OTG_PAD_CTL0_PD_ZI);
-	value |= padctl->calib.hs_curr_level[port] <<
+	value |= (padctl->calib.hs_curr_level[port] +
+		  padctl->hs_curr_level_offset[port]) <<
 		XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_CURR_LEVEL_SHIFT;
 	value |= padctl->soc->hs_slew <<
 		XUSB_PADCTL_USB2_OTG_PAD_CTL0_HS_SLEW_SHIFT;
-- 
2.1.0.rc2.206.gedb03e5

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

* Re: [PATCH v2 1/9] of: Add NVIDIA Tegra XUSB mailbox binding
  2014-08-18 17:08     ` Andrew Bresticker
  (?)
@ 2014-08-25 18:48         ` Stephen Warren
  -1 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-25 18:48 UTC (permalink / raw)
  To: Andrew Bresticker, Thierry Reding, linux-tegra-u79uwXL29TY76Z2rM5mHXA
  Cc: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Jassi Brar, Linus Walleij, Greg Kroah-Hartman,
	Mathias Nyman, Grant Likely, Alan Stern, Arnd Bergmann,
	Kishon Vijay Abraham I, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA

On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> Add device-tree bindings for the Tegra XUSB mailbox which will be used
> for communication between the Tegra xHCI controller's firmware and the
> host processor.

> diff --git a/Documentation/devicetree/bindings/mailbox/nvidia,tegra124-xusb-mbox.txt b/Documentation/devicetree/bindings/mailbox/nvidia,tegra124-xusb-mbox.txt

> +NVIDIA Tegra XUSB mailbox
> +=========================
> +
> +The Tegra XUSB mailbox is used by the Tegra xHCI controller's firmware to
> +communicate requests to the host and PHY drivers.
> +
> +Required properties:
> +--------------------
> + - compatible: Should be "nvidia,tegra124-xusb-mbox".
> + - reg: Address and length of the XUSB FPCI registers.
> + - interrupts: XUSB mailbox interrupt.
> + - #mbox-cells: Should be 1.  The specifier is the index of the mailbox to
> +   reference.  See <dt-bindings/mailbox/tegra-xusb-mailbox.h> for the list
> +   of valid values.

Is there a common mailbox binding somewhere? I couldn't find one. While 
the text above specifies the value for #mbox-cells, it doesn't specify 
the details of what the property is used for (i.e. there's no 
documentation of the consumer-side of this property, for parsing the 
mboxes property). Typically, that would be part of a subsystem's common 
binding document, and that document would be referenced here.

> diff --git a/include/dt-bindings/mailbox/tegra-xusb-mailbox.h b/include/dt-bindings/mailbox/tegra-xusb-mailbox.h

> +#define TEGRA_XUSB_MBOX_CHAN_HOST	0
> +#define TEGRA_XUSB_MBOX_CHAN_PHY	1

I can't work out how these values relate to hardware at all. Are they in 
fact properties of the particular firmware that's loaded into the XUSB 
module? If so, I don't think the DT should contain these values at all. 
I wonder if the individual MBOX_CMD_* values from patch 2 are any 
better, although I think those are also defined by the firmware, not the 
hardware?

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

* Re: [PATCH v2 1/9] of: Add NVIDIA Tegra XUSB mailbox binding
@ 2014-08-25 18:48         ` Stephen Warren
  0 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-25 18:48 UTC (permalink / raw)
  To: Andrew Bresticker, Thierry Reding, linux-tegra
  Cc: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Jassi Brar, Linus Walleij, Greg Kroah-Hartman,
	Mathias Nyman, Grant Likely, Alan Stern, Arnd Bergmann,
	Kishon Vijay Abraham I, devicetree, linux-kernel,
	linux-arm-kernel, linux-usb

On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> Add device-tree bindings for the Tegra XUSB mailbox which will be used
> for communication between the Tegra xHCI controller's firmware and the
> host processor.

> diff --git a/Documentation/devicetree/bindings/mailbox/nvidia,tegra124-xusb-mbox.txt b/Documentation/devicetree/bindings/mailbox/nvidia,tegra124-xusb-mbox.txt

> +NVIDIA Tegra XUSB mailbox
> +=========================
> +
> +The Tegra XUSB mailbox is used by the Tegra xHCI controller's firmware to
> +communicate requests to the host and PHY drivers.
> +
> +Required properties:
> +--------------------
> + - compatible: Should be "nvidia,tegra124-xusb-mbox".
> + - reg: Address and length of the XUSB FPCI registers.
> + - interrupts: XUSB mailbox interrupt.
> + - #mbox-cells: Should be 1.  The specifier is the index of the mailbox to
> +   reference.  See <dt-bindings/mailbox/tegra-xusb-mailbox.h> for the list
> +   of valid values.

Is there a common mailbox binding somewhere? I couldn't find one. While 
the text above specifies the value for #mbox-cells, it doesn't specify 
the details of what the property is used for (i.e. there's no 
documentation of the consumer-side of this property, for parsing the 
mboxes property). Typically, that would be part of a subsystem's common 
binding document, and that document would be referenced here.

> diff --git a/include/dt-bindings/mailbox/tegra-xusb-mailbox.h b/include/dt-bindings/mailbox/tegra-xusb-mailbox.h

> +#define TEGRA_XUSB_MBOX_CHAN_HOST	0
> +#define TEGRA_XUSB_MBOX_CHAN_PHY	1

I can't work out how these values relate to hardware at all. Are they in 
fact properties of the particular firmware that's loaded into the XUSB 
module? If so, I don't think the DT should contain these values at all. 
I wonder if the individual MBOX_CMD_* values from patch 2 are any 
better, although I think those are also defined by the firmware, not the 
hardware?

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

* [PATCH v2 1/9] of: Add NVIDIA Tegra XUSB mailbox binding
@ 2014-08-25 18:48         ` Stephen Warren
  0 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-25 18:48 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> Add device-tree bindings for the Tegra XUSB mailbox which will be used
> for communication between the Tegra xHCI controller's firmware and the
> host processor.

> diff --git a/Documentation/devicetree/bindings/mailbox/nvidia,tegra124-xusb-mbox.txt b/Documentation/devicetree/bindings/mailbox/nvidia,tegra124-xusb-mbox.txt

> +NVIDIA Tegra XUSB mailbox
> +=========================
> +
> +The Tegra XUSB mailbox is used by the Tegra xHCI controller's firmware to
> +communicate requests to the host and PHY drivers.
> +
> +Required properties:
> +--------------------
> + - compatible: Should be "nvidia,tegra124-xusb-mbox".
> + - reg: Address and length of the XUSB FPCI registers.
> + - interrupts: XUSB mailbox interrupt.
> + - #mbox-cells: Should be 1.  The specifier is the index of the mailbox to
> +   reference.  See <dt-bindings/mailbox/tegra-xusb-mailbox.h> for the list
> +   of valid values.

Is there a common mailbox binding somewhere? I couldn't find one. While 
the text above specifies the value for #mbox-cells, it doesn't specify 
the details of what the property is used for (i.e. there's no 
documentation of the consumer-side of this property, for parsing the 
mboxes property). Typically, that would be part of a subsystem's common 
binding document, and that document would be referenced here.

> diff --git a/include/dt-bindings/mailbox/tegra-xusb-mailbox.h b/include/dt-bindings/mailbox/tegra-xusb-mailbox.h

> +#define TEGRA_XUSB_MBOX_CHAN_HOST	0
> +#define TEGRA_XUSB_MBOX_CHAN_PHY	1

I can't work out how these values relate to hardware at all. Are they in 
fact properties of the particular firmware that's loaded into the XUSB 
module? If so, I don't think the DT should contain these values at all. 
I wonder if the individual MBOX_CMD_* values from patch 2 are any 
better, although I think those are also defined by the firmware, not the 
hardware?

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
  2014-08-18 17:08   ` Andrew Bresticker
  (?)
@ 2014-08-25 19:01       ` Stephen Warren
  -1 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-25 19:01 UTC (permalink / raw)
  To: Andrew Bresticker, Thierry Reding, linux-tegra-u79uwXL29TY76Z2rM5mHXA
  Cc: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Jassi Brar, Linus Walleij, Greg Kroah-Hartman,
	Mathias Nyman, Grant Likely, Alan Stern, Arnd Bergmann,
	Kishon Vijay Abraham I, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA

On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> The Tegra xHCI controller's firmware communicates requests to the host
> processor through a mailbox interface.  While there is only a single
> communication channel, messages sent by the controller can be divided
> into two groups: those intended for the PHY driver and those intended
> for the host-controller driver.  This mailbox driver exposes the two
> channels and routes incoming messages to the appropriate channel based
> on the command encoded in the message.

> diff --git a/drivers/mailbox/tegra-xusb-mailbox.c b/drivers/mailbox/tegra-xusb-mailbox.c

> +#define XUSB_CFG_ARU_MBOX_CMD			0xe4
> +#define  MBOX_FALC_INT_EN			BIT(27)
> +#define  MBOX_PME_INT_EN			BIT(28)
> +#define  MBOX_SMI_INT_EN			BIT(29)
> +#define  MBOX_XHCI_INT_EN			BIT(30)
> +#define  MBOX_INT_EN				BIT(31)

Those field names don't match the documentation in the TRM; they're 
called DEST_xxx rather than xxx_INT_EN. I'm not sure what that 
disconnect means (i.e. whether it's just a different naming choice, or 
there's some practical disconnect that will cause issues.)

> +static struct mbox_chan *mbox_cmd_to_chan(struct tegra_xusb_mbox *mbox, u32 cmd)
> +{
> +	switch (cmd) {
> +	case MBOX_CMD_INC_FALC_CLOCK:
> +	case MBOX_CMD_DEC_FALC_CLOCK:
> +	case MBOX_CMD_INC_SSPI_CLOCK:
> +	case MBOX_CMD_DEC_SSPI_CLOCK:
> +	case MBOX_CMD_SET_BW:
> +		return &mbox->mbox.chans[TEGRA_XUSB_MBOX_CHAN_HOST];
> +	case MBOX_CMD_SAVE_DFE_CTLE_CTX:
> +	case MBOX_CMD_START_HSIC_IDLE:
> +	case MBOX_CMD_STOP_HSIC_IDLE:
> +		return &mbox->mbox.chans[TEGRA_XUSB_MBOX_CHAN_PHY];
> +	default:
> +		return NULL;
> +	}
> +}

This makes me think that the CHAN_HOST/CHAN_PHY values are purely a 
facet of the Linux driver's message de-multiplexing, rather than 
anything to do with the HW.

I'm not even sure if it's appropriate for the low-level mailbox driver 
to know about the semantics of the message, rather than simply sending 
them on to the client driver? Perhaps when drivers register(?) for 
callbacks(?) for messages, they should state which types of messages 
they want to listen to?

> +static irqreturn_t tegra_xusb_mbox_irq(int irq, void *p)

> +	/* Clear mbox interrupts */
> +	reg = mbox_readl(mbox, XUSB_CFG_ARU_SMI_INTR);
> +	if (reg & MBOX_SMI_INTR_FW_HANG)
> +		dev_err(mbox->mbox.dev, "Controller firmware hang\n");
> +	mbox_writel(mbox, reg, XUSB_CFG_ARU_SMI_INTR);

> +	/*
> +	 * Set the mailbox back to idle.  The recipient of the message is
> +	 * responsible for sending an ACK/NAK, if necessary.
> +	 */
> +	reg = mbox_readl(mbox, XUSB_CFG_ARU_MBOX_CMD);
> +	reg &= ~MBOX_SMI_INT_EN;
> +	mbox_writel(mbox, reg, XUSB_CFG_ARU_MBOX_CMD);

Does the protocol not allow the remote firmware to send another message 
until the host has ack'd/nak'd the message; the code above turns off the 
IRQ that indicated to the host that a message was sent to it...

> +static int tegra_xusb_mbox_probe(struct platform_device *pdev)

> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!res)
> +		return -ENODEV;

Should devm_request_mem_region() be called here to claim the region?

> +	mbox->regs = devm_ioremap_nocache(&pdev->dev, res->start,
> +					  resource_size(res));
> +	if (!mbox->regs)
> +		return -ENOMEM;

Is _nocache required? I don't see other drivers using it. I assume 
there's nothing special about the mbox registers.

> +	mbox->irq = platform_get_irq(pdev, 0);
> +	if (mbox->irq < 0)
> +		return mbox->irq;
> +	ret = devm_request_irq(&pdev->dev, mbox->irq, tegra_xusb_mbox_irq, 0,
> +			       dev_name(&pdev->dev), mbox);

Is it possible for an IRQ to occur after tegra_xusb_mbox_remove() has 
returned, but before the cleanup for the devm IRQ allocation occurs? If 
that happens, will the code handle it gracefully, or crash?

> +MODULE_ALIAS("platform:tegra-xusb-mailbox");

I don't think that's required; it should auto-load based on the 
of_device_id/MODULE_DEVICE_TABLE(of,...) table.

> diff --git a/include/soc/tegra/xusb.h b/include/soc/tegra/xusb.h

> +#define TEGRA_XUSB_MBOX_NUM_CHANS 2 /* host + phy */

I'd rather see that definition in the same place as the 
TEGRA_XUSB_MBOX_CHAN_* values it refers to. Otherwise, it'd be quite 
easy to add values without updating this constant.
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-25 19:01       ` Stephen Warren
  0 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-25 19:01 UTC (permalink / raw)
  To: Andrew Bresticker, Thierry Reding, linux-tegra
  Cc: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Jassi Brar, Linus Walleij, Greg Kroah-Hartman,
	Mathias Nyman, Grant Likely, Alan Stern, Arnd Bergmann,
	Kishon Vijay Abraham I, devicetree, linux-kernel,
	linux-arm-kernel, linux-usb

On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> The Tegra xHCI controller's firmware communicates requests to the host
> processor through a mailbox interface.  While there is only a single
> communication channel, messages sent by the controller can be divided
> into two groups: those intended for the PHY driver and those intended
> for the host-controller driver.  This mailbox driver exposes the two
> channels and routes incoming messages to the appropriate channel based
> on the command encoded in the message.

> diff --git a/drivers/mailbox/tegra-xusb-mailbox.c b/drivers/mailbox/tegra-xusb-mailbox.c

> +#define XUSB_CFG_ARU_MBOX_CMD			0xe4
> +#define  MBOX_FALC_INT_EN			BIT(27)
> +#define  MBOX_PME_INT_EN			BIT(28)
> +#define  MBOX_SMI_INT_EN			BIT(29)
> +#define  MBOX_XHCI_INT_EN			BIT(30)
> +#define  MBOX_INT_EN				BIT(31)

Those field names don't match the documentation in the TRM; they're 
called DEST_xxx rather than xxx_INT_EN. I'm not sure what that 
disconnect means (i.e. whether it's just a different naming choice, or 
there's some practical disconnect that will cause issues.)

> +static struct mbox_chan *mbox_cmd_to_chan(struct tegra_xusb_mbox *mbox, u32 cmd)
> +{
> +	switch (cmd) {
> +	case MBOX_CMD_INC_FALC_CLOCK:
> +	case MBOX_CMD_DEC_FALC_CLOCK:
> +	case MBOX_CMD_INC_SSPI_CLOCK:
> +	case MBOX_CMD_DEC_SSPI_CLOCK:
> +	case MBOX_CMD_SET_BW:
> +		return &mbox->mbox.chans[TEGRA_XUSB_MBOX_CHAN_HOST];
> +	case MBOX_CMD_SAVE_DFE_CTLE_CTX:
> +	case MBOX_CMD_START_HSIC_IDLE:
> +	case MBOX_CMD_STOP_HSIC_IDLE:
> +		return &mbox->mbox.chans[TEGRA_XUSB_MBOX_CHAN_PHY];
> +	default:
> +		return NULL;
> +	}
> +}

This makes me think that the CHAN_HOST/CHAN_PHY values are purely a 
facet of the Linux driver's message de-multiplexing, rather than 
anything to do with the HW.

I'm not even sure if it's appropriate for the low-level mailbox driver 
to know about the semantics of the message, rather than simply sending 
them on to the client driver? Perhaps when drivers register(?) for 
callbacks(?) for messages, they should state which types of messages 
they want to listen to?

> +static irqreturn_t tegra_xusb_mbox_irq(int irq, void *p)

> +	/* Clear mbox interrupts */
> +	reg = mbox_readl(mbox, XUSB_CFG_ARU_SMI_INTR);
> +	if (reg & MBOX_SMI_INTR_FW_HANG)
> +		dev_err(mbox->mbox.dev, "Controller firmware hang\n");
> +	mbox_writel(mbox, reg, XUSB_CFG_ARU_SMI_INTR);

> +	/*
> +	 * Set the mailbox back to idle.  The recipient of the message is
> +	 * responsible for sending an ACK/NAK, if necessary.
> +	 */
> +	reg = mbox_readl(mbox, XUSB_CFG_ARU_MBOX_CMD);
> +	reg &= ~MBOX_SMI_INT_EN;
> +	mbox_writel(mbox, reg, XUSB_CFG_ARU_MBOX_CMD);

Does the protocol not allow the remote firmware to send another message 
until the host has ack'd/nak'd the message; the code above turns off the 
IRQ that indicated to the host that a message was sent to it...

> +static int tegra_xusb_mbox_probe(struct platform_device *pdev)

> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!res)
> +		return -ENODEV;

Should devm_request_mem_region() be called here to claim the region?

> +	mbox->regs = devm_ioremap_nocache(&pdev->dev, res->start,
> +					  resource_size(res));
> +	if (!mbox->regs)
> +		return -ENOMEM;

Is _nocache required? I don't see other drivers using it. I assume 
there's nothing special about the mbox registers.

> +	mbox->irq = platform_get_irq(pdev, 0);
> +	if (mbox->irq < 0)
> +		return mbox->irq;
> +	ret = devm_request_irq(&pdev->dev, mbox->irq, tegra_xusb_mbox_irq, 0,
> +			       dev_name(&pdev->dev), mbox);

Is it possible for an IRQ to occur after tegra_xusb_mbox_remove() has 
returned, but before the cleanup for the devm IRQ allocation occurs? If 
that happens, will the code handle it gracefully, or crash?

> +MODULE_ALIAS("platform:tegra-xusb-mailbox");

I don't think that's required; it should auto-load based on the 
of_device_id/MODULE_DEVICE_TABLE(of,...) table.

> diff --git a/include/soc/tegra/xusb.h b/include/soc/tegra/xusb.h

> +#define TEGRA_XUSB_MBOX_NUM_CHANS 2 /* host + phy */

I'd rather see that definition in the same place as the 
TEGRA_XUSB_MBOX_CHAN_* values it refers to. Otherwise, it'd be quite 
easy to add values without updating this constant.

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

* [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-25 19:01       ` Stephen Warren
  0 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-25 19:01 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> The Tegra xHCI controller's firmware communicates requests to the host
> processor through a mailbox interface.  While there is only a single
> communication channel, messages sent by the controller can be divided
> into two groups: those intended for the PHY driver and those intended
> for the host-controller driver.  This mailbox driver exposes the two
> channels and routes incoming messages to the appropriate channel based
> on the command encoded in the message.

> diff --git a/drivers/mailbox/tegra-xusb-mailbox.c b/drivers/mailbox/tegra-xusb-mailbox.c

> +#define XUSB_CFG_ARU_MBOX_CMD			0xe4
> +#define  MBOX_FALC_INT_EN			BIT(27)
> +#define  MBOX_PME_INT_EN			BIT(28)
> +#define  MBOX_SMI_INT_EN			BIT(29)
> +#define  MBOX_XHCI_INT_EN			BIT(30)
> +#define  MBOX_INT_EN				BIT(31)

Those field names don't match the documentation in the TRM; they're 
called DEST_xxx rather than xxx_INT_EN. I'm not sure what that 
disconnect means (i.e. whether it's just a different naming choice, or 
there's some practical disconnect that will cause issues.)

> +static struct mbox_chan *mbox_cmd_to_chan(struct tegra_xusb_mbox *mbox, u32 cmd)
> +{
> +	switch (cmd) {
> +	case MBOX_CMD_INC_FALC_CLOCK:
> +	case MBOX_CMD_DEC_FALC_CLOCK:
> +	case MBOX_CMD_INC_SSPI_CLOCK:
> +	case MBOX_CMD_DEC_SSPI_CLOCK:
> +	case MBOX_CMD_SET_BW:
> +		return &mbox->mbox.chans[TEGRA_XUSB_MBOX_CHAN_HOST];
> +	case MBOX_CMD_SAVE_DFE_CTLE_CTX:
> +	case MBOX_CMD_START_HSIC_IDLE:
> +	case MBOX_CMD_STOP_HSIC_IDLE:
> +		return &mbox->mbox.chans[TEGRA_XUSB_MBOX_CHAN_PHY];
> +	default:
> +		return NULL;
> +	}
> +}

This makes me think that the CHAN_HOST/CHAN_PHY values are purely a 
facet of the Linux driver's message de-multiplexing, rather than 
anything to do with the HW.

I'm not even sure if it's appropriate for the low-level mailbox driver 
to know about the semantics of the message, rather than simply sending 
them on to the client driver? Perhaps when drivers register(?) for 
callbacks(?) for messages, they should state which types of messages 
they want to listen to?

> +static irqreturn_t tegra_xusb_mbox_irq(int irq, void *p)

> +	/* Clear mbox interrupts */
> +	reg = mbox_readl(mbox, XUSB_CFG_ARU_SMI_INTR);
> +	if (reg & MBOX_SMI_INTR_FW_HANG)
> +		dev_err(mbox->mbox.dev, "Controller firmware hang\n");
> +	mbox_writel(mbox, reg, XUSB_CFG_ARU_SMI_INTR);

> +	/*
> +	 * Set the mailbox back to idle.  The recipient of the message is
> +	 * responsible for sending an ACK/NAK, if necessary.
> +	 */
> +	reg = mbox_readl(mbox, XUSB_CFG_ARU_MBOX_CMD);
> +	reg &= ~MBOX_SMI_INT_EN;
> +	mbox_writel(mbox, reg, XUSB_CFG_ARU_MBOX_CMD);

Does the protocol not allow the remote firmware to send another message 
until the host has ack'd/nak'd the message; the code above turns off the 
IRQ that indicated to the host that a message was sent to it...

> +static int tegra_xusb_mbox_probe(struct platform_device *pdev)

> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!res)
> +		return -ENODEV;

Should devm_request_mem_region() be called here to claim the region?

> +	mbox->regs = devm_ioremap_nocache(&pdev->dev, res->start,
> +					  resource_size(res));
> +	if (!mbox->regs)
> +		return -ENOMEM;

Is _nocache required? I don't see other drivers using it. I assume 
there's nothing special about the mbox registers.

> +	mbox->irq = platform_get_irq(pdev, 0);
> +	if (mbox->irq < 0)
> +		return mbox->irq;
> +	ret = devm_request_irq(&pdev->dev, mbox->irq, tegra_xusb_mbox_irq, 0,
> +			       dev_name(&pdev->dev), mbox);

Is it possible for an IRQ to occur after tegra_xusb_mbox_remove() has 
returned, but before the cleanup for the devm IRQ allocation occurs? If 
that happens, will the code handle it gracefully, or crash?

> +MODULE_ALIAS("platform:tegra-xusb-mailbox");

I don't think that's required; it should auto-load based on the 
of_device_id/MODULE_DEVICE_TABLE(of,...) table.

> diff --git a/include/soc/tegra/xusb.h b/include/soc/tegra/xusb.h

> +#define TEGRA_XUSB_MBOX_NUM_CHANS 2 /* host + phy */

I'd rather see that definition in the same place as the 
TEGRA_XUSB_MBOX_CHAN_* values it refers to. Otherwise, it'd be quite 
easy to add values without updating this constant.

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

* Re: [PATCH v2 1/9] of: Add NVIDIA Tegra XUSB mailbox binding
  2014-08-25 18:48         ` Stephen Warren
  (?)
@ 2014-08-25 19:06             ` Stephen Warren
  -1 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-25 19:06 UTC (permalink / raw)
  To: Andrew Bresticker, Thierry Reding, linux-tegra-u79uwXL29TY76Z2rM5mHXA
  Cc: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Jassi Brar, Linus Walleij, Greg Kroah-Hartman,
	Mathias Nyman, Grant Likely, Alan Stern, Arnd Bergmann,
	Kishon Vijay Abraham I, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA

On 08/25/2014 12:48 PM, Stephen Warren wrote:
> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>> Add device-tree bindings for the Tegra XUSB mailbox which will be used
>> for communication between the Tegra xHCI controller's firmware and the
>> host processor.
>
>> diff --git
>> a/Documentation/devicetree/bindings/mailbox/nvidia,tegra124-xusb-mbox.txt
>> b/Documentation/devicetree/bindings/mailbox/nvidia,tegra124-xusb-mbox.txt
>
>> +NVIDIA Tegra XUSB mailbox
>> +=========================
>> +
>> +The Tegra XUSB mailbox is used by the Tegra xHCI controller's
>> firmware to
>> +communicate requests to the host and PHY drivers.
>> +
>> +Required properties:
>> +--------------------
>> + - compatible: Should be "nvidia,tegra124-xusb-mbox".
>> + - reg: Address and length of the XUSB FPCI registers.
>> + - interrupts: XUSB mailbox interrupt.
>> + - #mbox-cells: Should be 1.  The specifier is the index of the
>> mailbox to
>> +   reference.  See <dt-bindings/mailbox/tegra-xusb-mailbox.h> for the
>> list
>> +   of valid values.
>
> Is there a common mailbox binding somewhere? I couldn't find one. While
> the text above specifies the value for #mbox-cells, it doesn't specify
> the details of what the property is used for (i.e. there's no
> documentation of the consumer-side of this property, for parsing the
> mboxes property). Typically, that would be part of a subsystem's common
> binding document, and that document would be referenced here.

Ah, I see it's still being developed. I found it at:
http://lkml.iu.edu/hypermail/linux/kernel/1408.0/00201.html

It would be good to mention that the semantics of this property are 
defined by ../mailbox/mailbox.txt.

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

* Re: [PATCH v2 1/9] of: Add NVIDIA Tegra XUSB mailbox binding
@ 2014-08-25 19:06             ` Stephen Warren
  0 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-25 19:06 UTC (permalink / raw)
  To: Andrew Bresticker, Thierry Reding, linux-tegra
  Cc: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Jassi Brar, Linus Walleij, Greg Kroah-Hartman,
	Mathias Nyman, Grant Likely, Alan Stern, Arnd Bergmann,
	Kishon Vijay Abraham I, devicetree, linux-kernel,
	linux-arm-kernel, linux-usb

On 08/25/2014 12:48 PM, Stephen Warren wrote:
> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>> Add device-tree bindings for the Tegra XUSB mailbox which will be used
>> for communication between the Tegra xHCI controller's firmware and the
>> host processor.
>
>> diff --git
>> a/Documentation/devicetree/bindings/mailbox/nvidia,tegra124-xusb-mbox.txt
>> b/Documentation/devicetree/bindings/mailbox/nvidia,tegra124-xusb-mbox.txt
>
>> +NVIDIA Tegra XUSB mailbox
>> +=========================
>> +
>> +The Tegra XUSB mailbox is used by the Tegra xHCI controller's
>> firmware to
>> +communicate requests to the host and PHY drivers.
>> +
>> +Required properties:
>> +--------------------
>> + - compatible: Should be "nvidia,tegra124-xusb-mbox".
>> + - reg: Address and length of the XUSB FPCI registers.
>> + - interrupts: XUSB mailbox interrupt.
>> + - #mbox-cells: Should be 1.  The specifier is the index of the
>> mailbox to
>> +   reference.  See <dt-bindings/mailbox/tegra-xusb-mailbox.h> for the
>> list
>> +   of valid values.
>
> Is there a common mailbox binding somewhere? I couldn't find one. While
> the text above specifies the value for #mbox-cells, it doesn't specify
> the details of what the property is used for (i.e. there's no
> documentation of the consumer-side of this property, for parsing the
> mboxes property). Typically, that would be part of a subsystem's common
> binding document, and that document would be referenced here.

Ah, I see it's still being developed. I found it at:
http://lkml.iu.edu/hypermail/linux/kernel/1408.0/00201.html

It would be good to mention that the semantics of this property are 
defined by ../mailbox/mailbox.txt.

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

* [PATCH v2 1/9] of: Add NVIDIA Tegra XUSB mailbox binding
@ 2014-08-25 19:06             ` Stephen Warren
  0 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-25 19:06 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/25/2014 12:48 PM, Stephen Warren wrote:
> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>> Add device-tree bindings for the Tegra XUSB mailbox which will be used
>> for communication between the Tegra xHCI controller's firmware and the
>> host processor.
>
>> diff --git
>> a/Documentation/devicetree/bindings/mailbox/nvidia,tegra124-xusb-mbox.txt
>> b/Documentation/devicetree/bindings/mailbox/nvidia,tegra124-xusb-mbox.txt
>
>> +NVIDIA Tegra XUSB mailbox
>> +=========================
>> +
>> +The Tegra XUSB mailbox is used by the Tegra xHCI controller's
>> firmware to
>> +communicate requests to the host and PHY drivers.
>> +
>> +Required properties:
>> +--------------------
>> + - compatible: Should be "nvidia,tegra124-xusb-mbox".
>> + - reg: Address and length of the XUSB FPCI registers.
>> + - interrupts: XUSB mailbox interrupt.
>> + - #mbox-cells: Should be 1.  The specifier is the index of the
>> mailbox to
>> +   reference.  See <dt-bindings/mailbox/tegra-xusb-mailbox.h> for the
>> list
>> +   of valid values.
>
> Is there a common mailbox binding somewhere? I couldn't find one. While
> the text above specifies the value for #mbox-cells, it doesn't specify
> the details of what the property is used for (i.e. there's no
> documentation of the consumer-side of this property, for parsing the
> mboxes property). Typically, that would be part of a subsystem's common
> binding document, and that document would be referenced here.

Ah, I see it's still being developed. I found it at:
http://lkml.iu.edu/hypermail/linux/kernel/1408.0/00201.html

It would be good to mention that the semantics of this property are 
defined by ../mailbox/mailbox.txt.

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

* Re: [PATCH v2 3/9] of: Update Tegra XUSB pad controller binding for USB
  2014-08-18 17:08   ` Andrew Bresticker
  (?)
@ 2014-08-25 19:12       ` Stephen Warren
  -1 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-25 19:12 UTC (permalink / raw)
  To: Andrew Bresticker, Thierry Reding, linux-tegra-u79uwXL29TY76Z2rM5mHXA
  Cc: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Jassi Brar, Linus Walleij, Greg Kroah-Hartman,
	Mathias Nyman, Grant Likely, Alan Stern, Arnd Bergmann,
	Kishon Vijay Abraham I, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA

On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> Add new bindings used for USB support by the Tegra XUSB pad controller.
> This includes additional PHY types, USB-specific pinconfig properties, etc.

I'll mainly defer to Thierry for this patch, since he's the expert on 
this HW module.

> diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt

>   - #phy-cells: Should be 1. The specifier is the index of the PHY to reference.
>     See <dt-bindings/pinctrl/pinctrl-tegra-xusb.h> for the list of valid values.
> +- mboxes: Must contain an entry for the XUSB PHY mailbox channel.
> +  See ../mailbox/mailbox.txt for details.

Can we require the mbox-names property here, so that everything is 
looked up by names. I know that the proposed mbox binding states that 
using indexes is preferred over names, but that's just silly considering 
that names are widely used in most other similar bindings, and are much 
easier to extend in a backwards compatible fashion in the face of 
optional entries. As such, I'd prefer that all Tegra bindings use 
foo-names properties where they exist.

> +Optional properties:
> +-------------------
> +- vbus-otg-{0,1,2}-supply: VBUS regulator for the corresponding UTMI pad.

Why "-otg"? It's quite possible to have a regulator for VBUS even on 
systems that don't support OTG, but rather simply have the ability to 
turn VBUS off.


>     - pcie-0, pcie-1, pcie-2, pcie-3, pcie-4, sata-0:
>
>       Valid functions for this group are: "pcie", "usb3", "sata", "rsvd".
>
> +    The nvidia,usb2-port-num property only applies and is required when
> +    the function is usb3.
> +
>

There are 2 blank lines there.

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

* Re: [PATCH v2 3/9] of: Update Tegra XUSB pad controller binding for USB
@ 2014-08-25 19:12       ` Stephen Warren
  0 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-25 19:12 UTC (permalink / raw)
  To: Andrew Bresticker, Thierry Reding, linux-tegra
  Cc: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Jassi Brar, Linus Walleij, Greg Kroah-Hartman,
	Mathias Nyman, Grant Likely, Alan Stern, Arnd Bergmann,
	Kishon Vijay Abraham I, devicetree, linux-kernel,
	linux-arm-kernel, linux-usb

On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> Add new bindings used for USB support by the Tegra XUSB pad controller.
> This includes additional PHY types, USB-specific pinconfig properties, etc.

I'll mainly defer to Thierry for this patch, since he's the expert on 
this HW module.

> diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt

>   - #phy-cells: Should be 1. The specifier is the index of the PHY to reference.
>     See <dt-bindings/pinctrl/pinctrl-tegra-xusb.h> for the list of valid values.
> +- mboxes: Must contain an entry for the XUSB PHY mailbox channel.
> +  See ../mailbox/mailbox.txt for details.

Can we require the mbox-names property here, so that everything is 
looked up by names. I know that the proposed mbox binding states that 
using indexes is preferred over names, but that's just silly considering 
that names are widely used in most other similar bindings, and are much 
easier to extend in a backwards compatible fashion in the face of 
optional entries. As such, I'd prefer that all Tegra bindings use 
foo-names properties where they exist.

> +Optional properties:
> +-------------------
> +- vbus-otg-{0,1,2}-supply: VBUS regulator for the corresponding UTMI pad.

Why "-otg"? It's quite possible to have a regulator for VBUS even on 
systems that don't support OTG, but rather simply have the ability to 
turn VBUS off.


>     - pcie-0, pcie-1, pcie-2, pcie-3, pcie-4, sata-0:
>
>       Valid functions for this group are: "pcie", "usb3", "sata", "rsvd".
>
> +    The nvidia,usb2-port-num property only applies and is required when
> +    the function is usb3.
> +
>

There are 2 blank lines there.


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

* [PATCH v2 3/9] of: Update Tegra XUSB pad controller binding for USB
@ 2014-08-25 19:12       ` Stephen Warren
  0 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-25 19:12 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> Add new bindings used for USB support by the Tegra XUSB pad controller.
> This includes additional PHY types, USB-specific pinconfig properties, etc.

I'll mainly defer to Thierry for this patch, since he's the expert on 
this HW module.

> diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-xusb-padctl.txt

>   - #phy-cells: Should be 1. The specifier is the index of the PHY to reference.
>     See <dt-bindings/pinctrl/pinctrl-tegra-xusb.h> for the list of valid values.
> +- mboxes: Must contain an entry for the XUSB PHY mailbox channel.
> +  See ../mailbox/mailbox.txt for details.

Can we require the mbox-names property here, so that everything is 
looked up by names. I know that the proposed mbox binding states that 
using indexes is preferred over names, but that's just silly considering 
that names are widely used in most other similar bindings, and are much 
easier to extend in a backwards compatible fashion in the face of 
optional entries. As such, I'd prefer that all Tegra bindings use 
foo-names properties where they exist.

> +Optional properties:
> +-------------------
> +- vbus-otg-{0,1,2}-supply: VBUS regulator for the corresponding UTMI pad.

Why "-otg"? It's quite possible to have a regulator for VBUS even on 
systems that don't support OTG, but rather simply have the ability to 
turn VBUS off.


>     - pcie-0, pcie-1, pcie-2, pcie-3, pcie-4, sata-0:
>
>       Valid functions for this group are: "pcie", "usb3", "sata", "rsvd".
>
> +    The nvidia,usb2-port-num property only applies and is required when
> +    the function is usb3.
> +
>

There are 2 blank lines there.

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

* Re: [PATCH v2 4/9] pinctrl: tegra-xusb: Add USB PHY support
  2014-08-18 17:08   ` Andrew Bresticker
  (?)
@ 2014-08-25 19:22       ` Stephen Warren
  -1 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-25 19:22 UTC (permalink / raw)
  To: Andrew Bresticker, Thierry Reding, Linus Walleij, Mikko Perttunen
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King, Jassi Brar,
	Greg Kroah-Hartman, Mathias Nyman, Grant Likely, Alan Stern,
	Arnd Bergmann, Kishon Vijay Abraham I,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA

On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> In addition to the PCIe and SATA PHYs, the XUSB pad controller also
> supports 3 UTMI, 2 HSIC, and 2 USB3 PHYs.  Each USB3 PHY uses a single
> PCIe or SATA lane and is mapped to one of the three UTMI ports.
>
> The xHCI controller will also send messages intended for the PHY driver,
> so request and listen for messages on the mailbox's PHY channel.

I'd like a review from Thierry here as the HW expert.

I need an ack from LinusW in order to take this pinctrl patch through 
the Tegra tree.

> diff --git a/drivers/pinctrl/pinctrl-tegra-xusb.c b/drivers/pinctrl/pinctrl-tegra-xusb.c

> +static int usb3_phy_power_on(struct phy *phy)
> +{
> +	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
> +	int port = usb3_phy_to_port(phy);
> +	int lane = padctl->usb3_ports[port].lane;
> +	u32 value, offset;
> +
> +	if (!is_pcie_or_sata_lane(lane)) {
> +		dev_err(padctl->dev, "USB3 PHY %d mapped to invalid lane: %d\n",
> +			port, lane);
> +		return -EINVAL;
> +	}

An aside: This implies that the SATA driver should be talking to this 
pinctrl driver and explicitly powering on the XUSB pins. However, the 
SATA driver doesn't depend on this series. I'm a bit confused how that 
works. Perhaps it's just by accident? Mikko, can you comment?

> +static int utmi_phy_to_port(struct phy *phy)
> +{
> +	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
> +	int i;
> +
> +	for (i = 0; i < TEGRA_XUSB_UTMI_PHYS; i++) {
> +		if (phy == padctl->phys[TEGRA_XUSB_PADCTL_UTMI_P0 + i])
> +			break;
> +	}
> +	BUG_ON(i == TEGRA_XUSB_UTMI_PHYS);

Can this be triggered by e.g. bad DT content? If so, returning an error 
would be nicer. The comment applies to other xxx_to_port() functions.

> @@ -896,6 +1933,22 @@ static int tegra_xusb_padctl_probe(struct platform_device *pdev)

> +	for (i = 0; i < TEGRA_XUSB_USB3_PHYS; i++) {
> +		char prop[sizeof("nvidia,usb3-port-N-lane")];
> +		u32 lane;
> +
> +		sprintf(prop, "nvidia,usb3-port-%d-lane", i);
> +		if (!of_property_read_u32(pdev->dev.of_node, prop, &lane)) {
> +			if (!is_pcie_or_sata_lane(lane)) {
> +				err = -EINVAL;
> +				goto unregister;

It'd be nice to print a message so that the user/developer knows what's 
wrong with the DT.

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

* Re: [PATCH v2 4/9] pinctrl: tegra-xusb: Add USB PHY support
@ 2014-08-25 19:22       ` Stephen Warren
  0 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-25 19:22 UTC (permalink / raw)
  To: Andrew Bresticker, Thierry Reding, Linus Walleij, Mikko Perttunen
  Cc: linux-tegra, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala, Russell King, Jassi Brar, Greg Kroah-Hartman,
	Mathias Nyman, Grant Likely, Alan Stern, Arnd Bergmann,
	Kishon Vijay Abraham I, devicetree, linux-kernel,
	linux-arm-kernel, linux-usb

On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> In addition to the PCIe and SATA PHYs, the XUSB pad controller also
> supports 3 UTMI, 2 HSIC, and 2 USB3 PHYs.  Each USB3 PHY uses a single
> PCIe or SATA lane and is mapped to one of the three UTMI ports.
>
> The xHCI controller will also send messages intended for the PHY driver,
> so request and listen for messages on the mailbox's PHY channel.

I'd like a review from Thierry here as the HW expert.

I need an ack from LinusW in order to take this pinctrl patch through 
the Tegra tree.

> diff --git a/drivers/pinctrl/pinctrl-tegra-xusb.c b/drivers/pinctrl/pinctrl-tegra-xusb.c

> +static int usb3_phy_power_on(struct phy *phy)
> +{
> +	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
> +	int port = usb3_phy_to_port(phy);
> +	int lane = padctl->usb3_ports[port].lane;
> +	u32 value, offset;
> +
> +	if (!is_pcie_or_sata_lane(lane)) {
> +		dev_err(padctl->dev, "USB3 PHY %d mapped to invalid lane: %d\n",
> +			port, lane);
> +		return -EINVAL;
> +	}

An aside: This implies that the SATA driver should be talking to this 
pinctrl driver and explicitly powering on the XUSB pins. However, the 
SATA driver doesn't depend on this series. I'm a bit confused how that 
works. Perhaps it's just by accident? Mikko, can you comment?

> +static int utmi_phy_to_port(struct phy *phy)
> +{
> +	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
> +	int i;
> +
> +	for (i = 0; i < TEGRA_XUSB_UTMI_PHYS; i++) {
> +		if (phy == padctl->phys[TEGRA_XUSB_PADCTL_UTMI_P0 + i])
> +			break;
> +	}
> +	BUG_ON(i == TEGRA_XUSB_UTMI_PHYS);

Can this be triggered by e.g. bad DT content? If so, returning an error 
would be nicer. The comment applies to other xxx_to_port() functions.

> @@ -896,6 +1933,22 @@ static int tegra_xusb_padctl_probe(struct platform_device *pdev)

> +	for (i = 0; i < TEGRA_XUSB_USB3_PHYS; i++) {
> +		char prop[sizeof("nvidia,usb3-port-N-lane")];
> +		u32 lane;
> +
> +		sprintf(prop, "nvidia,usb3-port-%d-lane", i);
> +		if (!of_property_read_u32(pdev->dev.of_node, prop, &lane)) {
> +			if (!is_pcie_or_sata_lane(lane)) {
> +				err = -EINVAL;
> +				goto unregister;

It'd be nice to print a message so that the user/developer knows what's 
wrong with the DT.

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

* [PATCH v2 4/9] pinctrl: tegra-xusb: Add USB PHY support
@ 2014-08-25 19:22       ` Stephen Warren
  0 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-25 19:22 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> In addition to the PCIe and SATA PHYs, the XUSB pad controller also
> supports 3 UTMI, 2 HSIC, and 2 USB3 PHYs.  Each USB3 PHY uses a single
> PCIe or SATA lane and is mapped to one of the three UTMI ports.
>
> The xHCI controller will also send messages intended for the PHY driver,
> so request and listen for messages on the mailbox's PHY channel.

I'd like a review from Thierry here as the HW expert.

I need an ack from LinusW in order to take this pinctrl patch through 
the Tegra tree.

> diff --git a/drivers/pinctrl/pinctrl-tegra-xusb.c b/drivers/pinctrl/pinctrl-tegra-xusb.c

> +static int usb3_phy_power_on(struct phy *phy)
> +{
> +	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
> +	int port = usb3_phy_to_port(phy);
> +	int lane = padctl->usb3_ports[port].lane;
> +	u32 value, offset;
> +
> +	if (!is_pcie_or_sata_lane(lane)) {
> +		dev_err(padctl->dev, "USB3 PHY %d mapped to invalid lane: %d\n",
> +			port, lane);
> +		return -EINVAL;
> +	}

An aside: This implies that the SATA driver should be talking to this 
pinctrl driver and explicitly powering on the XUSB pins. However, the 
SATA driver doesn't depend on this series. I'm a bit confused how that 
works. Perhaps it's just by accident? Mikko, can you comment?

> +static int utmi_phy_to_port(struct phy *phy)
> +{
> +	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
> +	int i;
> +
> +	for (i = 0; i < TEGRA_XUSB_UTMI_PHYS; i++) {
> +		if (phy == padctl->phys[TEGRA_XUSB_PADCTL_UTMI_P0 + i])
> +			break;
> +	}
> +	BUG_ON(i == TEGRA_XUSB_UTMI_PHYS);

Can this be triggered by e.g. bad DT content? If so, returning an error 
would be nicer. The comment applies to other xxx_to_port() functions.

> @@ -896,6 +1933,22 @@ static int tegra_xusb_padctl_probe(struct platform_device *pdev)

> +	for (i = 0; i < TEGRA_XUSB_USB3_PHYS; i++) {
> +		char prop[sizeof("nvidia,usb3-port-N-lane")];
> +		u32 lane;
> +
> +		sprintf(prop, "nvidia,usb3-port-%d-lane", i);
> +		if (!of_property_read_u32(pdev->dev.of_node, prop, &lane)) {
> +			if (!is_pcie_or_sata_lane(lane)) {
> +				err = -EINVAL;
> +				goto unregister;

It'd be nice to print a message so that the user/developer knows what's 
wrong with the DT.

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

* Re: [PATCH v2 5/9] of: Add NVIDIA Tegra xHCI controller binding
  2014-08-18 17:08   ` Andrew Bresticker
  (?)
@ 2014-08-25 19:26       ` Stephen Warren
  -1 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-25 19:26 UTC (permalink / raw)
  To: Andrew Bresticker, Thierry Reding, linux-tegra-u79uwXL29TY76Z2rM5mHXA
  Cc: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Jassi Brar, Linus Walleij, Greg Kroah-Hartman,
	Mathias Nyman, Grant Likely, Alan Stern, Arnd Bergmann,
	Kishon Vijay Abraham I, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA

On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> Add device-tree binding documentation for the xHCI controller present
> on Tegra124 and later SoCs.

> diff --git a/Documentation/devicetree/bindings/usb/nvidia,tegra124-xhci.txt b/Documentation/devicetree/bindings/usb/nvidia,tegra124-xhci.txt

> +Required properties:
> +--------------------

> + - mboxes: Must contain an entry for the XUSB host mailbox channel.
> +   See ../mailbox/mailbox.txt for details.

I'd like to use mbox-names here too.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 5/9] of: Add NVIDIA Tegra xHCI controller binding
@ 2014-08-25 19:26       ` Stephen Warren
  0 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-25 19:26 UTC (permalink / raw)
  To: Andrew Bresticker, Thierry Reding, linux-tegra
  Cc: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Jassi Brar, Linus Walleij, Greg Kroah-Hartman,
	Mathias Nyman, Grant Likely, Alan Stern, Arnd Bergmann,
	Kishon Vijay Abraham I, devicetree, linux-kernel,
	linux-arm-kernel, linux-usb

On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> Add device-tree binding documentation for the xHCI controller present
> on Tegra124 and later SoCs.

> diff --git a/Documentation/devicetree/bindings/usb/nvidia,tegra124-xhci.txt b/Documentation/devicetree/bindings/usb/nvidia,tegra124-xhci.txt

> +Required properties:
> +--------------------

> + - mboxes: Must contain an entry for the XUSB host mailbox channel.
> +   See ../mailbox/mailbox.txt for details.

I'd like to use mbox-names here too.

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

* [PATCH v2 5/9] of: Add NVIDIA Tegra xHCI controller binding
@ 2014-08-25 19:26       ` Stephen Warren
  0 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-25 19:26 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> Add device-tree binding documentation for the xHCI controller present
> on Tegra124 and later SoCs.

> diff --git a/Documentation/devicetree/bindings/usb/nvidia,tegra124-xhci.txt b/Documentation/devicetree/bindings/usb/nvidia,tegra124-xhci.txt

> +Required properties:
> +--------------------

> + - mboxes: Must contain an entry for the XUSB host mailbox channel.
> +   See ../mailbox/mailbox.txt for details.

I'd like to use mbox-names here too.

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

* Re: [PATCH v2 6/9] usb: xhci: Add NVIDIA Tegra xHCI host-controller driver
  2014-08-18 17:08   ` Andrew Bresticker
  (?)
@ 2014-08-25 19:36       ` Stephen Warren
  -1 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-25 19:36 UTC (permalink / raw)
  To: Andrew Bresticker, Thierry Reding, linux-tegra-u79uwXL29TY76Z2rM5mHXA
  Cc: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Jassi Brar, Linus Walleij, Greg Kroah-Hartman,
	Mathias Nyman, Grant Likely, Alan Stern, Arnd Bergmann,
	Kishon Vijay Abraham I, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA

On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> Add support for the on-chip xHCI host controller present on Tegra SoCs.
>
> The driver is currently very basic: it loads the controller with its
> firmware, starts the controller, and is able to service messages sent
> by the controller's firmware.  The hardware supports device mode as
> well as lower-power operating modes, but support for these is not yet
> implemented here.

Just one minor comment below.

I'd like an ack from a USB maintainer so that this patch can be taken 
through the Tegra tree along with the rest of the series, which has 
various dependencies.

> +MODULE_ALIAS("platform:xhci-tegra");

I don't think that's needed; MODULE_DEVICE_TABLE(of, 
tegra_xhci_of_match) should be enough upstream.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 6/9] usb: xhci: Add NVIDIA Tegra xHCI host-controller driver
@ 2014-08-25 19:36       ` Stephen Warren
  0 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-25 19:36 UTC (permalink / raw)
  To: Andrew Bresticker, Thierry Reding, linux-tegra
  Cc: Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Jassi Brar, Linus Walleij, Greg Kroah-Hartman,
	Mathias Nyman, Grant Likely, Alan Stern, Arnd Bergmann,
	Kishon Vijay Abraham I, devicetree, linux-kernel,
	linux-arm-kernel, linux-usb

On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> Add support for the on-chip xHCI host controller present on Tegra SoCs.
>
> The driver is currently very basic: it loads the controller with its
> firmware, starts the controller, and is able to service messages sent
> by the controller's firmware.  The hardware supports device mode as
> well as lower-power operating modes, but support for these is not yet
> implemented here.

Just one minor comment below.

I'd like an ack from a USB maintainer so that this patch can be taken 
through the Tegra tree along with the rest of the series, which has 
various dependencies.

> +MODULE_ALIAS("platform:xhci-tegra");

I don't think that's needed; MODULE_DEVICE_TABLE(of, 
tegra_xhci_of_match) should be enough upstream.

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

* [PATCH v2 6/9] usb: xhci: Add NVIDIA Tegra xHCI host-controller driver
@ 2014-08-25 19:36       ` Stephen Warren
  0 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-25 19:36 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> Add support for the on-chip xHCI host controller present on Tegra SoCs.
>
> The driver is currently very basic: it loads the controller with its
> firmware, starts the controller, and is able to service messages sent
> by the controller's firmware.  The hardware supports device mode as
> well as lower-power operating modes, but support for these is not yet
> implemented here.

Just one minor comment below.

I'd like an ack from a USB maintainer so that this patch can be taken 
through the Tegra tree along with the rest of the series, which has 
various dependencies.

> +MODULE_ALIAS("platform:xhci-tegra");

I don't think that's needed; MODULE_DEVICE_TABLE(of, 
tegra_xhci_of_match) should be enough upstream.

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

* Re: [PATCH 10/9] pinctrl: tegra-xusb: Support adjusted HS_CURR_LEVEL
       [not found]     ` <1408732088-28010-1-git-send-email-abrestic-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
@ 2014-08-25 19:39       ` Stephen Warren
  0 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-25 19:39 UTC (permalink / raw)
  To: Andrew Bresticker, Tomeu Vizoso, Thierry Reding
  Cc: linux-tegra-u79uwXL29TY76Z2rM5mHXA

On 08/22/2014 12:28 PM, Andrew Bresticker wrote:
> On some boards, e.g. Blaze, the fused per-UTMI pad HS_CURR_LEVEL value
> must be adjusted before being applied.  Add support for a new pinconfig
> property "nvidia,otg-hs-curr-level-offset" which will apply the specified
> offset to the fused HS_CURR_LEVEL value.

I'd like a review from Thierry on this one too.

Patches 7-10 seem OK to me.

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
  2014-08-25 19:01       ` Stephen Warren
  (?)
@ 2014-08-26  6:57           ` Thierry Reding
  -1 siblings, 0 replies; 141+ messages in thread
From: Thierry Reding @ 2014-08-26  6:57 UTC (permalink / raw)
  To: Stephen Warren
  Cc: Andrew Bresticker, linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Jassi Brar, Linus Walleij, Greg Kroah-Hartman,
	Mathias Nyman, Grant Likely, Alan Stern, Arnd Bergmann,
	Kishon Vijay Abraham I, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA

[-- Attachment #1: Type: text/plain, Size: 894 bytes --]

On Mon, Aug 25, 2014 at 01:01:52PM -0600, Stephen Warren wrote:
> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
[...]
> >+static int tegra_xusb_mbox_probe(struct platform_device *pdev)
> 
> >+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> >+	if (!res)
> >+		return -ENODEV;
> 
> Should devm_request_mem_region() be called here to claim the region?
> 
> >+	mbox->regs = devm_ioremap_nocache(&pdev->dev, res->start,
> >+					  resource_size(res));
> >+	if (!mbox->regs)
> >+		return -ENOMEM;
> 
> Is _nocache required? I don't see other drivers using it. I assume there's
> nothing special about the mbox registers.

Most drivers should be using devm_ioremap_resource() which will use the
_nocache variant of devm_ioremap() when appropriate. Usually the region
will not be marked cacheable (IORESOURCE_CACHEABLE) and therefore be
remapped uncached.

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-26  6:57           ` Thierry Reding
  0 siblings, 0 replies; 141+ messages in thread
From: Thierry Reding @ 2014-08-26  6:57 UTC (permalink / raw)
  To: Stephen Warren
  Cc: Andrew Bresticker, linux-tegra, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King, Jassi Brar,
	Linus Walleij, Greg Kroah-Hartman, Mathias Nyman, Grant Likely,
	Alan Stern, Arnd Bergmann, Kishon Vijay Abraham I, devicetree,
	linux-kernel, linux-arm-kernel, linux-usb

[-- Attachment #1: Type: text/plain, Size: 894 bytes --]

On Mon, Aug 25, 2014 at 01:01:52PM -0600, Stephen Warren wrote:
> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
[...]
> >+static int tegra_xusb_mbox_probe(struct platform_device *pdev)
> 
> >+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> >+	if (!res)
> >+		return -ENODEV;
> 
> Should devm_request_mem_region() be called here to claim the region?
> 
> >+	mbox->regs = devm_ioremap_nocache(&pdev->dev, res->start,
> >+					  resource_size(res));
> >+	if (!mbox->regs)
> >+		return -ENOMEM;
> 
> Is _nocache required? I don't see other drivers using it. I assume there's
> nothing special about the mbox registers.

Most drivers should be using devm_ioremap_resource() which will use the
_nocache variant of devm_ioremap() when appropriate. Usually the region
will not be marked cacheable (IORESOURCE_CACHEABLE) and therefore be
remapped uncached.

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

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

* [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-26  6:57           ` Thierry Reding
  0 siblings, 0 replies; 141+ messages in thread
From: Thierry Reding @ 2014-08-26  6:57 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Aug 25, 2014 at 01:01:52PM -0600, Stephen Warren wrote:
> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
[...]
> >+static int tegra_xusb_mbox_probe(struct platform_device *pdev)
> 
> >+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> >+	if (!res)
> >+		return -ENODEV;
> 
> Should devm_request_mem_region() be called here to claim the region?
> 
> >+	mbox->regs = devm_ioremap_nocache(&pdev->dev, res->start,
> >+					  resource_size(res));
> >+	if (!mbox->regs)
> >+		return -ENOMEM;
> 
> Is _nocache required? I don't see other drivers using it. I assume there's
> nothing special about the mbox registers.

Most drivers should be using devm_ioremap_resource() which will use the
_nocache variant of devm_ioremap() when appropriate. Usually the region
will not be marked cacheable (IORESOURCE_CACHEABLE) and therefore be
remapped uncached.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140826/1b4b4e30/attachment.sig>

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

* Re: [PATCH v2 4/9] pinctrl: tegra-xusb: Add USB PHY support
  2014-08-25 19:22       ` Stephen Warren
  (?)
@ 2014-08-26  7:29         ` Mikko Perttunen
  -1 siblings, 0 replies; 141+ messages in thread
From: Mikko Perttunen @ 2014-08-26  7:29 UTC (permalink / raw)
  To: Stephen Warren, Andrew Bresticker, Thierry Reding, Linus Walleij
  Cc: linux-tegra, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala, Russell King, Jassi Brar, Greg Kroah-Hartman,
	Mathias Nyman, Grant Likely, Alan Stern, Arnd Bergmann,
	Kishon Vijay Abraham I, devicetree, linux-kernel,
	linux-arm-kernel, linux-usb

On 25/08/14 22:22, Stephen Warren wrote:
> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>> In addition to the PCIe and SATA PHYs, the XUSB pad controller also
>> supports 3 UTMI, 2 HSIC, and 2 USB3 PHYs.  Each USB3 PHY uses a single
>> PCIe or SATA lane and is mapped to one of the three UTMI ports.
>>
>> The xHCI controller will also send messages intended for the PHY driver,
>> so request and listen for messages on the mailbox's PHY channel.
>
> I'd like a review from Thierry here as the HW expert.
>
> I need an ack from LinusW in order to take this pinctrl patch through
> the Tegra tree.
>
>> diff --git a/drivers/pinctrl/pinctrl-tegra-xusb.c
>> b/drivers/pinctrl/pinctrl-tegra-xusb.c
>
>> +static int usb3_phy_power_on(struct phy *phy)
>> +{
>> +    struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
>> +    int port = usb3_phy_to_port(phy);
>> +    int lane = padctl->usb3_ports[port].lane;
>> +    u32 value, offset;
>> +
>> +    if (!is_pcie_or_sata_lane(lane)) {
>> +        dev_err(padctl->dev, "USB3 PHY %d mapped to invalid lane: %d\n",
>> +            port, lane);
>> +        return -EINVAL;
>> +    }
>
> An aside: This implies that the SATA driver should be talking to this
> pinctrl driver and explicitly powering on the XUSB pins. However, the
> SATA driver doesn't depend on this series. I'm a bit confused how that
> works. Perhaps it's just by accident? Mikko, can you comment?

The SATA driver does depend on the pinctrl-tegra-xusb driver to power on 
the SATA lane. It looks like what this patch does is it adds support for 
using the SATA pad for USB3, in which case the SATA lane also needs to 
be powered on. At least that's the understanding I got from a quick read.

Mikko

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

* Re: [PATCH v2 4/9] pinctrl: tegra-xusb: Add USB PHY support
@ 2014-08-26  7:29         ` Mikko Perttunen
  0 siblings, 0 replies; 141+ messages in thread
From: Mikko Perttunen @ 2014-08-26  7:29 UTC (permalink / raw)
  To: Stephen Warren, Andrew Bresticker, Thierry Reding, Linus Walleij
  Cc: linux-tegra, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala, Russell King, Jassi Brar, Greg Kroah-Hartman,
	Mathias Nyman, Grant Likely, Alan Stern, Arnd Bergmann,
	Kishon Vijay Abraham I, devicetree, linux-kernel,
	linux-arm-kernel, linux-usb

On 25/08/14 22:22, Stephen Warren wrote:
> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>> In addition to the PCIe and SATA PHYs, the XUSB pad controller also
>> supports 3 UTMI, 2 HSIC, and 2 USB3 PHYs.  Each USB3 PHY uses a single
>> PCIe or SATA lane and is mapped to one of the three UTMI ports.
>>
>> The xHCI controller will also send messages intended for the PHY driver,
>> so request and listen for messages on the mailbox's PHY channel.
>
> I'd like a review from Thierry here as the HW expert.
>
> I need an ack from LinusW in order to take this pinctrl patch through
> the Tegra tree.
>
>> diff --git a/drivers/pinctrl/pinctrl-tegra-xusb.c
>> b/drivers/pinctrl/pinctrl-tegra-xusb.c
>
>> +static int usb3_phy_power_on(struct phy *phy)
>> +{
>> +    struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
>> +    int port = usb3_phy_to_port(phy);
>> +    int lane = padctl->usb3_ports[port].lane;
>> +    u32 value, offset;
>> +
>> +    if (!is_pcie_or_sata_lane(lane)) {
>> +        dev_err(padctl->dev, "USB3 PHY %d mapped to invalid lane: %d\n",
>> +            port, lane);
>> +        return -EINVAL;
>> +    }
>
> An aside: This implies that the SATA driver should be talking to this
> pinctrl driver and explicitly powering on the XUSB pins. However, the
> SATA driver doesn't depend on this series. I'm a bit confused how that
> works. Perhaps it's just by accident? Mikko, can you comment?

The SATA driver does depend on the pinctrl-tegra-xusb driver to power on 
the SATA lane. It looks like what this patch does is it adds support for 
using the SATA pad for USB3, in which case the SATA lane also needs to 
be powered on. At least that's the understanding I got from a quick read.

Mikko

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

* [PATCH v2 4/9] pinctrl: tegra-xusb: Add USB PHY support
@ 2014-08-26  7:29         ` Mikko Perttunen
  0 siblings, 0 replies; 141+ messages in thread
From: Mikko Perttunen @ 2014-08-26  7:29 UTC (permalink / raw)
  To: linux-arm-kernel

On 25/08/14 22:22, Stephen Warren wrote:
> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>> In addition to the PCIe and SATA PHYs, the XUSB pad controller also
>> supports 3 UTMI, 2 HSIC, and 2 USB3 PHYs.  Each USB3 PHY uses a single
>> PCIe or SATA lane and is mapped to one of the three UTMI ports.
>>
>> The xHCI controller will also send messages intended for the PHY driver,
>> so request and listen for messages on the mailbox's PHY channel.
>
> I'd like a review from Thierry here as the HW expert.
>
> I need an ack from LinusW in order to take this pinctrl patch through
> the Tegra tree.
>
>> diff --git a/drivers/pinctrl/pinctrl-tegra-xusb.c
>> b/drivers/pinctrl/pinctrl-tegra-xusb.c
>
>> +static int usb3_phy_power_on(struct phy *phy)
>> +{
>> +    struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
>> +    int port = usb3_phy_to_port(phy);
>> +    int lane = padctl->usb3_ports[port].lane;
>> +    u32 value, offset;
>> +
>> +    if (!is_pcie_or_sata_lane(lane)) {
>> +        dev_err(padctl->dev, "USB3 PHY %d mapped to invalid lane: %d\n",
>> +            port, lane);
>> +        return -EINVAL;
>> +    }
>
> An aside: This implies that the SATA driver should be talking to this
> pinctrl driver and explicitly powering on the XUSB pins. However, the
> SATA driver doesn't depend on this series. I'm a bit confused how that
> works. Perhaps it's just by accident? Mikko, can you comment?

The SATA driver does depend on the pinctrl-tegra-xusb driver to power on 
the SATA lane. It looks like what this patch does is it adds support for 
using the SATA pad for USB3, in which case the SATA lane also needs to 
be powered on. At least that's the understanding I got from a quick read.

Mikko

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
  2014-08-26  6:57           ` Thierry Reding
  (?)
@ 2014-08-26  7:43             ` Arnd Bergmann
  -1 siblings, 0 replies; 141+ messages in thread
From: Arnd Bergmann @ 2014-08-26  7:43 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Stephen Warren, Andrew Bresticker,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King, Jassi Brar,
	Linus Walleij, Greg Kroah-Hartman, Mathias Nyman, Grant Likely,
	Alan Stern, Kishon Vijay Abraham I,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA

On Tuesday 26 August 2014 08:57:31 Thierry Reding wrote:
> On Mon, Aug 25, 2014 at 01:01:52PM -0600, Stephen Warren wrote:
> > On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> [...]
> > >+static int tegra_xusb_mbox_probe(struct platform_device *pdev)
> > 
> > >+    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > >+    if (!res)
> > >+            return -ENODEV;
> > 
> > Should devm_request_mem_region() be called here to claim the region?
> > 
> > >+    mbox->regs = devm_ioremap_nocache(&pdev->dev, res->start,
> > >+                                      resource_size(res));
> > >+    if (!mbox->regs)
> > >+            return -ENOMEM;
> > 
> > Is _nocache required? I don't see other drivers using it. I assume there's
> > nothing special about the mbox registers.
> 
> Most drivers should be using devm_ioremap_resource() which will use the
> _nocache variant of devm_ioremap() when appropriate. Usually the region
> will not be marked cacheable (IORESOURCE_CACHEABLE) and therefore be
> remapped uncached.
> 

Note that ioremap() and ioremap_nocache() are the same. We really shouldn't
ever call ioremap_nocache().

devm_ioremap_resource() and pci_iomap() checking for IORESOURCE_CACHEABLE is
rather silly, since it doesn't call ioremap_cache() in that case.

	Arnd
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-26  7:43             ` Arnd Bergmann
  0 siblings, 0 replies; 141+ messages in thread
From: Arnd Bergmann @ 2014-08-26  7:43 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Stephen Warren, Andrew Bresticker, linux-tegra, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Jassi Brar, Linus Walleij, Greg Kroah-Hartman, Mathias Nyman,
	Grant Likely, Alan Stern, Kishon Vijay Abraham I, devicetree,
	linux-kernel, linux-arm-kernel, linux-usb

On Tuesday 26 August 2014 08:57:31 Thierry Reding wrote:
> On Mon, Aug 25, 2014 at 01:01:52PM -0600, Stephen Warren wrote:
> > On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> [...]
> > >+static int tegra_xusb_mbox_probe(struct platform_device *pdev)
> > 
> > >+    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > >+    if (!res)
> > >+            return -ENODEV;
> > 
> > Should devm_request_mem_region() be called here to claim the region?
> > 
> > >+    mbox->regs = devm_ioremap_nocache(&pdev->dev, res->start,
> > >+                                      resource_size(res));
> > >+    if (!mbox->regs)
> > >+            return -ENOMEM;
> > 
> > Is _nocache required? I don't see other drivers using it. I assume there's
> > nothing special about the mbox registers.
> 
> Most drivers should be using devm_ioremap_resource() which will use the
> _nocache variant of devm_ioremap() when appropriate. Usually the region
> will not be marked cacheable (IORESOURCE_CACHEABLE) and therefore be
> remapped uncached.
> 

Note that ioremap() and ioremap_nocache() are the same. We really shouldn't
ever call ioremap_nocache().

devm_ioremap_resource() and pci_iomap() checking for IORESOURCE_CACHEABLE is
rather silly, since it doesn't call ioremap_cache() in that case.

	Arnd

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

* [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-26  7:43             ` Arnd Bergmann
  0 siblings, 0 replies; 141+ messages in thread
From: Arnd Bergmann @ 2014-08-26  7:43 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday 26 August 2014 08:57:31 Thierry Reding wrote:
> On Mon, Aug 25, 2014 at 01:01:52PM -0600, Stephen Warren wrote:
> > On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> [...]
> > >+static int tegra_xusb_mbox_probe(struct platform_device *pdev)
> > 
> > >+    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > >+    if (!res)
> > >+            return -ENODEV;
> > 
> > Should devm_request_mem_region() be called here to claim the region?
> > 
> > >+    mbox->regs = devm_ioremap_nocache(&pdev->dev, res->start,
> > >+                                      resource_size(res));
> > >+    if (!mbox->regs)
> > >+            return -ENOMEM;
> > 
> > Is _nocache required? I don't see other drivers using it. I assume there's
> > nothing special about the mbox registers.
> 
> Most drivers should be using devm_ioremap_resource() which will use the
> _nocache variant of devm_ioremap() when appropriate. Usually the region
> will not be marked cacheable (IORESOURCE_CACHEABLE) and therefore be
> remapped uncached.
> 

Note that ioremap() and ioremap_nocache() are the same. We really shouldn't
ever call ioremap_nocache().

devm_ioremap_resource() and pci_iomap() checking for IORESOURCE_CACHEABLE is
rather silly, since it doesn't call ioremap_cache() in that case.

	Arnd

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
  2014-08-26  7:43             ` Arnd Bergmann
  (?)
@ 2014-08-26  7:50               ` Thierry Reding
  -1 siblings, 0 replies; 141+ messages in thread
From: Thierry Reding @ 2014-08-26  7:50 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Stephen Warren, Andrew Bresticker,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King, Jassi Brar,
	Linus Walleij, Greg Kroah-Hartman, Mathias Nyman, Grant Likely,
	Alan Stern, Kishon Vijay Abraham I,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA

[-- Attachment #1: Type: text/plain, Size: 1618 bytes --]

On Tue, Aug 26, 2014 at 09:43:50AM +0200, Arnd Bergmann wrote:
> On Tuesday 26 August 2014 08:57:31 Thierry Reding wrote:
> > On Mon, Aug 25, 2014 at 01:01:52PM -0600, Stephen Warren wrote:
> > > On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> > [...]
> > > >+static int tegra_xusb_mbox_probe(struct platform_device *pdev)
> > > 
> > > >+    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > > >+    if (!res)
> > > >+            return -ENODEV;
> > > 
> > > Should devm_request_mem_region() be called here to claim the region?
> > > 
> > > >+    mbox->regs = devm_ioremap_nocache(&pdev->dev, res->start,
> > > >+                                      resource_size(res));
> > > >+    if (!mbox->regs)
> > > >+            return -ENOMEM;
> > > 
> > > Is _nocache required? I don't see other drivers using it. I assume there's
> > > nothing special about the mbox registers.
> > 
> > Most drivers should be using devm_ioremap_resource() which will use the
> > _nocache variant of devm_ioremap() when appropriate. Usually the region
> > will not be marked cacheable (IORESOURCE_CACHEABLE) and therefore be
> > remapped uncached.
> > 
> 
> Note that ioremap() and ioremap_nocache() are the same. We really shouldn't
> ever call ioremap_nocache().

Perhaps we should remove ioremap_nocache() in that case. Or ioremap(),
really, and keep only those variants that do what they claim to do.

> devm_ioremap_resource() and pci_iomap() checking for IORESOURCE_CACHEABLE is
> rather silly, since it doesn't call ioremap_cache() in that case.

Then that should be fixed.

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-26  7:50               ` Thierry Reding
  0 siblings, 0 replies; 141+ messages in thread
From: Thierry Reding @ 2014-08-26  7:50 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Stephen Warren, Andrew Bresticker, linux-tegra, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Jassi Brar, Linus Walleij, Greg Kroah-Hartman, Mathias Nyman,
	Grant Likely, Alan Stern, Kishon Vijay Abraham I, devicetree,
	linux-kernel, linux-arm-kernel, linux-usb

[-- Attachment #1: Type: text/plain, Size: 1618 bytes --]

On Tue, Aug 26, 2014 at 09:43:50AM +0200, Arnd Bergmann wrote:
> On Tuesday 26 August 2014 08:57:31 Thierry Reding wrote:
> > On Mon, Aug 25, 2014 at 01:01:52PM -0600, Stephen Warren wrote:
> > > On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> > [...]
> > > >+static int tegra_xusb_mbox_probe(struct platform_device *pdev)
> > > 
> > > >+    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > > >+    if (!res)
> > > >+            return -ENODEV;
> > > 
> > > Should devm_request_mem_region() be called here to claim the region?
> > > 
> > > >+    mbox->regs = devm_ioremap_nocache(&pdev->dev, res->start,
> > > >+                                      resource_size(res));
> > > >+    if (!mbox->regs)
> > > >+            return -ENOMEM;
> > > 
> > > Is _nocache required? I don't see other drivers using it. I assume there's
> > > nothing special about the mbox registers.
> > 
> > Most drivers should be using devm_ioremap_resource() which will use the
> > _nocache variant of devm_ioremap() when appropriate. Usually the region
> > will not be marked cacheable (IORESOURCE_CACHEABLE) and therefore be
> > remapped uncached.
> > 
> 
> Note that ioremap() and ioremap_nocache() are the same. We really shouldn't
> ever call ioremap_nocache().

Perhaps we should remove ioremap_nocache() in that case. Or ioremap(),
really, and keep only those variants that do what they claim to do.

> devm_ioremap_resource() and pci_iomap() checking for IORESOURCE_CACHEABLE is
> rather silly, since it doesn't call ioremap_cache() in that case.

Then that should be fixed.

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

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

* [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-26  7:50               ` Thierry Reding
  0 siblings, 0 replies; 141+ messages in thread
From: Thierry Reding @ 2014-08-26  7:50 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Aug 26, 2014 at 09:43:50AM +0200, Arnd Bergmann wrote:
> On Tuesday 26 August 2014 08:57:31 Thierry Reding wrote:
> > On Mon, Aug 25, 2014 at 01:01:52PM -0600, Stephen Warren wrote:
> > > On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> > [...]
> > > >+static int tegra_xusb_mbox_probe(struct platform_device *pdev)
> > > 
> > > >+    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > > >+    if (!res)
> > > >+            return -ENODEV;
> > > 
> > > Should devm_request_mem_region() be called here to claim the region?
> > > 
> > > >+    mbox->regs = devm_ioremap_nocache(&pdev->dev, res->start,
> > > >+                                      resource_size(res));
> > > >+    if (!mbox->regs)
> > > >+            return -ENOMEM;
> > > 
> > > Is _nocache required? I don't see other drivers using it. I assume there's
> > > nothing special about the mbox registers.
> > 
> > Most drivers should be using devm_ioremap_resource() which will use the
> > _nocache variant of devm_ioremap() when appropriate. Usually the region
> > will not be marked cacheable (IORESOURCE_CACHEABLE) and therefore be
> > remapped uncached.
> > 
> 
> Note that ioremap() and ioremap_nocache() are the same. We really shouldn't
> ever call ioremap_nocache().

Perhaps we should remove ioremap_nocache() in that case. Or ioremap(),
really, and keep only those variants that do what they claim to do.

> devm_ioremap_resource() and pci_iomap() checking for IORESOURCE_CACHEABLE is
> rather silly, since it doesn't call ioremap_cache() in that case.

Then that should be fixed.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140826/a91ef206/attachment.sig>

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
  2014-08-26  7:50               ` Thierry Reding
  (?)
@ 2014-08-26  8:09                 ` Arnd Bergmann
  -1 siblings, 0 replies; 141+ messages in thread
From: Arnd Bergmann @ 2014-08-26  8:09 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Stephen Warren, Andrew Bresticker,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King, Jassi Brar,
	Linus Walleij, Greg Kroah-Hartman, Mathias Nyman, Grant Likely,
	Alan Stern, Kishon Vijay Abraham I,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA, Jonas Bonn, David Howells,
	Koichi Yasutake

On Tuesday 26 August 2014 09:50:25 Thierry Reding wrote:
> On Tue, Aug 26, 2014 at 09:43:50AM +0200, Arnd Bergmann wrote:
> > On Tuesday 26 August 2014 08:57:31 Thierry Reding wrote:
> > > On Mon, Aug 25, 2014 at 01:01:52PM -0600, Stephen Warren wrote:
> > > > On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> > > [...]
> > > > >+static int tegra_xusb_mbox_probe(struct platform_device *pdev)
> > > > 
> > > > >+    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > > > >+    if (!res)
> > > > >+            return -ENODEV;
> > > > 
> > > > Should devm_request_mem_region() be called here to claim the region?
> > > > 
> > > > >+    mbox->regs = devm_ioremap_nocache(&pdev->dev, res->start,
> > > > >+                                      resource_size(res));
> > > > >+    if (!mbox->regs)
> > > > >+            return -ENOMEM;
> > > > 
> > > > Is _nocache required? I don't see other drivers using it. I assume there's
> > > > nothing special about the mbox registers.
> > > 
> > > Most drivers should be using devm_ioremap_resource() which will use the
> > > _nocache variant of devm_ioremap() when appropriate. Usually the region
> > > will not be marked cacheable (IORESOURCE_CACHEABLE) and therefore be
> > > remapped uncached.
> > > 
> > 
> > Note that ioremap() and ioremap_nocache() are the same. We really shouldn't
> > ever call ioremap_nocache().
> 
> Perhaps we should remove ioremap_nocache() in that case. Or ioremap(),
> really, and keep only those variants that do what they claim to do.

That would be good, but there are many instances of either one:

arnd@wuerfel:/git/arm-soc$ git grep -w ioremap | wc
   2156   13402  183732
arnd@wuerfel:/git/arm-soc$ git grep -w ioremap_nocache | wc
    485    2529   42955

FWIW, I just looked through all architectures and found three on
which ioremap and ioremap_nocache are not the same, and ioremap
defaults to cacheable:

- OpenRISC so far only supports running in a simulator, so this
  is likely to be a bug that will get hit on actual hardware with
  MMIO. Jonas should probably look into this.

- mn10300 has no MMU and doesn't really use ioremap, but it should
  still be fixed for PCI drivers using it on the one board that
  supports PCI.

- cris seems to have been broken forever.

> > devm_ioremap_resource() and pci_iomap() checking for IORESOURCE_CACHEABLE is
> > rather silly, since it doesn't call ioremap_cache() in that case.
> 
> Then that should be fixed.

Yes. I'd suggest we just ignore that flag and always call ioremap here.

When I checked this before, IORESOURCE_CACHEABLE only ever gets set for
PCI ROM BARs, which we don't map into the kernel.

	Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-26  8:09                 ` Arnd Bergmann
  0 siblings, 0 replies; 141+ messages in thread
From: Arnd Bergmann @ 2014-08-26  8:09 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Stephen Warren, Andrew Bresticker, linux-tegra, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Jassi Brar, Linus Walleij, Greg Kroah-Hartman, Mathias Nyman,
	Grant Likely, Alan Stern, Kishon Vijay Abraham I, devicetree,
	linux-kernel, linux-arm-kernel, linux-usb, Jonas Bonn,
	David Howells, Koichi Yasutake

On Tuesday 26 August 2014 09:50:25 Thierry Reding wrote:
> On Tue, Aug 26, 2014 at 09:43:50AM +0200, Arnd Bergmann wrote:
> > On Tuesday 26 August 2014 08:57:31 Thierry Reding wrote:
> > > On Mon, Aug 25, 2014 at 01:01:52PM -0600, Stephen Warren wrote:
> > > > On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> > > [...]
> > > > >+static int tegra_xusb_mbox_probe(struct platform_device *pdev)
> > > > 
> > > > >+    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > > > >+    if (!res)
> > > > >+            return -ENODEV;
> > > > 
> > > > Should devm_request_mem_region() be called here to claim the region?
> > > > 
> > > > >+    mbox->regs = devm_ioremap_nocache(&pdev->dev, res->start,
> > > > >+                                      resource_size(res));
> > > > >+    if (!mbox->regs)
> > > > >+            return -ENOMEM;
> > > > 
> > > > Is _nocache required? I don't see other drivers using it. I assume there's
> > > > nothing special about the mbox registers.
> > > 
> > > Most drivers should be using devm_ioremap_resource() which will use the
> > > _nocache variant of devm_ioremap() when appropriate. Usually the region
> > > will not be marked cacheable (IORESOURCE_CACHEABLE) and therefore be
> > > remapped uncached.
> > > 
> > 
> > Note that ioremap() and ioremap_nocache() are the same. We really shouldn't
> > ever call ioremap_nocache().
> 
> Perhaps we should remove ioremap_nocache() in that case. Or ioremap(),
> really, and keep only those variants that do what they claim to do.

That would be good, but there are many instances of either one:

arnd@wuerfel:/git/arm-soc$ git grep -w ioremap | wc
   2156   13402  183732
arnd@wuerfel:/git/arm-soc$ git grep -w ioremap_nocache | wc
    485    2529   42955

FWIW, I just looked through all architectures and found three on
which ioremap and ioremap_nocache are not the same, and ioremap
defaults to cacheable:

- OpenRISC so far only supports running in a simulator, so this
  is likely to be a bug that will get hit on actual hardware with
  MMIO. Jonas should probably look into this.

- mn10300 has no MMU and doesn't really use ioremap, but it should
  still be fixed for PCI drivers using it on the one board that
  supports PCI.

- cris seems to have been broken forever.

> > devm_ioremap_resource() and pci_iomap() checking for IORESOURCE_CACHEABLE is
> > rather silly, since it doesn't call ioremap_cache() in that case.
> 
> Then that should be fixed.

Yes. I'd suggest we just ignore that flag and always call ioremap here.

When I checked this before, IORESOURCE_CACHEABLE only ever gets set for
PCI ROM BARs, which we don't map into the kernel.

	Arnd

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

* [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-26  8:09                 ` Arnd Bergmann
  0 siblings, 0 replies; 141+ messages in thread
From: Arnd Bergmann @ 2014-08-26  8:09 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday 26 August 2014 09:50:25 Thierry Reding wrote:
> On Tue, Aug 26, 2014 at 09:43:50AM +0200, Arnd Bergmann wrote:
> > On Tuesday 26 August 2014 08:57:31 Thierry Reding wrote:
> > > On Mon, Aug 25, 2014 at 01:01:52PM -0600, Stephen Warren wrote:
> > > > On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> > > [...]
> > > > >+static int tegra_xusb_mbox_probe(struct platform_device *pdev)
> > > > 
> > > > >+    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > > > >+    if (!res)
> > > > >+            return -ENODEV;
> > > > 
> > > > Should devm_request_mem_region() be called here to claim the region?
> > > > 
> > > > >+    mbox->regs = devm_ioremap_nocache(&pdev->dev, res->start,
> > > > >+                                      resource_size(res));
> > > > >+    if (!mbox->regs)
> > > > >+            return -ENOMEM;
> > > > 
> > > > Is _nocache required? I don't see other drivers using it. I assume there's
> > > > nothing special about the mbox registers.
> > > 
> > > Most drivers should be using devm_ioremap_resource() which will use the
> > > _nocache variant of devm_ioremap() when appropriate. Usually the region
> > > will not be marked cacheable (IORESOURCE_CACHEABLE) and therefore be
> > > remapped uncached.
> > > 
> > 
> > Note that ioremap() and ioremap_nocache() are the same. We really shouldn't
> > ever call ioremap_nocache().
> 
> Perhaps we should remove ioremap_nocache() in that case. Or ioremap(),
> really, and keep only those variants that do what they claim to do.

That would be good, but there are many instances of either one:

arnd at wuerfel:/git/arm-soc$ git grep -w ioremap | wc
   2156   13402  183732
arnd at wuerfel:/git/arm-soc$ git grep -w ioremap_nocache | wc
    485    2529   42955

FWIW, I just looked through all architectures and found three on
which ioremap and ioremap_nocache are not the same, and ioremap
defaults to cacheable:

- OpenRISC so far only supports running in a simulator, so this
  is likely to be a bug that will get hit on actual hardware with
  MMIO. Jonas should probably look into this.

- mn10300 has no MMU and doesn't really use ioremap, but it should
  still be fixed for PCI drivers using it on the one board that
  supports PCI.

- cris seems to have been broken forever.

> > devm_ioremap_resource() and pci_iomap() checking for IORESOURCE_CACHEABLE is
> > rather silly, since it doesn't call ioremap_cache() in that case.
> 
> Then that should be fixed.

Yes. I'd suggest we just ignore that flag and always call ioremap here.

When I checked this before, IORESOURCE_CACHEABLE only ever gets set for
PCI ROM BARs, which we don't map into the kernel.

	Arnd

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

* RE: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
  2014-08-26  6:57           ` Thierry Reding
  (?)
@ 2014-08-26  8:54             ` David Laight
  -1 siblings, 0 replies; 141+ messages in thread
From: David Laight @ 2014-08-26  8:54 UTC (permalink / raw)
  To: 'Thierry Reding', Stephen Warren
  Cc: Andrew Bresticker, linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Jassi Brar, Linus Walleij, Greg Kroah-Hartman,
	Mathias Nyman, Grant Likely, Alan Stern, Arnd Bergmann,
	Kishon Vijay Abraham I, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29Tb/PtFMR13I2A

From: Thierry Reding
...
> > Is _nocache required? I don't see other drivers using it. I assume there's
> > nothing special about the mbox registers.
> 
> Most drivers should be using devm_ioremap_resource() which will use the
> _nocache variant of devm_ioremap() when appropriate. Usually the region
> will not be marked cacheable (IORESOURCE_CACHEABLE) and therefore be
> remapped uncached.

A related question:
Is there any way for a driver to force that part of a PCIe BAR be mapped
through the data cache even when the BAR isn't actually marked cacheable?

Some hardware has address regions (which might not be an entire BAR)
that are actually memory and mapping through the data cache will
generate longer PCIe transfers [1].
Clearly the driver will have to be very careful about cache flushes
and invalidates to make this work.

[1] PCIe is high throughput and high latency, single word reads can
be much slower that PCI, much nearer x86 ISA bus speeds.

	David



--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* RE: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-26  8:54             ` David Laight
  0 siblings, 0 replies; 141+ messages in thread
From: David Laight @ 2014-08-26  8:54 UTC (permalink / raw)
  To: 'Thierry Reding', Stephen Warren
  Cc: Andrew Bresticker, linux-tegra, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King, Jassi Brar,
	Linus Walleij, Greg Kroah-Hartman, Mathias Nyman, Grant Likely,
	Alan Stern, Arnd Bergmann, Kishon Vijay Abraham I, devicetree,
	linux-kernel, linux-arm-kernel, linux-usb

From: Thierry Reding
...
> > Is _nocache required? I don't see other drivers using it. I assume there's
> > nothing special about the mbox registers.
> 
> Most drivers should be using devm_ioremap_resource() which will use the
> _nocache variant of devm_ioremap() when appropriate. Usually the region
> will not be marked cacheable (IORESOURCE_CACHEABLE) and therefore be
> remapped uncached.

A related question:
Is there any way for a driver to force that part of a PCIe BAR be mapped
through the data cache even when the BAR isn't actually marked cacheable?

Some hardware has address regions (which might not be an entire BAR)
that are actually memory and mapping through the data cache will
generate longer PCIe transfers [1].
Clearly the driver will have to be very careful about cache flushes
and invalidates to make this work.

[1] PCIe is high throughput and high latency, single word reads can
be much slower that PCI, much nearer x86 ISA bus speeds.

	David




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

* [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-26  8:54             ` David Laight
  0 siblings, 0 replies; 141+ messages in thread
From: David Laight @ 2014-08-26  8:54 UTC (permalink / raw)
  To: linux-arm-kernel

From: Thierry Reding
...
> > Is _nocache required? I don't see other drivers using it. I assume there's
> > nothing special about the mbox registers.
> 
> Most drivers should be using devm_ioremap_resource() which will use the
> _nocache variant of devm_ioremap() when appropriate. Usually the region
> will not be marked cacheable (IORESOURCE_CACHEABLE) and therefore be
> remapped uncached.

A related question:
Is there any way for a driver to force that part of a PCIe BAR be mapped
through the data cache even when the BAR isn't actually marked cacheable?

Some hardware has address regions (which might not be an entire BAR)
that are actually memory and mapping through the data cache will
generate longer PCIe transfers [1].
Clearly the driver will have to be very careful about cache flushes
and invalidates to make this work.

[1] PCIe is high throughput and high latency, single word reads can
be much slower that PCI, much nearer x86 ISA bus speeds.

	David

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
  2014-08-26  8:09                 ` Arnd Bergmann
@ 2014-08-26  9:08                   ` Thierry Reding
  -1 siblings, 0 replies; 141+ messages in thread
From: Thierry Reding @ 2014-08-26  9:08 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Stephen Warren, Andrew Bresticker, linux-tegra, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Jassi Brar, Linus Walleij, Greg Kroah-Hartman, Mathias Nyman,
	Grant Likely, Alan Stern, Kishon Vijay Abraham I, devicetree,
	linux-kernel, linux-arm-kernel, linux-usb, Jonas Bonn,
	David Howells, Koichi Yasutake

[-- Attachment #1: Type: text/plain, Size: 2786 bytes --]

On Tue, Aug 26, 2014 at 10:09:25AM +0200, Arnd Bergmann wrote:
> On Tuesday 26 August 2014 09:50:25 Thierry Reding wrote:
> > On Tue, Aug 26, 2014 at 09:43:50AM +0200, Arnd Bergmann wrote:
> > > On Tuesday 26 August 2014 08:57:31 Thierry Reding wrote:
> > > > On Mon, Aug 25, 2014 at 01:01:52PM -0600, Stephen Warren wrote:
> > > > > On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> > > > [...]
> > > > > >+static int tegra_xusb_mbox_probe(struct platform_device *pdev)
> > > > > 
> > > > > >+    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > > > > >+    if (!res)
> > > > > >+            return -ENODEV;
> > > > > 
> > > > > Should devm_request_mem_region() be called here to claim the region?
> > > > > 
> > > > > >+    mbox->regs = devm_ioremap_nocache(&pdev->dev, res->start,
> > > > > >+                                      resource_size(res));
> > > > > >+    if (!mbox->regs)
> > > > > >+            return -ENOMEM;
> > > > > 
> > > > > Is _nocache required? I don't see other drivers using it. I assume there's
> > > > > nothing special about the mbox registers.
> > > > 
> > > > Most drivers should be using devm_ioremap_resource() which will use the
> > > > _nocache variant of devm_ioremap() when appropriate. Usually the region
> > > > will not be marked cacheable (IORESOURCE_CACHEABLE) and therefore be
> > > > remapped uncached.
> > > > 
> > > 
> > > Note that ioremap() and ioremap_nocache() are the same. We really shouldn't
> > > ever call ioremap_nocache().
> > 
> > Perhaps we should remove ioremap_nocache() in that case. Or ioremap(),
> > really, and keep only those variants that do what they claim to do.
> 
> That would be good, but there are many instances of either one:
> 
> arnd@wuerfel:/git/arm-soc$ git grep -w ioremap | wc
>    2156   13402  183732
> arnd@wuerfel:/git/arm-soc$ git grep -w ioremap_nocache | wc
>     485    2529   42955

Ugh... nothing that I currently have time for. Perhaps this is a good
one for the Janitors? I'm not sure if the kernelnewbies.org TODO list is
still frequented since many pages seem to be very old. Is there some
other place where I could add this?

> > > devm_ioremap_resource() and pci_iomap() checking for IORESOURCE_CACHEABLE is
> > > rather silly, since it doesn't call ioremap_cache() in that case.
> > 
> > Then that should be fixed.
> 
> Yes. I'd suggest we just ignore that flag and always call ioremap here.
> 
> When I checked this before, IORESOURCE_CACHEABLE only ever gets set for
> PCI ROM BARs, which we don't map into the kernel.

There's still a few users of ioremap_cache() around and they are
potential candidates for a conversion to devm_ioremap_resource(), so I
think it'd still make sense to keep the check.

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

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

* [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-26  9:08                   ` Thierry Reding
  0 siblings, 0 replies; 141+ messages in thread
From: Thierry Reding @ 2014-08-26  9:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Aug 26, 2014 at 10:09:25AM +0200, Arnd Bergmann wrote:
> On Tuesday 26 August 2014 09:50:25 Thierry Reding wrote:
> > On Tue, Aug 26, 2014 at 09:43:50AM +0200, Arnd Bergmann wrote:
> > > On Tuesday 26 August 2014 08:57:31 Thierry Reding wrote:
> > > > On Mon, Aug 25, 2014 at 01:01:52PM -0600, Stephen Warren wrote:
> > > > > On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> > > > [...]
> > > > > >+static int tegra_xusb_mbox_probe(struct platform_device *pdev)
> > > > > 
> > > > > >+    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > > > > >+    if (!res)
> > > > > >+            return -ENODEV;
> > > > > 
> > > > > Should devm_request_mem_region() be called here to claim the region?
> > > > > 
> > > > > >+    mbox->regs = devm_ioremap_nocache(&pdev->dev, res->start,
> > > > > >+                                      resource_size(res));
> > > > > >+    if (!mbox->regs)
> > > > > >+            return -ENOMEM;
> > > > > 
> > > > > Is _nocache required? I don't see other drivers using it. I assume there's
> > > > > nothing special about the mbox registers.
> > > > 
> > > > Most drivers should be using devm_ioremap_resource() which will use the
> > > > _nocache variant of devm_ioremap() when appropriate. Usually the region
> > > > will not be marked cacheable (IORESOURCE_CACHEABLE) and therefore be
> > > > remapped uncached.
> > > > 
> > > 
> > > Note that ioremap() and ioremap_nocache() are the same. We really shouldn't
> > > ever call ioremap_nocache().
> > 
> > Perhaps we should remove ioremap_nocache() in that case. Or ioremap(),
> > really, and keep only those variants that do what they claim to do.
> 
> That would be good, but there are many instances of either one:
> 
> arnd at wuerfel:/git/arm-soc$ git grep -w ioremap | wc
>    2156   13402  183732
> arnd at wuerfel:/git/arm-soc$ git grep -w ioremap_nocache | wc
>     485    2529   42955

Ugh... nothing that I currently have time for. Perhaps this is a good
one for the Janitors? I'm not sure if the kernelnewbies.org TODO list is
still frequented since many pages seem to be very old. Is there some
other place where I could add this?

> > > devm_ioremap_resource() and pci_iomap() checking for IORESOURCE_CACHEABLE is
> > > rather silly, since it doesn't call ioremap_cache() in that case.
> > 
> > Then that should be fixed.
> 
> Yes. I'd suggest we just ignore that flag and always call ioremap here.
> 
> When I checked this before, IORESOURCE_CACHEABLE only ever gets set for
> PCI ROM BARs, which we don't map into the kernel.

There's still a few users of ioremap_cache() around and they are
potential candidates for a conversion to devm_ioremap_resource(), so I
think it'd still make sense to keep the check.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140826/ec08b2e6/attachment-0001.sig>

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
  2014-08-26  9:08                   ` Thierry Reding
  (?)
@ 2014-08-26  9:54                     ` Arnd Bergmann
  -1 siblings, 0 replies; 141+ messages in thread
From: Arnd Bergmann @ 2014-08-26  9:54 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Stephen Warren, Andrew Bresticker,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King, Jassi Brar,
	Linus Walleij, Greg Kroah-Hartman, Mathias Nyman, Grant Likely,
	Alan Stern, Kishon Vijay Abraham I,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA, Jonas Bonn, David Howells,
	Koichi Yasutake

On Tuesday 26 August 2014 11:08:11 Thierry Reding wrote:
> On Tue, Aug 26, 2014 at 10:09:25AM +0200, Arnd Bergmann wrote:
> > On Tuesday 26 August 2014 09:50:25 Thierry Reding wrote:
> > > On Tue, Aug 26, 2014 at 09:43:50AM +0200, Arnd Bergmann wrote:
> > > > On Tuesday 26 August 2014 08:57:31 Thierry Reding wrote:
> > > > > On Mon, Aug 25, 2014 at 01:01:52PM -0600, Stephen Warren wrote:
> > > > > > On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> > > > > [...]
> > > > > > >+static int tegra_xusb_mbox_probe(struct platform_device *pdev)
> > > > > > 
> > > > > > >+    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > > > > > >+    if (!res)
> > > > > > >+            return -ENODEV;
> > > > > > 
> > > > > > Should devm_request_mem_region() be called here to claim the region?
> > > > > > 
> > > > > > >+    mbox->regs = devm_ioremap_nocache(&pdev->dev, res->start,
> > > > > > >+                                      resource_size(res));
> > > > > > >+    if (!mbox->regs)
> > > > > > >+            return -ENOMEM;
> > > > > > 
> > > > > > Is _nocache required? I don't see other drivers using it. I assume there's
> > > > > > nothing special about the mbox registers.
> > > > > 
> > > > > Most drivers should be using devm_ioremap_resource() which will use the
> > > > > _nocache variant of devm_ioremap() when appropriate. Usually the region
> > > > > will not be marked cacheable (IORESOURCE_CACHEABLE) and therefore be
> > > > > remapped uncached.
> > > > > 
> > > > 
> > > > Note that ioremap() and ioremap_nocache() are the same. We really shouldn't
> > > > ever call ioremap_nocache().
> > > 
> > > Perhaps we should remove ioremap_nocache() in that case. Or ioremap(),
> > > really, and keep only those variants that do what they claim to do.
> > 
> > That would be good, but there are many instances of either one:
> > 
> > arnd@wuerfel:/git/arm-soc$ git grep -w ioremap | wc
> >    2156   13402  183732
> > arnd@wuerfel:/git/arm-soc$ git grep -w ioremap_nocache | wc
> >     485    2529   42955
> 
> Ugh... nothing that I currently have time for. Perhaps this is a good
> one for the Janitors? I'm not sure if the kernelnewbies.org TODO list is
> still frequented since many pages seem to be very old. Is there some
> other place where I could add this?

I'm not sure if it's really worth it. One thing we might do is just
remove all definitions of ioremap_nocache and add a wrapper to
include/linux/io.h, to make it more obvious what is going on.

> > > > devm_ioremap_resource() and pci_iomap() checking for IORESOURCE_CACHEABLE is
> > > > rather silly, since it doesn't call ioremap_cache() in that case.
> > > 
> > > Then that should be fixed.
> > 
> > Yes. I'd suggest we just ignore that flag and always call ioremap here.
> > 
> > When I checked this before, IORESOURCE_CACHEABLE only ever gets set for
> > PCI ROM BARs, which we don't map into the kernel.
> 
> There's still a few users of ioremap_cache() around and they are
> potential candidates for a conversion to devm_ioremap_resource(), so I
> think it'd still make sense to keep the check.

Possibly. Note that these are all in architecture-specific code, as
evidenced by the fact that we have multiple names for this function:

ioremap_cache:    arm, arm64, x86, ia64, sh
ioremap_cached:   metag, unicore32
ioremap_cachable: mips

All other architectures have none of the above.

An alternative approach would be to kill off IORESOURCE_CACHEABLE
and introduce a devm_ioremap_resource_cache() helper when the first
driver wants it.

	Arnd

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-26  9:54                     ` Arnd Bergmann
  0 siblings, 0 replies; 141+ messages in thread
From: Arnd Bergmann @ 2014-08-26  9:54 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Stephen Warren, Andrew Bresticker, linux-tegra, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Jassi Brar, Linus Walleij, Greg Kroah-Hartman, Mathias Nyman,
	Grant Likely, Alan Stern, Kishon Vijay Abraham I, devicetree,
	linux-kernel, linux-arm-kernel, linux-usb, Jonas Bonn,
	David Howells, Koichi Yasutake

On Tuesday 26 August 2014 11:08:11 Thierry Reding wrote:
> On Tue, Aug 26, 2014 at 10:09:25AM +0200, Arnd Bergmann wrote:
> > On Tuesday 26 August 2014 09:50:25 Thierry Reding wrote:
> > > On Tue, Aug 26, 2014 at 09:43:50AM +0200, Arnd Bergmann wrote:
> > > > On Tuesday 26 August 2014 08:57:31 Thierry Reding wrote:
> > > > > On Mon, Aug 25, 2014 at 01:01:52PM -0600, Stephen Warren wrote:
> > > > > > On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> > > > > [...]
> > > > > > >+static int tegra_xusb_mbox_probe(struct platform_device *pdev)
> > > > > > 
> > > > > > >+    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > > > > > >+    if (!res)
> > > > > > >+            return -ENODEV;
> > > > > > 
> > > > > > Should devm_request_mem_region() be called here to claim the region?
> > > > > > 
> > > > > > >+    mbox->regs = devm_ioremap_nocache(&pdev->dev, res->start,
> > > > > > >+                                      resource_size(res));
> > > > > > >+    if (!mbox->regs)
> > > > > > >+            return -ENOMEM;
> > > > > > 
> > > > > > Is _nocache required? I don't see other drivers using it. I assume there's
> > > > > > nothing special about the mbox registers.
> > > > > 
> > > > > Most drivers should be using devm_ioremap_resource() which will use the
> > > > > _nocache variant of devm_ioremap() when appropriate. Usually the region
> > > > > will not be marked cacheable (IORESOURCE_CACHEABLE) and therefore be
> > > > > remapped uncached.
> > > > > 
> > > > 
> > > > Note that ioremap() and ioremap_nocache() are the same. We really shouldn't
> > > > ever call ioremap_nocache().
> > > 
> > > Perhaps we should remove ioremap_nocache() in that case. Or ioremap(),
> > > really, and keep only those variants that do what they claim to do.
> > 
> > That would be good, but there are many instances of either one:
> > 
> > arnd@wuerfel:/git/arm-soc$ git grep -w ioremap | wc
> >    2156   13402  183732
> > arnd@wuerfel:/git/arm-soc$ git grep -w ioremap_nocache | wc
> >     485    2529   42955
> 
> Ugh... nothing that I currently have time for. Perhaps this is a good
> one for the Janitors? I'm not sure if the kernelnewbies.org TODO list is
> still frequented since many pages seem to be very old. Is there some
> other place where I could add this?

I'm not sure if it's really worth it. One thing we might do is just
remove all definitions of ioremap_nocache and add a wrapper to
include/linux/io.h, to make it more obvious what is going on.

> > > > devm_ioremap_resource() and pci_iomap() checking for IORESOURCE_CACHEABLE is
> > > > rather silly, since it doesn't call ioremap_cache() in that case.
> > > 
> > > Then that should be fixed.
> > 
> > Yes. I'd suggest we just ignore that flag and always call ioremap here.
> > 
> > When I checked this before, IORESOURCE_CACHEABLE only ever gets set for
> > PCI ROM BARs, which we don't map into the kernel.
> 
> There's still a few users of ioremap_cache() around and they are
> potential candidates for a conversion to devm_ioremap_resource(), so I
> think it'd still make sense to keep the check.

Possibly. Note that these are all in architecture-specific code, as
evidenced by the fact that we have multiple names for this function:

ioremap_cache:    arm, arm64, x86, ia64, sh
ioremap_cached:   metag, unicore32
ioremap_cachable: mips

All other architectures have none of the above.

An alternative approach would be to kill off IORESOURCE_CACHEABLE
and introduce a devm_ioremap_resource_cache() helper when the first
driver wants it.

	Arnd

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

* [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-26  9:54                     ` Arnd Bergmann
  0 siblings, 0 replies; 141+ messages in thread
From: Arnd Bergmann @ 2014-08-26  9:54 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday 26 August 2014 11:08:11 Thierry Reding wrote:
> On Tue, Aug 26, 2014 at 10:09:25AM +0200, Arnd Bergmann wrote:
> > On Tuesday 26 August 2014 09:50:25 Thierry Reding wrote:
> > > On Tue, Aug 26, 2014 at 09:43:50AM +0200, Arnd Bergmann wrote:
> > > > On Tuesday 26 August 2014 08:57:31 Thierry Reding wrote:
> > > > > On Mon, Aug 25, 2014 at 01:01:52PM -0600, Stephen Warren wrote:
> > > > > > On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> > > > > [...]
> > > > > > >+static int tegra_xusb_mbox_probe(struct platform_device *pdev)
> > > > > > 
> > > > > > >+    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > > > > > >+    if (!res)
> > > > > > >+            return -ENODEV;
> > > > > > 
> > > > > > Should devm_request_mem_region() be called here to claim the region?
> > > > > > 
> > > > > > >+    mbox->regs = devm_ioremap_nocache(&pdev->dev, res->start,
> > > > > > >+                                      resource_size(res));
> > > > > > >+    if (!mbox->regs)
> > > > > > >+            return -ENOMEM;
> > > > > > 
> > > > > > Is _nocache required? I don't see other drivers using it. I assume there's
> > > > > > nothing special about the mbox registers.
> > > > > 
> > > > > Most drivers should be using devm_ioremap_resource() which will use the
> > > > > _nocache variant of devm_ioremap() when appropriate. Usually the region
> > > > > will not be marked cacheable (IORESOURCE_CACHEABLE) and therefore be
> > > > > remapped uncached.
> > > > > 
> > > > 
> > > > Note that ioremap() and ioremap_nocache() are the same. We really shouldn't
> > > > ever call ioremap_nocache().
> > > 
> > > Perhaps we should remove ioremap_nocache() in that case. Or ioremap(),
> > > really, and keep only those variants that do what they claim to do.
> > 
> > That would be good, but there are many instances of either one:
> > 
> > arnd at wuerfel:/git/arm-soc$ git grep -w ioremap | wc
> >    2156   13402  183732
> > arnd at wuerfel:/git/arm-soc$ git grep -w ioremap_nocache | wc
> >     485    2529   42955
> 
> Ugh... nothing that I currently have time for. Perhaps this is a good
> one for the Janitors? I'm not sure if the kernelnewbies.org TODO list is
> still frequented since many pages seem to be very old. Is there some
> other place where I could add this?

I'm not sure if it's really worth it. One thing we might do is just
remove all definitions of ioremap_nocache and add a wrapper to
include/linux/io.h, to make it more obvious what is going on.

> > > > devm_ioremap_resource() and pci_iomap() checking for IORESOURCE_CACHEABLE is
> > > > rather silly, since it doesn't call ioremap_cache() in that case.
> > > 
> > > Then that should be fixed.
> > 
> > Yes. I'd suggest we just ignore that flag and always call ioremap here.
> > 
> > When I checked this before, IORESOURCE_CACHEABLE only ever gets set for
> > PCI ROM BARs, which we don't map into the kernel.
> 
> There's still a few users of ioremap_cache() around and they are
> potential candidates for a conversion to devm_ioremap_resource(), so I
> think it'd still make sense to keep the check.

Possibly. Note that these are all in architecture-specific code, as
evidenced by the fact that we have multiple names for this function:

ioremap_cache:    arm, arm64, x86, ia64, sh
ioremap_cached:   metag, unicore32
ioremap_cachable: mips

All other architectures have none of the above.

An alternative approach would be to kill off IORESOURCE_CACHEABLE
and introduce a devm_ioremap_resource_cache() helper when the first
driver wants it.

	Arnd

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
  2014-08-26  8:54             ` David Laight
  (?)
@ 2014-08-26 10:04               ` Arnd Bergmann
  -1 siblings, 0 replies; 141+ messages in thread
From: Arnd Bergmann @ 2014-08-26 10:04 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Mark Rutland, devicetree, Ian Campbell, Jassi Brar, Russell King,
	Pawel Moll, Mathias Nyman, Stephen Warren, Andrew Bresticker,
	Greg Kroah-Hartman, Linus Walleij, linux-usb, linux-kernel,
	Rob Herring, Kishon Vijay Abraham I, linux-tegra, David Laight,
	'Thierry Reding',
	Kumar Gala, Grant Likely

On Tuesday 26 August 2014 08:54:53 David Laight wrote:
> From: Thierry Reding
> ...
> > > Is _nocache required? I don't see other drivers using it. I assume there's
> > > nothing special about the mbox registers.
> > 
> > Most drivers should be using devm_ioremap_resource() which will use the
> > _nocache variant of devm_ioremap() when appropriate. Usually the region
> > will not be marked cacheable (IORESOURCE_CACHEABLE) and therefore be
> > remapped uncached.
> 
> A related question:
> Is there any way for a driver to force that part of a PCIe BAR be mapped
> through the data cache even when the BAR isn't actually marked cacheable?

No. BARs are not actually marked cacheable anyway, except for the ROM
BAR, which we tend to not use.

Some architectures don't even allow any caching of PCI memory ranges,
so we have no architecture independent API for that.

It's possible that ioremap_cache() works on x86 and/or ARM if you call
it manually on the physical address (rather than using a resource
API).

> Some hardware has address regions (which might not be an entire BAR)
> that are actually memory and mapping through the data cache will
> generate longer PCIe transfers [1].
> Clearly the driver will have to be very careful about cache flushes
> and invalidates to make this work.

Some framebuffer drivers use writethrough mappings, but those again
are only available on few architectures. vesafb uses ioremap_cache,
but this works because the memory is in system RAM and not on PCI.

	Arnd

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-26 10:04               ` Arnd Bergmann
  0 siblings, 0 replies; 141+ messages in thread
From: Arnd Bergmann @ 2014-08-26 10:04 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: David Laight, 'Thierry Reding',
	Stephen Warren, Mark Rutland, devicetree, linux-usb,
	Russell King, Mathias Nyman, Pawel Moll, Ian Campbell,
	Andrew Bresticker, Greg Kroah-Hartman, Linus Walleij, Jassi Brar,
	linux-kernel, Kishon Vijay Abraham I, Grant Likely, Rob Herring,
	Alan Stern, Kumar Gala, linux-tegra

On Tuesday 26 August 2014 08:54:53 David Laight wrote:
> From: Thierry Reding
> ...
> > > Is _nocache required? I don't see other drivers using it. I assume there's
> > > nothing special about the mbox registers.
> > 
> > Most drivers should be using devm_ioremap_resource() which will use the
> > _nocache variant of devm_ioremap() when appropriate. Usually the region
> > will not be marked cacheable (IORESOURCE_CACHEABLE) and therefore be
> > remapped uncached.
> 
> A related question:
> Is there any way for a driver to force that part of a PCIe BAR be mapped
> through the data cache even when the BAR isn't actually marked cacheable?

No. BARs are not actually marked cacheable anyway, except for the ROM
BAR, which we tend to not use.

Some architectures don't even allow any caching of PCI memory ranges,
so we have no architecture independent API for that.

It's possible that ioremap_cache() works on x86 and/or ARM if you call
it manually on the physical address (rather than using a resource
API).

> Some hardware has address regions (which might not be an entire BAR)
> that are actually memory and mapping through the data cache will
> generate longer PCIe transfers [1].
> Clearly the driver will have to be very careful about cache flushes
> and invalidates to make this work.

Some framebuffer drivers use writethrough mappings, but those again
are only available on few architectures. vesafb uses ioremap_cache,
but this works because the memory is in system RAM and not on PCI.

	Arnd

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

* [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-26 10:04               ` Arnd Bergmann
  0 siblings, 0 replies; 141+ messages in thread
From: Arnd Bergmann @ 2014-08-26 10:04 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday 26 August 2014 08:54:53 David Laight wrote:
> From: Thierry Reding
> ...
> > > Is _nocache required? I don't see other drivers using it. I assume there's
> > > nothing special about the mbox registers.
> > 
> > Most drivers should be using devm_ioremap_resource() which will use the
> > _nocache variant of devm_ioremap() when appropriate. Usually the region
> > will not be marked cacheable (IORESOURCE_CACHEABLE) and therefore be
> > remapped uncached.
> 
> A related question:
> Is there any way for a driver to force that part of a PCIe BAR be mapped
> through the data cache even when the BAR isn't actually marked cacheable?

No. BARs are not actually marked cacheable anyway, except for the ROM
BAR, which we tend to not use.

Some architectures don't even allow any caching of PCI memory ranges,
so we have no architecture independent API for that.

It's possible that ioremap_cache() works on x86 and/or ARM if you call
it manually on the physical address (rather than using a resource
API).

> Some hardware has address regions (which might not be an entire BAR)
> that are actually memory and mapping through the data cache will
> generate longer PCIe transfers [1].
> Clearly the driver will have to be very careful about cache flushes
> and invalidates to make this work.

Some framebuffer drivers use writethrough mappings, but those again
are only available on few architectures. vesafb uses ioremap_cache,
but this works because the memory is in system RAM and not on PCI.

	Arnd

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
  2014-08-26  9:54                     ` Arnd Bergmann
  (?)
@ 2014-08-26 10:20                       ` Thierry Reding
  -1 siblings, 0 replies; 141+ messages in thread
From: Thierry Reding @ 2014-08-26 10:20 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Stephen Warren, Andrew Bresticker,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King, Jassi Brar,
	Linus Walleij, Greg Kroah-Hartman, Mathias Nyman, Grant Likely,
	Alan Stern, Kishon Vijay Abraham I,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA, Jonas Bonn, David Howells,
	Koichi Yasutake

[-- Attachment #1: Type: text/plain, Size: 4126 bytes --]

On Tue, Aug 26, 2014 at 11:54:43AM +0200, Arnd Bergmann wrote:
> On Tuesday 26 August 2014 11:08:11 Thierry Reding wrote:
> > On Tue, Aug 26, 2014 at 10:09:25AM +0200, Arnd Bergmann wrote:
> > > On Tuesday 26 August 2014 09:50:25 Thierry Reding wrote:
> > > > On Tue, Aug 26, 2014 at 09:43:50AM +0200, Arnd Bergmann wrote:
> > > > > On Tuesday 26 August 2014 08:57:31 Thierry Reding wrote:
> > > > > > On Mon, Aug 25, 2014 at 01:01:52PM -0600, Stephen Warren wrote:
> > > > > > > On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> > > > > > [...]
> > > > > > > >+static int tegra_xusb_mbox_probe(struct platform_device *pdev)
> > > > > > > 
> > > > > > > >+    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > > > > > > >+    if (!res)
> > > > > > > >+            return -ENODEV;
> > > > > > > 
> > > > > > > Should devm_request_mem_region() be called here to claim the region?
> > > > > > > 
> > > > > > > >+    mbox->regs = devm_ioremap_nocache(&pdev->dev, res->start,
> > > > > > > >+                                      resource_size(res));
> > > > > > > >+    if (!mbox->regs)
> > > > > > > >+            return -ENOMEM;
> > > > > > > 
> > > > > > > Is _nocache required? I don't see other drivers using it. I assume there's
> > > > > > > nothing special about the mbox registers.
> > > > > > 
> > > > > > Most drivers should be using devm_ioremap_resource() which will use the
> > > > > > _nocache variant of devm_ioremap() when appropriate. Usually the region
> > > > > > will not be marked cacheable (IORESOURCE_CACHEABLE) and therefore be
> > > > > > remapped uncached.
> > > > > > 
> > > > > 
> > > > > Note that ioremap() and ioremap_nocache() are the same. We really shouldn't
> > > > > ever call ioremap_nocache().
> > > > 
> > > > Perhaps we should remove ioremap_nocache() in that case. Or ioremap(),
> > > > really, and keep only those variants that do what they claim to do.
> > > 
> > > That would be good, but there are many instances of either one:
> > > 
> > > arnd@wuerfel:/git/arm-soc$ git grep -w ioremap | wc
> > >    2156   13402  183732
> > > arnd@wuerfel:/git/arm-soc$ git grep -w ioremap_nocache | wc
> > >     485    2529   42955
> > 
> > Ugh... nothing that I currently have time for. Perhaps this is a good
> > one for the Janitors? I'm not sure if the kernelnewbies.org TODO list is
> > still frequented since many pages seem to be very old. Is there some
> > other place where I could add this?
> 
> I'm not sure if it's really worth it. One thing we might do is just
> remove all definitions of ioremap_nocache and add a wrapper to
> include/linux/io.h, to make it more obvious what is going on.

Yes, I suppose that would work too. I still think there's an advantage
in being explicit and avoid aliases like this. Perhaps a __deprecated
annotation would help with that?

> > > > > devm_ioremap_resource() and pci_iomap() checking for IORESOURCE_CACHEABLE is
> > > > > rather silly, since it doesn't call ioremap_cache() in that case.
> > > > 
> > > > Then that should be fixed.
> > > 
> > > Yes. I'd suggest we just ignore that flag and always call ioremap here.
> > > 
> > > When I checked this before, IORESOURCE_CACHEABLE only ever gets set for
> > > PCI ROM BARs, which we don't map into the kernel.
> > 
> > There's still a few users of ioremap_cache() around and they are
> > potential candidates for a conversion to devm_ioremap_resource(), so I
> > think it'd still make sense to keep the check.
> 
> Possibly. Note that these are all in architecture-specific code, as
> evidenced by the fact that we have multiple names for this function:
> 
> ioremap_cache:    arm, arm64, x86, ia64, sh
> ioremap_cached:   metag, unicore32
> ioremap_cachable: mips
> 
> All other architectures have none of the above.
> 
> An alternative approach would be to kill off IORESOURCE_CACHEABLE
> and introduce a devm_ioremap_resource_cache() helper when the first
> driver wants it.

Looking briefly at the involved headers and structure there seems to be
quite a bit of potential for cleanup.

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-26 10:20                       ` Thierry Reding
  0 siblings, 0 replies; 141+ messages in thread
From: Thierry Reding @ 2014-08-26 10:20 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Stephen Warren, Andrew Bresticker, linux-tegra, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Jassi Brar, Linus Walleij, Greg Kroah-Hartman, Mathias Nyman,
	Grant Likely, Alan Stern, Kishon Vijay Abraham I, devicetree,
	linux-kernel, linux-arm-kernel, linux-usb, Jonas Bonn,
	David Howells, Koichi Yasutake

[-- Attachment #1: Type: text/plain, Size: 4126 bytes --]

On Tue, Aug 26, 2014 at 11:54:43AM +0200, Arnd Bergmann wrote:
> On Tuesday 26 August 2014 11:08:11 Thierry Reding wrote:
> > On Tue, Aug 26, 2014 at 10:09:25AM +0200, Arnd Bergmann wrote:
> > > On Tuesday 26 August 2014 09:50:25 Thierry Reding wrote:
> > > > On Tue, Aug 26, 2014 at 09:43:50AM +0200, Arnd Bergmann wrote:
> > > > > On Tuesday 26 August 2014 08:57:31 Thierry Reding wrote:
> > > > > > On Mon, Aug 25, 2014 at 01:01:52PM -0600, Stephen Warren wrote:
> > > > > > > On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> > > > > > [...]
> > > > > > > >+static int tegra_xusb_mbox_probe(struct platform_device *pdev)
> > > > > > > 
> > > > > > > >+    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > > > > > > >+    if (!res)
> > > > > > > >+            return -ENODEV;
> > > > > > > 
> > > > > > > Should devm_request_mem_region() be called here to claim the region?
> > > > > > > 
> > > > > > > >+    mbox->regs = devm_ioremap_nocache(&pdev->dev, res->start,
> > > > > > > >+                                      resource_size(res));
> > > > > > > >+    if (!mbox->regs)
> > > > > > > >+            return -ENOMEM;
> > > > > > > 
> > > > > > > Is _nocache required? I don't see other drivers using it. I assume there's
> > > > > > > nothing special about the mbox registers.
> > > > > > 
> > > > > > Most drivers should be using devm_ioremap_resource() which will use the
> > > > > > _nocache variant of devm_ioremap() when appropriate. Usually the region
> > > > > > will not be marked cacheable (IORESOURCE_CACHEABLE) and therefore be
> > > > > > remapped uncached.
> > > > > > 
> > > > > 
> > > > > Note that ioremap() and ioremap_nocache() are the same. We really shouldn't
> > > > > ever call ioremap_nocache().
> > > > 
> > > > Perhaps we should remove ioremap_nocache() in that case. Or ioremap(),
> > > > really, and keep only those variants that do what they claim to do.
> > > 
> > > That would be good, but there are many instances of either one:
> > > 
> > > arnd@wuerfel:/git/arm-soc$ git grep -w ioremap | wc
> > >    2156   13402  183732
> > > arnd@wuerfel:/git/arm-soc$ git grep -w ioremap_nocache | wc
> > >     485    2529   42955
> > 
> > Ugh... nothing that I currently have time for. Perhaps this is a good
> > one for the Janitors? I'm not sure if the kernelnewbies.org TODO list is
> > still frequented since many pages seem to be very old. Is there some
> > other place where I could add this?
> 
> I'm not sure if it's really worth it. One thing we might do is just
> remove all definitions of ioremap_nocache and add a wrapper to
> include/linux/io.h, to make it more obvious what is going on.

Yes, I suppose that would work too. I still think there's an advantage
in being explicit and avoid aliases like this. Perhaps a __deprecated
annotation would help with that?

> > > > > devm_ioremap_resource() and pci_iomap() checking for IORESOURCE_CACHEABLE is
> > > > > rather silly, since it doesn't call ioremap_cache() in that case.
> > > > 
> > > > Then that should be fixed.
> > > 
> > > Yes. I'd suggest we just ignore that flag and always call ioremap here.
> > > 
> > > When I checked this before, IORESOURCE_CACHEABLE only ever gets set for
> > > PCI ROM BARs, which we don't map into the kernel.
> > 
> > There's still a few users of ioremap_cache() around and they are
> > potential candidates for a conversion to devm_ioremap_resource(), so I
> > think it'd still make sense to keep the check.
> 
> Possibly. Note that these are all in architecture-specific code, as
> evidenced by the fact that we have multiple names for this function:
> 
> ioremap_cache:    arm, arm64, x86, ia64, sh
> ioremap_cached:   metag, unicore32
> ioremap_cachable: mips
> 
> All other architectures have none of the above.
> 
> An alternative approach would be to kill off IORESOURCE_CACHEABLE
> and introduce a devm_ioremap_resource_cache() helper when the first
> driver wants it.

Looking briefly at the involved headers and structure there seems to be
quite a bit of potential for cleanup.

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

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

* [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-26 10:20                       ` Thierry Reding
  0 siblings, 0 replies; 141+ messages in thread
From: Thierry Reding @ 2014-08-26 10:20 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Aug 26, 2014 at 11:54:43AM +0200, Arnd Bergmann wrote:
> On Tuesday 26 August 2014 11:08:11 Thierry Reding wrote:
> > On Tue, Aug 26, 2014 at 10:09:25AM +0200, Arnd Bergmann wrote:
> > > On Tuesday 26 August 2014 09:50:25 Thierry Reding wrote:
> > > > On Tue, Aug 26, 2014 at 09:43:50AM +0200, Arnd Bergmann wrote:
> > > > > On Tuesday 26 August 2014 08:57:31 Thierry Reding wrote:
> > > > > > On Mon, Aug 25, 2014 at 01:01:52PM -0600, Stephen Warren wrote:
> > > > > > > On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
> > > > > > [...]
> > > > > > > >+static int tegra_xusb_mbox_probe(struct platform_device *pdev)
> > > > > > > 
> > > > > > > >+    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > > > > > > >+    if (!res)
> > > > > > > >+            return -ENODEV;
> > > > > > > 
> > > > > > > Should devm_request_mem_region() be called here to claim the region?
> > > > > > > 
> > > > > > > >+    mbox->regs = devm_ioremap_nocache(&pdev->dev, res->start,
> > > > > > > >+                                      resource_size(res));
> > > > > > > >+    if (!mbox->regs)
> > > > > > > >+            return -ENOMEM;
> > > > > > > 
> > > > > > > Is _nocache required? I don't see other drivers using it. I assume there's
> > > > > > > nothing special about the mbox registers.
> > > > > > 
> > > > > > Most drivers should be using devm_ioremap_resource() which will use the
> > > > > > _nocache variant of devm_ioremap() when appropriate. Usually the region
> > > > > > will not be marked cacheable (IORESOURCE_CACHEABLE) and therefore be
> > > > > > remapped uncached.
> > > > > > 
> > > > > 
> > > > > Note that ioremap() and ioremap_nocache() are the same. We really shouldn't
> > > > > ever call ioremap_nocache().
> > > > 
> > > > Perhaps we should remove ioremap_nocache() in that case. Or ioremap(),
> > > > really, and keep only those variants that do what they claim to do.
> > > 
> > > That would be good, but there are many instances of either one:
> > > 
> > > arnd at wuerfel:/git/arm-soc$ git grep -w ioremap | wc
> > >    2156   13402  183732
> > > arnd at wuerfel:/git/arm-soc$ git grep -w ioremap_nocache | wc
> > >     485    2529   42955
> > 
> > Ugh... nothing that I currently have time for. Perhaps this is a good
> > one for the Janitors? I'm not sure if the kernelnewbies.org TODO list is
> > still frequented since many pages seem to be very old. Is there some
> > other place where I could add this?
> 
> I'm not sure if it's really worth it. One thing we might do is just
> remove all definitions of ioremap_nocache and add a wrapper to
> include/linux/io.h, to make it more obvious what is going on.

Yes, I suppose that would work too. I still think there's an advantage
in being explicit and avoid aliases like this. Perhaps a __deprecated
annotation would help with that?

> > > > > devm_ioremap_resource() and pci_iomap() checking for IORESOURCE_CACHEABLE is
> > > > > rather silly, since it doesn't call ioremap_cache() in that case.
> > > > 
> > > > Then that should be fixed.
> > > 
> > > Yes. I'd suggest we just ignore that flag and always call ioremap here.
> > > 
> > > When I checked this before, IORESOURCE_CACHEABLE only ever gets set for
> > > PCI ROM BARs, which we don't map into the kernel.
> > 
> > There's still a few users of ioremap_cache() around and they are
> > potential candidates for a conversion to devm_ioremap_resource(), so I
> > think it'd still make sense to keep the check.
> 
> Possibly. Note that these are all in architecture-specific code, as
> evidenced by the fact that we have multiple names for this function:
> 
> ioremap_cache:    arm, arm64, x86, ia64, sh
> ioremap_cached:   metag, unicore32
> ioremap_cachable: mips
> 
> All other architectures have none of the above.
> 
> An alternative approach would be to kill off IORESOURCE_CACHEABLE
> and introduce a devm_ioremap_resource_cache() helper when the first
> driver wants it.

Looking briefly at the involved headers and structure there seems to be
quite a bit of potential for cleanup.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140826/88ee2aca/attachment.sig>

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
  2014-08-26 10:20                       ` Thierry Reding
  (?)
@ 2014-08-26 11:35                         ` Arnd Bergmann
  -1 siblings, 0 replies; 141+ messages in thread
From: Arnd Bergmann @ 2014-08-26 11:35 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Mark Rutland, Andrew Bresticker, Linus Walleij, David Howells,
	Jonas Bonn, Russell King, Pawel Moll, Jassi Brar,
	Kishon Vijay Abraham I, Alan Stern, Grant Likely, devicetree,
	Mathias Nyman, Stephen Warren, Rob Herring, linux-tegra,
	linux-arm-kernel, Ian Campbell, Greg Kroah-Hartman, linux-usb,
	linux-kernel, Kumar Gala, Koichi Yasutake

On Tuesday 26 August 2014 12:20:13 Thierry Reding wrote:
> On Tue, Aug 26, 2014 at 11:54:43AM +0200, Arnd Bergmann wrote: > 
> > I'm not sure if it's really worth it. One thing we might do is just
> > remove all definitions of ioremap_nocache and add a wrapper to
> > include/linux/io.h, to make it more obvious what is going on.
> 
> Yes, I suppose that would work too. I still think there's an advantage
> in being explicit and avoid aliases like this. Perhaps a __deprecated
> annotation would help with that?

I fear adding __deprecated would be too controversial, because that
would add hundreds of new warnings to code that is not actually wrong.

	Arnd

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-26 11:35                         ` Arnd Bergmann
  0 siblings, 0 replies; 141+ messages in thread
From: Arnd Bergmann @ 2014-08-26 11:35 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Stephen Warren, Andrew Bresticker, linux-tegra, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Jassi Brar, Linus Walleij, Greg Kroah-Hartman, Mathias Nyman,
	Grant Likely, Alan Stern, Kishon Vijay Abraham I, devicetree,
	linux-kernel, linux-arm-kernel, linux-usb, Jonas Bonn,
	David Howells, Koichi Yasutake

On Tuesday 26 August 2014 12:20:13 Thierry Reding wrote:
> On Tue, Aug 26, 2014 at 11:54:43AM +0200, Arnd Bergmann wrote: > 
> > I'm not sure if it's really worth it. One thing we might do is just
> > remove all definitions of ioremap_nocache and add a wrapper to
> > include/linux/io.h, to make it more obvious what is going on.
> 
> Yes, I suppose that would work too. I still think there's an advantage
> in being explicit and avoid aliases like this. Perhaps a __deprecated
> annotation would help with that?

I fear adding __deprecated would be too controversial, because that
would add hundreds of new warnings to code that is not actually wrong.

	Arnd

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

* [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-26 11:35                         ` Arnd Bergmann
  0 siblings, 0 replies; 141+ messages in thread
From: Arnd Bergmann @ 2014-08-26 11:35 UTC (permalink / raw)
  To: linux-arm-kernel

On Tuesday 26 August 2014 12:20:13 Thierry Reding wrote:
> On Tue, Aug 26, 2014 at 11:54:43AM +0200, Arnd Bergmann wrote: > 
> > I'm not sure if it's really worth it. One thing we might do is just
> > remove all definitions of ioremap_nocache and add a wrapper to
> > include/linux/io.h, to make it more obvious what is going on.
> 
> Yes, I suppose that would work too. I still think there's an advantage
> in being explicit and avoid aliases like this. Perhaps a __deprecated
> annotation would help with that?

I fear adding __deprecated would be too controversial, because that
would add hundreds of new warnings to code that is not actually wrong.

	Arnd

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
  2014-08-26 11:35                         ` Arnd Bergmann
  (?)
@ 2014-08-26 11:45                           ` Thierry Reding
  -1 siblings, 0 replies; 141+ messages in thread
From: Thierry Reding @ 2014-08-26 11:45 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Stephen Warren, Andrew Bresticker,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King, Jassi Brar,
	Linus Walleij, Greg Kroah-Hartman, Mathias Nyman, Grant Likely,
	Alan Stern, Kishon Vijay Abraham I,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TY76Z2rM5mHXA, Jonas Bonn, David Howells,
	Koichi Yasutake

[-- Attachment #1: Type: text/plain, Size: 926 bytes --]

On Tue, Aug 26, 2014 at 01:35:34PM +0200, Arnd Bergmann wrote:
> On Tuesday 26 August 2014 12:20:13 Thierry Reding wrote:
> > On Tue, Aug 26, 2014 at 11:54:43AM +0200, Arnd Bergmann wrote: > 
> > > I'm not sure if it's really worth it. One thing we might do is just
> > > remove all definitions of ioremap_nocache and add a wrapper to
> > > include/linux/io.h, to make it more obvious what is going on.
> > 
> > Yes, I suppose that would work too. I still think there's an advantage
> > in being explicit and avoid aliases like this. Perhaps a __deprecated
> > annotation would help with that?
> 
> I fear adding __deprecated would be too controversial, because that
> would add hundreds of new warnings to code that is not actually wrong.

Right. __deprecated is enabled via Kconfig, though, so people could turn
that off if they don't want to see the warnings. I don't mind very much
either way.

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-26 11:45                           ` Thierry Reding
  0 siblings, 0 replies; 141+ messages in thread
From: Thierry Reding @ 2014-08-26 11:45 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Stephen Warren, Andrew Bresticker, linux-tegra, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Jassi Brar, Linus Walleij, Greg Kroah-Hartman, Mathias Nyman,
	Grant Likely, Alan Stern, Kishon Vijay Abraham I, devicetree,
	linux-kernel, linux-arm-kernel, linux-usb, Jonas Bonn,
	David Howells, Koichi Yasutake

[-- Attachment #1: Type: text/plain, Size: 926 bytes --]

On Tue, Aug 26, 2014 at 01:35:34PM +0200, Arnd Bergmann wrote:
> On Tuesday 26 August 2014 12:20:13 Thierry Reding wrote:
> > On Tue, Aug 26, 2014 at 11:54:43AM +0200, Arnd Bergmann wrote: > 
> > > I'm not sure if it's really worth it. One thing we might do is just
> > > remove all definitions of ioremap_nocache and add a wrapper to
> > > include/linux/io.h, to make it more obvious what is going on.
> > 
> > Yes, I suppose that would work too. I still think there's an advantage
> > in being explicit and avoid aliases like this. Perhaps a __deprecated
> > annotation would help with that?
> 
> I fear adding __deprecated would be too controversial, because that
> would add hundreds of new warnings to code that is not actually wrong.

Right. __deprecated is enabled via Kconfig, though, so people could turn
that off if they don't want to see the warnings. I don't mind very much
either way.

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

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

* [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-26 11:45                           ` Thierry Reding
  0 siblings, 0 replies; 141+ messages in thread
From: Thierry Reding @ 2014-08-26 11:45 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Aug 26, 2014 at 01:35:34PM +0200, Arnd Bergmann wrote:
> On Tuesday 26 August 2014 12:20:13 Thierry Reding wrote:
> > On Tue, Aug 26, 2014 at 11:54:43AM +0200, Arnd Bergmann wrote: > 
> > > I'm not sure if it's really worth it. One thing we might do is just
> > > remove all definitions of ioremap_nocache and add a wrapper to
> > > include/linux/io.h, to make it more obvious what is going on.
> > 
> > Yes, I suppose that would work too. I still think there's an advantage
> > in being explicit and avoid aliases like this. Perhaps a __deprecated
> > annotation would help with that?
> 
> I fear adding __deprecated would be too controversial, because that
> would add hundreds of new warnings to code that is not actually wrong.

Right. __deprecated is enabled via Kconfig, though, so people could turn
that off if they don't want to see the warnings. I don't mind very much
either way.

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140826/12aa178b/attachment.sig>

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

* Re: [PATCH v2 1/9] of: Add NVIDIA Tegra XUSB mailbox binding
  2014-08-25 18:48         ` Stephen Warren
  (?)
@ 2014-08-27 16:33             ` Andrew Bresticker
  -1 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-27 16:33 UTC (permalink / raw)
  To: Stephen Warren
  Cc: Thierry Reding, linux-tegra-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Jassi Brar, Linus Walleij, Greg Kroah-Hartman, Mathias Nyman,
	Grant Likely, Alan Stern, Arnd Bergmann, Kishon Vijay Abraham I,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TbrhsbdSgBK9A

On Mon, Aug 25, 2014 at 11:48 AM, Stephen Warren <swarren-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org> wrote:
> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>
>> diff --git a/include/dt-bindings/mailbox/tegra-xusb-mailbox.h
>> b/include/dt-bindings/mailbox/tegra-xusb-mailbox.h
>
>
>> +#define TEGRA_XUSB_MBOX_CHAN_HOST      0
>> +#define TEGRA_XUSB_MBOX_CHAN_PHY       1
>
>
> I can't work out how these values relate to hardware at all. Are they in
> fact properties of the particular firmware that's loaded into the XUSB
> module? If so, I don't think the DT should contain these values at all.

Yes this is rather ugly... they're used by software for the demuxing
of messages and don't correspond to actual hardware.

> I wonder if the individual MBOX_CMD_* values from patch 2 are any
> better, although I think those are also defined by the firmware, not the
> hardware?

They are indeed defined by the firmware, so this would become an issue
if the firmware API ever changed.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 1/9] of: Add NVIDIA Tegra XUSB mailbox binding
@ 2014-08-27 16:33             ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-27 16:33 UTC (permalink / raw)
  To: Stephen Warren
  Cc: Thierry Reding, linux-tegra, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King, Jassi Brar,
	Linus Walleij, Greg Kroah-Hartman, Mathias Nyman, Grant Likely,
	Alan Stern, Arnd Bergmann, Kishon Vijay Abraham I, devicetree,
	linux-kernel, linux-arm-kernel, linux-usb

On Mon, Aug 25, 2014 at 11:48 AM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>
>> diff --git a/include/dt-bindings/mailbox/tegra-xusb-mailbox.h
>> b/include/dt-bindings/mailbox/tegra-xusb-mailbox.h
>
>
>> +#define TEGRA_XUSB_MBOX_CHAN_HOST      0
>> +#define TEGRA_XUSB_MBOX_CHAN_PHY       1
>
>
> I can't work out how these values relate to hardware at all. Are they in
> fact properties of the particular firmware that's loaded into the XUSB
> module? If so, I don't think the DT should contain these values at all.

Yes this is rather ugly... they're used by software for the demuxing
of messages and don't correspond to actual hardware.

> I wonder if the individual MBOX_CMD_* values from patch 2 are any
> better, although I think those are also defined by the firmware, not the
> hardware?

They are indeed defined by the firmware, so this would become an issue
if the firmware API ever changed.

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

* [PATCH v2 1/9] of: Add NVIDIA Tegra XUSB mailbox binding
@ 2014-08-27 16:33             ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-27 16:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Aug 25, 2014 at 11:48 AM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>
>> diff --git a/include/dt-bindings/mailbox/tegra-xusb-mailbox.h
>> b/include/dt-bindings/mailbox/tegra-xusb-mailbox.h
>
>
>> +#define TEGRA_XUSB_MBOX_CHAN_HOST      0
>> +#define TEGRA_XUSB_MBOX_CHAN_PHY       1
>
>
> I can't work out how these values relate to hardware at all. Are they in
> fact properties of the particular firmware that's loaded into the XUSB
> module? If so, I don't think the DT should contain these values at all.

Yes this is rather ugly... they're used by software for the demuxing
of messages and don't correspond to actual hardware.

> I wonder if the individual MBOX_CMD_* values from patch 2 are any
> better, although I think those are also defined by the firmware, not the
> hardware?

They are indeed defined by the firmware, so this would become an issue
if the firmware API ever changed.

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

* Re: [PATCH v2 3/9] of: Update Tegra XUSB pad controller binding for USB
  2014-08-25 19:12       ` Stephen Warren
  (?)
@ 2014-08-27 16:36           ` Andrew Bresticker
  -1 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-27 16:36 UTC (permalink / raw)
  To: Stephen Warren
  Cc: Thierry Reding, linux-tegra-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Jassi Brar, Linus Walleij, Greg Kroah-Hartman, Mathias Nyman,
	Grant Likely, Alan Stern, Arnd Bergmann, Kishon Vijay Abraham I,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TbrhsbdSgBK9A

On Mon, Aug 25, 2014 at 12:12 PM, Stephen Warren <swarren-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org> wrote:
> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>   - #phy-cells: Should be 1. The specifier is the index of the PHY to
>> reference.
>>     See <dt-bindings/pinctrl/pinctrl-tegra-xusb.h> for the list of valid
>> values.
>> +- mboxes: Must contain an entry for the XUSB PHY mailbox channel.
>> +  See ../mailbox/mailbox.txt for details.
>
>
> Can we require the mbox-names property here, so that everything is looked up
> by names. I know that the proposed mbox binding states that using indexes is
> preferred over names, but that's just silly considering that names are
> widely used in most other similar bindings, and are much easier to extend in
> a backwards compatible fashion in the face of optional entries. As such, I'd
> prefer that all Tegra bindings use foo-names properties where they exist.

Sure, will do.

>> +Optional properties:
>> +-------------------
>> +- vbus-otg-{0,1,2}-supply: VBUS regulator for the corresponding UTMI pad.
>
>
> Why "-otg"? It's quite possible to have a regulator for VBUS even on systems
> that don't support OTG, but rather simply have the ability to turn VBUS off.

Because they're the VBUS supplies for the OTG 'lanes'.  It doesn't
really add anything, so I'll omit the "-otg".
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 3/9] of: Update Tegra XUSB pad controller binding for USB
@ 2014-08-27 16:36           ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-27 16:36 UTC (permalink / raw)
  To: Stephen Warren
  Cc: Thierry Reding, linux-tegra, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King, Jassi Brar,
	Linus Walleij, Greg Kroah-Hartman, Mathias Nyman, Grant Likely,
	Alan Stern, Arnd Bergmann, Kishon Vijay Abraham I, devicetree,
	linux-kernel, linux-arm-kernel, linux-usb

On Mon, Aug 25, 2014 at 12:12 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>   - #phy-cells: Should be 1. The specifier is the index of the PHY to
>> reference.
>>     See <dt-bindings/pinctrl/pinctrl-tegra-xusb.h> for the list of valid
>> values.
>> +- mboxes: Must contain an entry for the XUSB PHY mailbox channel.
>> +  See ../mailbox/mailbox.txt for details.
>
>
> Can we require the mbox-names property here, so that everything is looked up
> by names. I know that the proposed mbox binding states that using indexes is
> preferred over names, but that's just silly considering that names are
> widely used in most other similar bindings, and are much easier to extend in
> a backwards compatible fashion in the face of optional entries. As such, I'd
> prefer that all Tegra bindings use foo-names properties where they exist.

Sure, will do.

>> +Optional properties:
>> +-------------------
>> +- vbus-otg-{0,1,2}-supply: VBUS regulator for the corresponding UTMI pad.
>
>
> Why "-otg"? It's quite possible to have a regulator for VBUS even on systems
> that don't support OTG, but rather simply have the ability to turn VBUS off.

Because they're the VBUS supplies for the OTG 'lanes'.  It doesn't
really add anything, so I'll omit the "-otg".

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

* [PATCH v2 3/9] of: Update Tegra XUSB pad controller binding for USB
@ 2014-08-27 16:36           ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-27 16:36 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Aug 25, 2014 at 12:12 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>   - #phy-cells: Should be 1. The specifier is the index of the PHY to
>> reference.
>>     See <dt-bindings/pinctrl/pinctrl-tegra-xusb.h> for the list of valid
>> values.
>> +- mboxes: Must contain an entry for the XUSB PHY mailbox channel.
>> +  See ../mailbox/mailbox.txt for details.
>
>
> Can we require the mbox-names property here, so that everything is looked up
> by names. I know that the proposed mbox binding states that using indexes is
> preferred over names, but that's just silly considering that names are
> widely used in most other similar bindings, and are much easier to extend in
> a backwards compatible fashion in the face of optional entries. As such, I'd
> prefer that all Tegra bindings use foo-names properties where they exist.

Sure, will do.

>> +Optional properties:
>> +-------------------
>> +- vbus-otg-{0,1,2}-supply: VBUS regulator for the corresponding UTMI pad.
>
>
> Why "-otg"? It's quite possible to have a regulator for VBUS even on systems
> that don't support OTG, but rather simply have the ability to turn VBUS off.

Because they're the VBUS supplies for the OTG 'lanes'.  It doesn't
really add anything, so I'll omit the "-otg".

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

* Re: [PATCH v2 3/9] of: Update Tegra XUSB pad controller binding for USB
  2014-08-27 16:36           ` Andrew Bresticker
  (?)
@ 2014-08-27 16:42               ` Stephen Warren
  -1 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-27 16:42 UTC (permalink / raw)
  To: Andrew Bresticker
  Cc: Thierry Reding, linux-tegra-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Jassi Brar, Linus Walleij, Greg Kroah-Hartman, Mathias Nyman,
	Grant Likely, Alan Stern, Arnd Bergmann, Kishon Vijay Abraham I,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TbrhsbdSgBK9A

On 08/27/2014 10:36 AM, Andrew Bresticker wrote:
> On Mon, Aug 25, 2014 at 12:12 PM, Stephen Warren <swarren-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org> wrote:
>> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>>    - #phy-cells: Should be 1. The specifier is the index of the PHY to
>>> reference.
>>>      See <dt-bindings/pinctrl/pinctrl-tegra-xusb.h> for the list of valid
>>> values.
>>> +- mboxes: Must contain an entry for the XUSB PHY mailbox channel.
>>> +  See ../mailbox/mailbox.txt for details.
>>
>>
>> Can we require the mbox-names property here, so that everything is looked up
>> by names. I know that the proposed mbox binding states that using indexes is
>> preferred over names, but that's just silly considering that names are
>> widely used in most other similar bindings, and are much easier to extend in
>> a backwards compatible fashion in the face of optional entries. As such, I'd
>> prefer that all Tegra bindings use foo-names properties where they exist.
>
> Sure, will do.
>
>>> +Optional properties:
>>> +-------------------
>>> +- vbus-otg-{0,1,2}-supply: VBUS regulator for the corresponding UTMI pad.
>>
>>
>> Why "-otg"? It's quite possible to have a regulator for VBUS even on systems
>> that don't support OTG, but rather simply have the ability to turn VBUS off.
>
> Because they're the VBUS supplies for the OTG 'lanes'.  It doesn't
> really add anything, so I'll omit the "-otg".

Ah right. In that case, if the lanes are named "OTG" lanes in the HW 
docs, I'm happy either way. If you did decide to keep the "-otg", 
rewording as "VBUS regulator for the corresponding OTG UTMI pad" would 
make the meaning clearer.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 3/9] of: Update Tegra XUSB pad controller binding for USB
@ 2014-08-27 16:42               ` Stephen Warren
  0 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-27 16:42 UTC (permalink / raw)
  To: Andrew Bresticker
  Cc: Thierry Reding, linux-tegra, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King, Jassi Brar,
	Linus Walleij, Greg Kroah-Hartman, Mathias Nyman, Grant Likely,
	Alan Stern, Arnd Bergmann, Kishon Vijay Abraham I, devicetree,
	linux-kernel, linux-arm-kernel, linux-usb

On 08/27/2014 10:36 AM, Andrew Bresticker wrote:
> On Mon, Aug 25, 2014 at 12:12 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>>    - #phy-cells: Should be 1. The specifier is the index of the PHY to
>>> reference.
>>>      See <dt-bindings/pinctrl/pinctrl-tegra-xusb.h> for the list of valid
>>> values.
>>> +- mboxes: Must contain an entry for the XUSB PHY mailbox channel.
>>> +  See ../mailbox/mailbox.txt for details.
>>
>>
>> Can we require the mbox-names property here, so that everything is looked up
>> by names. I know that the proposed mbox binding states that using indexes is
>> preferred over names, but that's just silly considering that names are
>> widely used in most other similar bindings, and are much easier to extend in
>> a backwards compatible fashion in the face of optional entries. As such, I'd
>> prefer that all Tegra bindings use foo-names properties where they exist.
>
> Sure, will do.
>
>>> +Optional properties:
>>> +-------------------
>>> +- vbus-otg-{0,1,2}-supply: VBUS regulator for the corresponding UTMI pad.
>>
>>
>> Why "-otg"? It's quite possible to have a regulator for VBUS even on systems
>> that don't support OTG, but rather simply have the ability to turn VBUS off.
>
> Because they're the VBUS supplies for the OTG 'lanes'.  It doesn't
> really add anything, so I'll omit the "-otg".

Ah right. In that case, if the lanes are named "OTG" lanes in the HW 
docs, I'm happy either way. If you did decide to keep the "-otg", 
rewording as "VBUS regulator for the corresponding OTG UTMI pad" would 
make the meaning clearer.

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

* [PATCH v2 3/9] of: Update Tegra XUSB pad controller binding for USB
@ 2014-08-27 16:42               ` Stephen Warren
  0 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-27 16:42 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/27/2014 10:36 AM, Andrew Bresticker wrote:
> On Mon, Aug 25, 2014 at 12:12 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>>    - #phy-cells: Should be 1. The specifier is the index of the PHY to
>>> reference.
>>>      See <dt-bindings/pinctrl/pinctrl-tegra-xusb.h> for the list of valid
>>> values.
>>> +- mboxes: Must contain an entry for the XUSB PHY mailbox channel.
>>> +  See ../mailbox/mailbox.txt for details.
>>
>>
>> Can we require the mbox-names property here, so that everything is looked up
>> by names. I know that the proposed mbox binding states that using indexes is
>> preferred over names, but that's just silly considering that names are
>> widely used in most other similar bindings, and are much easier to extend in
>> a backwards compatible fashion in the face of optional entries. As such, I'd
>> prefer that all Tegra bindings use foo-names properties where they exist.
>
> Sure, will do.
>
>>> +Optional properties:
>>> +-------------------
>>> +- vbus-otg-{0,1,2}-supply: VBUS regulator for the corresponding UTMI pad.
>>
>>
>> Why "-otg"? It's quite possible to have a regulator for VBUS even on systems
>> that don't support OTG, but rather simply have the ability to turn VBUS off.
>
> Because they're the VBUS supplies for the OTG 'lanes'.  It doesn't
> really add anything, so I'll omit the "-otg".

Ah right. In that case, if the lanes are named "OTG" lanes in the HW 
docs, I'm happy either way. If you did decide to keep the "-otg", 
rewording as "VBUS regulator for the corresponding OTG UTMI pad" would 
make the meaning clearer.

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

* Re: [PATCH v2 4/9] pinctrl: tegra-xusb: Add USB PHY support
  2014-08-25 19:22       ` Stephen Warren
  (?)
@ 2014-08-27 16:44           ` Andrew Bresticker
  -1 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-27 16:44 UTC (permalink / raw)
  To: Stephen Warren
  Cc: Thierry Reding, Linus Walleij, Mikko Perttunen,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King, Jassi Brar,
	Greg Kroah-Hartman, Mathias Nyman, Grant Likely, Alan Stern,
	Arnd Bergmann, Kishon Vijay Abraham I,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org

On Mon, Aug 25, 2014 at 12:22 PM, Stephen Warren <swarren-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org> wrote:
> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>
>> In addition to the PCIe and SATA PHYs, the XUSB pad controller also
>> supports 3 UTMI, 2 HSIC, and 2 USB3 PHYs.  Each USB3 PHY uses a single
>> PCIe or SATA lane and is mapped to one of the three UTMI ports.
>>
>> The xHCI controller will also send messages intended for the PHY driver,
>> so request and listen for messages on the mailbox's PHY channel.
>
>
> I'd like a review from Thierry here as the HW expert.
>
> I need an ack from LinusW in order to take this pinctrl patch through the
> Tegra tree.
>
>> diff --git a/drivers/pinctrl/pinctrl-tegra-xusb.c
>> b/drivers/pinctrl/pinctrl-tegra-xusb.c
>
>
>> +static int usb3_phy_power_on(struct phy *phy)
>> +{
>> +       struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
>> +       int port = usb3_phy_to_port(phy);
>> +       int lane = padctl->usb3_ports[port].lane;
>> +       u32 value, offset;
>> +
>> +       if (!is_pcie_or_sata_lane(lane)) {
>> +               dev_err(padctl->dev, "USB3 PHY %d mapped to invalid lane:
>> %d\n",
>> +                       port, lane);
>> +               return -EINVAL;
>> +       }
>
>
> An aside: This implies that the SATA driver should be talking to this
> pinctrl driver and explicitly powering on the XUSB pins. However, the SATA
> driver doesn't depend on this series. I'm a bit confused how that works.
> Perhaps it's just by accident? Mikko, can you comment?

As Mikko mentioned, the enabling of the SATA lane in
usb3_phy_power_on() is for when the SATA lane is being used for USB3.

>> +static int utmi_phy_to_port(struct phy *phy)
>> +{
>> +       struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
>> +       int i;
>> +
>> +       for (i = 0; i < TEGRA_XUSB_UTMI_PHYS; i++) {
>> +               if (phy == padctl->phys[TEGRA_XUSB_PADCTL_UTMI_P0 + i])
>> +                       break;
>> +       }
>> +       BUG_ON(i == TEGRA_XUSB_UTMI_PHYS);
>
>
> Can this be triggered by e.g. bad DT content? If so, returning an error
> would be nicer. The comment applies to other xxx_to_port() functions.

No, it cannot.  The struct phy that's passed in here comes from the
PHY core and must be a PHY that we registered earlier in probe().

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

* Re: [PATCH v2 4/9] pinctrl: tegra-xusb: Add USB PHY support
@ 2014-08-27 16:44           ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-27 16:44 UTC (permalink / raw)
  To: Stephen Warren
  Cc: Thierry Reding, Linus Walleij, Mikko Perttunen, linux-tegra,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Jassi Brar, Greg Kroah-Hartman, Mathias Nyman,
	Grant Likely, Alan Stern, Arnd Bergmann, Kishon Vijay Abraham I,
	devicetree, linux-kernel, linux-arm-kernel, linux-usb

On Mon, Aug 25, 2014 at 12:22 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>
>> In addition to the PCIe and SATA PHYs, the XUSB pad controller also
>> supports 3 UTMI, 2 HSIC, and 2 USB3 PHYs.  Each USB3 PHY uses a single
>> PCIe or SATA lane and is mapped to one of the three UTMI ports.
>>
>> The xHCI controller will also send messages intended for the PHY driver,
>> so request and listen for messages on the mailbox's PHY channel.
>
>
> I'd like a review from Thierry here as the HW expert.
>
> I need an ack from LinusW in order to take this pinctrl patch through the
> Tegra tree.
>
>> diff --git a/drivers/pinctrl/pinctrl-tegra-xusb.c
>> b/drivers/pinctrl/pinctrl-tegra-xusb.c
>
>
>> +static int usb3_phy_power_on(struct phy *phy)
>> +{
>> +       struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
>> +       int port = usb3_phy_to_port(phy);
>> +       int lane = padctl->usb3_ports[port].lane;
>> +       u32 value, offset;
>> +
>> +       if (!is_pcie_or_sata_lane(lane)) {
>> +               dev_err(padctl->dev, "USB3 PHY %d mapped to invalid lane:
>> %d\n",
>> +                       port, lane);
>> +               return -EINVAL;
>> +       }
>
>
> An aside: This implies that the SATA driver should be talking to this
> pinctrl driver and explicitly powering on the XUSB pins. However, the SATA
> driver doesn't depend on this series. I'm a bit confused how that works.
> Perhaps it's just by accident? Mikko, can you comment?

As Mikko mentioned, the enabling of the SATA lane in
usb3_phy_power_on() is for when the SATA lane is being used for USB3.

>> +static int utmi_phy_to_port(struct phy *phy)
>> +{
>> +       struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
>> +       int i;
>> +
>> +       for (i = 0; i < TEGRA_XUSB_UTMI_PHYS; i++) {
>> +               if (phy == padctl->phys[TEGRA_XUSB_PADCTL_UTMI_P0 + i])
>> +                       break;
>> +       }
>> +       BUG_ON(i == TEGRA_XUSB_UTMI_PHYS);
>
>
> Can this be triggered by e.g. bad DT content? If so, returning an error
> would be nicer. The comment applies to other xxx_to_port() functions.

No, it cannot.  The struct phy that's passed in here comes from the
PHY core and must be a PHY that we registered earlier in probe().

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

* [PATCH v2 4/9] pinctrl: tegra-xusb: Add USB PHY support
@ 2014-08-27 16:44           ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-27 16:44 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Aug 25, 2014 at 12:22 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>
>> In addition to the PCIe and SATA PHYs, the XUSB pad controller also
>> supports 3 UTMI, 2 HSIC, and 2 USB3 PHYs.  Each USB3 PHY uses a single
>> PCIe or SATA lane and is mapped to one of the three UTMI ports.
>>
>> The xHCI controller will also send messages intended for the PHY driver,
>> so request and listen for messages on the mailbox's PHY channel.
>
>
> I'd like a review from Thierry here as the HW expert.
>
> I need an ack from LinusW in order to take this pinctrl patch through the
> Tegra tree.
>
>> diff --git a/drivers/pinctrl/pinctrl-tegra-xusb.c
>> b/drivers/pinctrl/pinctrl-tegra-xusb.c
>
>
>> +static int usb3_phy_power_on(struct phy *phy)
>> +{
>> +       struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
>> +       int port = usb3_phy_to_port(phy);
>> +       int lane = padctl->usb3_ports[port].lane;
>> +       u32 value, offset;
>> +
>> +       if (!is_pcie_or_sata_lane(lane)) {
>> +               dev_err(padctl->dev, "USB3 PHY %d mapped to invalid lane:
>> %d\n",
>> +                       port, lane);
>> +               return -EINVAL;
>> +       }
>
>
> An aside: This implies that the SATA driver should be talking to this
> pinctrl driver and explicitly powering on the XUSB pins. However, the SATA
> driver doesn't depend on this series. I'm a bit confused how that works.
> Perhaps it's just by accident? Mikko, can you comment?

As Mikko mentioned, the enabling of the SATA lane in
usb3_phy_power_on() is for when the SATA lane is being used for USB3.

>> +static int utmi_phy_to_port(struct phy *phy)
>> +{
>> +       struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
>> +       int i;
>> +
>> +       for (i = 0; i < TEGRA_XUSB_UTMI_PHYS; i++) {
>> +               if (phy == padctl->phys[TEGRA_XUSB_PADCTL_UTMI_P0 + i])
>> +                       break;
>> +       }
>> +       BUG_ON(i == TEGRA_XUSB_UTMI_PHYS);
>
>
> Can this be triggered by e.g. bad DT content? If so, returning an error
> would be nicer. The comment applies to other xxx_to_port() functions.

No, it cannot.  The struct phy that's passed in here comes from the
PHY core and must be a PHY that we registered earlier in probe().

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
  2014-08-25 19:01       ` Stephen Warren
  (?)
@ 2014-08-27 17:38         ` Andrew Bresticker
  -1 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-27 17:38 UTC (permalink / raw)
  To: Stephen Warren, Jassi Brar
  Cc: Thierry Reding, linux-tegra, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Linus Walleij, Greg Kroah-Hartman, Mathias Nyman, Grant Likely,
	Alan Stern, Arnd Bergmann, Kishon Vijay Abraham I, devicetree,
	linux-kernel, linux-arm-kernel, linux-usb

On Mon, Aug 25, 2014 at 12:01 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>
>> The Tegra xHCI controller's firmware communicates requests to the host
>> processor through a mailbox interface.  While there is only a single
>> communication channel, messages sent by the controller can be divided
>> into two groups: those intended for the PHY driver and those intended
>> for the host-controller driver.  This mailbox driver exposes the two
>> channels and routes incoming messages to the appropriate channel based
>> on the command encoded in the message.
>
>
>> diff --git a/drivers/mailbox/tegra-xusb-mailbox.c
>> b/drivers/mailbox/tegra-xusb-mailbox.c
>
>
>> +#define XUSB_CFG_ARU_MBOX_CMD                  0xe4
>> +#define  MBOX_FALC_INT_EN                      BIT(27)
>> +#define  MBOX_PME_INT_EN                       BIT(28)
>> +#define  MBOX_SMI_INT_EN                       BIT(29)
>> +#define  MBOX_XHCI_INT_EN                      BIT(30)
>> +#define  MBOX_INT_EN                           BIT(31)
>
>
> Those field names don't match the documentation in the TRM; they're called
> DEST_xxx rather than xxx_INT_EN. I'm not sure what that disconnect means
> (i.e. whether it's just a different naming choice, or there's some practical
> disconnect that will cause issues.)

Hmm... interestingly *_INT_EN is the convention the downstream kernels
used.  DEST_* is definitely more accurate as I'm pretty sure these
bits select the destination for the interrupt.

>> +static struct mbox_chan *mbox_cmd_to_chan(struct tegra_xusb_mbox *mbox,
>> u32 cmd)
>> +{
>> +       switch (cmd) {
>> +       case MBOX_CMD_INC_FALC_CLOCK:
>> +       case MBOX_CMD_DEC_FALC_CLOCK:
>> +       case MBOX_CMD_INC_SSPI_CLOCK:
>> +       case MBOX_CMD_DEC_SSPI_CLOCK:
>> +       case MBOX_CMD_SET_BW:
>> +               return &mbox->mbox.chans[TEGRA_XUSB_MBOX_CHAN_HOST];
>> +       case MBOX_CMD_SAVE_DFE_CTLE_CTX:
>> +       case MBOX_CMD_START_HSIC_IDLE:
>> +       case MBOX_CMD_STOP_HSIC_IDLE:
>> +               return &mbox->mbox.chans[TEGRA_XUSB_MBOX_CHAN_PHY];
>> +       default:
>> +               return NULL;
>> +       }
>> +}
>
>
> This makes me think that the CHAN_HOST/CHAN_PHY values are purely a facet of
> the Linux driver's message de-multiplexing, rather than anything to do with
> the HW.

Yup, they are...

> I'm not even sure if it's appropriate for the low-level mailbox driver to
> know about the semantics of the message, rather than simply sending them on
> to the client driver? Perhaps when drivers register(?) for callbacks(?) for
> messages, they should state which types of messages they want to listen to?

So there's not really a way for the client driver to tell the mailbox
driver which types of messages it wants to listen to on a particular
channel with the mailbox framework - it simply provides a way for
clients to bind with channels.  I think there are a couple of options
here, either: a) have a channel per message (as you mentioned in the
previous patch), which allows the client to only register for messages
(channels) it wants to handle, or b) extend the mailbox framework to
allow shared channels so that both clients can receive messages on the
single channel and handle messages appropriately.   The disadvantage
of (a) is that the commands are firmware defined and could
theoretically change between releases of the firmware, though I'm not
sure how common that is in practice.  So that leaves (b) - Jassi, what
do you think about having shared (non-exclusive) channels?

>> +static irqreturn_t tegra_xusb_mbox_irq(int irq, void *p)
>
>
>> +       /* Clear mbox interrupts */
>>
>> +       reg = mbox_readl(mbox, XUSB_CFG_ARU_SMI_INTR);
>> +       if (reg & MBOX_SMI_INTR_FW_HANG)
>> +               dev_err(mbox->mbox.dev, "Controller firmware hang\n");
>> +       mbox_writel(mbox, reg, XUSB_CFG_ARU_SMI_INTR);
>
>
>> +       /*
>>
>> +        * Set the mailbox back to idle.  The recipient of the message is
>> +        * responsible for sending an ACK/NAK, if necessary.
>> +        */
>> +       reg = mbox_readl(mbox, XUSB_CFG_ARU_MBOX_CMD);
>> +       reg &= ~MBOX_SMI_INT_EN;
>> +       mbox_writel(mbox, reg, XUSB_CFG_ARU_MBOX_CMD);
>
>
> Does the protocol not allow the remote firmware to send another message
> until the host has ack'd/nak'd the message; the code above turns off the IRQ
> that indicated to the host that a message was sent to it...

While the firmware generally will not send another message until the
previous one is ACK'd/NAK'd (with the exception of the SET_BW
command), the above does not prevent it from doing so.  I believe the
controller sets up the DEST_* bits properly before sending another
message.

>> +static int tegra_xusb_mbox_probe(struct platform_device *pdev)
>
>
>> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>
>> +       if (!res)
>> +               return -ENODEV;
>
>
> Should devm_request_mem_region() be called here to claim the region?

No, the xHCI host driver also needs to map these registers, so they
cannot be mapped exclusively here.

>> +       mbox->regs = devm_ioremap_nocache(&pdev->dev, res->start,
>> +                                         resource_size(res));
>> +       if (!mbox->regs)
>> +               return -ENOMEM;
>
>
> Is _nocache required? I don't see other drivers using it. I assume there's
> nothing special about the mbox registers.

I'll drop the _nocache.

>> +       mbox->irq = platform_get_irq(pdev, 0);
>> +       if (mbox->irq < 0)
>> +               return mbox->irq;
>> +       ret = devm_request_irq(&pdev->dev, mbox->irq, tegra_xusb_mbox_irq,
>> 0,
>> +                              dev_name(&pdev->dev), mbox);
>
>
> Is it possible for an IRQ to occur after tegra_xusb_mbox_remove() has
> returned, but before the cleanup for the devm IRQ allocation occurs? If that
> happens, will the code handle it gracefully, or crash?

It looks like mbox_chan_received_data() will crash if the channel is
unbound, so yes, this needs to be fixed.

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-27 17:38         ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-27 17:38 UTC (permalink / raw)
  To: Stephen Warren, Jassi Brar
  Cc: Thierry Reding, linux-tegra, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Linus Walleij, Greg Kroah-Hartman, Mathias Nyman, Grant Likely,
	Alan Stern, Arnd Bergmann, Kishon Vijay Abraham I, devicetree,
	linux-kernel, linux-arm-kernel, linux-usb

On Mon, Aug 25, 2014 at 12:01 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>
>> The Tegra xHCI controller's firmware communicates requests to the host
>> processor through a mailbox interface.  While there is only a single
>> communication channel, messages sent by the controller can be divided
>> into two groups: those intended for the PHY driver and those intended
>> for the host-controller driver.  This mailbox driver exposes the two
>> channels and routes incoming messages to the appropriate channel based
>> on the command encoded in the message.
>
>
>> diff --git a/drivers/mailbox/tegra-xusb-mailbox.c
>> b/drivers/mailbox/tegra-xusb-mailbox.c
>
>
>> +#define XUSB_CFG_ARU_MBOX_CMD                  0xe4
>> +#define  MBOX_FALC_INT_EN                      BIT(27)
>> +#define  MBOX_PME_INT_EN                       BIT(28)
>> +#define  MBOX_SMI_INT_EN                       BIT(29)
>> +#define  MBOX_XHCI_INT_EN                      BIT(30)
>> +#define  MBOX_INT_EN                           BIT(31)
>
>
> Those field names don't match the documentation in the TRM; they're called
> DEST_xxx rather than xxx_INT_EN. I'm not sure what that disconnect means
> (i.e. whether it's just a different naming choice, or there's some practical
> disconnect that will cause issues.)

Hmm... interestingly *_INT_EN is the convention the downstream kernels
used.  DEST_* is definitely more accurate as I'm pretty sure these
bits select the destination for the interrupt.

>> +static struct mbox_chan *mbox_cmd_to_chan(struct tegra_xusb_mbox *mbox,
>> u32 cmd)
>> +{
>> +       switch (cmd) {
>> +       case MBOX_CMD_INC_FALC_CLOCK:
>> +       case MBOX_CMD_DEC_FALC_CLOCK:
>> +       case MBOX_CMD_INC_SSPI_CLOCK:
>> +       case MBOX_CMD_DEC_SSPI_CLOCK:
>> +       case MBOX_CMD_SET_BW:
>> +               return &mbox->mbox.chans[TEGRA_XUSB_MBOX_CHAN_HOST];
>> +       case MBOX_CMD_SAVE_DFE_CTLE_CTX:
>> +       case MBOX_CMD_START_HSIC_IDLE:
>> +       case MBOX_CMD_STOP_HSIC_IDLE:
>> +               return &mbox->mbox.chans[TEGRA_XUSB_MBOX_CHAN_PHY];
>> +       default:
>> +               return NULL;
>> +       }
>> +}
>
>
> This makes me think that the CHAN_HOST/CHAN_PHY values are purely a facet of
> the Linux driver's message de-multiplexing, rather than anything to do with
> the HW.

Yup, they are...

> I'm not even sure if it's appropriate for the low-level mailbox driver to
> know about the semantics of the message, rather than simply sending them on
> to the client driver? Perhaps when drivers register(?) for callbacks(?) for
> messages, they should state which types of messages they want to listen to?

So there's not really a way for the client driver to tell the mailbox
driver which types of messages it wants to listen to on a particular
channel with the mailbox framework - it simply provides a way for
clients to bind with channels.  I think there are a couple of options
here, either: a) have a channel per message (as you mentioned in the
previous patch), which allows the client to only register for messages
(channels) it wants to handle, or b) extend the mailbox framework to
allow shared channels so that both clients can receive messages on the
single channel and handle messages appropriately.   The disadvantage
of (a) is that the commands are firmware defined and could
theoretically change between releases of the firmware, though I'm not
sure how common that is in practice.  So that leaves (b) - Jassi, what
do you think about having shared (non-exclusive) channels?

>> +static irqreturn_t tegra_xusb_mbox_irq(int irq, void *p)
>
>
>> +       /* Clear mbox interrupts */
>>
>> +       reg = mbox_readl(mbox, XUSB_CFG_ARU_SMI_INTR);
>> +       if (reg & MBOX_SMI_INTR_FW_HANG)
>> +               dev_err(mbox->mbox.dev, "Controller firmware hang\n");
>> +       mbox_writel(mbox, reg, XUSB_CFG_ARU_SMI_INTR);
>
>
>> +       /*
>>
>> +        * Set the mailbox back to idle.  The recipient of the message is
>> +        * responsible for sending an ACK/NAK, if necessary.
>> +        */
>> +       reg = mbox_readl(mbox, XUSB_CFG_ARU_MBOX_CMD);
>> +       reg &= ~MBOX_SMI_INT_EN;
>> +       mbox_writel(mbox, reg, XUSB_CFG_ARU_MBOX_CMD);
>
>
> Does the protocol not allow the remote firmware to send another message
> until the host has ack'd/nak'd the message; the code above turns off the IRQ
> that indicated to the host that a message was sent to it...

While the firmware generally will not send another message until the
previous one is ACK'd/NAK'd (with the exception of the SET_BW
command), the above does not prevent it from doing so.  I believe the
controller sets up the DEST_* bits properly before sending another
message.

>> +static int tegra_xusb_mbox_probe(struct platform_device *pdev)
>
>
>> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>
>> +       if (!res)
>> +               return -ENODEV;
>
>
> Should devm_request_mem_region() be called here to claim the region?

No, the xHCI host driver also needs to map these registers, so they
cannot be mapped exclusively here.

>> +       mbox->regs = devm_ioremap_nocache(&pdev->dev, res->start,
>> +                                         resource_size(res));
>> +       if (!mbox->regs)
>> +               return -ENOMEM;
>
>
> Is _nocache required? I don't see other drivers using it. I assume there's
> nothing special about the mbox registers.

I'll drop the _nocache.

>> +       mbox->irq = platform_get_irq(pdev, 0);
>> +       if (mbox->irq < 0)
>> +               return mbox->irq;
>> +       ret = devm_request_irq(&pdev->dev, mbox->irq, tegra_xusb_mbox_irq,
>> 0,
>> +                              dev_name(&pdev->dev), mbox);
>
>
> Is it possible for an IRQ to occur after tegra_xusb_mbox_remove() has
> returned, but before the cleanup for the devm IRQ allocation occurs? If that
> happens, will the code handle it gracefully, or crash?

It looks like mbox_chan_received_data() will crash if the channel is
unbound, so yes, this needs to be fixed.

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

* [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-27 17:38         ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-27 17:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Aug 25, 2014 at 12:01 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>
>> The Tegra xHCI controller's firmware communicates requests to the host
>> processor through a mailbox interface.  While there is only a single
>> communication channel, messages sent by the controller can be divided
>> into two groups: those intended for the PHY driver and those intended
>> for the host-controller driver.  This mailbox driver exposes the two
>> channels and routes incoming messages to the appropriate channel based
>> on the command encoded in the message.
>
>
>> diff --git a/drivers/mailbox/tegra-xusb-mailbox.c
>> b/drivers/mailbox/tegra-xusb-mailbox.c
>
>
>> +#define XUSB_CFG_ARU_MBOX_CMD                  0xe4
>> +#define  MBOX_FALC_INT_EN                      BIT(27)
>> +#define  MBOX_PME_INT_EN                       BIT(28)
>> +#define  MBOX_SMI_INT_EN                       BIT(29)
>> +#define  MBOX_XHCI_INT_EN                      BIT(30)
>> +#define  MBOX_INT_EN                           BIT(31)
>
>
> Those field names don't match the documentation in the TRM; they're called
> DEST_xxx rather than xxx_INT_EN. I'm not sure what that disconnect means
> (i.e. whether it's just a different naming choice, or there's some practical
> disconnect that will cause issues.)

Hmm... interestingly *_INT_EN is the convention the downstream kernels
used.  DEST_* is definitely more accurate as I'm pretty sure these
bits select the destination for the interrupt.

>> +static struct mbox_chan *mbox_cmd_to_chan(struct tegra_xusb_mbox *mbox,
>> u32 cmd)
>> +{
>> +       switch (cmd) {
>> +       case MBOX_CMD_INC_FALC_CLOCK:
>> +       case MBOX_CMD_DEC_FALC_CLOCK:
>> +       case MBOX_CMD_INC_SSPI_CLOCK:
>> +       case MBOX_CMD_DEC_SSPI_CLOCK:
>> +       case MBOX_CMD_SET_BW:
>> +               return &mbox->mbox.chans[TEGRA_XUSB_MBOX_CHAN_HOST];
>> +       case MBOX_CMD_SAVE_DFE_CTLE_CTX:
>> +       case MBOX_CMD_START_HSIC_IDLE:
>> +       case MBOX_CMD_STOP_HSIC_IDLE:
>> +               return &mbox->mbox.chans[TEGRA_XUSB_MBOX_CHAN_PHY];
>> +       default:
>> +               return NULL;
>> +       }
>> +}
>
>
> This makes me think that the CHAN_HOST/CHAN_PHY values are purely a facet of
> the Linux driver's message de-multiplexing, rather than anything to do with
> the HW.

Yup, they are...

> I'm not even sure if it's appropriate for the low-level mailbox driver to
> know about the semantics of the message, rather than simply sending them on
> to the client driver? Perhaps when drivers register(?) for callbacks(?) for
> messages, they should state which types of messages they want to listen to?

So there's not really a way for the client driver to tell the mailbox
driver which types of messages it wants to listen to on a particular
channel with the mailbox framework - it simply provides a way for
clients to bind with channels.  I think there are a couple of options
here, either: a) have a channel per message (as you mentioned in the
previous patch), which allows the client to only register for messages
(channels) it wants to handle, or b) extend the mailbox framework to
allow shared channels so that both clients can receive messages on the
single channel and handle messages appropriately.   The disadvantage
of (a) is that the commands are firmware defined and could
theoretically change between releases of the firmware, though I'm not
sure how common that is in practice.  So that leaves (b) - Jassi, what
do you think about having shared (non-exclusive) channels?

>> +static irqreturn_t tegra_xusb_mbox_irq(int irq, void *p)
>
>
>> +       /* Clear mbox interrupts */
>>
>> +       reg = mbox_readl(mbox, XUSB_CFG_ARU_SMI_INTR);
>> +       if (reg & MBOX_SMI_INTR_FW_HANG)
>> +               dev_err(mbox->mbox.dev, "Controller firmware hang\n");
>> +       mbox_writel(mbox, reg, XUSB_CFG_ARU_SMI_INTR);
>
>
>> +       /*
>>
>> +        * Set the mailbox back to idle.  The recipient of the message is
>> +        * responsible for sending an ACK/NAK, if necessary.
>> +        */
>> +       reg = mbox_readl(mbox, XUSB_CFG_ARU_MBOX_CMD);
>> +       reg &= ~MBOX_SMI_INT_EN;
>> +       mbox_writel(mbox, reg, XUSB_CFG_ARU_MBOX_CMD);
>
>
> Does the protocol not allow the remote firmware to send another message
> until the host has ack'd/nak'd the message; the code above turns off the IRQ
> that indicated to the host that a message was sent to it...

While the firmware generally will not send another message until the
previous one is ACK'd/NAK'd (with the exception of the SET_BW
command), the above does not prevent it from doing so.  I believe the
controller sets up the DEST_* bits properly before sending another
message.

>> +static int tegra_xusb_mbox_probe(struct platform_device *pdev)
>
>
>> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>
>> +       if (!res)
>> +               return -ENODEV;
>
>
> Should devm_request_mem_region() be called here to claim the region?

No, the xHCI host driver also needs to map these registers, so they
cannot be mapped exclusively here.

>> +       mbox->regs = devm_ioremap_nocache(&pdev->dev, res->start,
>> +                                         resource_size(res));
>> +       if (!mbox->regs)
>> +               return -ENOMEM;
>
>
> Is _nocache required? I don't see other drivers using it. I assume there's
> nothing special about the mbox registers.

I'll drop the _nocache.

>> +       mbox->irq = platform_get_irq(pdev, 0);
>> +       if (mbox->irq < 0)
>> +               return mbox->irq;
>> +       ret = devm_request_irq(&pdev->dev, mbox->irq, tegra_xusb_mbox_irq,
>> 0,
>> +                              dev_name(&pdev->dev), mbox);
>
>
> Is it possible for an IRQ to occur after tegra_xusb_mbox_remove() has
> returned, but before the cleanup for the devm IRQ allocation occurs? If that
> happens, will the code handle it gracefully, or crash?

It looks like mbox_chan_received_data() will crash if the channel is
unbound, so yes, this needs to be fixed.

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
  2014-08-27 17:38         ` Andrew Bresticker
  (?)
@ 2014-08-27 17:50           ` Stephen Warren
  -1 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-27 17:50 UTC (permalink / raw)
  To: Andrew Bresticker, Jassi Brar
  Cc: Thierry Reding, linux-tegra, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Linus Walleij, Greg Kroah-Hartman, Mathias Nyman, Grant Likely,
	Alan Stern, Arnd Bergmann, Kishon Vijay Abraham I, devicetree,
	linux-kernel, linux-arm-kernel, linux-usb

On 08/27/2014 11:38 AM, Andrew Bresticker wrote:
> On Mon, Aug 25, 2014 at 12:01 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>>
>>> The Tegra xHCI controller's firmware communicates requests to the host
>>> processor through a mailbox interface.  While there is only a single
>>> communication channel, messages sent by the controller can be divided
>>> into two groups: those intended for the PHY driver and those intended
>>> for the host-controller driver.  This mailbox driver exposes the two
>>> channels and routes incoming messages to the appropriate channel based
>>> on the command encoded in the message.
>>
>>
>>> diff --git a/drivers/mailbox/tegra-xusb-mailbox.c
>>> b/drivers/mailbox/tegra-xusb-mailbox.c

>>> +static struct mbox_chan *mbox_cmd_to_chan(struct tegra_xusb_mbox *mbox,
>>> u32 cmd)
>>> +{
>>> +       switch (cmd) {
>>> +       case MBOX_CMD_INC_FALC_CLOCK:
>>> +       case MBOX_CMD_DEC_FALC_CLOCK:
>>> +       case MBOX_CMD_INC_SSPI_CLOCK:
>>> +       case MBOX_CMD_DEC_SSPI_CLOCK:
>>> +       case MBOX_CMD_SET_BW:
>>> +               return &mbox->mbox.chans[TEGRA_XUSB_MBOX_CHAN_HOST];
>>> +       case MBOX_CMD_SAVE_DFE_CTLE_CTX:
>>> +       case MBOX_CMD_START_HSIC_IDLE:
>>> +       case MBOX_CMD_STOP_HSIC_IDLE:
>>> +               return &mbox->mbox.chans[TEGRA_XUSB_MBOX_CHAN_PHY];
>>> +       default:
>>> +               return NULL;
>>> +       }
>>> +}
>>
>>
>> This makes me think that the CHAN_HOST/CHAN_PHY values are purely a facet of
>> the Linux driver's message de-multiplexing, rather than anything to do with
>> the HW.
>
> Yup, they are...
>
>> I'm not even sure if it's appropriate for the low-level mailbox driver to
>> know about the semantics of the message, rather than simply sending them on
>> to the client driver? Perhaps when drivers register(?) for callbacks(?) for
>> messages, they should state which types of messages they want to listen to?
>
> So there's not really a way for the client driver to tell the mailbox
> driver which types of messages it wants to listen to on a particular
> channel with the mailbox framework - it simply provides a way for
> clients to bind with channels.  I think there are a couple of options
> here, either: a) have a channel per message (as you mentioned in the
> previous patch), which allows the client to only register for messages
> (channels) it wants to handle, or b) extend the mailbox framework to
> allow shared channels so that both clients can receive messages on the
> single channel and handle messages appropriately.   The disadvantage
> of (a) is that the commands are firmware defined and could
> theoretically change between releases of the firmware, though I'm not
> sure how common that is in practice.  So that leaves (b) - Jassi, what
> do you think about having shared (non-exclusive) channels?

Another alternative might be for each client driver to hard-code a 
unique dummy channel ID so that each client still gets a separate 
exclusive channel, but then have the mbox driver broadcast each message 
to each of those channels. I'm not sure that would be any better though; 
adding (b) as an explicit option to the mbox subsystem would almost 
certainly be cleaner.

>>> +static int tegra_xusb_mbox_probe(struct platform_device *pdev)
>>
>>
>>> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>>
>>> +       if (!res)
>>> +               return -ENODEV;
>>
>>
>> Should devm_request_mem_region() be called here to claim the region?
>
> No, the xHCI host driver also needs to map these registers, so they
> cannot be mapped exclusively here.

That's unfortunate. Having multiple drivers with overlapping register 
regions is not a good idea. Can we instead have a top-level driver map 
all the IO regions, then instantiate the various different 
sub-components internally, and divide up the address space. Probably via 
MFD or similar. That would prevent multiple drivers from touching the 
same register region.

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-27 17:50           ` Stephen Warren
  0 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-27 17:50 UTC (permalink / raw)
  To: Andrew Bresticker, Jassi Brar
  Cc: Thierry Reding, linux-tegra, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Linus Walleij, Greg Kroah-Hartman, Mathias Nyman, Grant Likely,
	Alan Stern, Arnd Bergmann, Kishon Vijay Abraham I, devicetree,
	linux-kernel, linux-arm-kernel, linux-usb

On 08/27/2014 11:38 AM, Andrew Bresticker wrote:
> On Mon, Aug 25, 2014 at 12:01 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>>
>>> The Tegra xHCI controller's firmware communicates requests to the host
>>> processor through a mailbox interface.  While there is only a single
>>> communication channel, messages sent by the controller can be divided
>>> into two groups: those intended for the PHY driver and those intended
>>> for the host-controller driver.  This mailbox driver exposes the two
>>> channels and routes incoming messages to the appropriate channel based
>>> on the command encoded in the message.
>>
>>
>>> diff --git a/drivers/mailbox/tegra-xusb-mailbox.c
>>> b/drivers/mailbox/tegra-xusb-mailbox.c

>>> +static struct mbox_chan *mbox_cmd_to_chan(struct tegra_xusb_mbox *mbox,
>>> u32 cmd)
>>> +{
>>> +       switch (cmd) {
>>> +       case MBOX_CMD_INC_FALC_CLOCK:
>>> +       case MBOX_CMD_DEC_FALC_CLOCK:
>>> +       case MBOX_CMD_INC_SSPI_CLOCK:
>>> +       case MBOX_CMD_DEC_SSPI_CLOCK:
>>> +       case MBOX_CMD_SET_BW:
>>> +               return &mbox->mbox.chans[TEGRA_XUSB_MBOX_CHAN_HOST];
>>> +       case MBOX_CMD_SAVE_DFE_CTLE_CTX:
>>> +       case MBOX_CMD_START_HSIC_IDLE:
>>> +       case MBOX_CMD_STOP_HSIC_IDLE:
>>> +               return &mbox->mbox.chans[TEGRA_XUSB_MBOX_CHAN_PHY];
>>> +       default:
>>> +               return NULL;
>>> +       }
>>> +}
>>
>>
>> This makes me think that the CHAN_HOST/CHAN_PHY values are purely a facet of
>> the Linux driver's message de-multiplexing, rather than anything to do with
>> the HW.
>
> Yup, they are...
>
>> I'm not even sure if it's appropriate for the low-level mailbox driver to
>> know about the semantics of the message, rather than simply sending them on
>> to the client driver? Perhaps when drivers register(?) for callbacks(?) for
>> messages, they should state which types of messages they want to listen to?
>
> So there's not really a way for the client driver to tell the mailbox
> driver which types of messages it wants to listen to on a particular
> channel with the mailbox framework - it simply provides a way for
> clients to bind with channels.  I think there are a couple of options
> here, either: a) have a channel per message (as you mentioned in the
> previous patch), which allows the client to only register for messages
> (channels) it wants to handle, or b) extend the mailbox framework to
> allow shared channels so that both clients can receive messages on the
> single channel and handle messages appropriately.   The disadvantage
> of (a) is that the commands are firmware defined and could
> theoretically change between releases of the firmware, though I'm not
> sure how common that is in practice.  So that leaves (b) - Jassi, what
> do you think about having shared (non-exclusive) channels?

Another alternative might be for each client driver to hard-code a 
unique dummy channel ID so that each client still gets a separate 
exclusive channel, but then have the mbox driver broadcast each message 
to each of those channels. I'm not sure that would be any better though; 
adding (b) as an explicit option to the mbox subsystem would almost 
certainly be cleaner.

>>> +static int tegra_xusb_mbox_probe(struct platform_device *pdev)
>>
>>
>>> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>>
>>> +       if (!res)
>>> +               return -ENODEV;
>>
>>
>> Should devm_request_mem_region() be called here to claim the region?
>
> No, the xHCI host driver also needs to map these registers, so they
> cannot be mapped exclusively here.

That's unfortunate. Having multiple drivers with overlapping register 
regions is not a good idea. Can we instead have a top-level driver map 
all the IO regions, then instantiate the various different 
sub-components internally, and divide up the address space. Probably via 
MFD or similar. That would prevent multiple drivers from touching the 
same register region.

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

* [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-27 17:50           ` Stephen Warren
  0 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-27 17:50 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/27/2014 11:38 AM, Andrew Bresticker wrote:
> On Mon, Aug 25, 2014 at 12:01 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>>
>>> The Tegra xHCI controller's firmware communicates requests to the host
>>> processor through a mailbox interface.  While there is only a single
>>> communication channel, messages sent by the controller can be divided
>>> into two groups: those intended for the PHY driver and those intended
>>> for the host-controller driver.  This mailbox driver exposes the two
>>> channels and routes incoming messages to the appropriate channel based
>>> on the command encoded in the message.
>>
>>
>>> diff --git a/drivers/mailbox/tegra-xusb-mailbox.c
>>> b/drivers/mailbox/tegra-xusb-mailbox.c

>>> +static struct mbox_chan *mbox_cmd_to_chan(struct tegra_xusb_mbox *mbox,
>>> u32 cmd)
>>> +{
>>> +       switch (cmd) {
>>> +       case MBOX_CMD_INC_FALC_CLOCK:
>>> +       case MBOX_CMD_DEC_FALC_CLOCK:
>>> +       case MBOX_CMD_INC_SSPI_CLOCK:
>>> +       case MBOX_CMD_DEC_SSPI_CLOCK:
>>> +       case MBOX_CMD_SET_BW:
>>> +               return &mbox->mbox.chans[TEGRA_XUSB_MBOX_CHAN_HOST];
>>> +       case MBOX_CMD_SAVE_DFE_CTLE_CTX:
>>> +       case MBOX_CMD_START_HSIC_IDLE:
>>> +       case MBOX_CMD_STOP_HSIC_IDLE:
>>> +               return &mbox->mbox.chans[TEGRA_XUSB_MBOX_CHAN_PHY];
>>> +       default:
>>> +               return NULL;
>>> +       }
>>> +}
>>
>>
>> This makes me think that the CHAN_HOST/CHAN_PHY values are purely a facet of
>> the Linux driver's message de-multiplexing, rather than anything to do with
>> the HW.
>
> Yup, they are...
>
>> I'm not even sure if it's appropriate for the low-level mailbox driver to
>> know about the semantics of the message, rather than simply sending them on
>> to the client driver? Perhaps when drivers register(?) for callbacks(?) for
>> messages, they should state which types of messages they want to listen to?
>
> So there's not really a way for the client driver to tell the mailbox
> driver which types of messages it wants to listen to on a particular
> channel with the mailbox framework - it simply provides a way for
> clients to bind with channels.  I think there are a couple of options
> here, either: a) have a channel per message (as you mentioned in the
> previous patch), which allows the client to only register for messages
> (channels) it wants to handle, or b) extend the mailbox framework to
> allow shared channels so that both clients can receive messages on the
> single channel and handle messages appropriately.   The disadvantage
> of (a) is that the commands are firmware defined and could
> theoretically change between releases of the firmware, though I'm not
> sure how common that is in practice.  So that leaves (b) - Jassi, what
> do you think about having shared (non-exclusive) channels?

Another alternative might be for each client driver to hard-code a 
unique dummy channel ID so that each client still gets a separate 
exclusive channel, but then have the mbox driver broadcast each message 
to each of those channels. I'm not sure that would be any better though; 
adding (b) as an explicit option to the mbox subsystem would almost 
certainly be cleaner.

>>> +static int tegra_xusb_mbox_probe(struct platform_device *pdev)
>>
>>
>>> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>>
>>> +       if (!res)
>>> +               return -ENODEV;
>>
>>
>> Should devm_request_mem_region() be called here to claim the region?
>
> No, the xHCI host driver also needs to map these registers, so they
> cannot be mapped exclusively here.

That's unfortunate. Having multiple drivers with overlapping register 
regions is not a good idea. Can we instead have a top-level driver map 
all the IO regions, then instantiate the various different 
sub-components internally, and divide up the address space. Probably via 
MFD or similar. That would prevent multiple drivers from touching the 
same register region.

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
  2014-08-27 17:50           ` Stephen Warren
  (?)
@ 2014-08-27 18:13               ` Andrew Bresticker
  -1 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-27 18:13 UTC (permalink / raw)
  To: Stephen Warren
  Cc: Jassi Brar, Thierry Reding, linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Linus Walleij, Greg Kroah-Hartman, Mathias Nyman,
	Grant Likely, Alan Stern, Arnd Bergmann, Kishon Vijay Abraham I,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TbrhsbdSgBK9A

On Wed, Aug 27, 2014 at 10:50 AM, Stephen Warren <swarren-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org> wrote:
> On 08/27/2014 11:38 AM, Andrew Bresticker wrote:
>>
>> On Mon, Aug 25, 2014 at 12:01 PM, Stephen Warren <swarren-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
>> wrote:
>>>
>>> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>>>
>>>> +static int tegra_xusb_mbox_probe(struct platform_device *pdev)
>>>
>>>
>>>
>>>> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>>>
>>>> +       if (!res)
>>>> +               return -ENODEV;
>>>
>>>
>>>
>>> Should devm_request_mem_region() be called here to claim the region?
>>
>>
>> No, the xHCI host driver also needs to map these registers, so they
>> cannot be mapped exclusively here.
>
>
> That's unfortunate. Having multiple drivers with overlapping register
> regions is not a good idea. Can we instead have a top-level driver map all
> the IO regions, then instantiate the various different sub-components
> internally, and divide up the address space. Probably via MFD or similar.
> That would prevent multiple drivers from touching the same register region.

Perhaps I'm misunderstanding, but I don't see how MFD would prevent us
from having to map this register space in two different locations -
the XUSB FPCI address space cannot be divided cleanly between host and
mailbox registers.  Or are you saying that there should be a separate
device driver that exposes an API for accessing this register space,
like the Tegra fuse or PMC drivers?
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-27 18:13               ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-27 18:13 UTC (permalink / raw)
  To: Stephen Warren
  Cc: Jassi Brar, Thierry Reding, linux-tegra, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Linus Walleij, Greg Kroah-Hartman, Mathias Nyman, Grant Likely,
	Alan Stern, Arnd Bergmann, Kishon Vijay Abraham I, devicetree,
	linux-kernel, linux-arm-kernel, linux-usb

On Wed, Aug 27, 2014 at 10:50 AM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 08/27/2014 11:38 AM, Andrew Bresticker wrote:
>>
>> On Mon, Aug 25, 2014 at 12:01 PM, Stephen Warren <swarren@wwwdotorg.org>
>> wrote:
>>>
>>> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>>>
>>>> +static int tegra_xusb_mbox_probe(struct platform_device *pdev)
>>>
>>>
>>>
>>>> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>>>
>>>> +       if (!res)
>>>> +               return -ENODEV;
>>>
>>>
>>>
>>> Should devm_request_mem_region() be called here to claim the region?
>>
>>
>> No, the xHCI host driver also needs to map these registers, so they
>> cannot be mapped exclusively here.
>
>
> That's unfortunate. Having multiple drivers with overlapping register
> regions is not a good idea. Can we instead have a top-level driver map all
> the IO regions, then instantiate the various different sub-components
> internally, and divide up the address space. Probably via MFD or similar.
> That would prevent multiple drivers from touching the same register region.

Perhaps I'm misunderstanding, but I don't see how MFD would prevent us
from having to map this register space in two different locations -
the XUSB FPCI address space cannot be divided cleanly between host and
mailbox registers.  Or are you saying that there should be a separate
device driver that exposes an API for accessing this register space,
like the Tegra fuse or PMC drivers?

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

* [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-27 18:13               ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-27 18:13 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Aug 27, 2014 at 10:50 AM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 08/27/2014 11:38 AM, Andrew Bresticker wrote:
>>
>> On Mon, Aug 25, 2014 at 12:01 PM, Stephen Warren <swarren@wwwdotorg.org>
>> wrote:
>>>
>>> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>>>
>>>> +static int tegra_xusb_mbox_probe(struct platform_device *pdev)
>>>
>>>
>>>
>>>> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>>>
>>>> +       if (!res)
>>>> +               return -ENODEV;
>>>
>>>
>>>
>>> Should devm_request_mem_region() be called here to claim the region?
>>
>>
>> No, the xHCI host driver also needs to map these registers, so they
>> cannot be mapped exclusively here.
>
>
> That's unfortunate. Having multiple drivers with overlapping register
> regions is not a good idea. Can we instead have a top-level driver map all
> the IO regions, then instantiate the various different sub-components
> internally, and divide up the address space. Probably via MFD or similar.
> That would prevent multiple drivers from touching the same register region.

Perhaps I'm misunderstanding, but I don't see how MFD would prevent us
from having to map this register space in two different locations -
the XUSB FPCI address space cannot be divided cleanly between host and
mailbox registers.  Or are you saying that there should be a separate
device driver that exposes an API for accessing this register space,
like the Tegra fuse or PMC drivers?

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
  2014-08-27 18:13               ` Andrew Bresticker
  (?)
@ 2014-08-27 18:19                   ` Stephen Warren
  -1 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-27 18:19 UTC (permalink / raw)
  To: Andrew Bresticker
  Cc: Jassi Brar, Thierry Reding, linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Linus Walleij, Greg Kroah-Hartman, Mathias Nyman,
	Grant Likely, Alan Stern, Arnd Bergmann, Kishon Vijay Abraham I,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TbrhsbdSgBK9A

On 08/27/2014 12:13 PM, Andrew Bresticker wrote:
> On Wed, Aug 27, 2014 at 10:50 AM, Stephen Warren <swarren-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org> wrote:
>> On 08/27/2014 11:38 AM, Andrew Bresticker wrote:
>>>
>>> On Mon, Aug 25, 2014 at 12:01 PM, Stephen Warren <swarren-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
>>> wrote:
>>>>
>>>> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>>>>
>>>>> +static int tegra_xusb_mbox_probe(struct platform_device *pdev)
>>>>
>>>>
>>>>
>>>>> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>>>>
>>>>> +       if (!res)
>>>>> +               return -ENODEV;
>>>>
>>>>
>>>>
>>>> Should devm_request_mem_region() be called here to claim the region?
>>>
>>>
>>> No, the xHCI host driver also needs to map these registers, so they
>>> cannot be mapped exclusively here.
>>
>>
>> That's unfortunate. Having multiple drivers with overlapping register
>> regions is not a good idea. Can we instead have a top-level driver map all
>> the IO regions, then instantiate the various different sub-components
>> internally, and divide up the address space. Probably via MFD or similar.
>> That would prevent multiple drivers from touching the same register region.
>
> Perhaps I'm misunderstanding, but I don't see how MFD would prevent us
> from having to map this register space in two different locations -
> the XUSB FPCI address space cannot be divided cleanly between host and
> mailbox registers.  Or are you saying that there should be a separate
> device driver that exposes an API for accessing this register space,
> like the Tegra fuse or PMC drivers?

With MFD, there's typically a top-level driver for the HW module (or 
register space) that gets instantiated by the DT node. This driver then 
instantiates all the different sub-drivers that use that register space, 
and provides APIs for the sub-drivers to access the registers (either 
custom APIs or more recently by passing a regmap object down to the 
sub-drivers).

This top-level driver is the only driver that maps the space, and can 
manage sharing the space between the various sub-drivers.

That said, I haven't noticed many MFD drivers for MMIO devices. I 
certainly have seen multiple different drivers just re-mapping shared 
registers for themselves. It is simpler and does work. However, people 
usually mutter about it when it happens, since it's not clear which 
drivers are using what from the IO mapping registry. Using MFD or 
similar would allow the sharing to work in a clean fashion.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-27 18:19                   ` Stephen Warren
  0 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-27 18:19 UTC (permalink / raw)
  To: Andrew Bresticker
  Cc: Jassi Brar, Thierry Reding, linux-tegra, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Linus Walleij, Greg Kroah-Hartman, Mathias Nyman, Grant Likely,
	Alan Stern, Arnd Bergmann, Kishon Vijay Abraham I, devicetree,
	linux-kernel, linux-arm-kernel, linux-usb

On 08/27/2014 12:13 PM, Andrew Bresticker wrote:
> On Wed, Aug 27, 2014 at 10:50 AM, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> On 08/27/2014 11:38 AM, Andrew Bresticker wrote:
>>>
>>> On Mon, Aug 25, 2014 at 12:01 PM, Stephen Warren <swarren@wwwdotorg.org>
>>> wrote:
>>>>
>>>> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>>>>
>>>>> +static int tegra_xusb_mbox_probe(struct platform_device *pdev)
>>>>
>>>>
>>>>
>>>>> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>>>>
>>>>> +       if (!res)
>>>>> +               return -ENODEV;
>>>>
>>>>
>>>>
>>>> Should devm_request_mem_region() be called here to claim the region?
>>>
>>>
>>> No, the xHCI host driver also needs to map these registers, so they
>>> cannot be mapped exclusively here.
>>
>>
>> That's unfortunate. Having multiple drivers with overlapping register
>> regions is not a good idea. Can we instead have a top-level driver map all
>> the IO regions, then instantiate the various different sub-components
>> internally, and divide up the address space. Probably via MFD or similar.
>> That would prevent multiple drivers from touching the same register region.
>
> Perhaps I'm misunderstanding, but I don't see how MFD would prevent us
> from having to map this register space in two different locations -
> the XUSB FPCI address space cannot be divided cleanly between host and
> mailbox registers.  Or are you saying that there should be a separate
> device driver that exposes an API for accessing this register space,
> like the Tegra fuse or PMC drivers?

With MFD, there's typically a top-level driver for the HW module (or 
register space) that gets instantiated by the DT node. This driver then 
instantiates all the different sub-drivers that use that register space, 
and provides APIs for the sub-drivers to access the registers (either 
custom APIs or more recently by passing a regmap object down to the 
sub-drivers).

This top-level driver is the only driver that maps the space, and can 
manage sharing the space between the various sub-drivers.

That said, I haven't noticed many MFD drivers for MMIO devices. I 
certainly have seen multiple different drivers just re-mapping shared 
registers for themselves. It is simpler and does work. However, people 
usually mutter about it when it happens, since it's not clear which 
drivers are using what from the IO mapping registry. Using MFD or 
similar would allow the sharing to work in a clean fashion.

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

* [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-27 18:19                   ` Stephen Warren
  0 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-27 18:19 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/27/2014 12:13 PM, Andrew Bresticker wrote:
> On Wed, Aug 27, 2014 at 10:50 AM, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> On 08/27/2014 11:38 AM, Andrew Bresticker wrote:
>>>
>>> On Mon, Aug 25, 2014 at 12:01 PM, Stephen Warren <swarren@wwwdotorg.org>
>>> wrote:
>>>>
>>>> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>>>>
>>>>> +static int tegra_xusb_mbox_probe(struct platform_device *pdev)
>>>>
>>>>
>>>>
>>>>> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>>>>
>>>>> +       if (!res)
>>>>> +               return -ENODEV;
>>>>
>>>>
>>>>
>>>> Should devm_request_mem_region() be called here to claim the region?
>>>
>>>
>>> No, the xHCI host driver also needs to map these registers, so they
>>> cannot be mapped exclusively here.
>>
>>
>> That's unfortunate. Having multiple drivers with overlapping register
>> regions is not a good idea. Can we instead have a top-level driver map all
>> the IO regions, then instantiate the various different sub-components
>> internally, and divide up the address space. Probably via MFD or similar.
>> That would prevent multiple drivers from touching the same register region.
>
> Perhaps I'm misunderstanding, but I don't see how MFD would prevent us
> from having to map this register space in two different locations -
> the XUSB FPCI address space cannot be divided cleanly between host and
> mailbox registers.  Or are you saying that there should be a separate
> device driver that exposes an API for accessing this register space,
> like the Tegra fuse or PMC drivers?

With MFD, there's typically a top-level driver for the HW module (or 
register space) that gets instantiated by the DT node. This driver then 
instantiates all the different sub-drivers that use that register space, 
and provides APIs for the sub-drivers to access the registers (either 
custom APIs or more recently by passing a regmap object down to the 
sub-drivers).

This top-level driver is the only driver that maps the space, and can 
manage sharing the space between the various sub-drivers.

That said, I haven't noticed many MFD drivers for MMIO devices. I 
certainly have seen multiple different drivers just re-mapping shared 
registers for themselves. It is simpler and does work. However, people 
usually mutter about it when it happens, since it's not clear which 
drivers are using what from the IO mapping registry. Using MFD or 
similar would allow the sharing to work in a clean fashion.

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
  2014-08-27 17:38         ` Andrew Bresticker
  (?)
@ 2014-08-27 19:26             ` Jassi Brar
  -1 siblings, 0 replies; 141+ messages in thread
From: Jassi Brar @ 2014-08-27 19:26 UTC (permalink / raw)
  To: Andrew Bresticker
  Cc: Stephen Warren, Jassi Brar, Mark Rutland,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Russell King, Mathias Nyman,
	Pawel Moll, Ian Campbell, Greg Kroah-Hartman, Linus Walleij,
	linux-usb-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
	Kishon Vijay Abraham I, Grant Likely, Thierry Reding, Alan Stern,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Kumar Gala,
	linux-tegra

On 27 August 2014 23:08, Andrew Bresticker <abrestic-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org> wrote:
> On Mon, Aug 25, 2014 at 12:01 PM, Stephen Warren <swarren-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org> wrote:

>> I'm not even sure if it's appropriate for the low-level mailbox driver to
>> know about the semantics of the message, rather than simply sending them on
>> to the client driver? Perhaps when drivers register(?) for callbacks(?) for
>> messages, they should state which types of messages they want to listen to?
>
> So there's not really a way for the client driver to tell the mailbox
> driver which types of messages it wants to listen to on a particular
> channel with the mailbox framework - it simply provides a way for
> clients to bind with channels.  I think there are a couple of options
> here, either: a) have a channel per message (as you mentioned in the
> previous patch), which allows the client to only register for messages
> (channels) it wants to handle, or b) extend the mailbox framework to
> allow shared channels so that both clients can receive messages on the
> single channel and handle messages appropriately.   The disadvantage
> of (a) is that the commands are firmware defined and could
> theoretically change between releases of the firmware, though I'm not
> sure how common that is in practice.  So that leaves (b) - Jassi, what
> do you think about having shared (non-exclusive) channels?
>
n++ ... 'mailbox' is one such device that imbibes properties of local
controller hardware and the remote firmware. Change in remote f/w's
behavior might require the controller driver to change besides our
client driver. A typical example is format of payloads (if
involved).... a client and mailbox controller driver have direct
understanding of the packet format ... which is likely to change with
remote f/w.  So if the original concern "why are we doing s/w protocol
stuff in controller driver?" won't go away by providing for shared
channels (which would have its own tradeoffs).

BTW, on DMAEngine we are moving towards virtual channels backed by
limited physical ones ... your setup looks quite similar. So your
demuxer doesn't hurt my eyes at all.

-jassi

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-27 19:26             ` Jassi Brar
  0 siblings, 0 replies; 141+ messages in thread
From: Jassi Brar @ 2014-08-27 19:26 UTC (permalink / raw)
  To: Andrew Bresticker
  Cc: Stephen Warren, Jassi Brar, Mark Rutland, devicetree,
	Russell King, Mathias Nyman, Pawel Moll, Ian Campbell,
	Greg Kroah-Hartman, Linus Walleij, linux-usb, linux-kernel,
	Rob Herring, Kishon Vijay Abraham I, Grant Likely,
	Thierry Reding, Alan Stern, linux-arm-kernel, Kumar Gala,
	linux-tegra, Arnd Bergmann

On 27 August 2014 23:08, Andrew Bresticker <abrestic@chromium.org> wrote:
> On Mon, Aug 25, 2014 at 12:01 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:

>> I'm not even sure if it's appropriate for the low-level mailbox driver to
>> know about the semantics of the message, rather than simply sending them on
>> to the client driver? Perhaps when drivers register(?) for callbacks(?) for
>> messages, they should state which types of messages they want to listen to?
>
> So there's not really a way for the client driver to tell the mailbox
> driver which types of messages it wants to listen to on a particular
> channel with the mailbox framework - it simply provides a way for
> clients to bind with channels.  I think there are a couple of options
> here, either: a) have a channel per message (as you mentioned in the
> previous patch), which allows the client to only register for messages
> (channels) it wants to handle, or b) extend the mailbox framework to
> allow shared channels so that both clients can receive messages on the
> single channel and handle messages appropriately.   The disadvantage
> of (a) is that the commands are firmware defined and could
> theoretically change between releases of the firmware, though I'm not
> sure how common that is in practice.  So that leaves (b) - Jassi, what
> do you think about having shared (non-exclusive) channels?
>
n++ ... 'mailbox' is one such device that imbibes properties of local
controller hardware and the remote firmware. Change in remote f/w's
behavior might require the controller driver to change besides our
client driver. A typical example is format of payloads (if
involved).... a client and mailbox controller driver have direct
understanding of the packet format ... which is likely to change with
remote f/w.  So if the original concern "why are we doing s/w protocol
stuff in controller driver?" won't go away by providing for shared
channels (which would have its own tradeoffs).

BTW, on DMAEngine we are moving towards virtual channels backed by
limited physical ones ... your setup looks quite similar. So your
demuxer doesn't hurt my eyes at all.

-jassi

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

* [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-27 19:26             ` Jassi Brar
  0 siblings, 0 replies; 141+ messages in thread
From: Jassi Brar @ 2014-08-27 19:26 UTC (permalink / raw)
  To: linux-arm-kernel

On 27 August 2014 23:08, Andrew Bresticker <abrestic@chromium.org> wrote:
> On Mon, Aug 25, 2014 at 12:01 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:

>> I'm not even sure if it's appropriate for the low-level mailbox driver to
>> know about the semantics of the message, rather than simply sending them on
>> to the client driver? Perhaps when drivers register(?) for callbacks(?) for
>> messages, they should state which types of messages they want to listen to?
>
> So there's not really a way for the client driver to tell the mailbox
> driver which types of messages it wants to listen to on a particular
> channel with the mailbox framework - it simply provides a way for
> clients to bind with channels.  I think there are a couple of options
> here, either: a) have a channel per message (as you mentioned in the
> previous patch), which allows the client to only register for messages
> (channels) it wants to handle, or b) extend the mailbox framework to
> allow shared channels so that both clients can receive messages on the
> single channel and handle messages appropriately.   The disadvantage
> of (a) is that the commands are firmware defined and could
> theoretically change between releases of the firmware, though I'm not
> sure how common that is in practice.  So that leaves (b) - Jassi, what
> do you think about having shared (non-exclusive) channels?
>
n++ ... 'mailbox' is one such device that imbibes properties of local
controller hardware and the remote firmware. Change in remote f/w's
behavior might require the controller driver to change besides our
client driver. A typical example is format of payloads (if
involved).... a client and mailbox controller driver have direct
understanding of the packet format ... which is likely to change with
remote f/w.  So if the original concern "why are we doing s/w protocol
stuff in controller driver?" won't go away by providing for shared
channels (which would have its own tradeoffs).

BTW, on DMAEngine we are moving towards virtual channels backed by
limited physical ones ... your setup looks quite similar. So your
demuxer doesn't hurt my eyes at all.

-jassi

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
  2014-08-27 18:19                   ` Stephen Warren
  (?)
@ 2014-08-27 21:56                     ` Andrew Bresticker
  -1 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-27 21:56 UTC (permalink / raw)
  To: Stephen Warren
  Cc: Jassi Brar, Thierry Reding, linux-tegra, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Linus Walleij, Greg Kroah-Hartman, Mathias Nyman, Grant Likely,
	Alan Stern, Arnd Bergmann, Kishon Vijay Abraham I, devicetree,
	linux-kernel, linux-arm-kernel, linux-usb

On Wed, Aug 27, 2014 at 11:19 AM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 08/27/2014 12:13 PM, Andrew Bresticker wrote:
>>
>> On Wed, Aug 27, 2014 at 10:50 AM, Stephen Warren <swarren@wwwdotorg.org>
>> wrote:
>>>
>>> On 08/27/2014 11:38 AM, Andrew Bresticker wrote:
>>>>
>>>>
>>>> On Mon, Aug 25, 2014 at 12:01 PM, Stephen Warren <swarren@wwwdotorg.org>
>>>> wrote:
>>>>>
>>>>>
>>>>> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>>>>>
>>>>>>
>>>>>> +static int tegra_xusb_mbox_probe(struct platform_device *pdev)
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>>>>>
>>>>>> +       if (!res)
>>>>>> +               return -ENODEV;
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> Should devm_request_mem_region() be called here to claim the region?
>>>>
>>>>
>>>>
>>>> No, the xHCI host driver also needs to map these registers, so they
>>>> cannot be mapped exclusively here.
>>>
>>>
>>>
>>> That's unfortunate. Having multiple drivers with overlapping register
>>> regions is not a good idea. Can we instead have a top-level driver map
>>> all
>>> the IO regions, then instantiate the various different sub-components
>>> internally, and divide up the address space. Probably via MFD or similar.
>>> That would prevent multiple drivers from touching the same register
>>> region.
>>
>>
>> Perhaps I'm misunderstanding, but I don't see how MFD would prevent us
>> from having to map this register space in two different locations -
>> the XUSB FPCI address space cannot be divided cleanly between host and
>> mailbox registers.  Or are you saying that there should be a separate
>> device driver that exposes an API for accessing this register space,
>> like the Tegra fuse or PMC drivers?
>
>
> With MFD, there's typically a top-level driver for the HW module (or
> register space) that gets instantiated by the DT node. This driver then
> instantiates all the different sub-drivers that use that register space, and
> provides APIs for the sub-drivers to access the registers (either custom
> APIs or more recently by passing a regmap object down to the sub-drivers).
>
> This top-level driver is the only driver that maps the space, and can manage
> sharing the space between the various sub-drivers.

So if I'm understanding correctly, we end up with something like this:

usb@70090000 {
        compatible = "nvidia,tegra124-xusb";
        reg = <0x0 0x70090000 0x0 0x8000>, // xHCI host registers
              <0x0 0x70098000 0x0 0x1000>, // FPCI registers
              <0x0 0x70099000 0x0 0x1000>; // IPFS registers
        interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>, // host interrupt
                     <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH"; // mailbox interrupt

        host-controller {
                compatible = "nvidia,tegra124-xhci";
                ...
        };

        mailbox {
                compatible = "nvidia,tegra124-xusb-mailbox";
               ...
        };
};

To be honest though, this seems like overkill to share a couple of
registers when no other resources are shared between the two.

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-27 21:56                     ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-27 21:56 UTC (permalink / raw)
  To: Stephen Warren
  Cc: Jassi Brar, Thierry Reding, linux-tegra, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Linus Walleij, Greg Kroah-Hartman, Mathias Nyman, Grant Likely,
	Alan Stern, Arnd Bergmann, Kishon Vijay Abraham I, devicetree,
	linux-kernel, linux-arm-kernel, linux-usb

On Wed, Aug 27, 2014 at 11:19 AM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 08/27/2014 12:13 PM, Andrew Bresticker wrote:
>>
>> On Wed, Aug 27, 2014 at 10:50 AM, Stephen Warren <swarren@wwwdotorg.org>
>> wrote:
>>>
>>> On 08/27/2014 11:38 AM, Andrew Bresticker wrote:
>>>>
>>>>
>>>> On Mon, Aug 25, 2014 at 12:01 PM, Stephen Warren <swarren@wwwdotorg.org>
>>>> wrote:
>>>>>
>>>>>
>>>>> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>>>>>
>>>>>>
>>>>>> +static int tegra_xusb_mbox_probe(struct platform_device *pdev)
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>>>>>
>>>>>> +       if (!res)
>>>>>> +               return -ENODEV;
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> Should devm_request_mem_region() be called here to claim the region?
>>>>
>>>>
>>>>
>>>> No, the xHCI host driver also needs to map these registers, so they
>>>> cannot be mapped exclusively here.
>>>
>>>
>>>
>>> That's unfortunate. Having multiple drivers with overlapping register
>>> regions is not a good idea. Can we instead have a top-level driver map
>>> all
>>> the IO regions, then instantiate the various different sub-components
>>> internally, and divide up the address space. Probably via MFD or similar.
>>> That would prevent multiple drivers from touching the same register
>>> region.
>>
>>
>> Perhaps I'm misunderstanding, but I don't see how MFD would prevent us
>> from having to map this register space in two different locations -
>> the XUSB FPCI address space cannot be divided cleanly between host and
>> mailbox registers.  Or are you saying that there should be a separate
>> device driver that exposes an API for accessing this register space,
>> like the Tegra fuse or PMC drivers?
>
>
> With MFD, there's typically a top-level driver for the HW module (or
> register space) that gets instantiated by the DT node. This driver then
> instantiates all the different sub-drivers that use that register space, and
> provides APIs for the sub-drivers to access the registers (either custom
> APIs or more recently by passing a regmap object down to the sub-drivers).
>
> This top-level driver is the only driver that maps the space, and can manage
> sharing the space between the various sub-drivers.

So if I'm understanding correctly, we end up with something like this:

usb@70090000 {
        compatible = "nvidia,tegra124-xusb";
        reg = <0x0 0x70090000 0x0 0x8000>, // xHCI host registers
              <0x0 0x70098000 0x0 0x1000>, // FPCI registers
              <0x0 0x70099000 0x0 0x1000>; // IPFS registers
        interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>, // host interrupt
                     <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH"; // mailbox interrupt

        host-controller {
                compatible = "nvidia,tegra124-xhci";
                ...
        };

        mailbox {
                compatible = "nvidia,tegra124-xusb-mailbox";
               ...
        };
};

To be honest though, this seems like overkill to share a couple of
registers when no other resources are shared between the two.

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

* [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-27 21:56                     ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-27 21:56 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Aug 27, 2014 at 11:19 AM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 08/27/2014 12:13 PM, Andrew Bresticker wrote:
>>
>> On Wed, Aug 27, 2014 at 10:50 AM, Stephen Warren <swarren@wwwdotorg.org>
>> wrote:
>>>
>>> On 08/27/2014 11:38 AM, Andrew Bresticker wrote:
>>>>
>>>>
>>>> On Mon, Aug 25, 2014 at 12:01 PM, Stephen Warren <swarren@wwwdotorg.org>
>>>> wrote:
>>>>>
>>>>>
>>>>> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>>>>>
>>>>>>
>>>>>> +static int tegra_xusb_mbox_probe(struct platform_device *pdev)
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>>>>>
>>>>>> +       if (!res)
>>>>>> +               return -ENODEV;
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> Should devm_request_mem_region() be called here to claim the region?
>>>>
>>>>
>>>>
>>>> No, the xHCI host driver also needs to map these registers, so they
>>>> cannot be mapped exclusively here.
>>>
>>>
>>>
>>> That's unfortunate. Having multiple drivers with overlapping register
>>> regions is not a good idea. Can we instead have a top-level driver map
>>> all
>>> the IO regions, then instantiate the various different sub-components
>>> internally, and divide up the address space. Probably via MFD or similar.
>>> That would prevent multiple drivers from touching the same register
>>> region.
>>
>>
>> Perhaps I'm misunderstanding, but I don't see how MFD would prevent us
>> from having to map this register space in two different locations -
>> the XUSB FPCI address space cannot be divided cleanly between host and
>> mailbox registers.  Or are you saying that there should be a separate
>> device driver that exposes an API for accessing this register space,
>> like the Tegra fuse or PMC drivers?
>
>
> With MFD, there's typically a top-level driver for the HW module (or
> register space) that gets instantiated by the DT node. This driver then
> instantiates all the different sub-drivers that use that register space, and
> provides APIs for the sub-drivers to access the registers (either custom
> APIs or more recently by passing a regmap object down to the sub-drivers).
>
> This top-level driver is the only driver that maps the space, and can manage
> sharing the space between the various sub-drivers.

So if I'm understanding correctly, we end up with something like this:

usb at 70090000 {
        compatible = "nvidia,tegra124-xusb";
        reg = <0x0 0x70090000 0x0 0x8000>, // xHCI host registers
              <0x0 0x70098000 0x0 0x1000>, // FPCI registers
              <0x0 0x70099000 0x0 0x1000>; // IPFS registers
        interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>, // host interrupt
                     <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH"; // mailbox interrupt

        host-controller {
                compatible = "nvidia,tegra124-xhci";
                ...
        };

        mailbox {
                compatible = "nvidia,tegra124-xusb-mailbox";
               ...
        };
};

To be honest though, this seems like overkill to share a couple of
registers when no other resources are shared between the two.

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
  2014-08-27 21:56                     ` Andrew Bresticker
  (?)
@ 2014-08-27 22:30                         ` Stephen Warren
  -1 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-27 22:30 UTC (permalink / raw)
  To: Andrew Bresticker
  Cc: Jassi Brar, Thierry Reding, linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Linus Walleij, Greg Kroah-Hartman, Mathias Nyman,
	Grant Likely, Alan Stern, Arnd Bergmann, Kishon Vijay Abraham I,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-usb-u79uwXL29TbrhsbdSgBK9A

On 08/27/2014 03:56 PM, Andrew Bresticker wrote:
> On Wed, Aug 27, 2014 at 11:19 AM, Stephen Warren <swarren-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org> wrote:
>> On 08/27/2014 12:13 PM, Andrew Bresticker wrote:
>>>
>>> On Wed, Aug 27, 2014 at 10:50 AM, Stephen Warren <swarren-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
>>> wrote:
>>>>
>>>> On 08/27/2014 11:38 AM, Andrew Bresticker wrote:
>>>>>
>>>>>
>>>>> On Mon, Aug 25, 2014 at 12:01 PM, Stephen Warren <swarren-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
>>>>> wrote:
>>>>>>
>>>>>>
>>>>>> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>>>>>>
>>>>>>>
>>>>>>> +static int tegra_xusb_mbox_probe(struct platform_device *pdev)
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>>>>>>
>>>>>>> +       if (!res)
>>>>>>> +               return -ENODEV;
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> Should devm_request_mem_region() be called here to claim the region?
>>>>>
>>>>>
>>>>>
>>>>> No, the xHCI host driver also needs to map these registers, so they
>>>>> cannot be mapped exclusively here.
>>>>
>>>>
>>>>
>>>> That's unfortunate. Having multiple drivers with overlapping register
>>>> regions is not a good idea. Can we instead have a top-level driver map
>>>> all
>>>> the IO regions, then instantiate the various different sub-components
>>>> internally, and divide up the address space. Probably via MFD or similar.
>>>> That would prevent multiple drivers from touching the same register
>>>> region.
>>>
>>>
>>> Perhaps I'm misunderstanding, but I don't see how MFD would prevent us
>>> from having to map this register space in two different locations -
>>> the XUSB FPCI address space cannot be divided cleanly between host and
>>> mailbox registers.  Or are you saying that there should be a separate
>>> device driver that exposes an API for accessing this register space,
>>> like the Tegra fuse or PMC drivers?
>>
>>
>> With MFD, there's typically a top-level driver for the HW module (or
>> register space) that gets instantiated by the DT node. This driver then
>> instantiates all the different sub-drivers that use that register space, and
>> provides APIs for the sub-drivers to access the registers (either custom
>> APIs or more recently by passing a regmap object down to the sub-drivers).
>>
>> This top-level driver is the only driver that maps the space, and can manage
>> sharing the space between the various sub-drivers.
>
> So if I'm understanding correctly, we end up with something like this:
>
> usb@70090000 {
>          compatible = "nvidia,tegra124-xusb";
>          reg = <0x0 0x70090000 0x0 0x8000>, // xHCI host registers
>                <0x0 0x70098000 0x0 0x1000>, // FPCI registers
>                <0x0 0x70099000 0x0 0x1000>; // IPFS registers
>          interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>, // host interrupt
>                       <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH"; // mailbox interrupt
>
>          host-controller {
>                  compatible = "nvidia,tegra124-xhci";
>                  ...
>          };
>
>          mailbox {
>                  compatible = "nvidia,tegra124-xusb-mailbox";
>                 ...
>          };
> };
>
> To be honest though, this seems like overkill to share a couple of
> registers when no other resources are shared between the two.

Something like that, yes.

Given that the "xusb" driver knows that its HW module contains both an 
XHCI and XUSB mailbox chunk, those might not need to appear inside the 
main XUSB module, but could be hard-coded into the driver. They might 
serve as convenient containers for sub-device-specific properties though.

Other alternatives might be:

a) If the registers that are shared between drivers are distinct, then 
divide the reg values into non-overlapping lists. We have taken this 
approach for the MC/SMMU drivers on Tegra, although it's a horrible mess 
and Thierry is actively thinking about reverting that and doing it 
through MFD or something MFD-like.

b) Allow the same IO region to be claimed by multiple devices, perhaps 
with a new API so that it doesn't accidentally happen when not desired.

c) Ignore the issue and deal with the fact that not all driver usage 
shows up in /proc/iomem. This is what we have for the Tegra USB2 and 
USB2 PHY drivers, and this is (I think) what your current patch does.

To be honest, none of the options are that good; some end up with the 
correct result but are a pain to implement, but others are nice and 
simple yet /proc/iomem isn't complete. Given that, I'm personally not 
going to try and mandate one option or the other, so the current patch 
is fine. Food for thought though:-)

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-27 22:30                         ` Stephen Warren
  0 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-27 22:30 UTC (permalink / raw)
  To: Andrew Bresticker
  Cc: Jassi Brar, Thierry Reding, linux-tegra, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Linus Walleij, Greg Kroah-Hartman, Mathias Nyman, Grant Likely,
	Alan Stern, Arnd Bergmann, Kishon Vijay Abraham I, devicetree,
	linux-kernel, linux-arm-kernel, linux-usb

On 08/27/2014 03:56 PM, Andrew Bresticker wrote:
> On Wed, Aug 27, 2014 at 11:19 AM, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> On 08/27/2014 12:13 PM, Andrew Bresticker wrote:
>>>
>>> On Wed, Aug 27, 2014 at 10:50 AM, Stephen Warren <swarren@wwwdotorg.org>
>>> wrote:
>>>>
>>>> On 08/27/2014 11:38 AM, Andrew Bresticker wrote:
>>>>>
>>>>>
>>>>> On Mon, Aug 25, 2014 at 12:01 PM, Stephen Warren <swarren@wwwdotorg.org>
>>>>> wrote:
>>>>>>
>>>>>>
>>>>>> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>>>>>>
>>>>>>>
>>>>>>> +static int tegra_xusb_mbox_probe(struct platform_device *pdev)
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>>>>>>
>>>>>>> +       if (!res)
>>>>>>> +               return -ENODEV;
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> Should devm_request_mem_region() be called here to claim the region?
>>>>>
>>>>>
>>>>>
>>>>> No, the xHCI host driver also needs to map these registers, so they
>>>>> cannot be mapped exclusively here.
>>>>
>>>>
>>>>
>>>> That's unfortunate. Having multiple drivers with overlapping register
>>>> regions is not a good idea. Can we instead have a top-level driver map
>>>> all
>>>> the IO regions, then instantiate the various different sub-components
>>>> internally, and divide up the address space. Probably via MFD or similar.
>>>> That would prevent multiple drivers from touching the same register
>>>> region.
>>>
>>>
>>> Perhaps I'm misunderstanding, but I don't see how MFD would prevent us
>>> from having to map this register space in two different locations -
>>> the XUSB FPCI address space cannot be divided cleanly between host and
>>> mailbox registers.  Or are you saying that there should be a separate
>>> device driver that exposes an API for accessing this register space,
>>> like the Tegra fuse or PMC drivers?
>>
>>
>> With MFD, there's typically a top-level driver for the HW module (or
>> register space) that gets instantiated by the DT node. This driver then
>> instantiates all the different sub-drivers that use that register space, and
>> provides APIs for the sub-drivers to access the registers (either custom
>> APIs or more recently by passing a regmap object down to the sub-drivers).
>>
>> This top-level driver is the only driver that maps the space, and can manage
>> sharing the space between the various sub-drivers.
>
> So if I'm understanding correctly, we end up with something like this:
>
> usb@70090000 {
>          compatible = "nvidia,tegra124-xusb";
>          reg = <0x0 0x70090000 0x0 0x8000>, // xHCI host registers
>                <0x0 0x70098000 0x0 0x1000>, // FPCI registers
>                <0x0 0x70099000 0x0 0x1000>; // IPFS registers
>          interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>, // host interrupt
>                       <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH"; // mailbox interrupt
>
>          host-controller {
>                  compatible = "nvidia,tegra124-xhci";
>                  ...
>          };
>
>          mailbox {
>                  compatible = "nvidia,tegra124-xusb-mailbox";
>                 ...
>          };
> };
>
> To be honest though, this seems like overkill to share a couple of
> registers when no other resources are shared between the two.

Something like that, yes.

Given that the "xusb" driver knows that its HW module contains both an 
XHCI and XUSB mailbox chunk, those might not need to appear inside the 
main XUSB module, but could be hard-coded into the driver. They might 
serve as convenient containers for sub-device-specific properties though.

Other alternatives might be:

a) If the registers that are shared between drivers are distinct, then 
divide the reg values into non-overlapping lists. We have taken this 
approach for the MC/SMMU drivers on Tegra, although it's a horrible mess 
and Thierry is actively thinking about reverting that and doing it 
through MFD or something MFD-like.

b) Allow the same IO region to be claimed by multiple devices, perhaps 
with a new API so that it doesn't accidentally happen when not desired.

c) Ignore the issue and deal with the fact that not all driver usage 
shows up in /proc/iomem. This is what we have for the Tegra USB2 and 
USB2 PHY drivers, and this is (I think) what your current patch does.

To be honest, none of the options are that good; some end up with the 
correct result but are a pain to implement, but others are nice and 
simple yet /proc/iomem isn't complete. Given that, I'm personally not 
going to try and mandate one option or the other, so the current patch 
is fine. Food for thought though:-)


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

* [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver
@ 2014-08-27 22:30                         ` Stephen Warren
  0 siblings, 0 replies; 141+ messages in thread
From: Stephen Warren @ 2014-08-27 22:30 UTC (permalink / raw)
  To: linux-arm-kernel

On 08/27/2014 03:56 PM, Andrew Bresticker wrote:
> On Wed, Aug 27, 2014 at 11:19 AM, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> On 08/27/2014 12:13 PM, Andrew Bresticker wrote:
>>>
>>> On Wed, Aug 27, 2014 at 10:50 AM, Stephen Warren <swarren@wwwdotorg.org>
>>> wrote:
>>>>
>>>> On 08/27/2014 11:38 AM, Andrew Bresticker wrote:
>>>>>
>>>>>
>>>>> On Mon, Aug 25, 2014 at 12:01 PM, Stephen Warren <swarren@wwwdotorg.org>
>>>>> wrote:
>>>>>>
>>>>>>
>>>>>> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>>>>>>
>>>>>>>
>>>>>>> +static int tegra_xusb_mbox_probe(struct platform_device *pdev)
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>>>>>>
>>>>>>> +       if (!res)
>>>>>>> +               return -ENODEV;
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> Should devm_request_mem_region() be called here to claim the region?
>>>>>
>>>>>
>>>>>
>>>>> No, the xHCI host driver also needs to map these registers, so they
>>>>> cannot be mapped exclusively here.
>>>>
>>>>
>>>>
>>>> That's unfortunate. Having multiple drivers with overlapping register
>>>> regions is not a good idea. Can we instead have a top-level driver map
>>>> all
>>>> the IO regions, then instantiate the various different sub-components
>>>> internally, and divide up the address space. Probably via MFD or similar.
>>>> That would prevent multiple drivers from touching the same register
>>>> region.
>>>
>>>
>>> Perhaps I'm misunderstanding, but I don't see how MFD would prevent us
>>> from having to map this register space in two different locations -
>>> the XUSB FPCI address space cannot be divided cleanly between host and
>>> mailbox registers.  Or are you saying that there should be a separate
>>> device driver that exposes an API for accessing this register space,
>>> like the Tegra fuse or PMC drivers?
>>
>>
>> With MFD, there's typically a top-level driver for the HW module (or
>> register space) that gets instantiated by the DT node. This driver then
>> instantiates all the different sub-drivers that use that register space, and
>> provides APIs for the sub-drivers to access the registers (either custom
>> APIs or more recently by passing a regmap object down to the sub-drivers).
>>
>> This top-level driver is the only driver that maps the space, and can manage
>> sharing the space between the various sub-drivers.
>
> So if I'm understanding correctly, we end up with something like this:
>
> usb at 70090000 {
>          compatible = "nvidia,tegra124-xusb";
>          reg = <0x0 0x70090000 0x0 0x8000>, // xHCI host registers
>                <0x0 0x70098000 0x0 0x1000>, // FPCI registers
>                <0x0 0x70099000 0x0 0x1000>; // IPFS registers
>          interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>, // host interrupt
>                       <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH"; // mailbox interrupt
>
>          host-controller {
>                  compatible = "nvidia,tegra124-xhci";
>                  ...
>          };
>
>          mailbox {
>                  compatible = "nvidia,tegra124-xusb-mailbox";
>                 ...
>          };
> };
>
> To be honest though, this seems like overkill to share a couple of
> registers when no other resources are shared between the two.

Something like that, yes.

Given that the "xusb" driver knows that its HW module contains both an 
XHCI and XUSB mailbox chunk, those might not need to appear inside the 
main XUSB module, but could be hard-coded into the driver. They might 
serve as convenient containers for sub-device-specific properties though.

Other alternatives might be:

a) If the registers that are shared between drivers are distinct, then 
divide the reg values into non-overlapping lists. We have taken this 
approach for the MC/SMMU drivers on Tegra, although it's a horrible mess 
and Thierry is actively thinking about reverting that and doing it 
through MFD or something MFD-like.

b) Allow the same IO region to be claimed by multiple devices, perhaps 
with a new API so that it doesn't accidentally happen when not desired.

c) Ignore the issue and deal with the fact that not all driver usage 
shows up in /proc/iomem. This is what we have for the Tegra USB2 and 
USB2 PHY drivers, and this is (I think) what your current patch does.

To be honest, none of the options are that good; some end up with the 
correct result but are a pain to implement, but others are nice and 
simple yet /proc/iomem isn't complete. Given that, I'm personally not 
going to try and mandate one option or the other, so the current patch 
is fine. Food for thought though:-)

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

* Re: [PATCH v2 4/9] pinctrl: tegra-xusb: Add USB PHY support
  2014-08-25 19:22       ` Stephen Warren
  (?)
@ 2014-08-29 13:36           ` Linus Walleij
  -1 siblings, 0 replies; 141+ messages in thread
From: Linus Walleij @ 2014-08-29 13:36 UTC (permalink / raw)
  To: Stephen Warren
  Cc: Andrew Bresticker, Thierry Reding, Mikko Perttunen,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King, Jassi Brar,
	Greg Kroah-Hartman, Mathias Nyman, Grant Likely, Alan Stern,
	Arnd Bergmann, Kishon Vijay Abraham I,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org

On Mon, Aug 25, 2014 at 9:22 PM, Stephen Warren <swarren-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org> wrote:
> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>
>> In addition to the PCIe and SATA PHYs, the XUSB pad controller also
>> supports 3 UTMI, 2 HSIC, and 2 USB3 PHYs.  Each USB3 PHY uses a single
>> PCIe or SATA lane and is mapped to one of the three UTMI ports.
>>
>> The xHCI controller will also send messages intended for the PHY driver,
>> so request and listen for messages on the mailbox's PHY channel.
>
>
> I'd like a review from Thierry here as the HW expert.
>
> I need an ack from LinusW in order to take this pinctrl patch through the
> Tegra tree.

Acked-by: Linus Walleij <linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

Yours,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH v2 4/9] pinctrl: tegra-xusb: Add USB PHY support
@ 2014-08-29 13:36           ` Linus Walleij
  0 siblings, 0 replies; 141+ messages in thread
From: Linus Walleij @ 2014-08-29 13:36 UTC (permalink / raw)
  To: Stephen Warren
  Cc: Andrew Bresticker, Thierry Reding, Mikko Perttunen, linux-tegra,
	Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	Russell King, Jassi Brar, Greg Kroah-Hartman, Mathias Nyman,
	Grant Likely, Alan Stern, Arnd Bergmann, Kishon Vijay Abraham I,
	devicetree, linux-kernel, linux-arm-kernel, linux-usb

On Mon, Aug 25, 2014 at 9:22 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>
>> In addition to the PCIe and SATA PHYs, the XUSB pad controller also
>> supports 3 UTMI, 2 HSIC, and 2 USB3 PHYs.  Each USB3 PHY uses a single
>> PCIe or SATA lane and is mapped to one of the three UTMI ports.
>>
>> The xHCI controller will also send messages intended for the PHY driver,
>> so request and listen for messages on the mailbox's PHY channel.
>
>
> I'd like a review from Thierry here as the HW expert.
>
> I need an ack from LinusW in order to take this pinctrl patch through the
> Tegra tree.

Acked-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

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

* [PATCH v2 4/9] pinctrl: tegra-xusb: Add USB PHY support
@ 2014-08-29 13:36           ` Linus Walleij
  0 siblings, 0 replies; 141+ messages in thread
From: Linus Walleij @ 2014-08-29 13:36 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Aug 25, 2014 at 9:22 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 08/18/2014 11:08 AM, Andrew Bresticker wrote:
>>
>> In addition to the PCIe and SATA PHYs, the XUSB pad controller also
>> supports 3 UTMI, 2 HSIC, and 2 USB3 PHYs.  Each USB3 PHY uses a single
>> PCIe or SATA lane and is mapped to one of the three UTMI ports.
>>
>> The xHCI controller will also send messages intended for the PHY driver,
>> so request and listen for messages on the mailbox's PHY channel.
>
>
> I'd like a review from Thierry here as the HW expert.
>
> I need an ack from LinusW in order to take this pinctrl patch through the
> Tegra tree.

Acked-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

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

* Re: [PATCH v2 6/9] usb: xhci: Add NVIDIA Tegra xHCI host-controller driver
  2014-08-18 17:08   ` Andrew Bresticker
@ 2014-08-30 21:15     ` Greg Kroah-Hartman
  -1 siblings, 0 replies; 141+ messages in thread
From: Greg Kroah-Hartman @ 2014-08-30 21:15 UTC (permalink / raw)
  To: Andrew Bresticker
  Cc: Stephen Warren, Thierry Reding, linux-tegra, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Jassi Brar, Linus Walleij, Mathias Nyman, Grant Likely,
	Alan Stern, Arnd Bergmann, Kishon Vijay Abraham I, devicetree,
	linux-kernel, linux-arm-kernel, linux-usb

On Mon, Aug 18, 2014 at 10:08:22AM -0700, Andrew Bresticker wrote:
> Add support for the on-chip xHCI host controller present on Tegra SoCs.
> 
> The driver is currently very basic: it loads the controller with its
> firmware, starts the controller, and is able to service messages sent
> by the controller's firmware.  The hardware supports device mode as
> well as lower-power operating modes, but support for these is not yet
> implemented here.

So you are saying the device doesn't really work?  Can it handle USB
transactions properly?

I have a jetson board here, is this the controller for that hardware?
Can I test this series on that platform, or is it for something else?

> +static const struct tegra_xhci_soc_config tegra124_soc_config = {
> +	.firmware_file = "nvidia/tegra124/xusb.bin",
> +};
> +MODULE_FIRMWARE("nvidia/tegra124/xusb.bin");

Has this file been submitted to the linux-firmware tree?

thanks,

greg k-h

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

* [PATCH v2 6/9] usb: xhci: Add NVIDIA Tegra xHCI host-controller driver
@ 2014-08-30 21:15     ` Greg Kroah-Hartman
  0 siblings, 0 replies; 141+ messages in thread
From: Greg Kroah-Hartman @ 2014-08-30 21:15 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Aug 18, 2014 at 10:08:22AM -0700, Andrew Bresticker wrote:
> Add support for the on-chip xHCI host controller present on Tegra SoCs.
> 
> The driver is currently very basic: it loads the controller with its
> firmware, starts the controller, and is able to service messages sent
> by the controller's firmware.  The hardware supports device mode as
> well as lower-power operating modes, but support for these is not yet
> implemented here.

So you are saying the device doesn't really work?  Can it handle USB
transactions properly?

I have a jetson board here, is this the controller for that hardware?
Can I test this series on that platform, or is it for something else?

> +static const struct tegra_xhci_soc_config tegra124_soc_config = {
> +	.firmware_file = "nvidia/tegra124/xusb.bin",
> +};
> +MODULE_FIRMWARE("nvidia/tegra124/xusb.bin");

Has this file been submitted to the linux-firmware tree?

thanks,

greg k-h

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

* Re: [PATCH v2 6/9] usb: xhci: Add NVIDIA Tegra xHCI host-controller driver
  2014-08-30 21:15     ` Greg Kroah-Hartman
  (?)
@ 2014-08-31 19:04         ` Andrew Bresticker
  -1 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-31 19:04 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Stephen Warren, Thierry Reding,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, Russell King, Jassi Brar,
	Linus Walleij, Mathias Nyman, Grant Likely, Alan Stern,
	Arnd Bergmann, Kishon Vijay Abraham I,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r

On Sat, Aug 30, 2014 at 2:15 PM, Greg Kroah-Hartman
<gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org> wrote:
> On Mon, Aug 18, 2014 at 10:08:22AM -0700, Andrew Bresticker wrote:
>> Add support for the on-chip xHCI host controller present on Tegra SoCs.
>>
>> The driver is currently very basic: it loads the controller with its
>> firmware, starts the controller, and is able to service messages sent
>> by the controller's firmware.  The hardware supports device mode as
>> well as lower-power operating modes, but support for these is not yet
>> implemented here.
>
> So you are saying the device doesn't really work?  Can it handle USB
> transactions properly?

Huh?  It's just as functional as any other xHCI platform host.
Perhaps I should have been more clear about "lower-power operating
modes": this refers to the runtime powergating of the controller's
SuperSpeed and host-controller logic and has nothing to do with USB
link/hub/device power management.

> I have a jetson board here, is this the controller for that hardware?
> Can I test this series on that platform, or is it for something else?

Yup, that's the platform I primarily used for testing this series.

>> +static const struct tegra_xhci_soc_config tegra124_soc_config = {
>> +     .firmware_file = "nvidia/tegra124/xusb.bin",
>> +};
>> +MODULE_FIRMWARE("nvidia/tegra124/xusb.bin");
>
> Has this file been submitted to the linux-firmware tree?

It has been posted, see https://patchwork.ozlabs.org/patch/384013/

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

* Re: [PATCH v2 6/9] usb: xhci: Add NVIDIA Tegra xHCI host-controller driver
@ 2014-08-31 19:04         ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-31 19:04 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Stephen Warren, Thierry Reding, linux-tegra, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala, Russell King,
	Jassi Brar, Linus Walleij, Mathias Nyman, Grant Likely,
	Alan Stern, Arnd Bergmann, Kishon Vijay Abraham I, devicetree,
	linux-kernel, linux-arm-kernel, linux-usb

On Sat, Aug 30, 2014 at 2:15 PM, Greg Kroah-Hartman
<gregkh@linuxfoundation.org> wrote:
> On Mon, Aug 18, 2014 at 10:08:22AM -0700, Andrew Bresticker wrote:
>> Add support for the on-chip xHCI host controller present on Tegra SoCs.
>>
>> The driver is currently very basic: it loads the controller with its
>> firmware, starts the controller, and is able to service messages sent
>> by the controller's firmware.  The hardware supports device mode as
>> well as lower-power operating modes, but support for these is not yet
>> implemented here.
>
> So you are saying the device doesn't really work?  Can it handle USB
> transactions properly?

Huh?  It's just as functional as any other xHCI platform host.
Perhaps I should have been more clear about "lower-power operating
modes": this refers to the runtime powergating of the controller's
SuperSpeed and host-controller logic and has nothing to do with USB
link/hub/device power management.

> I have a jetson board here, is this the controller for that hardware?
> Can I test this series on that platform, or is it for something else?

Yup, that's the platform I primarily used for testing this series.

>> +static const struct tegra_xhci_soc_config tegra124_soc_config = {
>> +     .firmware_file = "nvidia/tegra124/xusb.bin",
>> +};
>> +MODULE_FIRMWARE("nvidia/tegra124/xusb.bin");
>
> Has this file been submitted to the linux-firmware tree?

It has been posted, see https://patchwork.ozlabs.org/patch/384013/

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

* [PATCH v2 6/9] usb: xhci: Add NVIDIA Tegra xHCI host-controller driver
@ 2014-08-31 19:04         ` Andrew Bresticker
  0 siblings, 0 replies; 141+ messages in thread
From: Andrew Bresticker @ 2014-08-31 19:04 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Aug 30, 2014 at 2:15 PM, Greg Kroah-Hartman
<gregkh@linuxfoundation.org> wrote:
> On Mon, Aug 18, 2014 at 10:08:22AM -0700, Andrew Bresticker wrote:
>> Add support for the on-chip xHCI host controller present on Tegra SoCs.
>>
>> The driver is currently very basic: it loads the controller with its
>> firmware, starts the controller, and is able to service messages sent
>> by the controller's firmware.  The hardware supports device mode as
>> well as lower-power operating modes, but support for these is not yet
>> implemented here.
>
> So you are saying the device doesn't really work?  Can it handle USB
> transactions properly?

Huh?  It's just as functional as any other xHCI platform host.
Perhaps I should have been more clear about "lower-power operating
modes": this refers to the runtime powergating of the controller's
SuperSpeed and host-controller logic and has nothing to do with USB
link/hub/device power management.

> I have a jetson board here, is this the controller for that hardware?
> Can I test this series on that platform, or is it for something else?

Yup, that's the platform I primarily used for testing this series.

>> +static const struct tegra_xhci_soc_config tegra124_soc_config = {
>> +     .firmware_file = "nvidia/tegra124/xusb.bin",
>> +};
>> +MODULE_FIRMWARE("nvidia/tegra124/xusb.bin");
>
> Has this file been submitted to the linux-firmware tree?

It has been posted, see https://patchwork.ozlabs.org/patch/384013/

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

end of thread, other threads:[~2014-08-31 19:04 UTC | newest]

Thread overview: 141+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-18 17:08 [PATCH v2 0/9] Tegra xHCI support Andrew Bresticker
2014-08-18 17:08 ` Andrew Bresticker
2014-08-18 17:08 ` Andrew Bresticker
2014-08-18 17:08 ` [PATCH v2 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver Andrew Bresticker
2014-08-18 17:08   ` Andrew Bresticker
2014-08-18 17:08   ` Andrew Bresticker
     [not found]   ` <1408381705-3623-3-git-send-email-abrestic-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2014-08-25 19:01     ` Stephen Warren
2014-08-25 19:01       ` Stephen Warren
2014-08-25 19:01       ` Stephen Warren
     [not found]       ` <53FB8820.4010202-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2014-08-26  6:57         ` Thierry Reding
2014-08-26  6:57           ` Thierry Reding
2014-08-26  6:57           ` Thierry Reding
2014-08-26  7:43           ` Arnd Bergmann
2014-08-26  7:43             ` Arnd Bergmann
2014-08-26  7:43             ` Arnd Bergmann
2014-08-26  7:50             ` Thierry Reding
2014-08-26  7:50               ` Thierry Reding
2014-08-26  7:50               ` Thierry Reding
2014-08-26  8:09               ` Arnd Bergmann
2014-08-26  8:09                 ` Arnd Bergmann
2014-08-26  8:09                 ` Arnd Bergmann
2014-08-26  9:08                 ` Thierry Reding
2014-08-26  9:08                   ` Thierry Reding
2014-08-26  9:54                   ` Arnd Bergmann
2014-08-26  9:54                     ` Arnd Bergmann
2014-08-26  9:54                     ` Arnd Bergmann
2014-08-26 10:20                     ` Thierry Reding
2014-08-26 10:20                       ` Thierry Reding
2014-08-26 10:20                       ` Thierry Reding
2014-08-26 11:35                       ` Arnd Bergmann
2014-08-26 11:35                         ` Arnd Bergmann
2014-08-26 11:35                         ` Arnd Bergmann
2014-08-26 11:45                         ` Thierry Reding
2014-08-26 11:45                           ` Thierry Reding
2014-08-26 11:45                           ` Thierry Reding
2014-08-26  8:54           ` David Laight
2014-08-26  8:54             ` David Laight
2014-08-26  8:54             ` David Laight
2014-08-26 10:04             ` Arnd Bergmann
2014-08-26 10:04               ` Arnd Bergmann
2014-08-26 10:04               ` Arnd Bergmann
2014-08-27 17:38       ` Andrew Bresticker
2014-08-27 17:38         ` Andrew Bresticker
2014-08-27 17:38         ` Andrew Bresticker
2014-08-27 17:50         ` Stephen Warren
2014-08-27 17:50           ` Stephen Warren
2014-08-27 17:50           ` Stephen Warren
     [not found]           ` <53FE1A7A.4010906-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2014-08-27 18:13             ` Andrew Bresticker
2014-08-27 18:13               ` Andrew Bresticker
2014-08-27 18:13               ` Andrew Bresticker
     [not found]               ` <CAL1qeaGPr=BeYL1-=ddRL7rSuvYdQcd6vCEEHDrNA-KYst6bnw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-08-27 18:19                 ` Stephen Warren
2014-08-27 18:19                   ` Stephen Warren
2014-08-27 18:19                   ` Stephen Warren
2014-08-27 21:56                   ` Andrew Bresticker
2014-08-27 21:56                     ` Andrew Bresticker
2014-08-27 21:56                     ` Andrew Bresticker
     [not found]                     ` <CAL1qeaGHz1+L8r-AXetw422ZWSJX1h025YOx9kB+EE4yJpOowQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-08-27 22:30                       ` Stephen Warren
2014-08-27 22:30                         ` Stephen Warren
2014-08-27 22:30                         ` Stephen Warren
     [not found]         ` <CAL1qeaERHeKKNpqh9qHOppgT7ymvntisdjVvZheP78U6NaPz-A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-08-27 19:26           ` Jassi Brar
2014-08-27 19:26             ` Jassi Brar
2014-08-27 19:26             ` Jassi Brar
2014-08-18 17:08 ` [PATCH v2 3/9] of: Update Tegra XUSB pad controller binding for USB Andrew Bresticker
2014-08-18 17:08   ` Andrew Bresticker
2014-08-18 17:08   ` Andrew Bresticker
     [not found]   ` <1408381705-3623-4-git-send-email-abrestic-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2014-08-25 19:12     ` Stephen Warren
2014-08-25 19:12       ` Stephen Warren
2014-08-25 19:12       ` Stephen Warren
     [not found]       ` <53FB8A8C.8040107-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2014-08-27 16:36         ` Andrew Bresticker
2014-08-27 16:36           ` Andrew Bresticker
2014-08-27 16:36           ` Andrew Bresticker
     [not found]           ` <CAL1qeaGHuMegpeyumD8GrFRmeufkiiUygAdqu1ECHrfSkixwOQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-08-27 16:42             ` Stephen Warren
2014-08-27 16:42               ` Stephen Warren
2014-08-27 16:42               ` Stephen Warren
2014-08-18 17:08 ` [PATCH v2 4/9] pinctrl: tegra-xusb: Add USB PHY support Andrew Bresticker
2014-08-18 17:08   ` Andrew Bresticker
     [not found]   ` <1408381705-3623-5-git-send-email-abrestic-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2014-08-25 19:22     ` Stephen Warren
2014-08-25 19:22       ` Stephen Warren
2014-08-25 19:22       ` Stephen Warren
2014-08-26  7:29       ` Mikko Perttunen
2014-08-26  7:29         ` Mikko Perttunen
2014-08-26  7:29         ` Mikko Perttunen
     [not found]       ` <53FB8CFE.3090007-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2014-08-27 16:44         ` Andrew Bresticker
2014-08-27 16:44           ` Andrew Bresticker
2014-08-27 16:44           ` Andrew Bresticker
2014-08-29 13:36         ` Linus Walleij
2014-08-29 13:36           ` Linus Walleij
2014-08-29 13:36           ` Linus Walleij
2014-08-18 17:08 ` [PATCH v2 5/9] of: Add NVIDIA Tegra xHCI controller binding Andrew Bresticker
2014-08-18 17:08   ` Andrew Bresticker
2014-08-18 17:08   ` Andrew Bresticker
     [not found]   ` <1408381705-3623-6-git-send-email-abrestic-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2014-08-25 19:26     ` Stephen Warren
2014-08-25 19:26       ` Stephen Warren
2014-08-25 19:26       ` Stephen Warren
2014-08-18 17:08 ` [PATCH v2 6/9] usb: xhci: Add NVIDIA Tegra xHCI host-controller driver Andrew Bresticker
2014-08-18 17:08   ` Andrew Bresticker
2014-08-18 17:08   ` Andrew Bresticker
     [not found]   ` <1408381705-3623-7-git-send-email-abrestic-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2014-08-25 19:36     ` Stephen Warren
2014-08-25 19:36       ` Stephen Warren
2014-08-25 19:36       ` Stephen Warren
2014-08-30 21:15   ` Greg Kroah-Hartman
2014-08-30 21:15     ` Greg Kroah-Hartman
     [not found]     ` <20140830211558.GA13814-U8xfFu+wG4EAvxtiuMwx3w@public.gmane.org>
2014-08-31 19:04       ` Andrew Bresticker
2014-08-31 19:04         ` Andrew Bresticker
2014-08-31 19:04         ` Andrew Bresticker
2014-08-18 17:08 ` [PATCH v2 7/9] ARM: tegra: Add Tegra124 XUSB mailbox and xHCI controller Andrew Bresticker
2014-08-18 17:08   ` Andrew Bresticker
2014-08-18 17:08 ` [PATCH v2 8/9] ARM: tegra: jetson-tk1: Add xHCI support Andrew Bresticker
2014-08-18 17:08   ` Andrew Bresticker
2014-08-18 17:08   ` Andrew Bresticker
2014-08-21 13:34 ` [PATCH v2 0/9] Tegra " Tomeu Vizoso
2014-08-21 13:34   ` Tomeu Vizoso
     [not found]   ` <CAAObsKDT4BV=fGAFkMxieQnC3HX=zm8G_qJ44yay4qG8inxoPQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-08-21 17:26     ` Andrew Bresticker
2014-08-21 17:26       ` Andrew Bresticker
2014-08-21 17:26       ` Andrew Bresticker
     [not found]       ` <CAL1qeaH=8Fgw6Zia3DuBL8wrrYMjZ8pqC2NanYtb5-YVJwmtsg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-08-22 11:23         ` Tomeu Vizoso
2014-08-22 11:23           ` Tomeu Vizoso
2014-08-22 11:23           ` Tomeu Vizoso
     [not found] ` <1408381705-3623-1-git-send-email-abrestic-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2014-08-18 17:08   ` [PATCH v2 1/9] of: Add NVIDIA Tegra XUSB mailbox binding Andrew Bresticker
2014-08-18 17:08     ` Andrew Bresticker
2014-08-18 17:08     ` Andrew Bresticker
     [not found]     ` <1408381705-3623-2-git-send-email-abrestic-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2014-08-25 18:48       ` Stephen Warren
2014-08-25 18:48         ` Stephen Warren
2014-08-25 18:48         ` Stephen Warren
     [not found]         ` <53FB84F7.8030509-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2014-08-25 19:06           ` Stephen Warren
2014-08-25 19:06             ` Stephen Warren
2014-08-25 19:06             ` Stephen Warren
2014-08-27 16:33           ` Andrew Bresticker
2014-08-27 16:33             ` Andrew Bresticker
2014-08-27 16:33             ` Andrew Bresticker
2014-08-18 17:08   ` [PATCH v2 9/9] ARM: tegra: venice2: Add xHCI support Andrew Bresticker
2014-08-18 17:08     ` Andrew Bresticker
2014-08-18 17:08     ` Andrew Bresticker
2014-08-18 17:30   ` [PATCH v2 0/9] Tegra " Stephen Warren
2014-08-18 17:30     ` Stephen Warren
2014-08-18 17:30     ` Stephen Warren
     [not found]     ` <53F2381B.8020801-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>
2014-08-18 19:35       ` Andrew Bresticker
2014-08-18 19:35         ` Andrew Bresticker
2014-08-18 19:35         ` Andrew Bresticker
2014-08-22 18:28   ` [PATCH 10/9] pinctrl: tegra-xusb: Support adjusted HS_CURR_LEVEL Andrew Bresticker
     [not found]     ` <1408732088-28010-1-git-send-email-abrestic-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2014-08-25 19:39       ` Stephen Warren

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.