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.

AM335X USB_ctrl0 register setting

Hi,

I tried to set the lowest 2 bits of register usb_ctrl0 Register [0x44E10620] to power down the PHY of USB controller, but it doesn’t take effect. And the register value of the lowest 2 bits are still 0.

Why setting these 2 lowest bits is not effective and the value of the 2 bits are still 0?

Regards,

Peng

                       

 

  • Hi Peng,

    What software do you use? If you do not use the USB port at all you should simply make connections as described here: http://processors.wiki.ti.com/index.php/AM335x_Schematic_Checklist#If_USB0_or_USB1_is_not_used...

  • Hi, Biser,

    In fact, we want to reset the PHY by turning off the PHY and then enable it.

    We got reference code from website using usb_ctrl0 Register [0x44E10620], but we could not change this register.

    Peng,

     

     

     

     

  • Peng,

    Do you use Linux or other OS? Do you modify usb_ctrl0 in user space or kernel space?

    You can refer to function ti81xx_musb_phy_power() in SDK6.0 kernel source code arch/arm/mach-omap2/omap_phy_internal.c for how the Linux kernel sets this register.

  • Bin, I had a similar question in another thread and you directed me to this thread, but I don't see how you answered the question. 

    The code you referenced has 2 paths one for a ti816 and one for a ti814. 

    I can only assume that you meant for us to look at the ti814 path since it appears to set the same first 2 bits of the register to 1 as is specified in the AM335x TRM. 

    I've attempted to set both of these bits to no effect and their actual values do not change. 

    I'm using devmem2 to set the register so I'm doing it in kernel space. 

    Can you elaborate on your answer? 

    Matt S. 

  • Matthew,

    Which kernel do you use? I don't see ti814 path in the SDK6.0 kernel, which only has ti816x and am33xx.

    Anyway, the point I was trying to explain here is that the usb_ctrl register can only be modified in kernel, not in user space.

  • I'm using SDK 7.0 (Kernel 3.12.12)

    Here is the function that you referenced

    void ti81xx_musb_phy_power(u8 on)
    {
    	void __iomem *scm_base = NULL;
    	u32 usbphycfg;
    
    	scm_base = ioremap(TI81XX_SCM_BASE, SZ_2K);
    	if (!scm_base) {
    		pr_err("system control module ioremap failed\n");
    		return;
    	}
    
    	usbphycfg = __raw_readl(scm_base + USBCTRL0);
    
    	if (on) {
    		if (cpu_is_ti816x()) {
    			usbphycfg |= TI816X_USBPHY0_NORMAL_MODE;
    			usbphycfg &= ~TI816X_USBPHY_REFCLK_OSC;
    		} else if (cpu_is_ti814x()) {
    			usbphycfg &= ~(USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN
    				| USBPHY_DPINPUT | USBPHY_DMINPUT);
    			usbphycfg |= (USBPHY_OTGVDET_EN | USBPHY_OTGSESSEND_EN
    				| USBPHY_DPOPBUFCTL | USBPHY_DMOPBUFCTL);
    		}
    	} else {
    		if (cpu_is_ti816x())
    			usbphycfg &= ~TI816X_USBPHY0_NORMAL_MODE;
    		else if (cpu_is_ti814x())
    			usbphycfg |= USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN;
    
    	}
    	__raw_writel(usbphycfg, scm_base + USBCTRL0);
    
    	iounmap(scm_base);
    }

    Now that you've established that the register write must be done from kernel space can you describe how to turn off the PHY's on the AM335x processor? Or perhaps explain why setting the bits described in the TRM doesn't seem to have an effect? 

    Thanks,
    Matt S. 

  • Ok, for SDK7.0 kernel, you have to modify am335x_phy_power() in drivers/usb/phy/phy-am335x-control.c.

  • Modify it to what? 

    That function appears to be doing the same thing that we've already stated doesn't appear to have any effect. 

  • Please try the following.

    diff --git a/drivers/usb/phy/phy-am335x-control.c b/drivers/usb/phy/phy-am335x-control.c
    index 634f49a..b2216af 100644
    --- a/drivers/usb/phy/phy-am335x-control.c
    +++ b/drivers/usb/phy/phy-am335x-control.c
    @@ -82,12 +82,7 @@ static void am335x_phy_power(struct phy_control *phy_ctrl, u32 id, bool on)
            }
     
            val = readl(usb_ctrl->phy_reg + reg);
    -       if (on) {
    -               val &= ~(USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN);
    -               val |= USBPHY_OTGVDET_EN | USBPHY_OTGSESSEND_EN;
    -       } else {
                    val |= USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN;
    -       }
     
            writel(val, usb_ctrl->phy_reg + reg);
     }
    
  • Sorry for the delay, for some reason I didn't get the e-mail that you had responded to the post.

    I verified that making this change prevents the USB PHY's from powering on and you can see the appropriate bits set in the register, you can also see a ~17mA drop in total board current draw for a BeagleBoneBlack. 

    I still don't understand why writing the same value to the register via devmem2
    (e.g. devmem2 0x44E10620 w 0x3C186007) has no effect on the register or the current draw of the board. 

    I now need to figure out how to instigate a power down (or power up) of the USB modules from user space code, any hints? 

    Thanks,
    Matt S. 

  • Matthew Schuckmann1 said:
    Sorry for the delay, for some reason I didn't get the e-mail that you had responded to the post.

    No worries. Maybe it went to the junk folder...

    Matthew Schuckmann1 said:
    I still don't understand why writing the same value to the register via devmem2
    (e.g. devmem2 0x44E10620 w 0x3C186007) has no effect on the register

    I am a sw guy and don't know much about insides of the silicon, but I was told it has something to do with the interconnect in the device, some control_module registers are read-only for user space, but r/w for kernel.

    Matthew Schuckmann1 said:
    I now need to figure out how to instigate a power down (or power up) of the USB modules from user space code, any hints? 

    You can easily hack the kernel to add a sysfs or procfs entry to provide an interface to turn on/off the register bit. But if you can describe the scenario when/how the phy power will be on/off, maybe I will have a better idea to archive this, as maybe the kernel dynamic power management framework can do something for you.

  • Matthew Schuckmann1 said:
    you can also see a ~17mA drop in total board current draw for a BeagleBoneBlack.

    Is this drop with both USB ports off or just one port?

  • Bin Liu said:
    I am a sw guy and don't know much about insides of the silicon, but I was told it has something to do with the interconnect in the device, some control_module registers are read-only for user space, but r/w for kernel.

    That is the whole point of devmem2, it's a user space program that allows one to write to hardware registers in kernel space, the actual write to the register occurs in kernel space, and it works with other registers. I figure that there must be some other condition that needs to be met to turn off the phy. 

    Bin Liu said:
    You can easily hack the kernel to add a sysfs or procfs entry to provide an interface to turn on/off the register bit. But if you can describe the scenario when/how the phy power will be on/off, maybe I will have a better idea to archive this, as maybe the kernel dynamic power management framework can do something for you.

    I need to be able to put the the processor in as low a power state as possible without going into standby mode. Basically the processor will be in idle with Ethernet, serial and GPIO functional. It's the requirement that I need Ethernet to be functional that prevents me from putting it in standby mode. 

    To answer your other question, the 17mA drop is with both phy's off. 

    Thank you,
    Matt S. 

  • Matthew Schuckmann1 said:
    That is the whole point of devmem2, it's a user space program that allows one to write to hardware registers in kernel space, the actual write to the register occurs in kernel space, and it works with other registers. I figure that there must be some other condition that needs to be met to turn off the phy. 

    devmem2 accesses registers thorough /dev/mem, which is different from what drivers do in kernel space. In short, devmem2 is unable to modify ALL registers, due to interconnect inside of the SoC.

    Matthew Schuckmann1 said:
    I need to be able to put the the processor in as low a power state as possible without going into standby mode. Basically the processor will be in idle with Ethernet, serial and GPIO functional. It's the requirement that I need Ethernet to be functional that prevents me from putting it in standby mode. 

    If you could control the phy in user space, how/when would you turn it on/off? Do you want the phy to be on when a USB device is plugged in, and off when nothing is plugged? Or you will turn off the phy sometimes even a USB device is connected?

  • Bin Liu said:
    devmem2 accesses registers thorough /dev/mem, which is different from what drivers do in kernel space. In short, devmem2 is unable to modify ALL registers, due to interconnect inside of the SoC.

    Thanks I did not know that, I wonder why that is, I'll have to research it. 

    Bin Liu said:
    If you could control the phy in user space, how/when would you turn it on/off? Do you want the phy to be on when a USB device is plugged in, and off when nothing is plugged? Or you will turn off the phy sometimes even a USB device is connected?

    I would presume that I'd turn the phy off via some sort of driver interface. 
    Whenever the system goes into standby (our standby mode, not the same as the AM335x standby) we'd turn off any unneeded interfaces to save power. This would include USB, even if a USB device is connected. 

    I'm trying to meet energy star standby requirements of 1.2W (total measured at AC) for a display while remaining responsive to Ethernet communication.

    Matt S. 

  • If you want to turn off USB even if a USB device is connected, you have to add a driver interface to get the user space access to the phy control API, as I said, you could add it in USB sysfs or debugfs.

    However, there a few things you have to pay attention.

    - turning off phy power while a USB device is still connected might cause lost of the connection/enumeration, make sure the user space application is aware of that;

    - in normal case which unplug the USB cable, the USB drivers have a serial of actions internally to tear down the connection. Simply turning off phy power might confuse the USB driver stack. You have to make sure the driver tears down the connection properly when turning off phy power.

    We never tested turning off phy power while a USB device is connected, so there might be some other corner cases I missed.

  • That all makes sense, mostly I'm in the fact finding stage and just trying to determine what we might need to do to get the power low enough, hopefully I won't have to go this far and I'll be able to just leave it well enough alone. If we were to do this we'd also be killing the 5V power to the USB devices so one would think that would be pretty close to a disconnection event. 

    I had assumed I'd have to properly shutdown the whole USB subsystem in one way or another, perhaps by just unloading the USB drivers I don't know yet,  I do know there is a sysfs method for disabling USB devices.

    Like I said hopefully I won't have to go this far to achieve our goals. Thank you for being responsive and answering my questions. 

    Matt S.