Merge branch 'master' of git://git.denx.de/u-boot-usb
authorTom Rini <trini@konsulko.com>
Mon, 10 Dec 2018 12:15:12 +0000 (07:15 -0500)
committerTom Rini <trini@konsulko.com>
Mon, 10 Dec 2018 12:15:12 +0000 (07:15 -0500)
- DWC3 and UDC cleanup

39 files changed:
arch/arm/Kconfig
arch/arm/dts/omap5-u-boot.dtsi
arch/sandbox/dts/test.dts
board/sunxi/board.c
board/ti/am57xx/board.c
board/ti/dra7xx/evm.c
cmd/fastboot.c
cmd/rockusb.c
cmd/thordown.c
cmd/usb_gadget_sdp.c
cmd/usb_mass_storage.c
common/dfu.c
configs/am57xx_evm_defconfig
configs/am57xx_hs_evm_defconfig
configs/dra7xx_evm_defconfig
configs/dra7xx_hs_evm_defconfig
configs/evb-rk3328_defconfig
drivers/core/syscon-uclass.c
drivers/phy/Kconfig
drivers/phy/Makefile
drivers/phy/omap-usb2-phy.c [new file with mode: 0644]
drivers/phy/ti-pipe3-phy.c
drivers/usb/Kconfig
drivers/usb/dwc3/Kconfig
drivers/usb/dwc3/core.c
drivers/usb/dwc3/dwc3-generic.c
drivers/usb/dwc3/ep0.c
drivers/usb/gadget/ether.c
drivers/usb/gadget/udc/Makefile
drivers/usb/gadget/udc/udc-core.c
drivers/usb/gadget/udc/udc-uclass.c [new file with mode: 0644]
drivers/usb/host/xhci-dwc3.c
drivers/usb/musb-new/omap2430.c
drivers/usb/musb-new/sunxi.c
include/dm/uclass-id.h
include/dwc3-uboot.h
include/linux/usb/gadget.h
include/syscon.h
test/dm/syscon.c

index 13ba774..7f513ce 100644 (file)
@@ -932,6 +932,7 @@ config ARCH_ZYNQMP_R5
        select DM_SERIAL
        select OF_CONTROL
        imply CMD_DM
+       imply DM_USB_GADGET
 
 config ARCH_ZYNQMP
        bool "Xilinx ZynqMP based platform"
@@ -949,6 +950,7 @@ config ARCH_ZYNQMP
        imply CMD_DM
        imply FAT_WRITE
        imply MP
+       imply DM_USB_GADGET
 
 config TEGRA
        bool "NVIDIA Tegra"
index bf2684c..a6a7801 100644 (file)
        ocp {
                u-boot,dm-spl;
 
+               ocp2scp@4a080000 {
+                       compatible = "ti,omap-ocp2scp", "simple-bus";
+               };
+
                ocp2scp@4a090000 {
                        compatible = "ti,omap-ocp2scp", "simple-bus";
                };
index 082fcec..6b1c269 100644 (file)
 
                test4 {
                        compatible = "denx,u-boot-probe-test";
+                       first-syscon = <&syscon0>;
+                       second-sys-ctrl = <&another_system_controller>;
                };
        };
 
                };
        };
 
-       syscon@0 {
+       syscon0: syscon@0 {
                compatible = "sandbox,syscon0";
                reg = <0x10 16>;
        };
 
-       syscon@1 {
+       another_system_controller: syscon@1 {
                compatible = "sandbox,syscon1";
                reg = <0x20 5
                        0x28 6
index 8e20dc7..917f5b1 100644 (file)
@@ -665,7 +665,7 @@ int g_dnl_board_usb_cable_connected(void)
        struct phy phy;
        int ret;
 
-       ret = uclass_get_device(UCLASS_USB_DEV_GENERIC, 0, &dev);
+       ret = uclass_get_device(UCLASS_USB_GADGET_GENERIC, 0, &dev);
        if (ret) {
                pr_err("%s: Cannot find USB device\n", __func__);
                return ret;
index 177a324..8dfb2ee 100644 (file)
@@ -675,6 +675,19 @@ out:
        return;
 }
 
+#if CONFIG_IS_ENABLED(DM_USB) && CONFIG_IS_ENABLED(OF_CONTROL)
+static int device_okay(const char *path)
+{
+       int node;
+
+       node = fdt_path_offset(gd->fdt_blob, path);
+       if (node < 0)
+               return 0;
+
+       return fdtdec_get_is_enabled(gd->fdt_blob, node);
+}
+#endif
+
 int board_late_init(void)
 {
        setup_board_eeprom_env();
@@ -714,6 +727,12 @@ int board_late_init(void)
        board_ti_set_ethaddr(2);
 #endif
 
+#if CONFIG_IS_ENABLED(DM_USB) && CONFIG_IS_ENABLED(OF_CONTROL)
+       if (device_okay("/ocp/omap_dwc3_1@48880000"))
+               enable_usb_clocks(0);
+       if (device_okay("/ocp/omap_dwc3_2@488c0000"))
+               enable_usb_clocks(1);
+#endif
        return 0;
 }
 
@@ -864,93 +883,6 @@ int spl_start_uboot(void)
 }
 #endif
 
-#ifdef CONFIG_USB_DWC3
-static struct dwc3_device usb_otg_ss2 = {
-       .maximum_speed = USB_SPEED_HIGH,
-       .base = DRA7_USB_OTG_SS2_BASE,
-       .tx_fifo_resize = false,
-       .index = 1,
-};
-
-static struct dwc3_omap_device usb_otg_ss2_glue = {
-       .base = (void *)DRA7_USB_OTG_SS2_GLUE_BASE,
-       .utmi_mode = DWC3_OMAP_UTMI_MODE_SW,
-       .index = 1,
-};
-
-static struct ti_usb_phy_device usb_phy2_device = {
-       .usb2_phy_power = (void *)DRA7_USB2_PHY2_POWER,
-       .index = 1,
-};
-
-int usb_gadget_handle_interrupts(int index)
-{
-       u32 status;
-
-       status = dwc3_omap_uboot_interrupt_status(index);
-       if (status)
-               dwc3_uboot_handle_interrupt(index);
-
-       return 0;
-}
-#endif /* CONFIG_USB_DWC3 */
-
-#if defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_XHCI_OMAP)
-int board_usb_init(int index, enum usb_init_type init)
-{
-       enable_usb_clocks(index);
-       switch (index) {
-       case 0:
-               if (init == USB_INIT_DEVICE) {
-                       printf("port %d can't be used as device\n", index);
-                       disable_usb_clocks(index);
-                       return -EINVAL;
-               }
-               break;
-       case 1:
-               if (init == USB_INIT_DEVICE) {
-#ifdef CONFIG_USB_DWC3
-                       usb_otg_ss2.dr_mode = USB_DR_MODE_PERIPHERAL;
-                       usb_otg_ss2_glue.vbus_id_status = OMAP_DWC3_VBUS_VALID;
-                       ti_usb_phy_uboot_init(&usb_phy2_device);
-                       dwc3_omap_uboot_init(&usb_otg_ss2_glue);
-                       dwc3_uboot_init(&usb_otg_ss2);
-#endif
-               } else {
-                       printf("port %d can't be used as host\n", index);
-                       disable_usb_clocks(index);
-                       return -EINVAL;
-               }
-
-               break;
-       default:
-               printf("Invalid Controller Index\n");
-       }
-
-       return 0;
-}
-
-int board_usb_cleanup(int index, enum usb_init_type init)
-{
-#ifdef CONFIG_USB_DWC3
-       switch (index) {
-       case 0:
-       case 1:
-               if (init == USB_INIT_DEVICE) {
-                       ti_usb_phy_uboot_exit(index);
-                       dwc3_uboot_exit(index);
-                       dwc3_omap_uboot_exit(index);
-               }
-               break;
-       default:
-               printf("Invalid Controller Index\n");
-       }
-#endif
-       disable_usb_clocks(index);
-       return 0;
-}
-#endif /* defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_XHCI_OMAP) */
-
 #ifdef CONFIG_DRIVER_TI_CPSW
 
 /* Delay value to add to calibrated value */
index bbe5445..d69641e 100644 (file)
@@ -646,6 +646,19 @@ int dram_init_banksize(void)
        return 0;
 }
 
+#if CONFIG_IS_ENABLED(DM_USB) && CONFIG_IS_ENABLED(OF_CONTROL)
+static int device_okay(const char *path)
+{
+       int node;
+
+       node = fdt_path_offset(gd->fdt_blob, path);
+       if (node < 0)
+               return 0;
+
+       return fdtdec_get_is_enabled(gd->fdt_blob, node);
+}
+#endif
+
 int board_late_init(void)
 {
 #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
@@ -685,6 +698,12 @@ int board_late_init(void)
        if (board_is_dra71x_evm())
                palmas_i2c_write_u8(LP873X_I2C_SLAVE_ADDR, 0x9, 0x7);
 #endif
+#if CONFIG_IS_ENABLED(DM_USB) && CONFIG_IS_ENABLED(OF_CONTROL)
+       if (device_okay("/ocp/omap_dwc3_1@48880000"))
+               enable_usb_clocks(0);
+       if (device_okay("/ocp/omap_dwc3_2@488c0000"))
+               enable_usb_clocks(1);
+#endif
        return 0;
 }
 
@@ -896,110 +915,6 @@ const struct mmc_platform_fixups *platform_fixups_mmc(uint32_t addr)
 }
 #endif
 
-#ifdef CONFIG_USB_DWC3
-static struct dwc3_device usb_otg_ss1 = {
-       .maximum_speed = USB_SPEED_SUPER,
-       .base = DRA7_USB_OTG_SS1_BASE,
-       .tx_fifo_resize = false,
-       .index = 0,
-};
-
-static struct dwc3_omap_device usb_otg_ss1_glue = {
-       .base = (void *)DRA7_USB_OTG_SS1_GLUE_BASE,
-       .utmi_mode = DWC3_OMAP_UTMI_MODE_SW,
-       .index = 0,
-};
-
-static struct ti_usb_phy_device usb_phy1_device = {
-       .pll_ctrl_base = (void *)DRA7_USB3_PHY1_PLL_CTRL,
-       .usb2_phy_power = (void *)DRA7_USB2_PHY1_POWER,
-       .usb3_phy_power = (void *)DRA7_USB3_PHY1_POWER,
-       .index = 0,
-};
-
-static struct dwc3_device usb_otg_ss2 = {
-       .maximum_speed = USB_SPEED_SUPER,
-       .base = DRA7_USB_OTG_SS2_BASE,
-       .tx_fifo_resize = false,
-       .index = 1,
-};
-
-static struct dwc3_omap_device usb_otg_ss2_glue = {
-       .base = (void *)DRA7_USB_OTG_SS2_GLUE_BASE,
-       .utmi_mode = DWC3_OMAP_UTMI_MODE_SW,
-       .index = 1,
-};
-
-static struct ti_usb_phy_device usb_phy2_device = {
-       .usb2_phy_power = (void *)DRA7_USB2_PHY2_POWER,
-       .index = 1,
-};
-
-int board_usb_init(int index, enum usb_init_type init)
-{
-       enable_usb_clocks(index);
-       switch (index) {
-       case 0:
-               if (init == USB_INIT_DEVICE) {
-                       usb_otg_ss1.dr_mode = USB_DR_MODE_PERIPHERAL;
-                       usb_otg_ss1_glue.vbus_id_status = OMAP_DWC3_VBUS_VALID;
-               } else {
-                       usb_otg_ss1.dr_mode = USB_DR_MODE_HOST;
-                       usb_otg_ss1_glue.vbus_id_status = OMAP_DWC3_ID_GROUND;
-               }
-
-               ti_usb_phy_uboot_init(&usb_phy1_device);
-               dwc3_omap_uboot_init(&usb_otg_ss1_glue);
-               dwc3_uboot_init(&usb_otg_ss1);
-               break;
-       case 1:
-               if (init == USB_INIT_DEVICE) {
-                       usb_otg_ss2.dr_mode = USB_DR_MODE_PERIPHERAL;
-                       usb_otg_ss2_glue.vbus_id_status = OMAP_DWC3_VBUS_VALID;
-               } else {
-                       usb_otg_ss2.dr_mode = USB_DR_MODE_HOST;
-                       usb_otg_ss2_glue.vbus_id_status = OMAP_DWC3_ID_GROUND;
-               }
-
-               ti_usb_phy_uboot_init(&usb_phy2_device);
-               dwc3_omap_uboot_init(&usb_otg_ss2_glue);
-               dwc3_uboot_init(&usb_otg_ss2);
-               break;
-       default:
-               printf("Invalid Controller Index\n");
-       }
-
-       return 0;
-}
-
-int board_usb_cleanup(int index, enum usb_init_type init)
-{
-       switch (index) {
-       case 0:
-       case 1:
-               ti_usb_phy_uboot_exit(index);
-               dwc3_uboot_exit(index);
-               dwc3_omap_uboot_exit(index);
-               break;
-       default:
-               printf("Invalid Controller Index\n");
-       }
-       disable_usb_clocks(index);
-       return 0;
-}
-
-int usb_gadget_handle_interrupts(int index)
-{
-       u32 status;
-
-       status = dwc3_omap_uboot_interrupt_status(index);
-       if (status)
-               dwc3_uboot_handle_interrupt(index);
-
-       return 0;
-}
-#endif
-
 #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_OS_BOOT)
 int spl_start_uboot(void)
 {
index ae3a5f6..0be83b7 100644 (file)
@@ -51,7 +51,7 @@ static int do_fastboot_usb(int argc, char *const argv[],
                return CMD_RET_FAILURE;
        }
 
-       ret = board_usb_init(controller_index, USB_INIT_DEVICE);
+       ret = usb_gadget_initialize(controller_index);
        if (ret) {
                pr_err("USB init failed: %d\n", ret);
                return CMD_RET_FAILURE;
@@ -82,7 +82,7 @@ static int do_fastboot_usb(int argc, char *const argv[],
 exit:
        g_dnl_unregister();
        g_dnl_clear_detach();
-       board_usb_cleanup(controller_index, USB_INIT_DEVICE);
+       usb_gadget_release(controller_index);
 
        return ret;
 #else
index 8206643..e0c1480 100644 (file)
@@ -33,7 +33,7 @@ static int do_rockusb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
        dev_index = simple_strtoul(devnum, NULL, 0);
        rockusb_dev_init(devtype, dev_index);
 
-       ret = board_usb_init(controller_index, USB_INIT_DEVICE);
+       ret = usb_gadget_initialize(controller_index);
        if (ret) {
                printf("USB init failed: %d\n", ret);
                return CMD_RET_FAILURE;
@@ -62,7 +62,7 @@ static int do_rockusb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
 exit:
        g_dnl_unregister();
        g_dnl_clear_detach();
-       board_usb_cleanup(controller_index, USB_INIT_DEVICE);
+       usb_gadget_release(controller_index);
 
        return ret;
 }
index 2615ada..ce3660d 100644 (file)
@@ -30,7 +30,7 @@ int do_thor_down(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                goto done;
 
        int controller_index = simple_strtoul(usb_controller, NULL, 0);
-       ret = board_usb_init(controller_index, USB_INIT_DEVICE);
+       ret = usb_gadget_initialize(controller_index);
        if (ret) {
                pr_err("USB init failed: %d\n", ret);
                ret = CMD_RET_FAILURE;
@@ -55,7 +55,7 @@ int do_thor_down(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
 exit:
        g_dnl_unregister();
-       board_usb_cleanup(controller_index, USB_INIT_DEVICE);
+       usb_gadget_release(controller_index);
 done:
        dfu_free_entities();
 
index ba1f66a..808ed97 100644 (file)
@@ -20,7 +20,7 @@ static int do_sdp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
        char *usb_controller = argv[1];
        int controller_index = simple_strtoul(usb_controller, NULL, 0);
-       board_usb_init(controller_index, USB_INIT_DEVICE);
+       usb_gadget_initialize(controller_index);
 
        g_dnl_clear_detach();
        g_dnl_register("usb_dnl_sdp");
@@ -37,7 +37,7 @@ static int do_sdp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
 exit:
        g_dnl_unregister();
-       board_usb_cleanup(controller_index, USB_INIT_DEVICE);
+       usb_gadget_release(controller_index);
 
        return ret;
 }
index 0d55114..753ae4f 100644 (file)
@@ -160,7 +160,7 @@ static int do_usb_mass_storage(cmd_tbl_t *cmdtp, int flag,
 
        controller_index = (unsigned int)(simple_strtoul(
                                usb_controller, NULL, 0));
-       if (board_usb_init(controller_index, USB_INIT_DEVICE)) {
+       if (usb_gadget_initialize(controller_index)) {
                pr_err("Couldn't init USB controller.\n");
                rc = CMD_RET_FAILURE;
                goto cleanup_ums_init;
@@ -231,7 +231,7 @@ static int do_usb_mass_storage(cmd_tbl_t *cmdtp, int flag,
 cleanup_register:
        g_dnl_unregister();
 cleanup_board:
-       board_usb_cleanup(controller_index, USB_INIT_DEVICE);
+       usb_gadget_release(controller_index);
 cleanup_ums_init:
        ums_fini();
 
index 2620d32..44d1484 100644 (file)
@@ -23,9 +23,9 @@ int run_usb_dnl_gadget(int usbctrl_index, char *usb_dnl_gadget)
        bool dfu_reset = false;
        int ret, i = 0;
 
-       ret = board_usb_init(usbctrl_index, USB_INIT_DEVICE);
+       ret = usb_gadget_initialize(usbctrl_index);
        if (ret) {
-               pr_err("board usb init failed\n");
+               pr_err("usb_gadget_initialize failed\n");
                return CMD_RET_FAILURE;
        }
        g_dnl_clear_detach();
@@ -84,7 +84,7 @@ int run_usb_dnl_gadget(int usbctrl_index, char *usb_dnl_gadget)
        }
 exit:
        g_dnl_unregister();
-       board_usb_cleanup(usbctrl_index, USB_INIT_DEVICE);
+       usb_gadget_release(usbctrl_index);
 
        if (dfu_reset)
                do_reset(NULL, 0, 0, NULL);
index 5242ab6..32a95ea 100644 (file)
@@ -50,6 +50,7 @@ CONFIG_FASTBOOT_FLASH_MMC_DEV=1
 CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_I2C=y
+CONFIG_MISC=y
 CONFIG_DM_MMC=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_DM_SPI_FLASH=y
@@ -61,6 +62,9 @@ CONFIG_PHY_MICREL_KSZ90X1=y
 CONFIG_DM_ETH=y
 CONFIG_DRIVER_TI_CPSW=y
 CONFIG_MII=y
+CONFIG_PHY=y
+CONFIG_PIPE3_PHY=y
+CONFIG_OMAP_USB2_PHY=y
 CONFIG_DM_PMIC=y
 CONFIG_PMIC_PALMAS=y
 CONFIG_DM_REGULATOR=y
@@ -70,13 +74,15 @@ CONFIG_SPI=y
 CONFIG_DM_SPI=y
 CONFIG_TI_QSPI=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_SPL_DM_USB=y
+CONFIG_DM_USB_GADGET=y
+CONFIG_SPL_DM_USB_GADGET=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_DWC3=y
 CONFIG_USB_DWC3_GADGET=y
-CONFIG_USB_DWC3_OMAP=y
-CONFIG_USB_DWC3_PHY_OMAP=y
-CONFIG_OMAP_USB_PHY=y
+CONFIG_USB_DWC3_GENERIC=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
index be4aa0f..6a05738 100644 (file)
@@ -53,6 +53,7 @@ CONFIG_FASTBOOT_FLASH_MMC_DEV=1
 CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
 CONFIG_DM_GPIO=y
 CONFIG_DM_I2C=y
+CONFIG_MISC=y
 CONFIG_DM_MMC=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_DM_SPI_FLASH=y
@@ -64,6 +65,9 @@ CONFIG_PHY_MICREL_KSZ90X1=y
 CONFIG_DM_ETH=y
 CONFIG_DRIVER_TI_CPSW=y
 CONFIG_MII=y
+CONFIG_PHY=y
+CONFIG_PIPE3_PHY=y
+CONFIG_OMAP_USB2_PHY=y
 CONFIG_DM_PMIC=y
 CONFIG_PMIC_PALMAS=y
 CONFIG_DM_REGULATOR=y
@@ -73,13 +77,15 @@ CONFIG_SPI=y
 CONFIG_DM_SPI=y
 CONFIG_TI_QSPI=y
 CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_SPL_DM_USB=y
+CONFIG_DM_USB_GADGET=y
+CONFIG_SPL_DM_USB_GADGET=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_DWC3=y
 CONFIG_USB_DWC3_GADGET=y
-CONFIG_USB_DWC3_OMAP=y
-CONFIG_USB_DWC3_PHY_OMAP=y
-CONFIG_OMAP_USB_PHY=y
+CONFIG_USB_DWC3_GENERIC=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
index 27f6b5d..1d9509c 100644 (file)
@@ -56,6 +56,7 @@ CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
 CONFIG_DM_GPIO=y
 CONFIG_PCF8575_GPIO=y
 CONFIG_DM_I2C=y
+CONFIG_MISC=y
 CONFIG_DM_MMC=y
 CONFIG_MMC_IO_VOLTAGE=y
 CONFIG_MMC_UHS_SUPPORT=y
@@ -72,6 +73,7 @@ CONFIG_PHY_GIGE=y
 CONFIG_MII=y
 CONFIG_SPL_PHY=y
 CONFIG_PIPE3_PHY=y
+CONFIG_OMAP_USB2_PHY=y
 CONFIG_PMIC_PALMAS=y
 CONFIG_PMIC_LP873X=y
 CONFIG_DM_REGULATOR_FIXED=y
@@ -87,14 +89,14 @@ CONFIG_TIMER=y
 CONFIG_OMAP_TIMER=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
+CONFIG_SPL_DM_USB=y
+CONFIG_DM_USB_GADGET=y
+CONFIG_SPL_DM_USB_GADGET=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
-CONFIG_USB_XHCI_DRA7XX_INDEX=1
 CONFIG_USB_DWC3=y
 CONFIG_USB_DWC3_GADGET=y
-CONFIG_USB_DWC3_OMAP=y
-CONFIG_USB_DWC3_PHY_OMAP=y
-CONFIG_OMAP_USB_PHY=y
+CONFIG_USB_DWC3_GENERIC=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
index 651fc4f..f3be339 100644 (file)
@@ -56,6 +56,7 @@ CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
 CONFIG_DM_GPIO=y
 CONFIG_PCF8575_GPIO=y
 CONFIG_DM_I2C=y
+CONFIG_MISC=y
 CONFIG_DM_MMC=y
 CONFIG_MMC_IO_VOLTAGE=y
 CONFIG_MMC_UHS_SUPPORT=y
@@ -71,6 +72,7 @@ CONFIG_PHY_GIGE=y
 CONFIG_MII=y
 CONFIG_SPL_PHY=y
 CONFIG_PIPE3_PHY=y
+CONFIG_OMAP_USB2_PHY=y
 CONFIG_PMIC_PALMAS=y
 CONFIG_PMIC_LP873X=y
 CONFIG_DM_REGULATOR_FIXED=y
@@ -86,14 +88,14 @@ CONFIG_TIMER=y
 CONFIG_OMAP_TIMER=y
 CONFIG_USB=y
 CONFIG_DM_USB=y
+CONFIG_SPL_DM_USB=y
+CONFIG_DM_USB_GADGET=y
+CONFIG_SPL_DM_USB_GADGET=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
-CONFIG_USB_XHCI_DRA7XX_INDEX=1
 CONFIG_USB_DWC3=y
 CONFIG_USB_DWC3_GADGET=y
-CONFIG_USB_DWC3_OMAP=y
-CONFIG_USB_DWC3_PHY_OMAP=y
-CONFIG_OMAP_USB_PHY=y
+CONFIG_USB_DWC3_GENERIC=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Texas Instruments"
index 5b3bb8e..f022163 100644 (file)
@@ -49,6 +49,7 @@ CONFIG_BAUDRATE=1500000
 CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_SYSRESET=y
 CONFIG_USB=y
+CONFIG_USB_DWC3=y
 CONFIG_USB_XHCI_HCD=y
 CONFIG_USB_XHCI_DWC3=y
 CONFIG_USB_EHCI_HCD=y
index 303e166..661cf61 100644 (file)
@@ -53,6 +53,29 @@ static int syscon_pre_probe(struct udevice *dev)
 #endif
 }
 
+struct regmap *syscon_regmap_lookup_by_phandle(struct udevice *dev,
+                                              const char *name)
+{
+       struct udevice *syscon;
+       struct regmap *r;
+       int err;
+
+       err = uclass_get_device_by_phandle(UCLASS_SYSCON, dev,
+                                          name, &syscon);
+       if (err) {
+               dev_dbg(dev, "unable to find syscon device\n");
+               return ERR_PTR(err);
+       }
+
+       r = syscon_get_regmap(syscon);
+       if (!r) {
+               dev_dbg(dev, "unable to find regmap\n");
+               return ERR_PTR(-ENODEV);
+       }
+
+       return r;
+}
+
 int syscon_get_by_driver_data(ulong driver_data, struct udevice **devp)
 {
        struct udevice *dev;
index 14d82b9..3921e39 100644 (file)
@@ -155,4 +155,13 @@ config MSM8916_USB_PHY
 
          This PHY is found on qualcomm dragonboard410c development board.
 
+config OMAP_USB2_PHY
+       bool "Support OMAP's USB2 PHY"
+       depends on PHY
+       depends on SYSCON
+       help
+         Support for the OMAP's USB2 PHY.
+
+         This PHY is found on OMAP devices supporting USB2.
+
 endmenu
index 8030d59..53dd5bd 100644 (file)
@@ -17,3 +17,4 @@ obj-$(CONFIG_PHY_RCAR_GEN3) += phy-rcar-gen3.o
 obj-$(CONFIG_PHY_STM32_USBPHYC) += phy-stm32-usbphyc.o
 obj-$(CONFIG_MESON_GXL_USB_PHY) += meson-gxl-usb2.o meson-gxl-usb3.o
 obj-$(CONFIG_MSM8916_USB_PHY) += msm8916-usbh-phy.o
+obj-$(CONFIG_OMAP_USB2_PHY) += omap-usb2-phy.o
diff --git a/drivers/phy/omap-usb2-phy.c b/drivers/phy/omap-usb2-phy.c
new file mode 100644 (file)
index 0000000..fd20e8c
--- /dev/null
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * OMAP USB2 PHY LAYER
+ *
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com
+ * Written by Jean-Jacques Hiblot <jjhiblot@ti.com>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <dm.h>
+#include <errno.h>
+#include <generic-phy.h>
+#include <regmap.h>
+#include <syscon.h>
+
+#define OMAP_USB2_CALIBRATE_FALSE_DISCONNECT   BIT(0)
+
+#define OMAP_DEV_PHY_PD                BIT(0)
+#define OMAP_USB2_PHY_PD       BIT(28)
+
+#define USB2PHY_DISCON_BYP_LATCH       BIT(31)
+#define USB2PHY_ANA_CONFIG1            (0x4c)
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct omap_usb2_phy {
+       struct regmap *pwr_regmap;
+       ulong flags;
+       void *phy_base;
+       u32 pwr_reg_offset;
+};
+
+struct usb_phy_data {
+       const char *label;
+       u8 flags;
+       u32 mask;
+       u32 power_on;
+       u32 power_off;
+};
+
+static const struct usb_phy_data omap5_usb2_data = {
+       .label = "omap5_usb2",
+       .flags = 0,
+       .mask = OMAP_DEV_PHY_PD,
+       .power_off = OMAP_DEV_PHY_PD,
+};
+
+static const struct usb_phy_data dra7x_usb2_data = {
+       .label = "dra7x_usb2",
+       .flags = OMAP_USB2_CALIBRATE_FALSE_DISCONNECT,
+       .mask = OMAP_DEV_PHY_PD,
+       .power_off = OMAP_DEV_PHY_PD,
+};
+
+static const struct usb_phy_data dra7x_usb2_phy2_data = {
+       .label = "dra7x_usb2_phy2",
+       .flags = OMAP_USB2_CALIBRATE_FALSE_DISCONNECT,
+       .mask = OMAP_USB2_PHY_PD,
+       .power_off = OMAP_USB2_PHY_PD,
+};
+
+static const struct udevice_id omap_usb2_id_table[] = {
+       {
+               .compatible = "ti,omap5-usb2",
+               .data = (ulong)&omap5_usb2_data,
+       },
+       {
+               .compatible = "ti,dra7x-usb2",
+               .data = (ulong)&dra7x_usb2_data,
+       },
+       {
+               .compatible = "ti,dra7x-usb2-phy2",
+               .data = (ulong)&dra7x_usb2_phy2_data,
+       },
+       {},
+};
+
+static int omap_usb_phy_power(struct phy *usb_phy, bool on)
+{
+       struct udevice *dev = usb_phy->dev;
+       const struct usb_phy_data *data;
+       const struct omap_usb2_phy *phy = dev_get_priv(dev);
+       u32 val;
+       int rc;
+
+       data = (const struct usb_phy_data *)dev_get_driver_data(dev);
+       if (!data)
+               return -EINVAL;
+
+       rc = regmap_read(phy->pwr_regmap, phy->pwr_reg_offset, &val);
+       if (rc)
+               return rc;
+       val &= ~data->mask;
+       if (on)
+               val |= data->power_on;
+       else
+               val |= data->power_off;
+       rc = regmap_write(phy->pwr_regmap, phy->pwr_reg_offset, val);
+       if (rc)
+               return rc;
+
+       return 0;
+}
+
+static int omap_usb2_phy_init(struct phy *usb_phy)
+{
+       struct udevice *dev = usb_phy->dev;
+       struct omap_usb2_phy *priv = dev_get_priv(dev);
+       u32 val;
+
+       if (priv->flags & OMAP_USB2_CALIBRATE_FALSE_DISCONNECT) {
+               /*
+                *
+                * Reduce the sensitivity of internal PHY by enabling the
+                * DISCON_BYP_LATCH of the USB2PHY_ANA_CONFIG1 register. This
+                * resolves issues with certain devices which can otherwise
+                * be prone to false disconnects.
+                *
+                */
+               val = readl(priv->phy_base + USB2PHY_ANA_CONFIG1);
+               val |= USB2PHY_DISCON_BYP_LATCH;
+               writel(val, priv->phy_base + USB2PHY_ANA_CONFIG1);
+       }
+
+       return 0;
+}
+
+static int omap_usb2_phy_power_on(struct phy *usb_phy)
+{
+       return omap_usb_phy_power(usb_phy, true);
+}
+
+static int omap_usb2_phy_power_off(struct phy *usb_phy)
+{
+       return omap_usb_phy_power(usb_phy, false);
+}
+
+static int omap_usb2_phy_exit(struct phy *usb_phy)
+{
+       return omap_usb_phy_power(usb_phy, false);
+}
+
+struct phy_ops omap_usb2_phy_ops = {
+       .init = omap_usb2_phy_init,
+       .power_on = omap_usb2_phy_power_on,
+       .power_off = omap_usb2_phy_power_off,
+       .exit = omap_usb2_phy_exit,
+};
+
+int omap_usb2_phy_probe(struct udevice *dev)
+{
+       int rc;
+       struct regmap *regmap;
+       struct omap_usb2_phy *priv = dev_get_priv(dev);
+       const struct usb_phy_data *data;
+       u32 tmp[2];
+
+       data = (const struct usb_phy_data *)dev_get_driver_data(dev);
+       if (!data)
+               return -EINVAL;
+
+       if (data->flags & OMAP_USB2_CALIBRATE_FALSE_DISCONNECT) {
+               u32 base = dev_read_addr(dev);
+
+               if (base == FDT_ADDR_T_NONE)
+                       return -EINVAL;
+               priv->phy_base = (void *)base;
+               priv->flags |= OMAP_USB2_CALIBRATE_FALSE_DISCONNECT;
+       }
+
+       regmap = syscon_regmap_lookup_by_phandle(dev, "syscon-phy-power");
+       if (IS_ERR(regmap)) {
+               printf("can't get regmap (err %ld)\n", PTR_ERR(regmap));
+               return PTR_ERR(regmap);
+       }
+       priv->pwr_regmap = regmap;
+
+       rc =  dev_read_u32_array(dev, "syscon-phy-power", tmp, 2);
+       if (rc) {
+               printf("couldn't get power reg. offset (err %d)\n", rc);
+               return rc;
+       }
+       priv->pwr_reg_offset = tmp[1];
+
+       return 0;
+}
+
+U_BOOT_DRIVER(omap_usb2_phy) = {
+       .name = "omap_usb2_phy",
+       .id = UCLASS_PHY,
+       .of_match = omap_usb2_id_table,
+       .probe = omap_usb2_phy_probe,
+       .ops = &omap_usb2_phy_ops,
+       .priv_auto_alloc_size = sizeof(struct omap_usb2_phy),
+};
index b22bbaf..e7e78e3 100644 (file)
@@ -141,7 +141,7 @@ static int omap_pipe3_dpll_program(struct omap_pipe3 *pipe3)
        omap_pipe3_writel(pipe3->pll_ctrl_base, PLL_CONFIGURATION1, val);
 
        val = omap_pipe3_readl(pipe3->pll_ctrl_base, PLL_CONFIGURATION2);
-       val &= ~PLL_SELFREQDCO_MASK;
+       val &= ~(PLL_SELFREQDCO_MASK | PLL_IDLE);
        val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT;
        omap_pipe3_writel(pipe3->pll_ctrl_base, PLL_CONFIGURATION2, val);
 
@@ -265,10 +265,13 @@ static int pipe3_exit(struct phy *phy)
                return -EBUSY;
        }
 
-       val = readl(pipe3->pll_reset_reg);
-       writel(val | SATA_PLL_SOFT_RESET, pipe3->pll_reset_reg);
-       mdelay(1);
-       writel(val & ~SATA_PLL_SOFT_RESET, pipe3->pll_reset_reg);
+       if (pipe3->pll_reset_reg) {
+               val = readl(pipe3->pll_reset_reg);
+               writel(val | SATA_PLL_SOFT_RESET, pipe3->pll_reset_reg);
+               mdelay(1);
+               writel(val & ~SATA_PLL_SOFT_RESET, pipe3->pll_reset_reg);
+       }
+
        return 0;
 }
 
@@ -331,9 +334,11 @@ static int pipe3_phy_probe(struct udevice *dev)
        if (!pipe3->power_reg)
                return -EINVAL;
 
-       pipe3->pll_reset_reg = get_reg(dev, "syscon-pllreset");
-       if (!pipe3->pll_reset_reg)
-               return -EINVAL;
+       if (device_is_compatible(dev, "ti,phy-pipe3-sata")) {
+               pipe3->pll_reset_reg = get_reg(dev, "syscon-pllreset");
+               if (!pipe3->pll_reset_reg)
+                       return -EINVAL;
+       }
 
        pipe3->dpll_map = (struct pipe3_dpll_map *)dev_get_driver_data(dev);
 
@@ -350,8 +355,19 @@ static struct pipe3_dpll_map dpll_map_sata[] = {
        { },                                    /* Terminator */
 };
 
+static struct pipe3_dpll_map dpll_map_usb[] = {
+       {12000000, {1250, 5, 4, 20, 0} },       /* 12 MHz */
+       {16800000, {3125, 20, 4, 20, 0} },      /* 16.8 MHz */
+       {19200000, {1172, 8, 4, 20, 65537} },   /* 19.2 MHz */
+       {20000000, {1000, 7, 4, 10, 0} },       /* 20 MHz */
+       {26000000, {1250, 12, 4, 20, 0} },      /* 26 MHz */
+       {38400000, {3125, 47, 4, 20, 92843} },  /* 38.4 MHz */
+       { },                                    /* Terminator */
+};
+
 static const struct udevice_id pipe3_phy_ids[] = {
        { .compatible = "ti,phy-pipe3-sata", .data = (ulong)&dpll_map_sata },
+       { .compatible = "ti,omap-usb3", .data = (ulong)&dpll_map_usb},
        { }
 };
 
index d456beb..98f8343 100644 (file)
@@ -52,6 +52,20 @@ config SPL_DM_USB
        depends on DM_USB
        default y
 
+config DM_USB_GADGET
+       bool "Enable driver model for USB Gadget"
+       depends on DM_USB
+       help
+         Enable driver model for USB Gadget (Peripheral
+         mode)
+
+config SPL_DM_USB_GADGET
+       bool "Enable driver model for USB Gadget in sPL"
+       depends on SPL_DM_USB
+       help
+         Enable driver model for USB Gadget in SPL
+         (Peripheral mode)
+
 source "drivers/usb/host/Kconfig"
 
 source "drivers/usb/dwc3/Kconfig"
index 943b763..bbd8105 100644 (file)
@@ -38,10 +38,11 @@ config USB_DWC3_OMAP
          Say 'Y' here if you have one such device
 
 config USB_DWC3_GENERIC
-       bool "Xilinx ZynqMP and similar Platforms"
-       depends on DM_USB && USB_DWC3
+       bool "Generic implementation of a DWC3 wrapper (aka dwc3 glue)"
+       depends on DM_USB && USB_DWC3 && MISC
        help
-         Some platforms can reuse this DWC3 generic implementation.
+         Select this for Xilinx ZynqMP and similar Platforms.
+         This wrapper supports Host and Peripheral operation modes.
 
 config USB_DWC3_UNIPHIER
        bool "DesignWare USB3 Host Support on UniPhier Platforms"
index f1ca619..56e2a04 100644 (file)
@@ -19,7 +19,7 @@
 #include <asm/dma-mapping.h>
 #include <linux/ioport.h>
 #include <dm.h>
-
+#include <generic-phy.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 
@@ -789,8 +789,92 @@ MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("DesignWare USB3 DRD Controller Driver");
 
-#if CONFIG_IS_ENABLED(DM_USB)
+#if CONFIG_IS_ENABLED(PHY) && CONFIG_IS_ENABLED(DM_USB)
+int dwc3_setup_phy(struct udevice *dev, struct phy **array, int *num_phys)
+{
+       int i, ret, count;
+       struct phy *usb_phys;
+
+       /* Return if no phy declared */
+       if (!dev_read_prop(dev, "phys", NULL))
+               return 0;
+       count = dev_count_phandle_with_args(dev, "phys", "#phy-cells");
+       if (count <= 0)
+               return count;
+
+       usb_phys = devm_kcalloc(dev, count, sizeof(struct phy),
+                               GFP_KERNEL);
+       if (!usb_phys)
+               return -ENOMEM;
+
+       for (i = 0; i < count; i++) {
+               ret = generic_phy_get_by_index(dev, i, &usb_phys[i]);
+               if (ret && ret != -ENOENT) {
+                       pr_err("Failed to get USB PHY%d for %s\n",
+                              i, dev->name);
+                       return ret;
+               }
+       }
+
+       for (i = 0; i < count; i++) {
+               ret = generic_phy_init(&usb_phys[i]);
+               if (ret) {
+                       pr_err("Can't init USB PHY%d for %s\n",
+                              i, dev->name);
+                       goto phys_init_err;
+               }
+       }
+
+       for (i = 0; i < count; i++) {
+               ret = generic_phy_power_on(&usb_phys[i]);
+               if (ret) {
+                       pr_err("Can't power USB PHY%d for %s\n",
+                              i, dev->name);
+                       goto phys_poweron_err;
+               }
+       }
+
+       *array = usb_phys;
+       *num_phys =  count;
+       return 0;
+
+phys_poweron_err:
+       for (i = count - 1; i >= 0; i--)
+               generic_phy_power_off(&usb_phys[i]);
 
+       for (i = 0; i < count; i++)
+               generic_phy_exit(&usb_phys[i]);
+
+       return ret;
+
+phys_init_err:
+       for (; i >= 0; i--)
+               generic_phy_exit(&usb_phys[i]);
+
+       return ret;
+}
+
+int dwc3_shutdown_phy(struct udevice *dev, struct phy *usb_phys, int num_phys)
+{
+       int i, ret;
+
+       for (i = 0; i < num_phys; i++) {
+               if (!generic_phy_valid(&usb_phys[i]))
+                       continue;
+
+               ret = generic_phy_power_off(&usb_phys[i]);
+               ret |= generic_phy_exit(&usb_phys[i]);
+               if (ret) {
+                       pr_err("Can't shutdown USB PHY%d for %s\n",
+                              i, dev->name);
+               }
+       }
+
+       return 0;
+}
+#endif
+
+#if CONFIG_IS_ENABLED(DM_USB_GADGET)
 int dwc3_init(struct dwc3 *dwc)
 {
        int ret;
@@ -841,5 +925,4 @@ void dwc3_remove(struct dwc3 *dwc)
        dwc3_core_exit(dwc);
        kfree(dwc->mem);
 }
-
 #endif
index 56c9fd6..bc6bba1 100644 (file)
@@ -8,72 +8,89 @@
  */
 
 #include <common.h>
+#include <asm-generic/io.h>
 #include <dm.h>
 #include <dm/device-internal.h>
 #include <dm/lists.h>
-#include <linux/usb/otg.h>
-#include <linux/compat.h>
+#include <dwc3-uboot.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 #include <malloc.h>
 #include <usb.h>
 #include "core.h"
 #include "gadget.h"
-#include "linux-compat.h"
+#include <reset.h>
+#include <clk.h>
 
-DECLARE_GLOBAL_DATA_PTR;
+#if CONFIG_IS_ENABLED(DM_USB_GADGET)
+struct dwc3_generic_peripheral {
+       struct dwc3 dwc3;
+       struct phy *phys;
+       int num_phys;
+       fdt_addr_t base;
+};
 
-int usb_gadget_handle_interrupts(int index)
+int dm_usb_gadget_handle_interrupts(struct udevice *dev)
 {
-       struct dwc3 *priv;
-       struct udevice *dev;
-       int ret;
-
-       ret = uclass_first_device(UCLASS_USB_DEV_GENERIC, &dev);
-       if (!dev || ret) {
-               pr_err("No USB device found\n");
-               return -ENODEV;
-       }
-
-       priv = dev_get_priv(dev);
+       struct dwc3_generic_peripheral *priv = dev_get_priv(dev);
+       struct dwc3 *dwc3 = &priv->dwc3;
 
-       dwc3_gadget_uboot_handle_interrupt(priv);
+       dwc3_gadget_uboot_handle_interrupt(dwc3);
 
        return 0;
 }
 
 static int dwc3_generic_peripheral_probe(struct udevice *dev)
 {
-       struct dwc3 *priv = dev_get_priv(dev);
+       int rc;
+       struct dwc3_generic_peripheral *priv = dev_get_priv(dev);
+       struct dwc3 *dwc3 = &priv->dwc3;
 
-       return dwc3_init(priv);
+       rc = dwc3_setup_phy(dev, &priv->phys, &priv->num_phys);
+       if (rc)
+               return rc;
+
+       dwc3->regs = map_physmem(priv->base, DWC3_OTG_REGS_END, MAP_NOCACHE);
+       dwc3->regs += DWC3_GLOBALS_REGS_START;
+       dwc3->dev = dev;
+
+       rc =  dwc3_init(dwc3);
+       if (rc) {
+               unmap_physmem(dwc3->regs, MAP_NOCACHE);
+               return rc;
+       }
+
+       return 0;
 }
 
 static int dwc3_generic_peripheral_remove(struct udevice *dev)
 {
-       struct dwc3 *priv = dev_get_priv(dev);
+       struct dwc3_generic_peripheral *priv = dev_get_priv(dev);
+       struct dwc3 *dwc3 = &priv->dwc3;
 
-       dwc3_remove(priv);
+       dwc3_remove(dwc3);
+       dwc3_shutdown_phy(dev, priv->phys, priv->num_phys);
+       unmap_physmem(dwc3->regs, MAP_NOCACHE);
 
        return 0;
 }
 
 static int dwc3_generic_peripheral_ofdata_to_platdata(struct udevice *dev)
 {
-       struct dwc3 *priv = dev_get_priv(dev);
+       struct dwc3_generic_peripheral *priv = dev_get_priv(dev);
+       struct dwc3 *dwc3 = &priv->dwc3;
        int node = dev_of_offset(dev);
 
-       priv->regs = (void *)devfdt_get_addr(dev);
-       priv->regs += DWC3_GLOBALS_REGS_START;
+       priv->base = devfdt_get_addr(dev);
 
-       priv->maximum_speed = usb_get_maximum_speed(node);
-       if (priv->maximum_speed == USB_SPEED_UNKNOWN) {
+       dwc3->maximum_speed = usb_get_maximum_speed(node);
+       if (dwc3->maximum_speed == USB_SPEED_UNKNOWN) {
                pr_err("Invalid usb maximum speed\n");
                return -ENODEV;
        }
 
-       priv->dr_mode = usb_get_dr_mode(node);
-       if (priv->dr_mode == USB_DR_MODE_UNKNOWN) {
+       dwc3->dr_mode = usb_get_dr_mode(node);
+       if (dwc3->dr_mode == USB_DR_MODE_UNKNOWN) {
                pr_err("Invalid usb mode setup\n");
                return -ENODEV;
        }
@@ -81,24 +98,112 @@ static int dwc3_generic_peripheral_ofdata_to_platdata(struct udevice *dev)
        return 0;
 }
 
-static int dwc3_generic_peripheral_bind(struct udevice *dev)
-{
-       return device_probe(dev);
-}
-
 U_BOOT_DRIVER(dwc3_generic_peripheral) = {
        .name   = "dwc3-generic-peripheral",
-       .id     = UCLASS_USB_DEV_GENERIC,
+       .id     = UCLASS_USB_GADGET_GENERIC,
        .ofdata_to_platdata = dwc3_generic_peripheral_ofdata_to_platdata,
        .probe = dwc3_generic_peripheral_probe,
        .remove = dwc3_generic_peripheral_remove,
-       .bind = dwc3_generic_peripheral_bind,
-       .platdata_auto_alloc_size = sizeof(struct usb_platdata),
-       .priv_auto_alloc_size = sizeof(struct dwc3),
-       .flags  = DM_FLAG_ALLOC_PRIV_DMA,
+       .priv_auto_alloc_size = sizeof(struct dwc3_generic_peripheral),
+};
+#endif
+
+struct dwc3_glue_data {
+       struct clk_bulk         clks;
+       struct reset_ctl_bulk   resets;
+       fdt_addr_t regs;
 };
 
-static int dwc3_generic_bind(struct udevice *parent)
+struct dwc3_glue_ops {
+       void (*select_dr_mode)(struct udevice *dev, int index,
+                              enum usb_dr_mode mode);
+};
+
+void dwc3_ti_select_dr_mode(struct udevice *dev, int index,
+                           enum usb_dr_mode mode)
+{
+#define USBOTGSS_UTMI_OTG_STATUS               0x0084
+#define USBOTGSS_UTMI_OTG_OFFSET               0x0480
+
+/* UTMI_OTG_STATUS REGISTER */
+#define USBOTGSS_UTMI_OTG_STATUS_SW_MODE       BIT(31)
+#define USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT  BIT(9)
+#define USBOTGSS_UTMI_OTG_STATUS_TXBITSTUFFENABLE BIT(8)
+#define USBOTGSS_UTMI_OTG_STATUS_IDDIG         BIT(4)
+#define USBOTGSS_UTMI_OTG_STATUS_SESSEND       BIT(3)
+#define USBOTGSS_UTMI_OTG_STATUS_SESSVALID     BIT(2)
+#define USBOTGSS_UTMI_OTG_STATUS_VBUSVALID     BIT(1)
+enum dwc3_omap_utmi_mode {
+       DWC3_OMAP_UTMI_MODE_UNKNOWN = 0,
+       DWC3_OMAP_UTMI_MODE_HW,
+       DWC3_OMAP_UTMI_MODE_SW,
+};
+
+       u32 use_id_pin;
+       u32 host_mode;
+       u32 reg;
+       u32 utmi_mode;
+       u32 utmi_status_offset = USBOTGSS_UTMI_OTG_STATUS;
+
+       struct dwc3_glue_data *glue = dev_get_platdata(dev);
+       void *base = map_physmem(glue->regs, 0x10000, MAP_NOCACHE);
+
+       if (device_is_compatible(dev, "ti,am437x-dwc3"))
+               utmi_status_offset += USBOTGSS_UTMI_OTG_OFFSET;
+
+       utmi_mode = dev_read_u32_default(dev, "utmi-mode",
+                                        DWC3_OMAP_UTMI_MODE_UNKNOWN);
+       if (utmi_mode != DWC3_OMAP_UTMI_MODE_HW) {
+               debug("%s: OTG is not supported. defaulting to PERIPHERAL\n",
+                     dev->name);
+               mode = USB_DR_MODE_PERIPHERAL;
+       }
+
+       switch (mode)  {
+       case USB_DR_MODE_PERIPHERAL:
+               use_id_pin = 0;
+               host_mode = 0;
+               break;
+       case USB_DR_MODE_HOST:
+               use_id_pin = 0;
+               host_mode = 1;
+               break;
+       case USB_DR_MODE_OTG:
+       default:
+               use_id_pin = 1;
+               host_mode = 0;
+               break;
+       }
+
+       reg = readl(base + utmi_status_offset);
+
+       reg &= ~(USBOTGSS_UTMI_OTG_STATUS_SW_MODE);
+       if (!use_id_pin)
+               reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
+
+       writel(reg, base + utmi_status_offset);
+
+       reg &= ~(USBOTGSS_UTMI_OTG_STATUS_SESSEND |
+               USBOTGSS_UTMI_OTG_STATUS_VBUSVALID |
+               USBOTGSS_UTMI_OTG_STATUS_IDDIG);
+
+       reg |= USBOTGSS_UTMI_OTG_STATUS_SESSVALID |
+               USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT;
+
+       if (!host_mode)
+               reg |= USBOTGSS_UTMI_OTG_STATUS_IDDIG |
+                       USBOTGSS_UTMI_OTG_STATUS_VBUSVALID;
+
+       writel(reg, base + utmi_status_offset);
+
+       unmap_physmem(base, MAP_NOCACHE);
+}
+
+struct dwc3_glue_ops ti_ops = {
+       .select_dr_mode = dwc3_ti_select_dr_mode,
+};
+
+static int dwc3_glue_bind(struct udevice *parent)
 {
        const void *fdt = gd->fdt_blob;
        int node;
@@ -109,29 +214,32 @@ static int dwc3_generic_bind(struct udevice *parent)
                const char *name = fdt_get_name(fdt, node, NULL);
                enum usb_dr_mode dr_mode;
                struct udevice *dev;
-               const char *driver;
+               const char *driver = NULL;
 
                debug("%s: subnode name: %s\n", __func__, name);
-               if (strncmp(name, "dwc3@", 4))
-                       continue;
 
                dr_mode = usb_get_dr_mode(node);
 
                switch (dr_mode) {
                case USB_DR_MODE_PERIPHERAL:
                case USB_DR_MODE_OTG:
+#if CONFIG_IS_ENABLED(DM_USB_GADGET)
                        debug("%s: dr_mode: OTG or Peripheral\n", __func__);
                        driver = "dwc3-generic-peripheral";
+#endif
                        break;
                case USB_DR_MODE_HOST:
                        debug("%s: dr_mode: HOST\n", __func__);
-                       driver = "dwc3-generic-host";
+                       driver = "xhci-dwc3";
                        break;
                default:
                        debug("%s: unsupported dr_mode\n", __func__);
                        return -ENODEV;
                };
 
+               if (!driver)
+                       continue;
+
                ret = device_bind_driver_to_node(parent, driver, name,
                                                 offset_to_ofnode(node), &dev);
                if (ret) {
@@ -144,14 +252,107 @@ static int dwc3_generic_bind(struct udevice *parent)
        return 0;
 }
 
-static const struct udevice_id dwc3_generic_ids[] = {
+static int dwc3_glue_reset_init(struct udevice *dev,
+                               struct dwc3_glue_data *glue)
+{
+       int ret;
+
+       ret = reset_get_bulk(dev, &glue->resets);
+       if (ret == -ENOTSUPP)
+               return 0;
+       else if (ret)
+               return ret;
+
+       ret = reset_deassert_bulk(&glue->resets);
+       if (ret) {
+               reset_release_bulk(&glue->resets);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int dwc3_glue_clk_init(struct udevice *dev,
+                             struct dwc3_glue_data *glue)
+{
+       int ret;
+
+       ret = clk_get_bulk(dev, &glue->clks);
+       if (ret == -ENOSYS)
+               return 0;
+       if (ret)
+               return ret;
+
+#if CONFIG_IS_ENABLED(CLK)
+       ret = clk_enable_bulk(&glue->clks);
+       if (ret) {
+               clk_release_bulk(&glue->clks);
+               return ret;
+       }
+#endif
+
+       return 0;
+}
+
+static int dwc3_glue_probe(struct udevice *dev)
+{
+       struct dwc3_glue_ops *ops = (struct dwc3_glue_ops *)dev_get_driver_data(dev);
+       struct dwc3_glue_data *glue = dev_get_platdata(dev);
+       struct udevice *child = NULL;
+       int index = 0;
+       int ret;
+
+       glue->regs = dev_read_addr(dev);
+
+       ret = dwc3_glue_clk_init(dev, glue);
+       if (ret)
+               return ret;
+
+       ret = dwc3_glue_reset_init(dev, glue);
+       if (ret)
+               return ret;
+
+       ret = device_find_first_child(dev, &child);
+       if (ret)
+               return ret;
+
+       while (child) {
+               enum usb_dr_mode dr_mode;
+
+               dr_mode = usb_get_dr_mode(dev_of_offset(child));
+               device_find_next_child(&child);
+               if (ops && ops->select_dr_mode)
+                       ops->select_dr_mode(dev, index, dr_mode);
+               index++;
+       }
+
+       return 0;
+}
+
+static int dwc3_glue_remove(struct udevice *dev)
+{
+       struct dwc3_glue_data *glue = dev_get_platdata(dev);
+
+       reset_release_bulk(&glue->resets);
+
+       clk_release_bulk(&glue->clks);
+
+       return dm_scan_fdt_dev(dev);
+}
+
+static const struct udevice_id dwc3_glue_ids[] = {
        { .compatible = "xlnx,zynqmp-dwc3" },
+       { .compatible = "ti,dwc3", .data = (ulong)&ti_ops },
        { }
 };
 
 U_BOOT_DRIVER(dwc3_generic_wrapper) = {
        .name   = "dwc3-generic-wrapper",
        .id     = UCLASS_MISC,
-       .of_match = dwc3_generic_ids,
-       .bind = dwc3_generic_bind,
+       .of_match = dwc3_glue_ids,
+       .bind = dwc3_glue_bind,
+       .probe = dwc3_glue_probe,
+       .remove = dwc3_glue_remove,
+       .platdata_auto_alloc_size = sizeof(struct dwc3_glue_data),
+
 };
index 4f68887..818efb3 100644 (file)
@@ -12,7 +12,7 @@
  *
  * commit c00552ebaf : Merge 3.18-rc7 into usb-next
  */
-
+#include <common.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
 
index 193583b..3b3d9af 100644 (file)
@@ -100,9 +100,6 @@ struct eth_dev {
        struct usb_gadget       *gadget;
        struct usb_request      *req;           /* for control responses */
        struct usb_request      *stat_req;      /* for cdc & rndis status */
-#if CONFIG_IS_ENABLED(DM_USB)
-       struct udevice          *usb_udev;
-#endif
 
        u8                      config;
        struct usb_ep           *in_ep, *out_ep, *status_ep;
@@ -2336,40 +2333,17 @@ fail:
 }
 
 /*-------------------------------------------------------------------------*/
-
-#if CONFIG_IS_ENABLED(DM_USB)
-int dm_usb_init(struct eth_dev *e_dev)
-{
-       struct udevice *dev = NULL;
-       int ret;
-
-       ret = uclass_first_device(UCLASS_USB_DEV_GENERIC, &dev);
-       if (!dev || ret) {
-               pr_err("No USB device found\n");
-               return -ENODEV;
-       }
-
-       e_dev->usb_udev = dev;
-
-       return ret;
-}
-#endif
-
 static int _usb_eth_init(struct ether_priv *priv)
 {
        struct eth_dev *dev = &priv->ethdev;
        struct usb_gadget *gadget;
        unsigned long ts;
+       int ret;
        unsigned long timeout = USB_CONNECT_TIMEOUT;
 
-#if CONFIG_IS_ENABLED(DM_USB)
-       if (dm_usb_init(dev)) {
-               pr_err("USB ether not found\n");
-               return -ENODEV;
-       }
-#else
-       board_usb_init(0, USB_INIT_DEVICE);
-#endif
+       ret = usb_gadget_initialize(0);
+       if (ret)
+               return ret;
 
        /* Configure default mac-addresses for the USB ethernet device */
 #ifdef CONFIG_USBNET_DEV_ADDR
@@ -2541,9 +2515,7 @@ void _usb_eth_halt(struct ether_priv *priv)
        }
 
        usb_gadget_unregister_driver(&priv->eth_driver);
-#if !CONFIG_IS_ENABLED(DM_USB)
-       board_usb_cleanup(0, USB_INIT_DEVICE);
-#endif
+       usb_gadget_release(0);
 }
 
 #ifndef CONFIG_DM_ETH
@@ -2699,7 +2671,7 @@ int usb_ether_init(void)
        struct udevice *usb_dev;
        int ret;
 
-       ret = uclass_first_device(UCLASS_USB_DEV_GENERIC, &usb_dev);
+       ret = uclass_first_device(UCLASS_USB_GADGET_GENERIC, &usb_dev);
        if (!usb_dev || ret) {
                pr_err("No USB device found\n");
                return ret;
index 449339f..38ac2dd 100644 (file)
@@ -2,4 +2,8 @@
 #
 # USB peripheral controller drivers
 
+ifndef CONFIG_$(SPL_)DM_USB_GADGET
 obj-$(CONFIG_USB_DWC3_GADGET)  += udc-core.o
+endif
+
+obj-$(CONFIG_$(SPL_)DM_USB_GADGET)     += udc-uclass.o udc-core.o
index f5c30dd..62b4778 100644 (file)
@@ -18,7 +18,8 @@
 #include <asm/cache.h>
 #include <asm/dma-mapping.h>
 #include <common.h>
-
+#include <dm.h>
+#include <dm/device-internal.h>
 #include <linux/usb/ch9.h>
 #include <linux/usb/gadget.h>
 
diff --git a/drivers/usb/gadget/udc/udc-uclass.c b/drivers/usb/gadget/udc/udc-uclass.c
new file mode 100644 (file)
index 0000000..0620518
--- /dev/null
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com
+ * Written by Jean-Jacques Hiblot <jjhiblot@ti.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <linux/usb/gadget.h>
+
+#define MAX_UDC_DEVICES 4
+static struct udevice *dev_array[MAX_UDC_DEVICES];
+int usb_gadget_initialize(int index)
+{
+       int ret;
+       struct udevice *dev = NULL;
+
+       if (index < 0 || index >= ARRAY_SIZE(dev_array))
+               return -EINVAL;
+       if (dev_array[index])
+               return 0;
+       ret = uclass_get_device(UCLASS_USB_GADGET_GENERIC, index, &dev);
+       if (!dev || ret) {
+               pr_err("No USB device found\n");
+               return -ENODEV;
+       }
+       dev_array[index] = dev;
+       return 0;
+}
+
+int usb_gadget_release(int index)
+{
+#if CONFIG_IS_ENABLED(DM_DEVICE_REMOVE)
+       int ret;
+       if (index < 0 || index >= ARRAY_SIZE(dev_array))
+               return -EINVAL;
+
+       ret = device_remove(dev_array[index], DM_REMOVE_NORMAL);
+       if (!ret)
+               dev_array[index] = NULL;
+       return ret;
+#else
+       return -ENOTSUPP;
+#endif
+}
+
+int usb_gadget_handle_interrupts(int index)
+{
+       if (index < 0 || index >= ARRAY_SIZE(dev_array))
+               return -EINVAL;
+       return dm_usb_gadget_handle_interrupts(dev_array[index]);
+}
+
+UCLASS_DRIVER(usb_gadget_generic) = {
+       .id             = UCLASS_USB_GADGET_GENERIC,
+       .name           = "usb_gadget_generic",
+};
index dd0d156..83b9f11 100644 (file)
@@ -12,6 +12,7 @@
 #include <fdtdec.h>
 #include <generic-phy.h>
 #include <usb.h>
+#include <dwc3-uboot.h>
 
 #include "xhci.h"
 #include <asm/io.h>
@@ -110,105 +111,21 @@ void dwc3_set_fladj(struct dwc3 *dwc3_reg, u32 val)
 }
 
 #if CONFIG_IS_ENABLED(DM_USB)
-static int xhci_dwc3_setup_phy(struct udevice *dev)
-{
-       struct xhci_dwc3_platdata *plat = dev_get_platdata(dev);
-       int i, ret, count;
-
-       /* Return if no phy declared */
-       if (!dev_read_prop(dev, "phys", NULL))
-               return 0;
-
-       count = dev_count_phandle_with_args(dev, "phys", "#phy-cells");
-       if (count <= 0)
-               return count;
-
-       plat->usb_phys = devm_kcalloc(dev, count, sizeof(struct phy),
-                                     GFP_KERNEL);
-       if (!plat->usb_phys)
-               return -ENOMEM;
-
-       for (i = 0; i < count; i++) {
-               ret = generic_phy_get_by_index(dev, i, &plat->usb_phys[i]);
-               if (ret && ret != -ENOENT) {
-                       pr_err("Failed to get USB PHY%d for %s\n",
-                              i, dev->name);
-                       return ret;
-               }
-
-               ++plat->num_phys;
-       }
-
-       for (i = 0; i < plat->num_phys; i++) {
-               ret = generic_phy_init(&plat->usb_phys[i]);
-               if (ret) {
-                       pr_err("Can't init USB PHY%d for %s\n",
-                              i, dev->name);
-                       goto phys_init_err;
-               }
-       }
-
-       for (i = 0; i < plat->num_phys; i++) {
-               ret = generic_phy_power_on(&plat->usb_phys[i]);
-               if (ret) {
-                       pr_err("Can't power USB PHY%d for %s\n",
-                              i, dev->name);
-                       goto phys_poweron_err;
-               }
-       }
-
-       return 0;
-
-phys_poweron_err:
-       for (; i >= 0; i--)
-               generic_phy_power_off(&plat->usb_phys[i]);
-
-       for (i = 0; i < plat->num_phys; i++)
-               generic_phy_exit(&plat->usb_phys[i]);
-
-       return ret;
-
-phys_init_err:
-       for (; i >= 0; i--)
-               generic_phy_exit(&plat->usb_phys[i]);
-
-       return ret;
-}
-
-static int xhci_dwc3_shutdown_phy(struct udevice *dev)
-{
-       struct xhci_dwc3_platdata *plat = dev_get_platdata(dev);
-       int i, ret;
-
-       for (i = 0; i < plat->num_phys; i++) {
-               if (!generic_phy_valid(&plat->usb_phys[i]))
-                       continue;
-
-               ret = generic_phy_power_off(&plat->usb_phys[i]);
-               ret |= generic_phy_exit(&plat->usb_phys[i]);
-               if (ret) {
-                       pr_err("Can't shutdown USB PHY%d for %s\n",
-                              i, dev->name);
-               }
-       }
-
-       return 0;
-}
-
 static int xhci_dwc3_probe(struct udevice *dev)
 {
        struct xhci_hcor *hcor;
        struct xhci_hccr *hccr;
        struct dwc3 *dwc3_reg;
        enum usb_dr_mode dr_mode;
+       struct xhci_dwc3_platdata *plat = dev_get_platdata(dev);
        int ret;
 
        hccr = (struct xhci_hccr *)((uintptr_t)dev_read_addr(dev));
        hcor = (struct xhci_hcor *)((uintptr_t)hccr +
                        HC_LENGTH(xhci_readl(&(hccr)->cr_capbase)));
 
-       ret = xhci_dwc3_setup_phy(dev);
-       if (ret)
+       ret = dwc3_setup_phy(dev, &plat->usb_phys, &plat->num_phys);
+       if (ret && (ret != -ENOTSUPP))
                return ret;
 
        dwc3_reg = (struct dwc3 *)((char *)(hccr) + DWC3_REG_OFFSET);
@@ -227,7 +144,9 @@ static int xhci_dwc3_probe(struct udevice *dev)
 
 static int xhci_dwc3_remove(struct udevice *dev)
 {
-       xhci_dwc3_shutdown_phy(dev);
+       struct xhci_dwc3_platdata *plat = dev_get_platdata(dev);
+
+       dwc3_shutdown_phy(dev, plat->usb_phys, plat->num_phys);
 
        return xhci_deregister(dev);
 }
index 58aed72..32743aa 100644 (file)
@@ -263,7 +263,7 @@ U_BOOT_DRIVER(omap2430_musb) = {
 #ifdef CONFIG_USB_MUSB_HOST
        .id             = UCLASS_USB,
 #else
-       .id             = UCLASS_USB_DEV_GENERIC,
+       .id             = UCLASS_USB_GADGET_GENERIC,
 #endif
        .of_match = omap2430_musb_ids,
        .ofdata_to_platdata = omap2430_musb_ofdata_to_platdata,
index 6cf9826..d7170a3 100644 (file)
@@ -535,7 +535,7 @@ U_BOOT_DRIVER(usb_musb) = {
 #ifdef CONFIG_USB_MUSB_HOST
        .id             = UCLASS_USB,
 #else
-       .id             = UCLASS_USB_DEV_GENERIC,
+       .id             = UCLASS_USB_GADGET_GENERIC,
 #endif
        .of_match       = sunxi_musb_ids,
        .probe          = musb_usb_probe,
index 037af04..5d4e207 100644 (file)
@@ -94,6 +94,7 @@ enum uclass_id {
        UCLASS_USB,             /* USB bus */
        UCLASS_USB_DEV_GENERIC, /* USB generic device */
        UCLASS_USB_HUB,         /* USB hub */
+       UCLASS_USB_GADGET_GENERIC,      /* USB generic device */
        UCLASS_VIDEO,           /* Video or LCD device */
        UCLASS_VIDEO_BRIDGE,    /* Video bridge, e.g. DisplayPort to LVDS */
        UCLASS_VIDEO_CONSOLE,   /* Text console driver for video device */
index 228ab3b..9941cc3 100644 (file)
@@ -38,4 +38,23 @@ struct dwc3_device {
 int dwc3_uboot_init(struct dwc3_device *dev);
 void dwc3_uboot_exit(int index);
 void dwc3_uboot_handle_interrupt(int index);
+
+struct phy;
+#if CONFIG_IS_ENABLED(PHY) && CONFIG_IS_ENABLED(DM_USB)
+int dwc3_setup_phy(struct udevice *dev, struct phy **array, int *num_phys);
+int dwc3_shutdown_phy(struct udevice *dev, struct phy *usb_phys, int num_phys);
+#else
+static inline int dwc3_setup_phy(struct udevice *dev, struct phy **array,
+                                int *num_phys)
+{
+       return -ENOTSUPP;
+}
+
+static inline int dwc3_shutdown_phy(struct udevice *dev, struct phy *usb_phys,
+                                   int num_phys)
+{
+       return -ENOTSUPP;
+}
+#endif
+
 #endif /* __DWC3_UBOOT_H_ */
index b824f13..497798a 100644 (file)
@@ -19,6 +19,7 @@
 #define __LINUX_USB_GADGET_H
 
 #include <errno.h>
+#include <usb.h>
 #include <linux/compat.h>
 #include <linux/list.h>
 
@@ -926,4 +927,21 @@ extern void usb_ep_autoconfig_reset(struct usb_gadget *);
 
 extern int usb_gadget_handle_interrupts(int index);
 
+#if CONFIG_IS_ENABLED(DM_USB_GADGET)
+int usb_gadget_initialize(int index);
+int usb_gadget_release(int index);
+int dm_usb_gadget_handle_interrupts(struct udevice *dev);
+#else
+#include <usb.h>
+static inline int usb_gadget_initialize(int index)
+{
+       return board_usb_init(index, USB_INIT_DEVICE);
+}
+
+static inline int usb_gadget_release(int index)
+{
+       return board_usb_cleanup(index, USB_INIT_DEVICE);
+}
+#endif
+
 #endif /* __LINUX_USB_GADGET_H */
index 2aa73e5..3df96e3 100644 (file)
@@ -74,6 +74,19 @@ int syscon_get_by_driver_data(ulong driver_data, struct udevice **devp);
 struct regmap *syscon_get_regmap_by_driver_data(ulong driver_data);
 
 /**
+ * syscon_regmap_lookup_by_phandle() - Look up a controller by a phandle
+ *
+ * This operates by looking up the given name in the device (device
+ * tree property) of the device using the system controller.
+ *
+ * @dev:       Device using the system controller
+ * @name:      Name of property referring to the system controller
+ * @return     A pointer to the regmap if found, ERR_PTR(-ve) on error
+ */
+struct regmap *syscon_regmap_lookup_by_phandle(struct udevice *dev,
+                                              const char *name);
+
+/**
  * syscon_get_first_range() - get the first memory range from a syscon regmap
  *
  * @driver_data:       Driver data value to look up
index 77c7928..a294dda 100644 (file)
@@ -6,6 +6,7 @@
 #include <common.h>
 #include <dm.h>
 #include <syscon.h>
+#include <regmap.h>
 #include <asm/test.h>
 #include <dm/test.h>
 #include <test/ut.h>
@@ -43,3 +44,31 @@ static int dm_test_syscon_by_driver_data(struct unit_test_state *uts)
        return 0;
 }
 DM_TEST(dm_test_syscon_by_driver_data, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);
+
+/* Test system controller by phandle */
+static int dm_test_syscon_by_phandle(struct unit_test_state *uts)
+{
+       struct udevice *dev;
+       struct regmap *map;
+
+       ut_assertok(uclass_get_device_by_name(UCLASS_TEST_PROBE, "test4",
+                                             &dev));
+
+       ut_assertok_ptr(syscon_regmap_lookup_by_phandle(dev, "first-syscon"));
+       map = syscon_regmap_lookup_by_phandle(dev, "first-syscon");
+       ut_assert(map);
+       ut_assert(!IS_ERR(map));
+       ut_asserteq(1, map->range_count);
+
+       ut_assertok_ptr(syscon_regmap_lookup_by_phandle(dev,
+                                                       "second-sys-ctrl"));
+       map = syscon_regmap_lookup_by_phandle(dev, "second-sys-ctrl");
+       ut_assert(map);
+       ut_assert(!IS_ERR(map));
+       ut_asserteq(4, map->range_count);
+
+       ut_assert(IS_ERR(syscon_regmap_lookup_by_phandle(dev, "not-present")));
+
+       return 0;
+}
+DM_TEST(dm_test_syscon_by_phandle, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);