[][kernel][common][eth][net: phy: mediatek-ge: add mt7988 gphy support and fix calibration flow]
[Description]
Add mt7988 gphy support and fix calibration flow for bypass mode.
[Release-log]
N/A
Change-Id: Ibb4104b73e6e2f58d34692ae65de28a71fcc753e
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/6342053
diff --git a/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek-ge.c b/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek-ge.c
index d8f9d6a..f149444 100644
--- a/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek-ge.c
+++ b/target/linux/mediatek/files-5.4/drivers/net/phy/mediatek-ge.c
@@ -21,14 +21,21 @@
#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5
/* Registers on MDIO_MMD_VEND1 */
-#define MTK_PHY_1st_OVERSHOOT_LEVEL_0TO1 (0x1)
-#define MTK_PHY_2nd_OVERSHOOT_LEVEL_0TO1 (0x2)
-#define MTK_PHY_1st_OVERSHOOT_LEVEL_1TO0 (0x4)
-#define MTK_PHY_2nd_OVERSHOOT_LEVEL_1TO0 (0x5)
-#define MTK_PHY_1st_OVERSHOOT_LEVEL_0TON1 (0x7) /* N means negative */
-#define MTK_PHY_2nd_OVERSHOOT_LEVEL_0TON1 (0x8)
-#define MTK_PHY_1st_OVERSHOOT_LEVEL_N1TO0 (0xa)
-#define MTK_PHY_2nd_OVERSHOOT_LEVEL_N1TO0 (0xb)
+typedef enum {
+ MTK_PHY_MIDDLE_LEVEL_SHAPPER_0TO1 = 0,
+ MTK_PHY_1st_OVERSHOOT_LEVEL_0TO1,
+ MTK_PHY_2nd_OVERSHOOT_LEVEL_0TO1,
+ MTK_PHY_MIDDLE_LEVEL_SHAPPER_1TO0,
+ MTK_PHY_1st_OVERSHOOT_LEVEL_1TO0,
+ MTK_PHY_2nd_OVERSHOOT_LEVEL_1TO0,
+ MTK_PHY_MIDDLE_LEVEL_SHAPPER_0TON1, /* N means negative */
+ MTK_PHY_1st_OVERSHOOT_LEVEL_0TON1,
+ MTK_PHY_2nd_OVERSHOOT_LEVEL_0TON1,
+ MTK_PHY_MIDDLE_LEVEL_SHAPPER_N1TO0,
+ MTK_PHY_1st_OVERSHOOT_LEVEL_N1TO0,
+ MTK_PHY_2nd_OVERSHOOT_LEVEL_N1TO0,
+ MTK_PHY_TX_MLT3_END,
+};
#define MTK_PHY_TXVLD_DA_RG (0x12)
#define MTK_PHY_DA_TX_I2MPB_A_GBE_MASK GENMASK(15, 10)
@@ -795,7 +802,7 @@
return 0;
}
-static inline void mt798x_phy_finetune(struct phy_device *phydev)
+static inline void mt7981_phy_finetune(struct phy_device *phydev)
{
/* 100M eye finetune:
* Keep middle level of TX MLT3 shapper as default.
@@ -809,7 +816,7 @@
phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_2nd_OVERSHOOT_LEVEL_0TON1, 0x3c0);
phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_1st_OVERSHOOT_LEVEL_N1TO0, 0x13);
phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_2nd_OVERSHOOT_LEVEL_N1TO0, 0x5);
-#
+
/* TX-AMP finetune:
* 100M +4, 1000M +6 to default value.
* If efuse values aren't valid, TX-AMP uses the below values.
@@ -824,10 +831,23 @@
phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2, 0x2426);
}
+static inline void mt7988_phy_finetune(struct phy_device *phydev)
+{
+ int i;
+ u16 val[12] = {0x0187, 0x01cd, 0x01c8, 0x0182,
+ 0x020d, 0x0206, 0x0384, 0x03d0,
+ 0x03c6, 0x030a, 0x0011, 0x0005};
+
+ for(i=0; i<MTK_PHY_TX_MLT3_END; i++) {
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, i, val[i]);
+ }
+}
+
-static int mt798x_phy_config_init(struct phy_device *phydev)
+static int mt798x_phy_calibration(struct phy_device *phydev)
{
const char *cal_mode_from_dts;
- int i, ret, cal_ret;
+ int i, ret;
+ int cal_ret = 0;
u32 *buf;
bool efs_valid = true;
size_t len;
@@ -836,8 +856,6 @@
if (phydev->interface != PHY_INTERFACE_MODE_GMII)
return -EINVAL;
- mt798x_phy_finetune(phydev);
-
cell = nvmem_cell_get(&phydev->mdio.dev, "phy-cal-data");
if (IS_ERR(cell)) {
if (PTR_ERR(cell) == -EPROBE_DEFER)
@@ -871,6 +889,25 @@
return ret;
}
+static int mt7981_phy_config_init(struct phy_device *phydev)
+{
+ mt7981_phy_finetune(phydev);
+
+ return mt798x_phy_calibration(phydev);
+}
+
+static int mt7988_phy_config_init(struct phy_device *phydev)
+{
+ mt7988_phy_finetune(phydev);
+
+ return mt798x_phy_calibration(phydev);
+}
+
+static int mt7988_phy_probe(struct phy_device *phydev)
+{
+ return mt7988_phy_config_init(phydev);
+}
+
static struct phy_driver mtk_gephy_driver[] = {
#if 0
{
@@ -904,8 +941,23 @@
#endif
{
PHY_ID_MATCH_EXACT(0x03a29461),
- .name = "MediaTek MT798x PHY",
- .config_init = mt798x_phy_config_init,
+ .name = "MediaTek MT7981 PHY",
+ .config_init = mt7981_phy_config_init,
+ /* Interrupts are handled by the switch, not the PHY
+ * itself.
+ */
+ .config_intr = genphy_no_config_intr,
+ .handle_interrupt = genphy_no_ack_interrupt,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ .read_page = mtk_gephy_read_page,
+ .write_page = mtk_gephy_write_page,
+ },
+ {
+ PHY_ID_MATCH_EXACT(0x03a29481),
+ .name = "MediaTek MT7988 PHY",
+ .probe = mt7988_phy_probe,
+ .config_init = mt7988_phy_config_init,
/* Interrupts are handled by the switch, not the PHY
* itself.
*/