aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2011-09-13 11:54:39 -0400
committerFelipe Balbi <balbi@ti.com>2012-04-30 04:31:21 -0400
commite6a3b5e2888b51e37c65c97dae966f793bc4806a (patch)
tree934c2a7578d15dedbe2221c28cbdff7afd28588f
parent51249dca627d9d0e6b41531e716cbc308554a62c (diff)
usb: dwc3: ep0: add LPM handling
On device loading the driver enables LPM and the acceptance of U1 and U2 states. The [Set|Clear]Feature requests for "U1/U2" are forwarded directly to the hardware and allow / forbid the initiation of the low power links. Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Felipe Balbi <balbi@ti.com>
-rw-r--r--drivers/usb/dwc3/core.h1
-rw-r--r--drivers/usb/dwc3/ep0.c46
-rw-r--r--drivers/usb/dwc3/gadget.c9
3 files changed, 45 insertions, 11 deletions
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index c7b3ca037bbc..93f9973ad53e 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -194,6 +194,7 @@
194#define DWC3_GHWPARAMS1_EN_PWROPT_CLK 1 194#define DWC3_GHWPARAMS1_EN_PWROPT_CLK 1
195 195
196/* Device Configuration Register */ 196/* Device Configuration Register */
197#define DWC3_DCFG_LPM_CAP (1 << 22)
197#define DWC3_DCFG_DEVADDR(addr) ((addr) << 3) 198#define DWC3_DCFG_DEVADDR(addr) ((addr) << 3)
198#define DWC3_DCFG_DEVADDR_MASK DWC3_DCFG_DEVADDR(0x7f) 199#define DWC3_DCFG_DEVADDR_MASK DWC3_DCFG_DEVADDR(0x7f)
199 200
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 25910e251c04..18494b0d7d6e 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -261,6 +261,7 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc,
261{ 261{
262 struct dwc3_ep *dep; 262 struct dwc3_ep *dep;
263 u32 recip; 263 u32 recip;
264 u32 reg;
264 u16 usb_status = 0; 265 u16 usb_status = 0;
265 __le16 *response_pkt; 266 __le16 *response_pkt;
266 267
@@ -268,10 +269,18 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc,
268 switch (recip) { 269 switch (recip) {
269 case USB_RECIP_DEVICE: 270 case USB_RECIP_DEVICE:
270 /* 271 /*
271 * We are self-powered. U1/U2/LTM will be set later 272 * LTM will be set once we know how to set this in HW.
272 * once we handle this states. RemoteWakeup is 0 on SS
273 */ 273 */
274 usb_status |= dwc->is_selfpowered << USB_DEVICE_SELF_POWERED; 274 usb_status |= dwc->is_selfpowered << USB_DEVICE_SELF_POWERED;
275
276 if (dwc->speed == DWC3_DSTS_SUPERSPEED) {
277 reg = dwc3_readl(dwc->regs, DWC3_DCTL);
278 if (reg & DWC3_DCTL_INITU1ENA)
279 usb_status |= 1 << USB_DEV_STAT_U1_ENABLED;
280 if (reg & DWC3_DCTL_INITU2ENA)
281 usb_status |= 1 << USB_DEV_STAT_U2_ENABLED;
282 }
283
275 break; 284 break;
276 285
277 case USB_RECIP_INTERFACE: 286 case USB_RECIP_INTERFACE:
@@ -312,6 +321,7 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
312 u32 recip; 321 u32 recip;
313 u32 wValue; 322 u32 wValue;
314 u32 wIndex; 323 u32 wIndex;
324 u32 reg;
315 int ret; 325 int ret;
316 326
317 wValue = le16_to_cpu(ctrl->wValue); 327 wValue = le16_to_cpu(ctrl->wValue);
@@ -320,29 +330,43 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
320 switch (recip) { 330 switch (recip) {
321 case USB_RECIP_DEVICE: 331 case USB_RECIP_DEVICE:
322 332
333 switch (wValue) {
334 case USB_DEVICE_REMOTE_WAKEUP:
335 break;
323 /* 336 /*
324 * 9.4.1 says only only for SS, in AddressState only for 337 * 9.4.1 says only only for SS, in AddressState only for
325 * default control pipe 338 * default control pipe
326 */ 339 */
327 switch (wValue) {
328 case USB_DEVICE_U1_ENABLE: 340 case USB_DEVICE_U1_ENABLE:
329 case USB_DEVICE_U2_ENABLE:
330 case USB_DEVICE_LTM_ENABLE:
331 if (dwc->dev_state != DWC3_CONFIGURED_STATE) 341 if (dwc->dev_state != DWC3_CONFIGURED_STATE)
332 return -EINVAL; 342 return -EINVAL;
333 if (dwc->speed != DWC3_DSTS_SUPERSPEED) 343 if (dwc->speed != DWC3_DSTS_SUPERSPEED)
334 return -EINVAL; 344 return -EINVAL;
335 }
336 345
337 /* XXX add U[12] & LTM */ 346 reg = dwc3_readl(dwc->regs, DWC3_DCTL);
338 switch (wValue) { 347 if (set)
339 case USB_DEVICE_REMOTE_WAKEUP: 348 reg |= DWC3_DCTL_INITU1ENA;
340 break; 349 else
341 case USB_DEVICE_U1_ENABLE: 350 reg &= ~DWC3_DCTL_INITU1ENA;
351 dwc3_writel(dwc->regs, DWC3_DCTL, reg);
342 break; 352 break;
353
343 case USB_DEVICE_U2_ENABLE: 354 case USB_DEVICE_U2_ENABLE:
355 if (dwc->dev_state != DWC3_CONFIGURED_STATE)
356 return -EINVAL;
357 if (dwc->speed != DWC3_DSTS_SUPERSPEED)
358 return -EINVAL;
359
360 reg = dwc3_readl(dwc->regs, DWC3_DCTL);
361 if (set)
362 reg |= DWC3_DCTL_INITU2ENA;
363 else
364 reg &= ~DWC3_DCTL_INITU2ENA;
365 dwc3_writel(dwc->regs, DWC3_DCTL, reg);
344 break; 366 break;
367
345 case USB_DEVICE_LTM_ENABLE: 368 case USB_DEVICE_LTM_ENABLE:
369 return -EINVAL;
346 break; 370 break;
347 371
348 case USB_DEVICE_TEST_MODE: 372 case USB_DEVICE_TEST_MODE:
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index dda56b8f8617..906db570ef4f 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1933,6 +1933,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
1933 1933
1934 reg = dwc3_readl(dwc->regs, DWC3_DCTL); 1934 reg = dwc3_readl(dwc->regs, DWC3_DCTL);
1935 reg &= ~DWC3_DCTL_TSTCTRL_MASK; 1935 reg &= ~DWC3_DCTL_TSTCTRL_MASK;
1936 reg &= ~(DWC3_DCTL_INITU1ENA | DWC3_DCTL_INITU2ENA);
1936 dwc3_writel(dwc->regs, DWC3_DCTL, reg); 1937 dwc3_writel(dwc->regs, DWC3_DCTL, reg);
1937 dwc->test_mode = false; 1938 dwc->test_mode = false;
1938 1939
@@ -2330,6 +2331,14 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc)
2330 goto err5; 2331 goto err5;
2331 } 2332 }
2332 2333
2334 reg = dwc3_readl(dwc->regs, DWC3_DCFG);
2335 reg |= DWC3_DCFG_LPM_CAP;
2336 dwc3_writel(dwc->regs, DWC3_DCFG, reg);
2337
2338 reg = dwc3_readl(dwc->regs, DWC3_DCTL);
2339 reg |= DWC3_DCTL_ACCEPTU1ENA | DWC3_DCTL_ACCEPTU2ENA;
2340 dwc3_writel(dwc->regs, DWC3_DCTL, reg);
2341
2333 /* Enable all but Start and End of Frame IRQs */ 2342 /* Enable all but Start and End of Frame IRQs */
2334 reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN | 2343 reg = (DWC3_DEVTEN_VNDRDEVTSTRCVEDEN |
2335 DWC3_DEVTEN_EVNTOVERFLOWEN | 2344 DWC3_DEVTEN_EVNTOVERFLOWEN |