blob: 32d6bebbbdb0463a163392f53d7d2c15afb3acbb [file] [log] [blame]
developer29d9d9f2025-01-10 16:41:13 +08001// 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 0x781C
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#define CHIP_REV_E1 0x0
22
23static int mt7531_core_reg_read(struct mt753x_switch_priv *priv, u32 reg)
24{
25 u8 phy_addr = MT753X_PHY_ADDR(priv->phy_base, 0);
26
27 return mt7531_mmd_read(priv, phy_addr, 0x1f, reg);
28}
29
30static void mt7531_core_reg_write(struct mt753x_switch_priv *priv, u32 reg,
31 u32 val)
32{
33 u8 phy_addr = MT753X_PHY_ADDR(priv->phy_base, 0);
34
35 mt7531_mmd_write(priv, phy_addr, 0x1f, reg, val);
36}
37
38static void mt7531_core_pll_setup(struct mt753x_switch_priv *priv)
39{
40 /* Step 1 : Disable MT7531 COREPLL */
41 mt753x_reg_rmw(priv, MT7531_PLLGP_EN, EN_COREPLL, 0);
42
43 /* Step 2: switch to XTAL output */
44 mt753x_reg_rmw(priv, MT7531_PLLGP_EN, SW_CLKSW, SW_CLKSW);
45
46 mt753x_reg_rmw(priv, MT7531_PLLGP_CR0, RG_COREPLL_EN, 0);
47
48 /* Step 3: disable PLLGP and enable program PLLGP */
49 mt753x_reg_rmw(priv, MT7531_PLLGP_EN, SW_PLLGP, SW_PLLGP);
50
51 /* Step 4: program COREPLL output frequency to 500MHz */
52 mt753x_reg_rmw(priv, MT7531_PLLGP_CR0, RG_COREPLL_POSDIV_M,
53 2 << RG_COREPLL_POSDIV_S);
54 udelay(25);
55
56 /* Currently, support XTAL 25Mhz only */
57 mt753x_reg_rmw(priv, MT7531_PLLGP_CR0, RG_COREPLL_SDM_PCW_M,
58 0x140000 << RG_COREPLL_SDM_PCW_S);
59
60 /* Set feedback divide ratio update signal to high */
61 mt753x_reg_rmw(priv, MT7531_PLLGP_CR0, RG_COREPLL_SDM_PCW_CHG,
62 RG_COREPLL_SDM_PCW_CHG);
63
64 /* Wait for at least 16 XTAL clocks */
65 udelay(10);
66
67 /* Step 5: set feedback divide ratio update signal to low */
68 mt753x_reg_rmw(priv, MT7531_PLLGP_CR0, RG_COREPLL_SDM_PCW_CHG, 0);
69
70 /* add enable 325M clock for SGMII */
71 mt753x_reg_write(priv, MT7531_ANA_PLLGP_CR5, 0xad0000);
72
73 /* add enable 250SSC clock for RGMII */
74 mt753x_reg_write(priv, MT7531_ANA_PLLGP_CR2, 0x4f40000);
75
76 /*Step 6: Enable MT7531 PLL */
77 mt753x_reg_rmw(priv, MT7531_PLLGP_CR0, RG_COREPLL_EN, RG_COREPLL_EN);
78
79 mt753x_reg_rmw(priv, MT7531_PLLGP_EN, EN_COREPLL, EN_COREPLL);
80
81 udelay(25);
82}
83
84static int mt7531_port_sgmii_init(struct mt753x_switch_priv *priv, u32 port)
85{
86 if (port != 5 && port != 6) {
87 printf("mt7531: port %d is not a SGMII port\n", port);
88 return -EINVAL;
89 }
90
91 /* Set SGMII GEN2 speed(2.5G) */
92 mt753x_reg_rmw(priv, MT7531_PHYA_CTRL_SIGNAL3(port), SGMSYS_SPEED_MASK,
93 FIELD_PREP(SGMSYS_SPEED_MASK, SGMSYS_SPEED_2500));
94
95 /* Disable SGMII AN */
96 mt753x_reg_rmw(priv, MT7531_PCS_CONTROL_1(port),
97 SGMII_AN_ENABLE, 0);
98
99 /* SGMII force mode setting */
100 mt753x_reg_write(priv, MT7531_SGMII_MODE(port), SGMII_FORCE_MODE);
101
102 /* Release PHYA power down state */
103 mt753x_reg_rmw(priv, MT7531_QPHY_PWR_STATE_CTRL(port),
104 SGMII_PHYA_PWD, 0);
105
106 return 0;
107}
108
109static int mt7531_port_rgmii_init(struct mt753x_switch_priv *priv, u32 port)
110{
111 u32 val;
112
113 if (port != 5) {
114 printf("error: RGMII mode is not available for port %d\n",
115 port);
116 return -EINVAL;
117 }
118
119 mt753x_reg_read(priv, MT7531_CLKGEN_CTRL, &val);
120 val |= GP_CLK_EN;
121 val &= ~GP_MODE_M;
122 val |= GP_MODE_RGMII << GP_MODE_S;
123 val |= TXCLK_NO_REVERSE;
124 val |= RXCLK_NO_DELAY;
125 val &= ~CLK_SKEW_IN_M;
126 val |= CLK_SKEW_IN_NO_CHANGE << CLK_SKEW_IN_S;
127 val &= ~CLK_SKEW_OUT_M;
128 val |= CLK_SKEW_OUT_NO_CHANGE << CLK_SKEW_OUT_S;
129 mt753x_reg_write(priv, MT7531_CLKGEN_CTRL, val);
130
131 return 0;
132}
133
134static void mt7531_phy_setting(struct mt753x_switch_priv *priv)
135{
136 int i;
137 u32 val;
138
139 for (i = 0; i < MT753X_NUM_PHYS; i++) {
140 /* Enable HW auto downshift */
141 mt7531_mii_write(priv, i, 0x1f, 0x1);
142 val = mt7531_mii_read(priv, i, PHY_EXT_REG_14);
143 val |= PHY_EN_DOWN_SHFIT;
144 mt7531_mii_write(priv, i, PHY_EXT_REG_14, val);
145
146 /* PHY link down power saving enable */
147 val = mt7531_mii_read(priv, i, PHY_EXT_REG_17);
148 val |= PHY_LINKDOWN_POWER_SAVING_EN;
149 mt7531_mii_write(priv, i, PHY_EXT_REG_17, val);
150
151 val = mt7531_mmd_read(priv, i, 0x1e, PHY_DEV1E_REG_0C6);
152 val &= ~PHY_POWER_SAVING_M;
153 val |= PHY_POWER_SAVING_TX << PHY_POWER_SAVING_S;
154 mt7531_mmd_write(priv, i, 0x1e, PHY_DEV1E_REG_0C6, val);
155 }
156}
157
158static void mt7531_mac_control(struct mtk_eth_switch_priv *swpriv, bool enable)
159{
160 struct mt753x_switch_priv *priv = (struct mt753x_switch_priv *)swpriv;
161 u32 pmcr = FORCE_MODE_LNK;
162
163 if (enable)
164 pmcr = priv->pmcr;
165
166 mt753x_reg_write(priv, PMCR_REG(5), pmcr);
167 mt753x_reg_write(priv, PMCR_REG(6), pmcr);
168}
169
170static int mt7531_setup(struct mtk_eth_switch_priv *swpriv)
171{
172 struct mt753x_switch_priv *priv = (struct mt753x_switch_priv *)swpriv;
173 u32 i, val, pmcr, port5_sgmii;
174 u16 phy_addr, phy_val;
175
176 priv->smi_addr = MT753X_DFL_SMI_ADDR;
177 priv->phy_base = (priv->smi_addr + 1) & MT753X_SMI_ADDR_MASK;
178 priv->reg_read = mt753x_mdio_reg_read;
179 priv->reg_write = mt753x_mdio_reg_write;
180
181 /* Turn off PHYs */
182 for (i = 0; i < MT753X_NUM_PHYS; i++) {
183 phy_addr = MT753X_PHY_ADDR(priv->phy_base, i);
184 phy_val = mt7531_mii_read(priv, phy_addr, MII_BMCR);
185 phy_val |= BMCR_PDOWN;
186 mt7531_mii_write(priv, phy_addr, MII_BMCR, phy_val);
187 }
188
189 /* Force MAC link down before reset */
190 mt753x_reg_write(priv, PMCR_REG(5), FORCE_MODE_LNK);
191 mt753x_reg_write(priv, PMCR_REG(6), FORCE_MODE_LNK);
192
193 /* Switch soft reset */
194 mt753x_reg_write(priv, SYS_CTRL_REG, SW_SYS_RST | SW_REG_RST);
195 udelay(100);
196
197 /* Enable MDC input Schmitt Trigger */
198 mt753x_reg_rmw(priv, MT7531_SMT0_IOLB, SMT_IOLB_5_SMI_MDC_EN,
199 SMT_IOLB_5_SMI_MDC_EN);
200
201 mt7531_core_pll_setup(priv);
202
203 mt753x_reg_read(priv, MT7531_TOP_SIG_SR, &val);
204 port5_sgmii = !!(val & PAD_DUAL_SGMII_EN);
205
206 /* port5 support either RGMII or SGMII, port6 only support SGMII. */
207 switch (priv->epriv.phy_interface) {
208 case PHY_INTERFACE_MODE_RGMII:
209 if (!port5_sgmii)
210 mt7531_port_rgmii_init(priv, 5);
211 break;
212
213 case PHY_INTERFACE_MODE_2500BASEX:
214 mt7531_port_sgmii_init(priv, 6);
215 if (port5_sgmii)
216 mt7531_port_sgmii_init(priv, 5);
217 break;
218
219 default:
220 break;
221 }
222
223 pmcr = MT7531_FORCE_MODE |
224 (IPG_96BIT_WITH_SHORT_IPG << IPG_CFG_S) |
225 MAC_MODE | MAC_TX_EN | MAC_RX_EN |
226 BKOFF_EN | BACKPR_EN |
227 FORCE_RX_FC | FORCE_TX_FC |
228 (SPEED_1000M << FORCE_SPD_S) | FORCE_DPX |
229 FORCE_LINK;
230
231 priv->pmcr = pmcr;
232
233 /* Keep MAC link down before starting eth */
234 mt753x_reg_write(priv, PMCR_REG(5), FORCE_MODE_LNK);
235 mt753x_reg_write(priv, PMCR_REG(6), FORCE_MODE_LNK);
236
237 /* Enable port isolation to block inter-port communication */
238 mt753x_port_isolation(priv);
239
240 /* Turn on PHYs */
241 for (i = 0; i < MT753X_NUM_PHYS; i++) {
242 phy_addr = MT753X_PHY_ADDR(priv->phy_base, i);
243 phy_val = mt7531_mii_read(priv, phy_addr, MII_BMCR);
244 phy_val &= ~BMCR_PDOWN;
245 mt7531_mii_write(priv, phy_addr, MII_BMCR, phy_val);
246 }
247
248 mt7531_phy_setting(priv);
249
250 /* Enable Internal PHYs */
251 val = mt7531_core_reg_read(priv, CORE_PLL_GROUP4);
252 val |= MT7531_BYPASS_MODE;
253 val &= ~MT7531_POWER_ON_OFF;
254 mt7531_core_reg_write(priv, CORE_PLL_GROUP4, val);
255
256 return mt7531_mdio_register(priv);
257}
258
259static int mt7531_cleanup(struct mtk_eth_switch_priv *swpriv)
260{
261 struct mt753x_switch_priv *priv = (struct mt753x_switch_priv *)swpriv;
262
263 mdio_unregister(priv->mdio_bus);
264
265 return 0;
266}
267
268static int mt7531_detect(struct mtk_eth_priv *priv)
269{
270 int ret;
271 u32 rev;
272
273 ret = __mt753x_mdio_reg_read(priv, MT753X_DFL_SMI_ADDR, CHIP_REV, &rev);
274 if (ret)
275 return ret;
276
277 if (((rev & CHIP_NAME_M) >> CHIP_NAME_S) == 0x7531)
278 return 0;
279
280 return -ENODEV;
281}
282
283MTK_ETH_SWITCH(mt7531) = {
284 .name = "mt7531",
285 .desc = "MediaTek MT7531",
286 .priv_size = sizeof(struct mt753x_switch_priv),
287 .reset_wait_time = 200,
288
289 .detect = mt7531_detect,
290 .setup = mt7531_setup,
291 .cleanup = mt7531_cleanup,
292 .mac_control = mt7531_mac_control,
293};