Hi Mathias, On Wed, 2021-02-03 at 18:26 +0800, Chunfeng Yun wrote: > There are 4 USB controllers on MT8195, the controllers (IP1~IP3, > exclude IP0) have a wrong default SOF/ITP interval which is > calculated from the frame counter clock 24Mhz by default, but > in fact, the frame counter clock is 48Mhz, so we should set > the accurate interval according to 48Mhz for those controllers. > Note: the first controller no need set it. > > Signed-off-by: Chunfeng Yun <chunfeng.yun@xxxxxxxxxxxx> > --- > v2: fix typo of comaptible > --- > drivers/usb/host/xhci-mtk.c | 63 +++++++++++++++++++++++++++++++++++++ > 1 file changed, 63 insertions(+) > > diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c > index 8f321f39ab96..0a68c4ac8b48 100644 > --- a/drivers/usb/host/xhci-mtk.c > +++ b/drivers/usb/host/xhci-mtk.c > @@ -68,11 +68,71 @@ > #define SSC_IP_SLEEP_EN BIT(4) > #define SSC_SPM_INT_EN BIT(1) > Can I Read/Write the following xHCI controller's registers in xhci-mtk.c? Ideally, xhci-mtk.c should not access them, because xhci-mtk is only a glue driver used to initialize clocks/power and IPPC registers which don't belong to xHCI controller. Thanks > +/* xHCI csr */ > +#define LS_EOF 0x930 > +#define LS_EOF_OFFSET 0x89 > + > +#define FS_EOF 0x934 > +#define FS_EOF_OFFSET 0x2e > + > +#define SS_GEN1_EOF 0x93c > +#define SS_GEN1_EOF_OFFSET 0x78 > + > +#define HFCNTR_CFG 0x944 > +#define ITP_DELTA_CLK (0xa << 1) > +#define ITP_DELTA_CLK_MASK GENMASK(5, 1) > +#define FRMCNT_LEV1_RANG (0x12b << 8) > +#define FRMCNT_LEV1_RANG_MASK GENMASK(19, 8) > + > +#define SS_GEN2_EOF 0x990 > +#define SS_GEN2_EOF_OFFSET 0x3c > +#define EOF_OFFSET_MASK GENMASK(11, 0) > + > enum ssusb_uwk_vers { > SSUSB_UWK_V1 = 1, > SSUSB_UWK_V2, > }; > > +/* > + * MT8195 has 4 controllers, the controller1~3's default SOF/ITP interval > + * is calculated from the frame counter clock 24M, but in fact, the clock > + * is 48M, so need change the interval. > + */ > +static void xhci_mtk_set_frame_interval(struct xhci_hcd_mtk *mtk) > +{ > + struct device *dev = mtk->dev; > + struct usb_hcd *hcd = mtk->hcd; > + u32 value; > + > + if (!of_device_is_compatible(dev->of_node, "mediatek,mt8195-xhci")) > + return; > + > + value = readl(hcd->regs + HFCNTR_CFG); > + value &= ~(ITP_DELTA_CLK_MASK | FRMCNT_LEV1_RANG_MASK); > + value |= (ITP_DELTA_CLK | FRMCNT_LEV1_RANG); > + writel(value, hcd->regs + HFCNTR_CFG); > + > + value = readl(hcd->regs + LS_EOF); > + value &= ~EOF_OFFSET_MASK; > + value |= LS_EOF_OFFSET; > + writel(value, hcd->regs + LS_EOF); > + > + value = readl(hcd->regs + FS_EOF); > + value &= ~EOF_OFFSET_MASK; > + value |= FS_EOF_OFFSET; > + writel(value, hcd->regs + FS_EOF); > + > + value = readl(hcd->regs + SS_GEN1_EOF); > + value &= ~EOF_OFFSET_MASK; > + value |= SS_GEN1_EOF_OFFSET; > + writel(value, hcd->regs + SS_GEN1_EOF); > + > + value = readl(hcd->regs + SS_GEN2_EOF); > + value &= ~EOF_OFFSET_MASK; > + value |= SS_GEN2_EOF_OFFSET; > + writel(value, hcd->regs + SS_GEN2_EOF); > +} > + > static int xhci_mtk_host_enable(struct xhci_hcd_mtk *mtk) > { > struct mu3c_ippc_regs __iomem *ippc = mtk->ippc_regs; > @@ -407,6 +467,8 @@ static int xhci_mtk_setup(struct usb_hcd *hcd) > ret = xhci_mtk_ssusb_config(mtk); > if (ret) > return ret; > + > + xhci_mtk_set_frame_interval(mtk); > } > > ret = xhci_gen_setup(hcd, xhci_mtk_quirks); > @@ -655,6 +717,7 @@ static const struct dev_pm_ops xhci_mtk_pm_ops = { > #ifdef CONFIG_OF > static const struct of_device_id mtk_xhci_of_match[] = { > { .compatible = "mediatek,mt8173-xhci"}, > + { .compatible = "mediatek,mt8195-xhci"}, > { .compatible = "mediatek,mtk-xhci"}, > { }, > };