linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/10] Add support for usb on Hikey960
@ 2018-10-27  9:58 Yu Chen
  2018-10-27  9:58 ` [PATCH 01/10] dt-bindings: usb: add support for dwc3 controller on HiSilicon SoCs Yu Chen
                   ` (9 more replies)
  0 siblings, 10 replies; 23+ messages in thread
From: Yu Chen @ 2018-10-27  9:58 UTC (permalink / raw)
  To: linux-usb, devicetree, linux-kernel; +Cc: suzhuangluan, kongfei, Yu Chen

The patchset adds support for usb functionality of Hikey960, includes:
- dwc3 driver for Hisilicon Kirin Soc hi3660
- usb driver for HiKey960 board
- some adjustment in dwc3, usb gadget and typec driver
- dts for support usb of HiKey960

Yu Chen (10):
  dt-bindings: usb: add support for dwc3 controller on HiSilicon SoCs
  dt-bindings: phy: Add support for HiSilicon's hi3660 USB PHY
  dt-bindings: misc: Add bindings for HiSilicon usb hub and data role
    switch functionality on HiKey960
  usb: dwc3: dwc3-hisi: Add code for dwc3 of Hisilicon Soc Platform
  usb: dwc3: Add two quirks for Hisilicon Kirin Soc Platform
  phy: Add usb phy support for hi3660 Soc of Hisilicon
  hikey960: Support usb functionality of Hikey960
  usb: typec: Add support for usb role switch in rt1711h driver
  usb: gadget: Add configfs attribuite for controling
    match_existing_only
  dts: hi3660: Add support for usb on Hikey960

 .../bindings/misc/hisilicon-hikey-usb.txt          |  24 ++
 .../devicetree/bindings/phy/phy-hi3660-usb3.txt    |  21 ++
 .../devicetree/bindings/usb/dwc3-hisi.txt          |  53 ++++
 MAINTAINERS                                        |  10 +
 arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts  |  35 +++
 arch/arm64/boot/dts/hisilicon/hi3660.dtsi          |  52 ++++
 drivers/misc/Kconfig                               |   7 +
 drivers/misc/Makefile                              |   1 +
 drivers/misc/hisi_hikey_usb.c                      | 319 ++++++++++++++++++++
 drivers/phy/hisilicon/Kconfig                      |  10 +
 drivers/phy/hisilicon/Makefile                     |   1 +
 drivers/phy/hisilicon/phy-hi3660-usb3.c            | 254 ++++++++++++++++
 drivers/usb/dwc3/Kconfig                           |   8 +
 drivers/usb/dwc3/Makefile                          |   1 +
 drivers/usb/dwc3/core.c                            |  43 +++
 drivers/usb/dwc3/core.h                            |   7 +
 drivers/usb/dwc3/dwc3-hisi.c                       | 335 +++++++++++++++++++++
 drivers/usb/dwc3/gadget.c                          |   2 +-
 drivers/usb/gadget/configfs.c                      |  32 ++
 drivers/usb/typec/tcpm/tcpci_rt1711h.c             |  15 +
 20 files changed, 1229 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/misc/hisilicon-hikey-usb.txt
 create mode 100644 Documentation/devicetree/bindings/phy/phy-hi3660-usb3.txt
 create mode 100644 Documentation/devicetree/bindings/usb/dwc3-hisi.txt
 create mode 100644 drivers/misc/hisi_hikey_usb.c
 create mode 100644 drivers/phy/hisilicon/phy-hi3660-usb3.c
 create mode 100644 drivers/usb/dwc3/dwc3-hisi.c

-- 
2.15.0-rc2


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

* [PATCH 01/10] dt-bindings: usb: add support for dwc3 controller on HiSilicon SoCs
  2018-10-27  9:58 [PATCH 00/10] Add support for usb on Hikey960 Yu Chen
@ 2018-10-27  9:58 ` Yu Chen
       [not found]   ` <20181112160241.GA14074@bogus>
  2018-10-27  9:58 ` [PATCH 02/10] dt-bindings: phy: Add support for HiSilicon's hi3660 USB PHY Yu Chen
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 23+ messages in thread
From: Yu Chen @ 2018-10-27  9:58 UTC (permalink / raw)
  To: linux-usb, devicetree, linux-kernel
  Cc: suzhuangluan, kongfei, Yu Chen, Greg Kroah-Hartman, Rob Herring,
	Mark Rutland, John Stultz

This patch adds binding descriptions to support the dwc3 controller
on HiSilicon SoCs and boards like the HiKey960.

Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: John Stultz <john.stultz@linaro.org>
Signed-off-by: Yu Chen <chenyu56@huawei.com>
---
 .../devicetree/bindings/usb/dwc3-hisi.txt          | 53 ++++++++++++++++++++++
 1 file changed, 53 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/dwc3-hisi.txt

diff --git a/Documentation/devicetree/bindings/usb/dwc3-hisi.txt b/Documentation/devicetree/bindings/usb/dwc3-hisi.txt
new file mode 100644
index 000000000000..e715e7b1c324
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/dwc3-hisi.txt
@@ -0,0 +1,53 @@
+HiSilicon DWC3 USB SoC controller
+
+This file documents the parameters for the dwc3-hisi driver.
+
+Required properties:
+- compatible:	should be "hisilicon,hi3660-dwc3"
+- clocks:	A list of phandle + clock-specifier pairs for the
+		clocks listed in clock-names
+- clock-names:	Specify clock names
+- resets:	list of phandle and reset specifier pairs.
+
+Sub-nodes:
+The dwc3 core should be added as subnode to HiSilicon DWC3 as shown in the
+example below. The DT binding details of dwc3 can be found in:
+Documentation/devicetree/bindings/usb/dwc3.txt
+
+Example:
+	usb3: hisi_dwc3 {
+		compatible = "hisilicon,hi3660-dwc3";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		clocks = <&crg_ctrl HI3660_CLK_ABB_USB>,
+			 <&crg_ctrl HI3660_ACLK_GATE_USB3OTG>;
+		clock-names = "clk_usb3phy_ref", "aclk_usb3otg";
+		assigned-clocks = <&crg_ctrl HI3660_ACLK_GATE_USB3OTG>;
+		assigned-clock-rates = <229000000>;
+		resets = <&crg_rst 0x90 8>,
+			 <&crg_rst 0x90 7>,
+			 <&crg_rst 0x90 6>,
+			 <&crg_rst 0x90 5>;
+
+		dwc3: dwc3@ff100000 {
+			compatible = "snps,dwc3";
+			reg = <0x0 0xff100000 0x0 0x100000>;
+			interrupts = <0 159 4>, <0 161 4>;
+			phys = <&usb_phy>;
+			phy-names = "usb3-phy";
+			dr_mode = "otg";
+			maximum-speed = "super-speed";
+			phy_type = "utmi";
+			snps,dis-del-phy-power-chg-quirk;
+			snps,lfps_filter_quirk;
+			snps,dis_u2_susphy_quirk;
+			snps,dis_u3_susphy_quirk;
+			snps,tx_de_emphasis_quirk;
+			snps,tx_de_emphasis = <1>;
+			snps,dis_enblslpm_quirk;
+			snps,gctl-reset-quirk;
+			extcon = <&hisi_hikey_usb>;
+		};
+	};
-- 
2.15.0-rc2


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

* [PATCH 02/10] dt-bindings: phy: Add support for HiSilicon's hi3660 USB PHY
  2018-10-27  9:58 [PATCH 00/10] Add support for usb on Hikey960 Yu Chen
  2018-10-27  9:58 ` [PATCH 01/10] dt-bindings: usb: add support for dwc3 controller on HiSilicon SoCs Yu Chen
@ 2018-10-27  9:58 ` Yu Chen
  2018-10-27  9:58 ` [PATCH 03/10] dt-bindings: misc: Add bindings for HiSilicon usb hub and data role switch functionality on HiKey960 Yu Chen
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 23+ messages in thread
From: Yu Chen @ 2018-10-27  9:58 UTC (permalink / raw)
  To: linux-usb, devicetree, linux-kernel
  Cc: suzhuangluan, kongfei, Yu Chen, Rob Herring, Mark Rutland,
	John Stultz, Binghui Wang

This patch adds binding documentation for supporting the hi3660 usb
phy on boards like the HiKey960.

Cc: Rob Herring <robh+dt@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Binghui Wang <wangbinghui@hisilicon.com>
Signed-off-by: Yu Chen <chenyu56@huawei.com>
---
 .../devicetree/bindings/phy/phy-hi3660-usb3.txt     | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/phy-hi3660-usb3.txt

diff --git a/Documentation/devicetree/bindings/phy/phy-hi3660-usb3.txt b/Documentation/devicetree/bindings/phy/phy-hi3660-usb3.txt
new file mode 100644
index 000000000000..26cab738ac7b
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/phy-hi3660-usb3.txt
@@ -0,0 +1,21 @@
+Hisilicon hi3660 usb PHY
+-----------------------
+
+Required properties:
+- compatible: should be "hisilicon,hi3660-usb-phy"
+- #phy-cells: must be 0
+- hisilicon,pericrg-syscon: phandle of syscon used to control phy.
+- hisilicon,pctrl-syscon: phandle of syscon used to control phy.
+- hisilicon,usb3-otg-bc-syscon: phandle of syscon used to control phy.
+- eye-diagram-param: parameter set for phy
+Refer to phy/phy-bindings.txt for the generic PHY binding properties
+
+Example:
+	usb_phy: usbphy {
+		compatible = "hisilicon,hi3660-usb-phy";
+		#phy-cells = <0>;
+		hisilicon,pericrg-syscon = <&crg_ctrl>;
+		hisilicon,pctrl-syscon = <&pctrl>;
+		hisilicon,usb3-otg-bc-syscon = <&usb3_otg_bc>;
+		eye-diagram-param = <0x22466e4>;
+	};
-- 
2.15.0-rc2


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

* [PATCH 03/10] dt-bindings: misc: Add bindings for HiSilicon usb hub and data role switch functionality on HiKey960
  2018-10-27  9:58 [PATCH 00/10] Add support for usb on Hikey960 Yu Chen
  2018-10-27  9:58 ` [PATCH 01/10] dt-bindings: usb: add support for dwc3 controller on HiSilicon SoCs Yu Chen
  2018-10-27  9:58 ` [PATCH 02/10] dt-bindings: phy: Add support for HiSilicon's hi3660 USB PHY Yu Chen
@ 2018-10-27  9:58 ` Yu Chen
  2018-10-27 18:06   ` Sergei Shtylyov
  2018-10-27  9:58 ` [PATCH 04/10] usb: dwc3: dwc3-hisi: Add code for dwc3 of Hisilicon Soc Platform Yu Chen
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 23+ messages in thread
From: Yu Chen @ 2018-10-27  9:58 UTC (permalink / raw)
  To: linux-usb, devicetree, linux-kernel
  Cc: suzhuangluan, kongfei, Yu Chen, Rob Herring, Mark Rutland,
	John Stultz, Binghui Wang

This patch adds binding documentation to support usb hub and usb
data role switch of Hisilicon HiKey&HiKey960 Board.

Cc: Rob Herring <robh+dt@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Binghui Wang <wangbinghui@hisilicon.com>
Signed-off-by: Yu Chen <chenyu56@huawei.com>
---
 .../bindings/misc/hisilicon-hikey-usb.txt          | 24 ++++++++++++++++++++++
 1 file changed, 24 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/misc/hisilicon-hikey-usb.txt

diff --git a/Documentation/devicetree/bindings/misc/hisilicon-hikey-usb.txt b/Documentation/devicetree/bindings/misc/hisilicon-hikey-usb.txt
new file mode 100644
index 000000000000..f94e990362c9
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/hisilicon-hikey-usb.txt
@@ -0,0 +1,24 @@
+Support usb hub and usb data role switch of Hisilicon HiKey&HiKey960 Board.
+
+-----------------------------
+
+Required properties:
+- compatible: "hisilicon,gpio_hubv1","hisilicon,hikey960_usb"
+- typc_vbus_int_gpio,typec-gpios: gpio to control the vbus of typeC port
+- typc_vbus_enable_val: gpio value that enable the vbus of typeC port
+- otg_gpio: gpio to switch DP&DM between the hub and typeC port
+- hub_vdd33_en_gpio: gpio to enable the power of hub
+- pinctrl-0: pinctrl config
+
+Example
+-----
+
+	hisi_hikey_usb: hisi_hikey_usb {
+		compatible = "hisilicon,hikey960_usb";
+		typc_vbus_int_gpio,typec-gpios = <&gpio25 2 0>;
+		typc_vbus_enable_val = <1>;
+		otg_gpio = <&gpio25 6 0>;
+		hub_vdd33_en_gpio = <&gpio5 6 0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&usbhub5734_pmx_func>;
+	};
-- 
2.15.0-rc2


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

* [PATCH 04/10] usb: dwc3: dwc3-hisi: Add code for dwc3 of Hisilicon Soc Platform
  2018-10-27  9:58 [PATCH 00/10] Add support for usb on Hikey960 Yu Chen
                   ` (2 preceding siblings ...)
  2018-10-27  9:58 ` [PATCH 03/10] dt-bindings: misc: Add bindings for HiSilicon usb hub and data role switch functionality on HiKey960 Yu Chen
@ 2018-10-27  9:58 ` Yu Chen
  2018-10-27  9:58 ` [PATCH 05/10] usb: dwc3: Add two quirks for Hisilicon Kirin " Yu Chen
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 23+ messages in thread
From: Yu Chen @ 2018-10-27  9:58 UTC (permalink / raw)
  To: linux-usb, devicetree, linux-kernel
  Cc: suzhuangluan, kongfei, Yu Chen, Felipe Balbi, Greg Kroah-Hartman,
	David S. Miller, Mauro Carvalho Chehab, Andrew Morton,
	Arnd Bergmann, John Stultz, Binghui Wang

This driver handles the poweron and shutdown of dwc3 core
on Hisilicon Soc Platform.

Cc: Felipe Balbi <balbi@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Binghui Wang <wangbinghui@hisilicon.com>
Signed-off-by: Yu Chen <chenyu56@huawei.com>
---
 MAINTAINERS                  |   8 ++
 drivers/usb/dwc3/Kconfig     |   8 ++
 drivers/usb/dwc3/Makefile    |   1 +
 drivers/usb/dwc3/dwc3-hisi.c | 335 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 352 insertions(+)
 create mode 100644 drivers/usb/dwc3/dwc3-hisi.c

diff --git a/MAINTAINERS b/MAINTAINERS
index fdb6a298c7e7..e485449f7811 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15288,6 +15288,14 @@ L:	linux-usb@vger.kernel.org
 S:	Maintained
 F:	drivers/usb/roles/intel-xhci-usb-role-switch.c
 
+USB IP DRIVER FOR HISILICON KIRIN
+M:	Yu Chen <chenyu56@huawei.com>
+M:	Binghui Wang <wangbinghui@hisilicon.com>
+L:	linux-usb@vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/usb/dwc3-hisi.txt
+F:	drivers/usb/dwc3/dwc3-hisi.c
+
 USB ISP116X DRIVER
 M:	Olav Kongas <ok@artecdesign.ee>
 L:	linux-usb@vger.kernel.org
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index 1a0404fda596..09d105a2b53a 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -123,4 +123,12 @@ config USB_DWC3_QCOM
 	  for peripheral mode support.
 	  Say 'Y' or 'M' if you have one such device.
 
+config USB_DWC3_HISI
+	tristate "HiSilicon Kirin Platforms"
+	depends on ((ARCH_HISI && ARM64) || COMPILE_TEST) && OF
+	default USB_DWC3
+	help
+	  Support USB2/3 functionality in HiSilicon Kirin platforms.
+	  Say 'Y' or 'M' if you have one such device.
+
 endif
diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile
index 6e3ef6144e5d..15781455e3f0 100644
--- a/drivers/usb/dwc3/Makefile
+++ b/drivers/usb/dwc3/Makefile
@@ -50,3 +50,4 @@ obj-$(CONFIG_USB_DWC3_KEYSTONE)		+= dwc3-keystone.o
 obj-$(CONFIG_USB_DWC3_OF_SIMPLE)	+= dwc3-of-simple.o
 obj-$(CONFIG_USB_DWC3_ST)		+= dwc3-st.o
 obj-$(CONFIG_USB_DWC3_QCOM)		+= dwc3-qcom.o
+obj-$(CONFIG_USB_DWC3_HISI)		+= dwc3-hisi.o
diff --git a/drivers/usb/dwc3/dwc3-hisi.c b/drivers/usb/dwc3/dwc3-hisi.c
new file mode 100644
index 000000000000..6e9787d420a7
--- /dev/null
+++ b/drivers/usb/dwc3/dwc3-hisi.c
@@ -0,0 +1,335 @@
+// SPDX-License-Identifier: GPL-2.0+
+/**
+ * dwc3-hisi.c - Support for dwc3 platform devices on HiSilicon platforms
+ *
+ * Copyright (C) 2017-2018 Hilisicon Electronics Co., Ltd.
+ *		http://www.huawei.com
+ *
+ * Authors: Yu Chen <chenyu56@huawei.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/pm_runtime.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include <linux/extcon.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pinctrl/consumer.h>
+
+struct dwc3_hisi {
+	struct device		*dev;
+	struct clk		**clks;
+	int			num_clocks;
+	struct reset_control	**rstcs;
+	int			num_rstcs;
+};
+
+struct dwc3_hisi *g_dwc3_hisi;
+
+static int dwc3_hisi_init_clks(struct dwc3_hisi *dwc3_hisi,
+		struct device_node *np)
+{
+	struct device *dev = dwc3_hisi->dev;
+	int i;
+
+	dwc3_hisi->num_clocks = of_clk_get_parent_count(np);
+	if (!dwc3_hisi->num_clocks)
+		return -ENOENT;
+
+	dwc3_hisi->clks = devm_kcalloc(dev, dwc3_hisi->num_clocks,
+			sizeof(struct clk *), GFP_KERNEL);
+	if (!dwc3_hisi->clks)
+		return -ENOMEM;
+
+	for (i = 0; i < dwc3_hisi->num_clocks; i++) {
+		struct clk	*clk;
+
+		clk = of_clk_get(np, i);
+		if (IS_ERR(clk)) {
+			while (--i >= 0)
+				clk_put(dwc3_hisi->clks[i]);
+
+			return PTR_ERR(clk);
+		}
+
+		dwc3_hisi->clks[i] = clk;
+	}
+
+	return 0;
+}
+
+static int dwc3_hisi_enable_clks(struct dwc3_hisi *dwc3_hisi)
+{
+	int i;
+	int ret;
+
+	for (i = 0; i < dwc3_hisi->num_clocks; i++) {
+		ret = clk_prepare_enable(dwc3_hisi->clks[i]);
+		if (ret < 0) {
+			while (--i >= 0)
+				clk_disable_unprepare(dwc3_hisi->clks[i]);
+
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static void dwc3_hisi_disable_clks(struct dwc3_hisi *dwc3_hisi)
+{
+	int i;
+
+	for (i = 0; i < dwc3_hisi->num_clocks; i++)
+		clk_disable_unprepare(dwc3_hisi->clks[i]);
+}
+
+static int dwc3_hisi_get_rstcs(struct dwc3_hisi *dwc3_hisi,
+		struct device_node *np)
+{
+	struct device *dev = dwc3_hisi->dev;
+	int i;
+
+	dwc3_hisi->num_rstcs = of_count_phandle_with_args(np,
+			"resets", "#reset-cells");
+	if (!dwc3_hisi->num_rstcs)
+		return -ENOENT;
+
+	dwc3_hisi->rstcs = devm_kcalloc(dev, dwc3_hisi->num_rstcs,
+			sizeof(struct reset_control *), GFP_KERNEL);
+	if (!dwc3_hisi->rstcs)
+		return -ENOMEM;
+
+	for (i = 0; i < dwc3_hisi->num_rstcs; i++) {
+		struct reset_control *rstc;
+
+		rstc = of_reset_control_get_shared_by_index(np, i);
+		if (IS_ERR(rstc)) {
+			while (--i >= 0)
+				reset_control_put(dwc3_hisi->rstcs[i]);
+			return PTR_ERR(rstc);
+		}
+
+		dwc3_hisi->rstcs[i] = rstc;
+	}
+
+	return 0;
+}
+
+static int dwc3_hisi_reset_control_assert(struct dwc3_hisi *dwc3_hisi)
+{
+	int i, ret;
+
+	for (i = dwc3_hisi->num_rstcs - 1; i >= 0 ; i--) {
+		ret = reset_control_assert(dwc3_hisi->rstcs[i]);
+		if (ret) {
+			while (--i >= 0)
+				reset_control_deassert(dwc3_hisi->rstcs[i]);
+			return ret;
+		}
+		udelay(10);
+	}
+
+	return 0;
+}
+
+static int dwc3_hisi_reset_control_deassert(struct dwc3_hisi *dwc3_hisi)
+{
+	int i, ret;
+
+	for (i = 0; i < dwc3_hisi->num_rstcs; i++) {
+		ret = reset_control_deassert(dwc3_hisi->rstcs[i]);
+		if (ret) {
+			while (--i >= 0)
+				reset_control_assert(dwc3_hisi->rstcs[i]);
+			return ret;
+		}
+		udelay(10);
+	}
+
+	return 0;
+}
+
+static int dwc3_hisi_probe(struct platform_device *pdev)
+{
+	struct dwc3_hisi	*dwc3_hisi;
+	struct device		*dev = &pdev->dev;
+	struct device_node	*np = dev->of_node;
+
+	int			ret;
+	int			i;
+
+	dwc3_hisi = devm_kzalloc(dev, sizeof(*dwc3_hisi), GFP_KERNEL);
+	if (!dwc3_hisi)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, dwc3_hisi);
+	dwc3_hisi->dev = dev;
+
+	ret = dwc3_hisi_init_clks(dwc3_hisi, np);
+	if (ret) {
+		dev_err(dev, "could not get clocks\n");
+		return ret;
+	}
+
+	ret = dwc3_hisi_enable_clks(dwc3_hisi);
+	if (ret) {
+		dev_err(dev, "could not enable clocks\n");
+		goto err_put_clks;
+	}
+
+	ret = dwc3_hisi_get_rstcs(dwc3_hisi, np);
+	if (ret) {
+		dev_err(dev, "could not get reset controllers\n");
+		goto err_disable_clks;
+	}
+	ret = dwc3_hisi_reset_control_deassert(dwc3_hisi);
+	if (ret) {
+		dev_err(dev, "reset control deassert failed\n");
+		goto err_put_rstcs;
+	}
+
+	pm_runtime_set_active(dev);
+	pm_runtime_enable(dev);
+	pm_runtime_get_sync(dev);
+
+	ret = of_platform_populate(np, NULL, NULL, dev);
+	if (ret) {
+		dev_err(dev, "failed to add dwc3 core\n");
+		goto err_reset_assert;
+	}
+
+	dev_err(dev, "finish dwc3 hisi probe\n");
+
+	g_dwc3_hisi = dwc3_hisi;
+	return 0;
+
+err_reset_assert:
+	ret = dwc3_hisi_reset_control_assert(dwc3_hisi);
+	if (ret)
+		dev_err(dev, "reset control assert failed\n");
+err_put_rstcs:
+	for (i = 0; i < dwc3_hisi->num_rstcs; i++)
+		reset_control_put(dwc3_hisi->rstcs[i]);
+err_disable_clks:
+	dwc3_hisi_disable_clks(dwc3_hisi);
+err_put_clks:
+	for (i = 0; i < dwc3_hisi->num_clocks; i++)
+		clk_put(dwc3_hisi->clks[i]);
+
+	return ret;
+}
+
+static int dwc3_hisi_remove(struct platform_device *pdev)
+{
+	struct dwc3_hisi	*dwc3_hisi = platform_get_drvdata(pdev);
+	struct device		*dev = &pdev->dev;
+	int			i, ret;
+
+	of_platform_depopulate(dev);
+
+	ret = dwc3_hisi_reset_control_assert(dwc3_hisi);
+	if (ret) {
+		dev_err(dev, "reset control assert failed\n");
+		return ret;
+	}
+
+	for (i = 0; i < dwc3_hisi->num_clocks; i++) {
+		clk_disable_unprepare(dwc3_hisi->clks[i]);
+		clk_put(dwc3_hisi->clks[i]);
+	}
+
+	pm_runtime_put_sync(dev);
+	pm_runtime_disable(dev);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int dwc3_hisi_suspend(struct device *dev)
+{
+	struct dwc3_hisi *dwc3_hisi = dev_get_drvdata(dev);
+	int ret;
+
+	dev_info(dev, "%s\n", __func__);
+
+	ret = dwc3_hisi_reset_control_assert(dwc3_hisi);
+	if (ret) {
+		dev_err(dev, "reset control assert failed\n");
+		return ret;
+	}
+
+	dwc3_hisi_disable_clks(dwc3_hisi);
+
+	pinctrl_pm_select_default_state(dev);
+
+	return 0;
+}
+
+static int dwc3_hisi_resume(struct device *dev)
+{
+	struct dwc3_hisi *dwc3_hisi = dev_get_drvdata(dev);
+	int ret;
+
+	dev_info(dev, "%s\n", __func__);
+	pinctrl_pm_select_default_state(dev);
+
+	ret = dwc3_hisi_enable_clks(dwc3_hisi);
+	if (ret) {
+		dev_err(dev, "could not enable clocks\n");
+		return ret;
+	}
+
+	ret = dwc3_hisi_reset_control_deassert(dwc3_hisi);
+	if (ret) {
+		dev_err(dev, "reset control deassert failed\n");
+		return ret;
+	}
+
+	/* Wait for clock stable */
+	msleep(100);
+
+	return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static SIMPLE_DEV_PM_OPS(dwc3_hisi_dev_pm_ops,
+		dwc3_hisi_suspend, dwc3_hisi_resume);
+
+static const struct of_device_id dwc3_hisi_match[] = {
+	{ .compatible = "hisilicon,hi3660-dwc3" },
+	{ /* sentinel */ },
+};
+
+MODULE_DEVICE_TABLE(of, dwc3_hisi_match);
+
+static struct platform_driver dwc3_hisi_driver = {
+	.probe = dwc3_hisi_probe,
+	.remove = dwc3_hisi_remove,
+	.driver = {
+		.name = "usb-hisi-dwc3",
+		.of_match_table = dwc3_hisi_match,
+		.pm = &dwc3_hisi_dev_pm_ops,
+	},
+};
+
+module_platform_driver(dwc3_hisi_driver);
+
+MODULE_AUTHOR("Yu Chen <chenyu56@huawei.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("DesignWare USB3 HiSilicon Glue Layer");
-- 
2.15.0-rc2


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

* [PATCH 05/10] usb: dwc3: Add two quirks for Hisilicon Kirin Soc Platform
  2018-10-27  9:58 [PATCH 00/10] Add support for usb on Hikey960 Yu Chen
                   ` (3 preceding siblings ...)
  2018-10-27  9:58 ` [PATCH 04/10] usb: dwc3: dwc3-hisi: Add code for dwc3 of Hisilicon Soc Platform Yu Chen
@ 2018-10-27  9:58 ` Yu Chen
  2018-10-27  9:58 ` [PATCH 06/10] phy: Add usb phy support for hi3660 Soc of Hisilicon Yu Chen
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 23+ messages in thread
From: Yu Chen @ 2018-10-27  9:58 UTC (permalink / raw)
  To: linux-usb, devicetree, linux-kernel
  Cc: suzhuangluan, kongfei, Yu Chen, Felipe Balbi, Greg Kroah-Hartman,
	John Stultz, Binghui Wang

There are tow quirks for DesignWare USB3 DRD Core of Hisilicon Kirin Soc.
1)SPLIT_BOUNDARY_DISABLE should be set for Host mode
2)A GCTL soft reset should be executed when switch mode

Cc: Felipe Balbi <balbi@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Binghui Wang <wangbinghui@hisilicon.com>
Signed-off-by: Yu Chen <chenyu56@huawei.com>
---
 drivers/usb/dwc3/core.c   | 43 +++++++++++++++++++++++++++++++++++++++++++
 drivers/usb/dwc3/core.h   |  7 +++++++
 drivers/usb/dwc3/gadget.c |  2 +-
 3 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index becfbb87f791..68c29e549bfb 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -111,11 +111,25 @@ void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode)
 	dwc->current_dr_role = mode;
 }
 
+static void dwc3_gctl_core_soft_reset(struct dwc3 *dwc)
+{
+	int reg;
+
+	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
+	reg |= (DWC3_GCTL_CORESOFTRESET);
+	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
+
+	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
+	reg &= ~(DWC3_GCTL_CORESOFTRESET);
+	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
+}
+
 static void __dwc3_set_mode(struct work_struct *work)
 {
 	struct dwc3 *dwc = work_to_dwc(work);
 	unsigned long flags;
 	int ret;
+	int reg;
 
 	if (dwc->dr_mode != USB_DR_MODE_OTG)
 		return;
@@ -168,9 +182,18 @@ static void __dwc3_set_mode(struct work_struct *work)
 			phy_set_mode(dwc->usb2_generic_phy, PHY_MODE_USB_HOST);
 			phy_set_mode(dwc->usb3_generic_phy, PHY_MODE_USB_HOST);
 			phy_calibrate(dwc->usb2_generic_phy);
+			if (dwc->dis_split_quirk) {
+				reg = dwc3_readl(dwc->regs, DWC3_GUCTL3);
+				reg |= DWC3_GUCTL3_SPLITDISABLE;
+				dwc3_writel(dwc->regs, DWC3_GUCTL3, reg);
+			}
 		}
 		break;
 	case DWC3_GCTL_PRTCAP_DEVICE:
+		/* Execute a GCTL Core Soft Reset when switch mode */
+		if (dwc->gctl_reset_quirk)
+			dwc3_gctl_core_soft_reset(dwc);
+
 		dwc3_event_buffers_setup(dwc);
 
 		if (dwc->usb2_phy)
@@ -1298,6 +1321,11 @@ static void dwc3_get_properties(struct dwc3 *dwc)
 	dwc->dis_metastability_quirk = device_property_read_bool(dev,
 				"snps,dis_metastability_quirk");
 
+	dwc->dis_split_quirk = device_property_read_bool(dev,
+				"snps,dis-split-quirk");
+	dwc->gctl_reset_quirk = device_property_read_bool(dev,
+				"snps,gctl-reset-quirk");
+
 	dwc->lpm_nyet_threshold = lpm_nyet_threshold;
 	dwc->tx_de_emphasis = tx_de_emphasis;
 
@@ -1815,10 +1843,25 @@ static int dwc3_resume(struct device *dev)
 
 	return 0;
 }
+
+static void dwc3_complete(struct device *dev)
+{
+	struct dwc3	*dwc = dev_get_drvdata(dev);
+	u32		reg;
+
+	if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST &&
+			dwc->dis_split_quirk) {
+		dev_dbg(dwc->dev, "set DWC3_GUCTL3_SPLITDISABLE\n");
+		reg = dwc3_readl(dwc->regs, DWC3_GUCTL3);
+		reg |= DWC3_GUCTL3_SPLITDISABLE;
+		dwc3_writel(dwc->regs, DWC3_GUCTL3, reg);
+	}
+}
 #endif /* CONFIG_PM_SLEEP */
 
 static const struct dev_pm_ops dwc3_dev_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume)
+	.complete = dwc3_complete,
 	SET_RUNTIME_PM_OPS(dwc3_runtime_suspend, dwc3_runtime_resume,
 			dwc3_runtime_idle)
 };
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 5bfb62533e0f..b3cea95f7720 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -135,6 +135,7 @@
 #define DWC3_GEVNTCOUNT(n)	(0xc40c + ((n) * 0x10))
 
 #define DWC3_GHWPARAMS8		0xc600
+#define DWC3_GUCTL3		0xc60c
 #define DWC3_GFLADJ		0xc630
 
 /* Device Registers */
@@ -359,6 +360,9 @@
 /* Global User Control Register 2 */
 #define DWC3_GUCTL2_RST_ACTBITLATER		BIT(14)
 
+/* Global User Control Register 3 */
+#define DWC3_GUCTL3_SPLITDISABLE		BIT(14)
+
 /* Device Configuration Register */
 #define DWC3_DCFG_DEVADDR(addr)	((addr) << 3)
 #define DWC3_DCFG_DEVADDR_MASK	DWC3_DCFG_DEVADDR(0x7f)
@@ -1168,6 +1172,9 @@ struct dwc3 {
 
 	unsigned		dis_metastability_quirk:1;
 
+	unsigned		dis_split_quirk:1;
+	unsigned		gctl_reset_quirk:1;
+
 	u16			imod_interval;
 };
 
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 679c12e14522..cd54ad3eaf01 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -269,7 +269,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned cmd,
 {
 	const struct usb_endpoint_descriptor *desc = dep->endpoint.desc;
 	struct dwc3		*dwc = dep->dwc;
-	u32			timeout = 1000;
+	u32			timeout = 5000;
 	u32			saved_config = 0;
 	u32			reg;
 
-- 
2.15.0-rc2


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

* [PATCH 06/10] phy: Add usb phy support for hi3660 Soc of Hisilicon
  2018-10-27  9:58 [PATCH 00/10] Add support for usb on Hikey960 Yu Chen
                   ` (4 preceding siblings ...)
  2018-10-27  9:58 ` [PATCH 05/10] usb: dwc3: Add two quirks for Hisilicon Kirin " Yu Chen
@ 2018-10-27  9:58 ` Yu Chen
  2018-11-12  9:09   ` Kishon Vijay Abraham I
  2018-10-27  9:58 ` [PATCH 07/10] hikey960: Support usb functionality of Hikey960 Yu Chen
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 23+ messages in thread
From: Yu Chen @ 2018-10-27  9:58 UTC (permalink / raw)
  To: linux-usb, devicetree, linux-kernel
  Cc: suzhuangluan, kongfei, Yu Chen, Kishon Vijay Abraham I,
	David S. Miller, Greg Kroah-Hartman, Mauro Carvalho Chehab,
	Andrew Morton, Arnd Bergmann, Shawn Guo, Pengcheng Li,
	Jianguo Sun, Masahiro Yamada, Jiancheng Xue, John Stultz,
	Binghui Wang

This driver handles usb phy power on and shutdown for hi3660 Soc of
Hisilicon.

Cc: Kishon Vijay Abraham I <kishon@ti.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Shawn Guo <shawnguo@kernel.org>
Cc: Pengcheng Li <lpc.li@hisilicon.com>
Cc: Jianguo Sun <sunjianguo1@huawei.com>
Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
Cc: Jiancheng Xue <xuejiancheng@hisilicon.com>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Binghui Wang <wangbinghui@hisilicon.com>
Signed-off-by: Yu Chen <chenyu56@huawei.com>
---
 MAINTAINERS                             |   2 +
 drivers/phy/hisilicon/Kconfig           |  10 ++
 drivers/phy/hisilicon/Makefile          |   1 +
 drivers/phy/hisilicon/phy-hi3660-usb3.c | 254 ++++++++++++++++++++++++++++++++
 4 files changed, 267 insertions(+)
 create mode 100644 drivers/phy/hisilicon/phy-hi3660-usb3.c

diff --git a/MAINTAINERS b/MAINTAINERS
index e485449f7811..7adf167588ee 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15294,7 +15294,9 @@ M:	Binghui Wang <wangbinghui@hisilicon.com>
 L:	linux-usb@vger.kernel.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/usb/dwc3-hisi.txt
+F:	Documentation/devicetree/bindings/phy/phy-hi3660-usb3.txt
 F:	drivers/usb/dwc3/dwc3-hisi.c
+F:	drivers/phy/hisilicon/phy-hi3660-usb3.c
 
 USB ISP116X DRIVER
 M:	Olav Kongas <ok@artecdesign.ee>
diff --git a/drivers/phy/hisilicon/Kconfig b/drivers/phy/hisilicon/Kconfig
index b40ee54a1a50..3c142f08987c 100644
--- a/drivers/phy/hisilicon/Kconfig
+++ b/drivers/phy/hisilicon/Kconfig
@@ -12,6 +12,16 @@ config PHY_HI6220_USB
 
 	  To compile this driver as a module, choose M here.
 
+config PHY_HI3660_USB
+	tristate "hi3660 USB PHY support"
+	depends on (ARCH_HISI && ARM64) || COMPILE_TEST
+	select GENERIC_PHY
+	select MFD_SYSCON
+	help
+	  Enable this to support the HISILICON HI3660 USB PHY.
+
+	  To compile this driver as a module, choose M here.
+
 config PHY_HISTB_COMBPHY
 	tristate "HiSilicon STB SoCs COMBPHY support"
 	depends on (ARCH_HISI && ARM64) || COMPILE_TEST
diff --git a/drivers/phy/hisilicon/Makefile b/drivers/phy/hisilicon/Makefile
index f662a4fe18d8..75ba64e2faf8 100644
--- a/drivers/phy/hisilicon/Makefile
+++ b/drivers/phy/hisilicon/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_PHY_HI6220_USB)		+= phy-hi6220-usb.o
+obj-$(CONFIG_PHY_HI3660_USB)		+= phy-hi3660-usb3.o
 obj-$(CONFIG_PHY_HISTB_COMBPHY)		+= phy-histb-combphy.o
 obj-$(CONFIG_PHY_HISI_INNO_USB2)	+= phy-hisi-inno-usb2.o
 obj-$(CONFIG_PHY_HIX5HD2_SATA)		+= phy-hix5hd2-sata.o
diff --git a/drivers/phy/hisilicon/phy-hi3660-usb3.c b/drivers/phy/hisilicon/phy-hi3660-usb3.c
new file mode 100644
index 000000000000..041c542750e2
--- /dev/null
+++ b/drivers/phy/hisilicon/phy-hi3660-usb3.c
@@ -0,0 +1,254 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Phy provider for USB 3.0 controller on HiSilicon 3660 platform
+ *
+ * Copyright (C) 2017-2018 Hilisicon Electronics Co., Ltd.
+ *		http://www.huawei.com
+ *
+ * Authors: Yu Chen <chenyu56@huawei.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2  of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+
+#define PERI_CRG_CLK_EN4			(0x40)
+#define PERI_CRG_CLK_DIS4			(0x44)
+#define GT_CLK_USB3OTG_REF			BIT(0)
+#define GT_ACLK_USB3OTG				BIT(1)
+
+#define PERI_CRG_RSTEN4				(0x90)
+#define PERI_CRG_RSTDIS4			(0x94)
+#define IP_RST_USB3OTGPHY_POR			BIT(3)
+#define IP_RST_USB3OTG				BIT(5)
+
+#define PERI_CRG_ISODIS				(0x148)
+#define USB_REFCLK_ISO_EN			BIT(25)
+
+#define PCTRL_PERI_CTRL3			(0x10)
+#define PCTRL_PERI_CTRL3_MSK_START		(16)
+#define USB_TCXO_EN				BIT(1)
+
+#define PCTRL_PERI_CTRL24			(0x64)
+#define SC_CLK_USB3PHY_3MUX1_SEL		BIT(25)
+
+#define USBOTG3_CTRL0				(0x00)
+#define SC_USB3PHY_ABB_GT_EN			BIT(15)
+
+#define USBOTG3_CTRL2				(0x08)
+#define USBOTG3CTRL2_POWERDOWN_HSP		BIT(0)
+#define USBOTG3CTRL2_POWERDOWN_SSP		BIT(1)
+
+#define USBOTG3_CTRL3				(0x0C)
+#define USBOTG3_CTRL3_VBUSVLDEXT		BIT(6)
+#define USBOTG3_CTRL3_VBUSVLDEXTSEL		BIT(5)
+
+#define USBOTG3_CTRL4				(0x10)
+
+#define USBOTG3_CTRL7				(0x1c)
+#define REF_SSP_EN				BIT(16)
+
+#define HI3660_USB_DEFAULT_PHY_PARAM		(0x1c466e3)
+
+struct hi3660_priv {
+	struct device *dev;
+	struct regmap *peri_crg;
+	struct regmap *pctrl;
+	struct regmap *otg_bc;
+	u32 eye_diagram_param;
+
+	u32 peri_crg_offset;
+	u32 pctrl_offset;
+	u32 otg_bc_offset;
+};
+
+static int hi3660_phy_init(struct phy *phy)
+{
+	struct hi3660_priv *priv = phy_get_drvdata(phy);
+	u32 val, mask;
+	int ret;
+
+	/* usb refclk iso disable */
+	ret = regmap_write(priv->peri_crg, PERI_CRG_ISODIS, USB_REFCLK_ISO_EN);
+	if (ret)
+		goto out;
+
+	/* enable usb_tcxo_en */
+	val = USB_TCXO_EN | (USB_TCXO_EN << PCTRL_PERI_CTRL3_MSK_START);
+	ret = regmap_write(priv->pctrl, PCTRL_PERI_CTRL3, val);
+	if (ret)
+		goto out;
+
+	/* select usbphy clk from abb */
+	mask = SC_CLK_USB3PHY_3MUX1_SEL;
+	ret = regmap_update_bits(priv->pctrl, PCTRL_PERI_CTRL24, mask, 0);
+	if (ret)
+		goto out;
+
+	/* assert phy */
+	val = IP_RST_USB3OTGPHY_POR | IP_RST_USB3OTG;
+	ret = regmap_write(priv->peri_crg, PERI_CRG_RSTEN4, val);
+	if (ret)
+		goto out;
+
+	/* enable phy ref clk */
+	val = SC_USB3PHY_ABB_GT_EN;
+	mask = val;
+	ret = regmap_update_bits(priv->otg_bc, USBOTG3_CTRL0, mask, val);
+	if (ret)
+		goto out;
+
+	val = REF_SSP_EN;
+	mask = val;
+	ret = regmap_update_bits(priv->otg_bc, USBOTG3_CTRL7, mask, val);
+	if (ret)
+		goto out;
+
+	/* exit from IDDQ mode */
+	mask = USBOTG3CTRL2_POWERDOWN_HSP | USBOTG3CTRL2_POWERDOWN_SSP;
+	ret = regmap_update_bits(priv->otg_bc, USBOTG3_CTRL2, mask, 0);
+	if (ret)
+		goto out;
+
+	udelay(100);
+
+	/* deassert phy */
+	val = IP_RST_USB3OTGPHY_POR | IP_RST_USB3OTG;
+	ret = regmap_write(priv->peri_crg, PERI_CRG_RSTDIS4, val);
+	if (ret)
+		goto out;
+
+	usleep_range(10000, 15000);
+
+	/* fake vbus valid signal */
+	val = USBOTG3_CTRL3_VBUSVLDEXT | USBOTG3_CTRL3_VBUSVLDEXTSEL;
+	mask = val;
+	ret = regmap_update_bits(priv->otg_bc, USBOTG3_CTRL3, mask, val);
+	if (ret)
+		goto out;
+
+	udelay(100);
+
+	ret = regmap_write(priv->otg_bc, USBOTG3_CTRL4,
+			priv->eye_diagram_param);
+	if (ret)
+		goto out;
+
+	return 0;
+out:
+	dev_err(priv->dev, "failed to init phy ret: %d\n", ret);
+	return ret;
+}
+
+static int hi3660_phy_exit(struct phy *phy)
+{
+	struct hi3660_priv *priv = phy_get_drvdata(phy);
+	u32 val, mask;
+	int ret;
+
+	/* assert phy */
+	val = IP_RST_USB3OTGPHY_POR;
+	ret = regmap_write(priv->peri_crg, PERI_CRG_RSTEN4, val);
+	if (ret)
+		goto out;
+
+	val = SC_CLK_USB3PHY_3MUX1_SEL;
+	mask = SC_CLK_USB3PHY_3MUX1_SEL;
+	ret = regmap_update_bits(priv->pctrl, PCTRL_PERI_CTRL24, mask, val);
+	if (ret)
+		goto out;
+
+	/* disable usb_tcxo_en */
+	val = USB_TCXO_EN << PCTRL_PERI_CTRL3_MSK_START;
+	ret = regmap_write(priv->pctrl, PCTRL_PERI_CTRL3, val);
+	if (ret)
+		goto out;
+
+	return 0;
+out:
+	dev_err(priv->dev, "failed to exit phy ret: %d\n", ret);
+	return ret;
+}
+
+static struct phy_ops hi3660_phy_ops = {
+	.init		= hi3660_phy_init,
+	.exit		= hi3660_phy_exit,
+	.owner		= THIS_MODULE,
+};
+
+static int hi3660_phy_probe(struct platform_device *pdev)
+{
+	struct phy_provider *phy_provider;
+	struct device *dev = &pdev->dev;
+	struct phy *phy;
+	struct hi3660_priv *priv;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->dev = dev;
+	priv->peri_crg = syscon_regmap_lookup_by_phandle(dev->of_node,
+					"hisilicon,pericrg-syscon");
+	if (IS_ERR(priv->peri_crg)) {
+		dev_err(dev, "no hisilicon,pericrg-syscon\n");
+		return PTR_ERR(priv->peri_crg);
+	}
+
+	priv->pctrl = syscon_regmap_lookup_by_phandle(dev->of_node,
+					"hisilicon,pctrl-syscon");
+	if (IS_ERR(priv->pctrl)) {
+		dev_err(dev, "no hisilicon,pctrl-syscon\n");
+		return PTR_ERR(priv->pctrl);
+	}
+
+	priv->otg_bc = syscon_regmap_lookup_by_phandle(dev->of_node,
+					"hisilicon,usb3-otg-bc-syscon");
+	if (IS_ERR(priv->otg_bc)) {
+		dev_err(dev, "no hisilicon,usb3-otg-bc-syscon\n");
+		return PTR_ERR(priv->otg_bc);
+	}
+
+	if (of_property_read_u32(dev->of_node, "eye-diagram-param",
+		&(priv->eye_diagram_param)))
+		priv->eye_diagram_param = HI3660_USB_DEFAULT_PHY_PARAM;
+
+	phy = devm_phy_create(dev, NULL, &hi3660_phy_ops);
+	if (IS_ERR(phy))
+		return PTR_ERR(phy);
+
+	phy_set_drvdata(phy, priv);
+	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+	return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id hi3660_phy_of_match[] = {
+	{.compatible = "hisilicon,hi3660-usb-phy",},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, hi3660_phy_of_match);
+
+static struct platform_driver hi3660_phy_driver = {
+	.probe	= hi3660_phy_probe,
+	.driver = {
+		.name	= "hi3660-usb-phy",
+		.of_match_table	= hi3660_phy_of_match,
+	}
+};
+module_platform_driver(hi3660_phy_driver);
+
+MODULE_AUTHOR("Yu Chen <chenyu56@huawei.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Hilisicon Hi3660 USB3 PHY Driver");
-- 
2.15.0-rc2


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

* [PATCH 07/10] hikey960: Support usb functionality of Hikey960
  2018-10-27  9:58 [PATCH 00/10] Add support for usb on Hikey960 Yu Chen
                   ` (5 preceding siblings ...)
  2018-10-27  9:58 ` [PATCH 06/10] phy: Add usb phy support for hi3660 Soc of Hisilicon Yu Chen
@ 2018-10-27  9:58 ` Yu Chen
  2018-10-29 14:30   ` Heikki Krogerus
  2018-10-27  9:58 ` [PATCH 08/10] usb: typec: Add support for usb role switch in rt1711h driver Yu Chen
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 23+ messages in thread
From: Yu Chen @ 2018-10-27  9:58 UTC (permalink / raw)
  To: linux-usb, devicetree, linux-kernel
  Cc: suzhuangluan, kongfei, Yu Chen, Arnd Bergmann,
	Greg Kroah-Hartman, John Stultz, Binghui Wang

This driver handles usb hub power on and typeC port event of HiKey960 board:
1)DP&DM switching between usb hub and typeC port base on typeC port
state
2)Control power of usb hub on Hikey960
3)Control vbus of typeC port
4)Handle typeC port event to switch data role

Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Binghui Wang <wangbinghui@hisilicon.com>
Signed-off-by: Yu Chen <chenyu56@huawei.com>
---
 drivers/misc/Kconfig          |   7 +
 drivers/misc/Makefile         |   1 +
 drivers/misc/hisi_hikey_usb.c | 319 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 327 insertions(+)
 create mode 100644 drivers/misc/hisi_hikey_usb.c

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 3726eacdf65d..8e04fc87b685 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -513,6 +513,13 @@ config MISC_RTSX
 	tristate
 	default MISC_RTSX_PCI || MISC_RTSX_USB
 
+config HISI_HIKEY_USB
+	tristate "USB functionality of HiSilicon Hikey Platform"
+	depends on GPIOLIB
+	default n
+	help
+	  If you say yes here you get support for usb functionality of HiSilicon Hikey Platform.
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index af22bbc3d00c..387dd302815c 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -58,3 +58,4 @@ obj-$(CONFIG_ASPEED_LPC_SNOOP)	+= aspeed-lpc-snoop.o
 obj-$(CONFIG_PCI_ENDPOINT_TEST)	+= pci_endpoint_test.o
 obj-$(CONFIG_OCXL)		+= ocxl/
 obj-$(CONFIG_MISC_RTSX)		+= cardreader/
+obj-$(CONFIG_HISI_HIKEY_USB)	+= hisi_hikey_usb.o
diff --git a/drivers/misc/hisi_hikey_usb.c b/drivers/misc/hisi_hikey_usb.c
new file mode 100644
index 000000000000..4965719c99ae
--- /dev/null
+++ b/drivers/misc/hisi_hikey_usb.c
@@ -0,0 +1,319 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * hisi_hikey_usb.c
+ *
+ * Copyright (c) Hisilicon Tech. Co., Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/extcon-provider.h>
+#include <linux/usb/role.h>
+
+#define DEVICE_DRIVER_NAME "hisi_hikey_usb"
+
+#define HUB_VBUS_POWER_ON 1
+#define HUB_VBUS_POWER_OFF 0
+#define USB_SWITCH_TO_HUB 1
+#define USB_SWITCH_TO_TYPEC 0
+
+#define INVALID_GPIO_VALUE (-1)
+
+struct hisi_hikey_usb {
+	int otg_switch_gpio;
+	int typec_vbus_gpio;
+	int typec_vbus_enable_val;
+	int hub_vbus_gpio;
+
+	struct extcon_dev *edev;
+	struct usb_role_switch *role_sw;
+};
+
+static const unsigned int usb_extcon_cable[] = {
+	EXTCON_USB,
+	EXTCON_USB_HOST,
+	EXTCON_NONE,
+};
+
+static void hub_power_ctrl(struct hisi_hikey_usb *hisi_hikey_usb, int value)
+{
+	int gpio = hisi_hikey_usb->hub_vbus_gpio;
+
+	if (gpio_is_valid(gpio))
+		gpio_set_value(gpio, value);
+}
+
+static void usb_switch_ctrl(struct hisi_hikey_usb *hisi_hikey_usb,
+		int switch_to)
+{
+	int gpio = hisi_hikey_usb->otg_switch_gpio;
+	const char *switch_to_str = (switch_to == USB_SWITCH_TO_HUB) ?
+		"hub" : "typec";
+
+	if (!gpio_is_valid(gpio)) {
+		pr_err("%s: otg_switch_gpio is err\n", __func__);
+		return;
+	}
+
+	if (gpio_get_value(gpio) == switch_to) {
+		pr_info("%s: already switch to %s\n", __func__, switch_to_str);
+		return;
+	}
+
+	gpio_direction_output(gpio, switch_to);
+	pr_info("%s: switch to %s\n", __func__, switch_to_str);
+}
+
+static void usb_typec_power_ctrl(struct hisi_hikey_usb *hisi_hikey_usb,
+		int value)
+{
+	int gpio = hisi_hikey_usb->typec_vbus_gpio;
+
+	if (!gpio_is_valid(gpio)) {
+		pr_err("%s: typec power gpio is err\n", __func__);
+		return;
+	}
+
+	if (gpio_get_value(gpio) == value) {
+		pr_info("%s: typec power no change\n", __func__);
+		return;
+	}
+
+	gpio_direction_output(gpio, value);
+	pr_info("%s: set typec vbus gpio to %d\n", __func__, value);
+}
+
+static int extcon_hisi_pd_set_role(struct device *dev, enum usb_role role)
+{
+	struct hisi_hikey_usb *hisi_hikey_usb = dev_get_drvdata(dev);
+
+	dev_info(dev, "%s:set usb role to %d\n", __func__, role);
+	switch (role) {
+	case USB_ROLE_NONE:
+		usb_switch_ctrl(hisi_hikey_usb, USB_SWITCH_TO_HUB);
+		usb_typec_power_ctrl(hisi_hikey_usb,
+				!hisi_hikey_usb->typec_vbus_enable_val);
+		hub_power_ctrl(hisi_hikey_usb, HUB_VBUS_POWER_ON);
+		extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB, false);
+		extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB_HOST,
+				true);
+		break;
+	case USB_ROLE_HOST:
+		usb_switch_ctrl(hisi_hikey_usb, USB_SWITCH_TO_TYPEC);
+		usb_typec_power_ctrl(hisi_hikey_usb,
+				hisi_hikey_usb->typec_vbus_enable_val);
+		extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB, false);
+		extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB_HOST,
+				true);
+		break;
+	case USB_ROLE_DEVICE:
+		hub_power_ctrl(hisi_hikey_usb, HUB_VBUS_POWER_OFF);
+		usb_typec_power_ctrl(hisi_hikey_usb,
+				hisi_hikey_usb->typec_vbus_enable_val);
+		usb_switch_ctrl(hisi_hikey_usb, USB_SWITCH_TO_TYPEC);
+		extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB_HOST,
+				false);
+		extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB, true);
+		break;
+	}
+
+	return 0;
+}
+
+static enum usb_role extcon_hisi_pd_get_role(struct device *dev)
+{
+	struct hisi_hikey_usb *hisi_hikey_usb = dev_get_drvdata(dev);
+
+	return usb_role_switch_get_role(hisi_hikey_usb->role_sw);
+}
+
+static const struct usb_role_switch_desc sw_desc = {
+	.set = extcon_hisi_pd_set_role,
+	.get = extcon_hisi_pd_get_role,
+	.allow_userspace_control = true,
+};
+
+static int hisi_hikey_usb_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *root = dev->of_node;
+	struct hisi_hikey_usb *hisi_hikey_usb;
+	int ret;
+
+	hisi_hikey_usb = devm_kzalloc(dev, sizeof(*hisi_hikey_usb), GFP_KERNEL);
+	if (!hisi_hikey_usb)
+		return -ENOMEM;
+
+	dev_set_name(dev, "hisi_hikey_usb");
+
+	hisi_hikey_usb->hub_vbus_gpio = INVALID_GPIO_VALUE;
+	hisi_hikey_usb->otg_switch_gpio = INVALID_GPIO_VALUE;
+	hisi_hikey_usb->typec_vbus_gpio = INVALID_GPIO_VALUE;
+
+	hisi_hikey_usb->hub_vbus_gpio = of_get_named_gpio(root,
+			"hub_vdd33_en_gpio", 0);
+	if (!gpio_is_valid(hisi_hikey_usb->hub_vbus_gpio)) {
+		pr_err("%s: hub_vbus_gpio is err\n", __func__);
+		return hisi_hikey_usb->hub_vbus_gpio;
+	}
+
+	ret = gpio_request(hisi_hikey_usb->hub_vbus_gpio, "hub_vbus_int_gpio");
+	if (ret) {
+		pr_err("%s: request hub_vbus_gpio err\n", __func__);
+		hisi_hikey_usb->hub_vbus_gpio = INVALID_GPIO_VALUE;
+		return ret;
+	}
+
+	ret = gpio_direction_output(hisi_hikey_usb->hub_vbus_gpio,
+			HUB_VBUS_POWER_ON);
+	if (ret) {
+		pr_err("%s: power on hub vbus err\n", __func__);
+		goto free_gpio1;
+	}
+
+	hisi_hikey_usb->typec_vbus_gpio = of_get_named_gpio(root,
+		"typc_vbus_int_gpio,typec-gpios", 0);
+	if (!gpio_is_valid(hisi_hikey_usb->typec_vbus_gpio)) {
+		pr_err("%s: typec_vbus_gpio is err\n", __func__);
+		ret = hisi_hikey_usb->typec_vbus_gpio;
+		goto free_gpio1;
+	}
+
+	ret = gpio_request(hisi_hikey_usb->typec_vbus_gpio,
+			"typc_vbus_int_gpio");
+	if (ret) {
+		pr_err("%s: request typec_vbus_gpio err\n", __func__);
+		hisi_hikey_usb->typec_vbus_gpio = INVALID_GPIO_VALUE;
+		goto free_gpio1;
+	}
+
+	ret = of_property_read_u32(root, "typc_vbus_enable_val",
+				   &hisi_hikey_usb->typec_vbus_enable_val);
+	if (ret) {
+		pr_err("%s: typc_vbus_enable_val can't get\n", __func__);
+		goto free_gpio2;
+	}
+
+	hisi_hikey_usb->typec_vbus_enable_val =
+		!!hisi_hikey_usb->typec_vbus_enable_val;
+
+	ret = gpio_direction_output(hisi_hikey_usb->typec_vbus_gpio,
+				    hisi_hikey_usb->typec_vbus_enable_val);
+	if (ret) {
+		pr_err("%s: power on typec vbus err", __func__);
+		goto free_gpio2;
+	}
+
+	if (of_device_is_compatible(root, "hisilicon,hikey960_usb")) {
+		hisi_hikey_usb->otg_switch_gpio = of_get_named_gpio(root,
+				"otg_gpio", 0);
+		if (!gpio_is_valid(hisi_hikey_usb->otg_switch_gpio)) {
+			pr_info("%s: otg_switch_gpio is err\n", __func__);
+			goto free_gpio2;
+		}
+
+		ret = gpio_request(hisi_hikey_usb->otg_switch_gpio,
+				"otg_switch_gpio");
+		if (ret) {
+			hisi_hikey_usb->otg_switch_gpio = INVALID_GPIO_VALUE;
+			pr_err("%s: request typec_vbus_gpio err\n", __func__);
+			goto free_gpio2;
+		}
+	}
+
+	hisi_hikey_usb->edev = devm_extcon_dev_allocate(dev, usb_extcon_cable);
+	if (IS_ERR(hisi_hikey_usb->edev)) {
+		dev_err(dev, "failed to allocate extcon device\n");
+		goto free_gpio2;
+	}
+
+	ret = devm_extcon_dev_register(dev, hisi_hikey_usb->edev);
+	if (ret < 0) {
+		dev_err(dev, "failed to register extcon device\n");
+		goto free_gpio2;
+	}
+	extcon_set_state(hisi_hikey_usb->edev, EXTCON_USB_HOST, true);
+
+	hisi_hikey_usb->role_sw = usb_role_switch_register(dev, &sw_desc);
+	if (IS_ERR(hisi_hikey_usb->role_sw))
+		goto free_gpio2;
+
+	platform_set_drvdata(pdev, hisi_hikey_usb);
+
+	return 0;
+
+free_gpio2:
+	if (gpio_is_valid(hisi_hikey_usb->typec_vbus_gpio)) {
+		gpio_free(hisi_hikey_usb->typec_vbus_gpio);
+		hisi_hikey_usb->typec_vbus_gpio = INVALID_GPIO_VALUE;
+	}
+
+free_gpio1:
+	if (gpio_is_valid(hisi_hikey_usb->hub_vbus_gpio)) {
+		gpio_free(hisi_hikey_usb->hub_vbus_gpio);
+		hisi_hikey_usb->hub_vbus_gpio = INVALID_GPIO_VALUE;
+	}
+
+	return ret;
+}
+
+static int  hisi_hikey_usb_remove(struct platform_device *pdev)
+{
+	struct hisi_hikey_usb *hisi_hikey_usb = platform_get_drvdata(pdev);
+
+	if (gpio_is_valid(hisi_hikey_usb->otg_switch_gpio)) {
+		gpio_free(hisi_hikey_usb->otg_switch_gpio);
+		hisi_hikey_usb->otg_switch_gpio = INVALID_GPIO_VALUE;
+	}
+
+	if (gpio_is_valid(hisi_hikey_usb->typec_vbus_gpio)) {
+		gpio_free(hisi_hikey_usb->typec_vbus_gpio);
+		hisi_hikey_usb->typec_vbus_gpio = INVALID_GPIO_VALUE;
+	}
+
+	if (gpio_is_valid(hisi_hikey_usb->hub_vbus_gpio)) {
+		gpio_free(hisi_hikey_usb->hub_vbus_gpio);
+		hisi_hikey_usb->hub_vbus_gpio = INVALID_GPIO_VALUE;
+	}
+
+	usb_role_switch_unregister(hisi_hikey_usb->role_sw);
+
+	return 0;
+}
+
+static const struct of_device_id id_table_hisi_hikey_usb[] = {
+	{.compatible = "hisilicon,gpio_hubv1"},
+	{.compatible = "hisilicon,hikey960_usb"},
+	{}
+};
+
+static struct platform_driver  hisi_hikey_usb_driver = {
+	.probe = hisi_hikey_usb_probe,
+	.remove = hisi_hikey_usb_remove,
+	.driver = {
+		.name = DEVICE_DRIVER_NAME,
+		.of_match_table = of_match_ptr(id_table_hisi_hikey_usb),
+
+	},
+};
+
+module_platform_driver(hisi_hikey_usb_driver);
+
+MODULE_AUTHOR("Yu Chen <chenyu56@huawei.com>");
+MODULE_DESCRIPTION("Driver Support for USB functionality of Hikey");
+MODULE_LICENSE("GPL v2");
-- 
2.15.0-rc2


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

* [PATCH 08/10] usb: typec: Add support for usb role switch in rt1711h driver
  2018-10-27  9:58 [PATCH 00/10] Add support for usb on Hikey960 Yu Chen
                   ` (6 preceding siblings ...)
  2018-10-27  9:58 ` [PATCH 07/10] hikey960: Support usb functionality of Hikey960 Yu Chen
@ 2018-10-27  9:58 ` Yu Chen
  2018-10-29 11:58   ` Heikki Krogerus
  2018-10-27  9:58 ` [PATCH 09/10] usb: gadget: Add configfs attribuite for controling match_existing_only Yu Chen
  2018-10-27  9:58 ` [PATCH 10/10] dts: hi3660: Add support for usb on Hikey960 Yu Chen
  9 siblings, 1 reply; 23+ messages in thread
From: Yu Chen @ 2018-10-27  9:58 UTC (permalink / raw)
  To: linux-usb, devicetree, linux-kernel
  Cc: suzhuangluan, kongfei, Yu Chen, Heikki Krogerus,
	Greg Kroah-Hartman, Lucas Tsai, shufan_lee, John Stultz,
	Binghui Wang

This patch add struct device_connection to rt1711h driver to support
find "usb-role-switch" in tcpm_register_port.

Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Lucas Tsai <lucas_tsai@richtek.com>
Cc: shufan_lee <shufan_lee@richtek.com>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Binghui Wang <wangbinghui@hisilicon.com>
Signed-off-by: Yu Chen <chenyu56@huawei.com>
---
 drivers/usb/typec/tcpm/tcpci_rt1711h.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/drivers/usb/typec/tcpm/tcpci_rt1711h.c b/drivers/usb/typec/tcpm/tcpci_rt1711h.c
index 017389021b96..5f8b952612fe 100644
--- a/drivers/usb/typec/tcpm/tcpci_rt1711h.c
+++ b/drivers/usb/typec/tcpm/tcpci_rt1711h.c
@@ -39,6 +39,7 @@ struct rt1711h_chip {
 	struct tcpci_data data;
 	struct tcpci *tcpci;
 	struct device *dev;
+	struct device_connection dev_conn;
 };
 
 static int rt1711h_read16(struct rt1711h_chip *chip, unsigned int reg, u16 *val)
@@ -237,6 +238,7 @@ static int rt1711h_probe(struct i2c_client *client,
 {
 	int ret;
 	struct rt1711h_chip *chip;
+	const char *dev_conn_end;
 
 	ret = rt1711h_check_revision(client);
 	if (ret < 0) {
@@ -254,6 +256,7 @@ static int rt1711h_probe(struct i2c_client *client,
 		return PTR_ERR(chip->data.regmap);
 
 	chip->dev = &client->dev;
+	dev_set_name(chip->dev, "rt1711h");
 	i2c_set_clientdata(client, chip);
 
 	ret = rt1711h_sw_reset(chip);
@@ -264,6 +267,15 @@ static int rt1711h_probe(struct i2c_client *client,
 	if (ret < 0)
 		return ret;
 
+	ret = device_property_read_string(chip->dev, "dev-conn-end",
+			&dev_conn_end);
+	if (!ret) {
+		chip->dev_conn.endpoint[0] = "rt1711h";
+		chip->dev_conn.endpoint[1] = dev_conn_end;
+		chip->dev_conn.id = "usb-role-switch";
+		device_connection_add(&chip->dev_conn);
+	}
+
 	chip->data.init = rt1711h_init;
 	chip->data.set_vconn = rt1711h_set_vconn;
 	chip->data.start_drp_toggling = rt1711h_start_drp_toggling;
@@ -279,6 +291,9 @@ static int rt1711h_remove(struct i2c_client *client)
 	struct rt1711h_chip *chip = i2c_get_clientdata(client);
 
 	tcpci_unregister_port(chip->tcpci);
+	if (chip->dev_conn.id)
+		device_connection_remove(&chip->dev_conn);
+
 	return 0;
 }
 
-- 
2.15.0-rc2


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

* [PATCH 09/10] usb: gadget: Add configfs attribuite for controling match_existing_only
  2018-10-27  9:58 [PATCH 00/10] Add support for usb on Hikey960 Yu Chen
                   ` (7 preceding siblings ...)
  2018-10-27  9:58 ` [PATCH 08/10] usb: typec: Add support for usb role switch in rt1711h driver Yu Chen
@ 2018-10-27  9:58 ` Yu Chen
  2018-10-27  9:58 ` [PATCH 10/10] dts: hi3660: Add support for usb on Hikey960 Yu Chen
  9 siblings, 0 replies; 23+ messages in thread
From: Yu Chen @ 2018-10-27  9:58 UTC (permalink / raw)
  To: linux-usb, devicetree, linux-kernel
  Cc: suzhuangluan, kongfei, Yu Chen, Felipe Balbi, Greg Kroah-Hartman,
	John Stultz, Binghui Wang

Currently the "match_existing_only" of usb_gadget_driver in configfs is
set to one which is not flexible.
Dwc3 udc will be removed when usb core switch to host mode. This causes
failure of writing name of dwc3 udc to configfs's UDC attribuite.
To fix this we need to add a way to change the config of
"match_existing_only".
This patch adds a configfs attribuite for controling match_existing_only
which allow user to config "match_existing_only".

Cc: Felipe Balbi <balbi@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: John Stultz <john.stultz@linaro.org>
Cc: Binghui Wang <wangbinghui@hisilicon.com>
Signed-off-by: Yu Chen <chenyu56@huawei.com>
---
 drivers/usb/gadget/configfs.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index 025129942894..c82b7bc98dea 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -291,6 +291,36 @@ static ssize_t gadget_dev_desc_UDC_store(struct config_item *item,
 	return ret;
 }
 
+static ssize_t gadget_driver_match_existing_only_store(struct config_item *item,
+		const char *page, size_t len)
+{
+	struct usb_gadget_driver *gadget_driver =
+		&(to_gadget_info(item)->composite.gadget_driver);
+	bool match_existing_only;
+	int ret;
+
+	ret = kstrtobool(page, &match_existing_only);
+	if (ret)
+		return ret;
+
+	if (match_existing_only)
+		gadget_driver->match_existing_only = 1;
+	else
+		gadget_driver->match_existing_only = 0;
+
+	return len;
+}
+
+static ssize_t gadget_driver_match_existing_only_show(struct config_item *item,
+		char *page)
+{
+	struct usb_gadget_driver *gadget_driver =
+		&(to_gadget_info(item)->composite.gadget_driver);
+	bool match_existing_only = !!gadget_driver->match_existing_only;
+
+	return sprintf(page, "%s\n", match_existing_only ? "true" : "false");
+}
+
 CONFIGFS_ATTR(gadget_dev_desc_, bDeviceClass);
 CONFIGFS_ATTR(gadget_dev_desc_, bDeviceSubClass);
 CONFIGFS_ATTR(gadget_dev_desc_, bDeviceProtocol);
@@ -300,6 +330,7 @@ CONFIGFS_ATTR(gadget_dev_desc_, idProduct);
 CONFIGFS_ATTR(gadget_dev_desc_, bcdDevice);
 CONFIGFS_ATTR(gadget_dev_desc_, bcdUSB);
 CONFIGFS_ATTR(gadget_dev_desc_, UDC);
+CONFIGFS_ATTR(gadget_, driver_match_existing_only);
 
 static struct configfs_attribute *gadget_root_attrs[] = {
 	&gadget_dev_desc_attr_bDeviceClass,
@@ -311,6 +342,7 @@ static struct configfs_attribute *gadget_root_attrs[] = {
 	&gadget_dev_desc_attr_bcdDevice,
 	&gadget_dev_desc_attr_bcdUSB,
 	&gadget_dev_desc_attr_UDC,
+	&gadget_attr_driver_match_existing_only,
 	NULL,
 };
 
-- 
2.15.0-rc2


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

* [PATCH 10/10] dts: hi3660: Add support for usb on Hikey960
  2018-10-27  9:58 [PATCH 00/10] Add support for usb on Hikey960 Yu Chen
                   ` (8 preceding siblings ...)
  2018-10-27  9:58 ` [PATCH 09/10] usb: gadget: Add configfs attribuite for controling match_existing_only Yu Chen
@ 2018-10-27  9:58 ` Yu Chen
  9 siblings, 0 replies; 23+ messages in thread
From: Yu Chen @ 2018-10-27  9:58 UTC (permalink / raw)
  To: linux-usb, devicetree, linux-kernel
  Cc: suzhuangluan, kongfei, Yu Chen, Wei Xu, Rob Herring,
	Mark Rutland, linux-arm-kernel, John Stultz, Binghui Wang

This patch adds support for usb on Hikey960.

Cc: Wei Xu <xuwei5@hisilicon.com>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: John Stultz <john.stultz@linaro.org>
Cc: Binghui Wang <wangbinghui@hisilicon.com>
Signed-off-by: Yu Chen <chenyu56@huawei.com>
---
 arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts | 35 +++++++++++++++
 arch/arm64/boot/dts/hisilicon/hi3660.dtsi         | 52 +++++++++++++++++++++++
 2 files changed, 87 insertions(+)

diff --git a/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts b/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts
index c98bcbc8dfba..49b6965a96c8 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts
+++ b/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts
@@ -13,6 +13,7 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/usb/pd.h>
 
 / {
 	model = "HiKey960";
@@ -196,6 +197,17 @@
 			method = "smc";
 		};
 	};
+
+	hisi_hikey_usb: hisi_hikey_usb {
+		compatible = "hisilicon,hikey960_usb";
+		typc_vbus_int_gpio,typec-gpios = <&gpio25 2 0>;
+		typc_vbus_enable_val = <1>;
+		otg_gpio = <&gpio25 6 0>;
+		hub_vdd33_en_gpio = <&gpio5 6 0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&usbhub5734_pmx_func>;
+	};
+
 };
 
 /*
@@ -526,6 +538,29 @@
 &i2c1 {
 	status = "okay";
 
+	rt1711h: rt1711h@4e {
+		compatible = "richtek,rt1711h";
+		reg = <0x4e>;
+		status = "ok";
+		interrupt-parent = <&gpio27>;
+		interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&usb_cfg_func>;
+		dev-conn-end = "hisi_hikey_usb-role-switch";
+
+		usb_con: connector {
+			compatible = "usb-c-connector";
+			label = "USB-C";
+			data-role = "dual";
+			power-role = "dual";
+			try-power-role = "sink";
+			source-pdos = <PDO_FIXED(5000, 500, PDO_FIXED_USB_COMM)>;
+			sink-pdos = <PDO_FIXED(5000, 500, PDO_FIXED_USB_COMM)
+				PDO_VAR(5000, 5000, 1000)>;
+			op-sink-microwatt = <10000000>;
+		};
+	};
+
 	adv7533: adv7533@39 {
 		status = "ok";
 		compatible = "adi,adv7533";
diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
index f432b0a88c65..d0af1cd4db80 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
@@ -1122,5 +1122,57 @@
 				};
 			};
 		};
+
+		usb3_otg_bc: usb3_otg_bc@ff200000 {
+			compatible = "syscon";
+			reg = <0x0 0xff200000 0x0 0x1000>;
+		};
+
+		usb_phy: usbphy {
+			compatible = "hisilicon,hi3660-usb-phy";
+			#phy-cells = <0>;
+			hisilicon,pericrg-syscon = <&crg_ctrl>;
+			hisilicon,pctrl-syscon = <&pctrl>;
+			hisilicon,usb3-otg-bc-syscon = <&usb3_otg_bc>;
+			eye-diagram-param = <0x22466e4>;
+		};
+
+		usb3: hisi_dwc3 {
+			compatible = "hisilicon,hi3660-dwc3";
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges;
+
+			clocks = <&crg_ctrl HI3660_CLK_ABB_USB>,
+				 <&crg_ctrl HI3660_ACLK_GATE_USB3OTG>;
+			clock-names = "clk_usb3phy_ref", "aclk_usb3otg";
+
+			assigned-clocks = <&crg_ctrl HI3660_ACLK_GATE_USB3OTG>;
+			assigned-clock-rates = <229000000>;
+			resets = <&crg_rst 0x90 8>,
+				 <&crg_rst 0x90 7>,
+				 <&crg_rst 0x90 6>,
+				 <&crg_rst 0x90 5>;
+
+			dwc3@ff100000 {
+				compatible = "snps,dwc3";
+				reg = <0x0 0xff100000 0x0 0x100000>;
+				interrupts = <0 159 4>, <0 161 4>;
+				phys = <&usb_phy>;
+				phy-names = "usb3-phy";
+				dr_mode = "otg";
+				maximum-speed = "super-speed";
+				phy_type = "utmi";
+				snps,dis-del-phy-power-chg-quirk;
+				snps,lfps_filter_quirk;
+				snps,dis_u2_susphy_quirk;
+				snps,dis_u3_susphy_quirk;
+				snps,tx_de_emphasis_quirk;
+				snps,tx_de_emphasis = <1>;
+				snps,dis_enblslpm_quirk;
+				snps,gctl-reset-quirk;
+				extcon = <&hisi_hikey_usb>;
+			};
+		};
 	};
 };
-- 
2.15.0-rc2


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

* Re: [PATCH 03/10] dt-bindings: misc: Add bindings for HiSilicon usb hub and data role switch functionality on HiKey960
  2018-10-27  9:58 ` [PATCH 03/10] dt-bindings: misc: Add bindings for HiSilicon usb hub and data role switch functionality on HiKey960 Yu Chen
@ 2018-10-27 18:06   ` Sergei Shtylyov
  2018-10-29 12:25     ` Chen Yu
  0 siblings, 1 reply; 23+ messages in thread
From: Sergei Shtylyov @ 2018-10-27 18:06 UTC (permalink / raw)
  To: Yu Chen, linux-usb, devicetree, linux-kernel
  Cc: suzhuangluan, kongfei, Rob Herring, Mark Rutland, John Stultz,
	Binghui Wang

On 27.10.2018 12:58, Yu Chen wrote:

> This patch adds binding documentation to support usb hub and usb
> data role switch of Hisilicon HiKey&HiKey960 Board.
>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: John Stultz <john.stultz@linaro.org>
> Cc: Binghui Wang <wangbinghui@hisilicon.com>
> Signed-off-by: Yu Chen <chenyu56@huawei.com>
> ---
>  .../bindings/misc/hisilicon-hikey-usb.txt          | 24 ++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/misc/hisilicon-hikey-usb.txt
>
> diff --git a/Documentation/devicetree/bindings/misc/hisilicon-hikey-usb.txt b/Documentation/devicetree/bindings/misc/hisilicon-hikey-usb.txt
> new file mode 100644
> index 000000000000..f94e990362c9
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/misc/hisilicon-hikey-usb.txt
> @@ -0,0 +1,24 @@
> +Support usb hub and usb data role switch of Hisilicon HiKey&HiKey960 Board.
> +
> +-----------------------------
> +
> +Required properties:
> +- compatible: "hisilicon,gpio_hubv1","hisilicon,hikey960_usb"
> +- typc_vbus_int_gpio,typec-gpios: gpio to control the vbus of typeC port
> +- typc_vbus_enable_val: gpio value that enable the vbus of typeC port

    The part of the prop name preceding the comma is supposed to be vendor prefix.
Also hyphens are preferred to underscores.

> +- otg_gpio: gpio to switch DP&DM between the hub and typeC port
> +- hub_vdd33_en_gpio: gpio to enable the power of hub
> +- pinctrl-0: pinctrl config
[...]

MBR, Sergei



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

* Re: [PATCH 08/10] usb: typec: Add support for usb role switch in rt1711h driver
  2018-10-27  9:58 ` [PATCH 08/10] usb: typec: Add support for usb role switch in rt1711h driver Yu Chen
@ 2018-10-29 11:58   ` Heikki Krogerus
  2018-10-29 12:22     ` Chen Yu
  0 siblings, 1 reply; 23+ messages in thread
From: Heikki Krogerus @ 2018-10-29 11:58 UTC (permalink / raw)
  To: Yu Chen
  Cc: linux-usb, devicetree, linux-kernel, suzhuangluan, kongfei,
	Greg Kroah-Hartman, Lucas Tsai, shufan_lee, John Stultz,
	Binghui Wang

On Sat, Oct 27, 2018 at 05:58:18PM +0800, Yu Chen wrote:
> This patch add struct device_connection to rt1711h driver to support
> find "usb-role-switch" in tcpm_register_port.
> 
> Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: Lucas Tsai <lucas_tsai@richtek.com>
> Cc: shufan_lee <shufan_lee@richtek.com>
> Cc: John Stultz <john.stultz@linaro.org>
> Cc: Binghui Wang <wangbinghui@hisilicon.com>
> Signed-off-by: Yu Chen <chenyu56@huawei.com>
> ---
>  drivers/usb/typec/tcpm/tcpci_rt1711h.c | 15 +++++++++++++++
>  1 file changed, 15 insertions(+)
> 
> diff --git a/drivers/usb/typec/tcpm/tcpci_rt1711h.c b/drivers/usb/typec/tcpm/tcpci_rt1711h.c
> index 017389021b96..5f8b952612fe 100644
> --- a/drivers/usb/typec/tcpm/tcpci_rt1711h.c
> +++ b/drivers/usb/typec/tcpm/tcpci_rt1711h.c
> @@ -39,6 +39,7 @@ struct rt1711h_chip {
>  	struct tcpci_data data;
>  	struct tcpci *tcpci;
>  	struct device *dev;
> +	struct device_connection dev_conn;
>  };
>  
>  static int rt1711h_read16(struct rt1711h_chip *chip, unsigned int reg, u16 *val)
> @@ -237,6 +238,7 @@ static int rt1711h_probe(struct i2c_client *client,
>  {
>  	int ret;
>  	struct rt1711h_chip *chip;
> +	const char *dev_conn_end;
>  
>  	ret = rt1711h_check_revision(client);
>  	if (ret < 0) {
> @@ -254,6 +256,7 @@ static int rt1711h_probe(struct i2c_client *client,
>  		return PTR_ERR(chip->data.regmap);
>  
>  	chip->dev = &client->dev;
> +	dev_set_name(chip->dev, "rt1711h");
>  	i2c_set_clientdata(client, chip);
>  
>  	ret = rt1711h_sw_reset(chip);
> @@ -264,6 +267,15 @@ static int rt1711h_probe(struct i2c_client *client,
>  	if (ret < 0)
>  		return ret;
>  
> +	ret = device_property_read_string(chip->dev, "dev-conn-end",
> +			&dev_conn_end);
> +	if (!ret) {
> +		chip->dev_conn.endpoint[0] = "rt1711h";
> +		chip->dev_conn.endpoint[1] = dev_conn_end;
> +		chip->dev_conn.id = "usb-role-switch";
> +		device_connection_add(&chip->dev_conn);
> +	}

That is wrong. You should not read name of a device from a property.

Regardless of that, I don't think this patch is needed at all. You
need to describe this kind connection with OF device graph
(Documentation/devicetree/bindings/graph.txt).

I've prepared a proposal how we should be able handle graphs in the
device connection API:
https://lkml.org/lkml/2018/10/24/613


thanks,

-- 
heikki

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

* Re: [PATCH 08/10] usb: typec: Add support for usb role switch in rt1711h driver
  2018-10-29 11:58   ` Heikki Krogerus
@ 2018-10-29 12:22     ` Chen Yu
  0 siblings, 0 replies; 23+ messages in thread
From: Chen Yu @ 2018-10-29 12:22 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: wangbinghui, linux-usb, devicetree, linux-kernel, suzhuangluan,
	kongfei, Greg Kroah-Hartman, Lucas Tsai, shufan_lee, John Stultz



On 2018/10/29 19:58, Heikki Krogerus wrote:
> On Sat, Oct 27, 2018 at 05:58:18PM +0800, Yu Chen wrote:
>> This patch add struct device_connection to rt1711h driver to support
>> find "usb-role-switch" in tcpm_register_port.
>>
>> Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>
>> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>> Cc: Lucas Tsai <lucas_tsai@richtek.com>
>> Cc: shufan_lee <shufan_lee@richtek.com>
>> Cc: John Stultz <john.stultz@linaro.org>
>> Cc: Binghui Wang <wangbinghui@hisilicon.com>
>> Signed-off-by: Yu Chen <chenyu56@huawei.com>
>> ---
>>  drivers/usb/typec/tcpm/tcpci_rt1711h.c | 15 +++++++++++++++
>>  1 file changed, 15 insertions(+)
>>
>> diff --git a/drivers/usb/typec/tcpm/tcpci_rt1711h.c b/drivers/usb/typec/tcpm/tcpci_rt1711h.c
>> index 017389021b96..5f8b952612fe 100644
>> --- a/drivers/usb/typec/tcpm/tcpci_rt1711h.c
>> +++ b/drivers/usb/typec/tcpm/tcpci_rt1711h.c
>> @@ -39,6 +39,7 @@ struct rt1711h_chip {
>>  	struct tcpci_data data;
>>  	struct tcpci *tcpci;
>>  	struct device *dev;
>> +	struct device_connection dev_conn;
>>  };
>>  
>>  static int rt1711h_read16(struct rt1711h_chip *chip, unsigned int reg, u16 *val)
>> @@ -237,6 +238,7 @@ static int rt1711h_probe(struct i2c_client *client,
>>  {
>>  	int ret;
>>  	struct rt1711h_chip *chip;
>> +	const char *dev_conn_end;
>>  
>>  	ret = rt1711h_check_revision(client);
>>  	if (ret < 0) {
>> @@ -254,6 +256,7 @@ static int rt1711h_probe(struct i2c_client *client,
>>  		return PTR_ERR(chip->data.regmap);
>>  
>>  	chip->dev = &client->dev;
>> +	dev_set_name(chip->dev, "rt1711h");
>>  	i2c_set_clientdata(client, chip);
>>  
>>  	ret = rt1711h_sw_reset(chip);
>> @@ -264,6 +267,15 @@ static int rt1711h_probe(struct i2c_client *client,
>>  	if (ret < 0)
>>  		return ret;
>>  
>> +	ret = device_property_read_string(chip->dev, "dev-conn-end",
>> +			&dev_conn_end);
>> +	if (!ret) {
>> +		chip->dev_conn.endpoint[0] = "rt1711h";
>> +		chip->dev_conn.endpoint[1] = dev_conn_end;
>> +		chip->dev_conn.id = "usb-role-switch";
>> +		device_connection_add(&chip->dev_conn);
>> +	}
> That is wrong. You should not read name of a device from a property.
>
> Regardless of that, I don't think this patch is needed at all. You
> need to describe this kind connection with OF device graph
> (Documentation/devicetree/bindings/graph.txt).
>
> I've prepared a proposal how we should be able handle graphs in the
> device connection API:
> https://lkml.org/lkml/2018/10/24/613
I will fix this patch. Thanks!
>
> thanks,
>



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

* Re: [PATCH 03/10] dt-bindings: misc: Add bindings for HiSilicon usb hub and data role switch functionality on HiKey960
  2018-10-27 18:06   ` Sergei Shtylyov
@ 2018-10-29 12:25     ` Chen Yu
  0 siblings, 0 replies; 23+ messages in thread
From: Chen Yu @ 2018-10-29 12:25 UTC (permalink / raw)
  To: Sergei Shtylyov, linux-usb, devicetree, linux-kernel
  Cc: wangbinghui, suzhuangluan, kongfei, Rob Herring, Mark Rutland,
	John Stultz



On 2018/10/28 2:06, Sergei Shtylyov wrote:
> On 27.10.2018 12:58, Yu Chen wrote:
>
>> This patch adds binding documentation to support usb hub and usb
>> data role switch of Hisilicon HiKey&HiKey960 Board.
>>
>> Cc: Rob Herring <robh+dt@kernel.org>
>> Cc: Mark Rutland <mark.rutland@arm.com>
>> Cc: John Stultz <john.stultz@linaro.org>
>> Cc: Binghui Wang <wangbinghui@hisilicon.com>
>> Signed-off-by: Yu Chen <chenyu56@huawei.com>
>> ---
>>  .../bindings/misc/hisilicon-hikey-usb.txt          | 24 ++++++++++++++++++++++
>>  1 file changed, 24 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/misc/hisilicon-hikey-usb.txt
>>
>> diff --git a/Documentation/devicetree/bindings/misc/hisilicon-hikey-usb.txt b/Documentation/devicetree/bindings/misc/hisilicon-hikey-usb.txt
>> new file mode 100644
>> index 000000000000..f94e990362c9
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/misc/hisilicon-hikey-usb.txt
>> @@ -0,0 +1,24 @@
>> +Support usb hub and usb data role switch of Hisilicon HiKey&HiKey960 Board.
>> +
>> +-----------------------------
>> +
>> +Required properties:
>> +- compatible: "hisilicon,gpio_hubv1","hisilicon,hikey960_usb"
>> +- typc_vbus_int_gpio,typec-gpios: gpio to control the vbus of typeC port
>> +- typc_vbus_enable_val: gpio value that enable the vbus of typeC port
>
>    The part of the prop name preceding the comma is supposed to be vendor prefix.
> Also hyphens are preferred to underscores.

I will fix the name of properties. Thanks!


>
>> +- otg_gpio: gpio to switch DP&DM between the hub and typeC port
>> +- hub_vdd33_en_gpio: gpio to enable the power of hub
>> +- pinctrl-0: pinctrl config
> [...]
>
> MBR, Sergei
>
>
>
> .
>



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

* Re: [PATCH 07/10] hikey960: Support usb functionality of Hikey960
  2018-10-27  9:58 ` [PATCH 07/10] hikey960: Support usb functionality of Hikey960 Yu Chen
@ 2018-10-29 14:30   ` Heikki Krogerus
  2018-10-30  2:50     ` Chen Yu
  0 siblings, 1 reply; 23+ messages in thread
From: Heikki Krogerus @ 2018-10-29 14:30 UTC (permalink / raw)
  To: Yu Chen
  Cc: linux-usb, devicetree, linux-kernel, suzhuangluan, kongfei,
	Arnd Bergmann, Greg Kroah-Hartman, John Stultz, Binghui Wang

Hi,

On Sat, Oct 27, 2018 at 05:58:17PM +0800, Yu Chen wrote:
> This driver handles usb hub power on and typeC port event of HiKey960 board:
> 1)DP&DM switching between usb hub and typeC port base on typeC port
> state

By "hub" do you mean you have some kind of an integrated USB hub on
your SoC?

> 2)Control power of usb hub on Hikey960
> 3)Control vbus of typeC port
> 4)Handle typeC port event to switch data role

Is your role switch a discrete component, or something part of the SoC?

> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: John Stultz <john.stultz@linaro.org>
> Cc: Binghui Wang <wangbinghui@hisilicon.com>
> Signed-off-by: Yu Chen <chenyu56@huawei.com>
> ---
>  drivers/misc/Kconfig          |   7 +
>  drivers/misc/Makefile         |   1 +
>  drivers/misc/hisi_hikey_usb.c | 319 ++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 327 insertions(+)
>  create mode 100644 drivers/misc/hisi_hikey_usb.c
> 
> diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
> index 3726eacdf65d..8e04fc87b685 100644
> --- a/drivers/misc/Kconfig
> +++ b/drivers/misc/Kconfig
> @@ -513,6 +513,13 @@ config MISC_RTSX
>  	tristate
>  	default MISC_RTSX_PCI || MISC_RTSX_USB
>  
> +config HISI_HIKEY_USB
> +	tristate "USB functionality of HiSilicon Hikey Platform"
> +	depends on GPIOLIB
> +	default n
> +	help
> +	  If you say yes here you get support for usb functionality of HiSilicon Hikey Platform.
> +
>  source "drivers/misc/c2port/Kconfig"
>  source "drivers/misc/eeprom/Kconfig"
>  source "drivers/misc/cb710/Kconfig"
> diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
> index af22bbc3d00c..387dd302815c 100644
> --- a/drivers/misc/Makefile
> +++ b/drivers/misc/Makefile
> @@ -58,3 +58,4 @@ obj-$(CONFIG_ASPEED_LPC_SNOOP)	+= aspeed-lpc-snoop.o
>  obj-$(CONFIG_PCI_ENDPOINT_TEST)	+= pci_endpoint_test.o
>  obj-$(CONFIG_OCXL)		+= ocxl/
>  obj-$(CONFIG_MISC_RTSX)		+= cardreader/
> +obj-$(CONFIG_HISI_HIKEY_USB)	+= hisi_hikey_usb.o
> diff --git a/drivers/misc/hisi_hikey_usb.c b/drivers/misc/hisi_hikey_usb.c
> new file mode 100644
> index 000000000000..4965719c99ae
> --- /dev/null
> +++ b/drivers/misc/hisi_hikey_usb.c
> @@ -0,0 +1,319 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * hisi_hikey_usb.c
> + *
> + * Copyright (c) Hisilicon Tech. Co., Ltd. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#include <linux/module.h>
> +#include <linux/kernel.h>
> +#include <linux/slab.h>
> +#include <linux/platform_device.h>
> +#include <linux/gpio.h>
> +#include <linux/of_gpio.h>
> +#include <linux/extcon-provider.h>
> +#include <linux/usb/role.h>
> +
> +#define DEVICE_DRIVER_NAME "hisi_hikey_usb"
> +
> +#define HUB_VBUS_POWER_ON 1
> +#define HUB_VBUS_POWER_OFF 0
> +#define USB_SWITCH_TO_HUB 1
> +#define USB_SWITCH_TO_TYPEC 0
> +
> +#define INVALID_GPIO_VALUE (-1)
> +
> +struct hisi_hikey_usb {
> +	int otg_switch_gpio;
> +	int typec_vbus_gpio;
> +	int typec_vbus_enable_val;
> +	int hub_vbus_gpio;

I think you should use struct gpio_desc and gpiod_*() API with the
gpios.

> +	struct extcon_dev *edev;
> +	struct usb_role_switch *role_sw;
> +};
> +
> +static const unsigned int usb_extcon_cable[] = {
> +	EXTCON_USB,
> +	EXTCON_USB_HOST,
> +	EXTCON_NONE,
> +};
> +
> +static void hub_power_ctrl(struct hisi_hikey_usb *hisi_hikey_usb, int value)
> +{
> +	int gpio = hisi_hikey_usb->hub_vbus_gpio;
> +
> +	if (gpio_is_valid(gpio))
> +		gpio_set_value(gpio, value);
> +}
> +
> +static void usb_switch_ctrl(struct hisi_hikey_usb *hisi_hikey_usb,
> +		int switch_to)
> +{
> +	int gpio = hisi_hikey_usb->otg_switch_gpio;
> +	const char *switch_to_str = (switch_to == USB_SWITCH_TO_HUB) ?
> +		"hub" : "typec";
> +
> +	if (!gpio_is_valid(gpio)) {
> +		pr_err("%s: otg_switch_gpio is err\n", __func__);
> +		return;
> +	}
> +
> +	if (gpio_get_value(gpio) == switch_to) {
> +		pr_info("%s: already switch to %s\n", __func__, switch_to_str);

That kind of prints are really just noise.

> +		return;
> +	}
> +
> +	gpio_direction_output(gpio, switch_to);
> +	pr_info("%s: switch to %s\n", __func__, switch_to_str);

That is also just noise.

> +}
> +
> +static void usb_typec_power_ctrl(struct hisi_hikey_usb *hisi_hikey_usb,
> +		int value)
> +{
> +	int gpio = hisi_hikey_usb->typec_vbus_gpio;
> +
> +	if (!gpio_is_valid(gpio)) {
> +		pr_err("%s: typec power gpio is err\n", __func__);
> +		return;
> +	}
> +
> +	if (gpio_get_value(gpio) == value) {
> +		pr_info("%s: typec power no change\n", __func__);

Ditto.

> +		return;
> +	}
> +
> +	gpio_direction_output(gpio, value);
> +	pr_info("%s: set typec vbus gpio to %d\n", __func__, value);

Ditto.

> +}
> +
> +static int extcon_hisi_pd_set_role(struct device *dev, enum usb_role role)
> +{
> +	struct hisi_hikey_usb *hisi_hikey_usb = dev_get_drvdata(dev);
> +
> +	dev_info(dev, "%s:set usb role to %d\n", __func__, role);
> +	switch (role) {
> +	case USB_ROLE_NONE:
> +		usb_switch_ctrl(hisi_hikey_usb, USB_SWITCH_TO_HUB);
> +		usb_typec_power_ctrl(hisi_hikey_usb,
> +				!hisi_hikey_usb->typec_vbus_enable_val);
> +		hub_power_ctrl(hisi_hikey_usb, HUB_VBUS_POWER_ON);
> +		extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB, false);
> +		extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB_HOST,
> +				true);
> +		break;
> +	case USB_ROLE_HOST:
> +		usb_switch_ctrl(hisi_hikey_usb, USB_SWITCH_TO_TYPEC);
> +		usb_typec_power_ctrl(hisi_hikey_usb,
> +				hisi_hikey_usb->typec_vbus_enable_val);
> +		extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB, false);
> +		extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB_HOST,
> +				true);
> +		break;
> +	case USB_ROLE_DEVICE:
> +		hub_power_ctrl(hisi_hikey_usb, HUB_VBUS_POWER_OFF);
> +		usb_typec_power_ctrl(hisi_hikey_usb,
> +				hisi_hikey_usb->typec_vbus_enable_val);
> +		usb_switch_ctrl(hisi_hikey_usb, USB_SWITCH_TO_TYPEC);
> +		extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB_HOST,
> +				false);
> +		extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB, true);
> +		break;
> +	}

If I understood the above correctly, you are controlling the VBUS
based on the data role, right?

With USB Type-C connectors the power and data roles are separate, so
you should not be doing that.

But since you are controlling the VBUS with a single GPIO, wouldn't it
be easier to just give the Type-C port controller device that GPIO
resources and let the Type-C drivers take care of it? You could add a
"set_vbus" callback to struct tcpci_data and take care of the GPIO in
tcpci_rt1711h.c, or alternatively, just handle it in tcpci.c.

> +	return 0;
> +}
> +
> +static enum usb_role extcon_hisi_pd_get_role(struct device *dev)
> +{
> +	struct hisi_hikey_usb *hisi_hikey_usb = dev_get_drvdata(dev);
> +
> +	return usb_role_switch_get_role(hisi_hikey_usb->role_sw);
> +}
> +
> +static const struct usb_role_switch_desc sw_desc = {
> +	.set = extcon_hisi_pd_set_role,
> +	.get = extcon_hisi_pd_get_role,
> +	.allow_userspace_control = true,
> +};
> +
> +static int hisi_hikey_usb_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct device_node *root = dev->of_node;
> +	struct hisi_hikey_usb *hisi_hikey_usb;
> +	int ret;
> +
> +	hisi_hikey_usb = devm_kzalloc(dev, sizeof(*hisi_hikey_usb), GFP_KERNEL);
> +	if (!hisi_hikey_usb)
> +		return -ENOMEM;
> +
> +	dev_set_name(dev, "hisi_hikey_usb");
> +
> +	hisi_hikey_usb->hub_vbus_gpio = INVALID_GPIO_VALUE;
> +	hisi_hikey_usb->otg_switch_gpio = INVALID_GPIO_VALUE;
> +	hisi_hikey_usb->typec_vbus_gpio = INVALID_GPIO_VALUE;
> +
> +	hisi_hikey_usb->hub_vbus_gpio = of_get_named_gpio(root,
> +			"hub_vdd33_en_gpio", 0);
> +	if (!gpio_is_valid(hisi_hikey_usb->hub_vbus_gpio)) {
> +		pr_err("%s: hub_vbus_gpio is err\n", __func__);
> +		return hisi_hikey_usb->hub_vbus_gpio;
> +	}
> +
> +	ret = gpio_request(hisi_hikey_usb->hub_vbus_gpio, "hub_vbus_int_gpio");
> +	if (ret) {
> +		pr_err("%s: request hub_vbus_gpio err\n", __func__);
> +		hisi_hikey_usb->hub_vbus_gpio = INVALID_GPIO_VALUE;
> +		return ret;
> +	}
> +
> +	ret = gpio_direction_output(hisi_hikey_usb->hub_vbus_gpio,
> +			HUB_VBUS_POWER_ON);
> +	if (ret) {
> +		pr_err("%s: power on hub vbus err\n", __func__);
> +		goto free_gpio1;
> +	}
> +
> +	hisi_hikey_usb->typec_vbus_gpio = of_get_named_gpio(root,
> +		"typc_vbus_int_gpio,typec-gpios", 0);
> +	if (!gpio_is_valid(hisi_hikey_usb->typec_vbus_gpio)) {
> +		pr_err("%s: typec_vbus_gpio is err\n", __func__);
> +		ret = hisi_hikey_usb->typec_vbus_gpio;
> +		goto free_gpio1;
> +	}
> +
> +	ret = gpio_request(hisi_hikey_usb->typec_vbus_gpio,
> +			"typc_vbus_int_gpio");
> +	if (ret) {
> +		pr_err("%s: request typec_vbus_gpio err\n", __func__);
> +		hisi_hikey_usb->typec_vbus_gpio = INVALID_GPIO_VALUE;
> +		goto free_gpio1;
> +	}
> +
> +	ret = of_property_read_u32(root, "typc_vbus_enable_val",
> +				   &hisi_hikey_usb->typec_vbus_enable_val);
> +	if (ret) {
> +		pr_err("%s: typc_vbus_enable_val can't get\n", __func__);
> +		goto free_gpio2;
> +	}
> +
> +	hisi_hikey_usb->typec_vbus_enable_val =
> +		!!hisi_hikey_usb->typec_vbus_enable_val;
> +
> +	ret = gpio_direction_output(hisi_hikey_usb->typec_vbus_gpio,
> +				    hisi_hikey_usb->typec_vbus_enable_val);
> +	if (ret) {
> +		pr_err("%s: power on typec vbus err", __func__);
> +		goto free_gpio2;
> +	}
> +
> +	if (of_device_is_compatible(root, "hisilicon,hikey960_usb")) {

Instead of that kind of checks, isn't it enough to just use optional
gpios?

> +		hisi_hikey_usb->otg_switch_gpio = of_get_named_gpio(root,
> +				"otg_gpio", 0);
> +		if (!gpio_is_valid(hisi_hikey_usb->otg_switch_gpio)) {
> +			pr_info("%s: otg_switch_gpio is err\n", __func__);
> +			goto free_gpio2;
> +		}
> +
> +		ret = gpio_request(hisi_hikey_usb->otg_switch_gpio,
> +				"otg_switch_gpio");
> +		if (ret) {
> +			hisi_hikey_usb->otg_switch_gpio = INVALID_GPIO_VALUE;
> +			pr_err("%s: request typec_vbus_gpio err\n", __func__);
> +			goto free_gpio2;
> +		}
> +	}
> +
> +	hisi_hikey_usb->edev = devm_extcon_dev_allocate(dev, usb_extcon_cable);
> +	if (IS_ERR(hisi_hikey_usb->edev)) {
> +		dev_err(dev, "failed to allocate extcon device\n");
> +		goto free_gpio2;
> +	}
> +
> +	ret = devm_extcon_dev_register(dev, hisi_hikey_usb->edev);
> +	if (ret < 0) {
> +		dev_err(dev, "failed to register extcon device\n");
> +		goto free_gpio2;
> +	}
> +	extcon_set_state(hisi_hikey_usb->edev, EXTCON_USB_HOST, true);

Is the primary purpose for this extcon device to satisfy the DRD code
in dwc3 driver?

> +	hisi_hikey_usb->role_sw = usb_role_switch_register(dev, &sw_desc);
> +	if (IS_ERR(hisi_hikey_usb->role_sw))
> +		goto free_gpio2;

It looks a bit clumsy to me to register both the extcon device and the
mux device, but I'm guessing you need to get a notification in dwc3
driver when the role changes, right? Perhaps we should simply add
notification chain to the role mux structure. That could potentially
allow this kind of code to be organized a bit better.

> +	platform_set_drvdata(pdev, hisi_hikey_usb);
> +
> +	return 0;
> +
> +free_gpio2:
> +	if (gpio_is_valid(hisi_hikey_usb->typec_vbus_gpio)) {
> +		gpio_free(hisi_hikey_usb->typec_vbus_gpio);
> +		hisi_hikey_usb->typec_vbus_gpio = INVALID_GPIO_VALUE;
> +	}
> +
> +free_gpio1:
> +	if (gpio_is_valid(hisi_hikey_usb->hub_vbus_gpio)) {
> +		gpio_free(hisi_hikey_usb->hub_vbus_gpio);
> +		hisi_hikey_usb->hub_vbus_gpio = INVALID_GPIO_VALUE;
> +	}
> +
> +	return ret;
> +}
> +
> +static int  hisi_hikey_usb_remove(struct platform_device *pdev)
> +{
> +	struct hisi_hikey_usb *hisi_hikey_usb = platform_get_drvdata(pdev);
> +
> +	if (gpio_is_valid(hisi_hikey_usb->otg_switch_gpio)) {
> +		gpio_free(hisi_hikey_usb->otg_switch_gpio);
> +		hisi_hikey_usb->otg_switch_gpio = INVALID_GPIO_VALUE;
> +	}
> +
> +	if (gpio_is_valid(hisi_hikey_usb->typec_vbus_gpio)) {
> +		gpio_free(hisi_hikey_usb->typec_vbus_gpio);
> +		hisi_hikey_usb->typec_vbus_gpio = INVALID_GPIO_VALUE;
> +	}
> +
> +	if (gpio_is_valid(hisi_hikey_usb->hub_vbus_gpio)) {
> +		gpio_free(hisi_hikey_usb->hub_vbus_gpio);
> +		hisi_hikey_usb->hub_vbus_gpio = INVALID_GPIO_VALUE;
> +	}
> +
> +	usb_role_switch_unregister(hisi_hikey_usb->role_sw);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id id_table_hisi_hikey_usb[] = {
> +	{.compatible = "hisilicon,gpio_hubv1"},
> +	{.compatible = "hisilicon,hikey960_usb"},
> +	{}
> +};
> +
> +static struct platform_driver  hisi_hikey_usb_driver = {
> +	.probe = hisi_hikey_usb_probe,
> +	.remove = hisi_hikey_usb_remove,
> +	.driver = {
> +		.name = DEVICE_DRIVER_NAME,
> +		.of_match_table = of_match_ptr(id_table_hisi_hikey_usb),
> +
> +	},
> +};
> +
> +module_platform_driver(hisi_hikey_usb_driver);
> +
> +MODULE_AUTHOR("Yu Chen <chenyu56@huawei.com>");
> +MODULE_DESCRIPTION("Driver Support for USB functionality of Hikey");
> +MODULE_LICENSE("GPL v2");
> -- 
> 2.15.0-rc2

I think you have too many things integrated into this one driver. IMO
it would at least be better to just let the Type-C port driver take
care of VBUS like I mentioned above. I'm also wondering if it would
make sense to handle the role switch and the "hub" in their own
drivers, but I don't know enough about your platform at this point to
say for sure.


br,

-- 
heikki

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

* Re: [PATCH 07/10] hikey960: Support usb functionality of Hikey960
  2018-10-29 14:30   ` Heikki Krogerus
@ 2018-10-30  2:50     ` Chen Yu
  2018-10-30 10:16       ` Heikki Krogerus
  0 siblings, 1 reply; 23+ messages in thread
From: Chen Yu @ 2018-10-30  2:50 UTC (permalink / raw)
  To: Heikki Krogerus
  Cc: wangbinghui, linux-usb, devicetree, linux-kernel, suzhuangluan,
	kongfei, Arnd Bergmann, Greg Kroah-Hartman, John Stultz

Hi


On 2018/10/29 22:30, Heikki Krogerus wrote:
> Hi,
>
> On Sat, Oct 27, 2018 at 05:58:17PM +0800, Yu Chen wrote:
>> This driver handles usb hub power on and typeC port event of HiKey960 board:
>> 1)DP&DM switching between usb hub and typeC port base on typeC port
>> state
> By "hub" do you mean you have some kind of an integrated USB hub on
> your SoC?
No. The "hub" is on the board of HiKey960 development platform.

>> 2)Control power of usb hub on Hikey960
>> 3)Control vbus of typeC port
>> 4)Handle typeC port event to switch data role
> Is your role switch a discrete component, or something part of the SoC?
Yes, the dwc3 usb controller of the SoC needs switch between device and host
mode based on the typeC port event.

>
>> +#define USB_SWITCH_TO_HUB 1
>> +#define USB_SWITCH_TO_TYPEC 0
>> +
>> +#define INVALID_GPIO_VALUE (-1)
>> +
>> +struct hisi_hikey_usb {
>> +	int otg_switch_gpio;
>> +	int typec_vbus_gpio;
>> +	int typec_vbus_enable_val;
>> +	int hub_vbus_gpio;
> I think you should use struct gpio_desc and gpiod_*() API with the
> gpios.

You are right, I will fix that. Thanks!
>> +	struct extcon_dev *edev;
>> +	struct usb_role_switch *role_sw;
>> +};
>> +
>> +static const unsigned int usb_extcon_cable[] = {
>> +	EXTCON_USB,
>> +	EXTCON_USB_HOST,
>> +	EXTCON_NONE,
>> +};
>> +
>> +static void hub_power_ctrl(struct hisi_hikey_usb *hisi_hikey_usb, int value)
>> +{
>> +	int gpio = hisi_hikey_usb->hub_vbus_gpio;
>> +
>> +	if (gpio_is_valid(gpio))
>> +		gpio_set_value(gpio, value);
>> +}
>> +
>> +static void usb_switch_ctrl(struct hisi_hikey_usb *hisi_hikey_usb,
>> +		int switch_to)
>> +{
>> +	int gpio = hisi_hikey_usb->otg_switch_gpio;
>> +	const char *switch_to_str = (switch_to == USB_SWITCH_TO_HUB) ?
>> +		"hub" : "typec";
>> +
>> +	if (!gpio_is_valid(gpio)) {
>> +		pr_err("%s: otg_switch_gpio is err\n", __func__);
>> +		return;
>> +	}
>> +
>> +	if (gpio_get_value(gpio) == switch_to) {
>> +		pr_info("%s: already switch to %s\n", __func__, switch_to_str);
> That kind of prints are really just noise.
>
>> +		return;
>> +	}
>> +
>> +	gpio_direction_output(gpio, switch_to);
>> +	pr_info("%s: switch to %s\n", __func__, switch_to_str);
> That is also just noise.
>
>> +}
>> +
>> +static void usb_typec_power_ctrl(struct hisi_hikey_usb *hisi_hikey_usb,
>> +		int value)
>> +{
>> +	int gpio = hisi_hikey_usb->typec_vbus_gpio;
>> +
>> +	if (!gpio_is_valid(gpio)) {
>> +		pr_err("%s: typec power gpio is err\n", __func__);
>> +		return;
>> +	}
>> +
>> +	if (gpio_get_value(gpio) == value) {
>> +		pr_info("%s: typec power no change\n", __func__);
> Ditto.
>
>> +		return;
>> +	}
>> +
>> +	gpio_direction_output(gpio, value);
>> +	pr_info("%s: set typec vbus gpio to %d\n", __func__, value);
> Ditto.
>
>> +}
>> +
>> +static int extcon_hisi_pd_set_role(struct device *dev, enum usb_role role)
>> +{
>> +	struct hisi_hikey_usb *hisi_hikey_usb = dev_get_drvdata(dev);
>> +
>> +	dev_info(dev, "%s:set usb role to %d\n", __func__, role);
>> +	switch (role) {
>> +	case USB_ROLE_NONE:
>> +		usb_switch_ctrl(hisi_hikey_usb, USB_SWITCH_TO_HUB);
>> +		usb_typec_power_ctrl(hisi_hikey_usb,
>> +				!hisi_hikey_usb->typec_vbus_enable_val);
>> +		hub_power_ctrl(hisi_hikey_usb, HUB_VBUS_POWER_ON);
>> +		extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB, false);
>> +		extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB_HOST,
>> +				true);
>> +		break;
>> +	case USB_ROLE_HOST:
>> +		usb_switch_ctrl(hisi_hikey_usb, USB_SWITCH_TO_TYPEC);
>> +		usb_typec_power_ctrl(hisi_hikey_usb,
>> +				hisi_hikey_usb->typec_vbus_enable_val);
>> +		extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB, false);
>> +		extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB_HOST,
>> +				true);
>> +		break;
>> +	case USB_ROLE_DEVICE:
>> +		hub_power_ctrl(hisi_hikey_usb, HUB_VBUS_POWER_OFF);
>> +		usb_typec_power_ctrl(hisi_hikey_usb,
>> +				hisi_hikey_usb->typec_vbus_enable_val);
>> +		usb_switch_ctrl(hisi_hikey_usb, USB_SWITCH_TO_TYPEC);
>> +		extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB_HOST,
>> +				false);
>> +		extcon_set_state_sync(hisi_hikey_usb->edev, EXTCON_USB, true);
>> +		break;
>> +	}
> If I understood the above correctly, you are controlling the VBUS
> based on the data role, right?
Yes, you are right.
> With USB Type-C connectors the power and data roles are separate, so
> you should not be doing that.
>
> But since you are controlling the VBUS with a single GPIO, wouldn't it
> be easier to just give the Type-C port controller device that GPIO
> resources and let the Type-C drivers take care of it? You could add a
> "set_vbus" callback to struct tcpci_data and take care of the GPIO in
> tcpci_rt1711h.c, or alternatively, just handle it in tcpci.c.
I will try to implement the "set_vbus" callback.

>> +	return 0;
>> +}
>> +
>> +static enum usb_role extcon_hisi_pd_get_role(struct device *dev)
>> +{
>> +	struct hisi_hikey_usb *hisi_hikey_usb = dev_get_drvdata(dev);
>> +
>> +	return usb_role_switch_get_role(hisi_hikey_usb->role_sw);
>> +}
>> +
>> +static const struct usb_role_switch_desc sw_desc = {
>> +	.set = extcon_hisi_pd_set_role,
>> +	.get = extcon_hisi_pd_get_role,
>> +	.allow_userspace_control = true,
>> +};
>> +
>> +static int hisi_hikey_usb_probe(struct platform_device *pdev)
>> +{
>> +	struct device *dev = &pdev->dev;
>> +	struct device_node *root = dev->of_node;
>> +	struct hisi_hikey_usb *hisi_hikey_usb;
>> +	int ret;
>> +
>> +	hisi_hikey_usb = devm_kzalloc(dev, sizeof(*hisi_hikey_usb), GFP_KERNEL);
>> +	if (!hisi_hikey_usb)
>> +		return -ENOMEM;
>> +
>> +	dev_set_name(dev, "hisi_hikey_usb");
>> +
>> +	hisi_hikey_usb->hub_vbus_gpio = INVALID_GPIO_VALUE;
>> +	hisi_hikey_usb->otg_switch_gpio = INVALID_GPIO_VALUE;
>> +	hisi_hikey_usb->typec_vbus_gpio = INVALID_GPIO_VALUE;
>> +
>> +	hisi_hikey_usb->hub_vbus_gpio = of_get_named_gpio(root,
>> +			"hub_vdd33_en_gpio", 0);
>> +	if (!gpio_is_valid(hisi_hikey_usb->hub_vbus_gpio)) {
>> +		pr_err("%s: hub_vbus_gpio is err\n", __func__);
>> +		return hisi_hikey_usb->hub_vbus_gpio;
>> +	}
>> +
>> +	ret = gpio_request(hisi_hikey_usb->hub_vbus_gpio, "hub_vbus_int_gpio");
>> +	if (ret) {
>> +		pr_err("%s: request hub_vbus_gpio err\n", __func__);
>> +		hisi_hikey_usb->hub_vbus_gpio = INVALID_GPIO_VALUE;
>> +		return ret;
>> +	}
>> +
>> +	ret = gpio_direction_output(hisi_hikey_usb->hub_vbus_gpio,
>> +			HUB_VBUS_POWER_ON);
>> +	if (ret) {
>> +		pr_err("%s: power on hub vbus err\n", __func__);
>> +		goto free_gpio1;
>> +	}
>> +
>> +	hisi_hikey_usb->typec_vbus_gpio = of_get_named_gpio(root,
>> +		"typc_vbus_int_gpio,typec-gpios", 0);
>> +	if (!gpio_is_valid(hisi_hikey_usb->typec_vbus_gpio)) {
>> +		pr_err("%s: typec_vbus_gpio is err\n", __func__);
>> +		ret = hisi_hikey_usb->typec_vbus_gpio;
>> +		goto free_gpio1;
>> +	}
>> +
>> +	ret = gpio_request(hisi_hikey_usb->typec_vbus_gpio,
>> +			"typc_vbus_int_gpio");
>> +	if (ret) {
>> +		pr_err("%s: request typec_vbus_gpio err\n", __func__);
>> +		hisi_hikey_usb->typec_vbus_gpio = INVALID_GPIO_VALUE;
>> +		goto free_gpio1;
>> +	}
>> +
>> +	ret = of_property_read_u32(root, "typc_vbus_enable_val",
>> +				   &hisi_hikey_usb->typec_vbus_enable_val);
>> +	if (ret) {
>> +		pr_err("%s: typc_vbus_enable_val can't get\n", __func__);
>> +		goto free_gpio2;
>> +	}
>> +
>> +	hisi_hikey_usb->typec_vbus_enable_val =
>> +		!!hisi_hikey_usb->typec_vbus_enable_val;
>> +
>> +	ret = gpio_direction_output(hisi_hikey_usb->typec_vbus_gpio,
>> +				    hisi_hikey_usb->typec_vbus_enable_val);
>> +	if (ret) {
>> +		pr_err("%s: power on typec vbus err", __func__);
>> +		goto free_gpio2;
>> +	}
>> +
>> +	if (of_device_is_compatible(root, "hisilicon,hikey960_usb")) {
> Instead of that kind of checks, isn't it enough to just use optional
> gpios?
>
>> +		hisi_hikey_usb->otg_switch_gpio = of_get_named_gpio(root,
>> +				"otg_gpio", 0);
>> +		if (!gpio_is_valid(hisi_hikey_usb->otg_switch_gpio)) {
>> +			pr_info("%s: otg_switch_gpio is err\n", __func__);
>> +			goto free_gpio2;
>> +		}
>> +
>> +		ret = gpio_request(hisi_hikey_usb->otg_switch_gpio,
>> +				"otg_switch_gpio");
>> +		if (ret) {
>> +			hisi_hikey_usb->otg_switch_gpio = INVALID_GPIO_VALUE;
>> +			pr_err("%s: request typec_vbus_gpio err\n", __func__);
>> +			goto free_gpio2;
>> +		}
>> +	}
>> +
>> +	hisi_hikey_usb->edev = devm_extcon_dev_allocate(dev, usb_extcon_cable);
>> +	if (IS_ERR(hisi_hikey_usb->edev)) {
>> +		dev_err(dev, "failed to allocate extcon device\n");
>> +		goto free_gpio2;
>> +	}
>> +
>> +	ret = devm_extcon_dev_register(dev, hisi_hikey_usb->edev);
>> +	if (ret < 0) {
>> +		dev_err(dev, "failed to register extcon device\n");
>> +		goto free_gpio2;
>> +	}
>> +	extcon_set_state(hisi_hikey_usb->edev, EXTCON_USB_HOST, true);
> Is the primary purpose for this extcon device to satisfy the DRD code
> in dwc3 driver?
Yes. I need it to switch mode of dwc3.
>> +	hisi_hikey_usb->role_sw = usb_role_switch_register(dev, &sw_desc);
>> +	if (IS_ERR(hisi_hikey_usb->role_sw))
>> +		goto free_gpio2;
> It looks a bit clumsy to me to register both the extcon device and the
> mux device, but I'm guessing you need to get a notification in dwc3
> driver when the role changes, right? Perhaps we should simply add
> notification chain to the role mux structure. That could potentially
> allow this kind of code to be organized a bit better.
>
>> +	platform_set_drvdata(pdev, hisi_hikey_usb);
>> +
>> +	return 0;
>> +
>> +free_gpio2:
>> +	if (gpio_is_valid(hisi_hikey_usb->typec_vbus_gpio)) {
>> +		gpio_free(hisi_hikey_usb->typec_vbus_gpio);
>> +		hisi_hikey_usb->typec_vbus_gpio = INVALID_GPIO_VALUE;
>> +	}
>> +
>> +free_gpio1:
>> +	if (gpio_is_valid(hisi_hikey_usb->hub_vbus_gpio)) {
>> +		gpio_free(hisi_hikey_usb->hub_vbus_gpio);
>> +		hisi_hikey_usb->hub_vbus_gpio = INVALID_GPIO_VALUE;
>> +	}
>> +
>> +	return ret;
>> +}
>> +
>> +static int  hisi_hikey_usb_remove(struct platform_device *pdev)
>> +{
>> +	struct hisi_hikey_usb *hisi_hikey_usb = platform_get_drvdata(pdev);
>> +
>> +	if (gpio_is_valid(hisi_hikey_usb->otg_switch_gpio)) {
>> +		gpio_free(hisi_hikey_usb->otg_switch_gpio);
>> +		hisi_hikey_usb->otg_switch_gpio = INVALID_GPIO_VALUE;
>> +	}
>> +
>> +	if (gpio_is_valid(hisi_hikey_usb->typec_vbus_gpio)) {
>> +		gpio_free(hisi_hikey_usb->typec_vbus_gpio);
>> +		hisi_hikey_usb->typec_vbus_gpio = INVALID_GPIO_VALUE;
>> +	}
>> +
>> +	if (gpio_is_valid(hisi_hikey_usb->hub_vbus_gpio)) {
>> +		gpio_free(hisi_hikey_usb->hub_vbus_gpio);
>> +		hisi_hikey_usb->hub_vbus_gpio = INVALID_GPIO_VALUE;
>> +	}
>> +
>> +	usb_role_switch_unregister(hisi_hikey_usb->role_sw);
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct of_device_id id_table_hisi_hikey_usb[] = {
>> +	{.compatible = "hisilicon,gpio_hubv1"},
>> +	{.compatible = "hisilicon,hikey960_usb"},
>> +	{}
>> +};
>> +
>> +static struct platform_driver  hisi_hikey_usb_driver = {
>> +	.probe = hisi_hikey_usb_probe,
>> +	.remove = hisi_hikey_usb_remove,
>> +	.driver = {
>> +		.name = DEVICE_DRIVER_NAME,
>> +		.of_match_table = of_match_ptr(id_table_hisi_hikey_usb),
>> +
>> +	},
>> +};
>> +
>> +module_platform_driver(hisi_hikey_usb_driver);
>> +
>> +MODULE_AUTHOR("Yu Chen <chenyu56@huawei.com>");
>> +MODULE_DESCRIPTION("Driver Support for USB functionality of Hikey");
>> +MODULE_LICENSE("GPL v2");
>> -- 
>> 2.15.0-rc2
> I think you have too many things integrated into this one driver. IMO
> it would at least be better to just let the Type-C port driver take
> care of VBUS like I mentioned above. I'm also wondering if it would
> make sense to handle the role switch and the "hub" in their own
> drivers, but I don't know enough about your platform at this point to
> say for sure.

Thanks for your advice! The HiKey 960 development platform is based around the Huawei Kirin 960.
The Hikey960 Development Board supports three USB host port via a USB hub (U1803 USB5734).
The Hikey960 Development Board also implements a USB2.0 typeC OTG port. 
The Dp and Dm of Soc can be switched between the typeC port and the USB hub.
If there is no cable on the typeC port, then dwc3 core of Soc will be switch to host mode and the
driver of this patch will switch Dp and Dp to the hub. The driver also power on the hub in the meantime.
>
> br,
>



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

* Re: [PATCH 07/10] hikey960: Support usb functionality of Hikey960
  2018-10-30  2:50     ` Chen Yu
@ 2018-10-30 10:16       ` Heikki Krogerus
  0 siblings, 0 replies; 23+ messages in thread
From: Heikki Krogerus @ 2018-10-30 10:16 UTC (permalink / raw)
  To: Chen Yu
  Cc: wangbinghui, linux-usb, devicetree, linux-kernel, suzhuangluan,
	kongfei, Arnd Bergmann, Greg Kroah-Hartman, John Stultz

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

On Tue, Oct 30, 2018 at 10:50:22AM +0800, Chen Yu wrote:
> > I think you have too many things integrated into this one driver. IMO
> > it would at least be better to just let the Type-C port driver take
> > care of VBUS like I mentioned above. I'm also wondering if it would
> > make sense to handle the role switch and the "hub" in their own
> > drivers, but I don't know enough about your platform at this point to
> > say for sure.
> 
> Thanks for your advice! The HiKey 960 development platform is based around the Huawei Kirin 960.
> The Hikey960 Development Board supports three USB host port via a USB hub (U1803 USB5734).
> The Hikey960 Development Board also implements a USB2.0 typeC OTG port.??
> The Dp and Dm of Soc can be switched between the typeC port and the USB hub.
> If there is no cable on the typeC port, then dwc3 core of Soc will be switch to host mode and the
> driver of this patch will switch Dp and Dp to the hub. The driver also power on the hub in the meantime.

Thank you for the explanation. I got the picture now. I realized that
there is some online information for this board:
https://www.96boards.org/documentation/consumer/hikey/hikey960/hardware-docs/hardware-user-manual.md.html#usb-ports

So that mux is actually _not_ switching between the host and device
modes, but instead, it's switching between Type-C and Type-A
connectors (I'm skipping the hub, as it's irrelevant from the PoW of
the mux), so I've misunderstood. And yes, you did say that it is
switching between connectors in the commit message, but I got confused
because you are registers a role switch.

I don't think you should register a role switch from this driver. This
driver is not really representing USB role switch. The mux on this
board is something else. Instead you should register the role switch
from the dwc3 drd code. That is the part that is representing the role
switch here. I actually think that we should do that in any case. The
dwc3 drd code should always register a role switch.

We can solve the problem of getting the role change events in this
driver by adding notification chain to struct usb_role_switch (check
the attached diff). You would then just need to call
usb_role_switch_get() and usb_role_switch_register_notifier(), and
wait for those notifications. The extcon device does not serve any
purpose anymore.

This driver would continue to take care of the hub powering and the
mux, and also the VBUS like before.


br,

-- 
heikki

[-- Attachment #2: roles.diff --]
[-- Type: text/plain, Size: 1662 bytes --]

diff --git a/drivers/usb/common/roles.c b/drivers/usb/common/roles.c
index bb52e006d203..2881777c16e5 100644
--- a/drivers/usb/common/roles.c
+++ b/drivers/usb/common/roles.c
@@ -20,6 +20,7 @@ struct usb_role_switch {
 	struct device dev;
 	struct mutex lock; /* device lock*/
 	enum usb_role role;
+	struct blocking_notifier_head nh;
 
 	/* From descriptor */
 	struct device *usb2_port;
@@ -49,8 +50,10 @@ int usb_role_switch_set_role(struct usb_role_switch *sw, enum usb_role role)
 	mutex_lock(&sw->lock);
 
 	ret = sw->set(sw->dev.parent, role);
-	if (!ret)
+	if (!ret) {
 		sw->role = role;
+		blocking_notifier_call_chain(&sw->nh, role, NULL);
+	}
 
 	mutex_unlock(&sw->lock);
 
@@ -110,6 +113,20 @@ static void *usb_role_switch_match(struct device_connection *con, int ep,
 	return dev ? to_role_switch(dev) : ERR_PTR(-EPROBE_DEFER);
 }
 
+int usb_role_switch_register_notifier(struct usb_role_switch *sw,
+				      struct notifier_block *nb)
+{
+	return blocking_notifier_chain_register(&sw->nh, nb);
+}
+EXPORT_SYMBOL_GPL(usb_role_switch_register_notifier);
+
+int usb_role_switch_unregister_notifier(struct usb_role_switch *sw,
+					struct notifier_block *nb)
+{
+	return blocking_notifier_chain_unregister(&sw->nh, nb);
+}
+EXPORT_SYMBOL_GPL(usb_role_switch_unregister_notifier);
+
 /**
  * usb_role_switch_get - Find USB role switch linked with the caller
  * @dev: The caller device
@@ -267,6 +284,7 @@ usb_role_switch_register(struct device *parent,
 		return ERR_PTR(-ENOMEM);
 
 	mutex_init(&sw->lock);
+	BLOCKING_INIT_NOTIFIER_HEAD(&sw->nh);
 
 	sw->allow_userspace_control = desc->allow_userspace_control;
 	sw->usb2_port = desc->usb2_port;

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

* Re: [PATCH 06/10] phy: Add usb phy support for hi3660 Soc of Hisilicon
  2018-10-27  9:58 ` [PATCH 06/10] phy: Add usb phy support for hi3660 Soc of Hisilicon Yu Chen
@ 2018-11-12  9:09   ` Kishon Vijay Abraham I
  0 siblings, 0 replies; 23+ messages in thread
From: Kishon Vijay Abraham I @ 2018-11-12  9:09 UTC (permalink / raw)
  To: Yu Chen, linux-usb, devicetree, linux-kernel
  Cc: suzhuangluan, kongfei, David S. Miller, Greg Kroah-Hartman,
	Mauro Carvalho Chehab, Andrew Morton, Arnd Bergmann, Shawn Guo,
	Pengcheng Li, Jianguo Sun, Masahiro Yamada, Jiancheng Xue,
	John Stultz, Binghui Wang

Hi,

On 27/10/18 3:28 PM, Yu Chen wrote:
> This driver handles usb phy power on and shutdown for hi3660 Soc of
> Hisilicon.
> 
> Cc: Kishon Vijay Abraham I <kishon@ti.com>
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Shawn Guo <shawnguo@kernel.org>
> Cc: Pengcheng Li <lpc.li@hisilicon.com>
> Cc: Jianguo Sun <sunjianguo1@huawei.com>
> Cc: Masahiro Yamada <yamada.masahiro@socionext.com>
> Cc: Jiancheng Xue <xuejiancheng@hisilicon.com>
> Cc: John Stultz <john.stultz@linaro.org>
> Cc: Binghui Wang <wangbinghui@hisilicon.com>
> Signed-off-by: Yu Chen <chenyu56@huawei.com>
> ---
>  MAINTAINERS                             |   2 +
>  drivers/phy/hisilicon/Kconfig           |  10 ++
>  drivers/phy/hisilicon/Makefile          |   1 +
>  drivers/phy/hisilicon/phy-hi3660-usb3.c | 254 ++++++++++++++++++++++++++++++++
>  4 files changed, 267 insertions(+)
>  create mode 100644 drivers/phy/hisilicon/phy-hi3660-usb3.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index e485449f7811..7adf167588ee 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -15294,7 +15294,9 @@ M:	Binghui Wang <wangbinghui@hisilicon.com>
>  L:	linux-usb@vger.kernel.org
>  S:	Maintained
>  F:	Documentation/devicetree/bindings/usb/dwc3-hisi.txt
> +F:	Documentation/devicetree/bindings/phy/phy-hi3660-usb3.txt
>  F:	drivers/usb/dwc3/dwc3-hisi.c
> +F:	drivers/phy/hisilicon/phy-hi3660-usb3.c
>  
>  USB ISP116X DRIVER
>  M:	Olav Kongas <ok@artecdesign.ee>
> diff --git a/drivers/phy/hisilicon/Kconfig b/drivers/phy/hisilicon/Kconfig
> index b40ee54a1a50..3c142f08987c 100644
> --- a/drivers/phy/hisilicon/Kconfig
> +++ b/drivers/phy/hisilicon/Kconfig
> @@ -12,6 +12,16 @@ config PHY_HI6220_USB
>  
>  	  To compile this driver as a module, choose M here.
>  
> +config PHY_HI3660_USB
> +	tristate "hi3660 USB PHY support"
> +	depends on (ARCH_HISI && ARM64) || COMPILE_TEST
> +	select GENERIC_PHY
> +	select MFD_SYSCON
> +	help
> +	  Enable this to support the HISILICON HI3660 USB PHY.
> +
> +	  To compile this driver as a module, choose M here.
> +
>  config PHY_HISTB_COMBPHY
>  	tristate "HiSilicon STB SoCs COMBPHY support"
>  	depends on (ARCH_HISI && ARM64) || COMPILE_TEST
> diff --git a/drivers/phy/hisilicon/Makefile b/drivers/phy/hisilicon/Makefile
> index f662a4fe18d8..75ba64e2faf8 100644
> --- a/drivers/phy/hisilicon/Makefile
> +++ b/drivers/phy/hisilicon/Makefile
> @@ -1,4 +1,5 @@
>  obj-$(CONFIG_PHY_HI6220_USB)		+= phy-hi6220-usb.o
> +obj-$(CONFIG_PHY_HI3660_USB)		+= phy-hi3660-usb3.o
>  obj-$(CONFIG_PHY_HISTB_COMBPHY)		+= phy-histb-combphy.o
>  obj-$(CONFIG_PHY_HISI_INNO_USB2)	+= phy-hisi-inno-usb2.o
>  obj-$(CONFIG_PHY_HIX5HD2_SATA)		+= phy-hix5hd2-sata.o
> diff --git a/drivers/phy/hisilicon/phy-hi3660-usb3.c b/drivers/phy/hisilicon/phy-hi3660-usb3.c
> new file mode 100644
> index 000000000000..041c542750e2
> --- /dev/null
> +++ b/drivers/phy/hisilicon/phy-hi3660-usb3.c
> @@ -0,0 +1,254 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Phy provider for USB 3.0 controller on HiSilicon 3660 platform
> + *
> + * Copyright (C) 2017-2018 Hilisicon Electronics Co., Ltd.
> + *		http://www.huawei.com
> + *
> + * Authors: Yu Chen <chenyu56@huawei.com>
> + *
> + * This program is free software: you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2  of
> + * the License as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */

This license text doesn't have to added explicitly. It should be already
governed by SPDX line.
> +
> +#include <linux/kernel.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/phy/phy.h>
> +#include <linux/regmap.h>
> +
> +#define PERI_CRG_CLK_EN4			(0x40)
> +#define PERI_CRG_CLK_DIS4			(0x44)
> +#define GT_CLK_USB3OTG_REF			BIT(0)
> +#define GT_ACLK_USB3OTG				BIT(1)
> +
> +#define PERI_CRG_RSTEN4				(0x90)
> +#define PERI_CRG_RSTDIS4			(0x94)
> +#define IP_RST_USB3OTGPHY_POR			BIT(3)
> +#define IP_RST_USB3OTG				BIT(5)
> +
> +#define PERI_CRG_ISODIS				(0x148)
> +#define USB_REFCLK_ISO_EN			BIT(25)
> +
> +#define PCTRL_PERI_CTRL3			(0x10)
> +#define PCTRL_PERI_CTRL3_MSK_START		(16)
> +#define USB_TCXO_EN				BIT(1)
> +
> +#define PCTRL_PERI_CTRL24			(0x64)
> +#define SC_CLK_USB3PHY_3MUX1_SEL		BIT(25)
> +
> +#define USBOTG3_CTRL0				(0x00)
> +#define SC_USB3PHY_ABB_GT_EN			BIT(15)
> +
> +#define USBOTG3_CTRL2				(0x08)
> +#define USBOTG3CTRL2_POWERDOWN_HSP		BIT(0)
> +#define USBOTG3CTRL2_POWERDOWN_SSP		BIT(1)
> +
> +#define USBOTG3_CTRL3				(0x0C)
> +#define USBOTG3_CTRL3_VBUSVLDEXT		BIT(6)
> +#define USBOTG3_CTRL3_VBUSVLDEXTSEL		BIT(5)
> +
> +#define USBOTG3_CTRL4				(0x10)
> +
> +#define USBOTG3_CTRL7				(0x1c)
> +#define REF_SSP_EN				BIT(16)
> +
> +#define HI3660_USB_DEFAULT_PHY_PARAM		(0x1c466e3)
> +
> +struct hi3660_priv {
> +	struct device *dev;
> +	struct regmap *peri_crg;
> +	struct regmap *pctrl;
> +	struct regmap *otg_bc;
> +	u32 eye_diagram_param;
> +
> +	u32 peri_crg_offset;
> +	u32 pctrl_offset;
> +	u32 otg_bc_offset;
> +};
> +
> +static int hi3660_phy_init(struct phy *phy)
> +{
> +	struct hi3660_priv *priv = phy_get_drvdata(phy);
> +	u32 val, mask;
> +	int ret;
> +
> +	/* usb refclk iso disable */
> +	ret = regmap_write(priv->peri_crg, PERI_CRG_ISODIS, USB_REFCLK_ISO_EN);
> +	if (ret)
> +		goto out;
> +
> +	/* enable usb_tcxo_en */
> +	val = USB_TCXO_EN | (USB_TCXO_EN << PCTRL_PERI_CTRL3_MSK_START);
> +	ret = regmap_write(priv->pctrl, PCTRL_PERI_CTRL3, val);
> +	if (ret)
> +		goto out;
> +
> +	/* select usbphy clk from abb */
> +	mask = SC_CLK_USB3PHY_3MUX1_SEL;

Shouldn't we use clock API's for enabling/selecting clocks?
> +	ret = regmap_update_bits(priv->pctrl, PCTRL_PERI_CTRL24, mask, 0);
> +	if (ret)
> +		goto out;
> +
> +	/* assert phy */
> +	val = IP_RST_USB3OTGPHY_POR | IP_RST_USB3OTG;
> +	ret = regmap_write(priv->peri_crg, PERI_CRG_RSTEN4, val);
> +	if (ret)
> +		goto out;
> +
> +	/* enable phy ref clk */
> +	val = SC_USB3PHY_ABB_GT_EN;
> +	mask = val;
> +	ret = regmap_update_bits(priv->otg_bc, USBOTG3_CTRL0, mask, val);
> +	if (ret)
> +		goto out;
> +
> +	val = REF_SSP_EN;
> +	mask = val;
> +	ret = regmap_update_bits(priv->otg_bc, USBOTG3_CTRL7, mask, val);
> +	if (ret)
> +		goto out;
> +
> +	/* exit from IDDQ mode */
> +	mask = USBOTG3CTRL2_POWERDOWN_HSP | USBOTG3CTRL2_POWERDOWN_SSP;
> +	ret = regmap_update_bits(priv->otg_bc, USBOTG3_CTRL2, mask, 0);
> +	if (ret)
> +		goto out;
> +
> +	udelay(100);

Please add a comment for this delay. Does the HW manual states that or it's a
result of experimentation.

Also according to timers/timers-howto.txt, it's preferable to use usleep_range
for 10us - 20ms.
> +
> +	/* deassert phy */
> +	val = IP_RST_USB3OTGPHY_POR | IP_RST_USB3OTG;
> +	ret = regmap_write(priv->peri_crg, PERI_CRG_RSTDIS4, val);
> +	if (ret)
> +		goto out;
> +
> +	usleep_range(10000, 15000);

Add a comment for this delay.
> +
> +	/* fake vbus valid signal */
> +	val = USBOTG3_CTRL3_VBUSVLDEXT | USBOTG3_CTRL3_VBUSVLDEXTSEL;
> +	mask = val;
> +	ret = regmap_update_bits(priv->otg_bc, USBOTG3_CTRL3, mask, val);
> +	if (ret)
> +		goto out;
> +
> +	udelay(100);

Same comment here.

Thanks
Kishon

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

* Re: [PATCH 01/10] dt-bindings: usb: add support for dwc3 controller on HiSilicon SoCs
       [not found]   ` <20181112160241.GA14074@bogus>
@ 2018-11-17  2:29     ` Chen Yu
  2018-12-03 16:01       ` Rob Herring
  0 siblings, 1 reply; 23+ messages in thread
From: Chen Yu @ 2018-11-17  2:29 UTC (permalink / raw)
  To: Rob Herring
  Cc: wangbinghui, linux-usb, devicetree, linux-kernel, suzhuangluan,
	kongfei, Greg Kroah-Hartman, Mark Rutland, John Stultz

Hi,

On 2018/11/13 0:02, Rob Herring wrote:
> On Sat, Oct 27, 2018 at 05:58:11PM +0800, Yu Chen wrote:
>> This patch adds binding descriptions to support the dwc3 controller
>> on HiSilicon SoCs and boards like the HiKey960.
>>
>> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>> Cc: Rob Herring <robh+dt@kernel.org>
>> Cc: Mark Rutland <mark.rutland@arm.com>
>> Cc: John Stultz <john.stultz@linaro.org>
>> Signed-off-by: Yu Chen <chenyu56@huawei.com>
>> ---
>>  .../devicetree/bindings/usb/dwc3-hisi.txt          | 53 ++++++++++++++++++++++
>>  1 file changed, 53 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/usb/dwc3-hisi.txt
>>
>> diff --git a/Documentation/devicetree/bindings/usb/dwc3-hisi.txt b/Documentation/devicetree/bindings/usb/dwc3-hisi.txt
>> new file mode 100644
>> index 000000000000..e715e7b1c324
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/usb/dwc3-hisi.txt
>> @@ -0,0 +1,53 @@
>> +HiSilicon DWC3 USB SoC controller
>> +
>> +This file documents the parameters for the dwc3-hisi driver.
>> +
>> +Required properties:
>> +- compatible:	should be "hisilicon,hi3660-dwc3"
>> +- clocks:	A list of phandle + clock-specifier pairs for the
>> +		clocks listed in clock-names
>> +- clock-names:	Specify clock names
>> +- resets:	list of phandle and reset specifier pairs.
>> +
>> +Sub-nodes:
>> +The dwc3 core should be added as subnode to HiSilicon DWC3 as shown in the
>> +example below. The DT binding details of dwc3 can be found in:
>> +Documentation/devicetree/bindings/usb/dwc3.txt
> 
> If you only have clocks and resets and no glue registers, then you 
> don't need a sub-node. Just make the controller one node.
> 

In dwc3 glue driver,the controller driver usually probed by call of_platform_populate
which will search the child node of glue driver.
The code of function of_platform_populate is as below:

	for_each_child_of_node(root, child) {
                 rc = of_platform_bus_create(child, matches, lookup, parent, true);
                 if (rc) {
                         of_node_put(child);
                         break;
                 }
         }

So I think the controller node should be a sub-node.

>> +
>> +Example:
>> +	usb3: hisi_dwc3 {
>> +		compatible = "hisilicon,hi3660-dwc3";
>> +		#address-cells = <2>;
>> +		#size-cells = <2>;
>> +		ranges;
>> +
>> +		clocks = <&crg_ctrl HI3660_CLK_ABB_USB>,
>> +			 <&crg_ctrl HI3660_ACLK_GATE_USB3OTG>;
>> +		clock-names = "clk_usb3phy_ref", "aclk_usb3otg";
>> +		assigned-clocks = <&crg_ctrl HI3660_ACLK_GATE_USB3OTG>;
>> +		assigned-clock-rates = <229000000>;
>> +		resets = <&crg_rst 0x90 8>,
>> +			 <&crg_rst 0x90 7>,
>> +			 <&crg_rst 0x90 6>,
>> +			 <&crg_rst 0x90 5>;
>> +
>> +		dwc3: dwc3@ff100000 {
> 
> usb@...
> 
>> +			compatible = "snps,dwc3";
>> +			reg = <0x0 0xff100000 0x0 0x100000>;
>> +			interrupts = <0 159 4>, <0 161 4>;
>> +			phys = <&usb_phy>;
>> +			phy-names = "usb3-phy";
>> +			dr_mode = "otg";
>> +			maximum-speed = "super-speed";
>> +			phy_type = "utmi";
>> +			snps,dis-del-phy-power-chg-quirk;
>> +			snps,lfps_filter_quirk;
>> +			snps,dis_u2_susphy_quirk;
>> +			snps,dis_u3_susphy_quirk;
>> +			snps,tx_de_emphasis_quirk;
>> +			snps,tx_de_emphasis = <1>;
>> +			snps,dis_enblslpm_quirk;
>> +			snps,gctl-reset-quirk;
>> +			extcon = <&hisi_hikey_usb>;
>> +		};
>> +	};
>> -- 
>> 2.15.0-rc2
>>
> 
> 
> .
> 


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

* Re: [PATCH 01/10] dt-bindings: usb: add support for dwc3 controller on HiSilicon SoCs
  2018-11-17  2:29     ` Chen Yu
@ 2018-12-03 16:01       ` Rob Herring
  2018-12-04  1:03         ` Chen Yu
  2018-12-14  8:05         ` Chen Yu
  0 siblings, 2 replies; 23+ messages in thread
From: Rob Herring @ 2018-12-03 16:01 UTC (permalink / raw)
  To: Chen Yu
  Cc: Wangbinghui, Linux USB List, devicetree, linux-kernel,
	Suzhuangluan, kongfei, Greg Kroah-Hartman, Mark Rutland,
	John Stultz

On Fri, Nov 16, 2018 at 8:29 PM Chen Yu <chenyu56@huawei.com> wrote:
>
> Hi,
>
> On 2018/11/13 0:02, Rob Herring wrote:
> > On Sat, Oct 27, 2018 at 05:58:11PM +0800, Yu Chen wrote:
> >> This patch adds binding descriptions to support the dwc3 controller
> >> on HiSilicon SoCs and boards like the HiKey960.
> >>
> >> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> >> Cc: Rob Herring <robh+dt@kernel.org>
> >> Cc: Mark Rutland <mark.rutland@arm.com>
> >> Cc: John Stultz <john.stultz@linaro.org>
> >> Signed-off-by: Yu Chen <chenyu56@huawei.com>
> >> ---
> >>  .../devicetree/bindings/usb/dwc3-hisi.txt          | 53 ++++++++++++++++++++++
> >>  1 file changed, 53 insertions(+)
> >>  create mode 100644 Documentation/devicetree/bindings/usb/dwc3-hisi.txt
> >>
> >> diff --git a/Documentation/devicetree/bindings/usb/dwc3-hisi.txt b/Documentation/devicetree/bindings/usb/dwc3-hisi.txt
> >> new file mode 100644
> >> index 000000000000..e715e7b1c324
> >> --- /dev/null
> >> +++ b/Documentation/devicetree/bindings/usb/dwc3-hisi.txt
> >> @@ -0,0 +1,53 @@
> >> +HiSilicon DWC3 USB SoC controller
> >> +
> >> +This file documents the parameters for the dwc3-hisi driver.
> >> +
> >> +Required properties:
> >> +- compatible:       should be "hisilicon,hi3660-dwc3"
> >> +- clocks:   A list of phandle + clock-specifier pairs for the
> >> +            clocks listed in clock-names
> >> +- clock-names:      Specify clock names
> >> +- resets:   list of phandle and reset specifier pairs.
> >> +
> >> +Sub-nodes:
> >> +The dwc3 core should be added as subnode to HiSilicon DWC3 as shown in the
> >> +example below. The DT binding details of dwc3 can be found in:
> >> +Documentation/devicetree/bindings/usb/dwc3.txt
> >
> > If you only have clocks and resets and no glue registers, then you
> > don't need a sub-node. Just make the controller one node.
> >
>
> In dwc3 glue driver,the controller driver usually probed by call of_platform_populate
> which will search the child node of glue driver.
> The code of function of_platform_populate is as below:
>
>         for_each_child_of_node(root, child) {
>                  rc = of_platform_bus_create(child, matches, lookup, parent, true);
>                  if (rc) {
>                          of_node_put(child);
>                          break;
>                  }
>          }
>
> So I think the controller node should be a sub-node.

It was done that way, but has changed. See commit fe8abf332b8f ("usb:
dwc3: support clocks and resets for DWC3 core").

Rob

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

* Re: [PATCH 01/10] dt-bindings: usb: add support for dwc3 controller on HiSilicon SoCs
  2018-12-03 16:01       ` Rob Herring
@ 2018-12-04  1:03         ` Chen Yu
  2018-12-14  8:05         ` Chen Yu
  1 sibling, 0 replies; 23+ messages in thread
From: Chen Yu @ 2018-12-04  1:03 UTC (permalink / raw)
  To: Rob Herring
  Cc: wangbinghui, Linux USB List, devicetree, linux-kernel,
	Suzhuangluan, kongfei, Greg Kroah-Hartman, Mark Rutland,
	John Stultz



On 2018/12/4 0:01, Rob Herring wrote:
> On Fri, Nov 16, 2018 at 8:29 PM Chen Yu <chenyu56@huawei.com> wrote:
>>
>> Hi,
>>
>> On 2018/11/13 0:02, Rob Herring wrote:
>>> On Sat, Oct 27, 2018 at 05:58:11PM +0800, Yu Chen wrote:
>>>> This patch adds binding descriptions to support the dwc3 controller
>>>> on HiSilicon SoCs and boards like the HiKey960.
>>>>
>>>> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>>>> Cc: Rob Herring <robh+dt@kernel.org>
>>>> Cc: Mark Rutland <mark.rutland@arm.com>
>>>> Cc: John Stultz <john.stultz@linaro.org>
>>>> Signed-off-by: Yu Chen <chenyu56@huawei.com>
>>>> ---
>>>>  .../devicetree/bindings/usb/dwc3-hisi.txt          | 53 ++++++++++++++++++++++
>>>>  1 file changed, 53 insertions(+)
>>>>  create mode 100644 Documentation/devicetree/bindings/usb/dwc3-hisi.txt
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/usb/dwc3-hisi.txt b/Documentation/devicetree/bindings/usb/dwc3-hisi.txt
>>>> new file mode 100644
>>>> index 000000000000..e715e7b1c324
>>>> --- /dev/null
>>>> +++ b/Documentation/devicetree/bindings/usb/dwc3-hisi.txt
>>>> @@ -0,0 +1,53 @@
>>>> +HiSilicon DWC3 USB SoC controller
>>>> +
>>>> +This file documents the parameters for the dwc3-hisi driver.
>>>> +
>>>> +Required properties:
>>>> +- compatible:       should be "hisilicon,hi3660-dwc3"
>>>> +- clocks:   A list of phandle + clock-specifier pairs for the
>>>> +            clocks listed in clock-names
>>>> +- clock-names:      Specify clock names
>>>> +- resets:   list of phandle and reset specifier pairs.
>>>> +
>>>> +Sub-nodes:
>>>> +The dwc3 core should be added as subnode to HiSilicon DWC3 as shown in the
>>>> +example below. The DT binding details of dwc3 can be found in:
>>>> +Documentation/devicetree/bindings/usb/dwc3.txt
>>>
>>> If you only have clocks and resets and no glue registers, then you
>>> don't need a sub-node. Just make the controller one node.
>>>
>>
>> In dwc3 glue driver,the controller driver usually probed by call of_platform_populate
>> which will search the child node of glue driver.
>> The code of function of_platform_populate is as below:
>>
>>         for_each_child_of_node(root, child) {
>>                  rc = of_platform_bus_create(child, matches, lookup, parent, true);
>>                  if (rc) {
>>                          of_node_put(child);
>>                          break;
>>                  }
>>          }
>>
>> So I think the controller node should be a sub-node.
> 
> It was done that way, but has changed. See commit fe8abf332b8f ("usb:
> dwc3: support clocks and resets for DWC3 core").

OK.Thanks!

> 
> Rob
> 
> .
> 


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

* Re: [PATCH 01/10] dt-bindings: usb: add support for dwc3 controller on HiSilicon SoCs
  2018-12-03 16:01       ` Rob Herring
  2018-12-04  1:03         ` Chen Yu
@ 2018-12-14  8:05         ` Chen Yu
  1 sibling, 0 replies; 23+ messages in thread
From: Chen Yu @ 2018-12-14  8:05 UTC (permalink / raw)
  To: Rob Herring
  Cc: liuyu712, Wangbinghui, Linux USB List, devicetree, linux-kernel,
	Suzhuangluan, kongfei, Greg Kroah-Hartman, Mark Rutland,
	John Stultz

Hi,

On 2018/12/4 0:01, Rob Herring wrote:
> On Fri, Nov 16, 2018 at 8:29 PM Chen Yu <chenyu56@huawei.com> wrote:
>>
>> Hi,
>>
>> On 2018/11/13 0:02, Rob Herring wrote:
>>> On Sat, Oct 27, 2018 at 05:58:11PM +0800, Yu Chen wrote:
>>>> This patch adds binding descriptions to support the dwc3 controller
>>>> on HiSilicon SoCs and boards like the HiKey960.
>>>>
>>>> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>>>> Cc: Rob Herring <robh+dt@kernel.org>
>>>> Cc: Mark Rutland <mark.rutland@arm.com>
>>>> Cc: John Stultz <john.stultz@linaro.org>
>>>> Signed-off-by: Yu Chen <chenyu56@huawei.com>
>>>> ---
>>>>  .../devicetree/bindings/usb/dwc3-hisi.txt          | 53 ++++++++++++++++++++++
>>>>  1 file changed, 53 insertions(+)
>>>>  create mode 100644 Documentation/devicetree/bindings/usb/dwc3-hisi.txt
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/usb/dwc3-hisi.txt b/Documentation/devicetree/bindings/usb/dwc3-hisi.txt
>>>> new file mode 100644
>>>> index 000000000000..e715e7b1c324
>>>> --- /dev/null
>>>> +++ b/Documentation/devicetree/bindings/usb/dwc3-hisi.txt
>>>> @@ -0,0 +1,53 @@
>>>> +HiSilicon DWC3 USB SoC controller
>>>> +
>>>> +This file documents the parameters for the dwc3-hisi driver.
>>>> +
>>>> +Required properties:
>>>> +- compatible:       should be "hisilicon,hi3660-dwc3"
>>>> +- clocks:   A list of phandle + clock-specifier pairs for the
>>>> +            clocks listed in clock-names
>>>> +- clock-names:      Specify clock names
>>>> +- resets:   list of phandle and reset specifier pairs.
>>>> +
>>>> +Sub-nodes:
>>>> +The dwc3 core should be added as subnode to HiSilicon DWC3 as shown in the
>>>> +example below. The DT binding details of dwc3 can be found in:
>>>> +Documentation/devicetree/bindings/usb/dwc3.txt
>>>
>>> If you only have clocks and resets and no glue registers, then you
>>> don't need a sub-node. Just make the controller one node.
>>>
>>
>> In dwc3 glue driver,the controller driver usually probed by call of_platform_populate
>> which will search the child node of glue driver.
>> The code of function of_platform_populate is as below:
>>
>>         for_each_child_of_node(root, child) {
>>                  rc = of_platform_bus_create(child, matches, lookup, parent, true);
>>                  if (rc) {
>>                          of_node_put(child);
>>                          break;
>>                  }
>>          }
>>
>> So I think the controller node should be a sub-node.
> 
> It was done that way, but has changed. See commit fe8abf332b8f ("usb:
> dwc3: support clocks and resets for DWC3 core").
> 
I have read the commit and there is a question. If I make the controller one node,
how can the pm suspend of the glue driver be guaranteed to be called after the pm suspend
of dwc3 controller? And also the order of pm resume.
There are some reset registers that should be configured before the initialization
of dwc3 controller on Hi3660 platform.

> Rob
> 
> .
> 


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

end of thread, other threads:[~2018-12-14  8:05 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-27  9:58 [PATCH 00/10] Add support for usb on Hikey960 Yu Chen
2018-10-27  9:58 ` [PATCH 01/10] dt-bindings: usb: add support for dwc3 controller on HiSilicon SoCs Yu Chen
     [not found]   ` <20181112160241.GA14074@bogus>
2018-11-17  2:29     ` Chen Yu
2018-12-03 16:01       ` Rob Herring
2018-12-04  1:03         ` Chen Yu
2018-12-14  8:05         ` Chen Yu
2018-10-27  9:58 ` [PATCH 02/10] dt-bindings: phy: Add support for HiSilicon's hi3660 USB PHY Yu Chen
2018-10-27  9:58 ` [PATCH 03/10] dt-bindings: misc: Add bindings for HiSilicon usb hub and data role switch functionality on HiKey960 Yu Chen
2018-10-27 18:06   ` Sergei Shtylyov
2018-10-29 12:25     ` Chen Yu
2018-10-27  9:58 ` [PATCH 04/10] usb: dwc3: dwc3-hisi: Add code for dwc3 of Hisilicon Soc Platform Yu Chen
2018-10-27  9:58 ` [PATCH 05/10] usb: dwc3: Add two quirks for Hisilicon Kirin " Yu Chen
2018-10-27  9:58 ` [PATCH 06/10] phy: Add usb phy support for hi3660 Soc of Hisilicon Yu Chen
2018-11-12  9:09   ` Kishon Vijay Abraham I
2018-10-27  9:58 ` [PATCH 07/10] hikey960: Support usb functionality of Hikey960 Yu Chen
2018-10-29 14:30   ` Heikki Krogerus
2018-10-30  2:50     ` Chen Yu
2018-10-30 10:16       ` Heikki Krogerus
2018-10-27  9:58 ` [PATCH 08/10] usb: typec: Add support for usb role switch in rt1711h driver Yu Chen
2018-10-29 11:58   ` Heikki Krogerus
2018-10-29 12:22     ` Chen Yu
2018-10-27  9:58 ` [PATCH 09/10] usb: gadget: Add configfs attribuite for controling match_existing_only Yu Chen
2018-10-27  9:58 ` [PATCH 10/10] dts: hi3660: Add support for usb on Hikey960 Yu Chen

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).