diff mbox series

[U-Boot,16/16] stm32mp1: add stusb1600 support for DK1 and DK2 board

Message ID 1553870544-15734-17-git-send-email-patrick.delaunay@st.com
State Accepted
Commit 6fe7dd3327d552bacf4266d7f1ed074bf98ffb92
Delegated to: Lukasz Majewski
Headers show
Series usb: convert dwc2 gadget to driver model, used in stm32mp1 | expand

Commit Message

Patrick DELAUNAY March 29, 2019, 2:42 p.m. UTC
The DK1 and DK2 boards use the USB Type-C controller STUSB1600.
This patch updates:
- the device tree to add the I2C node in the DT
- the board stm32mp1 to probe this I2C device and use this controller
  to check cable detection.
- the DWC2 driver to support a new dt property
  "u-boot,force-b-session-valid" which forces B session and
  device mode; it is a workaround because the VBUS sensing and
  ID detection isn't available with stusb1600.

Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com>
---

 arch/arm/dts/stm32mp157-pinctrl.dtsi     |  7 ++++
 arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi |  2 +-
 arch/arm/dts/stm32mp157a-dk1.dts         | 18 ++++++++++
 board/st/stm32mp1/stm32mp1.c             | 56 ++++++++++++++++++++++++++++++++
 doc/device-tree-bindings/usb/dwc2.txt    |  2 ++
 drivers/usb/gadget/dwc2_udc_otg.c        |  8 +++--
 6 files changed, 90 insertions(+), 3 deletions(-)

Comments

Lukasz Majewski April 8, 2019, 10:04 p.m. UTC | #1
On Fri, 29 Mar 2019 15:42:24 +0100
Patrick Delaunay <patrick.delaunay@st.com> wrote:

> The DK1 and DK2 boards use the USB Type-C controller STUSB1600.
> This patch updates:
> - the device tree to add the I2C node in the DT
> - the board stm32mp1 to probe this I2C device and use this controller
>   to check cable detection.
> - the DWC2 driver to support a new dt property
>   "u-boot,force-b-session-valid" which forces B session and
>   device mode; it is a workaround because the VBUS sensing and
>   ID detection isn't available with stusb1600.
> 
> Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com>
> ---
> 
>  arch/arm/dts/stm32mp157-pinctrl.dtsi     |  7 ++++
>  arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi |  2 +-
>  arch/arm/dts/stm32mp157a-dk1.dts         | 18 ++++++++++
>  board/st/stm32mp1/stm32mp1.c             | 56
> ++++++++++++++++++++++++++++++++
> doc/device-tree-bindings/usb/dwc2.txt    |  2 ++
> drivers/usb/gadget/dwc2_udc_otg.c        |  8 +++-- 6 files changed,
> 90 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/arm/dts/stm32mp157-pinctrl.dtsi
> b/arch/arm/dts/stm32mp157-pinctrl.dtsi index 867d244..1962267 100644
> --- a/arch/arm/dts/stm32mp157-pinctrl.dtsi
> +++ b/arch/arm/dts/stm32mp157-pinctrl.dtsi
> @@ -380,6 +380,13 @@
>  				};
>  			};
>  
> +			stusb1600_pins_a: stusb1600-0 {
> +				pins {
> +					pinmux = <STM32_PINMUX('I',
> 11, ANALOG)>;
> +					bias-pull-up;
> +				};
> +			};
> +
>  			uart4_pins_a: uart4-0 {
>  				pins1 {
>  					pinmux = <STM32_PINMUX('G',
> 11, AF6)>; /* UART4_TX */ diff --git
> a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi
> b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi index 7e2c5d0..0f32a38
> 100644 --- a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi +++
> b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi @@ -191,7 +191,7 @@
>  };
>  
>  &usbotg_hs {
> -	force-b-session-valid;
> +	u-boot,force-b-session-valid;
>  	hnp-srp-disable;
>  };
>  
> diff --git a/arch/arm/dts/stm32mp157a-dk1.dts
> b/arch/arm/dts/stm32mp157a-dk1.dts index b8ef820..e36773d 100644
> --- a/arch/arm/dts/stm32mp157a-dk1.dts
> +++ b/arch/arm/dts/stm32mp157a-dk1.dts
> @@ -67,6 +67,24 @@
>  	/delete-property/dmas;
>  	/delete-property/dma-names;
>  
> +	typec: stusb1600@28 {
> +		compatible = "st,stusb1600";
> +		reg = <0x28>;
> +		interrupts = <11 IRQ_TYPE_EDGE_FALLING>;
> +		interrupt-parent = <&gpioi>;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&stusb1600_pins_a>;
> +
> +		status = "okay";
> +
> +		typec_con: connector {
> +			compatible = "usb-c-connector";
> +			label = "USB-C";
> +			power-role = "sink";
> +			power-opmode = "default";
> +		};
> +	};
> +
>  	pmic: stpmic@33 {
>  		compatible = "st,stpmic1";
>  		reg = <0x33>;
> diff --git a/board/st/stm32mp1/stm32mp1.c
> b/board/st/stm32mp1/stm32mp1.c index 58b6d78..23737ce 100644
> --- a/board/st/stm32mp1/stm32mp1.c
> +++ b/board/st/stm32mp1/stm32mp1.c
> @@ -9,15 +9,18 @@
>  #include <dm.h>
>  #include <g_dnl.h>
>  #include <generic-phy.h>
> +#include <i2c.h>
>  #include <led.h>
>  #include <misc.h>
>  #include <phy.h>
>  #include <reset.h>
>  #include <syscon.h>
> +#include <usb.h>
>  #include <asm/io.h>
>  #include <asm/gpio.h>
>  #include <asm/arch/stm32.h>
>  #include <power/regulator.h>
> +#include <usb/dwc2_udc.h>
>  
>  /* SYSCFG registers */
>  #define SYSCFG_BOOTR		0x00
> @@ -151,11 +154,64 @@ static void board_key_check(void)
>  
>  #if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG)
>  
> +/* STMicroelectronics STUSB1600 Type-C controller */
> +#define STUSB1600_CC_CONNECTION_STATUS		0x0E
> +
> +/* STUSB1600_CC_CONNECTION_STATUS bitfields */
> +#define STUSB1600_CC_ATTACH			BIT(0)
> +
> +static int stusb1600_init(struct udevice **dev_stusb1600)
> +{
> +	ofnode node;
> +	struct udevice *dev, *bus;
> +	int ret;
> +	u32 chip_addr;
> +
> +	*dev_stusb1600 = NULL;
> +
> +	/* if node stusb1600 is present, means DK1 or DK2 board */
> +	node = ofnode_by_compatible(ofnode_null(), "st,stusb1600");
> +	if (!ofnode_valid(node))
> +		return -ENODEV;
> +
> +	ret = ofnode_read_u32(node, "reg", &chip_addr);
> +	if (ret)
> +		return -EINVAL;
> +
> +	ret = uclass_get_device_by_ofnode(UCLASS_I2C,
> ofnode_get_parent(node),
> +					  &bus);
> +	if (ret) {
> +		printf("bus for stusb1600 not found\n");
> +		return -ENODEV;
> +	}
> +
> +	ret = dm_i2c_probe(bus, chip_addr, 0, &dev);
> +	if (!ret)
> +		*dev_stusb1600 = dev;
> +
> +	return ret;
> +}
> +
> +static int stusb1600_cable_connected(struct udevice *dev)
> +{
> +	u8 status;
> +
> +	if (dm_i2c_read(dev, STUSB1600_CC_CONNECTION_STATUS,
> &status, 1))
> +		return 0;
> +
> +	return status & STUSB1600_CC_ATTACH;
> +}
> +
> +#include <usb/dwc2_udc.h>
>  int g_dnl_board_usb_cable_connected(void)
>  {
> +	struct udevice *stusb1600;
>  	struct udevice *dwc2_udc_otg;
>  	int ret;
>  
> +	if (!stusb1600_init(&stusb1600))
> +		return stusb1600_cable_connected(stusb1600);
> +
>  	ret = uclass_get_device_by_driver(UCLASS_USB_GADGET_GENERIC,
>  					  DM_GET_DRIVER(dwc2_udc_otg),
>  					  &dwc2_udc_otg);
> diff --git a/doc/device-tree-bindings/usb/dwc2.txt
> b/doc/device-tree-bindings/usb/dwc2.txt index eb60ffa..61493f7 100644
> --- a/doc/device-tree-bindings/usb/dwc2.txt
> +++ b/doc/device-tree-bindings/usb/dwc2.txt
> @@ -39,6 +39,8 @@ Refer to phy/phy-bindings.txt for generic phy
> consumer properties
>  - g-tx-fifo-size: size of periodic tx fifo per endpoint (except ep0)
> in gadget mode.
>  - usb33d-supply: external VBUS and ID sensing comparators supply, in
> order to perform OTG operation, used on STM32MP1 SoCs.
> +- u-boot,force-b-session-valid: force B-peripheral session instead
> of relying on
> +  VBUS sensing (only valid when dr_mode = "peripheral" and for
> u-boot). 
>  Deprecated properties:
>  - g-use-dma: gadget DMA mode is automatically detected
> diff --git a/drivers/usb/gadget/dwc2_udc_otg.c
> b/drivers/usb/gadget/dwc2_udc_otg.c index 3fdaa10..494ab53 100644
> --- a/drivers/usb/gadget/dwc2_udc_otg.c
> +++ b/drivers/usb/gadget/dwc2_udc_otg.c
> @@ -1053,7 +1053,7 @@ static int
> dwc2_udc_otg_ofdata_to_platdata(struct udevice *dev)
> platdata->tx_fifo_sz = dev_read_u32_default(dev, "g-tx-fifo-size",
> 0); platdata->force_b_session_valid =
> -		dev_read_bool(dev, "force-b-session-valid");
> +		dev_read_bool(dev, "u-boot,force-b-session-valid");
>  
>  	/* force platdata according compatible */
>  	drvdata = dev_get_driver_data(dev);
> @@ -1075,6 +1075,9 @@ static void
> dwc2_set_stm32mp1_hsotg_params(struct dwc2_plat_otg_data *p) | 0 <<
> 8	/* [0:SRP disable 1:SRP enable]*/ | 0 << 6	/* 0: high
> speed utmi+, 1: full speed serial*/ | 0x7 << 0;	/* FS timeout
> calibration**/ +
> +	if (p->force_b_session_valid)
> +		p->usb_gusbcfg |= 1 << 30; /* FDMOD: Force device
> mode */ }
>  
>  static int dwc2_udc_otg_reset_init(struct udevice *dev,
> @@ -1166,7 +1169,8 @@ static int dwc2_udc_otg_probe(struct udevice
> *dev) 
>  	if (platdata->force_b_session_valid)
>  		/* Override B session bits : value and enable */
> -		setbits_le32(&usbotg_reg->gotgctl,  B_VALOEN |
> B_VALOVAL);
> +		setbits_le32(&usbotg_reg->gotgctl,
> +			     A_VALOEN | A_VALOVAL | B_VALOEN |
> B_VALOVAL); 
>  	ret = dwc2_udc_probe(platdata);
>  	if (ret)

Reviewed-by: Lukasz Majewski <lukma@denx.de>


Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
diff mbox series

Patch

diff --git a/arch/arm/dts/stm32mp157-pinctrl.dtsi b/arch/arm/dts/stm32mp157-pinctrl.dtsi
index 867d244..1962267 100644
--- a/arch/arm/dts/stm32mp157-pinctrl.dtsi
+++ b/arch/arm/dts/stm32mp157-pinctrl.dtsi
@@ -380,6 +380,13 @@ 
 				};
 			};
 
+			stusb1600_pins_a: stusb1600-0 {
+				pins {
+					pinmux = <STM32_PINMUX('I', 11, ANALOG)>;
+					bias-pull-up;
+				};
+			};
+
 			uart4_pins_a: uart4-0 {
 				pins1 {
 					pinmux = <STM32_PINMUX('G', 11, AF6)>; /* UART4_TX */
diff --git a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi
index 7e2c5d0..0f32a38 100644
--- a/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi
+++ b/arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi
@@ -191,7 +191,7 @@ 
 };
 
 &usbotg_hs {
-	force-b-session-valid;
+	u-boot,force-b-session-valid;
 	hnp-srp-disable;
 };
 
diff --git a/arch/arm/dts/stm32mp157a-dk1.dts b/arch/arm/dts/stm32mp157a-dk1.dts
index b8ef820..e36773d 100644
--- a/arch/arm/dts/stm32mp157a-dk1.dts
+++ b/arch/arm/dts/stm32mp157a-dk1.dts
@@ -67,6 +67,24 @@ 
 	/delete-property/dmas;
 	/delete-property/dma-names;
 
+	typec: stusb1600@28 {
+		compatible = "st,stusb1600";
+		reg = <0x28>;
+		interrupts = <11 IRQ_TYPE_EDGE_FALLING>;
+		interrupt-parent = <&gpioi>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&stusb1600_pins_a>;
+
+		status = "okay";
+
+		typec_con: connector {
+			compatible = "usb-c-connector";
+			label = "USB-C";
+			power-role = "sink";
+			power-opmode = "default";
+		};
+	};
+
 	pmic: stpmic@33 {
 		compatible = "st,stpmic1";
 		reg = <0x33>;
diff --git a/board/st/stm32mp1/stm32mp1.c b/board/st/stm32mp1/stm32mp1.c
index 58b6d78..23737ce 100644
--- a/board/st/stm32mp1/stm32mp1.c
+++ b/board/st/stm32mp1/stm32mp1.c
@@ -9,15 +9,18 @@ 
 #include <dm.h>
 #include <g_dnl.h>
 #include <generic-phy.h>
+#include <i2c.h>
 #include <led.h>
 #include <misc.h>
 #include <phy.h>
 #include <reset.h>
 #include <syscon.h>
+#include <usb.h>
 #include <asm/io.h>
 #include <asm/gpio.h>
 #include <asm/arch/stm32.h>
 #include <power/regulator.h>
+#include <usb/dwc2_udc.h>
 
 /* SYSCFG registers */
 #define SYSCFG_BOOTR		0x00
@@ -151,11 +154,64 @@  static void board_key_check(void)
 
 #if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG)
 
+/* STMicroelectronics STUSB1600 Type-C controller */
+#define STUSB1600_CC_CONNECTION_STATUS		0x0E
+
+/* STUSB1600_CC_CONNECTION_STATUS bitfields */
+#define STUSB1600_CC_ATTACH			BIT(0)
+
+static int stusb1600_init(struct udevice **dev_stusb1600)
+{
+	ofnode node;
+	struct udevice *dev, *bus;
+	int ret;
+	u32 chip_addr;
+
+	*dev_stusb1600 = NULL;
+
+	/* if node stusb1600 is present, means DK1 or DK2 board */
+	node = ofnode_by_compatible(ofnode_null(), "st,stusb1600");
+	if (!ofnode_valid(node))
+		return -ENODEV;
+
+	ret = ofnode_read_u32(node, "reg", &chip_addr);
+	if (ret)
+		return -EINVAL;
+
+	ret = uclass_get_device_by_ofnode(UCLASS_I2C, ofnode_get_parent(node),
+					  &bus);
+	if (ret) {
+		printf("bus for stusb1600 not found\n");
+		return -ENODEV;
+	}
+
+	ret = dm_i2c_probe(bus, chip_addr, 0, &dev);
+	if (!ret)
+		*dev_stusb1600 = dev;
+
+	return ret;
+}
+
+static int stusb1600_cable_connected(struct udevice *dev)
+{
+	u8 status;
+
+	if (dm_i2c_read(dev, STUSB1600_CC_CONNECTION_STATUS, &status, 1))
+		return 0;
+
+	return status & STUSB1600_CC_ATTACH;
+}
+
+#include <usb/dwc2_udc.h>
 int g_dnl_board_usb_cable_connected(void)
 {
+	struct udevice *stusb1600;
 	struct udevice *dwc2_udc_otg;
 	int ret;
 
+	if (!stusb1600_init(&stusb1600))
+		return stusb1600_cable_connected(stusb1600);
+
 	ret = uclass_get_device_by_driver(UCLASS_USB_GADGET_GENERIC,
 					  DM_GET_DRIVER(dwc2_udc_otg),
 					  &dwc2_udc_otg);
diff --git a/doc/device-tree-bindings/usb/dwc2.txt b/doc/device-tree-bindings/usb/dwc2.txt
index eb60ffa..61493f7 100644
--- a/doc/device-tree-bindings/usb/dwc2.txt
+++ b/doc/device-tree-bindings/usb/dwc2.txt
@@ -39,6 +39,8 @@  Refer to phy/phy-bindings.txt for generic phy consumer properties
 - g-tx-fifo-size: size of periodic tx fifo per endpoint (except ep0) in gadget mode.
 - usb33d-supply: external VBUS and ID sensing comparators supply, in order to
   perform OTG operation, used on STM32MP1 SoCs.
+- u-boot,force-b-session-valid: force B-peripheral session instead of relying on
+  VBUS sensing (only valid when dr_mode = "peripheral" and for u-boot).
 
 Deprecated properties:
 - g-use-dma: gadget DMA mode is automatically detected
diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c
index 3fdaa10..494ab53 100644
--- a/drivers/usb/gadget/dwc2_udc_otg.c
+++ b/drivers/usb/gadget/dwc2_udc_otg.c
@@ -1053,7 +1053,7 @@  static int dwc2_udc_otg_ofdata_to_platdata(struct udevice *dev)
 	platdata->tx_fifo_sz = dev_read_u32_default(dev, "g-tx-fifo-size", 0);
 
 	platdata->force_b_session_valid =
-		dev_read_bool(dev, "force-b-session-valid");
+		dev_read_bool(dev, "u-boot,force-b-session-valid");
 
 	/* force platdata according compatible */
 	drvdata = dev_get_driver_data(dev);
@@ -1075,6 +1075,9 @@  static void dwc2_set_stm32mp1_hsotg_params(struct dwc2_plat_otg_data *p)
 		| 0 << 8	/* [0:SRP disable 1:SRP enable]*/
 		| 0 << 6	/* 0: high speed utmi+, 1: full speed serial*/
 		| 0x7 << 0;	/* FS timeout calibration**/
+
+	if (p->force_b_session_valid)
+		p->usb_gusbcfg |= 1 << 30; /* FDMOD: Force device mode */
 }
 
 static int dwc2_udc_otg_reset_init(struct udevice *dev,
@@ -1166,7 +1169,8 @@  static int dwc2_udc_otg_probe(struct udevice *dev)
 
 	if (platdata->force_b_session_valid)
 		/* Override B session bits : value and enable */
-		setbits_le32(&usbotg_reg->gotgctl,  B_VALOEN | B_VALOVAL);
+		setbits_le32(&usbotg_reg->gotgctl,
+			     A_VALOEN | A_VALOVAL | B_VALOEN | B_VALOVAL);
 
 	ret = dwc2_udc_probe(platdata);
 	if (ret)