#define   USB_CTRL_USB_PM_SOFT_RESET_MASK              0x40000000
 #define   USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK         0x00800000
 #define   USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK         0x00400000
+#define   USB_CTRL_USB_PM_XHC_PME_EN_MASK              0x00000010
+#define   USB_CTRL_USB_PM_XHC_S2_CLK_SWITCH_EN_MASK    0x00000008
 #define USB_CTRL_USB_PM_STATUS         0x08
 #define USB_CTRL_USB_DEVICE_CTL1       0x10
 #define   USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK      0x00000003
 
        pr_debug("%s\n", __func__);
 
-       USB_CTRL_UNSET(ctrl, USB_PM, USB_PWRDN);
-       /* 1 millisecond - for USB clocks to settle down */
-       usleep_range(1000, 2000);
-
        if (USB_CTRL_MASK(USB_DEVICE_CTL1, PORT_MODE)) {
                reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));
                reg &= ~USB_CTRL_MASK(USB_DEVICE_CTL1, PORT_MODE);
                USB_CTRL_UNSET(ctrl, CTLR_CSHCR, ctl_pme_en);
 }
 
+static void usb_wake_enable_7216(struct brcm_usb_init_params *params,
+                                bool enable)
+{
+       void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
+
+       if (enable)
+               USB_CTRL_SET(ctrl, USB_PM, XHC_PME_EN);
+       else
+               USB_CTRL_UNSET(ctrl, USB_PM, XHC_PME_EN);
+}
+
 static void usb_init_common_7211b0(struct brcm_usb_init_params *params)
 {
        void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
        usb2_eye_fix_7211b0(params);
 }
 
+static void usb_init_common_7216(struct brcm_usb_init_params *params)
+{
+       void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
+
+       USB_CTRL_UNSET(ctrl, USB_PM, XHC_S2_CLK_SWITCH_EN);
+       USB_CTRL_UNSET(ctrl, USB_PM, USB_PWRDN);
+
+       /* 1 millisecond - for USB clocks to settle down */
+       usleep_range(1000, 2000);
+
+       usb_wake_enable_7216(params, false);
+       usb_init_common(params);
+}
+
 static void usb_init_xhci(struct brcm_usb_init_params *params)
 {
        pr_debug("%s\n", __func__);
        xhci_soft_reset(params, 0);
 }
 
-static void usb_uninit_common(struct brcm_usb_init_params *params)
+static void usb_uninit_common_7216(struct brcm_usb_init_params *params)
 {
        void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
 
        pr_debug("%s\n", __func__);
 
-       USB_CTRL_SET(ctrl, USB_PM, USB_PWRDN);
+       if (!params->wake_enabled) {
+               USB_CTRL_SET(ctrl, USB_PM, USB_PWRDN);
 
+               /* Switch to using slower clock during suspend to save power */
+               USB_CTRL_SET(ctrl, USB_PM, XHC_S2_CLK_SWITCH_EN);
+       } else {
+               usb_wake_enable_7216(params, true);
+       }
 }
 
 static void usb_uninit_common_7211b0(struct brcm_usb_init_params *params)
 
 static const struct brcm_usb_init_ops bcm7216_ops = {
        .init_ipp = usb_init_ipp,
-       .init_common = usb_init_common,
+       .init_common = usb_init_common_7216,
        .init_xhci = usb_init_xhci,
-       .uninit_common = usb_uninit_common,
+       .uninit_common = usb_uninit_common_7216,
        .uninit_xhci = usb_uninit_xhci,
        .get_dual_select = usb_get_dual_select,
        .set_dual_select = usb_set_dual_select,
 
        params->family_name = "7216";
        params->ops = &bcm7216_ops;
+       params->suspend_with_clocks = true;
 }
 
 void brcm_usb_dvr_init_7211b0(struct brcm_usb_init_params *params)