This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Linux/AM5728: DFU support on IDK

Part Number: AM5728

Tool/software: Linux

Hi,

we have been viewing the DFU support video for AM57xx, which Bin Liu did a great job on.

Additionally we have been reviewing the u-boot user guide, and validated the DFU support on a DRA7xx EVM using the latest SDK 4.03.

We understand that the AM57xx EVM has a Hub chip on USB1 port, therefore the EVM cannot be used for DFU.

However we wanted to see if we could get the DFU support to work with an AM5728 IDK, which connects the USB1 directly to a connector. The thinking is that as long as we connect the USB cable with the right adapter, that the AM5728 will enumerate as device with an external Host PC.

The result is that the Boot ROM actually is able to enumerate with the external Host PC correctly.

Then we tested whether whether we can make the SPL work, building it with the AM57xx defconfig with the DFU support as prescribed by the UG. But when loading via DFU, we are getting the following error:

U-Boot SPL 2017.01-00458-g32d3fcd-dirty (Jun 20 2018 - 10:25:23)
DRA752-GP ES2.0
Trying to boot from DFU
Using default environment

port 0 can't be used as device
ERROR: board usb init failed

at common/dfu.c:29/run_usb_dnl_gadget()

Looking at the board files in u-boot of AM57xx vs DRA7xx, I think we need to change the function board_usb_init to force the AM57xx to setup its USB1 as device.

~/ti-processor-sdk-linux-am57xx-evm-04.03.00.05/board-support/u-boot-2017.01+gitAUTOINC+c68ed086bd-gc68ed086bd/board/ti$ diff -Nurp am57xx/board.c dra7xx/evm.c

...

 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;
+ 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;
...

The original code in the AM57xx board.c was written such that if one wants to configure the port 0 (USB1) as Device, that it will not allow that. This makes sense given that the AM57xx EVM has a Hub chip on USB1, thereby forcing Host mode.

Could you let me know your thoughts and whether there is anything else we are missing?

Thanks,

--Gunter

  • Hi Gunter,

    Your observation is correct, the uboot code implements the usb port function based on the board design, the AM57x EVM and AM57x IDKs define the USB1 to be the host port with type-A receptacle, so device mode is not allowed.

    I rarely read the uboot code, and don't know how the device mode is initialized, but I have helped some customers to enable USB2 port, which is the device port on the EVM and IDKs, to be the host mode. It is more about switching the base address of each usb module - usb subsystem, controller, and the PHY. I believe the device mode is done in the similar way.

    I could review the uboot code to see how to switch USB1 port to device mode and come up with a patch, but it won't happen in next week or two.
  • Hi Bin,

    thanks for checking. If you have some patches that could steer me in the right direction for switching USB1 from host to device (even if that is via patches of USB2 from device to host), then I could check more into it.

    Is there something you can share?

    Thanks,

    --Gunter

  • Gunter,

    I don't have it ready now, but I will take a look and create the patch. it won't be very soon, is it okay to deliver it in a few weeks?
  • Hi Gunter,

    The patch below can enable USB1 port to device mode in uboot for AM57x. I tested it on the IDK EVM. Please note that you don't want to directly validate the patch on the IDK EVM without hw modification, or you could damage the USB host port on the PC, because the IDK USB1 port is designed to be host-only mode, which sources VBUS power.

    diff --git a/board/ti/am57xx/board.c b/board/ti/am57xx/board.c
    index 5f2d4dfab8c5..09d7f3ff17a9 100644
    --- a/board/ti/am57xx/board.c
    +++ b/board/ti/am57xx/board.c
    @@ -585,6 +585,26 @@ int spl_start_uboot(void)
     #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_HIGH,
            .base = DRA7_USB_OTG_SS2_BASE,
    @@ -622,9 +642,13 @@ int board_usb_init(int index, enum usb_init_type init)
            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;
    +#ifdef CONFIG_USB_DWC3
    +                       usb_otg_ss1.dr_mode = USB_DR_MODE_PERIPHERAL;
    +                       usb_otg_ss1_glue.vbus_id_status = OMAP_DWC3_VBUS_VALID;
    +                       ti_usb_phy_uboot_init(&usb_phy1_device);
    +                       dwc3_omap_uboot_init(&usb_otg_ss1_glue);
    +                       dwc3_uboot_init(&usb_otg_ss1);
    +#endif
                    }
                    break;
            case 1:
    
  • I attached the patch below so you can directly download and apply it.

    diff --git a/board/ti/am57xx/board.c b/board/ti/am57xx/board.c
    index 5f2d4dfab8c5..09d7f3ff17a9 100644
    --- a/board/ti/am57xx/board.c
    +++ b/board/ti/am57xx/board.c
    @@ -585,6 +585,26 @@ int spl_start_uboot(void)
     #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_HIGH,
     	.base = DRA7_USB_OTG_SS2_BASE,
    @@ -622,9 +642,13 @@ int board_usb_init(int index, enum usb_init_type init)
     	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;
    +#ifdef CONFIG_USB_DWC3
    +			usb_otg_ss1.dr_mode = USB_DR_MODE_PERIPHERAL;
    +			usb_otg_ss1_glue.vbus_id_status = OMAP_DWC3_VBUS_VALID;
    +			ti_usb_phy_uboot_init(&usb_phy1_device);
    +			dwc3_omap_uboot_init(&usb_otg_ss1_glue);
    +			dwc3_uboot_init(&usb_otg_ss1);
    +#endif
     		}
     		break;
     	case 1: