blob: 3065d35e126d1c8e561950b4c03ef74e151e39cd [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 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
22static 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
30static 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
91static 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
102static 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
112static 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
123static 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
148static 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
247static 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
256static 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
271MTK_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};