From b1234e3b3b265588bab1e7a28508621045b87efa Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Wed, 2 Sep 2020 17:57:32 +0800 Subject: usb: cdns3: add runtime PM support Introduce runtime PM and wakeup interrupt handler for cdns3, the runtime PM is default off since other cdns3 may not implement glue layer support for runtime PM. One typical wakeup event use case is xHCI runtime suspend will clear USBCMD.RS bit, after that the xHCI will not trigger any interrupts, so its parent (cdns core device) needs to resume xHCI device when any (wakeup) events occurs at host port. When the controller is in low power mode, the lpm flag will be set. The interrupt triggered later than lpm flag is set considers as wakeup interrupt and handled at cdns_wakeup_irq. Once the wakeup occurs, it first disables interrupt to avoid later interrupt occurrence since the controller is in low power mode at that time, and access registers may be invalid at that time. At wakeup handler, it will call pm_request_resume to wakeup xHCI device, and at runtime resume handler, it will enable interrupt again. The API platform_suspend is introduced for glue layer to implement platform specific PM sequence. Reviewed-by: Pawel Laszczak Signed-off-by: Peter Chen Signed-off-by: Felipe Balbi --- drivers/usb/cdns3/core.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers/usb/cdns3/core.h') diff --git a/drivers/usb/cdns3/core.h b/drivers/usb/cdns3/core.h index 1ad1f1fe61e9..1b1707796db2 100644 --- a/drivers/usb/cdns3/core.h +++ b/drivers/usb/cdns3/core.h @@ -38,6 +38,12 @@ struct cdns3_role_driver { }; #define CDNS3_XHCI_RESOURCES_NUM 2 + +struct cdns3_platform_data { + int (*platform_suspend)(struct device *dev, + bool suspend, bool wakeup); +}; + /** * struct cdns3 - Representation of Cadence USB3 DRD controller. * @dev: pointer to Cadence device struct @@ -50,6 +56,7 @@ struct cdns3_role_driver { * @otg_regs: pointer to base of otg registers * @otg_irq: irq number for otg controller * @dev_irq: irq number for device controller + * @wakeup_irq: irq number for wakeup event, it is optional * @roles: array of supported roles for this controller * @role: current role * @host_dev: the child host device pointer for cdns3 core @@ -62,6 +69,10 @@ struct cdns3_role_driver { * This field based on firmware setting, kernel configuration * and hardware configuration. * @role_sw: pointer to role switch object. + * @in_lpm: indicate the controller is in low power mode + * @wakeup_pending: wakeup interrupt pending + * @pdata: platform data from glue layer + * @lock: spinlock structure */ struct cdns3 { struct device *dev; @@ -79,6 +90,7 @@ struct cdns3 { int otg_irq; int dev_irq; + int wakeup_irq; struct cdns3_role_driver *roles[USB_ROLE_DEVICE + 1]; enum usb_role role; struct platform_device *host_dev; @@ -89,6 +101,10 @@ struct cdns3 { struct mutex mutex; enum usb_dr_mode dr_mode; struct usb_role_switch *role_sw; + bool in_lpm; + bool wakeup_pending; + struct cdns3_platform_data *pdata; + spinlock_t lock; }; int cdns3_hw_role_switch(struct cdns3 *cdns); -- cgit v1.2.3 From 2eae2dfd581420f94d6041dddc7a88d7ae9ce2ff Mon Sep 17 00:00:00 2001 From: Pawel Laszczak Date: Tue, 15 Sep 2020 14:45:43 +0300 Subject: usb: cdns3: Enable workaround for USB2.0 PHY Rx compliance test PHY lockup USB2.0 PHY hangs in Rx Compliance test when the incoming packet amplitude is varied below and above the Squelch Level of Receiver during the active packet multiple times. Version 1 of the controller allows PHY to be reset when RX fail condition is detected to work around the above issue. This feature is disabled by default and needs to be enabled using a bit from the newly added PHYRST_CFG register. This patch enables the workaround. There is no way to know controller version before device controller is started and the workaround needs to be applied for both host and device modes, so we rely on a DT property do decide when to apply the workaround. Signed-off-by: Pawel Laszczak Signed-off-by: Roger Quadros Signed-off-by: Felipe Balbi --- drivers/usb/cdns3/core.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/usb/cdns3/core.h') diff --git a/drivers/usb/cdns3/core.h b/drivers/usb/cdns3/core.h index 1b1707796db2..8a40d53d5ede 100644 --- a/drivers/usb/cdns3/core.h +++ b/drivers/usb/cdns3/core.h @@ -87,6 +87,7 @@ struct cdns3 { #define CDNS3_CONTROLLER_V0 0 #define CDNS3_CONTROLLER_V1 1 u32 version; + bool phyrst_a_enable; int otg_irq; int dev_irq; -- cgit v1.2.3