stm32mp1: add stusb1600 support for DK1 and DK2 board
[platform/kernel/u-boot.git] / board / st / stm32mp1 / stm32mp1.c
index b369b7a..76917b0 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);