linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 0/5] Allwinner H6 USB3 support
@ 2019-04-05 20:57 Icenowy Zheng
  2019-04-05 20:57 ` [PATCH v5 1/5] dt-bindings: usb-connector: add Vbus regulator for Type-A/B Icenowy Zheng
                   ` (4 more replies)
  0 siblings, 5 replies; 16+ messages in thread
From: Icenowy Zheng @ 2019-04-05 20:57 UTC (permalink / raw)
  To: Rob Herring, Kishon Vijay Abraham I, Maxime Ripard, Chen-Yu Tsai
  Cc: devicetree, linux-kernel, linux-arm-kernel, linux-sunxi, Icenowy Zheng

This patchset adds device tree binding and driver support for Allwinner
H6 USB3 PHY. The controller is just a DWC3 controller from Synposys.

Because of the suggest of Rob Herring, this revision uses the USB
connector device tree binding, and enhanced it by adding Vbus supply
property to it.

Icenowy Zheng (5):
  dt-bindings: usb-connector: add Vbus regulator for Type-A/B
  dt-bindings: phy: add binding for Allwinner USB3 PHY
  phy: allwinner: add phy driver for USB3 PHY on Allwinner H6 SoC
  arm64: allwinner: dts: h6: add USB3 device nodes
  arm64: allwinner: dts: h6: enable USB3 port on Pine H64

 .../bindings/connector/usb-connector.txt      |   3 +
 .../bindings/phy/sun50i-usb3-phy.txt          |  28 ++
 .../boot/dts/allwinner/sun50i-h6-pine-h64.dts |  13 +
 arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi  |  32 +++
 drivers/phy/allwinner/Kconfig                 |  12 +
 drivers/phy/allwinner/Makefile                |   1 +
 drivers/phy/allwinner/phy-sun50i-usb3.c       | 260 ++++++++++++++++++
 7 files changed, 349 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/sun50i-usb3-phy.txt
 create mode 100644 drivers/phy/allwinner/phy-sun50i-usb3.c

-- 
2.18.1


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

* [PATCH v5 1/5] dt-bindings: usb-connector: add Vbus regulator for Type-A/B
  2019-04-05 20:57 [PATCH v5 0/5] Allwinner H6 USB3 support Icenowy Zheng
@ 2019-04-05 20:57 ` Icenowy Zheng
  2019-04-06  7:10   ` Rob Herring
  2019-04-05 20:57 ` [PATCH v5 2/5] dt-bindings: phy: add binding for Allwinner USB3 PHY Icenowy Zheng
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 16+ messages in thread
From: Icenowy Zheng @ 2019-04-05 20:57 UTC (permalink / raw)
  To: Rob Herring, Kishon Vijay Abraham I, Maxime Ripard, Chen-Yu Tsai
  Cc: devicetree, linux-kernel, linux-arm-kernel, linux-sunxi, Icenowy Zheng

USB Type-A and Type-B connectors have a Vbus pin, which provides +5V
power to bus-powered devices.

Add a power supply regulator property for this pin.

Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
New patch in v5.

 Documentation/devicetree/bindings/connector/usb-connector.txt | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/connector/usb-connector.txt b/Documentation/devicetree/bindings/connector/usb-connector.txt
index a9a2f2fc44f2..5608feeb1105 100644
--- a/Documentation/devicetree/bindings/connector/usb-connector.txt
+++ b/Documentation/devicetree/bindings/connector/usb-connector.txt
@@ -17,6 +17,9 @@ Optional properties:
 - self-powered: Set this property if the usb device that has its own power
   source.
 
+Optional properties for usb-a-connector or usb-b-connector:
+- vbus-supply: phandle to a regulator supplying the VBUS voltage.
+
 Optional properties for usb-c-connector:
 - power-role: should be one of "source", "sink" or "dual"(DRP) if typec
   connector has power support.
-- 
2.18.1


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

* [PATCH v5 2/5] dt-bindings: phy: add binding for Allwinner USB3 PHY
  2019-04-05 20:57 [PATCH v5 0/5] Allwinner H6 USB3 support Icenowy Zheng
  2019-04-05 20:57 ` [PATCH v5 1/5] dt-bindings: usb-connector: add Vbus regulator for Type-A/B Icenowy Zheng
@ 2019-04-05 20:57 ` Icenowy Zheng
  2019-04-06  7:14   ` Rob Herring
  2019-04-08  7:14   ` Maxime Ripard
  2019-04-05 20:57 ` [PATCH v5 3/5] phy: allwinner: add phy driver for USB3 PHY on Allwinner H6 SoC Icenowy Zheng
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 16+ messages in thread
From: Icenowy Zheng @ 2019-04-05 20:57 UTC (permalink / raw)
  To: Rob Herring, Kishon Vijay Abraham I, Maxime Ripard, Chen-Yu Tsai
  Cc: devicetree, linux-kernel, linux-arm-kernel, linux-sunxi, Icenowy Zheng

The new Allwinner H6 SoC contains a USB3 PHY that is wired to the
external USB3 pins of the SoC.

Add a device tree binding for the PHY.

Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
---
Changes in v5:
- Dropped Vbus regulator and added connector subnode.

Changes in v4:
- Changed Vbus regulator property to vbus-supply.

Changes in v3:
- Added Chen-Yu's Review tag.

No changes in v2, v1.

 .../bindings/phy/sun50i-usb3-phy.txt          | 28 +++++++++++++++++++
 1 file changed, 28 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/sun50i-usb3-phy.txt

diff --git a/Documentation/devicetree/bindings/phy/sun50i-usb3-phy.txt b/Documentation/devicetree/bindings/phy/sun50i-usb3-phy.txt
new file mode 100644
index 000000000000..eeedc53e6360
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/sun50i-usb3-phy.txt
@@ -0,0 +1,28 @@
+Allwinner sun50i USB3 PHY
+-----------------------
+
+Required properties:
+- compatible : should be one of
+  * allwinner,sun60i-h6-usb3-phy
+- reg : a list of offset + length pairs
+- #phy-cells : from the generic phy bindings, must be 0
+- clocks : phandle + clock specifier for the phy clock
+- resets : phandle + reset specifier for the phy reset
+
+Optional nodes:
+- connector : A sub-node required for representing the connector connected
+	      to the USB PHY. See ../connector/usb-connector.txt for details.
+
+Example:
+	usb3phy: phy@5210000 {
+		compatible = "allwinner,sun50i-h6-usb3-phy";
+		reg = <0x5210000 0x10000>;
+		clocks = <&ccu CLK_USB_PHY1>;
+		resets = <&ccu RST_USB_PHY1>;
+		#phy-cells = <0>;
+
+		connector {
+			compatible = "usb-a-connector";
+			label = "USB3";
+		};
+	};
-- 
2.18.1


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

* [PATCH v5 3/5] phy: allwinner: add phy driver for USB3 PHY on Allwinner H6 SoC
  2019-04-05 20:57 [PATCH v5 0/5] Allwinner H6 USB3 support Icenowy Zheng
  2019-04-05 20:57 ` [PATCH v5 1/5] dt-bindings: usb-connector: add Vbus regulator for Type-A/B Icenowy Zheng
  2019-04-05 20:57 ` [PATCH v5 2/5] dt-bindings: phy: add binding for Allwinner USB3 PHY Icenowy Zheng
@ 2019-04-05 20:57 ` Icenowy Zheng
  2019-04-06 17:21   ` [linux-sunxi] " Ondřej Jirman
                     ` (3 more replies)
  2019-04-05 20:57 ` [PATCH v5 4/5] arm64: allwinner: dts: h6: add USB3 device nodes Icenowy Zheng
  2019-04-05 20:57 ` [PATCH v5 5/5] arm64: allwinner: dts: h6: enable USB3 port on Pine H64 Icenowy Zheng
  4 siblings, 4 replies; 16+ messages in thread
From: Icenowy Zheng @ 2019-04-05 20:57 UTC (permalink / raw)
  To: Rob Herring, Kishon Vijay Abraham I, Maxime Ripard, Chen-Yu Tsai
  Cc: devicetree, linux-kernel, linux-arm-kernel, linux-sunxi, Icenowy Zheng

Allwinner H6 SoC contains a USB3 PHY (with USB2 DP/DM lines also
controlled).

Add a driver for it.

The register operations in this driver is mainly extracted from the BSP
USB3 driver.

Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
---
Changes in v5:
- Dropped support for vbus-supply property in the device node itself and
  added support for vbus-supply property in the connector subnode.

Changes in v4:
- Added support for vbus-supply property.

Changes in v3:
- Dropped USB_SUPPORT dependency.
- Added Chen-Yu's Review tag.

No changes in v2, v1. drivers/phy/allwinner/Kconfig           |  12 ++
 drivers/phy/allwinner/Makefile          |   1 +
 drivers/phy/allwinner/phy-sun50i-usb3.c | 260 ++++++++++++++++++++++++
 3 files changed, 273 insertions(+)
 create mode 100644 drivers/phy/allwinner/phy-sun50i-usb3.c

diff --git a/drivers/phy/allwinner/Kconfig b/drivers/phy/allwinner/Kconfig
index fb1204bcc454..2c363db177f2 100644
--- a/drivers/phy/allwinner/Kconfig
+++ b/drivers/phy/allwinner/Kconfig
@@ -41,3 +41,15 @@ config PHY_SUN9I_USB
 	  sun9i SoCs.
 
 	  This driver controls each individual USB 2 host PHY.
+
+config PHY_SUN50I_USB3
+	tristate "Allwinner sun50i SoC USB3 PHY driver"
+	depends on ARCH_SUNXI && HAS_IOMEM && OF
+	depends on RESET_CONTROLLER
+	select USB_COMMON
+	select GENERIC_PHY
+	help
+	  Enable this to support the USB3.0-capable transceiver that is
+	  part of some Allwinner sun50i SoCs.
+
+	  This driver controls each individual USB 2+3 host PHY combo.
diff --git a/drivers/phy/allwinner/Makefile b/drivers/phy/allwinner/Makefile
index 7d0053efbfaa..59575a895779 100644
--- a/drivers/phy/allwinner/Makefile
+++ b/drivers/phy/allwinner/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_PHY_SUN4I_USB)		+= phy-sun4i-usb.o
 obj-$(CONFIG_PHY_SUN6I_MIPI_DPHY)	+= phy-sun6i-mipi-dphy.o
 obj-$(CONFIG_PHY_SUN9I_USB)		+= phy-sun9i-usb.o
+obj-$(CONFIG_PHY_SUN50I_USB3)		+= phy-sun50i-usb3.o
diff --git a/drivers/phy/allwinner/phy-sun50i-usb3.c b/drivers/phy/allwinner/phy-sun50i-usb3.c
new file mode 100644
index 000000000000..5299aef98668
--- /dev/null
+++ b/drivers/phy/allwinner/phy-sun50i-usb3.c
@@ -0,0 +1,260 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Allwinner sun50i(H6) USB 3.0 phy driver
+ *
+ * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
+ *
+ * Based on phy-sun9i-usb.c, which is:
+ *
+ * Copyright (C) 2014-2015 Chen-Yu Tsai <wens@csie.org>
+ *
+ * Based on code from Allwinner BSP, which is:
+ *
+ * Copyright (c) 2010-2015 Allwinner Technology Co., Ltd.
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/phy/phy.h>
+#include <linux/of_platform.h>
+#include <linux/usb/of.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
+
+/* Interface Status and Control Registers */
+#define SUNXI_ISCR			0x00
+#define SUNXI_PIPE_CLOCK_CONTROL	0x14
+#define SUNXI_PHY_TUNE_LOW		0x18
+#define SUNXI_PHY_TUNE_HIGH		0x1c
+#define SUNXI_PHY_EXTERNAL_CONTROL	0x20
+
+/* USB2.0 Interface Status and Control Register */
+#define SUNXI_ISCR_FORCE_VBUS		(3 << 12)
+
+/* PIPE Clock Control Register */
+#define SUNXI_PCC_PIPE_CLK_OPEN		(1 << 6)
+
+/* PHY External Control Register */
+#define SUNXI_PEC_EXTERN_VBUS		(3 << 1)
+#define SUNXI_PEC_SSC_EN		(1 << 24)
+#define SUNXI_PEC_REF_SSP_EN		(1 << 26)
+
+/* PHY Tune High Register */
+#define SUNXI_TX_DEEMPH_3P5DB(n)	((n) << 19)
+#define SUNXI_TX_DEEMPH_3P5DB_MASK	GENMASK(24, 19)
+#define SUNXI_TX_DEEMPH_6DB(n)		((n) << 13)
+#define SUNXI_TX_DEEMPH_6GB_MASK	GENMASK(18, 13)
+#define SUNXI_TX_SWING_FULL(n)		((n) << 6)
+#define SUNXI_TX_SWING_FULL_MASK	GENMASK(12, 6)
+#define SUNXI_LOS_BIAS(n)		((n) << 3)
+#define SUNXI_LOS_BIAS_MASK		GENMASK(5, 3)
+#define SUNXI_TXVBOOSTLVL(n)		((n) << 0)
+#define SUNXI_TXVBOOSTLVL_MASK		GENMASK(0, 2)
+
+struct sun50i_usb3_phy {
+	struct phy *phy;
+	void __iomem *regs;
+	struct reset_control *reset;
+	struct clk *clk;
+	struct platform_device *connector_dev;
+	struct regulator *vbus;
+};
+
+static void sun50i_usb3_phy_open(struct sun50i_usb3_phy *phy)
+{
+	u32 val;
+
+	val = readl(phy->regs + SUNXI_PHY_EXTERNAL_CONTROL);
+	val |= SUNXI_PEC_EXTERN_VBUS;
+	val |= SUNXI_PEC_SSC_EN | SUNXI_PEC_REF_SSP_EN;
+	writel(val, phy->regs + SUNXI_PHY_EXTERNAL_CONTROL);
+
+	val = readl(phy->regs + SUNXI_PIPE_CLOCK_CONTROL);
+	val |= SUNXI_PCC_PIPE_CLK_OPEN;
+	writel(val, phy->regs + SUNXI_PIPE_CLOCK_CONTROL);
+
+	val = readl(phy->regs + SUNXI_ISCR);
+	val |= SUNXI_ISCR_FORCE_VBUS;
+	writel(val, phy->regs + SUNXI_ISCR);
+
+	/*
+	 * All the magic numbers written to the PHY_TUNE_{LOW_HIGH}
+	 * registers are directly taken from the BSP USB3 driver from
+	 * Allwiner.
+	 */
+	writel(0x0047fc87, phy->regs + SUNXI_PHY_TUNE_LOW);
+
+	val = readl(phy->regs + SUNXI_PHY_TUNE_HIGH);
+	val &= ~(SUNXI_TXVBOOSTLVL_MASK | SUNXI_LOS_BIAS_MASK |
+		 SUNXI_TX_SWING_FULL_MASK | SUNXI_TX_DEEMPH_6GB_MASK |
+		 SUNXI_TX_DEEMPH_3P5DB_MASK);
+	val |= SUNXI_TXVBOOSTLVL(0x7);
+	val |= SUNXI_LOS_BIAS(0x7);
+	val |= SUNXI_TX_SWING_FULL(0x55);
+	val |= SUNXI_TX_DEEMPH_6DB(0x20);
+	val |= SUNXI_TX_DEEMPH_3P5DB(0x15);
+	writel(val, phy->regs + SUNXI_PHY_TUNE_HIGH);
+}
+
+static int sun50i_usb3_phy_init(struct phy *_phy)
+{
+	struct sun50i_usb3_phy *phy = phy_get_drvdata(_phy);
+	int ret;
+
+	ret = clk_prepare_enable(phy->clk);
+	if (ret)
+		goto err_clk;
+
+	ret = reset_control_deassert(phy->reset);
+	if (ret)
+		goto err_reset;
+
+	sun50i_usb3_phy_open(phy);
+	return 0;
+
+err_reset:
+	clk_disable_unprepare(phy->clk);
+
+err_clk:
+	return ret;
+}
+
+static int sun50i_usb3_phy_exit(struct phy *_phy)
+{
+	struct sun50i_usb3_phy *phy = phy_get_drvdata(_phy);
+
+	reset_control_assert(phy->reset);
+	clk_disable_unprepare(phy->clk);
+
+	return 0;
+}
+
+static int sun50i_usb3_phy_power_on(struct phy *_phy)
+{
+	struct sun50i_usb3_phy *phy = phy_get_drvdata(_phy);
+
+	if (phy->vbus)
+		return regulator_enable(phy->vbus);
+	else
+		return 0;
+}
+
+static int sun50i_usb3_phy_power_off(struct phy *_phy)
+{
+	struct sun50i_usb3_phy *phy = phy_get_drvdata(_phy);
+
+	if (phy->vbus)
+		return regulator_disable(phy->vbus);
+	else
+		return 0;
+}
+
+static const struct phy_ops sun50i_usb3_phy_ops = {
+	.init		= sun50i_usb3_phy_init,
+	.exit		= sun50i_usb3_phy_exit,
+	.power_on	= sun50i_usb3_phy_power_on,
+	.power_off	= sun50i_usb3_phy_power_off,
+	.owner		= THIS_MODULE,
+};
+
+static int sun50i_usb3_phy_probe(struct platform_device *pdev)
+{
+	struct sun50i_usb3_phy *phy;
+	struct device *dev = &pdev->dev;
+	struct phy_provider *phy_provider;
+	struct resource *res;
+	struct device_node *connector_node;
+	int ret;
+
+	phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
+	if (!phy)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, phy);
+
+	phy->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(phy->clk)) {
+		dev_err(dev, "failed to get phy clock\n");
+		return PTR_ERR(phy->clk);
+	}
+
+	phy->reset = devm_reset_control_get(dev, NULL);
+	if (IS_ERR(phy->reset)) {
+		dev_err(dev, "failed to get reset control\n");
+		return PTR_ERR(phy->reset);
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	phy->regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(phy->regs))
+		return PTR_ERR(phy->regs);
+
+	/* Populate the connector as platform device */
+	ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+	if (ret)
+		return ret;
+
+	/*
+	 * Currently the Allwinner USB3 PHY contains only one port, so we
+	 * only process one connector now.
+	 */
+	connector_node = of_get_next_child(pdev->dev.of_node, NULL);
+
+	if (connector_node) {
+		/* Get the platform device */
+		phy->connector_dev = of_find_device_by_node(connector_node);
+		if (!phy->connector_dev) {
+			dev_err(dev, "no device for connector\n");
+			return -ENODEV;
+		}
+
+		phy->vbus = regulator_get(&phy->connector_dev->dev, "vbus");
+		if (IS_ERR(phy->vbus))
+			return PTR_ERR(phy->vbus);
+	}
+
+	phy->phy = devm_phy_create(dev, NULL, &sun50i_usb3_phy_ops);
+	if (IS_ERR(phy->phy)) {
+		dev_err(dev, "failed to create PHY\n");
+		return PTR_ERR(phy->phy);
+	}
+
+	phy_set_drvdata(phy->phy, phy);
+	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+
+	return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static int sun50i_usb3_phy_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct sun50i_usb3_phy *phy = dev_get_drvdata(dev);
+
+	if (phy->vbus)
+		regulator_put(phy->vbus);
+
+	return 0;
+}
+
+static const struct of_device_id sun50i_usb3_phy_of_match[] = {
+	{ .compatible = "allwinner,sun50i-h6-usb3-phy" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, sun50i_usb3_phy_of_match);
+
+static struct platform_driver sun50i_usb3_phy_driver = {
+	.probe	= sun50i_usb3_phy_probe,
+	.remove	= sun50i_usb3_phy_remove,
+	.driver = {
+		.of_match_table	= sun50i_usb3_phy_of_match,
+		.name  = "sun50i-usb3-phy",
+	}
+};
+module_platform_driver(sun50i_usb3_phy_driver);
+
+MODULE_DESCRIPTION("Allwinner sun50i USB 3.0 phy driver");
+MODULE_AUTHOR("Icenowy Zheng <icenowy@aosc.io>");
+MODULE_LICENSE("GPL");
-- 
2.18.1


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

* [PATCH v5 4/5] arm64: allwinner: dts: h6: add USB3 device nodes
  2019-04-05 20:57 [PATCH v5 0/5] Allwinner H6 USB3 support Icenowy Zheng
                   ` (2 preceding siblings ...)
  2019-04-05 20:57 ` [PATCH v5 3/5] phy: allwinner: add phy driver for USB3 PHY on Allwinner H6 SoC Icenowy Zheng
@ 2019-04-05 20:57 ` Icenowy Zheng
  2019-04-05 20:57 ` [PATCH v5 5/5] arm64: allwinner: dts: h6: enable USB3 port on Pine H64 Icenowy Zheng
  4 siblings, 0 replies; 16+ messages in thread
From: Icenowy Zheng @ 2019-04-05 20:57 UTC (permalink / raw)
  To: Rob Herring, Kishon Vijay Abraham I, Maxime Ripard, Chen-Yu Tsai
  Cc: devicetree, linux-kernel, linux-arm-kernel, linux-sunxi, Icenowy Zheng

Allwinner H6 SoC features USB3 functionality, with a DWC3 controller and
a custom PHY.

Add device tree nodes for them.

Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
---
No changes in v4, v5.

Changes in v3:
- Changed the dwc3 clock according to the user manual.
- Added Chen-Yu's Review tag. arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 32 ++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
index 91fecab58836..4fcd4c0f470d 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
@@ -426,6 +426,38 @@
 			status = "disabled";
 		};
 
+		dwc3: dwc3@5200000 {
+			compatible = "snps,dwc3";
+			reg = <0x05200000 0x10000>;
+			interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_XHCI>,
+				 <&ccu CLK_BUS_XHCI>,
+				 <&osc32k>;
+			clock-names = "ref", "bus_early", "suspend";
+			resets = <&ccu RST_BUS_XHCI>;
+			/*
+			 * The datasheet of the chip doesn't declare the
+			 * peripheral function, and there's no boards known
+			 * to have a USB Type-B port routed to the port.
+			 * In addition, no one has tested the peripheral
+			 * function yet.
+			 * So set the dr_mode to "host" in the DTSI file.
+			 */
+			dr_mode = "host";
+			phys = <&usb3phy>;
+			phy-names = "usb3-phy";
+			status = "disabled";
+		};
+
+		usb3phy: phy@5210000 {
+			compatible = "allwinner,sun50i-h6-usb3-phy";
+			reg = <0x5210000 0x10000>;
+			clocks = <&ccu CLK_USB_PHY1>;
+			resets = <&ccu RST_USB_PHY1>;
+			#phy-cells = <0>;
+			status = "disabled";
+		};
+
 		ehci3: usb@5311000 {
 			compatible = "allwinner,sun50i-h6-ehci", "generic-ehci";
 			reg = <0x05311000 0x100>;
-- 
2.18.1


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

* [PATCH v5 5/5] arm64: allwinner: dts: h6: enable USB3 port on Pine H64
  2019-04-05 20:57 [PATCH v5 0/5] Allwinner H6 USB3 support Icenowy Zheng
                   ` (3 preceding siblings ...)
  2019-04-05 20:57 ` [PATCH v5 4/5] arm64: allwinner: dts: h6: add USB3 device nodes Icenowy Zheng
@ 2019-04-05 20:57 ` Icenowy Zheng
  4 siblings, 0 replies; 16+ messages in thread
From: Icenowy Zheng @ 2019-04-05 20:57 UTC (permalink / raw)
  To: Rob Herring, Kishon Vijay Abraham I, Maxime Ripard, Chen-Yu Tsai
  Cc: devicetree, linux-kernel, linux-arm-kernel, linux-sunxi, Icenowy Zheng

Pine H64 board have a USB3 port, which is connected to the USB3 pins of
the H6 SoC, and the 5V power supply is controlled via GPIO (shared with
the power USB ports).

Enable this port.

Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
---
Changes in v5:
- Migrated to connector subnode.

No changes in v4.

Changes in v3:
- Added Chen-Yu's Review tag. 
.../arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
index bdb8470fc8dc..d03e20ee1cc3 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
@@ -95,6 +95,10 @@
 	};
 };
 
+&dwc3 {
+	status = "okay";
+};
+
 &ehci0 {
 	status = "okay";
 };
@@ -267,3 +271,12 @@
 	usb3_vbus-supply = <&reg_usb_vbus>;
 	status = "okay";
 };
+
+&usb3phy {
+	status = "okay";
+
+	connector {
+		compatible = "usb-a-connector";
+		vbus-supply = <&reg_usb_vbus>;
+	};
+};
-- 
2.18.1


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

* Re: [PATCH v5 1/5] dt-bindings: usb-connector: add Vbus regulator for Type-A/B
  2019-04-05 20:57 ` [PATCH v5 1/5] dt-bindings: usb-connector: add Vbus regulator for Type-A/B Icenowy Zheng
@ 2019-04-06  7:10   ` Rob Herring
  0 siblings, 0 replies; 16+ messages in thread
From: Rob Herring @ 2019-04-06  7:10 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Kishon Vijay Abraham I, Maxime Ripard, Chen-Yu Tsai, devicetree,
	linux-kernel, linux-arm-kernel, linux-sunxi, Icenowy Zheng

On Sat,  6 Apr 2019 04:57:32 +0800, Icenowy Zheng wrote:
> USB Type-A and Type-B connectors have a Vbus pin, which provides +5V
> power to bus-powered devices.
> 
> Add a power supply regulator property for this pin.
> 
> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
> ---
> New patch in v5.
> 
>  Documentation/devicetree/bindings/connector/usb-connector.txt | 3 +++
>  1 file changed, 3 insertions(+)
> 

Reviewed-by: Rob Herring <robh@kernel.org>

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

* Re: [PATCH v5 2/5] dt-bindings: phy: add binding for Allwinner USB3 PHY
  2019-04-05 20:57 ` [PATCH v5 2/5] dt-bindings: phy: add binding for Allwinner USB3 PHY Icenowy Zheng
@ 2019-04-06  7:14   ` Rob Herring
  2019-04-06  7:24     ` Icenowy Zheng
  2019-04-08  7:14   ` Maxime Ripard
  1 sibling, 1 reply; 16+ messages in thread
From: Rob Herring @ 2019-04-06  7:14 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Kishon Vijay Abraham I, Maxime Ripard, Chen-Yu Tsai, devicetree,
	linux-kernel, linux-arm-kernel, linux-sunxi

On Sat, Apr 06, 2019 at 04:57:33AM +0800, Icenowy Zheng wrote:
> The new Allwinner H6 SoC contains a USB3 PHY that is wired to the
> external USB3 pins of the SoC.
> 
> Add a device tree binding for the PHY.
> 
> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
> Reviewed-by: Chen-Yu Tsai <wens@csie.org>
> ---
> Changes in v5:
> - Dropped Vbus regulator and added connector subnode.
> 
> Changes in v4:
> - Changed Vbus regulator property to vbus-supply.
> 
> Changes in v3:
> - Added Chen-Yu's Review tag.
> 
> No changes in v2, v1.
> 
>  .../bindings/phy/sun50i-usb3-phy.txt          | 28 +++++++++++++++++++
>  1 file changed, 28 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/phy/sun50i-usb3-phy.txt
> 
> diff --git a/Documentation/devicetree/bindings/phy/sun50i-usb3-phy.txt b/Documentation/devicetree/bindings/phy/sun50i-usb3-phy.txt
> new file mode 100644
> index 000000000000..eeedc53e6360
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/phy/sun50i-usb3-phy.txt
> @@ -0,0 +1,28 @@
> +Allwinner sun50i USB3 PHY
> +-----------------------
> +
> +Required properties:
> +- compatible : should be one of
> +  * allwinner,sun60i-h6-usb3-phy
> +- reg : a list of offset + length pairs
> +- #phy-cells : from the generic phy bindings, must be 0
> +- clocks : phandle + clock specifier for the phy clock
> +- resets : phandle + reset specifier for the phy reset
> +
> +Optional nodes:
> +- connector : A sub-node required for representing the connector connected
> +	      to the USB PHY. See ../connector/usb-connector.txt for details.
> +
> +Example:
> +	usb3phy: phy@5210000 {
> +		compatible = "allwinner,sun50i-h6-usb3-phy";
> +		reg = <0x5210000 0x10000>;
> +		clocks = <&ccu CLK_USB_PHY1>;
> +		resets = <&ccu RST_USB_PHY1>;
> +		#phy-cells = <0>;
> +
> +		connector {
> +			compatible = "usb-a-connector";
> +			label = "USB3";

The binding defines that a connector is a child of USB controller or 
some port controller (such as USB-C ctrlr) with OF graph to USB 
controller. So either way, this is wrong unless this is more than just a 
phy.

Rob

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

* Re: [PATCH v5 2/5] dt-bindings: phy: add binding for Allwinner USB3 PHY
  2019-04-06  7:14   ` Rob Herring
@ 2019-04-06  7:24     ` Icenowy Zheng
  2019-04-09  1:09       ` Rob Herring
  0 siblings, 1 reply; 16+ messages in thread
From: Icenowy Zheng @ 2019-04-06  7:24 UTC (permalink / raw)
  To: linux-arm-kernel, Rob Herring
  Cc: devicetree, Maxime Ripard, linux-sunxi, linux-kernel,
	Kishon Vijay Abraham I, Chen-Yu Tsai



于 2019年4月6日 GMT+08:00 下午3:14:02, Rob Herring <robh@kernel.org> 写到:
>On Sat, Apr 06, 2019 at 04:57:33AM +0800, Icenowy Zheng wrote:
>> The new Allwinner H6 SoC contains a USB3 PHY that is wired to the
>> external USB3 pins of the SoC.
>> 
>> Add a device tree binding for the PHY.
>> 
>> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
>> Reviewed-by: Chen-Yu Tsai <wens@csie.org>
>> ---
>> Changes in v5:
>> - Dropped Vbus regulator and added connector subnode.
>> 
>> Changes in v4:
>> - Changed Vbus regulator property to vbus-supply.
>> 
>> Changes in v3:
>> - Added Chen-Yu's Review tag.
>> 
>> No changes in v2, v1.
>> 
>>  .../bindings/phy/sun50i-usb3-phy.txt          | 28
>+++++++++++++++++++
>>  1 file changed, 28 insertions(+)
>>  create mode 100644
>Documentation/devicetree/bindings/phy/sun50i-usb3-phy.txt
>> 
>> diff --git
>a/Documentation/devicetree/bindings/phy/sun50i-usb3-phy.txt
>b/Documentation/devicetree/bindings/phy/sun50i-usb3-phy.txt
>> new file mode 100644
>> index 000000000000..eeedc53e6360
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/phy/sun50i-usb3-phy.txt
>> @@ -0,0 +1,28 @@
>> +Allwinner sun50i USB3 PHY
>> +-----------------------
>> +
>> +Required properties:
>> +- compatible : should be one of
>> +  * allwinner,sun60i-h6-usb3-phy
>> +- reg : a list of offset + length pairs
>> +- #phy-cells : from the generic phy bindings, must be 0
>> +- clocks : phandle + clock specifier for the phy clock
>> +- resets : phandle + reset specifier for the phy reset
>> +
>> +Optional nodes:
>> +- connector : A sub-node required for representing the connector
>connected
>> +	      to the USB PHY. See ../connector/usb-connector.txt for
>details.
>> +
>> +Example:
>> +	usb3phy: phy@5210000 {
>> +		compatible = "allwinner,sun50i-h6-usb3-phy";
>> +		reg = <0x5210000 0x10000>;
>> +		clocks = <&ccu CLK_USB_PHY1>;
>> +		resets = <&ccu RST_USB_PHY1>;
>> +		#phy-cells = <0>;
>> +
>> +		connector {
>> +			compatible = "usb-a-connector";
>> +			label = "USB3";
>
>The binding defines that a connector is a child of USB controller or 

Please note that the word used is not "USB controller", but "USB interface
controller".

A USB controller is something that deal with USB protocol, and connect to a USB
PHY with ULPI/UTMI/PIPE interface. It's not connected to the connector
directly at all. Then the PHY is connected to the interface controller (if present), or
the connector, with D+, D- and SS pins.

>some port controller (such as USB-C ctrlr) with OF graph to USB 
>controller. So either way, this is wrong unless this is more than just
>a 
>phy.
>
>Rob
>
>_______________________________________________
>linux-arm-kernel mailing list
>linux-arm-kernel@lists.infradead.org
>http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

-- 
使用 K-9 Mail 发送自我的Android设备。

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

* Re: [linux-sunxi] [PATCH v5 3/5] phy: allwinner: add phy driver for USB3 PHY on Allwinner H6 SoC
  2019-04-05 20:57 ` [PATCH v5 3/5] phy: allwinner: add phy driver for USB3 PHY on Allwinner H6 SoC Icenowy Zheng
@ 2019-04-06 17:21   ` Ondřej Jirman
  2019-04-06 17:24     ` Icenowy Zheng
  2019-04-09 16:34   ` Clément Péron
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 16+ messages in thread
From: Ondřej Jirman @ 2019-04-06 17:21 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Kishon Vijay Abraham I, Maxime Ripard, Chen-Yu Tsai,
	devicetree, linux-kernel, linux-arm-kernel, linux-sunxi

Hello Icenowy,

On Sat, Apr 06, 2019 at 04:57:34AM +0800, Icenowy Zheng wrote:
> Allwinner H6 SoC contains a USB3 PHY (with USB2 DP/DM lines also
> controlled).
> 
> Add a driver for it.
> 
> The register operations in this driver is mainly extracted from the BSP
> USB3 driver.
> 
> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
> Reviewed-by: Chen-Yu Tsai <wens@csie.org>
> ---
> Changes in v5:
> - Dropped support for vbus-supply property in the device node itself and
>   added support for vbus-supply property in the connector subnode.
> 
> Changes in v4:
> - Added support for vbus-supply property.
> 
> Changes in v3:
> - Dropped USB_SUPPORT dependency.
> - Added Chen-Yu's Review tag.
> 
> No changes in v2, v1. drivers/phy/allwinner/Kconfig           |  12 ++
>  drivers/phy/allwinner/Makefile          |   1 +
>  drivers/phy/allwinner/phy-sun50i-usb3.c | 260 ++++++++++++++++++++++++
>  3 files changed, 273 insertions(+)
>  create mode 100644 drivers/phy/allwinner/phy-sun50i-usb3.c
> 
> diff --git a/drivers/phy/allwinner/Kconfig b/drivers/phy/allwinner/Kconfig
> index fb1204bcc454..2c363db177f2 100644
> --- a/drivers/phy/allwinner/Kconfig
> +++ b/drivers/phy/allwinner/Kconfig
> @@ -41,3 +41,15 @@ config PHY_SUN9I_USB
>  	  sun9i SoCs.
>  
>  	  This driver controls each individual USB 2 host PHY.
> +
> +config PHY_SUN50I_USB3
> +	tristate "Allwinner sun50i SoC USB3 PHY driver"
> +	depends on ARCH_SUNXI && HAS_IOMEM && OF
> +	depends on RESET_CONTROLLER
> +	select USB_COMMON
> +	select GENERIC_PHY
> +	help
> +	  Enable this to support the USB3.0-capable transceiver that is
> +	  part of some Allwinner sun50i SoCs.
> +
> +	  This driver controls each individual USB 2+3 host PHY combo.
> diff --git a/drivers/phy/allwinner/Makefile b/drivers/phy/allwinner/Makefile
> index 7d0053efbfaa..59575a895779 100644
> --- a/drivers/phy/allwinner/Makefile
> +++ b/drivers/phy/allwinner/Makefile
> @@ -1,3 +1,4 @@
>  obj-$(CONFIG_PHY_SUN4I_USB)		+= phy-sun4i-usb.o
>  obj-$(CONFIG_PHY_SUN6I_MIPI_DPHY)	+= phy-sun6i-mipi-dphy.o
>  obj-$(CONFIG_PHY_SUN9I_USB)		+= phy-sun9i-usb.o
> +obj-$(CONFIG_PHY_SUN50I_USB3)		+= phy-sun50i-usb3.o
> diff --git a/drivers/phy/allwinner/phy-sun50i-usb3.c b/drivers/phy/allwinner/phy-sun50i-usb3.c
> new file mode 100644
> index 000000000000..5299aef98668
> --- /dev/null
> +++ b/drivers/phy/allwinner/phy-sun50i-usb3.c
> @@ -0,0 +1,260 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Allwinner sun50i(H6) USB 3.0 phy driver
> + *
> + * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
> + *
> + * Based on phy-sun9i-usb.c, which is:
> + *
> + * Copyright (C) 2014-2015 Chen-Yu Tsai <wens@csie.org>
> + *
> + * Based on code from Allwinner BSP, which is:
> + *
> + * Copyright (c) 2010-2015 Allwinner Technology Co., Ltd.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/phy/phy.h>
> +#include <linux/of_platform.h>
> +#include <linux/usb/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/reset.h>
> +
> +/* Interface Status and Control Registers */
> +#define SUNXI_ISCR			0x00
> +#define SUNXI_PIPE_CLOCK_CONTROL	0x14
> +#define SUNXI_PHY_TUNE_LOW		0x18
> +#define SUNXI_PHY_TUNE_HIGH		0x1c
> +#define SUNXI_PHY_EXTERNAL_CONTROL	0x20
> +
> +/* USB2.0 Interface Status and Control Register */
> +#define SUNXI_ISCR_FORCE_VBUS		(3 << 12)
> +
> +/* PIPE Clock Control Register */
> +#define SUNXI_PCC_PIPE_CLK_OPEN		(1 << 6)
> +
> +/* PHY External Control Register */
> +#define SUNXI_PEC_EXTERN_VBUS		(3 << 1)
> +#define SUNXI_PEC_SSC_EN		(1 << 24)
> +#define SUNXI_PEC_REF_SSP_EN		(1 << 26)
> +
> +/* PHY Tune High Register */
> +#define SUNXI_TX_DEEMPH_3P5DB(n)	((n) << 19)
> +#define SUNXI_TX_DEEMPH_3P5DB_MASK	GENMASK(24, 19)
> +#define SUNXI_TX_DEEMPH_6DB(n)		((n) << 13)
> +#define SUNXI_TX_DEEMPH_6GB_MASK	GENMASK(18, 13)
> +#define SUNXI_TX_SWING_FULL(n)		((n) << 6)
> +#define SUNXI_TX_SWING_FULL_MASK	GENMASK(12, 6)
> +#define SUNXI_LOS_BIAS(n)		((n) << 3)
> +#define SUNXI_LOS_BIAS_MASK		GENMASK(5, 3)
> +#define SUNXI_TXVBOOSTLVL(n)		((n) << 0)
> +#define SUNXI_TXVBOOSTLVL_MASK		GENMASK(0, 2)
> +
> +struct sun50i_usb3_phy {
> +	struct phy *phy;
> +	void __iomem *regs;
> +	struct reset_control *reset;
> +	struct clk *clk;
> +	struct platform_device *connector_dev;
> +	struct regulator *vbus;
> +};
> +
> +static void sun50i_usb3_phy_open(struct sun50i_usb3_phy *phy)
> +{
> +	u32 val;
> +
> +	val = readl(phy->regs + SUNXI_PHY_EXTERNAL_CONTROL);
> +	val |= SUNXI_PEC_EXTERN_VBUS;
> +	val |= SUNXI_PEC_SSC_EN | SUNXI_PEC_REF_SSP_EN;
> +	writel(val, phy->regs + SUNXI_PHY_EXTERNAL_CONTROL);
> +
> +	val = readl(phy->regs + SUNXI_PIPE_CLOCK_CONTROL);
> +	val |= SUNXI_PCC_PIPE_CLK_OPEN;
> +	writel(val, phy->regs + SUNXI_PIPE_CLOCK_CONTROL);
> +
> +	val = readl(phy->regs + SUNXI_ISCR);
> +	val |= SUNXI_ISCR_FORCE_VBUS;
> +	writel(val, phy->regs + SUNXI_ISCR);
> +
> +	/*
> +	 * All the magic numbers written to the PHY_TUNE_{LOW_HIGH}
> +	 * registers are directly taken from the BSP USB3 driver from
> +	 * Allwiner.
> +	 */
> +	writel(0x0047fc87, phy->regs + SUNXI_PHY_TUNE_LOW);
> +
> +	val = readl(phy->regs + SUNXI_PHY_TUNE_HIGH);
> +	val &= ~(SUNXI_TXVBOOSTLVL_MASK | SUNXI_LOS_BIAS_MASK |
> +		 SUNXI_TX_SWING_FULL_MASK | SUNXI_TX_DEEMPH_6GB_MASK |
> +		 SUNXI_TX_DEEMPH_3P5DB_MASK);
> +	val |= SUNXI_TXVBOOSTLVL(0x7);
> +	val |= SUNXI_LOS_BIAS(0x7);
> +	val |= SUNXI_TX_SWING_FULL(0x55);
> +	val |= SUNXI_TX_DEEMPH_6DB(0x20);
> +	val |= SUNXI_TX_DEEMPH_3P5DB(0x15);
> +	writel(val, phy->regs + SUNXI_PHY_TUNE_HIGH);
> +}
> +
> +static int sun50i_usb3_phy_init(struct phy *_phy)
> +{
> +	struct sun50i_usb3_phy *phy = phy_get_drvdata(_phy);
> +	int ret;
> +
> +	ret = clk_prepare_enable(phy->clk);
> +	if (ret)
> +		goto err_clk;
> +
> +	ret = reset_control_deassert(phy->reset);
> +	if (ret)
> +		goto err_reset;
> +
> +	sun50i_usb3_phy_open(phy);
> +	return 0;
> +
> +err_reset:
> +	clk_disable_unprepare(phy->clk);
> +
> +err_clk:
> +	return ret;
> +}
> +
> +static int sun50i_usb3_phy_exit(struct phy *_phy)
> +{
> +	struct sun50i_usb3_phy *phy = phy_get_drvdata(_phy);
> +
> +	reset_control_assert(phy->reset);
> +	clk_disable_unprepare(phy->clk);
> +
> +	return 0;
> +}
> +
> +static int sun50i_usb3_phy_power_on(struct phy *_phy)
> +{
> +	struct sun50i_usb3_phy *phy = phy_get_drvdata(_phy);
> +
> +	if (phy->vbus)
> +		return regulator_enable(phy->vbus);
> +	else
> +		return 0;
> +}
> +
> +static int sun50i_usb3_phy_power_off(struct phy *_phy)
> +{
> +	struct sun50i_usb3_phy *phy = phy_get_drvdata(_phy);
> +
> +	if (phy->vbus)
> +		return regulator_disable(phy->vbus);
> +	else
> +		return 0;
> +}
> +
> +static const struct phy_ops sun50i_usb3_phy_ops = {
> +	.init		= sun50i_usb3_phy_init,
> +	.exit		= sun50i_usb3_phy_exit,
> +	.power_on	= sun50i_usb3_phy_power_on,
> +	.power_off	= sun50i_usb3_phy_power_off,
> +	.owner		= THIS_MODULE,
> +};
> +
> +static int sun50i_usb3_phy_probe(struct platform_device *pdev)
> +{
> +	struct sun50i_usb3_phy *phy;
> +	struct device *dev = &pdev->dev;
> +	struct phy_provider *phy_provider;
> +	struct resource *res;
> +	struct device_node *connector_node;
> +	int ret;
> +
> +	phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
> +	if (!phy)
> +		return -ENOMEM;
> +
> +	dev_set_drvdata(dev, phy);
> +
> +	phy->clk = devm_clk_get(dev, NULL);
> +	if (IS_ERR(phy->clk)) {
> +		dev_err(dev, "failed to get phy clock\n");
> +		return PTR_ERR(phy->clk);
> +	}
> +
> +	phy->reset = devm_reset_control_get(dev, NULL);
> +	if (IS_ERR(phy->reset)) {
> +		dev_err(dev, "failed to get reset control\n");
> +		return PTR_ERR(phy->reset);
> +	}
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	phy->regs = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(phy->regs))
> +		return PTR_ERR(phy->regs);
> +
> +	/* Populate the connector as platform device */
> +	ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
> +	if (ret)
> +		return ret;
> +
> +	/*
> +	 * Currently the Allwinner USB3 PHY contains only one port, so we
> +	 * only process one connector now.
> +	 */
> +	connector_node = of_get_next_child(pdev->dev.of_node, NULL);
> +
> +	if (connector_node) {
> +		/* Get the platform device */
> +		phy->connector_dev = of_find_device_by_node(connector_node);
> +		if (!phy->connector_dev) {
> +			dev_err(dev, "no device for connector\n");
> +			return -ENODEV;
> +		}
> +
> +		phy->vbus = regulator_get(&phy->connector_dev->dev, "vbus");
> +		if (IS_ERR(phy->vbus))
> +			return PTR_ERR(phy->vbus);
> +	}
> +
> +	phy->phy = devm_phy_create(dev, NULL, &sun50i_usb3_phy_ops);
> +	if (IS_ERR(phy->phy)) {

You're possibly leaking phy->vbus here.

> +		dev_err(dev, "failed to create PHY\n");
> +		return PTR_ERR(phy->phy);
> +	}
> +
> +	phy_set_drvdata(phy->phy, phy);
> +	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
> +

... and also here:

> +	return PTR_ERR_OR_ZERO(phy_provider);
> +}
> +
> +static int sun50i_usb3_phy_remove(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct sun50i_usb3_phy *phy = dev_get_drvdata(dev);
> +
> +	if (phy->vbus)
> +		regulator_put(phy->vbus);

Perhaps just use devm_regulator_get, and drop he sun50i_usb3_phy_remove
entirely?

thank you and regards,
	Ondrej

> +	return 0;
> +}
> +
> +static const struct of_device_id sun50i_usb3_phy_of_match[] = {
> +	{ .compatible = "allwinner,sun50i-h6-usb3-phy" },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, sun50i_usb3_phy_of_match);
> +
> +static struct platform_driver sun50i_usb3_phy_driver = {
> +	.probe	= sun50i_usb3_phy_probe,
> +	.remove	= sun50i_usb3_phy_remove,
> +	.driver = {
> +		.of_match_table	= sun50i_usb3_phy_of_match,
> +		.name  = "sun50i-usb3-phy",
> +	}
> +};
> +module_platform_driver(sun50i_usb3_phy_driver);
> +
> +MODULE_DESCRIPTION("Allwinner sun50i USB 3.0 phy driver");
> +MODULE_AUTHOR("Icenowy Zheng <icenowy@aosc.io>");
> +MODULE_LICENSE("GPL");
> -- 
> 2.18.1
> 
> -- 
> You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

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

* Re: [linux-sunxi] [PATCH v5 3/5] phy: allwinner: add phy driver for USB3 PHY on Allwinner H6 SoC
  2019-04-06 17:21   ` [linux-sunxi] " Ondřej Jirman
@ 2019-04-06 17:24     ` Icenowy Zheng
  0 siblings, 0 replies; 16+ messages in thread
From: Icenowy Zheng @ 2019-04-06 17:24 UTC (permalink / raw)
  To: Ondřej Jirman
  Cc: Rob Herring, Kishon Vijay Abraham I, Maxime Ripard, Chen-Yu Tsai,
	devicetree, linux-kernel, linux-arm-kernel, linux-sunxi



于 2019年4月7日 GMT+08:00 上午1:21:13, "Ondřej Jirman" <megous@megous.com> 写到:
>Hello Icenowy,
>
>On Sat, Apr 06, 2019 at 04:57:34AM +0800, Icenowy Zheng wrote:
>> Allwinner H6 SoC contains a USB3 PHY (with USB2 DP/DM lines also
>> controlled).
>> 
>> Add a driver for it.
>> 
>> The register operations in this driver is mainly extracted from the
>BSP
>> USB3 driver.
>> 
>> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
>> Reviewed-by: Chen-Yu Tsai <wens@csie.org>
>> ---
>> Changes in v5:
>> - Dropped support for vbus-supply property in the device node itself
>and
>>   added support for vbus-supply property in the connector subnode.
>> 
>> Changes in v4:
>> - Added support for vbus-supply property.
>> 
>> Changes in v3:
>> - Dropped USB_SUPPORT dependency.
>> - Added Chen-Yu's Review tag.
>> 
>> No changes in v2, v1. drivers/phy/allwinner/Kconfig           |  12
>++
>>  drivers/phy/allwinner/Makefile          |   1 +
>>  drivers/phy/allwinner/phy-sun50i-usb3.c | 260
>++++++++++++++++++++++++
>>  3 files changed, 273 insertions(+)
>>  create mode 100644 drivers/phy/allwinner/phy-sun50i-usb3.c
>> 
>> diff --git a/drivers/phy/allwinner/Kconfig
>b/drivers/phy/allwinner/Kconfig
>> index fb1204bcc454..2c363db177f2 100644
>> --- a/drivers/phy/allwinner/Kconfig
>> +++ b/drivers/phy/allwinner/Kconfig
>> @@ -41,3 +41,15 @@ config PHY_SUN9I_USB
>>  	  sun9i SoCs.
>>  
>>  	  This driver controls each individual USB 2 host PHY.
>> +
>> +config PHY_SUN50I_USB3
>> +	tristate "Allwinner sun50i SoC USB3 PHY driver"
>> +	depends on ARCH_SUNXI && HAS_IOMEM && OF
>> +	depends on RESET_CONTROLLER
>> +	select USB_COMMON
>> +	select GENERIC_PHY
>> +	help
>> +	  Enable this to support the USB3.0-capable transceiver that is
>> +	  part of some Allwinner sun50i SoCs.
>> +
>> +	  This driver controls each individual USB 2+3 host PHY combo.
>> diff --git a/drivers/phy/allwinner/Makefile
>b/drivers/phy/allwinner/Makefile
>> index 7d0053efbfaa..59575a895779 100644
>> --- a/drivers/phy/allwinner/Makefile
>> +++ b/drivers/phy/allwinner/Makefile
>> @@ -1,3 +1,4 @@
>>  obj-$(CONFIG_PHY_SUN4I_USB)		+= phy-sun4i-usb.o
>>  obj-$(CONFIG_PHY_SUN6I_MIPI_DPHY)	+= phy-sun6i-mipi-dphy.o
>>  obj-$(CONFIG_PHY_SUN9I_USB)		+= phy-sun9i-usb.o
>> +obj-$(CONFIG_PHY_SUN50I_USB3)		+= phy-sun50i-usb3.o
>> diff --git a/drivers/phy/allwinner/phy-sun50i-usb3.c
>b/drivers/phy/allwinner/phy-sun50i-usb3.c
>> new file mode 100644
>> index 000000000000..5299aef98668
>> --- /dev/null
>> +++ b/drivers/phy/allwinner/phy-sun50i-usb3.c
>> @@ -0,0 +1,260 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * Allwinner sun50i(H6) USB 3.0 phy driver
>> + *
>> + * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
>> + *
>> + * Based on phy-sun9i-usb.c, which is:
>> + *
>> + * Copyright (C) 2014-2015 Chen-Yu Tsai <wens@csie.org>
>> + *
>> + * Based on code from Allwinner BSP, which is:
>> + *
>> + * Copyright (c) 2010-2015 Allwinner Technology Co., Ltd.
>> + */
>> +
>> +#include <linux/clk.h>
>> +#include <linux/err.h>
>> +#include <linux/io.h>
>> +#include <linux/module.h>
>> +#include <linux/phy/phy.h>
>> +#include <linux/of_platform.h>
>> +#include <linux/usb/of.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/regulator/consumer.h>
>> +#include <linux/reset.h>
>> +
>> +/* Interface Status and Control Registers */
>> +#define SUNXI_ISCR			0x00
>> +#define SUNXI_PIPE_CLOCK_CONTROL	0x14
>> +#define SUNXI_PHY_TUNE_LOW		0x18
>> +#define SUNXI_PHY_TUNE_HIGH		0x1c
>> +#define SUNXI_PHY_EXTERNAL_CONTROL	0x20
>> +
>> +/* USB2.0 Interface Status and Control Register */
>> +#define SUNXI_ISCR_FORCE_VBUS		(3 << 12)
>> +
>> +/* PIPE Clock Control Register */
>> +#define SUNXI_PCC_PIPE_CLK_OPEN		(1 << 6)
>> +
>> +/* PHY External Control Register */
>> +#define SUNXI_PEC_EXTERN_VBUS		(3 << 1)
>> +#define SUNXI_PEC_SSC_EN		(1 << 24)
>> +#define SUNXI_PEC_REF_SSP_EN		(1 << 26)
>> +
>> +/* PHY Tune High Register */
>> +#define SUNXI_TX_DEEMPH_3P5DB(n)	((n) << 19)
>> +#define SUNXI_TX_DEEMPH_3P5DB_MASK	GENMASK(24, 19)
>> +#define SUNXI_TX_DEEMPH_6DB(n)		((n) << 13)
>> +#define SUNXI_TX_DEEMPH_6GB_MASK	GENMASK(18, 13)
>> +#define SUNXI_TX_SWING_FULL(n)		((n) << 6)
>> +#define SUNXI_TX_SWING_FULL_MASK	GENMASK(12, 6)
>> +#define SUNXI_LOS_BIAS(n)		((n) << 3)
>> +#define SUNXI_LOS_BIAS_MASK		GENMASK(5, 3)
>> +#define SUNXI_TXVBOOSTLVL(n)		((n) << 0)
>> +#define SUNXI_TXVBOOSTLVL_MASK		GENMASK(0, 2)
>> +
>> +struct sun50i_usb3_phy {
>> +	struct phy *phy;
>> +	void __iomem *regs;
>> +	struct reset_control *reset;
>> +	struct clk *clk;
>> +	struct platform_device *connector_dev;
>> +	struct regulator *vbus;
>> +};
>> +
>> +static void sun50i_usb3_phy_open(struct sun50i_usb3_phy *phy)
>> +{
>> +	u32 val;
>> +
>> +	val = readl(phy->regs + SUNXI_PHY_EXTERNAL_CONTROL);
>> +	val |= SUNXI_PEC_EXTERN_VBUS;
>> +	val |= SUNXI_PEC_SSC_EN | SUNXI_PEC_REF_SSP_EN;
>> +	writel(val, phy->regs + SUNXI_PHY_EXTERNAL_CONTROL);
>> +
>> +	val = readl(phy->regs + SUNXI_PIPE_CLOCK_CONTROL);
>> +	val |= SUNXI_PCC_PIPE_CLK_OPEN;
>> +	writel(val, phy->regs + SUNXI_PIPE_CLOCK_CONTROL);
>> +
>> +	val = readl(phy->regs + SUNXI_ISCR);
>> +	val |= SUNXI_ISCR_FORCE_VBUS;
>> +	writel(val, phy->regs + SUNXI_ISCR);
>> +
>> +	/*
>> +	 * All the magic numbers written to the PHY_TUNE_{LOW_HIGH}
>> +	 * registers are directly taken from the BSP USB3 driver from
>> +	 * Allwiner.
>> +	 */
>> +	writel(0x0047fc87, phy->regs + SUNXI_PHY_TUNE_LOW);
>> +
>> +	val = readl(phy->regs + SUNXI_PHY_TUNE_HIGH);
>> +	val &= ~(SUNXI_TXVBOOSTLVL_MASK | SUNXI_LOS_BIAS_MASK |
>> +		 SUNXI_TX_SWING_FULL_MASK | SUNXI_TX_DEEMPH_6GB_MASK |
>> +		 SUNXI_TX_DEEMPH_3P5DB_MASK);
>> +	val |= SUNXI_TXVBOOSTLVL(0x7);
>> +	val |= SUNXI_LOS_BIAS(0x7);
>> +	val |= SUNXI_TX_SWING_FULL(0x55);
>> +	val |= SUNXI_TX_DEEMPH_6DB(0x20);
>> +	val |= SUNXI_TX_DEEMPH_3P5DB(0x15);
>> +	writel(val, phy->regs + SUNXI_PHY_TUNE_HIGH);
>> +}
>> +
>> +static int sun50i_usb3_phy_init(struct phy *_phy)
>> +{
>> +	struct sun50i_usb3_phy *phy = phy_get_drvdata(_phy);
>> +	int ret;
>> +
>> +	ret = clk_prepare_enable(phy->clk);
>> +	if (ret)
>> +		goto err_clk;
>> +
>> +	ret = reset_control_deassert(phy->reset);
>> +	if (ret)
>> +		goto err_reset;
>> +
>> +	sun50i_usb3_phy_open(phy);
>> +	return 0;
>> +
>> +err_reset:
>> +	clk_disable_unprepare(phy->clk);
>> +
>> +err_clk:
>> +	return ret;
>> +}
>> +
>> +static int sun50i_usb3_phy_exit(struct phy *_phy)
>> +{
>> +	struct sun50i_usb3_phy *phy = phy_get_drvdata(_phy);
>> +
>> +	reset_control_assert(phy->reset);
>> +	clk_disable_unprepare(phy->clk);
>> +
>> +	return 0;
>> +}
>> +
>> +static int sun50i_usb3_phy_power_on(struct phy *_phy)
>> +{
>> +	struct sun50i_usb3_phy *phy = phy_get_drvdata(_phy);
>> +
>> +	if (phy->vbus)
>> +		return regulator_enable(phy->vbus);
>> +	else
>> +		return 0;
>> +}
>> +
>> +static int sun50i_usb3_phy_power_off(struct phy *_phy)
>> +{
>> +	struct sun50i_usb3_phy *phy = phy_get_drvdata(_phy);
>> +
>> +	if (phy->vbus)
>> +		return regulator_disable(phy->vbus);
>> +	else
>> +		return 0;
>> +}
>> +
>> +static const struct phy_ops sun50i_usb3_phy_ops = {
>> +	.init		= sun50i_usb3_phy_init,
>> +	.exit		= sun50i_usb3_phy_exit,
>> +	.power_on	= sun50i_usb3_phy_power_on,
>> +	.power_off	= sun50i_usb3_phy_power_off,
>> +	.owner		= THIS_MODULE,
>> +};
>> +
>> +static int sun50i_usb3_phy_probe(struct platform_device *pdev)
>> +{
>> +	struct sun50i_usb3_phy *phy;
>> +	struct device *dev = &pdev->dev;
>> +	struct phy_provider *phy_provider;
>> +	struct resource *res;
>> +	struct device_node *connector_node;
>> +	int ret;
>> +
>> +	phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
>> +	if (!phy)
>> +		return -ENOMEM;
>> +
>> +	dev_set_drvdata(dev, phy);
>> +
>> +	phy->clk = devm_clk_get(dev, NULL);
>> +	if (IS_ERR(phy->clk)) {
>> +		dev_err(dev, "failed to get phy clock\n");
>> +		return PTR_ERR(phy->clk);
>> +	}
>> +
>> +	phy->reset = devm_reset_control_get(dev, NULL);
>> +	if (IS_ERR(phy->reset)) {
>> +		dev_err(dev, "failed to get reset control\n");
>> +		return PTR_ERR(phy->reset);
>> +	}
>> +
>> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +	phy->regs = devm_ioremap_resource(dev, res);
>> +	if (IS_ERR(phy->regs))
>> +		return PTR_ERR(phy->regs);
>> +
>> +	/* Populate the connector as platform device */
>> +	ret = of_platform_populate(pdev->dev.of_node, NULL, NULL,
>&pdev->dev);
>> +	if (ret)
>> +		return ret;
>> +
>> +	/*
>> +	 * Currently the Allwinner USB3 PHY contains only one port, so we
>> +	 * only process one connector now.
>> +	 */
>> +	connector_node = of_get_next_child(pdev->dev.of_node, NULL);
>> +
>> +	if (connector_node) {
>> +		/* Get the platform device */
>> +		phy->connector_dev = of_find_device_by_node(connector_node);
>> +		if (!phy->connector_dev) {
>> +			dev_err(dev, "no device for connector\n");
>> +			return -ENODEV;
>> +		}
>> +
>> +		phy->vbus = regulator_get(&phy->connector_dev->dev, "vbus");
>> +		if (IS_ERR(phy->vbus))
>> +			return PTR_ERR(phy->vbus);
>> +	}
>> +
>> +	phy->phy = devm_phy_create(dev, NULL, &sun50i_usb3_phy_ops);
>> +	if (IS_ERR(phy->phy)) {
>
>You're possibly leaking phy->vbus here.

Thanks.

>
>> +		dev_err(dev, "failed to create PHY\n");
>> +		return PTR_ERR(phy->phy);
>> +	}
>> +
>> +	phy_set_drvdata(phy->phy, phy);
>> +	phy_provider = devm_of_phy_provider_register(dev,
>of_phy_simple_xlate);
>> +
>
>... and also here:
>
>> +	return PTR_ERR_OR_ZERO(phy_provider);
>> +}
>> +
>> +static int sun50i_usb3_phy_remove(struct platform_device *pdev)
>> +{
>> +	struct device *dev = &pdev->dev;
>> +	struct sun50i_usb3_phy *phy = dev_get_drvdata(dev);
>> +
>> +	if (phy->vbus)
>> +		regulator_put(phy->vbus);
>
>Perhaps just use devm_regulator_get, and drop he sun50i_usb3_phy_remove
>entirely?

No. We're borrowing another device's regulator, so devm function won't
work here -- it will clean up when the connector gets removed, not the phy,
but the connector has no driver.

>
>thank you and regards,
>	Ondrej
>
>> +	return 0;
>> +}
>> +
>> +static const struct of_device_id sun50i_usb3_phy_of_match[] = {
>> +	{ .compatible = "allwinner,sun50i-h6-usb3-phy" },
>> +	{ },
>> +};
>> +MODULE_DEVICE_TABLE(of, sun50i_usb3_phy_of_match);
>> +
>> +static struct platform_driver sun50i_usb3_phy_driver = {
>> +	.probe	= sun50i_usb3_phy_probe,
>> +	.remove	= sun50i_usb3_phy_remove,
>> +	.driver = {
>> +		.of_match_table	= sun50i_usb3_phy_of_match,
>> +		.name  = "sun50i-usb3-phy",
>> +	}
>> +};
>> +module_platform_driver(sun50i_usb3_phy_driver);
>> +
>> +MODULE_DESCRIPTION("Allwinner sun50i USB 3.0 phy driver");
>> +MODULE_AUTHOR("Icenowy Zheng <icenowy@aosc.io>");
>> +MODULE_LICENSE("GPL");
>> -- 
>> 2.18.1
>> 
>> -- 
>> You received this message because you are subscribed to the Google
>Groups "linux-sunxi" group.
>> To unsubscribe from this group and stop receiving emails from it,
>send an email to linux-sunxi+unsubscribe@googlegroups.com.
>> For more options, visit https://groups.google.com/d/optout.

-- 
使用 K-9 Mail 发送自我的Android设备。

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

* Re: [PATCH v5 2/5] dt-bindings: phy: add binding for Allwinner USB3 PHY
  2019-04-05 20:57 ` [PATCH v5 2/5] dt-bindings: phy: add binding for Allwinner USB3 PHY Icenowy Zheng
  2019-04-06  7:14   ` Rob Herring
@ 2019-04-08  7:14   ` Maxime Ripard
  1 sibling, 0 replies; 16+ messages in thread
From: Maxime Ripard @ 2019-04-08  7:14 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Kishon Vijay Abraham I, Chen-Yu Tsai, devicetree,
	linux-kernel, linux-arm-kernel, linux-sunxi

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

Hi,

On Sat, Apr 06, 2019 at 04:57:33AM +0800, Icenowy Zheng wrote:
> The new Allwinner H6 SoC contains a USB3 PHY that is wired to the
> external USB3 pins of the SoC.
>
> Add a device tree binding for the PHY.
>
> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
> Reviewed-by: Chen-Yu Tsai <wens@csie.org>

I know that this isn't the first iteration, and sorry if this comes
out a bit late, but could you make a YAML schemas for this instead?

Thanks!
Maxime

--
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

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

* Re: [PATCH v5 2/5] dt-bindings: phy: add binding for Allwinner USB3 PHY
  2019-04-06  7:24     ` Icenowy Zheng
@ 2019-04-09  1:09       ` Rob Herring
  0 siblings, 0 replies; 16+ messages in thread
From: Rob Herring @ 2019-04-09  1:09 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	devicetree, Maxime Ripard, linux-sunxi, linux-kernel,
	Kishon Vijay Abraham I, Chen-Yu Tsai

On Sat, Apr 6, 2019 at 2:24 AM Icenowy Zheng <icenowy@aosc.io> wrote:
>
>
>
> 于 2019年4月6日 GMT+08:00 下午3:14:02, Rob Herring <robh@kernel.org> 写到:
> >On Sat, Apr 06, 2019 at 04:57:33AM +0800, Icenowy Zheng wrote:
> >> The new Allwinner H6 SoC contains a USB3 PHY that is wired to the
> >> external USB3 pins of the SoC.
> >>
> >> Add a device tree binding for the PHY.
> >>
> >> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
> >> Reviewed-by: Chen-Yu Tsai <wens@csie.org>
> >> ---
> >> Changes in v5:
> >> - Dropped Vbus regulator and added connector subnode.
> >>
> >> Changes in v4:
> >> - Changed Vbus regulator property to vbus-supply.
> >>
> >> Changes in v3:
> >> - Added Chen-Yu's Review tag.
> >>
> >> No changes in v2, v1.
> >>
> >>  .../bindings/phy/sun50i-usb3-phy.txt          | 28
> >+++++++++++++++++++
> >>  1 file changed, 28 insertions(+)
> >>  create mode 100644
> >Documentation/devicetree/bindings/phy/sun50i-usb3-phy.txt
> >>
> >> diff --git
> >a/Documentation/devicetree/bindings/phy/sun50i-usb3-phy.txt
> >b/Documentation/devicetree/bindings/phy/sun50i-usb3-phy.txt
> >> new file mode 100644
> >> index 000000000000..eeedc53e6360
> >> --- /dev/null
> >> +++ b/Documentation/devicetree/bindings/phy/sun50i-usb3-phy.txt
> >> @@ -0,0 +1,28 @@
> >> +Allwinner sun50i USB3 PHY
> >> +-----------------------
> >> +
> >> +Required properties:
> >> +- compatible : should be one of
> >> +  * allwinner,sun60i-h6-usb3-phy
> >> +- reg : a list of offset + length pairs
> >> +- #phy-cells : from the generic phy bindings, must be 0
> >> +- clocks : phandle + clock specifier for the phy clock
> >> +- resets : phandle + reset specifier for the phy reset
> >> +
> >> +Optional nodes:
> >> +- connector : A sub-node required for representing the connector
> >connected
> >> +          to the USB PHY. See ../connector/usb-connector.txt for
> >details.
> >> +
> >> +Example:
> >> +    usb3phy: phy@5210000 {
> >> +            compatible = "allwinner,sun50i-h6-usb3-phy";
> >> +            reg = <0x5210000 0x10000>;
> >> +            clocks = <&ccu CLK_USB_PHY1>;
> >> +            resets = <&ccu RST_USB_PHY1>;
> >> +            #phy-cells = <0>;
> >> +
> >> +            connector {
> >> +                    compatible = "usb-a-connector";
> >> +                    label = "USB3";
> >
> >The binding defines that a connector is a child of USB controller or
>
> Please note that the word used is not "USB controller", but "USB interface
> controller".

Same thing.

We do not represent PHYs as part of the hierarchy. The controller just
points to its PHY with the 'phys' property, but is not part of the
graph.

Unless your PHY handle USB-C functions like PD and alternate modes,
then it shouldn't be part of the graph.

> A USB controller is something that deal with USB protocol, and connect to a USB
> PHY with ULPI/UTMI/PIPE interface. It's not connected to the connector
> directly at all. Then the PHY is connected to the interface controller (if present), or
> the connector, with D+, D- and SS pins.
>
> >some port controller (such as USB-C ctrlr) with OF graph to USB
> >controller. So either way, this is wrong unless this is more than just
> >a
> >phy.
> >
> >Rob
> >
> >_______________________________________________
> >linux-arm-kernel mailing list
> >linux-arm-kernel@lists.infradead.org
> >http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
> --
> 使用 K-9 Mail 发送自我的Android设备。

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

* Re: [linux-sunxi] [PATCH v5 3/5] phy: allwinner: add phy driver for USB3 PHY on Allwinner H6 SoC
  2019-04-05 20:57 ` [PATCH v5 3/5] phy: allwinner: add phy driver for USB3 PHY on Allwinner H6 SoC Icenowy Zheng
  2019-04-06 17:21   ` [linux-sunxi] " Ondřej Jirman
@ 2019-04-09 16:34   ` Clément Péron
  2019-04-11  0:15   ` Ondřej Jirman
  2019-04-11  0:20   ` Ondřej Jirman
  3 siblings, 0 replies; 16+ messages in thread
From: Clément Péron @ 2019-04-09 16:34 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Kishon Vijay Abraham I, Maxime Ripard, Chen-Yu Tsai,
	devicetree, linux-kernel, linux-arm-kernel, linux-sunxi

Hi,

On Fri, 5 Apr 2019 at 22:58, Icenowy Zheng <icenowy@aosc.io> wrote:
>
> Allwinner H6 SoC contains a USB3 PHY (with USB2 DP/DM lines also
> controlled).
>
> Add a driver for it.

Tested the serie on top of sunxi/for-next with USB3 storage and
HID-generic keyboard on my Beelink GS1.

Tested-by: Clément Péron <peron.clem@gmail.com>

 Just a suggestion could you add a patch to enable this PHY in the
arm64/defconfig by default ?

Thanks,
Clément

>
> The register operations in this driver is mainly extracted from the BSP
> USB3 driver.
>
> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
> Reviewed-by: Chen-Yu Tsai <wens@csie.org>
> ---
> Changes in v5:
> - Dropped support for vbus-supply property in the device node itself and
>   added support for vbus-supply property in the connector subnode.
>
> Changes in v4:
> - Added support for vbus-supply property.
>
> Changes in v3:
> - Dropped USB_SUPPORT dependency.
> - Added Chen-Yu's Review tag.
>
> No changes in v2, v1. drivers/phy/allwinner/Kconfig           |  12 ++
>  drivers/phy/allwinner/Makefile          |   1 +
>  drivers/phy/allwinner/phy-sun50i-usb3.c | 260 ++++++++++++++++++++++++
>  3 files changed, 273 insertions(+)
>  create mode 100644 drivers/phy/allwinner/phy-sun50i-usb3.c
>
> diff --git a/drivers/phy/allwinner/Kconfig b/drivers/phy/allwinner/Kconfig
> index fb1204bcc454..2c363db177f2 100644
> --- a/drivers/phy/allwinner/Kconfig
> +++ b/drivers/phy/allwinner/Kconfig
> @@ -41,3 +41,15 @@ config PHY_SUN9I_USB
>           sun9i SoCs.
>
>           This driver controls each individual USB 2 host PHY.
> +
> +config PHY_SUN50I_USB3
> +       tristate "Allwinner sun50i SoC USB3 PHY driver"
> +       depends on ARCH_SUNXI && HAS_IOMEM && OF
> +       depends on RESET_CONTROLLER
> +       select USB_COMMON
> +       select GENERIC_PHY
> +       help
> +         Enable this to support the USB3.0-capable transceiver that is
> +         part of some Allwinner sun50i SoCs.
> +
> +         This driver controls each individual USB 2+3 host PHY combo.
> diff --git a/drivers/phy/allwinner/Makefile b/drivers/phy/allwinner/Makefile
> index 7d0053efbfaa..59575a895779 100644
> --- a/drivers/phy/allwinner/Makefile
> +++ b/drivers/phy/allwinner/Makefile
> @@ -1,3 +1,4 @@
>  obj-$(CONFIG_PHY_SUN4I_USB)            += phy-sun4i-usb.o
>  obj-$(CONFIG_PHY_SUN6I_MIPI_DPHY)      += phy-sun6i-mipi-dphy.o
>  obj-$(CONFIG_PHY_SUN9I_USB)            += phy-sun9i-usb.o
> +obj-$(CONFIG_PHY_SUN50I_USB3)          += phy-sun50i-usb3.o
> diff --git a/drivers/phy/allwinner/phy-sun50i-usb3.c b/drivers/phy/allwinner/phy-sun50i-usb3.c
> new file mode 100644
> index 000000000000..5299aef98668
> --- /dev/null
> +++ b/drivers/phy/allwinner/phy-sun50i-usb3.c
> @@ -0,0 +1,260 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Allwinner sun50i(H6) USB 3.0 phy driver
> + *
> + * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
> + *
> + * Based on phy-sun9i-usb.c, which is:
> + *
> + * Copyright (C) 2014-2015 Chen-Yu Tsai <wens@csie.org>
> + *
> + * Based on code from Allwinner BSP, which is:
> + *
> + * Copyright (c) 2010-2015 Allwinner Technology Co., Ltd.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/phy/phy.h>
> +#include <linux/of_platform.h>
> +#include <linux/usb/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/reset.h>
> +
> +/* Interface Status and Control Registers */
> +#define SUNXI_ISCR                     0x00
> +#define SUNXI_PIPE_CLOCK_CONTROL       0x14
> +#define SUNXI_PHY_TUNE_LOW             0x18
> +#define SUNXI_PHY_TUNE_HIGH            0x1c
> +#define SUNXI_PHY_EXTERNAL_CONTROL     0x20
> +
> +/* USB2.0 Interface Status and Control Register */
> +#define SUNXI_ISCR_FORCE_VBUS          (3 << 12)
> +
> +/* PIPE Clock Control Register */
> +#define SUNXI_PCC_PIPE_CLK_OPEN                (1 << 6)
> +
> +/* PHY External Control Register */
> +#define SUNXI_PEC_EXTERN_VBUS          (3 << 1)
> +#define SUNXI_PEC_SSC_EN               (1 << 24)
> +#define SUNXI_PEC_REF_SSP_EN           (1 << 26)
> +
> +/* PHY Tune High Register */
> +#define SUNXI_TX_DEEMPH_3P5DB(n)       ((n) << 19)
> +#define SUNXI_TX_DEEMPH_3P5DB_MASK     GENMASK(24, 19)
> +#define SUNXI_TX_DEEMPH_6DB(n)         ((n) << 13)
> +#define SUNXI_TX_DEEMPH_6GB_MASK       GENMASK(18, 13)
> +#define SUNXI_TX_SWING_FULL(n)         ((n) << 6)
> +#define SUNXI_TX_SWING_FULL_MASK       GENMASK(12, 6)
> +#define SUNXI_LOS_BIAS(n)              ((n) << 3)
> +#define SUNXI_LOS_BIAS_MASK            GENMASK(5, 3)
> +#define SUNXI_TXVBOOSTLVL(n)           ((n) << 0)
> +#define SUNXI_TXVBOOSTLVL_MASK         GENMASK(0, 2)
> +
> +struct sun50i_usb3_phy {
> +       struct phy *phy;
> +       void __iomem *regs;
> +       struct reset_control *reset;
> +       struct clk *clk;
> +       struct platform_device *connector_dev;
> +       struct regulator *vbus;
> +};
> +
> +static void sun50i_usb3_phy_open(struct sun50i_usb3_phy *phy)
> +{
> +       u32 val;
> +
> +       val = readl(phy->regs + SUNXI_PHY_EXTERNAL_CONTROL);
> +       val |= SUNXI_PEC_EXTERN_VBUS;
> +       val |= SUNXI_PEC_SSC_EN | SUNXI_PEC_REF_SSP_EN;
> +       writel(val, phy->regs + SUNXI_PHY_EXTERNAL_CONTROL);
> +
> +       val = readl(phy->regs + SUNXI_PIPE_CLOCK_CONTROL);
> +       val |= SUNXI_PCC_PIPE_CLK_OPEN;
> +       writel(val, phy->regs + SUNXI_PIPE_CLOCK_CONTROL);
> +
> +       val = readl(phy->regs + SUNXI_ISCR);
> +       val |= SUNXI_ISCR_FORCE_VBUS;
> +       writel(val, phy->regs + SUNXI_ISCR);
> +
> +       /*
> +        * All the magic numbers written to the PHY_TUNE_{LOW_HIGH}
> +        * registers are directly taken from the BSP USB3 driver from
> +        * Allwiner.
> +        */
> +       writel(0x0047fc87, phy->regs + SUNXI_PHY_TUNE_LOW);
> +
> +       val = readl(phy->regs + SUNXI_PHY_TUNE_HIGH);
> +       val &= ~(SUNXI_TXVBOOSTLVL_MASK | SUNXI_LOS_BIAS_MASK |
> +                SUNXI_TX_SWING_FULL_MASK | SUNXI_TX_DEEMPH_6GB_MASK |
> +                SUNXI_TX_DEEMPH_3P5DB_MASK);
> +       val |= SUNXI_TXVBOOSTLVL(0x7);
> +       val |= SUNXI_LOS_BIAS(0x7);
> +       val |= SUNXI_TX_SWING_FULL(0x55);
> +       val |= SUNXI_TX_DEEMPH_6DB(0x20);
> +       val |= SUNXI_TX_DEEMPH_3P5DB(0x15);
> +       writel(val, phy->regs + SUNXI_PHY_TUNE_HIGH);
> +}
> +
> +static int sun50i_usb3_phy_init(struct phy *_phy)
> +{
> +       struct sun50i_usb3_phy *phy = phy_get_drvdata(_phy);
> +       int ret;
> +
> +       ret = clk_prepare_enable(phy->clk);
> +       if (ret)
> +               goto err_clk;
> +
> +       ret = reset_control_deassert(phy->reset);
> +       if (ret)
> +               goto err_reset;
> +
> +       sun50i_usb3_phy_open(phy);
> +       return 0;
> +
> +err_reset:
> +       clk_disable_unprepare(phy->clk);
> +
> +err_clk:
> +       return ret;
> +}
> +
> +static int sun50i_usb3_phy_exit(struct phy *_phy)
> +{
> +       struct sun50i_usb3_phy *phy = phy_get_drvdata(_phy);
> +
> +       reset_control_assert(phy->reset);
> +       clk_disable_unprepare(phy->clk);
> +
> +       return 0;
> +}
> +
> +static int sun50i_usb3_phy_power_on(struct phy *_phy)
> +{
> +       struct sun50i_usb3_phy *phy = phy_get_drvdata(_phy);
> +
> +       if (phy->vbus)
> +               return regulator_enable(phy->vbus);
> +       else
> +               return 0;
> +}
> +
> +static int sun50i_usb3_phy_power_off(struct phy *_phy)
> +{
> +       struct sun50i_usb3_phy *phy = phy_get_drvdata(_phy);
> +
> +       if (phy->vbus)
> +               return regulator_disable(phy->vbus);
> +       else
> +               return 0;
> +}
> +
> +static const struct phy_ops sun50i_usb3_phy_ops = {
> +       .init           = sun50i_usb3_phy_init,
> +       .exit           = sun50i_usb3_phy_exit,
> +       .power_on       = sun50i_usb3_phy_power_on,
> +       .power_off      = sun50i_usb3_phy_power_off,
> +       .owner          = THIS_MODULE,
> +};
> +
> +static int sun50i_usb3_phy_probe(struct platform_device *pdev)
> +{
> +       struct sun50i_usb3_phy *phy;
> +       struct device *dev = &pdev->dev;
> +       struct phy_provider *phy_provider;
> +       struct resource *res;
> +       struct device_node *connector_node;
> +       int ret;
> +
> +       phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
> +       if (!phy)
> +               return -ENOMEM;
> +
> +       dev_set_drvdata(dev, phy);
> +
> +       phy->clk = devm_clk_get(dev, NULL);
> +       if (IS_ERR(phy->clk)) {
> +               dev_err(dev, "failed to get phy clock\n");
> +               return PTR_ERR(phy->clk);
> +       }
> +
> +       phy->reset = devm_reset_control_get(dev, NULL);
> +       if (IS_ERR(phy->reset)) {
> +               dev_err(dev, "failed to get reset control\n");
> +               return PTR_ERR(phy->reset);
> +       }
> +
> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       phy->regs = devm_ioremap_resource(dev, res);
> +       if (IS_ERR(phy->regs))
> +               return PTR_ERR(phy->regs);
> +
> +       /* Populate the connector as platform device */
> +       ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
> +       if (ret)
> +               return ret;
> +
> +       /*
> +        * Currently the Allwinner USB3 PHY contains only one port, so we
> +        * only process one connector now.
> +        */
> +       connector_node = of_get_next_child(pdev->dev.of_node, NULL);
> +
> +       if (connector_node) {
> +               /* Get the platform device */
> +               phy->connector_dev = of_find_device_by_node(connector_node);
> +               if (!phy->connector_dev) {
> +                       dev_err(dev, "no device for connector\n");
> +                       return -ENODEV;
> +               }
> +
> +               phy->vbus = regulator_get(&phy->connector_dev->dev, "vbus");
> +               if (IS_ERR(phy->vbus))
> +                       return PTR_ERR(phy->vbus);
> +       }
> +
> +       phy->phy = devm_phy_create(dev, NULL, &sun50i_usb3_phy_ops);
> +       if (IS_ERR(phy->phy)) {
> +               dev_err(dev, "failed to create PHY\n");
> +               return PTR_ERR(phy->phy);
> +       }
> +
> +       phy_set_drvdata(phy->phy, phy);
> +       phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
> +
> +       return PTR_ERR_OR_ZERO(phy_provider);
> +}
> +
> +static int sun50i_usb3_phy_remove(struct platform_device *pdev)
> +{
> +       struct device *dev = &pdev->dev;
> +       struct sun50i_usb3_phy *phy = dev_get_drvdata(dev);
> +
> +       if (phy->vbus)
> +               regulator_put(phy->vbus);
> +
> +       return 0;
> +}
> +
> +static const struct of_device_id sun50i_usb3_phy_of_match[] = {
> +       { .compatible = "allwinner,sun50i-h6-usb3-phy" },
> +       { },
> +};
> +MODULE_DEVICE_TABLE(of, sun50i_usb3_phy_of_match);
> +
> +static struct platform_driver sun50i_usb3_phy_driver = {
> +       .probe  = sun50i_usb3_phy_probe,
> +       .remove = sun50i_usb3_phy_remove,
> +       .driver = {
> +               .of_match_table = sun50i_usb3_phy_of_match,
> +               .name  = "sun50i-usb3-phy",
> +       }
> +};
> +module_platform_driver(sun50i_usb3_phy_driver);
> +
> +MODULE_DESCRIPTION("Allwinner sun50i USB 3.0 phy driver");
> +MODULE_AUTHOR("Icenowy Zheng <icenowy@aosc.io>");
> +MODULE_LICENSE("GPL");
> --
> 2.18.1
>
> --
> You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

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

* Re: [linux-sunxi] [PATCH v5 3/5] phy: allwinner: add phy driver for USB3 PHY on Allwinner H6 SoC
  2019-04-05 20:57 ` [PATCH v5 3/5] phy: allwinner: add phy driver for USB3 PHY on Allwinner H6 SoC Icenowy Zheng
  2019-04-06 17:21   ` [linux-sunxi] " Ondřej Jirman
  2019-04-09 16:34   ` Clément Péron
@ 2019-04-11  0:15   ` Ondřej Jirman
  2019-04-11  0:20   ` Ondřej Jirman
  3 siblings, 0 replies; 16+ messages in thread
From: Ondřej Jirman @ 2019-04-11  0:15 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Kishon Vijay Abraham I, Maxime Ripard, Chen-Yu Tsai,
	devicetree, linux-kernel, linux-arm-kernel, linux-sunxi

Hello Icenowy,

On Sat, Apr 06, 2019 at 04:57:34AM +0800, Icenowy Zheng wrote:
> Allwinner H6 SoC contains a USB3 PHY (with USB2 DP/DM lines also
> controlled).
> 
> Add a driver for it.
> 
> The register operations in this driver is mainly extracted from the BSP
> USB3 driver.
> 
> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
> Reviewed-by: Chen-Yu Tsai <wens@csie.org>
> ---
> Changes in v5:
> - Dropped support for vbus-supply property in the device node itself and
>   added support for vbus-supply property in the connector subnode.
> 
> Changes in v4:
> - Added support for vbus-supply property.
> 
> Changes in v3:
> - Dropped USB_SUPPORT dependency.
> - Added Chen-Yu's Review tag.
> 
> No changes in v2, v1. drivers/phy/allwinner/Kconfig           |  12 ++
>  drivers/phy/allwinner/Makefile          |   1 +
>  drivers/phy/allwinner/phy-sun50i-usb3.c | 260 ++++++++++++++++++++++++
>  3 files changed, 273 insertions(+)
>  create mode 100644 drivers/phy/allwinner/phy-sun50i-usb3.c
> 
> diff --git a/drivers/phy/allwinner/Kconfig b/drivers/phy/allwinner/Kconfig
> index fb1204bcc454..2c363db177f2 100644
> --- a/drivers/phy/allwinner/Kconfig
> +++ b/drivers/phy/allwinner/Kconfig
> @@ -41,3 +41,15 @@ config PHY_SUN9I_USB
>  	  sun9i SoCs.
>  
>  	  This driver controls each individual USB 2 host PHY.
> +
> +config PHY_SUN50I_USB3
> +	tristate "Allwinner sun50i SoC USB3 PHY driver"
> +	depends on ARCH_SUNXI && HAS_IOMEM && OF
> +	depends on RESET_CONTROLLER
> +	select USB_COMMON
> +	select GENERIC_PHY
> +	help
> +	  Enable this to support the USB3.0-capable transceiver that is
> +	  part of some Allwinner sun50i SoCs.
> +
> +	  This driver controls each individual USB 2+3 host PHY combo.
> diff --git a/drivers/phy/allwinner/Makefile b/drivers/phy/allwinner/Makefile
> index 7d0053efbfaa..59575a895779 100644
> --- a/drivers/phy/allwinner/Makefile
> +++ b/drivers/phy/allwinner/Makefile
> @@ -1,3 +1,4 @@
>  obj-$(CONFIG_PHY_SUN4I_USB)		+= phy-sun4i-usb.o
>  obj-$(CONFIG_PHY_SUN6I_MIPI_DPHY)	+= phy-sun6i-mipi-dphy.o
>  obj-$(CONFIG_PHY_SUN9I_USB)		+= phy-sun9i-usb.o
> +obj-$(CONFIG_PHY_SUN50I_USB3)		+= phy-sun50i-usb3.o
> diff --git a/drivers/phy/allwinner/phy-sun50i-usb3.c b/drivers/phy/allwinner/phy-sun50i-usb3.c
> new file mode 100644
> index 000000000000..5299aef98668
> --- /dev/null
> +++ b/drivers/phy/allwinner/phy-sun50i-usb3.c
> @@ -0,0 +1,260 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Allwinner sun50i(H6) USB 3.0 phy driver
> + *
> + * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
> + *
> + * Based on phy-sun9i-usb.c, which is:
> + *
> + * Copyright (C) 2014-2015 Chen-Yu Tsai <wens@csie.org>
> + *
> + * Based on code from Allwinner BSP, which is:
> + *
> + * Copyright (c) 2010-2015 Allwinner Technology Co., Ltd.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/phy/phy.h>
> +#include <linux/of_platform.h>
> +#include <linux/usb/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/reset.h>
> +
> +/* Interface Status and Control Registers */
> +#define SUNXI_ISCR			0x00
> +#define SUNXI_PIPE_CLOCK_CONTROL	0x14
> +#define SUNXI_PHY_TUNE_LOW		0x18
> +#define SUNXI_PHY_TUNE_HIGH		0x1c
> +#define SUNXI_PHY_EXTERNAL_CONTROL	0x20
> +
> +/* USB2.0 Interface Status and Control Register */
> +#define SUNXI_ISCR_FORCE_VBUS		(3 << 12)
> +
> +/* PIPE Clock Control Register */
> +#define SUNXI_PCC_PIPE_CLK_OPEN		(1 << 6)
> +
> +/* PHY External Control Register */
> +#define SUNXI_PEC_EXTERN_VBUS		(3 << 1)
> +#define SUNXI_PEC_SSC_EN		(1 << 24)
> +#define SUNXI_PEC_REF_SSP_EN		(1 << 26)
> +
> +/* PHY Tune High Register */
> +#define SUNXI_TX_DEEMPH_3P5DB(n)	((n) << 19)
> +#define SUNXI_TX_DEEMPH_3P5DB_MASK	GENMASK(24, 19)
> +#define SUNXI_TX_DEEMPH_6DB(n)		((n) << 13)
> +#define SUNXI_TX_DEEMPH_6GB_MASK	GENMASK(18, 13)
> +#define SUNXI_TX_SWING_FULL(n)		((n) << 6)
> +#define SUNXI_TX_SWING_FULL_MASK	GENMASK(12, 6)
> +#define SUNXI_LOS_BIAS(n)		((n) << 3)
> +#define SUNXI_LOS_BIAS_MASK		GENMASK(5, 3)
> +#define SUNXI_TXVBOOSTLVL(n)		((n) << 0)
> +#define SUNXI_TXVBOOSTLVL_MASK		GENMASK(0, 2)
> +
> +struct sun50i_usb3_phy {
> +	struct phy *phy;
> +	void __iomem *regs;
> +	struct reset_control *reset;
> +	struct clk *clk;
> +	struct platform_device *connector_dev;
> +	struct regulator *vbus;
> +};
> +
> +static void sun50i_usb3_phy_open(struct sun50i_usb3_phy *phy)
> +{
> +	u32 val;
> +
> +	val = readl(phy->regs + SUNXI_PHY_EXTERNAL_CONTROL);
> +	val |= SUNXI_PEC_EXTERN_VBUS;
> +	val |= SUNXI_PEC_SSC_EN | SUNXI_PEC_REF_SSP_EN;
> +	writel(val, phy->regs + SUNXI_PHY_EXTERNAL_CONTROL);
> +
> +	val = readl(phy->regs + SUNXI_PIPE_CLOCK_CONTROL);
> +	val |= SUNXI_PCC_PIPE_CLK_OPEN;
> +	writel(val, phy->regs + SUNXI_PIPE_CLOCK_CONTROL);
> +
> +	val = readl(phy->regs + SUNXI_ISCR);
> +	val |= SUNXI_ISCR_FORCE_VBUS;
> +	writel(val, phy->regs + SUNXI_ISCR);
> +
> +	/*
> +	 * All the magic numbers written to the PHY_TUNE_{LOW_HIGH}
> +	 * registers are directly taken from the BSP USB3 driver from
> +	 * Allwiner.
> +	 */
> +	writel(0x0047fc87, phy->regs + SUNXI_PHY_TUNE_LOW);
> +
> +	val = readl(phy->regs + SUNXI_PHY_TUNE_HIGH);
> +	val &= ~(SUNXI_TXVBOOSTLVL_MASK | SUNXI_LOS_BIAS_MASK |
> +		 SUNXI_TX_SWING_FULL_MASK | SUNXI_TX_DEEMPH_6GB_MASK |
> +		 SUNXI_TX_DEEMPH_3P5DB_MASK);
> +	val |= SUNXI_TXVBOOSTLVL(0x7);
> +	val |= SUNXI_LOS_BIAS(0x7);
> +	val |= SUNXI_TX_SWING_FULL(0x55);
> +	val |= SUNXI_TX_DEEMPH_6DB(0x20);
> +	val |= SUNXI_TX_DEEMPH_3P5DB(0x15);
> +	writel(val, phy->regs + SUNXI_PHY_TUNE_HIGH);
> +}
> +
> +static int sun50i_usb3_phy_init(struct phy *_phy)
> +{
> +	struct sun50i_usb3_phy *phy = phy_get_drvdata(_phy);
> +	int ret;
> +
> +	ret = clk_prepare_enable(phy->clk);
> +	if (ret)
> +		goto err_clk;
> +
> +	ret = reset_control_deassert(phy->reset);
> +	if (ret)
> +		goto err_reset;
> +
> +	sun50i_usb3_phy_open(phy);
> +	return 0;
> +
> +err_reset:
> +	clk_disable_unprepare(phy->clk);
> +
> +err_clk:
> +	return ret;
> +}
> +
> +static int sun50i_usb3_phy_exit(struct phy *_phy)
> +{
> +	struct sun50i_usb3_phy *phy = phy_get_drvdata(_phy);
> +
> +	reset_control_assert(phy->reset);
> +	clk_disable_unprepare(phy->clk);
> +
> +	return 0;
> +}
> +
> +static int sun50i_usb3_phy_power_on(struct phy *_phy)
> +{
> +	struct sun50i_usb3_phy *phy = phy_get_drvdata(_phy);
> +
> +	if (phy->vbus)
> +		return regulator_enable(phy->vbus);
> +	else
> +		return 0;
> +}
> +
> +static int sun50i_usb3_phy_power_off(struct phy *_phy)
> +{
> +	struct sun50i_usb3_phy *phy = phy_get_drvdata(_phy);
> +
> +	if (phy->vbus)
> +		return regulator_disable(phy->vbus);
> +	else
> +		return 0;
> +}
> +
> +static const struct phy_ops sun50i_usb3_phy_ops = {
> +	.init		= sun50i_usb3_phy_init,
> +	.exit		= sun50i_usb3_phy_exit,
> +	.power_on	= sun50i_usb3_phy_power_on,
> +	.power_off	= sun50i_usb3_phy_power_off,
> +	.owner		= THIS_MODULE,
> +};
> +
> +static int sun50i_usb3_phy_probe(struct platform_device *pdev)
> +{
> +	struct sun50i_usb3_phy *phy;
> +	struct device *dev = &pdev->dev;
> +	struct phy_provider *phy_provider;
> +	struct resource *res;
> +	struct device_node *connector_node;
> +	int ret;
> +
> +	phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
> +	if (!phy)
> +		return -ENOMEM;
> +
> +	dev_set_drvdata(dev, phy);
> +
> +	phy->clk = devm_clk_get(dev, NULL);
> +	if (IS_ERR(phy->clk)) {
> +		dev_err(dev, "failed to get phy clock\n");
> +		return PTR_ERR(phy->clk);
> +	}
> +
> +	phy->reset = devm_reset_control_get(dev, NULL);
> +	if (IS_ERR(phy->reset)) {
> +		dev_err(dev, "failed to get reset control\n");
> +		return PTR_ERR(phy->reset);
> +	}
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	phy->regs = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(phy->regs))
> +		return PTR_ERR(phy->regs);
> +
> +	/* Populate the connector as platform device */
> +	ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
> +	if (ret)
> +		return ret;
> +
> +	/*
> +	 * Currently the Allwinner USB3 PHY contains only one port, so we
> +	 * only process one connector now.
> +	 */
> +	connector_node = of_get_next_child(pdev->dev.of_node, NULL);

I also noticed, that you're leaking connector_node, but I guess next patch will
not have this code, so anyway... You should call of_node_put(). So just
something to keep in mind in the future.

regards,
	o.

> +	if (connector_node) {
> +		/* Get the platform device */
> +		phy->connector_dev = of_find_device_by_node(connector_node);
> +		if (!phy->connector_dev) {
> +			dev_err(dev, "no device for connector\n");
> +			return -ENODEV;
> +		}
> +
> +		phy->vbus = regulator_get(&phy->connector_dev->dev, "vbus");
> +		if (IS_ERR(phy->vbus))
> +			return PTR_ERR(phy->vbus);
> +	}
> +
> +	phy->phy = devm_phy_create(dev, NULL, &sun50i_usb3_phy_ops);
> +	if (IS_ERR(phy->phy)) {
> +		dev_err(dev, "failed to create PHY\n");
> +		return PTR_ERR(phy->phy);
> +	}
> +
> +	phy_set_drvdata(phy->phy, phy);
> +	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
> +
> +	return PTR_ERR_OR_ZERO(phy_provider);
> +}
> +
> +static int sun50i_usb3_phy_remove(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct sun50i_usb3_phy *phy = dev_get_drvdata(dev);
> +
> +	if (phy->vbus)
> +		regulator_put(phy->vbus);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id sun50i_usb3_phy_of_match[] = {
> +	{ .compatible = "allwinner,sun50i-h6-usb3-phy" },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, sun50i_usb3_phy_of_match);
> +
> +static struct platform_driver sun50i_usb3_phy_driver = {
> +	.probe	= sun50i_usb3_phy_probe,
> +	.remove	= sun50i_usb3_phy_remove,
> +	.driver = {
> +		.of_match_table	= sun50i_usb3_phy_of_match,
> +		.name  = "sun50i-usb3-phy",
> +	}
> +};
> +module_platform_driver(sun50i_usb3_phy_driver);
> +
> +MODULE_DESCRIPTION("Allwinner sun50i USB 3.0 phy driver");
> +MODULE_AUTHOR("Icenowy Zheng <icenowy@aosc.io>");
> +MODULE_LICENSE("GPL");
> -- 
> 2.18.1
> 
> -- 
> You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

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

* Re: [linux-sunxi] [PATCH v5 3/5] phy: allwinner: add phy driver for USB3 PHY on Allwinner H6 SoC
  2019-04-05 20:57 ` [PATCH v5 3/5] phy: allwinner: add phy driver for USB3 PHY on Allwinner H6 SoC Icenowy Zheng
                     ` (2 preceding siblings ...)
  2019-04-11  0:15   ` Ondřej Jirman
@ 2019-04-11  0:20   ` Ondřej Jirman
  3 siblings, 0 replies; 16+ messages in thread
From: Ondřej Jirman @ 2019-04-11  0:20 UTC (permalink / raw)
  To: Icenowy Zheng
  Cc: Rob Herring, Kishon Vijay Abraham I, Maxime Ripard, Chen-Yu Tsai,
	devicetree, linux-kernel, linux-arm-kernel, linux-sunxi

On Sat, Apr 06, 2019 at 04:57:34AM +0800, Icenowy Zheng wrote:
> Allwinner H6 SoC contains a USB3 PHY (with USB2 DP/DM lines also
> controlled).
> 
> Add a driver for it.
> 
> The register operations in this driver is mainly extracted from the BSP
> USB3 driver.
> 
> Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
> Reviewed-by: Chen-Yu Tsai <wens@csie.org>
> ---
> Changes in v5:
> - Dropped support for vbus-supply property in the device node itself and
>   added support for vbus-supply property in the connector subnode.
> 
> Changes in v4:
> - Added support for vbus-supply property.
> 
> Changes in v3:
> - Dropped USB_SUPPORT dependency.
> - Added Chen-Yu's Review tag.
> 
> No changes in v2, v1. drivers/phy/allwinner/Kconfig           |  12 ++
>  drivers/phy/allwinner/Makefile          |   1 +
>  drivers/phy/allwinner/phy-sun50i-usb3.c | 260 ++++++++++++++++++++++++
>  3 files changed, 273 insertions(+)
>  create mode 100644 drivers/phy/allwinner/phy-sun50i-usb3.c
> 
> diff --git a/drivers/phy/allwinner/Kconfig b/drivers/phy/allwinner/Kconfig
> index fb1204bcc454..2c363db177f2 100644
> --- a/drivers/phy/allwinner/Kconfig
> +++ b/drivers/phy/allwinner/Kconfig
> @@ -41,3 +41,15 @@ config PHY_SUN9I_USB
>  	  sun9i SoCs.
>  
>  	  This driver controls each individual USB 2 host PHY.
> +
> +config PHY_SUN50I_USB3
> +	tristate "Allwinner sun50i SoC USB3 PHY driver"
> +	depends on ARCH_SUNXI && HAS_IOMEM && OF
> +	depends on RESET_CONTROLLER
> +	select USB_COMMON
> +	select GENERIC_PHY
> +	help
> +	  Enable this to support the USB3.0-capable transceiver that is
> +	  part of some Allwinner sun50i SoCs.
> +
> +	  This driver controls each individual USB 2+3 host PHY combo.
> diff --git a/drivers/phy/allwinner/Makefile b/drivers/phy/allwinner/Makefile
> index 7d0053efbfaa..59575a895779 100644
> --- a/drivers/phy/allwinner/Makefile
> +++ b/drivers/phy/allwinner/Makefile
> @@ -1,3 +1,4 @@
>  obj-$(CONFIG_PHY_SUN4I_USB)		+= phy-sun4i-usb.o
>  obj-$(CONFIG_PHY_SUN6I_MIPI_DPHY)	+= phy-sun6i-mipi-dphy.o
>  obj-$(CONFIG_PHY_SUN9I_USB)		+= phy-sun9i-usb.o
> +obj-$(CONFIG_PHY_SUN50I_USB3)		+= phy-sun50i-usb3.o
> diff --git a/drivers/phy/allwinner/phy-sun50i-usb3.c b/drivers/phy/allwinner/phy-sun50i-usb3.c
> new file mode 100644
> index 000000000000..5299aef98668
> --- /dev/null
> +++ b/drivers/phy/allwinner/phy-sun50i-usb3.c
> @@ -0,0 +1,260 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Allwinner sun50i(H6) USB 3.0 phy driver
> + *
> + * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io>
> + *
> + * Based on phy-sun9i-usb.c, which is:
> + *
> + * Copyright (C) 2014-2015 Chen-Yu Tsai <wens@csie.org>
> + *
> + * Based on code from Allwinner BSP, which is:
> + *
> + * Copyright (c) 2010-2015 Allwinner Technology Co., Ltd.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/phy/phy.h>
> +#include <linux/of_platform.h>
> +#include <linux/usb/of.h>
> +#include <linux/platform_device.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/reset.h>
> +
> +/* Interface Status and Control Registers */
> +#define SUNXI_ISCR			0x00
> +#define SUNXI_PIPE_CLOCK_CONTROL	0x14
> +#define SUNXI_PHY_TUNE_LOW		0x18
> +#define SUNXI_PHY_TUNE_HIGH		0x1c
> +#define SUNXI_PHY_EXTERNAL_CONTROL	0x20
> +
> +/* USB2.0 Interface Status and Control Register */
> +#define SUNXI_ISCR_FORCE_VBUS		(3 << 12)
> +
> +/* PIPE Clock Control Register */
> +#define SUNXI_PCC_PIPE_CLK_OPEN		(1 << 6)
> +
> +/* PHY External Control Register */
> +#define SUNXI_PEC_EXTERN_VBUS		(3 << 1)
> +#define SUNXI_PEC_SSC_EN		(1 << 24)
> +#define SUNXI_PEC_REF_SSP_EN		(1 << 26)
> +
> +/* PHY Tune High Register */
> +#define SUNXI_TX_DEEMPH_3P5DB(n)	((n) << 19)
> +#define SUNXI_TX_DEEMPH_3P5DB_MASK	GENMASK(24, 19)
> +#define SUNXI_TX_DEEMPH_6DB(n)		((n) << 13)
> +#define SUNXI_TX_DEEMPH_6GB_MASK	GENMASK(18, 13)
> +#define SUNXI_TX_SWING_FULL(n)		((n) << 6)
> +#define SUNXI_TX_SWING_FULL_MASK	GENMASK(12, 6)
> +#define SUNXI_LOS_BIAS(n)		((n) << 3)
> +#define SUNXI_LOS_BIAS_MASK		GENMASK(5, 3)
> +#define SUNXI_TXVBOOSTLVL(n)		((n) << 0)
> +#define SUNXI_TXVBOOSTLVL_MASK		GENMASK(0, 2)
> +
> +struct sun50i_usb3_phy {
> +	struct phy *phy;
> +	void __iomem *regs;
> +	struct reset_control *reset;
> +	struct clk *clk;
> +	struct platform_device *connector_dev;
> +	struct regulator *vbus;
> +};
> +
> +static void sun50i_usb3_phy_open(struct sun50i_usb3_phy *phy)
> +{
> +	u32 val;
> +
> +	val = readl(phy->regs + SUNXI_PHY_EXTERNAL_CONTROL);
> +	val |= SUNXI_PEC_EXTERN_VBUS;
> +	val |= SUNXI_PEC_SSC_EN | SUNXI_PEC_REF_SSP_EN;
> +	writel(val, phy->regs + SUNXI_PHY_EXTERNAL_CONTROL);
> +
> +	val = readl(phy->regs + SUNXI_PIPE_CLOCK_CONTROL);
> +	val |= SUNXI_PCC_PIPE_CLK_OPEN;
> +	writel(val, phy->regs + SUNXI_PIPE_CLOCK_CONTROL);
> +
> +	val = readl(phy->regs + SUNXI_ISCR);
> +	val |= SUNXI_ISCR_FORCE_VBUS;
> +	writel(val, phy->regs + SUNXI_ISCR);
> +
> +	/*
> +	 * All the magic numbers written to the PHY_TUNE_{LOW_HIGH}
> +	 * registers are directly taken from the BSP USB3 driver from
> +	 * Allwiner.
> +	 */
> +	writel(0x0047fc87, phy->regs + SUNXI_PHY_TUNE_LOW);
> +
> +	val = readl(phy->regs + SUNXI_PHY_TUNE_HIGH);
> +	val &= ~(SUNXI_TXVBOOSTLVL_MASK | SUNXI_LOS_BIAS_MASK |
> +		 SUNXI_TX_SWING_FULL_MASK | SUNXI_TX_DEEMPH_6GB_MASK |
> +		 SUNXI_TX_DEEMPH_3P5DB_MASK);
> +	val |= SUNXI_TXVBOOSTLVL(0x7);
> +	val |= SUNXI_LOS_BIAS(0x7);
> +	val |= SUNXI_TX_SWING_FULL(0x55);
> +	val |= SUNXI_TX_DEEMPH_6DB(0x20);
> +	val |= SUNXI_TX_DEEMPH_3P5DB(0x15);
> +	writel(val, phy->regs + SUNXI_PHY_TUNE_HIGH);
> +}
> +
> +static int sun50i_usb3_phy_init(struct phy *_phy)
> +{
> +	struct sun50i_usb3_phy *phy = phy_get_drvdata(_phy);
> +	int ret;
> +
> +	ret = clk_prepare_enable(phy->clk);
> +	if (ret)
> +		goto err_clk;
> +
> +	ret = reset_control_deassert(phy->reset);
> +	if (ret)
> +		goto err_reset;
> +
> +	sun50i_usb3_phy_open(phy);
> +	return 0;
> +
> +err_reset:
> +	clk_disable_unprepare(phy->clk);
> +
> +err_clk:
> +	return ret;
> +}
> +
> +static int sun50i_usb3_phy_exit(struct phy *_phy)
> +{
> +	struct sun50i_usb3_phy *phy = phy_get_drvdata(_phy);
> +
> +	reset_control_assert(phy->reset);
> +	clk_disable_unprepare(phy->clk);
> +
> +	return 0;
> +}
> +
> +static int sun50i_usb3_phy_power_on(struct phy *_phy)
> +{
> +	struct sun50i_usb3_phy *phy = phy_get_drvdata(_phy);
> +
> +	if (phy->vbus)
> +		return regulator_enable(phy->vbus);
> +	else
> +		return 0;
> +}
> +
> +static int sun50i_usb3_phy_power_off(struct phy *_phy)
> +{
> +	struct sun50i_usb3_phy *phy = phy_get_drvdata(_phy);
> +
> +	if (phy->vbus)
> +		return regulator_disable(phy->vbus);
> +	else
> +		return 0;
> +}
> +
> +static const struct phy_ops sun50i_usb3_phy_ops = {
> +	.init		= sun50i_usb3_phy_init,
> +	.exit		= sun50i_usb3_phy_exit,
> +	.power_on	= sun50i_usb3_phy_power_on,
> +	.power_off	= sun50i_usb3_phy_power_off,
> +	.owner		= THIS_MODULE,
> +};
> +
> +static int sun50i_usb3_phy_probe(struct platform_device *pdev)
> +{
> +	struct sun50i_usb3_phy *phy;
> +	struct device *dev = &pdev->dev;
> +	struct phy_provider *phy_provider;
> +	struct resource *res;
> +	struct device_node *connector_node;
> +	int ret;
> +
> +	phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
> +	if (!phy)
> +		return -ENOMEM;
> +
> +	dev_set_drvdata(dev, phy);
> +
> +	phy->clk = devm_clk_get(dev, NULL);
> +	if (IS_ERR(phy->clk)) {
> +		dev_err(dev, "failed to get phy clock\n");
> +		return PTR_ERR(phy->clk);
> +	}
> +
> +	phy->reset = devm_reset_control_get(dev, NULL);
> +	if (IS_ERR(phy->reset)) {
> +		dev_err(dev, "failed to get reset control\n");
> +		return PTR_ERR(phy->reset);
> +	}
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	phy->regs = devm_ioremap_resource(dev, res);
> +	if (IS_ERR(phy->regs))
> +		return PTR_ERR(phy->regs);
> +
> +	/* Populate the connector as platform device */
> +	ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
> +	if (ret)
> +		return ret;
> +
> +	/*
> +	 * Currently the Allwinner USB3 PHY contains only one port, so we
> +	 * only process one connector now.
> +	 */
> +	connector_node = of_get_next_child(pdev->dev.of_node, NULL);
> +
> +	if (connector_node) {
> +		/* Get the platform device */
> +		phy->connector_dev = of_find_device_by_node(connector_node);

Also of_find_device_by_node takes a reference that needs to be put back in
sun50i_usb3_phy_remove() and error paths. So many refs to take care of,
everywhere. Hmm. :)

I'm just noticing all this now, because I'm writing similar code for
HDMI/connector regualtor borrowing from HDMI controller via of_graph.

regards,
	o.

> +		if (!phy->connector_dev) {
> +			dev_err(dev, "no device for connector\n");
> +			return -ENODEV;
> +		}
> +
> +		phy->vbus = regulator_get(&phy->connector_dev->dev, "vbus");
> +		if (IS_ERR(phy->vbus))
> +			return PTR_ERR(phy->vbus);
> +	}
> +
> +	phy->phy = devm_phy_create(dev, NULL, &sun50i_usb3_phy_ops);
> +	if (IS_ERR(phy->phy)) {
> +		dev_err(dev, "failed to create PHY\n");
> +		return PTR_ERR(phy->phy);
> +	}
> +
> +	phy_set_drvdata(phy->phy, phy);
> +	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
> +
> +	return PTR_ERR_OR_ZERO(phy_provider);
> +}
> +
> +static int sun50i_usb3_phy_remove(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct sun50i_usb3_phy *phy = dev_get_drvdata(dev);
> +
> +	if (phy->vbus)
> +		regulator_put(phy->vbus);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id sun50i_usb3_phy_of_match[] = {
> +	{ .compatible = "allwinner,sun50i-h6-usb3-phy" },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, sun50i_usb3_phy_of_match);
> +
> +static struct platform_driver sun50i_usb3_phy_driver = {
> +	.probe	= sun50i_usb3_phy_probe,
> +	.remove	= sun50i_usb3_phy_remove,
> +	.driver = {
> +		.of_match_table	= sun50i_usb3_phy_of_match,
> +		.name  = "sun50i-usb3-phy",
> +	}
> +};
> +module_platform_driver(sun50i_usb3_phy_driver);
> +
> +MODULE_DESCRIPTION("Allwinner sun50i USB 3.0 phy driver");
> +MODULE_AUTHOR("Icenowy Zheng <icenowy@aosc.io>");
> +MODULE_LICENSE("GPL");
> -- 
> 2.18.1
> 
> -- 
> You received this message because you are subscribed to the Google Groups "linux-sunxi" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to linux-sunxi+unsubscribe@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

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

end of thread, other threads:[~2019-04-11  0:20 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-05 20:57 [PATCH v5 0/5] Allwinner H6 USB3 support Icenowy Zheng
2019-04-05 20:57 ` [PATCH v5 1/5] dt-bindings: usb-connector: add Vbus regulator for Type-A/B Icenowy Zheng
2019-04-06  7:10   ` Rob Herring
2019-04-05 20:57 ` [PATCH v5 2/5] dt-bindings: phy: add binding for Allwinner USB3 PHY Icenowy Zheng
2019-04-06  7:14   ` Rob Herring
2019-04-06  7:24     ` Icenowy Zheng
2019-04-09  1:09       ` Rob Herring
2019-04-08  7:14   ` Maxime Ripard
2019-04-05 20:57 ` [PATCH v5 3/5] phy: allwinner: add phy driver for USB3 PHY on Allwinner H6 SoC Icenowy Zheng
2019-04-06 17:21   ` [linux-sunxi] " Ondřej Jirman
2019-04-06 17:24     ` Icenowy Zheng
2019-04-09 16:34   ` Clément Péron
2019-04-11  0:15   ` Ondřej Jirman
2019-04-11  0:20   ` Ondřej Jirman
2019-04-05 20:57 ` [PATCH v5 4/5] arm64: allwinner: dts: h6: add USB3 device nodes Icenowy Zheng
2019-04-05 20:57 ` [PATCH v5 5/5] arm64: allwinner: dts: h6: enable USB3 port on Pine H64 Icenowy Zheng

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).