1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2025 MediaTek Inc.
4  *
5  * Author: Weijie Gao <weijie.gao@mediatek.com>
6  * Author: Mark Lee <mark-mc.lee@mediatek.com>
7  */
8 
9 #include <miiphy.h>
10 #include <linux/delay.h>
11 #include <linux/mdio.h>
12 #include <linux/mii.h>
13 #include "mtk_eth.h"
14 #include "mt753x.h"
15 
16 #define CHIP_REV			0x7ffc
17 #define CHIP_NAME_S			16
18 #define CHIP_NAME_M			0xffff0000
19 #define CHIP_REV_S			0
20 #define CHIP_REV_M			0x0f
21 
mt7530_core_reg_write(struct mt753x_switch_priv * priv,u32 reg,u32 val)22 static void mt7530_core_reg_write(struct mt753x_switch_priv *priv, u32 reg,
23 				  u32 val)
24 {
25 	u8 phy_addr = MT753X_PHY_ADDR(priv->phy_base, 0);
26 
27 	mtk_mmd_ind_write(priv->epriv.eth, phy_addr, 0x1f, reg, val);
28 }
29 
mt7530_pad_clk_setup(struct mt753x_switch_priv * priv,int mode)30 static int mt7530_pad_clk_setup(struct mt753x_switch_priv *priv, int mode)
31 {
32 	u32 ncpo1, ssc_delta;
33 
34 	switch (mode) {
35 	case PHY_INTERFACE_MODE_RGMII:
36 		ncpo1 = 0x0c80;
37 		ssc_delta = 0x87;
38 		break;
39 
40 	default:
41 		printf("error: xMII mode %d is not supported\n", mode);
42 		return -EINVAL;
43 	}
44 
45 	/* Disable MT7530 core clock */
46 	mt7530_core_reg_write(priv, CORE_TRGMII_GSW_CLK_CG, 0);
47 
48 	/* Disable MT7530 PLL */
49 	mt7530_core_reg_write(priv, CORE_GSWPLL_GRP1,
50 			      (2 << RG_GSWPLL_POSDIV_200M_S) |
51 			      (32 << RG_GSWPLL_FBKDIV_200M_S));
52 
53 	/* For MT7530 core clock = 500Mhz */
54 	mt7530_core_reg_write(priv, CORE_GSWPLL_GRP2,
55 			      (1 << RG_GSWPLL_POSDIV_500M_S) |
56 			      (25 << RG_GSWPLL_FBKDIV_500M_S));
57 
58 	/* Enable MT7530 PLL */
59 	mt7530_core_reg_write(priv, CORE_GSWPLL_GRP1,
60 			      (2 << RG_GSWPLL_POSDIV_200M_S) |
61 			      (32 << RG_GSWPLL_FBKDIV_200M_S) |
62 			      RG_GSWPLL_EN_PRE);
63 
64 	udelay(20);
65 
66 	mt7530_core_reg_write(priv, CORE_TRGMII_GSW_CLK_CG, REG_GSWCK_EN);
67 
68 	/* Setup the MT7530 TRGMII Tx Clock */
69 	mt7530_core_reg_write(priv, CORE_PLL_GROUP5, ncpo1);
70 	mt7530_core_reg_write(priv, CORE_PLL_GROUP6, 0);
71 	mt7530_core_reg_write(priv, CORE_PLL_GROUP10, ssc_delta);
72 	mt7530_core_reg_write(priv, CORE_PLL_GROUP11, ssc_delta);
73 	mt7530_core_reg_write(priv, CORE_PLL_GROUP4, RG_SYSPLL_DDSFBK_EN |
74 			      RG_SYSPLL_BIAS_EN | RG_SYSPLL_BIAS_LPF_EN);
75 
76 	mt7530_core_reg_write(priv, CORE_PLL_GROUP2,
77 			      RG_SYSPLL_EN_NORMAL | RG_SYSPLL_VODEN |
78 			      (1 << RG_SYSPLL_POSDIV_S));
79 
80 	mt7530_core_reg_write(priv, CORE_PLL_GROUP7,
81 			      RG_LCDDS_PCW_NCPO_CHG | (3 << RG_LCCDS_C_S) |
82 			      RG_LCDDS_PWDB | RG_LCDDS_ISO_EN);
83 
84 	/* Enable MT7530 core clock */
85 	mt7530_core_reg_write(priv, CORE_TRGMII_GSW_CLK_CG,
86 			      REG_GSWCK_EN | REG_TRGMIICK_EN);
87 
88 	return 0;
89 }
90 
mt7530_mac_control(struct mtk_eth_switch_priv * swpriv,bool enable)91 static void mt7530_mac_control(struct mtk_eth_switch_priv *swpriv, bool enable)
92 {
93 	struct mt753x_switch_priv *priv = (struct mt753x_switch_priv *)swpriv;
94 	u32 pmcr = FORCE_MODE;
95 
96 	if (enable)
97 		pmcr = priv->pmcr;
98 
99 	mt753x_reg_write(priv, PMCR_REG(6), pmcr);
100 }
101 
mt7530_mdio_read(struct mii_dev * bus,int addr,int devad,int reg)102 static int mt7530_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
103 {
104 	struct mt753x_switch_priv *priv = bus->priv;
105 
106 	if (devad < 0)
107 		return mtk_mii_read(priv->epriv.eth, addr, reg);
108 
109 	return mtk_mmd_ind_read(priv->epriv.eth, addr, devad, reg);
110 }
111 
mt7530_mdio_write(struct mii_dev * bus,int addr,int devad,int reg,u16 val)112 static int mt7530_mdio_write(struct mii_dev *bus, int addr, int devad, int reg,
113 			     u16 val)
114 {
115 	struct mt753x_switch_priv *priv = bus->priv;
116 
117 	if (devad < 0)
118 		return mtk_mii_write(priv->epriv.eth, addr, reg, val);
119 
120 	return mtk_mmd_ind_write(priv->epriv.eth, addr, devad, reg, val);
121 }
122 
mt7530_mdio_register(struct mt753x_switch_priv * priv)123 static int mt7530_mdio_register(struct mt753x_switch_priv *priv)
124 {
125 	struct mii_dev *mdio_bus = mdio_alloc();
126 	int ret;
127 
128 	if (!mdio_bus)
129 		return -ENOMEM;
130 
131 	mdio_bus->read = mt7530_mdio_read;
132 	mdio_bus->write = mt7530_mdio_write;
133 	snprintf(mdio_bus->name, sizeof(mdio_bus->name), priv->epriv.sw->name);
134 
135 	mdio_bus->priv = priv;
136 
137 	ret = mdio_register(mdio_bus);
138 	if (ret) {
139 		mdio_free(mdio_bus);
140 		return ret;
141 	}
142 
143 	priv->mdio_bus = mdio_bus;
144 
145 	return 0;
146 }
147 
mt7530_setup(struct mtk_eth_switch_priv * swpriv)148 static int mt7530_setup(struct mtk_eth_switch_priv *swpriv)
149 {
150 	struct mt753x_switch_priv *priv = (struct mt753x_switch_priv *)swpriv;
151 	u16 phy_addr, phy_val;
152 	u32 i, val, txdrv;
153 
154 	priv->smi_addr = MT753X_DFL_SMI_ADDR;
155 	priv->reg_read = mt753x_mdio_reg_read;
156 	priv->reg_write = mt753x_mdio_reg_write;
157 
158 	if (!MTK_HAS_CAPS(priv->epriv.soc->caps, MTK_TRGMII_MT7621_CLK)) {
159 		/* Select 250MHz clk for RGMII mode */
160 		mtk_ethsys_rmw(priv->epriv.eth, ETHSYS_CLKCFG0_REG,
161 			       ETHSYS_TRGMII_CLK_SEL362_5, 0);
162 
163 		txdrv = 8;
164 	} else {
165 		txdrv = 4;
166 	}
167 
168 	/* Modify HWTRAP first to allow direct access to internal PHYs */
169 	mt753x_reg_read(priv, HWTRAP_REG, &val);
170 	val |= CHG_TRAP;
171 	val &= ~C_MDIO_BPS;
172 	mt753x_reg_write(priv, MHWTRAP_REG, val);
173 
174 	/* Calculate the phy base address */
175 	val = ((val & SMI_ADDR_M) >> SMI_ADDR_S) << 3;
176 	priv->phy_base = (val | 0x7) + 1;
177 
178 	/* Turn off PHYs */
179 	for (i = 0; i < MT753X_NUM_PHYS; i++) {
180 		phy_addr = MT753X_PHY_ADDR(priv->phy_base, i);
181 		phy_val = mtk_mii_read(priv->epriv.eth, phy_addr, MII_BMCR);
182 		phy_val |= BMCR_PDOWN;
183 		mtk_mii_write(priv->epriv.eth, phy_addr, MII_BMCR, phy_val);
184 	}
185 
186 	/* Force MAC link down before reset */
187 	mt753x_reg_write(priv, PMCR_REG(5), FORCE_MODE);
188 	mt753x_reg_write(priv, PMCR_REG(6), FORCE_MODE);
189 
190 	/* MT7530 reset */
191 	mt753x_reg_write(priv, SYS_CTRL_REG, SW_SYS_RST | SW_REG_RST);
192 	udelay(100);
193 
194 	val = (IPG_96BIT_WITH_SHORT_IPG << IPG_CFG_S) |
195 	      MAC_MODE | FORCE_MODE |
196 	      MAC_TX_EN | MAC_RX_EN |
197 	      BKOFF_EN | BACKPR_EN |
198 	      (SPEED_1000M << FORCE_SPD_S) |
199 	      FORCE_DPX | FORCE_LINK;
200 
201 	/* MT7530 Port6: Forced 1000M/FD, FC disabled */
202 	priv->pmcr = val;
203 
204 	/* MT7530 Port5: Forced link down */
205 	mt753x_reg_write(priv, PMCR_REG(5), FORCE_MODE);
206 
207 	/* Keep MAC link down before starting eth */
208 	mt753x_reg_write(priv, PMCR_REG(6), FORCE_MODE);
209 
210 	/* MT7530 Port6: Set to RGMII */
211 	mt753x_reg_rmw(priv, MT7530_P6ECR, P6_INTF_MODE_M, P6_INTF_MODE_RGMII);
212 
213 	/* Hardware Trap: Enable Port6, Disable Port5 */
214 	mt753x_reg_read(priv, HWTRAP_REG, &val);
215 	val |= CHG_TRAP | LOOPDET_DIS | P5_INTF_DIS |
216 	       (P5_INTF_SEL_GMAC5 << P5_INTF_SEL_S) |
217 	       (P5_INTF_MODE_RGMII << P5_INTF_MODE_S);
218 	val &= ~(C_MDIO_BPS | P6_INTF_DIS);
219 	mt753x_reg_write(priv, MHWTRAP_REG, val);
220 
221 	/* Setup switch core pll */
222 	mt7530_pad_clk_setup(priv, priv->epriv.phy_interface);
223 
224 	/* Lower Tx Driving for TRGMII path */
225 	for (i = 0 ; i < NUM_TRGMII_CTRL ; i++)
226 		mt753x_reg_write(priv, MT7530_TRGMII_TD_ODT(i),
227 				 (txdrv << TD_DM_DRVP_S) |
228 				 (txdrv << TD_DM_DRVN_S));
229 
230 	for (i = 0 ; i < NUM_TRGMII_CTRL; i++)
231 		mt753x_reg_rmw(priv, MT7530_TRGMII_RD(i), RD_TAP_M, 16);
232 
233 	/* Enable port isolation to block inter-port communication */
234 	mt753x_port_isolation(priv);
235 
236 	/* Turn on PHYs */
237 	for (i = 0; i < MT753X_NUM_PHYS; i++) {
238 		phy_addr = MT753X_PHY_ADDR(priv->phy_base, i);
239 		phy_val = mtk_mii_read(priv->epriv.eth, phy_addr, MII_BMCR);
240 		phy_val &= ~BMCR_PDOWN;
241 		mtk_mii_write(priv->epriv.eth, phy_addr, MII_BMCR, phy_val);
242 	}
243 
244 	return mt7530_mdio_register(priv);
245 }
246 
mt7530_cleanup(struct mtk_eth_switch_priv * swpriv)247 static int mt7530_cleanup(struct mtk_eth_switch_priv *swpriv)
248 {
249 	struct mt753x_switch_priv *priv = (struct mt753x_switch_priv *)swpriv;
250 
251 	mdio_unregister(priv->mdio_bus);
252 
253 	return 0;
254 }
255 
mt7530_detect(struct mtk_eth_priv * priv)256 static int mt7530_detect(struct mtk_eth_priv *priv)
257 {
258 	int ret;
259 	u32 rev;
260 
261 	ret = __mt753x_mdio_reg_read(priv, MT753X_DFL_SMI_ADDR, CHIP_REV, &rev);
262 	if (ret)
263 		return ret;
264 
265 	if (((rev & CHIP_NAME_M) >> CHIP_NAME_S) == 0x7530)
266 		return 0;
267 
268 	return -ENODEV;
269 }
270 
271 MTK_ETH_SWITCH(mt7530) = {
272 	.name = "mt7530",
273 	.desc = "MediaTek MT7530",
274 	.priv_size = sizeof(struct mt753x_switch_priv),
275 	.reset_wait_time = 1000,
276 
277 	.detect = mt7530_detect,
278 	.setup = mt7530_setup,
279 	.cleanup = mt7530_cleanup,
280 	.mac_control = mt7530_mac_control,
281 };
282