1818#include <linux/soc/brcmstb/brcmstb.h>
1919#include <dt-bindings/phy/phy.h>
2020#include <linux/mfd/syscon.h>
21+ #include <linux/suspend.h>
2122
2223#include "phy-brcm-usb-init.h"
2324
@@ -70,12 +71,35 @@ struct brcm_usb_phy_data {
7071 int init_count ;
7172 int wake_irq ;
7273 struct brcm_usb_phy phys [BRCM_USB_PHY_ID_MAX ];
74+ struct notifier_block pm_notifier ;
75+ bool pm_active ;
7376};
7477
7578static s8 * node_reg_names [BRCM_REGS_MAX ] = {
7679 "crtl" , "xhci_ec" , "xhci_gbl" , "usb_phy" , "usb_mdio" , "bdc_ec"
7780};
7881
82+ static int brcm_pm_notifier (struct notifier_block * notifier ,
83+ unsigned long pm_event ,
84+ void * unused )
85+ {
86+ struct brcm_usb_phy_data * priv =
87+ container_of (notifier , struct brcm_usb_phy_data , pm_notifier );
88+
89+ switch (pm_event ) {
90+ case PM_HIBERNATION_PREPARE :
91+ case PM_SUSPEND_PREPARE :
92+ priv -> pm_active = true;
93+ break ;
94+ case PM_POST_RESTORE :
95+ case PM_POST_HIBERNATION :
96+ case PM_POST_SUSPEND :
97+ priv -> pm_active = false;
98+ break ;
99+ }
100+ return NOTIFY_DONE ;
101+ }
102+
79103static irqreturn_t brcm_usb_phy_wake_isr (int irq , void * dev_id )
80104{
81105 struct phy * gphy = dev_id ;
@@ -91,6 +115,9 @@ static int brcm_usb_phy_init(struct phy *gphy)
91115 struct brcm_usb_phy_data * priv =
92116 container_of (phy , struct brcm_usb_phy_data , phys [phy -> id ]);
93117
118+ if (priv -> pm_active )
119+ return 0 ;
120+
94121 /*
95122 * Use a lock to make sure a second caller waits until
96123 * the base phy is inited before using it.
@@ -120,6 +147,9 @@ static int brcm_usb_phy_exit(struct phy *gphy)
120147 struct brcm_usb_phy_data * priv =
121148 container_of (phy , struct brcm_usb_phy_data , phys [phy -> id ]);
122149
150+ if (priv -> pm_active )
151+ return 0 ;
152+
123153 dev_dbg (& gphy -> dev , "EXIT\n" );
124154 if (phy -> id == BRCM_USB_PHY_2_0 )
125155 brcm_usb_uninit_eohci (& priv -> ini );
@@ -488,6 +518,9 @@ static int brcm_usb_phy_probe(struct platform_device *pdev)
488518 if (err )
489519 return err ;
490520
521+ priv -> pm_notifier .notifier_call = brcm_pm_notifier ;
522+ register_pm_notifier (& priv -> pm_notifier );
523+
491524 mutex_init (& priv -> mutex );
492525
493526 /* make sure invert settings are correct */
@@ -528,7 +561,10 @@ static int brcm_usb_phy_probe(struct platform_device *pdev)
528561
529562static int brcm_usb_phy_remove (struct platform_device * pdev )
530563{
564+ struct brcm_usb_phy_data * priv = dev_get_drvdata (& pdev -> dev );
565+
531566 sysfs_remove_group (& pdev -> dev .kobj , & brcm_usb_phy_group );
567+ unregister_pm_notifier (& priv -> pm_notifier );
532568
533569 return 0 ;
534570}
@@ -539,6 +575,7 @@ static int brcm_usb_phy_suspend(struct device *dev)
539575 struct brcm_usb_phy_data * priv = dev_get_drvdata (dev );
540576
541577 if (priv -> init_count ) {
578+ dev_dbg (dev , "SUSPEND\n" );
542579 priv -> ini .wake_enabled = device_may_wakeup (dev );
543580 if (priv -> phys [BRCM_USB_PHY_3_0 ].inited )
544581 brcm_usb_uninit_xhci (& priv -> ini );
@@ -578,6 +615,7 @@ static int brcm_usb_phy_resume(struct device *dev)
578615 * Uninitialize anything that wasn't previously initialized.
579616 */
580617 if (priv -> init_count ) {
618+ dev_dbg (dev , "RESUME\n" );
581619 if (priv -> wake_irq >= 0 )
582620 disable_irq_wake (priv -> wake_irq );
583621 brcm_usb_init_common (& priv -> ini );
0 commit comments