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/AM5718: USB CDC configuration

Part Number: AM5718


Tool/software: Linux

SDK: Processor SDK Linux 4.00

We recently did a board spin. The main difference between old and new board are:

1. Moved from AM5718 SR 1.0 to SR 2.0

2. Earlier design has CPU board plugged into the main board. The new design has integrated both boards.

On the old board, USB peripheral configured as Ethernet works fine. We are having trouble in making it work on the new board. 

Messages in the dmesg (old board): Messages highlighted bold does not appear on the new board.

root@am57xx-evm:~# dmesg | egrep -i "usb | g_ether"
[ 0.611443] LDOUSB: supplied by VDD_5V0_IN
[ 4.964414] udc-core: couldn't find an available UDC - added [g_ether] to list of pending drivers
[ 12.237711] extcon-usb-gpio extcon_usb1: GPIO lookup for consumer id
[ 12.237716] extcon-usb-gpio extcon_usb1: using device tree for GPIO lookup
[ 12.237764] of_get_named_gpiod_flags: parsed 'id-gpios' property of node '/extcon_usb1[0]' - status (0)
[ 12.237775] extcon-usb-gpio extcon_usb1: GPIO lookup for consumer vbus
[ 12.237778] extcon-usb-gpio extcon_usb1: using device tree for GPIO lookup
[ 12.237782] of_get_named_gpiod_flags: can't parse 'vbus-gpios' property of node '/extcon_usb1[0]'
[ 12.237785] of_get_named_gpiod_flags: can't parse 'vbus-gpio' property of node '/extcon_usb1[0]'
[ 12.237788] extcon-usb-gpio extcon_usb1: using lookup tables for GPIO lookup
[ 12.237792] extcon-usb-gpio extcon_usb1: lookup for GPIO vbus failed
[ 14.069734] usb0: HOST MAC 8e:a0:8a:7a:f3:bc
[ 14.201715] usb0: MAC 00:1e:58:41:b8:78
[ 14.231352] g_ether gadget: Ethernet Gadget, version: Memorial Day 2008
[ 14.248592] g_ether gadget: g_ether ready
[ 14.337535] usbcore: registered new interface driver usbfs
[ 14.351737] usbcore: registered new interface driver hub
[ 14.363504] usbcore: registered new device driver usb
[ 14.419030] xhci-hcd xhci-hcd.0.auto: new USB bus registered, assigned bus number 1
[ 14.463382] hub 1-0:1.0: USB hub found
[ 14.478774] xhci-hcd xhci-hcd.0.auto: new USB bus registered, assigned bus number 2
[ 14.487271] usb usb2: We don't know the algorithms for LPM for this host, disabling LPM.
[ 14.498089] hub 2-0:1.0: USB hub found
[ 15.784750] IPv6: ADDRCONF(NETDEV_UP): usb0: link is not ready
[ 639.617277] g_ether gadget: full-speed config #1: CDC Ethernet (ECM)
[ 640.089222] IPv6: ADDRCONF(NETDEV_CHANGE): usb0: link becomes ready

 

Related configuration in the DTS file:

extcon_usb1: extcon_usb1 {
pinctrl-names = "default";
pinctrl-0 = <&extcon_usb1_default>;
compatible = "linux,extcon-usb-gpio";
id-gpios = <&gpio8 16 GPIO_ACTIVE_HIGH>;
};

...

extcon_usb1_default: extcon_usb1_default {
pinctrl-single,pins = <
0x21c (PIN_INPUT_PULLUP | MUX_MODE14) /* vout1_d16.gpio8_16 : Fake USB1-ID : GPIO 240 */
>;
};

...

&omap_dwc3_1 {
extcon = <&extcon_usb1>;
};

&usb1 {
dr_mode = "peripheral";
maximum-speed = "high-speed";
};

Looking into the schematic, there is no VBUS detection mechanism via PMIC. However, this is the case with the old board as well, still USB Ethernet works on the old board.

  • Hi Paritosh,

    Other than SR1.0 vs SR2.0 of AM5718, is there any other board change which is related to USB?

    Please post the usb portion of the schematics, including the routing of gpio8_16. Is gpio8_16 for ID pin detection? If so, you don't need it, since the usb port is in peripheral mode. ID pin detection is for host or dual-role port.

    Please also run the following script on your board and post its output.

    #!/bin/bash
    #
    # Util to check USB subsystem for Linux kernel 3.12+ on TI Sitara devices
    #
    # Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
    #
    #
    #  Redistribution and use in source and binary forms, with or without
    #  modification, are permitted provided that the following conditions
    #  are met:
    #
    #    Redistributions of source code must retain the above copyright
    #    notice, this list of conditions and the following disclaimer.
    #
    #    Redistributions in binary form must reproduce the above copyright
    #    notice, this list of conditions and the following disclaimer in the
    #    documentation and/or other materials provided with the
    #    distribution.
    #
    #    Neither the name of Texas Instruments Incorporated nor the names of
    #    its contributors may be used to endorse or promote products derived
    #    from this software without specific prior written permission.
    #
    #  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    #  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    #  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    #  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    #  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    #  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    #  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    #  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    #  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    #  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    #  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    
    VERSION=0.2.8
    
    
    ### functions ###
    
    # $1 command to be checked
    check_command() {
        local _cmd=$1
    
        which $_cmd > /dev/null || {
            echo "Error: $_cmd command not found"
            exit 1
        }
    }
    
    # check if the kernel is supported
    # this tool only runs on v3.12+ kernel
    # return 0 - if kernel version >= 3.12
    #        1 - if kernel version < 3.12
    has_supported_kernel() {
    	local _ver
    	local _t
    
        check_command uname
        uname -a
    	_ver=`uname -r`
        _t=${_ver%%.*}
        # 2.x.x, unsupported
        [ $_t -ge 3 ] || return 1
        # 4.x.x, supported
        [ $_t -lt 4 ] || return 0
    
        _ver=${_ver#*.}
        _t=${_ver%%.*}
        # < 3.12.x, unsupported
        [ $_t -ge 12 ] || return 1
        return 0
    }
    
    # check if the platform is supported
    #    $PLATFORM - global variable
    # return 0 - if platform is supported
    #        1 - if platform is not supported
    check_platform () {
    	local _hw
    
        check_command grep
        [ "$PLATFORM" != "" ] || {
    	    _hw=`cat /sys/firmware/devicetree/base/compatible | tr '\0' ' '`
    	    DBG_PRINT $_hw
    
            if [[ "$_hw" == *"ti,am33xx"* ]]; then
                PLATFORM="am335x"
            elif [[ "$_hw" == *"ti,am43"* ]]; then
                PLATFORM="am437x"
            elif [[ "$_hw" == *"ti,dra7"* ]]; then
                PLATFORM="am57x"
            elif [[ "$_hw" == *"ti,k2g"* ]]; then
                PLATFORM="keystone"
            elif [[ "$_hw" == *"ti,da850"* ]]; then
                PLATFORM="omapl1"
            elif [[ "$_hw" == *"ti,am654"* ]]; then
                PLATFORM="am65x"
            else
                PLATFORM=$_hw
            fi
        }
    
        DBG_PRINT $PLATFORM
        case $PLATFORM in
            "am335x")
                USB0='/ocp/usb@47400000/usb@47401000'
                USB1='/ocp/usb@47400000/usb@47401800'
                return 0;;
            "am437x")
                USB0='/ocp/omap_dwc3@48380000/usb@48390000'
                USB1='/ocp/omap_dwc3@483c0000/usb@483d0000'
                return 0;;
            "am57x")
                USB0='/ocp/omap_dwc3_1@48880000/usb@48890000'
                USB1='/ocp/omap_dwc3_2@488c0000/usb@488d0000'
                return 0;;
            "keystone")
                USB0='/ocp/omap_dwc3_1@48880000/usb@48890000'
                USB1='/ocp/omap_dwc3_2@488c0000/usb@488d0000'
                return 0;;
            "omapl1")
                USB0='/soc@1c00000/usb@200000'
                USB1=''
                return 0;;
            "am65x")
                USB0='/soc0/dwc3@4000000/usb@10000'
                USB1='/soc0/dwc3@4020000/usb@10000'
                return 0;;
            *)
                echo "Unsupported \"$PLATFORM\""
                return 1;;
        esac
    }
    
    # check a kernel CONFIG option
    # params $1 - the config option
    #        $2 = '-q', quiet output
    # return 0 - undefined
    #        1 - defined as 'm', kernel module
    #        2 - defined as 'y', kernel builtin
    check_kernel_config() {
        local _cfg
    
        [ -n "$1" ] || return 0
        check_command zcat
        _cfg=`zcat /proc/config.gz | grep "^$1\>"`
    
        case ${_cfg#*=} in
            "y") return 2;;
            "m") return 1;;
              *) [ "$2" = "-q" ] ||
                  echo "Error: $1 is undefined in kernel config"
              return 0;;
        esac
    }
    
    # check a kernel module
    # $1 - module name, relative path from drivers/, with .ko surfix
    # return 0 - found
    #        1 - error
    check_module() {
        local _modname
        local _moddep
    
        [ -n "$1" ] || return 1
    
        _modname="/lib/modules/`uname -r`/kernel/drivers/${1}.ko"
        _moddep="/lib/modules/`uname -r`/modules.dep"
    
        DBG_PRINT 1
        [ -f $_modname ] || {
            echo "Error: $_modname not found."
            echo "       Please ensure 'make module_install' is done properly."
            return 1
        }
    
        DBG_PRINT 2
        [ -f $_moddep ] || $moddep_checked || {
            echo "Error: $_moddep not found."
            echo "       Please ensure 'make module_install' is done properly."
            moddep_checked=true
        }
    
        DBG_PRINT 3
        check_command lsmod
        check_command basename
        check_command tr
    
        lsmod | grep `basename $1 | tr '-' '_'` > /dev/null || {
            DBG_PRINT ">>>> ${1}.ko:"
            if grep "${1}.ko:" $_moddep > /dev/null; then
                DBG_PRINT 5
                echo "Error: $_moddep seems to be valid,"
                echo "       but `basename $1`.ko is not loaded."
                echo "       Please provide /proc/config.gz and /lib/module/`uname -r`/*"
                echo "       for further investigation."
            else
                DBG_PRINT 6
                echo "Error: `basename $1`: $_moddep is invalid."
                echo "       Please run command 'depmod' on the target to re-generate it,"
                echo "       then reboot the target. If the issue still exists, please"
                echo "       ensure 'make module_install' is done properly."
            fi
    
            DBG_PRINT 7
            return 1
        }
        DBG_PRINT 8
        return 0
    }
    
    # check kernel config, and modules (if CONFIG_*=M) for musb
    check_musb_drivers() {
        check_kernel_config CONFIG_USB_MUSB_HDRC
        [ $? != 1 ] || check_module 'usb/musb/musb_hdrc'
    
        check_kernel_config CONFIG_USB_MUSB_DUAL_ROLE -q
        [ $? != 0 ] || echo "Warning: CONFIG_USB_MUSB_DUAL_ROLE undefined."
    
        case $PLATFORM in
            am335x)
                check_kernel_config CONFIG_USB_MUSB_DSPS
                [ $? != 1 ] || {
                    check_module 'usb/musb/musb_dsps'
                    check_module 'usb/musb/musb_am335x'
                }
                ;;
            omapl1)
                check_kernel_config CONFIG_USB_MUSB_DA8XX
                [ $? != 1 ] || check_module 'usb/musb/da8xx'
                ;;
        esac
    
        case $PLATFORM in
            am335x)
                check_kernel_config CONFIG_AM335X_PHY_USB
                [ $? != 1 ] || {
                    check_module 'usb/phy/phy-am335x'
                    check_module 'usb/phy/phy-am335x-control'
                }
                ;;
            omapl1)
                check_kernel_config CONFIG_NOP_USB_XCEIV
                [ $? != 1 ] || check_module 'usb/phy/phy-generic'
                ;;
        esac
    
        check_kernel_config CONFIG_MUSB_PIO_ONLY -q
        [ $? != 0 ] || {
           if check_kernel_config CONFIG_TI_CPPI41 -q; then
               echo "Error: MUSB CPPI DMA mode is enabled, but CPPI moudle is not enabled in DMA Engine."
               echo "       Please enable CONFIG_TI_CPPI41 under DMA Engine Support in kernel config."
           fi
        }
    }
    
    # check kernel config, and modules (if CONFIG_*=M) for dwc3
    check_dwc3_drivers() {
        check_kernel_config CONFIG_USB_DWC3
        [ $? != 1 ] || check_module 'usb/dwc3/dwc3'
    
        check_kernel_config CONFIG_USB_DWC3_DUAL_ROLE -q
        [ $? != 0 ] || echo "Warning: CONFIG_USB_DWC3_DUAL_ROLE undefined."
    
        check_kernel_config CONFIG_USB_OTG -q
        [ $? != 0 ] || echo "Warning: CONFIG_USB_OTG undefined, which is required for DRD mode."
    
        check_kernel_config CONFIG_USB_DWC3_OMAP
        [ $? != 1 ] || check_module 'usb/dwc3/dwc3-omap'
    
        check_kernel_config CONFIG_USB_XHCI_HCD
        [ $? != 1 ] || {
            check_module 'usb/host/xhci-plat-hcd'
            check_module 'usb/host/xhci-hcd'
        }
    
        check_kernel_config CONFIG_OMAP_CONTROL_PHY
        [ $? != 1 ] || check_module 'phy/phy-omap-control'
    
        if [ $PLATFORM = am437x ]; then
            check_kernel_config CONFIG_OMAP_USB2
            [ $? != 1 ] || check_module 'phy/phy-omap-usb2'
        else
            check_kernel_config CONFIG_TI_PIPE3
            [ $? != 1 ] || check_module 'phy/phy-ti-pipe3'
        fi
    }
    
    check_musb_dt() {
        local _dt_dir
        local _ent
        local _sts
    
        case $PLATFORM in
        am335x)
            _dt_dir='/proc/device-tree/ocp/usb@47400000'
            _ent='. control@44e10620 usb-phy@47401300 usb-phy@47401b00 dma-controller@47402000'
            ;;
        omapl1)
            _dt_dir='/proc/device-tree/soc@1c00000'
            _ent='usb@200000 chip-controller@1417c/usb-phy usb@200000/dma-controller@201000'
            ;;
        *)
            return ;;
        esac
    
        for _t in $_ent; do
            _sts=$(tr -d '\0' <${_dt_dir}/${_t}/status)
            [ "$_sts" != "disabled" ] || echo $_t: disabled in devicetree
        done
    }
    
    ### debug ###
    
    g_log_file=/tmp/chkusb.log
    
    DBG_ENABLE() { g_dbg_enabled=true; }
    DBG_DISABLE() { g_dbg_enabled=false; }
    DBG_LOG_RESET() { ! $g_dbg_enabled || echo > $g_log_file; }
    DBG_PRINT() { ! $g_dbg_enabled || echo "$(date +%H:%M:%S) [$(basename $0)]: $*"; }
    DBG_LOG() { DBG_PRINT $* >> $g_log_file; }
    DBG_LOG_MARK() { DBG_PRINT "----------------" >> $g_log_file; }
    
    
    ### main ####
    
    moddep_checked=false
    
    echo "chkusb.sh Version $VERSION"
    
    [ "$V" = "1" ] && DBG_ENABLE && DBG_LOG_RESET || DBG_DISABLE
    
    has_supported_kernel ||
        { echo "Unsupported kernel version: `uname -r`"; exit 1; }
    check_platform || exit 2
    DBG_PRINT device: $PLATFORM
    
    check_command lsusb
    if lsusb > /dev/null 2>&1; then
        echo "USB is initialized"
    else
        echo "USB initialization failed"
    fi
    
    # check kernel configs
    
    if [ -f /proc/config.gz ]; then
        case $PLATFORM in
            am335x | omapl1) check_musb_drivers;;
            am437x | am57x | keystone | am65x) check_dwc3_drivers;;
            *)
                echo "Error: unsupported platform $PLATFORM"
                exit 5;;
        esac
    else
        echo "Error: /proc/config.gz not found"
    fi
    
    case $PLATFORM in
        am335x | omapl1)
            _debugfs=`sed -ne 's/^debugfs \(.*\) debugfs.*/\1/p' /proc/mounts`
            [ -z "$_debugfs" ] ||
                grep -i 'power\|devctl\|testmode' ${_debugfs}/musb-hdrc.?/regdump
            ;;
    esac
    
    # check dr_mode & gadget drivers
    
    [ -d /proc/device-tree ] || {
        echo "Warning: /proc/device-tree/ not found"
        if [ -d "/lib/modules/`uname -r`/" ]; then
            echo "The list of USB gadget drivers installed:"
            ls -1Rp "/lib/modules/`uname -r`/kernel/drivers/usb/gadget/"
        fi
        exit 0
    }
    
    check_command basename
    for _usb in "${USB0}" "${USB1}"; do
        [ -n "$_usb" ] || continue
    
        _usb_dir="/proc/device-tree/${_usb}"
        _status=`tr -d '\0' <$_usb_dir/status`
        _dr_mode=`tr -d '\0'  <$_usb_dir/dr_mode`
        echo `basename $_usb`: $_dr_mode, $_status
    
        [ "$_status" = "disabled" -o "$_dr_mode" = "host" ] || gadget_mode=true
    done
    
    case $PLATFORM in
        am335x | omapl1) check_musb_dt;;
        *) ;;
    esac
    
    DBG_PRINT $gadget_mode
    $gadget_mode || exit 0
    
    echo
    
    check_kernel_config CONFIG_USB_LIBCOMPOSITE
    case $? in
        0) echo "Error: no any gadget driver enabled"
           exit 6;;
        1) is_gadget_builtin=false;;
        2) echo "The gadget driver is built-in"
           is_gadget_builtin=true;;
    esac
    
    check_kernel_config CONFIG_USB_ZERO -q ||
        echo "Gadget Kernel Config: g_zero is enabled"
    check_kernel_config CONFIG_USB_AUDIO -q ||
        echo "Gadget Kernel Config: g_audio is enabled"
    check_kernel_config CONFIG_USB_ETH -q ||
        echo "Gadget Kernel Config: g_ether is enabled"
    check_kernel_config CONFIG_USB_G_NCM -q ||
        echo "Gadget Kernel Config: g_ncm is enabled"
    check_kernel_config CONFIG_USB_MASS_STORAGE -q ||
        echo "Gadget Kernel Config: g_mass_storage is enabled"
    check_kernel_config CONFIG_USB_G_SERIAL -q ||
        echo "Gadget Kernel Config: g_serial is enabled"
    check_kernel_config CONFIG_USB_G_PRINTER -q ||
        echo "Gadget Kernel Config: g_printer is enabled"
    
    g_driver=`grep '^DRIVER=' /sys/class/udc/*/uevent 2>/dev/null`
    echo "gadget driver loaded: ${g_driver:-(none)}"
    
    echo
    
    if ! $is_gadget_builtin; then
        if [ -d "/lib/modules/`uname -r`/" ]; then
            echo "The list of USB gadget drivers installed:"
            ls -1Rp "/lib/modules/`uname -r`/kernel/drivers/usb/gadget/"
        else
            echo "Error: /lib/modules/`uname -r`/ not found"
            echo "       Please ensure 'make modules_install' is done properly."
            exit 7
        fi
    fi
    
    # vim: ft=sh:ts=4:sw=4:et
    

  • Paritosh Dixit said:
    [ 4.964414] udc-core: couldn't find an available UDC - added [g_ether] to list of pending drivers

    Okay, this message is the hint - it seems the g-ether driver was loaded before the usb drivers are loaded. If you manually load g_ether driver from the command line after the board is booted, can the usb port be detected on the usb host?

  • Hi Bin,

    thanks for your reply.

    We found that in the old SR1.0 board, in the usb1 configuration in the DTS, a gpio was configured as id-gpio. It seems in this workaround this GPIO was always pulled high. It wasn't documented properly in the schematic.

    When same fix is applied in new board, USB Ethernet is working.

    It was bit confusing that this gpio was configured as id-gpio, instead of vbus-gpio. When we change it to vbus-gpio, behaviour remains the same. That is, USB Ethernet works fine. USB Ethernet interface remains always UP even though USB cable is removed.

    Please ignore the speed question (for this AM5718 based board).
    Speed of USB Ethernet is ~10 Mbps, instead of high-speed 480 Mbps. What could be root cause of this ?

  • Hi Paritosh,

    Is this project the same as e2e.ti.com/.../2797348?
    I hope not, since I am kind of confused with both threads and trying to clean up my mind now.

  • Paritosh Dixit said:
    Speed of USB Ethernet is ~10 Mbps, instead of high-speed 480 Mbps. What could be root cause of this ?

    What is the numerated bus speed on the host, full-speed or high-speed? You can check the enumeration log on the host.

    Never mind, the log you posted in the initial post shows the numeration to full-speed.

  • No Bin. These are two different boards. Starting this Monday, I am having to work on both
  • Paritosh,

    Glad to hear the issue is solved. Thanks for the update.