9e09e7ede342e5f9bbb21345beaa2cacb00562fe
[openwrt/staging/mkresin.git] / target / linux / generic / backport-5.10 / 771-v5.14-net-phy-add-MediaTek-Gigabit-Ethernet-PHY-driver.patch
1 From e40d2cca01893c1941f5959b14bb0cd0d4f4d099 Mon Sep 17 00:00:00 2001
2 From: DENG Qingfang <dqfext@gmail.com>
3 Date: Wed, 19 May 2021 11:31:59 +0800
4 Subject: [PATCH] net: phy: add MediaTek Gigabit Ethernet PHY driver
5
6 Add support for MediaTek Gigabit Ethernet PHYs found in MT7530 and
7 MT7531 switches.
8 The initialization procedure is from the vendor driver, but due to lack
9 of documentation, the function of some register values remains unknown.
10
11 Signed-off-by: DENG Qingfang <dqfext@gmail.com>
12 Signed-off-by: David S. Miller <davem@davemloft.net>
13 ---
14 drivers/net/phy/Kconfig | 5 ++
15 drivers/net/phy/Makefile | 1 +
16 drivers/net/phy/mediatek-ge.c | 116 ++++++++++++++++++++++++++++++++++
17 3 files changed, 122 insertions(+)
18 create mode 100644 drivers/net/phy/mediatek-ge.c
19
20 --- a/drivers/net/phy/Kconfig
21 +++ b/drivers/net/phy/Kconfig
22 @@ -201,6 +201,11 @@ config MARVELL_10G_PHY
23 help
24 Support for the Marvell Alaska MV88X3310 and compatible PHYs.
25
26 +config MEDIATEK_GE_PHY
27 + tristate "MediaTek PHYs"
28 + help
29 + Supports the MediaTek switch integrated PHYs.
30 +
31 config MICREL_PHY
32 tristate "Micrel PHYs"
33 help
34 --- a/drivers/net/phy/Makefile
35 +++ b/drivers/net/phy/Makefile
36 @@ -63,6 +63,7 @@ obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c
37 obj-$(CONFIG_LXT_PHY) += lxt.o
38 obj-$(CONFIG_MARVELL_10G_PHY) += marvell10g.o
39 obj-$(CONFIG_MARVELL_PHY) += marvell.o
40 +obj-$(CONFIG_MEDIATEK_GE_PHY) += mediatek-ge.o
41 obj-$(CONFIG_MESON_GXL_PHY) += meson-gxl.o
42 obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o
43 obj-$(CONFIG_MICREL_PHY) += micrel.o
44 --- /dev/null
45 +++ b/drivers/net/phy/mediatek-ge.c
46 @@ -0,0 +1,116 @@
47 +// SPDX-License-Identifier: GPL-2.0+
48 +#include <linux/bitfield.h>
49 +#include <linux/module.h>
50 +#include <linux/phy.h>
51 +
52 +#define MTK_T10_TEST_CONTROL 0x145
53 +#define MTK_PHY_TP_MASK GENMASK(4, 3)
54 +#define MTK_PHY_TP_AUTO 0
55 +#define MTK_PHY_TP_MDI 2
56 +#define MTK_PHY_TP_MDIX 3
57 +
58 +#define MTK_EXT_PAGE_ACCESS 0x1f
59 +#define MTK_PHY_PAGE_STANDARD 0x0000
60 +#define MTK_PHY_PAGE_EXTENDED 0x0001
61 +#define MTK_PHY_PAGE_EXTENDED_2 0x0002
62 +#define MTK_PHY_PAGE_EXTENDED_3 0x0003
63 +#define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30
64 +#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5
65 +
66 +static int mtk_gephy_read_page(struct phy_device *phydev)
67 +{
68 + return __phy_read(phydev, MTK_EXT_PAGE_ACCESS);
69 +}
70 +
71 +static int mtk_gephy_write_page(struct phy_device *phydev, int page)
72 +{
73 + return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page);
74 +}
75 +
76 +static void mtk_gephy_config_init(struct phy_device *phydev)
77 +{
78 + /* Disable EEE */
79 + phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0);
80 +
81 + /* Enable HW auto downshift */
82 + phy_modify_paged(phydev, MTK_PHY_PAGE_EXTENDED, 0x14, 0, BIT(4));
83 +
84 + /* Increase SlvDPSready time */
85 + phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
86 + __phy_write(phydev, 0x10, 0xafae);
87 + __phy_write(phydev, 0x12, 0x2f);
88 + __phy_write(phydev, 0x10, 0x8fae);
89 + phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
90 +
91 + /* Adjust 100_mse_threshold */
92 + phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x123, 0xffff);
93 +
94 + /* Disable mcc */
95 + phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xa6, 0x300);
96 +}
97 +
98 +static int mt7530_phy_config_init(struct phy_device *phydev)
99 +{
100 + mtk_gephy_config_init(phydev);
101 +
102 + /* Increase post_update_timer */
103 + phy_write_paged(phydev, MTK_PHY_PAGE_EXTENDED_3, 0x11, 0x4b);
104 +
105 + return 0;
106 +}
107 +
108 +static int mt7531_phy_config_init(struct phy_device *phydev)
109 +{
110 + if (phydev->interface != PHY_INTERFACE_MODE_INTERNAL)
111 + return -EINVAL;
112 +
113 + mtk_gephy_config_init(phydev);
114 +
115 + /* PHY link down power saving enable */
116 + phy_set_bits(phydev, 0x17, BIT(4));
117 + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 0xc6, 0x300);
118 +
119 + /* Set TX Pair delay selection */
120 + phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x13, 0x404);
121 + phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x14, 0x404);
122 +
123 + return 0;
124 +}
125 +
126 +static struct phy_driver mtk_gephy_driver[] = {
127 + {
128 + PHY_ID_MATCH_EXACT(0x03a29412),
129 + .name = "MediaTek MT7530 PHY",
130 + .config_init = mt7530_phy_config_init,
131 + /* Interrupts are handled by the switch, not the PHY
132 + * itself.
133 + */
134 + .config_intr = genphy_no_config_intr,
135 + .ack_interrupt = genphy_no_ack_interrupt,
136 + .suspend = genphy_suspend,
137 + .resume = genphy_resume,
138 + .read_page = mtk_gephy_read_page,
139 + .write_page = mtk_gephy_write_page,
140 + },
141 + {
142 + PHY_ID_MATCH_EXACT(0x03a29441),
143 + .name = "MediaTek MT7531 PHY",
144 + .config_init = mt7531_phy_config_init,
145 + /* Interrupts are handled by the switch, not the PHY
146 + * itself.
147 + */
148 + .config_intr = genphy_no_config_intr,
149 + .ack_interrupt = genphy_no_ack_interrupt,
150 + .suspend = genphy_suspend,
151 + .resume = genphy_resume,
152 + .read_page = mtk_gephy_read_page,
153 + .write_page = mtk_gephy_write_page,
154 + },
155 +};
156 +
157 +module_phy_driver(mtk_gephy_driver);
158 +
159 +static struct mdio_device_id __maybe_unused mtk_gephy_tbl[] = {
160 + { PHY_ID_MATCH_VENDOR(0x03a29400) },
161 + { }
162 +};