1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2018-2019 MediaTek Inc.
4 /* A library for configuring path from GMAC/GDM to target PHY
10 #include <linux/phy.h>
11 #include <linux/regmap.h>
13 #include "mtk_eth_soc.h"
18 int (*set_path)(struct mtk_eth *eth, int path);
21 static const char *mtk_eth_path_name(int path)
24 case MTK_ETH_PATH_GMAC1_RGMII:
26 case MTK_ETH_PATH_GMAC1_TRGMII:
27 return "gmac1_trgmii";
28 case MTK_ETH_PATH_GMAC1_SGMII:
30 case MTK_ETH_PATH_GMAC2_RGMII:
32 case MTK_ETH_PATH_GMAC2_SGMII:
34 case MTK_ETH_PATH_GMAC2_GEPHY:
36 case MTK_ETH_PATH_GDM1_ESW:
39 return "unknown path";
43 static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, int path)
49 case MTK_ETH_PATH_GMAC1_SGMII:
50 mask = ~(u32)MTK_MUX_TO_ESW;
53 case MTK_ETH_PATH_GDM1_ESW:
54 mask = ~(u32)MTK_MUX_TO_ESW;
63 val = mtk_r32(eth, MTK_MAC_MISC);
64 val = (val & mask) | set;
65 mtk_w32(eth, val, MTK_MAC_MISC);
68 dev_dbg(eth->dev, "path %s in %s updated = %d\n",
69 mtk_eth_path_name(path), __func__, updated);
74 static int set_mux_gmac2_gmac0_to_gephy(struct mtk_eth *eth, int path)
80 case MTK_ETH_PATH_GMAC2_GEPHY:
81 val = ~(u32)GEPHY_MAC_SEL;
89 regmap_update_bits(eth->infra, INFRA_MISC2, GEPHY_MAC_SEL, val);
91 dev_dbg(eth->dev, "path %s in %s updated = %d\n",
92 mtk_eth_path_name(path), __func__, updated);
97 static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, int path)
99 unsigned int val = 0, mask = 0, reg = 0;
103 case MTK_ETH_PATH_GMAC2_SGMII:
104 if (MTK_HAS_CAPS(eth->soc->caps, MTK_U3_COPHY_V2)) {
105 reg = USB_PHY_SWITCH_REG;
106 val = SGMII_QPHY_SEL;
107 mask = QPHY_SEL_MASK;
120 regmap_update_bits(eth->infra, reg, mask, val);
122 dev_dbg(eth->dev, "path %s in %s updated = %d\n",
123 mtk_eth_path_name(path), __func__, updated);
128 static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, int path)
130 unsigned int val = 0;
134 case MTK_ETH_PATH_GMAC1_SGMII:
135 val = SYSCFG0_SGMII_GMAC1;
137 case MTK_ETH_PATH_GMAC2_SGMII:
138 val = SYSCFG0_SGMII_GMAC2;
140 case MTK_ETH_PATH_GMAC1_RGMII:
141 case MTK_ETH_PATH_GMAC2_RGMII:
142 regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
143 val &= SYSCFG0_SGMII_MASK;
145 if ((path == MTK_GMAC1_RGMII && val == SYSCFG0_SGMII_GMAC1) ||
146 (path == MTK_GMAC2_RGMII && val == SYSCFG0_SGMII_GMAC2))
157 regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
158 SYSCFG0_SGMII_MASK, val);
160 dev_dbg(eth->dev, "path %s in %s updated = %d\n",
161 mtk_eth_path_name(path), __func__, updated);
166 static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth *eth, int path)
168 unsigned int val = 0;
171 regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
174 case MTK_ETH_PATH_GMAC1_SGMII:
175 val |= SYSCFG0_SGMII_GMAC1_V2;
177 case MTK_ETH_PATH_GMAC2_GEPHY:
178 val &= ~(u32)SYSCFG0_SGMII_GMAC2_V2;
180 case MTK_ETH_PATH_GMAC2_SGMII:
181 val |= SYSCFG0_SGMII_GMAC2_V2;
188 regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
189 SYSCFG0_SGMII_MASK, val);
191 dev_dbg(eth->dev, "path %s in %s updated = %d\n",
192 mtk_eth_path_name(path), __func__, updated);
197 static const struct mtk_eth_muxc mtk_eth_muxc[] = {
199 .name = "mux_gdm1_to_gmac1_esw",
200 .cap_bit = MTK_ETH_MUX_GDM1_TO_GMAC1_ESW,
201 .set_path = set_mux_gdm1_to_gmac1_esw,
203 .name = "mux_gmac2_gmac0_to_gephy",
204 .cap_bit = MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY,
205 .set_path = set_mux_gmac2_gmac0_to_gephy,
207 .name = "mux_u3_gmac2_to_qphy",
208 .cap_bit = MTK_ETH_MUX_U3_GMAC2_TO_QPHY,
209 .set_path = set_mux_u3_gmac2_to_qphy,
211 .name = "mux_gmac1_gmac2_to_sgmii_rgmii",
212 .cap_bit = MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII,
213 .set_path = set_mux_gmac1_gmac2_to_sgmii_rgmii,
215 .name = "mux_gmac12_to_gephy_sgmii",
216 .cap_bit = MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII,
217 .set_path = set_mux_gmac12_to_gephy_sgmii,
221 static int mtk_eth_mux_setup(struct mtk_eth *eth, int path)
225 if (!MTK_HAS_CAPS(eth->soc->caps, path)) {
226 dev_err(eth->dev, "path %s isn't support on the SoC\n",
227 mtk_eth_path_name(path));
231 if (!MTK_HAS_CAPS(eth->soc->caps, MTK_MUX))
234 /* Setup MUX in path fabric */
235 for (i = 0; i < ARRAY_SIZE(mtk_eth_muxc); i++) {
236 if (MTK_HAS_CAPS(eth->soc->caps, mtk_eth_muxc[i].cap_bit)) {
237 err = mtk_eth_muxc[i].set_path(eth, path);
241 dev_dbg(eth->dev, "mux %s isn't present on the SoC\n",
242 mtk_eth_muxc[i].name);
250 int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id)
254 path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_SGMII :
255 MTK_ETH_PATH_GMAC2_SGMII;
257 /* Setup proper MUXes along the path */
258 return mtk_eth_mux_setup(eth, path);
261 int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id)
266 path = MTK_ETH_PATH_GMAC2_GEPHY;
271 /* Setup proper MUXes along the path */
272 return mtk_eth_mux_setup(eth, path);
275 int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id)
279 path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_RGMII :
280 MTK_ETH_PATH_GMAC2_RGMII;
282 /* Setup proper MUXes along the path */
283 return mtk_eth_mux_setup(eth, path);