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
6 * Author: Sean Wang <sean.wang@mediatek.com>
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
)
103 case MTK_ETH_PATH_GMAC2_SGMII
:
112 regmap_update_bits(eth
->infra
, INFRA_MISC2
, CO_QPHY_SEL
, val
);
114 dev_dbg(eth
->dev
, "path %s in %s updated = %d\n",
115 mtk_eth_path_name(path
), __func__
, updated
);
120 static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth
*eth
, int path
)
122 unsigned int val
= 0;
126 case MTK_ETH_PATH_GMAC1_SGMII
:
127 val
= SYSCFG0_SGMII_GMAC1
;
129 case MTK_ETH_PATH_GMAC2_SGMII
:
130 val
= SYSCFG0_SGMII_GMAC2
;
132 case MTK_ETH_PATH_GMAC1_RGMII
:
133 case MTK_ETH_PATH_GMAC2_RGMII
:
134 regmap_read(eth
->ethsys
, ETHSYS_SYSCFG0
, &val
);
135 val
&= SYSCFG0_SGMII_MASK
;
137 if ((path
== MTK_GMAC1_RGMII
&& val
== SYSCFG0_SGMII_GMAC1
) ||
138 (path
== MTK_GMAC2_RGMII
&& val
== SYSCFG0_SGMII_GMAC2
))
149 regmap_update_bits(eth
->ethsys
, ETHSYS_SYSCFG0
,
150 SYSCFG0_SGMII_MASK
, val
);
152 dev_dbg(eth
->dev
, "path %s in %s updated = %d\n",
153 mtk_eth_path_name(path
), __func__
, updated
);
158 static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth
*eth
, int path
)
160 unsigned int val
= 0;
163 regmap_read(eth
->ethsys
, ETHSYS_SYSCFG0
, &val
);
166 case MTK_ETH_PATH_GMAC1_SGMII
:
167 val
|= SYSCFG0_SGMII_GMAC1_V2
;
169 case MTK_ETH_PATH_GMAC2_GEPHY
:
170 val
&= ~(u32
)SYSCFG0_SGMII_GMAC2_V2
;
172 case MTK_ETH_PATH_GMAC2_SGMII
:
173 val
|= SYSCFG0_SGMII_GMAC2_V2
;
180 regmap_update_bits(eth
->ethsys
, ETHSYS_SYSCFG0
,
181 SYSCFG0_SGMII_MASK
, val
);
183 dev_dbg(eth
->dev
, "path %s in %s updated = %d\n",
184 mtk_eth_path_name(path
), __func__
, updated
);
189 static const struct mtk_eth_muxc mtk_eth_muxc
[] = {
191 .name
= "mux_gdm1_to_gmac1_esw",
192 .cap_bit
= MTK_ETH_MUX_GDM1_TO_GMAC1_ESW
,
193 .set_path
= set_mux_gdm1_to_gmac1_esw
,
195 .name
= "mux_gmac2_gmac0_to_gephy",
196 .cap_bit
= MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY
,
197 .set_path
= set_mux_gmac2_gmac0_to_gephy
,
199 .name
= "mux_u3_gmac2_to_qphy",
200 .cap_bit
= MTK_ETH_MUX_U3_GMAC2_TO_QPHY
,
201 .set_path
= set_mux_u3_gmac2_to_qphy
,
203 .name
= "mux_gmac1_gmac2_to_sgmii_rgmii",
204 .cap_bit
= MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII
,
205 .set_path
= set_mux_gmac1_gmac2_to_sgmii_rgmii
,
207 .name
= "mux_gmac12_to_gephy_sgmii",
208 .cap_bit
= MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII
,
209 .set_path
= set_mux_gmac12_to_gephy_sgmii
,
213 static int mtk_eth_mux_setup(struct mtk_eth
*eth
, int path
)
217 if (!MTK_HAS_CAPS(eth
->soc
->caps
, path
)) {
218 dev_err(eth
->dev
, "path %s isn't support on the SoC\n",
219 mtk_eth_path_name(path
));
223 if (!MTK_HAS_CAPS(eth
->soc
->caps
, MTK_MUX
))
226 /* Setup MUX in path fabric */
227 for (i
= 0; i
< ARRAY_SIZE(mtk_eth_muxc
); i
++) {
228 if (MTK_HAS_CAPS(eth
->soc
->caps
, mtk_eth_muxc
[i
].cap_bit
)) {
229 err
= mtk_eth_muxc
[i
].set_path(eth
, path
);
233 dev_dbg(eth
->dev
, "mux %s isn't present on the SoC\n",
234 mtk_eth_muxc
[i
].name
);
242 int mtk_gmac_sgmii_path_setup(struct mtk_eth
*eth
, int mac_id
)
246 path
= (mac_id
== 0) ? MTK_ETH_PATH_GMAC1_SGMII
:
247 MTK_ETH_PATH_GMAC2_SGMII
;
249 /* Setup proper MUXes along the path */
250 return mtk_eth_mux_setup(eth
, path
);
253 int mtk_gmac_gephy_path_setup(struct mtk_eth
*eth
, int mac_id
)
258 path
= MTK_ETH_PATH_GMAC2_GEPHY
;
263 /* Setup proper MUXes along the path */
264 return mtk_eth_mux_setup(eth
, path
);
267 int mtk_gmac_rgmii_path_setup(struct mtk_eth
*eth
, int mac_id
)
271 path
= (mac_id
== 0) ? MTK_ETH_PATH_GMAC1_RGMII
:
272 MTK_ETH_PATH_GMAC2_RGMII
;
274 /* Setup proper MUXes along the path */
275 return mtk_eth_mux_setup(eth
, path
);