1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun // Copyright (c) 2018-2019 MediaTek Inc.
3*4882a593Smuzhiyun
4*4882a593Smuzhiyun /* A library for configuring path from GMAC/GDM to target PHY
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Author: Sean Wang <sean.wang@mediatek.com>
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/phy.h>
11*4882a593Smuzhiyun #include <linux/regmap.h>
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun #include "mtk_eth_soc.h"
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun struct mtk_eth_muxc {
16*4882a593Smuzhiyun const char *name;
17*4882a593Smuzhiyun int cap_bit;
18*4882a593Smuzhiyun int (*set_path)(struct mtk_eth *eth, int path);
19*4882a593Smuzhiyun };
20*4882a593Smuzhiyun
mtk_eth_path_name(int path)21*4882a593Smuzhiyun static const char *mtk_eth_path_name(int path)
22*4882a593Smuzhiyun {
23*4882a593Smuzhiyun switch (path) {
24*4882a593Smuzhiyun case MTK_ETH_PATH_GMAC1_RGMII:
25*4882a593Smuzhiyun return "gmac1_rgmii";
26*4882a593Smuzhiyun case MTK_ETH_PATH_GMAC1_TRGMII:
27*4882a593Smuzhiyun return "gmac1_trgmii";
28*4882a593Smuzhiyun case MTK_ETH_PATH_GMAC1_SGMII:
29*4882a593Smuzhiyun return "gmac1_sgmii";
30*4882a593Smuzhiyun case MTK_ETH_PATH_GMAC2_RGMII:
31*4882a593Smuzhiyun return "gmac2_rgmii";
32*4882a593Smuzhiyun case MTK_ETH_PATH_GMAC2_SGMII:
33*4882a593Smuzhiyun return "gmac2_sgmii";
34*4882a593Smuzhiyun case MTK_ETH_PATH_GMAC2_GEPHY:
35*4882a593Smuzhiyun return "gmac2_gephy";
36*4882a593Smuzhiyun case MTK_ETH_PATH_GDM1_ESW:
37*4882a593Smuzhiyun return "gdm1_esw";
38*4882a593Smuzhiyun default:
39*4882a593Smuzhiyun return "unknown path";
40*4882a593Smuzhiyun }
41*4882a593Smuzhiyun }
42*4882a593Smuzhiyun
set_mux_gdm1_to_gmac1_esw(struct mtk_eth * eth,int path)43*4882a593Smuzhiyun static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, int path)
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun bool updated = true;
46*4882a593Smuzhiyun u32 val, mask, set;
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun switch (path) {
49*4882a593Smuzhiyun case MTK_ETH_PATH_GMAC1_SGMII:
50*4882a593Smuzhiyun mask = ~(u32)MTK_MUX_TO_ESW;
51*4882a593Smuzhiyun set = 0;
52*4882a593Smuzhiyun break;
53*4882a593Smuzhiyun case MTK_ETH_PATH_GDM1_ESW:
54*4882a593Smuzhiyun mask = ~(u32)MTK_MUX_TO_ESW;
55*4882a593Smuzhiyun set = MTK_MUX_TO_ESW;
56*4882a593Smuzhiyun break;
57*4882a593Smuzhiyun default:
58*4882a593Smuzhiyun updated = false;
59*4882a593Smuzhiyun break;
60*4882a593Smuzhiyun }
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun if (updated) {
63*4882a593Smuzhiyun val = mtk_r32(eth, MTK_MAC_MISC);
64*4882a593Smuzhiyun val = (val & mask) | set;
65*4882a593Smuzhiyun mtk_w32(eth, val, MTK_MAC_MISC);
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun dev_dbg(eth->dev, "path %s in %s updated = %d\n",
69*4882a593Smuzhiyun mtk_eth_path_name(path), __func__, updated);
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun return 0;
72*4882a593Smuzhiyun }
73*4882a593Smuzhiyun
set_mux_gmac2_gmac0_to_gephy(struct mtk_eth * eth,int path)74*4882a593Smuzhiyun static int set_mux_gmac2_gmac0_to_gephy(struct mtk_eth *eth, int path)
75*4882a593Smuzhiyun {
76*4882a593Smuzhiyun unsigned int val = 0;
77*4882a593Smuzhiyun bool updated = true;
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun switch (path) {
80*4882a593Smuzhiyun case MTK_ETH_PATH_GMAC2_GEPHY:
81*4882a593Smuzhiyun val = ~(u32)GEPHY_MAC_SEL;
82*4882a593Smuzhiyun break;
83*4882a593Smuzhiyun default:
84*4882a593Smuzhiyun updated = false;
85*4882a593Smuzhiyun break;
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun if (updated)
89*4882a593Smuzhiyun regmap_update_bits(eth->infra, INFRA_MISC2, GEPHY_MAC_SEL, val);
90*4882a593Smuzhiyun
91*4882a593Smuzhiyun dev_dbg(eth->dev, "path %s in %s updated = %d\n",
92*4882a593Smuzhiyun mtk_eth_path_name(path), __func__, updated);
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun return 0;
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun
set_mux_u3_gmac2_to_qphy(struct mtk_eth * eth,int path)97*4882a593Smuzhiyun static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, int path)
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun unsigned int val = 0;
100*4882a593Smuzhiyun bool updated = true;
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun switch (path) {
103*4882a593Smuzhiyun case MTK_ETH_PATH_GMAC2_SGMII:
104*4882a593Smuzhiyun val = CO_QPHY_SEL;
105*4882a593Smuzhiyun break;
106*4882a593Smuzhiyun default:
107*4882a593Smuzhiyun updated = false;
108*4882a593Smuzhiyun break;
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun if (updated)
112*4882a593Smuzhiyun regmap_update_bits(eth->infra, INFRA_MISC2, CO_QPHY_SEL, val);
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun dev_dbg(eth->dev, "path %s in %s updated = %d\n",
115*4882a593Smuzhiyun mtk_eth_path_name(path), __func__, updated);
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun return 0;
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun
set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth * eth,int path)120*4882a593Smuzhiyun static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, int path)
121*4882a593Smuzhiyun {
122*4882a593Smuzhiyun unsigned int val = 0;
123*4882a593Smuzhiyun bool updated = true;
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun switch (path) {
126*4882a593Smuzhiyun case MTK_ETH_PATH_GMAC1_SGMII:
127*4882a593Smuzhiyun val = SYSCFG0_SGMII_GMAC1;
128*4882a593Smuzhiyun break;
129*4882a593Smuzhiyun case MTK_ETH_PATH_GMAC2_SGMII:
130*4882a593Smuzhiyun val = SYSCFG0_SGMII_GMAC2;
131*4882a593Smuzhiyun break;
132*4882a593Smuzhiyun case MTK_ETH_PATH_GMAC1_RGMII:
133*4882a593Smuzhiyun case MTK_ETH_PATH_GMAC2_RGMII:
134*4882a593Smuzhiyun regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
135*4882a593Smuzhiyun val &= SYSCFG0_SGMII_MASK;
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun if ((path == MTK_GMAC1_RGMII && val == SYSCFG0_SGMII_GMAC1) ||
138*4882a593Smuzhiyun (path == MTK_GMAC2_RGMII && val == SYSCFG0_SGMII_GMAC2))
139*4882a593Smuzhiyun val = 0;
140*4882a593Smuzhiyun else
141*4882a593Smuzhiyun updated = false;
142*4882a593Smuzhiyun break;
143*4882a593Smuzhiyun default:
144*4882a593Smuzhiyun updated = false;
145*4882a593Smuzhiyun break;
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun if (updated)
149*4882a593Smuzhiyun regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
150*4882a593Smuzhiyun SYSCFG0_SGMII_MASK, val);
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun dev_dbg(eth->dev, "path %s in %s updated = %d\n",
153*4882a593Smuzhiyun mtk_eth_path_name(path), __func__, updated);
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun return 0;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
set_mux_gmac12_to_gephy_sgmii(struct mtk_eth * eth,int path)158*4882a593Smuzhiyun static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth *eth, int path)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun unsigned int val = 0;
161*4882a593Smuzhiyun bool updated = true;
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun switch (path) {
166*4882a593Smuzhiyun case MTK_ETH_PATH_GMAC1_SGMII:
167*4882a593Smuzhiyun val |= SYSCFG0_SGMII_GMAC1_V2;
168*4882a593Smuzhiyun break;
169*4882a593Smuzhiyun case MTK_ETH_PATH_GMAC2_GEPHY:
170*4882a593Smuzhiyun val &= ~(u32)SYSCFG0_SGMII_GMAC2_V2;
171*4882a593Smuzhiyun break;
172*4882a593Smuzhiyun case MTK_ETH_PATH_GMAC2_SGMII:
173*4882a593Smuzhiyun val |= SYSCFG0_SGMII_GMAC2_V2;
174*4882a593Smuzhiyun break;
175*4882a593Smuzhiyun default:
176*4882a593Smuzhiyun updated = false;
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun if (updated)
180*4882a593Smuzhiyun regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
181*4882a593Smuzhiyun SYSCFG0_SGMII_MASK, val);
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun dev_dbg(eth->dev, "path %s in %s updated = %d\n",
184*4882a593Smuzhiyun mtk_eth_path_name(path), __func__, updated);
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun return 0;
187*4882a593Smuzhiyun }
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun static const struct mtk_eth_muxc mtk_eth_muxc[] = {
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun .name = "mux_gdm1_to_gmac1_esw",
192*4882a593Smuzhiyun .cap_bit = MTK_ETH_MUX_GDM1_TO_GMAC1_ESW,
193*4882a593Smuzhiyun .set_path = set_mux_gdm1_to_gmac1_esw,
194*4882a593Smuzhiyun }, {
195*4882a593Smuzhiyun .name = "mux_gmac2_gmac0_to_gephy",
196*4882a593Smuzhiyun .cap_bit = MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY,
197*4882a593Smuzhiyun .set_path = set_mux_gmac2_gmac0_to_gephy,
198*4882a593Smuzhiyun }, {
199*4882a593Smuzhiyun .name = "mux_u3_gmac2_to_qphy",
200*4882a593Smuzhiyun .cap_bit = MTK_ETH_MUX_U3_GMAC2_TO_QPHY,
201*4882a593Smuzhiyun .set_path = set_mux_u3_gmac2_to_qphy,
202*4882a593Smuzhiyun }, {
203*4882a593Smuzhiyun .name = "mux_gmac1_gmac2_to_sgmii_rgmii",
204*4882a593Smuzhiyun .cap_bit = MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII,
205*4882a593Smuzhiyun .set_path = set_mux_gmac1_gmac2_to_sgmii_rgmii,
206*4882a593Smuzhiyun }, {
207*4882a593Smuzhiyun .name = "mux_gmac12_to_gephy_sgmii",
208*4882a593Smuzhiyun .cap_bit = MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII,
209*4882a593Smuzhiyun .set_path = set_mux_gmac12_to_gephy_sgmii,
210*4882a593Smuzhiyun },
211*4882a593Smuzhiyun };
212*4882a593Smuzhiyun
mtk_eth_mux_setup(struct mtk_eth * eth,int path)213*4882a593Smuzhiyun static int mtk_eth_mux_setup(struct mtk_eth *eth, int path)
214*4882a593Smuzhiyun {
215*4882a593Smuzhiyun int i, err = 0;
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun if (!MTK_HAS_CAPS(eth->soc->caps, path)) {
218*4882a593Smuzhiyun dev_err(eth->dev, "path %s isn't support on the SoC\n",
219*4882a593Smuzhiyun mtk_eth_path_name(path));
220*4882a593Smuzhiyun return -EINVAL;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun if (!MTK_HAS_CAPS(eth->soc->caps, MTK_MUX))
224*4882a593Smuzhiyun return 0;
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun /* Setup MUX in path fabric */
227*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(mtk_eth_muxc); i++) {
228*4882a593Smuzhiyun if (MTK_HAS_CAPS(eth->soc->caps, mtk_eth_muxc[i].cap_bit)) {
229*4882a593Smuzhiyun err = mtk_eth_muxc[i].set_path(eth, path);
230*4882a593Smuzhiyun if (err)
231*4882a593Smuzhiyun goto out;
232*4882a593Smuzhiyun } else {
233*4882a593Smuzhiyun dev_dbg(eth->dev, "mux %s isn't present on the SoC\n",
234*4882a593Smuzhiyun mtk_eth_muxc[i].name);
235*4882a593Smuzhiyun }
236*4882a593Smuzhiyun }
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun out:
239*4882a593Smuzhiyun return err;
240*4882a593Smuzhiyun }
241*4882a593Smuzhiyun
mtk_gmac_sgmii_path_setup(struct mtk_eth * eth,int mac_id)242*4882a593Smuzhiyun int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id)
243*4882a593Smuzhiyun {
244*4882a593Smuzhiyun int err, path;
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_SGMII :
247*4882a593Smuzhiyun MTK_ETH_PATH_GMAC2_SGMII;
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun /* Setup proper MUXes along the path */
250*4882a593Smuzhiyun err = mtk_eth_mux_setup(eth, path);
251*4882a593Smuzhiyun if (err)
252*4882a593Smuzhiyun return err;
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun return 0;
255*4882a593Smuzhiyun }
256*4882a593Smuzhiyun
mtk_gmac_gephy_path_setup(struct mtk_eth * eth,int mac_id)257*4882a593Smuzhiyun int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id)
258*4882a593Smuzhiyun {
259*4882a593Smuzhiyun int err, path = 0;
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun if (mac_id == 1)
262*4882a593Smuzhiyun path = MTK_ETH_PATH_GMAC2_GEPHY;
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun if (!path)
265*4882a593Smuzhiyun return -EINVAL;
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun /* Setup proper MUXes along the path */
268*4882a593Smuzhiyun err = mtk_eth_mux_setup(eth, path);
269*4882a593Smuzhiyun if (err)
270*4882a593Smuzhiyun return err;
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun return 0;
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun
mtk_gmac_rgmii_path_setup(struct mtk_eth * eth,int mac_id)275*4882a593Smuzhiyun int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id)
276*4882a593Smuzhiyun {
277*4882a593Smuzhiyun int err, path;
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_RGMII :
280*4882a593Smuzhiyun MTK_ETH_PATH_GMAC2_RGMII;
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun /* Setup proper MUXes along the path */
283*4882a593Smuzhiyun err = mtk_eth_mux_setup(eth, path);
284*4882a593Smuzhiyun if (err)
285*4882a593Smuzhiyun return err;
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun return 0;
288*4882a593Smuzhiyun }
289*4882a593Smuzhiyun
290