usb: cdnsp: fix L1 resume issue for RTL_REVISION_NEW_LPM version
commit8614ecdb15upstream. The controllers with rtl version larger than RTL_REVISION_NEW_LPM (0x00002700) has bug which causes that controller doesn't resume from L1 state. It happens if after receiving LPM packet controller starts transitioning to L1 and in this moment the driver force resuming by write operation to PORTSC.PLS. It's corner case and happens when write operation to PORTSC occurs during device delay before transitioning to L1 after transmitting ACK time (TL1TokenRetry). Forcing transition from L1->L0 by driver for revision larger than RTL_REVISION_NEW_LPM is not needed, so driver can simply fix this issue through block call of cdnsp_force_l0_go function. Fixes:3d82904559("usb: cdnsp: cdns3 Add main part of Cadence USBSSP DRD Driver") Cc: stable <stable@kernel.org> Signed-off-by: Pawel Laszczak <pawell@cadence.com> Acked-by: Peter Chen <peter.chen@kernel.org> Link: https://lore.kernel.org/r/PH7PR07MB9538B55C3A6E71F9ED29E980DD842@PH7PR07MB9538.namprd07.prod.outlook.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
815d6afeac
commit
2997957a4e
@@ -1799,6 +1799,8 @@ static void cdnsp_get_rev_cap(struct cdnsp_device *pdev)
|
||||
reg += cdnsp_find_next_ext_cap(reg, 0, RTL_REV_CAP);
|
||||
pdev->rev_cap = reg;
|
||||
|
||||
pdev->rtl_revision = readl(&pdev->rev_cap->rtl_revision);
|
||||
|
||||
dev_info(pdev->dev, "Rev: %08x/%08x, eps: %08x, buff: %08x/%08x\n",
|
||||
readl(&pdev->rev_cap->ctrl_revision),
|
||||
readl(&pdev->rev_cap->rtl_revision),
|
||||
|
||||
@@ -1362,6 +1362,7 @@ struct cdnsp_port {
|
||||
* @rev_cap: Controller Capabilities Registers.
|
||||
* @hcs_params1: Cached register copies of read-only HCSPARAMS1
|
||||
* @hcc_params: Cached register copies of read-only HCCPARAMS1
|
||||
* @rtl_revision: Cached controller rtl revision.
|
||||
* @setup: Temporary buffer for setup packet.
|
||||
* @ep0_preq: Internal allocated request used during enumeration.
|
||||
* @ep0_stage: ep0 stage during enumeration process.
|
||||
@@ -1416,6 +1417,8 @@ struct cdnsp_device {
|
||||
__u32 hcs_params1;
|
||||
__u32 hcs_params3;
|
||||
__u32 hcc_params;
|
||||
#define RTL_REVISION_NEW_LPM 0x2700
|
||||
__u32 rtl_revision;
|
||||
/* Lock used in interrupt thread context. */
|
||||
spinlock_t lock;
|
||||
struct usb_ctrlrequest setup;
|
||||
|
||||
@@ -308,7 +308,8 @@ static bool cdnsp_ring_ep_doorbell(struct cdnsp_device *pdev,
|
||||
|
||||
writel(db_value, reg_addr);
|
||||
|
||||
cdnsp_force_l0_go(pdev);
|
||||
if (pdev->rtl_revision < RTL_REVISION_NEW_LPM)
|
||||
cdnsp_force_l0_go(pdev);
|
||||
|
||||
/* Doorbell was set. */
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user