diff options
-rw-r--r-- | doc/device-tree-bindings/phy/phy-mtk-tphy.txt | 1 | ||||
-rw-r--r-- | doc/device-tree-bindings/usb/mediatek,mtk-xhci.txt | 4 | ||||
-rw-r--r-- | drivers/phy/phy-mtk-tphy.c | 213 | ||||
-rw-r--r-- | drivers/usb/dwc3/Kconfig | 4 | ||||
-rw-r--r-- | drivers/usb/host/xhci-mtk.c | 49 |
5 files changed, 182 insertions, 89 deletions
diff --git a/doc/device-tree-bindings/phy/phy-mtk-tphy.txt b/doc/device-tree-bindings/phy/phy-mtk-tphy.txt index 8cd23d8..3042c39 100644 --- a/doc/device-tree-bindings/phy/phy-mtk-tphy.txt +++ b/doc/device-tree-bindings/phy/phy-mtk-tphy.txt @@ -8,6 +8,7 @@ Required properties (controller (parent) node): - compatible : should be one of "mediatek,generic-tphy-v1" "mediatek,generic-tphy-v2" + "mediatek,mt8195-tphy" - #address-cells: the number of cells used to represent physical base addresses. diff --git a/doc/device-tree-bindings/usb/mediatek,mtk-xhci.txt b/doc/device-tree-bindings/usb/mediatek,mtk-xhci.txt index 2a298f7..e26e961 100644 --- a/doc/device-tree-bindings/usb/mediatek,mtk-xhci.txt +++ b/doc/device-tree-bindings/usb/mediatek,mtk-xhci.txt @@ -3,7 +3,9 @@ MediaTek xHCI The device node for USB3 host controller on MediaTek SoCs. Required properties: - - compatible : should be "mediatek,mtk-xhci" + - compatible : should be one of + "mediatek,mtk-xhci" + "mediatek,mt8195-xhci" - reg : specifies physical base address and size of the registers - reg-names: should be "mac" for xHCI MAC and "ippc" for IP port control - power-domains : a phandle to USB power domain node to control USB's diff --git a/drivers/phy/phy-mtk-tphy.c b/drivers/phy/phy-mtk-tphy.c index 2dd964f..1883f9f 100644 --- a/drivers/phy/phy-mtk-tphy.c +++ b/drivers/phy/phy-mtk-tphy.c @@ -14,6 +14,7 @@ #include <asm/io.h> #include <dm/device_compat.h> #include <dm/devres.h> +#include <linux/bitfield.h> #include <linux/bitops.h> #include <linux/delay.h> @@ -43,19 +44,21 @@ #define U3P_USBPHYACR0 0x000 #define PA0_RG_U2PLL_FORCE_ON BIT(15) +#define PA0_USB20_PLL_PREDIV GENMASK(7, 6) #define PA0_RG_USB20_INTR_EN BIT(5) +#define U3P_USBPHYACR2 0x008 +#define PA2_RG_U2PLL_BW GENMASK(21, 19) + #define U3P_USBPHYACR5 0x014 #define PA5_RG_U2_HSTX_SRCAL_EN BIT(15) #define PA5_RG_U2_HSTX_SRCTRL GENMASK(14, 12) -#define PA5_RG_U2_HSTX_SRCTRL_VAL(x) ((0x7 & (x)) << 12) #define PA5_RG_U2_HS_100U_U3_EN BIT(11) #define U3P_USBPHYACR6 0x018 #define PA6_RG_U2_BC11_SW_EN BIT(23) #define PA6_RG_U2_OTG_VBUSCMP_EN BIT(20) #define PA6_RG_U2_SQTH GENMASK(3, 0) -#define PA6_RG_U2_SQTH_VAL(x) (0xf & (x)) #define U3P_U2PHYACR4 0x020 #define P2C_RG_USB20_GPIO_CTL BIT(9) @@ -63,6 +66,14 @@ #define P2C_U2_GPIO_CTR_MSK \ (P2C_RG_USB20_GPIO_CTL | P2C_USB20_GPIO_MODE) +#define U3P_U2PHYA_RESV 0x030 +#define P2R_RG_U2PLL_FBDIV_26M 0x1bb13b +#define P2R_RG_U2PLL_FBDIV_48M 0x3c0000 + +#define U3P_U2PHYA_RESV1 0x044 +#define P2R_RG_U2PLL_REFCLK_SEL BIT(5) +#define P2R_RG_U2PLL_FRA_EN BIT(3) + #define U3P_U2PHYDTM0 0x068 #define P2C_FORCE_UART_EN BIT(26) #define P2C_FORCE_DATAIN BIT(23) @@ -72,11 +83,9 @@ #define P2C_FORCE_SUSPENDM BIT(18) #define P2C_FORCE_TERMSEL BIT(17) #define P2C_RG_DATAIN GENMASK(13, 10) -#define P2C_RG_DATAIN_VAL(x) ((0xf & (x)) << 10) #define P2C_RG_DMPULLDOWN BIT(7) #define P2C_RG_DPPULLDOWN BIT(6) #define P2C_RG_XCVRSEL GENMASK(5, 4) -#define P2C_RG_XCVRSEL_VAL(x) ((0x3 & (x)) << 4) #define P2C_RG_SUSPENDM BIT(3) #define P2C_RG_TERMSEL BIT(2) #define P2C_DTM0_PART_MASK \ @@ -104,72 +113,53 @@ #define U3P_U3_PHYA_REG0 0x000 #define P3A_RG_CLKDRV_OFF GENMASK(3, 2) -#define P3A_RG_CLKDRV_OFF_VAL(x) ((0x3 & (x)) << 2) #define U3P_U3_PHYA_REG1 0x004 #define P3A_RG_CLKDRV_AMP GENMASK(31, 29) -#define P3A_RG_CLKDRV_AMP_VAL(x) ((0x7 & (x)) << 29) #define U3P_U3_PHYA_REG6 0x018 #define P3A_RG_TX_EIDLE_CM GENMASK(31, 28) -#define P3A_RG_TX_EIDLE_CM_VAL(x) ((0xf & (x)) << 28) #define U3P_U3_PHYA_REG9 0x024 #define P3A_RG_RX_DAC_MUX GENMASK(5, 1) -#define P3A_RG_RX_DAC_MUX_VAL(x) ((0x1f & (x)) << 1) #define U3P_U3_PHYA_DA_REG0 0x100 #define P3A_RG_XTAL_EXT_PE2H GENMASK(17, 16) -#define P3A_RG_XTAL_EXT_PE2H_VAL(x) ((0x3 & (x)) << 16) #define P3A_RG_XTAL_EXT_PE1H GENMASK(13, 12) -#define P3A_RG_XTAL_EXT_PE1H_VAL(x) ((0x3 & (x)) << 12) #define P3A_RG_XTAL_EXT_EN_U3 GENMASK(11, 10) -#define P3A_RG_XTAL_EXT_EN_U3_VAL(x) ((0x3 & (x)) << 10) #define U3P_U3_PHYA_DA_REG4 0x108 #define P3A_RG_PLL_DIVEN_PE2H GENMASK(21, 19) #define P3A_RG_PLL_BC_PE2H GENMASK(7, 6) -#define P3A_RG_PLL_BC_PE2H_VAL(x) ((0x3 & (x)) << 6) #define U3P_U3_PHYA_DA_REG5 0x10c #define P3A_RG_PLL_BR_PE2H GENMASK(29, 28) -#define P3A_RG_PLL_BR_PE2H_VAL(x) ((0x3 & (x)) << 28) #define P3A_RG_PLL_IC_PE2H GENMASK(15, 12) -#define P3A_RG_PLL_IC_PE2H_VAL(x) ((0xf & (x)) << 12) #define U3P_U3_PHYA_DA_REG6 0x110 #define P3A_RG_PLL_IR_PE2H GENMASK(19, 16) -#define P3A_RG_PLL_IR_PE2H_VAL(x) ((0xf & (x)) << 16) #define U3P_U3_PHYA_DA_REG7 0x114 #define P3A_RG_PLL_BP_PE2H GENMASK(19, 16) -#define P3A_RG_PLL_BP_PE2H_VAL(x) ((0xf & (x)) << 16) #define U3P_U3_PHYA_DA_REG20 0x13c #define P3A_RG_PLL_DELTA1_PE2H GENMASK(31, 16) -#define P3A_RG_PLL_DELTA1_PE2H_VAL(x) ((0xffff & (x)) << 16) #define U3P_U3_PHYA_DA_REG25 0x148 #define P3A_RG_PLL_DELTA_PE2H GENMASK(15, 0) -#define P3A_RG_PLL_DELTA_PE2H_VAL(x) (0xffff & (x)) #define U3P_U3_PHYD_LFPS1 0x00c #define P3D_RG_FWAKE_TH GENMASK(21, 16) -#define P3D_RG_FWAKE_TH_VAL(x) ((0x3f & (x)) << 16) #define U3P_U3_PHYD_CDR1 0x05c #define P3D_RG_CDR_BIR_LTD1 GENMASK(28, 24) -#define P3D_RG_CDR_BIR_LTD1_VAL(x) ((0x1f & (x)) << 24) #define P3D_RG_CDR_BIR_LTD0 GENMASK(12, 8) -#define P3D_RG_CDR_BIR_LTD0_VAL(x) ((0x1f & (x)) << 8) #define U3P_U3_PHYD_RXDET1 0x128 #define P3D_RG_RXDET_STB2_SET GENMASK(17, 9) -#define P3D_RG_RXDET_STB2_SET_VAL(x) ((0x1ff & (x)) << 9) #define U3P_U3_PHYD_RXDET2 0x12c #define P3D_RG_RXDET_STB2_SET_P3 GENMASK(8, 0) -#define P3D_RG_RXDET_STB2_SET_P3_VAL(x) (0x1ff & (x)) #define U3P_SPLLC_XTALCTL3 0x018 #define XC3_RG_U3_XTAL_RX_PWD BIT(9) @@ -179,66 +169,62 @@ #define PHYD_CTRL_SIGNAL_MODE4 0x1c /* CDR Charge Pump P-path current adjustment */ #define RG_CDR_BICLTD1_GEN1_MSK GENMASK(23, 20) -#define RG_CDR_BICLTD1_GEN1_VAL(x) ((0xf & (x)) << 20) #define RG_CDR_BICLTD0_GEN1_MSK GENMASK(11, 8) -#define RG_CDR_BICLTD0_GEN1_VAL(x) ((0xf & (x)) << 8) #define PHYD_DESIGN_OPTION2 0x24 /* Symbol lock count selection */ #define RG_LOCK_CNT_SEL_MSK GENMASK(5, 4) -#define RG_LOCK_CNT_SEL_VAL(x) ((0x3 & (x)) << 4) #define PHYD_DESIGN_OPTION9 0x40 /* COMWAK GAP width window */ #define RG_TG_MAX_MSK GENMASK(20, 16) -#define RG_TG_MAX_VAL(x) ((0x1f & (x)) << 16) /* COMINIT GAP width window */ #define RG_T2_MAX_MSK GENMASK(13, 8) -#define RG_T2_MAX_VAL(x) ((0x3f & (x)) << 8) /* COMWAK GAP width window */ #define RG_TG_MIN_MSK GENMASK(7, 5) -#define RG_TG_MIN_VAL(x) ((0x7 & (x)) << 5) /* COMINIT GAP width window */ #define RG_T2_MIN_MSK GENMASK(4, 0) -#define RG_T2_MIN_VAL(x) (0x1f & (x)) #define ANA_RG_CTRL_SIGNAL1 0x4c /* TX driver tail current control for 0dB de-empahsis mdoe for Gen1 speed */ #define RG_IDRV_0DB_GEN1_MSK GENMASK(13, 8) -#define RG_IDRV_0DB_GEN1_VAL(x) ((0x3f & (x)) << 8) #define ANA_RG_CTRL_SIGNAL4 0x58 #define RG_CDR_BICLTR_GEN1_MSK GENMASK(23, 20) -#define RG_CDR_BICLTR_GEN1_VAL(x) ((0xf & (x)) << 20) /* Loop filter R1 resistance adjustment for Gen1 speed */ #define RG_CDR_BR_GEN2_MSK GENMASK(10, 8) -#define RG_CDR_BR_GEN2_VAL(x) ((0x7 & (x)) << 8) #define ANA_RG_CTRL_SIGNAL6 0x60 /* I-path capacitance adjustment for Gen1 */ #define RG_CDR_BC_GEN1_MSK GENMASK(28, 24) -#define RG_CDR_BC_GEN1_VAL(x) ((0x1f & (x)) << 24) #define RG_CDR_BIRLTR_GEN1_MSK GENMASK(4, 0) -#define RG_CDR_BIRLTR_GEN1_VAL(x) (0x1f & (x)) #define ANA_EQ_EYE_CTRL_SIGNAL1 0x6c /* RX Gen1 LEQ tuning step */ #define RG_EQ_DLEQ_LFI_GEN1_MSK GENMASK(11, 8) -#define RG_EQ_DLEQ_LFI_GEN1_VAL(x) ((0xf & (x)) << 8) #define ANA_EQ_EYE_CTRL_SIGNAL4 0xd8 #define RG_CDR_BIRLTD0_GEN1_MSK GENMASK(20, 16) -#define RG_CDR_BIRLTD0_GEN1_VAL(x) ((0x1f & (x)) << 16) #define ANA_EQ_EYE_CTRL_SIGNAL5 0xdc #define RG_CDR_BIRLTD0_GEN3_MSK GENMASK(4, 0) -#define RG_CDR_BIRLTD0_GEN3_VAL(x) (0x1f & (x)) enum mtk_phy_version { MTK_TPHY_V1 = 1, MTK_TPHY_V2, }; +struct tphy_pdata { + enum mtk_phy_version version; + + /* + * workaround only for mt8195: + * u2phy should use integer mode instead of fractional mode of + * 48M PLL, fix it by switching PLL to 26M from default 48M + */ + bool sw_pll_48m_to_26m; +}; + struct u2phy_banks { void __iomem *misc; void __iomem *fmreg; @@ -269,11 +255,32 @@ struct mtk_phy_instance { struct mtk_tphy { struct udevice *dev; void __iomem *sif_base; - enum mtk_phy_version version; + const struct tphy_pdata *pdata; struct mtk_phy_instance **phys; int nphys; }; +/* workaround only for mt8195 */ +static void u2_phy_pll_26m_set(struct mtk_tphy *tphy, + struct mtk_phy_instance *instance) +{ + struct u2phy_banks *u2_banks = &instance->u2_banks; + + if (!tphy->pdata->sw_pll_48m_to_26m) + return; + + clrsetbits_le32(u2_banks->com + U3P_USBPHYACR0, PA0_USB20_PLL_PREDIV, + FIELD_PREP(PA0_USB20_PLL_PREDIV, 0)); + + clrsetbits_le32(u2_banks->com + U3P_USBPHYACR2, PA2_RG_U2PLL_BW, + FIELD_PREP(PA2_RG_U2PLL_BW, 3)); + + writel(P2R_RG_U2PLL_FBDIV_26M, u2_banks->com + U3P_U2PHYA_RESV); + + setbits_le32(u2_banks->com + U3P_U2PHYA_RESV1, + P2R_RG_U2PLL_FRA_EN | P2R_RG_U2PLL_REFCLK_SEL); +} + static void u2_phy_instance_init(struct mtk_tphy *tphy, struct mtk_phy_instance *instance) { @@ -282,7 +289,8 @@ static void u2_phy_instance_init(struct mtk_tphy *tphy, /* switch to USB function, and enable usb pll */ clrsetbits_le32(u2_banks->com + U3P_U2PHYDTM0, P2C_FORCE_UART_EN | P2C_FORCE_SUSPENDM, - P2C_RG_XCVRSEL_VAL(1) | P2C_RG_DATAIN_VAL(0)); + FIELD_PREP(P2C_RG_XCVRSEL, 1) | + FIELD_PREP(P2C_RG_DATAIN, 0)); clrbits_le32(u2_banks->com + U3P_U2PHYDTM1, P2C_RG_UART_EN); setbits_le32(u2_banks->com + U3P_USBPHYACR0, PA0_RG_USB20_INTR_EN); @@ -295,11 +303,14 @@ static void u2_phy_instance_init(struct mtk_tphy *tphy, /* DP/DM BC1.1 path Disable */ clrsetbits_le32(u2_banks->com + U3P_USBPHYACR6, PA6_RG_U2_BC11_SW_EN | PA6_RG_U2_SQTH, - PA6_RG_U2_SQTH_VAL(2)); + FIELD_PREP(PA6_RG_U2_SQTH, 2)); /* set HS slew rate */ clrsetbits_le32(u2_banks->com + U3P_USBPHYACR5, - PA5_RG_U2_HSTX_SRCTRL, PA5_RG_U2_HSTX_SRCTRL_VAL(4)); + PA5_RG_U2_HSTX_SRCTRL, + FIELD_PREP(PA5_RG_U2_HSTX_SRCTRL, 4)); + + u2_phy_pll_26m_set(tphy, instance); dev_dbg(tphy->dev, "%s(%d)\n", __func__, instance->index); } @@ -351,28 +362,31 @@ static void u3_phy_instance_init(struct mtk_tphy *tphy, /* gating XSQ */ clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_DA_REG0, - P3A_RG_XTAL_EXT_EN_U3, P3A_RG_XTAL_EXT_EN_U3_VAL(2)); + P3A_RG_XTAL_EXT_EN_U3, + FIELD_PREP(P3A_RG_XTAL_EXT_EN_U3, 2)); clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_REG9, - P3A_RG_RX_DAC_MUX, P3A_RG_RX_DAC_MUX_VAL(4)); + P3A_RG_RX_DAC_MUX, FIELD_PREP(P3A_RG_RX_DAC_MUX, 4)); clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_REG6, - P3A_RG_TX_EIDLE_CM, P3A_RG_TX_EIDLE_CM_VAL(0xe)); + P3A_RG_TX_EIDLE_CM, + FIELD_PREP(P3A_RG_TX_EIDLE_CM, 0xe)); clrsetbits_le32(u3_banks->phyd + U3P_U3_PHYD_CDR1, P3D_RG_CDR_BIR_LTD0 | P3D_RG_CDR_BIR_LTD1, - P3D_RG_CDR_BIR_LTD0_VAL(0xc) | - P3D_RG_CDR_BIR_LTD1_VAL(0x3)); + FIELD_PREP(P3D_RG_CDR_BIR_LTD0, 0xc) | + FIELD_PREP(P3D_RG_CDR_BIR_LTD1, 0x3)); clrsetbits_le32(u3_banks->phyd + U3P_U3_PHYD_LFPS1, - P3D_RG_FWAKE_TH, P3D_RG_FWAKE_TH_VAL(0x34)); + P3D_RG_FWAKE_TH, FIELD_PREP(P3D_RG_FWAKE_TH, 0x34)); clrsetbits_le32(u3_banks->phyd + U3P_U3_PHYD_RXDET1, - P3D_RG_RXDET_STB2_SET, P3D_RG_RXDET_STB2_SET_VAL(0x10)); + P3D_RG_RXDET_STB2_SET, + FIELD_PREP(P3D_RG_RXDET_STB2_SET, 0x10)); clrsetbits_le32(u3_banks->phyd + U3P_U3_PHYD_RXDET2, P3D_RG_RXDET_STB2_SET_P3, - P3D_RG_RXDET_STB2_SET_P3_VAL(0x10)); + FIELD_PREP(P3D_RG_RXDET_STB2_SET_P3, 0x10)); dev_dbg(tphy->dev, "%s(%d)\n", __func__, instance->index); } @@ -382,50 +396,52 @@ static void pcie_phy_instance_init(struct mtk_tphy *tphy, { struct u3phy_banks *u3_banks = &instance->u3_banks; - if (tphy->version != MTK_TPHY_V1) + if (tphy->pdata->version != MTK_TPHY_V1) return; clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_DA_REG0, P3A_RG_XTAL_EXT_PE1H | P3A_RG_XTAL_EXT_PE2H, - P3A_RG_XTAL_EXT_PE1H_VAL(0x2) | - P3A_RG_XTAL_EXT_PE2H_VAL(0x2)); + FIELD_PREP(P3A_RG_XTAL_EXT_PE1H, 0x2) | + FIELD_PREP(P3A_RG_XTAL_EXT_PE2H, 0x2)); /* ref clk drive */ clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_REG1, P3A_RG_CLKDRV_AMP, - P3A_RG_CLKDRV_AMP_VAL(0x4)); + FIELD_PREP(P3A_RG_CLKDRV_AMP, 0x4)); clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_REG0, P3A_RG_CLKDRV_OFF, - P3A_RG_CLKDRV_OFF_VAL(0x1)); + FIELD_PREP(P3A_RG_CLKDRV_OFF, 0x1)); /* SSC delta -5000ppm */ clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_DA_REG20, P3A_RG_PLL_DELTA1_PE2H, - P3A_RG_PLL_DELTA1_PE2H_VAL(0x3c)); + FIELD_PREP(P3A_RG_PLL_DELTA1_PE2H, 0x3c)); clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_DA_REG25, P3A_RG_PLL_DELTA_PE2H, - P3A_RG_PLL_DELTA_PE2H_VAL(0x36)); + FIELD_PREP(P3A_RG_PLL_DELTA_PE2H, 0x36)); /* change pll BW 0.6M */ clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_DA_REG5, P3A_RG_PLL_BR_PE2H | P3A_RG_PLL_IC_PE2H, - P3A_RG_PLL_BR_PE2H_VAL(0x1) | - P3A_RG_PLL_IC_PE2H_VAL(0x1)); + FIELD_PREP(P3A_RG_PLL_BR_PE2H, 0x1) | + FIELD_PREP(P3A_RG_PLL_IC_PE2H, 0x1)); clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_DA_REG4, P3A_RG_PLL_DIVEN_PE2H | P3A_RG_PLL_BC_PE2H, - P3A_RG_PLL_BC_PE2H_VAL(0x3)); + FIELD_PREP(P3A_RG_PLL_BC_PE2H, 0x3)); clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_DA_REG6, - P3A_RG_PLL_IR_PE2H, P3A_RG_PLL_IR_PE2H_VAL(0x2)); + P3A_RG_PLL_IR_PE2H, + FIELD_PREP(P3A_RG_PLL_IR_PE2H, 0x2)); clrsetbits_le32(u3_banks->phya + U3P_U3_PHYA_DA_REG7, - P3A_RG_PLL_BP_PE2H, P3A_RG_PLL_BP_PE2H_VAL(0xa)); + P3A_RG_PLL_BP_PE2H, + FIELD_PREP(P3A_RG_PLL_BP_PE2H, 0xa)); /* Tx Detect Rx Timing: 10us -> 5us */ clrsetbits_le32(u3_banks->phyd + U3P_U3_PHYD_RXDET1, P3D_RG_RXDET_STB2_SET, - P3D_RG_RXDET_STB2_SET_VAL(0x10)); + FIELD_PREP(P3D_RG_RXDET_STB2_SET, 0x10)); clrsetbits_le32(u3_banks->phyd + U3P_U3_PHYD_RXDET2, P3D_RG_RXDET_STB2_SET_P3, - P3D_RG_RXDET_STB2_SET_P3_VAL(0x10)); + FIELD_PREP(P3D_RG_RXDET_STB2_SET_P3, 0x10)); /* wait for PCIe subsys register to active */ udelay(3000); @@ -438,36 +454,38 @@ static void sata_phy_instance_init(struct mtk_tphy *tphy, clrsetbits_le32(u3_banks->phyd + ANA_RG_CTRL_SIGNAL6, RG_CDR_BIRLTR_GEN1_MSK | RG_CDR_BC_GEN1_MSK, - RG_CDR_BIRLTR_GEN1_VAL(0x6) | - RG_CDR_BC_GEN1_VAL(0x1a)); + FIELD_PREP(RG_CDR_BIRLTR_GEN1_MSK, 0x6) | + FIELD_PREP(RG_CDR_BC_GEN1_MSK, 0x1a)); clrsetbits_le32(u3_banks->phyd + ANA_EQ_EYE_CTRL_SIGNAL4, RG_CDR_BIRLTD0_GEN1_MSK, - RG_CDR_BIRLTD0_GEN1_VAL(0x18)); + FIELD_PREP(RG_CDR_BIRLTD0_GEN1_MSK, 0x18)); clrsetbits_le32(u3_banks->phyd + ANA_EQ_EYE_CTRL_SIGNAL5, RG_CDR_BIRLTD0_GEN3_MSK, - RG_CDR_BIRLTD0_GEN3_VAL(0x06)); + FIELD_PREP(RG_CDR_BIRLTD0_GEN3_MSK, 0x06)); clrsetbits_le32(u3_banks->phyd + ANA_RG_CTRL_SIGNAL4, RG_CDR_BICLTR_GEN1_MSK | RG_CDR_BR_GEN2_MSK, - RG_CDR_BICLTR_GEN1_VAL(0x0c) | - RG_CDR_BR_GEN2_VAL(0x07)); + FIELD_PREP(RG_CDR_BICLTR_GEN1_MSK, 0x0c) | + FIELD_PREP(RG_CDR_BR_GEN2_MSK, 0x07)); clrsetbits_le32(u3_banks->phyd + PHYD_CTRL_SIGNAL_MODE4, RG_CDR_BICLTD0_GEN1_MSK | RG_CDR_BICLTD1_GEN1_MSK, - RG_CDR_BICLTD0_GEN1_VAL(0x08) | - RG_CDR_BICLTD1_GEN1_VAL(0x02)); + FIELD_PREP(RG_CDR_BICLTD0_GEN1_MSK, 0x08) | + FIELD_PREP(RG_CDR_BICLTD1_GEN1_MSK, 0x02)); clrsetbits_le32(u3_banks->phyd + PHYD_DESIGN_OPTION2, RG_LOCK_CNT_SEL_MSK, - RG_LOCK_CNT_SEL_VAL(0x02)); + FIELD_PREP(RG_LOCK_CNT_SEL_MSK, 0x02)); clrsetbits_le32(u3_banks->phyd + PHYD_DESIGN_OPTION9, RG_T2_MIN_MSK | RG_TG_MIN_MSK | RG_T2_MAX_MSK | RG_TG_MAX_MSK, - RG_T2_MIN_VAL(0x12) | RG_TG_MIN_VAL(0x04) | - RG_T2_MAX_VAL(0x31) | RG_TG_MAX_VAL(0x0e)); + FIELD_PREP(RG_T2_MIN_MSK, 0x12) | + FIELD_PREP(RG_TG_MIN_MSK, 0x04) | + FIELD_PREP(RG_T2_MAX_MSK, 0x31) | + FIELD_PREP(RG_TG_MAX_MSK, 0x0e)); clrsetbits_le32(u3_banks->phyd + ANA_RG_CTRL_SIGNAL1, RG_IDRV_0DB_GEN1_MSK, - RG_IDRV_0DB_GEN1_VAL(0x20)); + FIELD_PREP(RG_IDRV_0DB_GEN1_MSK, 0x20)); clrsetbits_le32(u3_banks->phyd + ANA_EQ_EYE_CTRL_SIGNAL1, RG_EQ_DLEQ_LFI_GEN1_MSK, - RG_EQ_DLEQ_LFI_GEN1_VAL(0x03)); + FIELD_PREP(RG_EQ_DLEQ_LFI_GEN1_MSK, 0x03)); } static void pcie_phy_instance_power_on(struct mtk_tphy *tphy, @@ -662,11 +680,14 @@ static int mtk_phy_xlate(struct phy *phy, return -EINVAL; } - if (tphy->version == MTK_TPHY_V1) { + switch (tphy->pdata->version) { + case MTK_TPHY_V1: phy_v1_banks_init(tphy, instance); - } else if (tphy->version == MTK_TPHY_V2) { + break; + case MTK_TPHY_V2: phy_v2_banks_init(tphy, instance); - } else { + break; + default: dev_err(phy->dev, "phy version is not supported\n"); return -EINVAL; } @@ -696,13 +717,12 @@ static int mtk_tphy_probe(struct udevice *dev) return -ENOMEM; tphy->dev = dev; - tphy->version = dev_get_driver_data(dev); + tphy->pdata = (void *)dev_get_driver_data(dev); /* v1 has shared banks for usb/pcie mode, */ /* but not for sata mode */ - if (tphy->version == MTK_TPHY_V1) { + if (tphy->pdata->version == MTK_TPHY_V1) tphy->sif_base = dev_read_addr_ptr(dev); - } dev_for_each_subnode(subnode, dev) { struct mtk_phy_instance *instance; @@ -737,9 +757,32 @@ static int mtk_tphy_probe(struct udevice *dev) return 0; } +static struct tphy_pdata tphy_v1_pdata = { + .version = MTK_TPHY_V1, +}; + +static struct tphy_pdata tphy_v2_pdata = { + .version = MTK_TPHY_V2, +}; + +static struct tphy_pdata mt8195_pdata = { + .version = MTK_TPHY_V2, + .sw_pll_48m_to_26m = true, +}; + static const struct udevice_id mtk_tphy_id_table[] = { - { .compatible = "mediatek,generic-tphy-v1", .data = MTK_TPHY_V1, }, - { .compatible = "mediatek,generic-tphy-v2", .data = MTK_TPHY_V2, }, + { + .compatible = "mediatek,generic-tphy-v1", + .data = (ulong)&tphy_v1_pdata, + }, + { + .compatible = "mediatek,generic-tphy-v2", + .data = (ulong)&tphy_v2_pdata, + }, + { + .compatible = "mediatek,mt8195-tphy", + .data = (ulong)&mt8195_pdata, + }, { } }; diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index d1665f8..c0c8c16 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -40,7 +40,7 @@ config SPL_USB_DWC3_GENERIC config USB_DWC3_MESON_G12A bool "Amlogic Meson G12A USB wrapper" depends on DM_USB && USB_DWC3 && ARCH_MESON - imply PHY + select PHY help Select this for Amlogic Meson G12A Platforms. This wrapper supports Host and Peripheral operation modes. @@ -48,7 +48,7 @@ config USB_DWC3_MESON_G12A config USB_DWC3_MESON_GXL bool "Amlogic Meson GXL USB wrapper" depends on DM_USB && USB_DWC3 && ARCH_MESON - imply PHY + select PHY help Select this for Amlogic Meson GXL and GXM Platforms. This wrapper supports Host and Peripheral operation modes. diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c index 3838a99..63dfb79 100644 --- a/drivers/usb/host/xhci-mtk.c +++ b/drivers/usb/host/xhci-mtk.c @@ -14,8 +14,9 @@ #include <power/regulator.h> #include <usb.h> #include <usb/xhci.h> -#include <linux/errno.h> +#include <linux/bitfield.h> #include <linux/compat.h> +#include <linux/errno.h> #include <linux/iopoll.h> /* IPPC (IP Port Control) registers */ @@ -50,6 +51,25 @@ #define IPPC_U3_CTRL(p) (IPPC_U3_CTRL_0P + ((p) * 0x08)) #define IPPC_U2_CTRL(p) (IPPC_U2_CTRL_0P + ((p) * 0x08)) +/* xHCI CSR */ +#define LS_EOF_CFG 0x930 +#define LSEOF_OFFSET 0x89 + +#define FS_EOF_CFG 0x934 +#define FSEOF_OFFSET 0x2e + +#define SS_GEN1_EOF_CFG 0x93c +#define SSG1EOF_OFFSET 0x78 + +#define HFCNTR_CFG 0x944 +#define ITP_DELTA_CLK_MASK GENMASK(5, 1) +#define FRMCNT_LEV1_RANG_MASK GENMASK(19, 8) + +#define SS_GEN2_EOF_CFG 0x990 +#define SSG2EOF_OFFSET 0x3c + +#define XSEOF_OFFSET_MASK GENMASK(11, 0) + struct mtk_xhci { struct xhci_ctrl ctrl; /* Needs to come first in this struct! */ struct xhci_hccr *hcd; @@ -65,6 +85,30 @@ struct mtk_xhci { u32 u2p_dis_msk; }; +/* + * workaround for mt8195: + * 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. + */ +static void xhci_mtk_set_frame_interval(struct mtk_xhci *mtk) +{ + void __iomem *mac = (void __iomem *)mtk->hcd; + + if (!ofnode_device_is_compatible(dev_ofnode(mtk->dev), "mediatek,mt8195-xhci")) + return; + + clrsetbits_le32(mac + HFCNTR_CFG, + ITP_DELTA_CLK_MASK | FRMCNT_LEV1_RANG_MASK, + FIELD_PREP(ITP_DELTA_CLK_MASK, 0xa) | + FIELD_PREP(FRMCNT_LEV1_RANG_MASK, 0x12b)); + + clrsetbits_le32(mac + LS_EOF_CFG, XSEOF_OFFSET_MASK, LSEOF_OFFSET); + clrsetbits_le32(mac + FS_EOF_CFG, XSEOF_OFFSET_MASK, FSEOF_OFFSET); + clrsetbits_le32(mac + SS_GEN1_EOF_CFG, XSEOF_OFFSET_MASK, SSG1EOF_OFFSET); + clrsetbits_le32(mac + SS_GEN2_EOF_CFG, XSEOF_OFFSET_MASK, SSG2EOF_OFFSET); +} + static int xhci_mtk_host_enable(struct mtk_xhci *mtk) { int u3_ports_disabed = 0; @@ -278,6 +322,8 @@ static int xhci_mtk_probe(struct udevice *dev) if (ret) goto ssusb_init_err; + xhci_mtk_set_frame_interval(mtk); + mtk->ctrl.quirks = XHCI_MTK_HOST; hcor = (struct xhci_hcor *)((uintptr_t)mtk->hcd + HC_LENGTH(xhci_readl(&mtk->hcd->cr_capbase))); @@ -308,6 +354,7 @@ static int xhci_mtk_remove(struct udevice *dev) static const struct udevice_id xhci_mtk_ids[] = { { .compatible = "mediatek,mtk-xhci" }, + { .compatible = "mediatek,mt8195-xhci" }, { } }; |