MT6589 USB Driver (v6.16)#23
Closed
akku1139 wants to merge 77 commits into
Closed
Conversation
Signed-off-by: Akari Tsuyukusa <akkun11.open@gmail.com>
Signed-off-by: Akari Tsuyukusa <akkun11.open@gmail.com>
Signed-off-by: Akari Tsuyukusa <akkun11.open@gmail.com>
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>
Member
Author
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>
Member
Author
|
otg is broken |
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>
Closed
Member
Author
|
do not merge into blade/6.16 |
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>
Draft
Member
Author
|
goto #62 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
#5