Loading drivers/usb/host/ehci-fsl.c +153 −0 Original line number Diff line number Diff line Loading @@ -328,6 +328,149 @@ struct ehci_fsl { #ifdef CONFIG_PM #ifdef CONFIG_PPC_MPC512x static int ehci_fsl_mpc512x_drv_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct ehci_hcd *ehci = hcd_to_ehci(hcd); struct fsl_usb2_platform_data *pdata = dev->platform_data; u32 tmp; #ifdef DEBUG u32 mode = ehci_readl(ehci, hcd->regs + FSL_SOC_USB_USBMODE); mode &= USBMODE_CM_MASK; tmp = ehci_readl(ehci, hcd->regs + 0x140); /* usbcmd */ dev_dbg(dev, "suspend=%d already_suspended=%d " "mode=%d usbcmd %08x\n", pdata->suspended, pdata->already_suspended, mode, tmp); #endif /* * If the controller is already suspended, then this must be a * PM suspend. Remember this fact, so that we will leave the * controller suspended at PM resume time. */ if (pdata->suspended) { dev_dbg(dev, "already suspended, leaving early\n"); pdata->already_suspended = 1; return 0; } dev_dbg(dev, "suspending...\n"); hcd->state = HC_STATE_SUSPENDED; dev->power.power_state = PMSG_SUSPEND; /* ignore non-host interrupts */ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); /* stop the controller */ tmp = ehci_readl(ehci, &ehci->regs->command); tmp &= ~CMD_RUN; ehci_writel(ehci, tmp, &ehci->regs->command); /* save EHCI registers */ pdata->pm_command = ehci_readl(ehci, &ehci->regs->command); pdata->pm_command &= ~CMD_RUN; pdata->pm_status = ehci_readl(ehci, &ehci->regs->status); pdata->pm_intr_enable = ehci_readl(ehci, &ehci->regs->intr_enable); pdata->pm_frame_index = ehci_readl(ehci, &ehci->regs->frame_index); pdata->pm_segment = ehci_readl(ehci, &ehci->regs->segment); pdata->pm_frame_list = ehci_readl(ehci, &ehci->regs->frame_list); pdata->pm_async_next = ehci_readl(ehci, &ehci->regs->async_next); pdata->pm_configured_flag = ehci_readl(ehci, &ehci->regs->configured_flag); pdata->pm_portsc = ehci_readl(ehci, &ehci->regs->port_status[0]); pdata->pm_usbgenctrl = ehci_readl(ehci, hcd->regs + FSL_SOC_USB_USBGENCTRL); /* clear the W1C bits */ pdata->pm_portsc &= cpu_to_hc32(ehci, ~PORT_RWC_BITS); pdata->suspended = 1; /* clear PP to cut power to the port */ tmp = ehci_readl(ehci, &ehci->regs->port_status[0]); tmp &= ~PORT_POWER; ehci_writel(ehci, tmp, &ehci->regs->port_status[0]); return 0; } static int ehci_fsl_mpc512x_drv_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct ehci_hcd *ehci = hcd_to_ehci(hcd); struct fsl_usb2_platform_data *pdata = dev->platform_data; u32 tmp; dev_dbg(dev, "suspend=%d already_suspended=%d\n", pdata->suspended, pdata->already_suspended); /* * If the controller was already suspended at suspend time, * then don't resume it now. */ if (pdata->already_suspended) { dev_dbg(dev, "already suspended, leaving early\n"); pdata->already_suspended = 0; return 0; } if (!pdata->suspended) { dev_dbg(dev, "not suspended, leaving early\n"); return 0; } pdata->suspended = 0; dev_dbg(dev, "resuming...\n"); /* set host mode */ tmp = USBMODE_CM_HOST | (pdata->es ? USBMODE_ES : 0); ehci_writel(ehci, tmp, hcd->regs + FSL_SOC_USB_USBMODE); ehci_writel(ehci, pdata->pm_usbgenctrl, hcd->regs + FSL_SOC_USB_USBGENCTRL); ehci_writel(ehci, ISIPHYCTRL_PXE | ISIPHYCTRL_PHYE, hcd->regs + FSL_SOC_USB_ISIPHYCTRL); /* restore EHCI registers */ ehci_writel(ehci, pdata->pm_command, &ehci->regs->command); ehci_writel(ehci, pdata->pm_intr_enable, &ehci->regs->intr_enable); ehci_writel(ehci, pdata->pm_frame_index, &ehci->regs->frame_index); ehci_writel(ehci, pdata->pm_segment, &ehci->regs->segment); ehci_writel(ehci, pdata->pm_frame_list, &ehci->regs->frame_list); ehci_writel(ehci, pdata->pm_async_next, &ehci->regs->async_next); ehci_writel(ehci, pdata->pm_configured_flag, &ehci->regs->configured_flag); ehci_writel(ehci, pdata->pm_portsc, &ehci->regs->port_status[0]); set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); hcd->state = HC_STATE_RUNNING; dev->power.power_state = PMSG_ON; tmp = ehci_readl(ehci, &ehci->regs->command); tmp |= CMD_RUN; ehci_writel(ehci, tmp, &ehci->regs->command); usb_hcd_resume_root_hub(hcd); return 0; } #else static inline int ehci_fsl_mpc512x_drv_suspend(struct device *dev) { return 0; } static inline int ehci_fsl_mpc512x_drv_resume(struct device *dev) { return 0; } #endif /* CONFIG_PPC_MPC512x */ static struct ehci_fsl *hcd_to_ehci_fsl(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); Loading @@ -341,6 +484,11 @@ static int ehci_fsl_drv_suspend(struct device *dev) struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd); void __iomem *non_ehci = hcd->regs; if (of_device_is_compatible(dev->parent->of_node, "fsl,mpc5121-usb2-dr")) { return ehci_fsl_mpc512x_drv_suspend(dev); } ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd), device_may_wakeup(dev)); if (!fsl_deep_sleep()) Loading @@ -357,6 +505,11 @@ static int ehci_fsl_drv_resume(struct device *dev) struct ehci_hcd *ehci = hcd_to_ehci(hcd); void __iomem *non_ehci = hcd->regs; if (of_device_is_compatible(dev->parent->of_node, "fsl,mpc5121-usb2-dr")) { return ehci_fsl_mpc512x_drv_resume(dev); } ehci_prepare_ports_for_controller_resume(ehci); if (!fsl_deep_sleep()) return 0; Loading drivers/usb/host/ehci-fsl.h +4 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,10 @@ #define PORT_PTS_SERIAL (3<<30) #define PORT_PTS_PTW (1<<28) #define FSL_SOC_USB_PORTSC2 0x188 #define FSL_SOC_USB_USBMODE 0x1a8 #define USBMODE_CM_MASK (3 << 0) /* controller mode mask */ #define USBMODE_CM_HOST (3 << 0) /* controller mode: host */ #define USBMODE_ES (1 << 2) /* (Big) Endian Select */ #define FSL_SOC_USB_USBGENCTRL 0x200 #define USBGENCTRL_PPP (1 << 3) Loading include/linux/fsl_devices.h +15 −0 Original line number Diff line number Diff line Loading @@ -79,6 +79,21 @@ struct fsl_usb2_platform_data { unsigned have_sysif_regs:1; unsigned invert_drvvbus:1; unsigned invert_pwr_fault:1; unsigned suspended:1; unsigned already_suspended:1; /* register save area for suspend/resume */ u32 pm_command; u32 pm_status; u32 pm_intr_enable; u32 pm_frame_index; u32 pm_segment; u32 pm_frame_list; u32 pm_async_next; u32 pm_configured_flag; u32 pm_portsc; u32 pm_usbgenctrl; }; /* Flags in fsl_usb2_mph_platform_data */ Loading Loading
drivers/usb/host/ehci-fsl.c +153 −0 Original line number Diff line number Diff line Loading @@ -328,6 +328,149 @@ struct ehci_fsl { #ifdef CONFIG_PM #ifdef CONFIG_PPC_MPC512x static int ehci_fsl_mpc512x_drv_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct ehci_hcd *ehci = hcd_to_ehci(hcd); struct fsl_usb2_platform_data *pdata = dev->platform_data; u32 tmp; #ifdef DEBUG u32 mode = ehci_readl(ehci, hcd->regs + FSL_SOC_USB_USBMODE); mode &= USBMODE_CM_MASK; tmp = ehci_readl(ehci, hcd->regs + 0x140); /* usbcmd */ dev_dbg(dev, "suspend=%d already_suspended=%d " "mode=%d usbcmd %08x\n", pdata->suspended, pdata->already_suspended, mode, tmp); #endif /* * If the controller is already suspended, then this must be a * PM suspend. Remember this fact, so that we will leave the * controller suspended at PM resume time. */ if (pdata->suspended) { dev_dbg(dev, "already suspended, leaving early\n"); pdata->already_suspended = 1; return 0; } dev_dbg(dev, "suspending...\n"); hcd->state = HC_STATE_SUSPENDED; dev->power.power_state = PMSG_SUSPEND; /* ignore non-host interrupts */ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); /* stop the controller */ tmp = ehci_readl(ehci, &ehci->regs->command); tmp &= ~CMD_RUN; ehci_writel(ehci, tmp, &ehci->regs->command); /* save EHCI registers */ pdata->pm_command = ehci_readl(ehci, &ehci->regs->command); pdata->pm_command &= ~CMD_RUN; pdata->pm_status = ehci_readl(ehci, &ehci->regs->status); pdata->pm_intr_enable = ehci_readl(ehci, &ehci->regs->intr_enable); pdata->pm_frame_index = ehci_readl(ehci, &ehci->regs->frame_index); pdata->pm_segment = ehci_readl(ehci, &ehci->regs->segment); pdata->pm_frame_list = ehci_readl(ehci, &ehci->regs->frame_list); pdata->pm_async_next = ehci_readl(ehci, &ehci->regs->async_next); pdata->pm_configured_flag = ehci_readl(ehci, &ehci->regs->configured_flag); pdata->pm_portsc = ehci_readl(ehci, &ehci->regs->port_status[0]); pdata->pm_usbgenctrl = ehci_readl(ehci, hcd->regs + FSL_SOC_USB_USBGENCTRL); /* clear the W1C bits */ pdata->pm_portsc &= cpu_to_hc32(ehci, ~PORT_RWC_BITS); pdata->suspended = 1; /* clear PP to cut power to the port */ tmp = ehci_readl(ehci, &ehci->regs->port_status[0]); tmp &= ~PORT_POWER; ehci_writel(ehci, tmp, &ehci->regs->port_status[0]); return 0; } static int ehci_fsl_mpc512x_drv_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct ehci_hcd *ehci = hcd_to_ehci(hcd); struct fsl_usb2_platform_data *pdata = dev->platform_data; u32 tmp; dev_dbg(dev, "suspend=%d already_suspended=%d\n", pdata->suspended, pdata->already_suspended); /* * If the controller was already suspended at suspend time, * then don't resume it now. */ if (pdata->already_suspended) { dev_dbg(dev, "already suspended, leaving early\n"); pdata->already_suspended = 0; return 0; } if (!pdata->suspended) { dev_dbg(dev, "not suspended, leaving early\n"); return 0; } pdata->suspended = 0; dev_dbg(dev, "resuming...\n"); /* set host mode */ tmp = USBMODE_CM_HOST | (pdata->es ? USBMODE_ES : 0); ehci_writel(ehci, tmp, hcd->regs + FSL_SOC_USB_USBMODE); ehci_writel(ehci, pdata->pm_usbgenctrl, hcd->regs + FSL_SOC_USB_USBGENCTRL); ehci_writel(ehci, ISIPHYCTRL_PXE | ISIPHYCTRL_PHYE, hcd->regs + FSL_SOC_USB_ISIPHYCTRL); /* restore EHCI registers */ ehci_writel(ehci, pdata->pm_command, &ehci->regs->command); ehci_writel(ehci, pdata->pm_intr_enable, &ehci->regs->intr_enable); ehci_writel(ehci, pdata->pm_frame_index, &ehci->regs->frame_index); ehci_writel(ehci, pdata->pm_segment, &ehci->regs->segment); ehci_writel(ehci, pdata->pm_frame_list, &ehci->regs->frame_list); ehci_writel(ehci, pdata->pm_async_next, &ehci->regs->async_next); ehci_writel(ehci, pdata->pm_configured_flag, &ehci->regs->configured_flag); ehci_writel(ehci, pdata->pm_portsc, &ehci->regs->port_status[0]); set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); hcd->state = HC_STATE_RUNNING; dev->power.power_state = PMSG_ON; tmp = ehci_readl(ehci, &ehci->regs->command); tmp |= CMD_RUN; ehci_writel(ehci, tmp, &ehci->regs->command); usb_hcd_resume_root_hub(hcd); return 0; } #else static inline int ehci_fsl_mpc512x_drv_suspend(struct device *dev) { return 0; } static inline int ehci_fsl_mpc512x_drv_resume(struct device *dev) { return 0; } #endif /* CONFIG_PPC_MPC512x */ static struct ehci_fsl *hcd_to_ehci_fsl(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); Loading @@ -341,6 +484,11 @@ static int ehci_fsl_drv_suspend(struct device *dev) struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd); void __iomem *non_ehci = hcd->regs; if (of_device_is_compatible(dev->parent->of_node, "fsl,mpc5121-usb2-dr")) { return ehci_fsl_mpc512x_drv_suspend(dev); } ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd), device_may_wakeup(dev)); if (!fsl_deep_sleep()) Loading @@ -357,6 +505,11 @@ static int ehci_fsl_drv_resume(struct device *dev) struct ehci_hcd *ehci = hcd_to_ehci(hcd); void __iomem *non_ehci = hcd->regs; if (of_device_is_compatible(dev->parent->of_node, "fsl,mpc5121-usb2-dr")) { return ehci_fsl_mpc512x_drv_resume(dev); } ehci_prepare_ports_for_controller_resume(ehci); if (!fsl_deep_sleep()) return 0; Loading
drivers/usb/host/ehci-fsl.h +4 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,10 @@ #define PORT_PTS_SERIAL (3<<30) #define PORT_PTS_PTW (1<<28) #define FSL_SOC_USB_PORTSC2 0x188 #define FSL_SOC_USB_USBMODE 0x1a8 #define USBMODE_CM_MASK (3 << 0) /* controller mode mask */ #define USBMODE_CM_HOST (3 << 0) /* controller mode: host */ #define USBMODE_ES (1 << 2) /* (Big) Endian Select */ #define FSL_SOC_USB_USBGENCTRL 0x200 #define USBGENCTRL_PPP (1 << 3) Loading
include/linux/fsl_devices.h +15 −0 Original line number Diff line number Diff line Loading @@ -79,6 +79,21 @@ struct fsl_usb2_platform_data { unsigned have_sysif_regs:1; unsigned invert_drvvbus:1; unsigned invert_pwr_fault:1; unsigned suspended:1; unsigned already_suspended:1; /* register save area for suspend/resume */ u32 pm_command; u32 pm_status; u32 pm_intr_enable; u32 pm_frame_index; u32 pm_segment; u32 pm_frame_list; u32 pm_async_next; u32 pm_configured_flag; u32 pm_portsc; u32 pm_usbgenctrl; }; /* Flags in fsl_usb2_mph_platform_data */ Loading