|
56 | 56 | /* u2_phy_pll register */
|
57 | 57 | #define CTRL_U2_FORCE_PLL_STB BIT(28)
|
58 | 58 |
|
| 59 | +/* xHCI CSR */ |
| 60 | +#define LS_EOF_CFG 0x930 |
| 61 | +#define LSEOF_OFFSET 0x89 |
| 62 | + |
| 63 | +#define FS_EOF_CFG 0x934 |
| 64 | +#define FSEOF_OFFSET 0x2e |
| 65 | + |
| 66 | +#define SS_GEN1_EOF_CFG 0x93c |
| 67 | +#define SSG1EOF_OFFSET 0x78 |
| 68 | + |
| 69 | +#define HFCNTR_CFG 0x944 |
| 70 | +#define ITP_DELTA_CLK (0xa << 1) |
| 71 | +#define ITP_DELTA_CLK_MASK GENMASK(5, 1) |
| 72 | +#define FRMCNT_LEV1_RANG (0x12b << 8) |
| 73 | +#define FRMCNT_LEV1_RANG_MASK GENMASK(19, 8) |
| 74 | + |
| 75 | +#define SS_GEN2_EOF_CFG 0x990 |
| 76 | +#define SSG2EOF_OFFSET 0x3c |
| 77 | + |
| 78 | +#define XSEOF_OFFSET_MASK GENMASK(11, 0) |
| 79 | + |
59 | 80 | /* usb remote wakeup registers in syscon */
|
60 | 81 |
|
61 | 82 | /* mt8173 etc */
|
@@ -86,6 +107,46 @@ enum ssusb_uwk_vers {
|
86 | 107 | SSUSB_UWK_V1_2, /* specific revision 1.2 */
|
87 | 108 | };
|
88 | 109 |
|
| 110 | +/* |
| 111 | + * MT8195 has 4 controllers, the controller1~3's default SOF/ITP interval |
| 112 | + * is calculated from the frame counter clock 24M, but in fact, the clock |
| 113 | + * is 48M, add workaround for it. |
| 114 | + */ |
| 115 | +static void xhci_mtk_set_frame_interval(struct xhci_hcd_mtk *mtk) |
| 116 | +{ |
| 117 | + struct device *dev = mtk->dev; |
| 118 | + struct usb_hcd *hcd = mtk->hcd; |
| 119 | + u32 value; |
| 120 | + |
| 121 | + if (!of_device_is_compatible(dev->of_node, "mediatek,mt8195-xhci")) |
| 122 | + return; |
| 123 | + |
| 124 | + value = readl(hcd->regs + HFCNTR_CFG); |
| 125 | + value &= ~(ITP_DELTA_CLK_MASK | FRMCNT_LEV1_RANG_MASK); |
| 126 | + value |= (ITP_DELTA_CLK | FRMCNT_LEV1_RANG); |
| 127 | + writel(value, hcd->regs + HFCNTR_CFG); |
| 128 | + |
| 129 | + value = readl(hcd->regs + LS_EOF_CFG); |
| 130 | + value &= ~XSEOF_OFFSET_MASK; |
| 131 | + value |= LSEOF_OFFSET; |
| 132 | + writel(value, hcd->regs + LS_EOF_CFG); |
| 133 | + |
| 134 | + value = readl(hcd->regs + FS_EOF_CFG); |
| 135 | + value &= ~XSEOF_OFFSET_MASK; |
| 136 | + value |= FSEOF_OFFSET; |
| 137 | + writel(value, hcd->regs + FS_EOF_CFG); |
| 138 | + |
| 139 | + value = readl(hcd->regs + SS_GEN1_EOF_CFG); |
| 140 | + value &= ~XSEOF_OFFSET_MASK; |
| 141 | + value |= SSG1EOF_OFFSET; |
| 142 | + writel(value, hcd->regs + SS_GEN1_EOF_CFG); |
| 143 | + |
| 144 | + value = readl(hcd->regs + SS_GEN2_EOF_CFG); |
| 145 | + value &= ~XSEOF_OFFSET_MASK; |
| 146 | + value |= SSG2EOF_OFFSET; |
| 147 | + writel(value, hcd->regs + SS_GEN2_EOF_CFG); |
| 148 | +} |
| 149 | + |
89 | 150 | static int xhci_mtk_host_enable(struct xhci_hcd_mtk *mtk)
|
90 | 151 | {
|
91 | 152 | struct mu3c_ippc_regs __iomem *ippc = mtk->ippc_regs;
|
@@ -367,6 +428,9 @@ static int xhci_mtk_setup(struct usb_hcd *hcd)
|
367 | 428 | ret = xhci_mtk_ssusb_config(mtk);
|
368 | 429 | if (ret)
|
369 | 430 | return ret;
|
| 431 | + |
| 432 | + /* workaround only for mt8195 */ |
| 433 | + xhci_mtk_set_frame_interval(mtk); |
370 | 434 | }
|
371 | 435 |
|
372 | 436 | ret = xhci_gen_setup(hcd, xhci_mtk_quirks);
|
@@ -712,6 +776,7 @@ static const struct dev_pm_ops xhci_mtk_pm_ops = {
|
712 | 776 |
|
713 | 777 | static const struct of_device_id mtk_xhci_of_match[] = {
|
714 | 778 | { .compatible = "mediatek,mt8173-xhci"},
|
| 779 | + { .compatible = "mediatek,mt8195-xhci"}, |
715 | 780 | { .compatible = "mediatek,mtk-xhci"},
|
716 | 781 | { },
|
717 | 782 | };
|
|
0 commit comments