blob: 6a1c9e02069e30fef0206af0bec9b4a49a8eac19 [file] [log] [blame]
developer2cdaeb12022-10-04 20:25:05 +08001// SPDX-License-Identifier: GPL-2.0+
2#include <linux/bitfield.h>
3#include <linux/firmware.h>
4#include <linux/module.h>
5#include <linux/nvmem-consumer.h>
6#include <linux/of_address.h>
7#include <linux/of_platform.h>
developeraec59ea2023-04-10 16:58:03 +08008#include <linux/pinctrl/consumer.h>
developer2cdaeb12022-10-04 20:25:05 +08009#include <linux/phy.h>
10
11#define MEDAITEK_2P5GE_PHY_DMB_FW "mediatek-2p5ge-phy-dmb.bin"
12#define MEDIATEK_2P5GE_PHY_PMB_FW "mediatek-2p5ge-phy-pmb.bin"
13
14#define MD32_EN_CFG 0x18
15#define MD32_EN BIT(0)
16
developer284cd6e2022-12-15 22:19:39 +080017#define BASE100T_STATUS_EXTEND (0x10)
18#define BASE1000T_STATUS_EXTEND (0x11)
19#define EXTEND_CTRL_AND_STATUS (0x16)
20
developere7f61612022-12-30 11:34:52 +080021#define PHY_AUX_CTRL_STATUS (0x1d)
22#define PHY_AUX_DPX_MASK GENMASK(5, 5)
23#define PHY_AUX_SPEED_MASK GENMASK(4, 2)
24
developer5c0c0622023-04-12 11:51:08 +080025/* Registers on MDIO_MMD_VEND1 */
26#define MTK_PHY_LINK_STATUS_MISC (0xa2)
27#define MTK_PHY_FDX_ENABLE BIT(5)
28
developer2ac05d72023-09-25 11:41:17 +080029#define MTK_PHY_LPI_PCS_DSP_CTRL (0x121)
30#define MTK_PHY_LPI_SIG_EN_LO_THRESH100_MASK GENMASK(12, 8)
31
developeraec59ea2023-04-10 16:58:03 +080032/* Registers on MDIO_MMD_VEND2 */
33#define MTK_PHY_LED0_ON_CTRL (0x24)
developer813ffc42023-05-17 13:39:48 +080034#define MTK_PHY_LED0_ON_LINK1000 BIT(0)
35#define MTK_PHY_LED0_ON_LINK100 BIT(1)
36#define MTK_PHY_LED0_ON_LINK10 BIT(2)
37#define MTK_PHY_LED0_ON_LINK2500 BIT(7)
developeraec59ea2023-04-10 16:58:03 +080038#define MTK_PHY_LED0_POLARITY BIT(14)
39
developer813ffc42023-05-17 13:39:48 +080040#define MTK_PHY_LED1_ON_CTRL (0x26)
41#define MTK_PHY_LED1_ON_FDX BIT(4)
42#define MTK_PHY_LED1_ON_HDX BIT(5)
43#define MTK_PHY_LED1_POLARITY BIT(14)
44
developere7f61612022-12-30 11:34:52 +080045enum {
46 PHY_AUX_SPD_10 = 0,
47 PHY_AUX_SPD_100,
48 PHY_AUX_SPD_1000,
49 PHY_AUX_SPD_2500,
50};
51
developer2cdaeb12022-10-04 20:25:05 +080052static int mt798x_2p5ge_phy_config_init(struct phy_device *phydev)
53{
54 int ret;
55 int i;
56 const struct firmware *fw;
57 struct device *dev = &phydev->mdio.dev;
58 struct device_node *np;
59 void __iomem *dmb_addr;
60 void __iomem *pmb_addr;
61 void __iomem *mcucsr_base;
62 u16 reg;
developer813ffc42023-05-17 13:39:48 +080063 struct pinctrl *pinctrl;
64
developer2cdaeb12022-10-04 20:25:05 +080065
66 np = of_find_compatible_node(NULL, NULL, "mediatek,2p5gphy-fw");
67 if (!np)
68 return -ENOENT;
69
70 dmb_addr = of_iomap(np, 0);
71 if (!dmb_addr)
72 return -ENOMEM;
73 pmb_addr = of_iomap(np, 1);
74 if (!pmb_addr)
75 return -ENOMEM;
76 mcucsr_base = of_iomap(np, 2);
77 if (!mcucsr_base)
78 return -ENOMEM;
79
80 ret = request_firmware(&fw, MEDAITEK_2P5GE_PHY_DMB_FW, dev);
81 if (ret) {
82 dev_err(dev, "failed to load firmware: %s, ret: %d\n",
83 MEDAITEK_2P5GE_PHY_DMB_FW, ret);
84 return ret;
85 }
86 for (i = 0; i < fw->size - 1; i += 4)
87 writel(*((uint32_t *)(fw->data + i)), dmb_addr + i);
88 release_firmware(fw);
89
90 ret = request_firmware(&fw, MEDIATEK_2P5GE_PHY_PMB_FW, dev);
91 if (ret) {
92 dev_err(dev, "failed to load firmware: %s, ret: %d\n",
93 MEDIATEK_2P5GE_PHY_PMB_FW, ret);
94 return ret;
95 }
96 for (i = 0; i < fw->size - 1; i += 4)
97 writel(*((uint32_t *)(fw->data + i)), pmb_addr + i);
98 release_firmware(fw);
99
100 reg = readw(mcucsr_base + MD32_EN_CFG);
101 writew(reg | MD32_EN, mcucsr_base + MD32_EN_CFG);
102 dev_info(dev, "Firmware loading/trigger ok.\n");
103
developer2ac05d72023-09-25 11:41:17 +0800104 phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LPI_PCS_DSP_CTRL,
105 MTK_PHY_LPI_SIG_EN_LO_THRESH100_MASK, 0);
106
developer813ffc42023-05-17 13:39:48 +0800107 /* Setup LED */
108 phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL,
109 MTK_PHY_LED0_POLARITY | MTK_PHY_LED0_ON_LINK10 |
110 MTK_PHY_LED0_ON_LINK100 | MTK_PHY_LED0_ON_LINK1000 |
111 MTK_PHY_LED0_ON_LINK2500);
112 phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED1_ON_CTRL,
113 MTK_PHY_LED1_ON_FDX | MTK_PHY_LED1_ON_HDX);
114
115 pinctrl = devm_pinctrl_get_select(&phydev->mdio.dev, "i2p5gbe-led");
116 if (IS_ERR(pinctrl)) {
117 dev_err(&phydev->mdio.dev, "Fail to set LED pins!\n");
118 return PTR_ERR(pinctrl);
119 }
120
developer2cdaeb12022-10-04 20:25:05 +0800121 return 0;
122}
123
developer1302b252022-12-30 19:04:55 +0800124static int mt798x_2p5ge_phy_config_aneg(struct phy_device *phydev)
125{
126 bool changed = false;
127 u32 adv;
128 int ret;
129
130 if (phydev->autoneg == AUTONEG_DISABLE) {
131 /* Configure half duplex with genphy_setup_forced,
132 * because genphy_c45_pma_setup_forced does not support.
133 */
134 return phydev->duplex != DUPLEX_FULL
135 ? genphy_setup_forced(phydev)
136 : genphy_c45_pma_setup_forced(phydev);
137 }
138
139 ret = genphy_c45_an_config_aneg(phydev);
140 if (ret < 0)
141 return ret;
142 if (ret > 0)
143 changed = true;
144
145 adv = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising);
146 ret = phy_modify_changed(phydev, MII_CTRL1000,
147 ADVERTISE_1000FULL | ADVERTISE_1000HALF,
148 adv);
149 if (ret < 0)
150 return ret;
151 if (ret > 0)
152 changed = true;
153
154 return genphy_c45_check_and_restart_aneg(phydev, changed);
155}
156
developer2cdaeb12022-10-04 20:25:05 +0800157static int mt798x_2p5ge_phy_get_features(struct phy_device *phydev)
158{
159 int ret;
160
161 ret = genphy_read_abilities(phydev);
162 if (ret)
163 return ret;
164
developerd4abc8c2022-10-28 10:45:36 +0800165 /* We don't support HDX at MAC layer on mt798x.
166 * So mask phy's HDX capabilities, too.
167 */
168 linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
developer2cdaeb12022-10-04 20:25:05 +0800169 phydev->supported);
170 linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
171 phydev->supported);
172 linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
173 phydev->supported);
174 linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
175 phydev->supported);
176 linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported);
177
178 return 0;
179}
180
developer284cd6e2022-12-15 22:19:39 +0800181static int mt798x_2p5ge_phy_read_status(struct phy_device *phydev)
182{
183 int ret;
developer284cd6e2022-12-15 22:19:39 +0800184
developere7f61612022-12-30 11:34:52 +0800185 ret = genphy_update_link(phydev);
186 if (ret)
187 return ret;
developer284cd6e2022-12-15 22:19:39 +0800188
developere7f61612022-12-30 11:34:52 +0800189 phydev->speed = SPEED_UNKNOWN;
190 phydev->duplex = DUPLEX_UNKNOWN;
191 phydev->pause = 0;
192 phydev->asym_pause = 0;
developer284cd6e2022-12-15 22:19:39 +0800193
developere7f61612022-12-30 11:34:52 +0800194 if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) {
195 ret = genphy_c45_read_lpa(phydev);
196 if (ret < 0)
197 return ret;
198
199 /* Read the link partner's 1G advertisement */
200 ret = phy_read(phydev, MII_STAT1000);
201 if (ret < 0)
202 return ret;
203 mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, ret);
204 } else if (phydev->autoneg == AUTONEG_DISABLE) {
205 linkmode_zero(phydev->lp_advertising);
developer284cd6e2022-12-15 22:19:39 +0800206 }
207
developere7f61612022-12-30 11:34:52 +0800208 ret = phy_read(phydev, PHY_AUX_CTRL_STATUS);
209 if (ret < 0)
210 return ret;
211
developere7f61612022-12-30 11:34:52 +0800212 switch (FIELD_GET(PHY_AUX_SPEED_MASK, ret)) {
213 case PHY_AUX_SPD_10:
developer284cd6e2022-12-15 22:19:39 +0800214 phydev->speed = SPEED_10;
developere7f61612022-12-30 11:34:52 +0800215 break;
216 case PHY_AUX_SPD_100:
217 phydev->speed = SPEED_100;
218 break;
219 case PHY_AUX_SPD_1000:
220 phydev->speed = SPEED_1000;
221 break;
222 case PHY_AUX_SPD_2500:
223 phydev->speed = SPEED_2500;
developere7f61612022-12-30 11:34:52 +0800224 break;
developer284cd6e2022-12-15 22:19:39 +0800225 }
226
developer5c0c0622023-04-12 11:51:08 +0800227 ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LINK_STATUS_MISC);
228 if (ret < 0)
229 return ret;
230 phydev->duplex = (ret & MTK_PHY_FDX_ENABLE) ? DUPLEX_FULL : DUPLEX_HALF;
developerd5969672023-06-07 10:35:00 +0800231 /* FIXME: The current firmware always enables rate adaptation mode. */
232 phydev->rate_matching = RATE_MATCH_PAUSE;
developer5c0c0622023-04-12 11:51:08 +0800233
developere7f61612022-12-30 11:34:52 +0800234 return 0;
developer284cd6e2022-12-15 22:19:39 +0800235}
236
developerd5969672023-06-07 10:35:00 +0800237static int mt798x_2p5ge_phy_get_rate_matching(struct phy_device *phydev,
238 phy_interface_t iface)
239{
240 if (iface == PHY_INTERFACE_MODE_XGMII)
241 return RATE_MATCH_PAUSE;
242 return RATE_MATCH_NONE;
243}
244
developer2cdaeb12022-10-04 20:25:05 +0800245static struct phy_driver mtk_gephy_driver[] = {
246 {
247 PHY_ID_MATCH_EXACT(0x00339c11),
248 .name = "MediaTek MT798x 2.5GbE PHY",
249 .config_init = mt798x_2p5ge_phy_config_init,
developer1302b252022-12-30 19:04:55 +0800250 .config_aneg = mt798x_2p5ge_phy_config_aneg,
developer2cdaeb12022-10-04 20:25:05 +0800251 .get_features = mt798x_2p5ge_phy_get_features,
developer284cd6e2022-12-15 22:19:39 +0800252 .read_status = mt798x_2p5ge_phy_read_status,
developerd5969672023-06-07 10:35:00 +0800253 .get_rate_matching = mt798x_2p5ge_phy_get_rate_matching,
developer2cdaeb12022-10-04 20:25:05 +0800254 //.config_intr = genphy_no_config_intr,
255 //.handle_interrupt = genphy_no_ack_interrupt,
developer6080c642023-10-27 18:09:35 +0800256 .suspend = genphy_suspend,
257 .resume = genphy_resume,
developer2cdaeb12022-10-04 20:25:05 +0800258 },
259};
260
261module_phy_driver(mtk_gephy_driver);
262
263static struct mdio_device_id __maybe_unused mtk_2p5ge_phy_tbl[] = {
264 { PHY_ID_MATCH_VENDOR(0x00339c00) },
265 { }
266};
267
268MODULE_DESCRIPTION("MediaTek 2.5Gb Ethernet PHY driver");
269MODULE_AUTHOR("SkyLake Huang <SkyLake.Huang@mediatek.com>");
270MODULE_LICENSE("GPL");
271
272MODULE_DEVICE_TABLE(mdio, mtk_2p5ge_phy_tbl);