16.12.2020 12:32, Peter Chen пишет: > >>>> >>>> struct tegra_usb_soc_info { >>>> unsigned long flags; >>>> + unsigned int txfifothresh; >>>> + enum usb_dr_mode dr_mode; >>>> +}; >>>> + >>>> +static const struct tegra_usb_soc_info tegra20_ehci_soc_info = { >>>> + .flags = CI_HDRC_REQUIRES_ALIGNED_DMA | >>>> + CI_HDRC_OVERRIDE_PHY_CONTROL, >>>> + .dr_mode = USB_DR_MODE_HOST, >>>> + .txfifothresh = 10, >>>> +}; >>>> + >>>> +static const struct tegra_usb_soc_info tegra30_ehci_soc_info = { >>>> + .flags = CI_HDRC_REQUIRES_ALIGNED_DMA | >>>> + CI_HDRC_OVERRIDE_PHY_CONTROL >>>> + .dr_mode = USB_DR_MODE_HOST, >>>> + .txfifothresh = 16, >>>> }; >>>> >>>> static const struct tegra_usb_soc_info tegra_udc_soc_info = { >>>> - .flags = CI_HDRC_REQUIRES_ALIGNED_DMA, >>>> + .flags = CI_HDRC_REQUIRES_ALIGNED_DMA | >>>> + CI_HDRC_OVERRIDE_PHY_CONTROL, >>>> + .dr_mode = USB_DR_MODE_UNKNOWN, >>>> }; >>> >>> What's the usage for this dr_mode? Does these three SoCs only supports >>> single mode, it usually sets dr_mode at board dts file to indicate USB >>> role for this board. >> >> All Tegra SoCs have three USB controllers. Only one of these three controllers >> supports peripheral / OTG modes, the other two controllers are fixed to the >> host mode and device trees do not specify the dr_mode for the host >> controllers. >> >> Hence we need to enforce the dr_mode=host for the host-mode controllers. >> >> For UDC the default mode is "unknown" because actual mode comes from a >> board's device tree. >> > > You could add dr_mode property at usb node of soc.dtsi to fulfill that. This will break older DTBs, we can't do this. ... >>>> static int ehci_ci_portpower(struct usb_hcd *hcd, int portnum, bool >>>> enable) { >>>> struct ehci_hcd *ehci = hcd_to_ehci(hcd); @@ -160,14 +166,14 @@ >>>> static int host_start(struct ci_hdrc *ci) >>>> pinctrl_select_state(ci->platdata->pctl, >>>> ci->platdata->pins_host); >>>> >>>> + ci->hcd = hcd; >>>> + >>>> ret = usb_add_hcd(hcd, 0, 0); >>>> if (ret) { >>>> goto disable_reg; >>>> } else { >>>> struct usb_otg *otg = &ci->otg; >>>> >>>> - ci->hcd = hcd; >>>> - >>> >>> Why this changed? >> >> The ci->hcd is used by tegra_usb_notify_event() to handle reset event and the >> reset happens once usb_add_hcd() is invoked. Hence we need to pre-assign >> the hcd pointer, otherwise there will be a NULL dereference. > > Get it, please set ci->hcd as NULL at error path. Ok, thanks.