]> git.baikalelectronics.ru Git - kernel.git/commitdiff
usb: chipidea: add workaround for chipidea PEC bug
authorXu Yang <xu.yang_2@nxp.com>
Wed, 9 Aug 2023 02:44:32 +0000 (10:44 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 23 Sep 2023 09:11:07 +0000 (11:11 +0200)
[ Upstream commit 12e6ac69cc7e7d3367599ae26a92a0f9a18bc728 ]

Some NXP processors using ChipIdea USB IP have a bug when frame babble is
detected.

Issue description:
In USB camera test, our controller is host in HS mode. In ISOC IN, when
device sends data across the micro frame, it causes the babble in host
controller. This will clear the PE bit. In spec, it also requires to set
the PEC bit and then set the PCI bit. Without the PCI interrupt, the
software does not know the PE is cleared.

This will add a flag CI_HDRC_HAS_PORTSC_PEC_MISSED to some impacted
platform datas. And the ehci host driver will assert PEC by SW when
specific conditions are satisfied.

Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
Link: https://lore.kernel.org/r/20230809024432.535160-2-xu.yang_2@nxp.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/usb/chipidea/ci.h
drivers/usb/chipidea/ci_hdrc_imx.c
drivers/usb/chipidea/core.c
drivers/usb/chipidea/host.c
include/linux/usb/chipidea.h

index 85a803c135ab31b7cf6766158081b24f5dc8cb82..2ff83911219f85218cefb7d400a5f53765bbd390 100644 (file)
@@ -253,6 +253,7 @@ struct ci_hdrc {
        bool                            id_event;
        bool                            b_sess_valid_event;
        bool                            imx28_write_fix;
+       bool                            has_portsc_pec_bug;
        bool                            supports_runtime_pm;
        bool                            in_lpm;
        bool                            wakeup_int;
index caa91117ba4291198e035d553b9f7ecb47981b4d..984087bbf3e2b1475168a89281d669eb22bb3f4d 100644 (file)
@@ -67,11 +67,13 @@ static const struct ci_hdrc_imx_platform_flag imx7d_usb_data = {
 
 static const struct ci_hdrc_imx_platform_flag imx7ulp_usb_data = {
        .flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
+               CI_HDRC_HAS_PORTSC_PEC_MISSED |
                CI_HDRC_PMQOS,
 };
 
 static const struct ci_hdrc_imx_platform_flag imx8ulp_usb_data = {
-       .flags = CI_HDRC_SUPPORTS_RUNTIME_PM,
+       .flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
+               CI_HDRC_HAS_PORTSC_PEC_MISSED,
 };
 
 static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
index 71f172ecfaabcba484e0bf7edf75c726a426e77b..b9227f41cf1c08f930c9d87cc929a1b56ca80991 100644 (file)
@@ -1038,6 +1038,8 @@ static int ci_hdrc_probe(struct platform_device *pdev)
                CI_HDRC_IMX28_WRITE_FIX);
        ci->supports_runtime_pm = !!(ci->platdata->flags &
                CI_HDRC_SUPPORTS_RUNTIME_PM);
+       ci->has_portsc_pec_bug = !!(ci->platdata->flags &
+               CI_HDRC_HAS_PORTSC_PEC_MISSED);
        platform_set_drvdata(pdev, ci);
 
        ret = hw_device_init(ci, base);
index bc3634a54c6b7f5e5e3aa95bac1e7af0e41e642e..3b08c5e81170748fec0cd2afd49db9c37f0aaa7a 100644 (file)
@@ -151,6 +151,7 @@ static int host_start(struct ci_hdrc *ci)
        ehci->has_hostpc = ci->hw_bank.lpm;
        ehci->has_tdi_phy_lpm = ci->hw_bank.lpm;
        ehci->imx28_write_fix = ci->imx28_write_fix;
+       ehci->has_ci_pec_bug = ci->has_portsc_pec_bug;
 
        priv = (struct ehci_ci_priv *)ehci->priv;
        priv->reg_vbus = NULL;
index ee38835ed77cc4bd2b43425fffbaff280c3ab881..0b4f2d5faa080dfd122a051d8fde6b706fe6c61f 100644 (file)
@@ -63,6 +63,7 @@ struct ci_hdrc_platform_data {
 #define CI_HDRC_IMX_IS_HSIC            BIT(14)
 #define CI_HDRC_PMQOS                  BIT(15)
 #define CI_HDRC_PHY_VBUS_CONTROL       BIT(16)
+#define CI_HDRC_HAS_PORTSC_PEC_MISSED  BIT(17)
        enum usb_dr_mode        dr_mode;
 #define CI_HDRC_CONTROLLER_RESET_EVENT         0
 #define CI_HDRC_CONTROLLER_STOPPED_EVENT       1