I have a board with an i.MX6DL part and I'm not seeing any USB devices being enumerated by the kernel when inserted into the USB ports. I've also adjusted the kernel to include more verbose USB debugging messages and I noticed the controller seems to continuously be going into and out of a suspend/resume cycle.
Here's the tail end of my dmesg where you can see the cycle going:
...
wakeup int at ci_hdrc.1
ci_hdrc ci_hdrc.1: at ci_controller_resume
ci_hdrc ci_hdrc.1: at ci_runtime_suspend
imx_usb 2184200.usb: at imx_controller_suspend
imx_usb 2184200.usb: at imx_controller_resume
wakeup int at ci_hdrc.1
ci_hdrc ci_hdrc.1: at ci_controller_resume
ci_hdrc ci_hdrc.1: at ci_runtime_suspend
imx_usb 2184200.usb: at imx_controller_suspend
imx_usb 2184200.usb: at imx_controller_resume
wakeup int at ci_hdrc.1
...
My setup in the device tree is pretty straight forward:
pinctrl_usbotg: usbotggrp {
fsl,pins = <
MX6QDL_PAD_KEY_COL4__USB_OTG_OC 0x18000
MX6QDL_PAD_KEY_ROW4__USB_OTG_PWR 0x8018
>;
};
pinctrl_usbh: usbhgrp {
fsl,pins = <
MX6QDL_PAD_EIM_D30__USB_H1_OC 0x18000
MX6QDL_PAD_EIM_D31__USB_H1_PWR 0x8018
>;
};
&usbh1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usbh>;
vbus-supply = <&vbat>;
status = "okay";
};
&usbotg {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usbotg>;
vbus-supply = <&vbat>;
disable-over-current;
srp-disable;
hnp-disable;
adp-disable;
status = "okay";
};
The ID pin is not used in our design, which is why it's not present in the pinctrl setup.
Are there any obvious reasons why this issue of the USB going in and out of suspend might happen? I suspect that's related to the fact that no devices are registered on the USB interface when inserted as well.
As per the suggestions of jimmychan I did end up upgrading my kernel to 4.1.15, however this did not resolve my issue.
I've put a patch in place which makes the USB Host work, but I'm not sure this is the correct thing to do. Based on my previous findings with "usb start" from the bootload and the register dumps, I'm now updating the USBNC_USB_UH1_CTRL register from within the ci_hdrc_imx.c file's probe function.
This register defaults to 0x30001002 so this change adjusts it to 0x30001782.
p = ioremap_nocache(0x02184800, 32);
iowrite32(0x30001782, p+4);
iounmap(p);
This new setting has the following changes:
This now matches what is seen in the kernel after "usb start" is issued in U-Boot, and as such, with this change the USB devices are detected.
My question now is, what could be done to avoid this patch? Obviously the kernel upmerge by itself wasn't enough... I feel like there must be something incorrect else where that is causing me to have to take these steps.
Thanks for your suggestion Jimmy. I have not yet tried a newer BSP, do you suspect there is some particular fix in there that would be useful? Any commits or patches you could suggest?
We are close to finishing validation on the 3.X kernel so I hadn't desired to move to a 4.X kernel, but if you know of something in there that would be helpful I could try that.
Note: I've discovered that if I stop the boot up sequence to enter u-boot and enter the "usb start" command before continuing with "boot" then I get better results. So I think this must come down to some sort of configuration issue with the pad configuration or a missed setting.
Note: I also checked the dmesg but didn't see any smoking guns in there, it looks like the driver initializes
root@imx6dlicomv2cib:~# dmesg | grep -i "usb"
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
usbphy_nop1.10 supply vcc not found, using dummy regulator
usbphy_nop2.11 supply vcc not found, using dummy regulator
ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
usbcore: registered new interface driver usb-storage
usbcore: registered new interface driver usb_ehset_test
2184800.usbmisc supply vbus-wakeup not found, using dummy regulator
imx_usb 2184000.usb: pinctrl_hsic_idle lookup failed, err=-19
imx_usb 2184000.usb: pinctrl_hsic_active lookup failed, err=-19
imx_usb 2184200.usb: pinctrl_hsic_idle lookup failed, err=-19
imx_usb 2184200.usb: pinctrl_hsic_active lookup failed, err=-19
ci_hdrc ci_hdrc.1: new USB bus registered, assigned bus number 1
ci_hdrc ci_hdrc.1: USB 2.0 started, EHCI 1.00
usb usb1: New USB device found, idVendor=1d6b, idProduct=0002
usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
usb usb1: Product: EHCI Host Controller
usb usb1: Manufacturer: Linux 3.14.38-134340-gddea85e-dirty ehci_hcd
usb usb1: SerialNumber: ci_hdrc.1
hub 1-0:1.0: USB hub found
usbcore: registered new interface driver usbhid
usbhid: USB HID core driver
imx_usb 2184200.usb: at imx_controller_suspend
imx_usb 2184200.usb: at imx_controller_resume
...
I've found that if I pause the boot up sequence as u-boot I can execute the "usb start" command and then complete the "boot" process to the Linux kernel. If I proceed with that sequence of commands than the cycle of "suspend"/"resume" messages never shows up.
I'm not yet sure as to what this has to do with the issue, only that the bootloader must be leaving USB in some recognizable state for the kernel which is thus preventing the "suspend"/"resume" cycle.
I've also confirmed that the Linux kernel can "see" devices which are inserted and enumerate them properly on a boot up after the "usb start" was issued in the bootloader.
I've started taking a look at USB registers to see what was changed after this command which is now making USB work. Thus far I've confirmed that IOMUX (both PAD_CTL and MUX_CLT) haven't changed by the command. I've also verified that the CCM_ANALOG_PLL_USB1n register(s) haven't been adjusted.. however I did see a chance in the "locked" state of CCM_ANALOG_PLL_USB2n register(s). Not sure if that will be significant.
After some rather exhaustive register dumps, I've determined that the non-core registers:
218_4800 USB OTG Control Register (USBNC_USB_OTG_CTRL) 32 R/W 0000_3000h 65.5.1/5437
218_4804 USB Host1 Control Register (USBNC_USB_UH1_CTRL) 32 R/W 0000_3000h 65.5.2/5440
Seem to be the issue. Under a normal power up, the Host1 register is set to 0x30001002 yet after a "usb start" command issued in the bootloader then a normal boot up this register is set to 0x30001782. This adjustment changes the Wakeup Interrupt Enabled bit, Overcurrent polarity and disables overcurrent detection, and changes the polarity of the power switch.
After making these adjustments at run time with the devmem2 tool I could see the loop of suspend/resume function calls disappeared and now the Host1 port is detecting USB devices when inserted correctly.
I still need to determine the requirement which makes us need these changes and the best place to set these registers if indeed this is the best fix.
Hello Michael,
I'm seeing the resume/suspend loop issue with kernel 3.14 too.
Thanks for your approach on debugging and sharing your results.
Did you find a proper place to fix this?
Regards
Frieder
Proper place? Not sure on that... but I did "make it work". See latest comment below about patching the ci_hdrc_imx.c file.