@@ -328,6 +328,149 @@ struct ehci_fsl {
328
328
329
329
#ifdef CONFIG_PM
330
330
331
+ #ifdef CONFIG_PPC_MPC512x
332
+ static int ehci_fsl_mpc512x_drv_suspend (struct device * dev )
333
+ {
334
+ struct usb_hcd * hcd = dev_get_drvdata (dev );
335
+ struct ehci_hcd * ehci = hcd_to_ehci (hcd );
336
+ struct fsl_usb2_platform_data * pdata = dev -> platform_data ;
337
+ u32 tmp ;
338
+
339
+ #ifdef DEBUG
340
+ u32 mode = ehci_readl (ehci , hcd -> regs + FSL_SOC_USB_USBMODE );
341
+ mode &= USBMODE_CM_MASK ;
342
+ tmp = ehci_readl (ehci , hcd -> regs + 0x140 ); /* usbcmd */
343
+
344
+ dev_dbg (dev , "suspend=%d already_suspended=%d "
345
+ "mode=%d usbcmd %08x\n" , pdata -> suspended ,
346
+ pdata -> already_suspended , mode , tmp );
347
+ #endif
348
+
349
+ /*
350
+ * If the controller is already suspended, then this must be a
351
+ * PM suspend. Remember this fact, so that we will leave the
352
+ * controller suspended at PM resume time.
353
+ */
354
+ if (pdata -> suspended ) {
355
+ dev_dbg (dev , "already suspended, leaving early\n" );
356
+ pdata -> already_suspended = 1 ;
357
+ return 0 ;
358
+ }
359
+
360
+ dev_dbg (dev , "suspending...\n" );
361
+
362
+ hcd -> state = HC_STATE_SUSPENDED ;
363
+ dev -> power .power_state = PMSG_SUSPEND ;
364
+
365
+ /* ignore non-host interrupts */
366
+ clear_bit (HCD_FLAG_HW_ACCESSIBLE , & hcd -> flags );
367
+
368
+ /* stop the controller */
369
+ tmp = ehci_readl (ehci , & ehci -> regs -> command );
370
+ tmp &= ~CMD_RUN ;
371
+ ehci_writel (ehci , tmp , & ehci -> regs -> command );
372
+
373
+ /* save EHCI registers */
374
+ pdata -> pm_command = ehci_readl (ehci , & ehci -> regs -> command );
375
+ pdata -> pm_command &= ~CMD_RUN ;
376
+ pdata -> pm_status = ehci_readl (ehci , & ehci -> regs -> status );
377
+ pdata -> pm_intr_enable = ehci_readl (ehci , & ehci -> regs -> intr_enable );
378
+ pdata -> pm_frame_index = ehci_readl (ehci , & ehci -> regs -> frame_index );
379
+ pdata -> pm_segment = ehci_readl (ehci , & ehci -> regs -> segment );
380
+ pdata -> pm_frame_list = ehci_readl (ehci , & ehci -> regs -> frame_list );
381
+ pdata -> pm_async_next = ehci_readl (ehci , & ehci -> regs -> async_next );
382
+ pdata -> pm_configured_flag =
383
+ ehci_readl (ehci , & ehci -> regs -> configured_flag );
384
+ pdata -> pm_portsc = ehci_readl (ehci , & ehci -> regs -> port_status [0 ]);
385
+ pdata -> pm_usbgenctrl = ehci_readl (ehci ,
386
+ hcd -> regs + FSL_SOC_USB_USBGENCTRL );
387
+
388
+ /* clear the W1C bits */
389
+ pdata -> pm_portsc &= cpu_to_hc32 (ehci , ~PORT_RWC_BITS );
390
+
391
+ pdata -> suspended = 1 ;
392
+
393
+ /* clear PP to cut power to the port */
394
+ tmp = ehci_readl (ehci , & ehci -> regs -> port_status [0 ]);
395
+ tmp &= ~PORT_POWER ;
396
+ ehci_writel (ehci , tmp , & ehci -> regs -> port_status [0 ]);
397
+
398
+ return 0 ;
399
+ }
400
+
401
+ static int ehci_fsl_mpc512x_drv_resume (struct device * dev )
402
+ {
403
+ struct usb_hcd * hcd = dev_get_drvdata (dev );
404
+ struct ehci_hcd * ehci = hcd_to_ehci (hcd );
405
+ struct fsl_usb2_platform_data * pdata = dev -> platform_data ;
406
+ u32 tmp ;
407
+
408
+ dev_dbg (dev , "suspend=%d already_suspended=%d\n" ,
409
+ pdata -> suspended , pdata -> already_suspended );
410
+
411
+ /*
412
+ * If the controller was already suspended at suspend time,
413
+ * then don't resume it now.
414
+ */
415
+ if (pdata -> already_suspended ) {
416
+ dev_dbg (dev , "already suspended, leaving early\n" );
417
+ pdata -> already_suspended = 0 ;
418
+ return 0 ;
419
+ }
420
+
421
+ if (!pdata -> suspended ) {
422
+ dev_dbg (dev , "not suspended, leaving early\n" );
423
+ return 0 ;
424
+ }
425
+
426
+ pdata -> suspended = 0 ;
427
+
428
+ dev_dbg (dev , "resuming...\n" );
429
+
430
+ /* set host mode */
431
+ tmp = USBMODE_CM_HOST | (pdata -> es ? USBMODE_ES : 0 );
432
+ ehci_writel (ehci , tmp , hcd -> regs + FSL_SOC_USB_USBMODE );
433
+
434
+ ehci_writel (ehci , pdata -> pm_usbgenctrl ,
435
+ hcd -> regs + FSL_SOC_USB_USBGENCTRL );
436
+ ehci_writel (ehci , ISIPHYCTRL_PXE | ISIPHYCTRL_PHYE ,
437
+ hcd -> regs + FSL_SOC_USB_ISIPHYCTRL );
438
+
439
+ /* restore EHCI registers */
440
+ ehci_writel (ehci , pdata -> pm_command , & ehci -> regs -> command );
441
+ ehci_writel (ehci , pdata -> pm_intr_enable , & ehci -> regs -> intr_enable );
442
+ ehci_writel (ehci , pdata -> pm_frame_index , & ehci -> regs -> frame_index );
443
+ ehci_writel (ehci , pdata -> pm_segment , & ehci -> regs -> segment );
444
+ ehci_writel (ehci , pdata -> pm_frame_list , & ehci -> regs -> frame_list );
445
+ ehci_writel (ehci , pdata -> pm_async_next , & ehci -> regs -> async_next );
446
+ ehci_writel (ehci , pdata -> pm_configured_flag ,
447
+ & ehci -> regs -> configured_flag );
448
+ ehci_writel (ehci , pdata -> pm_portsc , & ehci -> regs -> port_status [0 ]);
449
+
450
+ set_bit (HCD_FLAG_HW_ACCESSIBLE , & hcd -> flags );
451
+ hcd -> state = HC_STATE_RUNNING ;
452
+ dev -> power .power_state = PMSG_ON ;
453
+
454
+ tmp = ehci_readl (ehci , & ehci -> regs -> command );
455
+ tmp |= CMD_RUN ;
456
+ ehci_writel (ehci , tmp , & ehci -> regs -> command );
457
+
458
+ usb_hcd_resume_root_hub (hcd );
459
+
460
+ return 0 ;
461
+ }
462
+ #else
463
+ static inline int ehci_fsl_mpc512x_drv_suspend (struct device * dev )
464
+ {
465
+ return 0 ;
466
+ }
467
+
468
+ static inline int ehci_fsl_mpc512x_drv_resume (struct device * dev )
469
+ {
470
+ return 0 ;
471
+ }
472
+ #endif /* CONFIG_PPC_MPC512x */
473
+
331
474
static struct ehci_fsl * hcd_to_ehci_fsl (struct usb_hcd * hcd )
332
475
{
333
476
struct ehci_hcd * ehci = hcd_to_ehci (hcd );
@@ -341,6 +484,11 @@ static int ehci_fsl_drv_suspend(struct device *dev)
341
484
struct ehci_fsl * ehci_fsl = hcd_to_ehci_fsl (hcd );
342
485
void __iomem * non_ehci = hcd -> regs ;
343
486
487
+ if (of_device_is_compatible (dev -> parent -> of_node ,
488
+ "fsl,mpc5121-usb2-dr" )) {
489
+ return ehci_fsl_mpc512x_drv_suspend (dev );
490
+ }
491
+
344
492
ehci_prepare_ports_for_controller_suspend (hcd_to_ehci (hcd ),
345
493
device_may_wakeup (dev ));
346
494
if (!fsl_deep_sleep ())
@@ -357,6 +505,11 @@ static int ehci_fsl_drv_resume(struct device *dev)
357
505
struct ehci_hcd * ehci = hcd_to_ehci (hcd );
358
506
void __iomem * non_ehci = hcd -> regs ;
359
507
508
+ if (of_device_is_compatible (dev -> parent -> of_node ,
509
+ "fsl,mpc5121-usb2-dr" )) {
510
+ return ehci_fsl_mpc512x_drv_resume (dev );
511
+ }
512
+
360
513
ehci_prepare_ports_for_controller_resume (ehci );
361
514
if (!fsl_deep_sleep ())
362
515
return 0 ;
0 commit comments