stm32mp1: add stusb1600 support for DK1 and DK2 board
authorPatrick Delaunay <patrick.delaunay@st.com>
Fri, 29 Mar 2019 14:42:24 +0000 (15:42 +0100)
committerMarek Vasut <marex@denx.de>
Sun, 21 Apr 2019 08:26:52 +0000 (10:26 +0200)
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>
Reviewed-by: Lukasz Majewski <lukma@denx.de>
arch/arm/dts/stm32mp157-pinctrl.dtsi
arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi
arch/arm/dts/stm32mp157a-dk1.dts
board/st/stm32mp1/stm32mp1.c
doc/device-tree-bindings/usb/dwc2.txt
drivers/usb/gadget/dwc2_udc_otg.c

index c06987548612083159bf7bb3d7fbd3539f35b5cf..0aae69b0a04818a8e94075dfdf7ba3d8d88bc9d6 100644 (file)
                                };
                        };
 
+                       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 */
index 7e2c5d0de3503ff6e7547fb430a70e7a74357cd9..0f32a38dc9476d050ac815f6a5ce02a738004166 100644 (file)
 };
 
 &usbotg_hs {
-       force-b-session-valid;
+       u-boot,force-b-session-valid;
        hnp-srp-disable;
 };
 
index b8ef82015b0c320a03750c7178264428853e8057..e36773dde917ecbf91691c9b32f23f8fc3d8ceb1 100644 (file)
        /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>;
index b369b7a54b61e40410964a64bd1e4b9236cfcd3f..76917b022ede019176244bdd007b8f3b9b74c8d7 100644 (file)
@@ -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);
index eb60ffae58be35a6bbd432f61d16e7213f5f6963..61493f7cb0c7f6fdf56c61aedb6be9ef713824c2 100644 (file)
@@ -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
index 3fdaa102baee3aa32bc83535d240669f68cd1d91..494ab533cca31a3c19b530ed44d2545625e4168d 100644 (file)
@@ -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)