Skip to content

MT6589 USB Driver (v6.16)#23

Closed
akku1139 wants to merge 77 commits into
blade/v6.16from
dev/v6.16/mt6589-usb
Closed

MT6589 USB Driver (v6.16)#23
akku1139 wants to merge 77 commits into
blade/v6.16from
dev/v6.16/mt6589-usb

Conversation

@akku1139

Copy link
Copy Markdown
Member

#5

@akku1139 akku1139 marked this pull request as draft February 26, 2026 09:50
@akku1139

Copy link
Copy Markdown
Member Author

full patch

diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c
index 644a34bd2b0b..8c384792f3e0 100644
--- a/drivers/phy/mediatek/phy-mtk-tphy.c
+++ b/drivers/phy/mediatek/phy-mtk-tphy.c
@@ -72,8 +72,15 @@
 #define PA6_RG_U2_OTG_VBUSCMP_EN	BIT(20)
 #define PA6_RG_U2_DISCTH		GENMASK(7, 4)
 #define PA6_RG_U2_SQTH		GENMASK(3, 0)
+/* MT6785 */
+#define PA6_RG_U2_PHY_REV6		GENMASK(31, 30)
+
+#define U3P_USBPHYACR3		0x01c
+#define PA3_RG_USB20_PUPD_BIST_EN	BIT(12)
 
 #define U3P_U2PHYACR4		0x020
+#define P2C_RG_USB20_DM_100K_EN		BIT(17)
+#define P2C_RG_USB20_DP_100K_EN		BIT(16)
 #define P2C_RG_USB20_GPIO_CTL		BIT(9)
 #define P2C_USB20_GPIO_MODE		BIT(8)
 #define P2C_U2_GPIO_CTR_MSK	(P2C_RG_USB20_GPIO_CTL | P2C_USB20_GPIO_MODE)
@@ -111,9 +118,15 @@
 
 #define U3P_U2PHYDTM1		0x06C
 #define P2C_RG_UART_EN			BIT(16)
+#define P2C_FORCE_VBUSVALID		BIT(13)
+#define P2C_FORCE_SESSEND		BIT(12)
+#define P2C_FORCE_BVALID		BIT(11)
+#define P2C_FORCE_AVALID		BIT(10)
 #define P2C_FORCE_IDDIG		BIT(9)
+#define P2C_FORCE_IDPULLUP		BIT(8)
 #define P2C_RG_VBUSVALID		BIT(5)
 #define P2C_RG_SESSEND			BIT(4)
+#define P2C_RG_BVALID		BIT(3)
 #define P2C_RG_AVALID			BIT(2)
 #define P2C_RG_IDDIG			BIT(1)
 
@@ -291,6 +304,14 @@ struct mtk_phy_pdata {
 	 * support sw way, also support it for v2/v3 optionally.
 	 */
 	bool sw_efuse_supported;
+	bool disable_dpdm_100k;		/* disable DP/DM 100k pull-down */
+	bool use_sif2_fm;		/* FM block is located in sif2 region */
+	u8 phy_rev6_val; /* 0: don't touch, 1-3: value to write to bits 31:30 of U3P_USBPHYACR6 */
+	u8 sqth_val;			/* RG_USB20_SQTH override (0 = default 2) */
+	u32 pupd_bist_reg;		/* offset from com base for PUPD_BIST */
+	u32 pupd_bist_bit;		/* bit mask to clear */
+	u32 device_force_mask;		/* Force bits for device mode */
+	u32 host_force_mask;		/* Force bits for host mode */
 	enum mtk_phy_version version;
 };
 
@@ -336,7 +357,9 @@ struct mtk_phy_instance {
 
 struct mtk_tphy {
 	struct device *dev;
-	void __iomem *sif_base;	/* only shared sif */
+	void __iomem *sif_base; /* only shared sif (V1) */
+	void __iomem *sif2_base; /* second shared sif (e.g., MT6757) */
+	void __iomem *legacy_fm_base; /* legacy FM block (e.g., MT6589) */
 	const struct mtk_phy_pdata *pdata;
 	struct mtk_phy_instance **phys;
 	int nphys;
@@ -694,6 +717,10 @@ static void hs_slew_rate_calibrate(struct mtk_tphy *tphy,
 	if (instance->eye_src)
 		return;
 
+	/* legacy FM block base */
+	if (tphy->legacy_fm_base)
+		fmreg = tphy->legacy_fm_base;
+
 	/* enable USB ring oscillator */
 	mtk_phy_set_bits(com + U3P_USBPHYACR5, PA5_RG_U2_HSTX_SRCAL_EN);
 	udelay(1);
@@ -852,7 +879,32 @@ static void u2_phy_instance_init(struct mtk_tphy *tphy,
 	/* DP/DM BC1.1 path Disable */
 	mtk_phy_clear_bits(com + U3P_USBPHYACR6, PA6_RG_U2_BC11_SW_EN);
 
-	mtk_phy_update_field(com + U3P_USBPHYACR6, PA6_RG_U2_SQTH, 2);
+	/* Disable DP/DM 100K resistors */
+	if (tphy->pdata->disable_dpdm_100k) {
+		mtk_phy_clear_bits(com + U3P_U2PHYACR4,
+				   P2C_RG_USB20_DP_100K_EN |
+				   P2C_RG_USB20_DM_100K_EN);
+	}
+
+	/* PUPD_BIST_EN clear */
+	if (tphy->pdata->pupd_bist_bit) {
+		void __iomem *bist_reg = com + tphy->pdata->pupd_bist_reg;
+		mtk_phy_clear_bits(bist_reg, tphy->pdata->pupd_bist_bit);
+	}
+
+	/* SQTH override */
+	if (tphy->pdata->sqth_val) {
+		mtk_phy_update_field(com + U3P_USBPHYACR6, PA6_RG_U2_SQTH,
+				     tphy->pdata->sqth_val);
+	} else {
+		mtk_phy_update_field(com + U3P_USBPHYACR6, PA6_RG_U2_SQTH, 2);
+	}
+
+	/* PHY rev6 for some newer SoCs */
+	if (tphy->pdata->phy_rev6_val) {
+		mtk_phy_update_field(com + U3P_USBPHYACR6, PA6_RG_U2_PHY_REV6,
+				     tphy->pdata->phy_rev6_val);
+	}
 
 	/* Workaround only for mt8195, HW fix it for others (V3) */
 	u2_phy_pll_26m_set(tphy, instance);
@@ -879,6 +931,24 @@ static void u2_phy_instance_power_on(struct mtk_tphy *tphy,
 
 		mtk_phy_set_bits(com + U3P_U2PHYDTM0, P2C_RG_SUSPENDM | P2C_FORCE_SUSPENDM);
 	}
+
+	/* Force device mode bits during power on */
+	if (tphy->pdata->device_force_mask) {
+		u32 tmp = readl(com + U3P_U2PHYDTM1);
+		tmp |= tphy->pdata->device_force_mask;
+		if (tphy->pdata->device_force_mask & P2C_FORCE_VBUSVALID)
+			tmp |= P2C_RG_VBUSVALID;
+		if (tphy->pdata->device_force_mask & P2C_FORCE_AVALID)
+			tmp |= P2C_RG_AVALID;
+		if (tphy->pdata->device_force_mask & P2C_FORCE_BVALID)
+			tmp |= P2C_RG_BVALID;
+		if (tphy->pdata->device_force_mask & P2C_FORCE_SESSEND)
+			tmp |= P2C_RG_SESSEND;
+		if (tphy->pdata->device_force_mask & P2C_FORCE_IDDIG)
+			tmp |= P2C_RG_IDDIG;
+		writel(tmp, com + U3P_U2PHYDTM1);
+	}
+
 	dev_dbg(tphy->dev, "%s(%d)\n", __func__, index);
 }
 
@@ -902,6 +972,18 @@ static void u2_phy_instance_power_off(struct mtk_tphy *tphy,
 		mtk_phy_clear_bits(com + U3D_U2PHYDCR0, P2C_RG_SIF_U2PLL_FORCE_ON);
 	}
 
+	/* Clear all force bits */
+	if (tphy->pdata->device_force_mask || tphy->pdata->host_force_mask) {
+		u32 tmp = readl(com + U3P_U2PHYDTM1);
+		tmp &= ~(P2C_FORCE_VBUSVALID | P2C_FORCE_AVALID |
+			 P2C_FORCE_BVALID | P2C_FORCE_SESSEND |
+			 P2C_FORCE_IDDIG | P2C_FORCE_IDPULLUP);
+		/* Also clear corresponding normal bits */
+		tmp &= ~(P2C_RG_VBUSVALID | P2C_RG_AVALID | P2C_RG_BVALID |
+			 P2C_RG_SESSEND | P2C_RG_IDDIG);
+		writel(tmp, com + U3P_U2PHYDTM1);
+	}
+
 	dev_dbg(tphy->dev, "%s(%d)\n", __func__, index);
 }
 
@@ -941,6 +1023,35 @@ static void u2_phy_instance_set_mode(struct mtk_tphy *tphy,
 	default:
 		return;
 	}
+
+	/* Apply dynamic force bits for host/device mode */
+	if (tphy->pdata->device_force_mask || tphy->pdata->host_force_mask) {
+		u32 force = 0;
+
+		switch (mode) {
+		case PHY_MODE_USB_DEVICE:
+			force = tphy->pdata->device_force_mask;
+			break;
+		case PHY_MODE_USB_HOST:
+			force = tphy->pdata->host_force_mask;
+			break;
+		default:
+			break;
+		}
+
+		/* update only force-related bits in tmp */
+		tmp &= ~(P2C_FORCE_VBUSVALID | P2C_FORCE_AVALID |
+			 P2C_FORCE_BVALID | P2C_FORCE_SESSEND |
+			 P2C_FORCE_IDDIG | P2C_FORCE_IDPULLUP);
+		tmp |= force;
+
+		/* also set the corresponding normal bits */
+		if (force & P2C_FORCE_VBUSVALID) tmp |= P2C_RG_VBUSVALID;
+		if (force & P2C_FORCE_AVALID)    tmp |= P2C_RG_AVALID;
+		if (force & P2C_FORCE_BVALID)    tmp |= P2C_RG_BVALID;
+		if (force & P2C_FORCE_SESSEND)   tmp |= P2C_RG_SESSEND;
+		if (force & P2C_FORCE_IDDIG)     tmp |= P2C_RG_IDDIG;
+	}
 	writel(tmp, u2_banks->com + U3P_U2PHYDTM1);
 }
 
@@ -1101,7 +1212,10 @@ static void phy_v2_banks_init(struct mtk_tphy *tphy,
 	switch (instance->type) {
 	case PHY_TYPE_USB2:
 		u2_banks->misc = instance->port_base + SSUSB_SIFSLV_V2_MISC;
-		u2_banks->fmreg = instance->port_base + SSUSB_SIFSLV_V2_U2FREQ;
+		if (tphy->pdata->use_sif2_fm && tphy->sif2_base)
+			u2_banks->fmreg = tphy->sif2_base + SSUSB_SIFSLV_V2_U2FREQ;
+		else
+			u2_banks->fmreg = instance->port_base + SSUSB_SIFSLV_V2_U2FREQ;
 		u2_banks->com = instance->port_base + SSUSB_SIFSLV_V2_U2PHY_COM;
 		break;
 	case PHY_TYPE_USB3:
@@ -1530,6 +1644,61 @@ static const struct mtk_phy_pdata tphy_v3_pdata = {
 	.version = MTK_PHY_V3,
 };
 
+static const struct mtk_phy_pdata mt6589_pdata = {
+	.version = MTK_PHY_V1,
+	.pupd_bist_reg = U3P_USBPHYACR3,
+	.pupd_bist_bit = PA3_RG_USB20_PUPD_BIST_EN,
+	.device_force_mask = P2C_FORCE_VBUSVALID | P2C_FORCE_AVALID |
+			     P2C_FORCE_SESSEND,
+	.host_force_mask = P2C_FORCE_IDDIG,
+	.disable_dpdm_100k = true,
+	.sqth_val = 2,
+};
+
+static const struct mtk_phy_pdata mt6582_pdata = {
+	.version = MTK_PHY_V1,
+	.pupd_bist_reg = U3P_USBPHYACR3,
+	.pupd_bist_bit = PA3_RG_USB20_PUPD_BIST_EN,
+	.device_force_mask = P2C_FORCE_VBUSVALID | P2C_FORCE_AVALID |
+			     P2C_FORCE_SESSEND,
+	.host_force_mask = P2C_FORCE_IDDIG,
+	.disable_dpdm_100k = true,
+	.sqth_val = 2,
+};
+
+static const struct mtk_phy_pdata mt6757_pdata = {
+	.version = MTK_PHY_V2,
+	.device_force_mask = P2C_FORCE_VBUSVALID | P2C_FORCE_AVALID |
+			     P2C_FORCE_SESSEND,
+	.disable_dpdm_100k = true,
+	.sqth_val = 5,
+	.use_sif2_fm = true,
+};
+
+static const struct mtk_phy_pdata mt6785_pdata = {
+	.version = MTK_PHY_V2,
+	.device_force_mask = P2C_FORCE_VBUSVALID | P2C_FORCE_AVALID |
+			     P2C_FORCE_SESSEND,
+	.phy_rev6_val = 1,
+};
+
+static const struct mtk_phy_pdata mt6853_pdata = {
+	.version = MTK_PHY_V2,
+	.device_force_mask = P2C_FORCE_VBUSVALID | P2C_FORCE_AVALID |
+			     P2C_FORCE_SESSEND,
+};
+
+static const struct mtk_phy_pdata mt8135_pdata = {
+	.version = MTK_PHY_V1,
+	.pupd_bist_reg = U3P_USBPHYACR3,
+	.pupd_bist_bit = PA3_RG_USB20_PUPD_BIST_EN,
+	.device_force_mask = P2C_FORCE_VBUSVALID | P2C_FORCE_AVALID |
+			     P2C_FORCE_SESSEND,
+	.host_force_mask = P2C_FORCE_IDDIG,
+	.disable_dpdm_100k = true,
+	.sqth_val = 2,
+};
+
 static const struct mtk_phy_pdata mt8173_pdata = {
 	.avoid_rx_sen_degradation = true,
 	.version = MTK_PHY_V1,
@@ -1541,11 +1710,31 @@ static const struct mtk_phy_pdata mt8195_pdata = {
 	.version = MTK_PHY_V3,
 };
 
+static const struct mtk_phy_pdata mt8518_pdata = {
+	.version = MTK_PHY_V1,
+	.pupd_bist_reg = U3P_USBPHYACR3,
+	.pupd_bist_bit = PA3_RG_USB20_PUPD_BIST_EN,
+	.device_force_mask = P2C_FORCE_VBUSVALID | P2C_FORCE_AVALID |
+			     P2C_FORCE_SESSEND,
+	.host_force_mask = P2C_FORCE_IDDIG,
+	.disable_dpdm_100k = true,
+	.sqth_val = 2,
+};
+
 static const struct of_device_id mtk_tphy_id_table[] = {
 	{ .compatible = "mediatek,mt2701-u3phy", .data = &tphy_v1_pdata },
 	{ .compatible = "mediatek,mt2712-u3phy", .data = &tphy_v2_pdata },
+	{ .compatible = "mediatek,mt6589-tphy", .data = &mt6589_pdata },
+	{ .compatible = "mediatek,mt6582-tphy", .data = &mt6582_pdata },
+	{ .compatible = "mediatek,mt6757-tphy", .data = &mt6757_pdata },
+	{ .compatible = "mediatek,mt6785-tphy", .data = &mt6785_pdata }, /* additional tuning via DT */
+	{ .compatible = "mediatek,mt6853-tphy", .data = &mt6853_pdata },
+	{ .compatible = "mediatek,mt6873-tphy", .data = &mt6853_pdata },
+	{ .compatible = "mediatek,mt6877-tphy", .data = &mt6853_pdata }, /* SQTH=5 set via DT */
+	{ .compatible = "mediatek,mt8135-tphy", .data = &mt8135_pdata },
 	{ .compatible = "mediatek,mt8173-u3phy", .data = &mt8173_pdata },
 	{ .compatible = "mediatek,mt8195-tphy", .data = &mt8195_pdata },
+	{ .compatible = "mediatek,mt8518-tphy", .data = &mt8518_pdata },
 	{ .compatible = "mediatek,generic-tphy-v1", .data = &tphy_v1_pdata },
 	{ .compatible = "mediatek,generic-tphy-v2", .data = &tphy_v2_pdata },
 	{ .compatible = "mediatek,generic-tphy-v3", .data = &tphy_v3_pdata },
@@ -1591,6 +1780,21 @@ static int mtk_tphy_probe(struct platform_device *pdev)
 		}
 	}
 
+	/* "sif2" is optional, only for SoCs that need it (e.g., MT6757) */
+	struct resource *sif2_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sif2");
+	if (sif2_res) {
+		tphy->sif2_base = devm_ioremap_resource(dev, sif2_res);
+		if (IS_ERR(tphy->sif2_base))
+			return PTR_ERR(tphy->sif2_base);
+	}
+
+	struct resource *fm_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "legacy-fm");
+	if (fm_res) {
+		tphy->legacy_fm_base = devm_ioremap_resource(dev, fm_res);
+		if (IS_ERR(tphy->legacy_fm_base))
+			return PTR_ERR(tphy->legacy_fm_base);
+	}
+
 	if (tphy->pdata->version < MTK_PHY_V3) {
 		tphy->src_ref_clk = U3P_REF_CLK;
 		tphy->src_coef = U3P_SLEW_RATE_COEF;

Assisted-by: DeepSeek:deepseek-v4-pro
Signed-off-by: Akari Tsuyukusa <akkun11.open@gmail.com>
@akku1139

Copy link
Copy Markdown
Member Author

akku1139 added 4 commits June 26, 2026 00:44
Signed-off-by: Akari Tsuyukusa <akkun11.open@gmail.com>
Assisted-by: Gemini:gemini-3.5-flash
Signed-off-by: Akari Tsuyukusa <akkun11.open@gmail.com>
Assisted-by: DeepSeek:deepseek-v4-pro
Signed-off-by: Akari Tsuyukusa <akkun11.open@gmail.com>
Add support for the MediaTek MT6589 smartphone SoC in the T-PHY
driver.  This SoC requires additional PHY initialization that is
present in downstream kernels but missing from the mainline
generic-tphy-v1 implementation.

MT6589 relies on an external PMIC for VBUS detection and charger
type detection.  The PMIC temporarily enables PUPD_BIST mode during
charger detection, which must be explicitly cleared afterwards to
allow normal USB operation.  Additionally, VBUS and session
signals are not fully routed in hardware, so software must force
AVALID, VBUSVALID and SESSEND states for stable operation.

The frequency meter block for slew rate calibration is at a
non-standard offset.  A separate "legacy-fm" reg entry maps it.

Introduce struct mtk_phy_pdata fields to control these workarounds:
disable_pupd_bist, disable_dpdm_100k, sqth_val, device_force_mask,
and host_force_mask.  All new fields default to 0/false so existing
platforms are unaffected.

Assisted-by: Claude:claude-sonnet-4-6
Assisted-by: DeepSeek:deepseek-v4-pro
Signed-off-by: Akari Tsuyukusa <akkun11.open@gmail.com>
@akku1139

Copy link
Copy Markdown
Member Author

otg is broken

akku1139 added 4 commits June 26, 2026 13:59
Assisted-by: DeepSeek:deepseek-v4-pro
Signed-off-by: Akari Tsuyukusa <akkun11.open@gmail.com>
Assisted-by: DeepSeek:deepseek-v4-pro
Signed-off-by: Akari Tsuyukusa <akkun11.open@gmail.com>
Assisted-by: Google AI Mode:gemini-3.x-flash
Signed-off-by: Akari Tsuyukusa <akkun11.open@gmail.com>
@akku1139 akku1139 mentioned this pull request Jun 28, 2026
@akku1139 akku1139 changed the base branch from blade/v6.16 to blade/v7.1 July 3, 2026 18:21
@akku1139 akku1139 changed the base branch from blade/v7.1 to blade/v6.16 July 3, 2026 18:26
@akku1139

akku1139 commented Jul 3, 2026

Copy link
Copy Markdown
Member Author

do not merge into blade/6.16

@akku1139 akku1139 changed the title MT6589 USB Driver MT6589 USB Driver (v6.16) Jul 4, 2026
akku1139 added a commit that referenced this pull request Jul 4, 2026
for Linux 7.1 dev

Link: #23
Signed-off-by: Akari Tsuyukusa <akkun11.open@gmail.com>
@akku1139 akku1139 mentioned this pull request Jul 4, 2026
@akku1139

akku1139 commented Jul 4, 2026

Copy link
Copy Markdown
Member Author

goto #62

@akku1139 akku1139 closed this Jul 4, 2026
@akku1139 akku1139 deleted the dev/v6.16/mt6589-usb branch July 4, 2026 08:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants