#define PORTSC_FPR BIT(6)
#define PORTSC_SUSP BIT(7)
#define PORTSC_HSP BIT(9)
+#define PORTSC_LS (BIT(11) | BIT(10))
+#define PORTSC_LS_J BIT(11)
+#define PORTSC_LS_K BIT(10)
#define PORTSC_PP BIT(12)
#define PORTSC_PTC (0x0FUL << 16)
#define PORTSC_WKCN BIT(20)
#define PORTSC_PFSC BIT(24)
#define PORTSC_PTS(d) \
(u32)((((d) & 0x3) << 30) | (((d) & 0x4) ? BIT(25) : 0))
+#define PORT_SPEED_LOW(d) ((((d) >> 26) & 0x3) == 1)
#define PORTSC_PTW BIT(28)
#define PORTSC_STS BIT(29)
void dbg_create_files(struct ci_hdrc *ci);
void dbg_remove_files(struct ci_hdrc *ci);
+
+void ci_hdrc_enter_lpm(struct ci_hdrc *ci, bool enable);
#endif /* __DRIVERS_USB_CHIPIDEA_CI_H */
}
/* The PHY enters/leaves low power mode */
-static void ci_hdrc_enter_lpm(struct ci_hdrc *ci, bool enable)
+void ci_hdrc_enter_lpm(struct ci_hdrc *ci, bool enable)
{
enum ci_hw_regs reg = ci->hw_bank.lpm ? OP_DEVLC : OP_PORTSC;
bool lpm = !!(hw_read(ci, reg, PORTSC_PHCD(ci->hw_bank.lpm)));
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
u32 __iomem *status_reg;
- u32 temp;
+ u32 temp, suspend_line_state;
unsigned long flags;
int retval = 0;
struct device *dev = hcd->self.controller;
PORT_SUSPEND, 5000))
ehci_err(ehci, "timeout waiting for SUSPEND\n");
+ if (ci->platdata->flags & CI_HDRC_HOST_SUSP_PHY_LPM) {
+ if (PORT_SPEED_LOW(temp))
+ suspend_line_state = PORTSC_LS_K;
+ else
+ suspend_line_state = PORTSC_LS_J;
+ if (!ehci_handshake(ehci, status_reg, PORTSC_LS,
+ suspend_line_state, 5000))
+ ci_hdrc_enter_lpm(ci, true);
+ }
+
if (ci->platdata->flags & CI_HDRC_IMX_IS_HSIC) {
if (ci->platdata->notify_event)
ci->platdata->notify_event
#define CI_HDRC_PMQOS BIT(16)
/* Using PHY's charger detection */
#define CI_HDRC_PHY_CHARGER_DETECTION BIT(17)
+/* PHY enter low power mode when bus suspend */
+#define CI_HDRC_HOST_SUSP_PHY_LPM BIT(18)
enum usb_dr_mode dr_mode;
#define CI_HDRC_CONTROLLER_RESET_EVENT 0
#define CI_HDRC_CONTROLLER_STOPPED_EVENT 1