xref: /OK3568_Linux_fs/kernel/drivers/net/ethernet/mediatek/mtk_eth_path.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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