xhci = from_timer(xhci, t, comp_mode_recovery_timer);
        rhub = &xhci->usb3_rhub;
+       hcd = rhub->hcd;
+
+       if (!hcd)
+               return;
 
        for (i = 0; i < rhub->num_ports; i++) {
                temp = readl(rhub->ports[i]->addr);
                                        i + 1);
                        xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
                                        "Attempting compliance mode recovery");
-                       hcd = xhci->shared_hcd;
 
                        if (hcd->state == HC_STATE_SUSPENDED)
                                usb_hcd_resume_root_hub(hcd);
                xhci_halt(xhci);
                return -ENODEV;
        }
-       xhci->shared_hcd->state = HC_STATE_RUNNING;
        xhci->cmd_ring_state = CMD_RING_STATE_RUNNING;
 
        if (xhci->quirks & XHCI_NEC_HOST)
                xhci_ring_cmd_db(xhci);
 
-       xhci_dbg_trace(xhci, trace_xhci_dbg_init,
-                       "Finished xhci_run for USB3 roothub");
        return 0;
 }
 
                        xhci_free_command(xhci, command);
        }
        xhci_dbg_trace(xhci, trace_xhci_dbg_init,
-                       "Finished xhci_run for USB2 roothub");
+                       "Finished %s for main hcd", __func__);
 
        set_bit(HCD_FLAG_DEFER_RH_REGISTER, &hcd->flags);
 
 
        xhci_debugfs_init(xhci);
 
+       if (xhci_has_one_roothub(xhci))
+               return xhci_run_finished(xhci);
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(xhci_run);
                return 0;
 
        if (hcd->state != HC_STATE_SUSPENDED ||
-                       xhci->shared_hcd->state != HC_STATE_SUSPENDED)
+           (xhci->shared_hcd && xhci->shared_hcd->state != HC_STATE_SUSPENDED))
                return -EINVAL;
 
        /* Clear root port wake on bits if wakeup not allowed. */
                 __func__, hcd->self.busnum);
        clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
        del_timer_sync(&hcd->rh_timer);
-       clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
-       del_timer_sync(&xhci->shared_hcd->rh_timer);
+       if (xhci->shared_hcd) {
+               clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
+               del_timer_sync(&xhci->shared_hcd->rh_timer);
+       }
 
        if (xhci->quirks & XHCI_SUSPEND_DELAY)
                usleep_range(1000, 1500);
 
        spin_lock_irq(&xhci->lock);
        clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-       clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
+       if (xhci->shared_hcd)
+               clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
        /* step 1: stop endpoint */
        /* skipped assuming that port suspend has done */
 
                msleep(100);
 
        set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-       set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
+       if (xhci->shared_hcd)
+               set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
 
        spin_lock_irq(&xhci->lock);
 
 
                /* Let the USB core know _both_ roothubs lost power. */
                usb_root_hub_lost_power(xhci->main_hcd->self.root_hub);
-               usb_root_hub_lost_power(xhci->shared_hcd->self.root_hub);
+               if (xhci->shared_hcd)
+                       usb_root_hub_lost_power(xhci->shared_hcd->self.root_hub);
 
                xhci_dbg(xhci, "Stop HCD\n");
                xhci_halt(xhci);
 
                xhci_dbg(xhci, "Start the primary HCD\n");
                retval = xhci_run(hcd->primary_hcd);
-               if (!retval) {
+               if (!retval && secondary_hcd) {
                        xhci_dbg(xhci, "Start the secondary HCD\n");
                        retval = xhci_run(secondary_hcd);
                }
                hcd->state = HC_STATE_SUSPENDED;
-               xhci->shared_hcd->state = HC_STATE_SUSPENDED;
+               if (xhci->shared_hcd)
+                       xhci->shared_hcd->state = HC_STATE_SUSPENDED;
                goto done;
        }
 
                }
 
                if (pending_portevent) {
-                       usb_hcd_resume_root_hub(xhci->shared_hcd);
+                       if (xhci->shared_hcd)
+                               usb_hcd_resume_root_hub(xhci->shared_hcd);
                        usb_hcd_resume_root_hub(hcd);
                }
        }
        /* Re-enable port polling. */
        xhci_dbg(xhci, "%s: starting usb%d port polling.\n",
                 __func__, hcd->self.busnum);
-       set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
-       usb_hcd_poll_rh_status(xhci->shared_hcd);
+       if (xhci->shared_hcd) {
+               set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
+               usb_hcd_poll_rh_status(xhci->shared_hcd);
+       }
        set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
        usb_hcd_poll_rh_status(hcd);
 
 
        xhci = hcd_to_xhci(hcd);
 
-       if (usb_hcd_is_primary_hcd(hcd)) {
-               xhci_hcd_init_usb2_data(xhci, hcd);
-       } else {
+       if (!usb_hcd_is_primary_hcd(hcd)) {
                xhci_hcd_init_usb3_data(xhci, hcd);
                return 0;
        }
                return retval;
        xhci_dbg(xhci, "Called HCD init\n");
 
+       if (xhci_hcd_is_usb3(hcd))
+               xhci_hcd_init_usb3_data(xhci, hcd);
+       else
+               xhci_hcd_init_usb2_data(xhci, hcd);
+
        xhci_info(xhci, "hcc params 0x%08x hci version 0x%x quirks 0x%016llx\n",
                  xhci->hcc_params, xhci->hci_version, xhci->quirks);
 
 
        unsigned                hw_lpm_support:1;
        /* Broken Suspend flag for SNPS Suspend resume issue */
        unsigned                broken_suspend:1;
+       /* Indicates that omitting hcd is supported if root hub has no ports */
+       unsigned                allow_single_roothub:1;
        /* cached usb2 extened protocol capabilites */
        u32                     *ext_caps;
        unsigned int            num_ext_caps;
        return xhci->main_hcd;
 }
 
+static inline struct usb_hcd *xhci_get_usb3_hcd(struct xhci_hcd *xhci)
+{
+       if (xhci->shared_hcd)
+               return xhci->shared_hcd;
+
+       if (!xhci->usb2_rhub.num_ports)
+               return xhci->main_hcd;
+
+       return NULL;
+}
+
+static inline bool xhci_hcd_is_usb3(struct usb_hcd *hcd)
+{
+       struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+
+       return hcd == xhci_get_usb3_hcd(xhci);
+}
+
+static inline bool xhci_has_one_roothub(struct xhci_hcd *xhci)
+{
+       return xhci->allow_single_roothub &&
+              (!xhci->usb2_rhub.num_ports || !xhci->usb3_rhub.num_ports);
+}
+
 #define xhci_dbg(xhci, fmt, args...) \
        dev_dbg(xhci_to_hcd(xhci)->self.controller , fmt , ## args)
 #define xhci_err(xhci, fmt, args...) \