1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2018-2019 MediaTek Inc.
3 
4 /* A library for configuring path from GMAC/GDM to target PHY
5  *
6  * Author: Sean Wang <sean.wang@mediatek.com>
7  *
8  */
9 
10 #include <linux/phy.h>
11 #include <linux/regmap.h>
12 
13 #include "mtk_eth_soc.h"
14 
15 struct mtk_eth_muxc {
16 	const char	*name;
17 	int		cap_bit;
18 	int		(*set_path)(struct mtk_eth *eth, int path);
19 };
20 
21 static const char *mtk_eth_path_name(int path)
22 {
23 	switch (path) {
24 	case MTK_ETH_PATH_GMAC1_RGMII:
25 		return "gmac1_rgmii";
26 	case MTK_ETH_PATH_GMAC1_TRGMII:
27 		return "gmac1_trgmii";
28 	case MTK_ETH_PATH_GMAC1_SGMII:
29 		return "gmac1_sgmii";
30 	case MTK_ETH_PATH_GMAC2_RGMII:
31 		return "gmac2_rgmii";
32 	case MTK_ETH_PATH_GMAC2_SGMII:
33 		return "gmac2_sgmii";
34 	case MTK_ETH_PATH_GMAC2_GEPHY:
35 		return "gmac2_gephy";
36 	case MTK_ETH_PATH_GDM1_ESW:
37 		return "gdm1_esw";
38 	default:
39 		return "unknown path";
40 	}
41 }
42 
43 static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, int path)
44 {
45 	bool updated = true;
46 	u32 val, mask, set;
47 
48 	switch (path) {
49 	case MTK_ETH_PATH_GMAC1_SGMII:
50 		mask = ~(u32)MTK_MUX_TO_ESW;
51 		set = 0;
52 		break;
53 	case MTK_ETH_PATH_GDM1_ESW:
54 		mask = ~(u32)MTK_MUX_TO_ESW;
55 		set = MTK_MUX_TO_ESW;
56 		break;
57 	default:
58 		updated = false;
59 		break;
60 	};
61 
62 	if (updated) {
63 		val = mtk_r32(eth, MTK_MAC_MISC);
64 		val = (val & mask) | set;
65 		mtk_w32(eth, val, MTK_MAC_MISC);
66 	}
67 
68 	dev_dbg(eth->dev, "path %s in %s updated = %d\n",
69 		mtk_eth_path_name(path), __func__, updated);
70 
71 	return 0;
72 }
73 
74 static int set_mux_gmac2_gmac0_to_gephy(struct mtk_eth *eth, int path)
75 {
76 	unsigned int val = 0;
77 	bool updated = true;
78 
79 	switch (path) {
80 	case MTK_ETH_PATH_GMAC2_GEPHY:
81 		val = ~(u32)GEPHY_MAC_SEL;
82 		break;
83 	default:
84 		updated = false;
85 		break;
86 	}
87 
88 	if (updated)
89 		regmap_update_bits(eth->infra, INFRA_MISC2, GEPHY_MAC_SEL, val);
90 
91 	dev_dbg(eth->dev, "path %s in %s updated = %d\n",
92 		mtk_eth_path_name(path), __func__, updated);
93 
94 	return 0;
95 }
96 
97 static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, int path)
98 {
99 	unsigned int val = 0;
100 	bool updated = true;
101 
102 	switch (path) {
103 	case MTK_ETH_PATH_GMAC2_SGMII:
104 		val = CO_QPHY_SEL;
105 		break;
106 	default:
107 		updated = false;
108 		break;
109 	}
110 
111 	if (updated)
112 		regmap_update_bits(eth->infra, INFRA_MISC2, CO_QPHY_SEL, val);
113 
114 	dev_dbg(eth->dev, "path %s in %s updated = %d\n",
115 		mtk_eth_path_name(path), __func__, updated);
116 
117 	return 0;
118 }
119 
120 static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, int path)
121 {
122 	unsigned int val = 0;
123 	bool updated = true;
124 
125 	switch (path) {
126 	case MTK_ETH_PATH_GMAC1_SGMII:
127 		val = SYSCFG0_SGMII_GMAC1;
128 		break;
129 	case MTK_ETH_PATH_GMAC2_SGMII:
130 		val = SYSCFG0_SGMII_GMAC2;
131 		break;
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;
136 
137 		if ((path == MTK_GMAC1_RGMII && val == SYSCFG0_SGMII_GMAC1) ||
138 		    (path == MTK_GMAC2_RGMII && val == SYSCFG0_SGMII_GMAC2))
139 			val = 0;
140 		else
141 			updated = false;
142 		break;
143 	default:
144 		updated = false;
145 		break;
146 	};
147 
148 	if (updated)
149 		regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
150 				   SYSCFG0_SGMII_MASK, val);
151 
152 	dev_dbg(eth->dev, "path %s in %s updated = %d\n",
153 		mtk_eth_path_name(path), __func__, updated);
154 
155 	return 0;
156 }
157 
158 static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth *eth, int path)
159 {
160 	unsigned int val = 0;
161 	bool updated = true;
162 
163 	regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
164 
165 	switch (path) {
166 	case MTK_ETH_PATH_GMAC1_SGMII:
167 		val |= SYSCFG0_SGMII_GMAC1_V2;
168 		break;
169 	case MTK_ETH_PATH_GMAC2_GEPHY:
170 		val &= ~(u32)SYSCFG0_SGMII_GMAC2_V2;
171 		break;
172 	case MTK_ETH_PATH_GMAC2_SGMII:
173 		val |= SYSCFG0_SGMII_GMAC2_V2;
174 		break;
175 	default:
176 		updated = false;
177 	};
178 
179 	if (updated)
180 		regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
181 				   SYSCFG0_SGMII_MASK, val);
182 
183 	dev_dbg(eth->dev, "path %s in %s updated = %d\n",
184 		mtk_eth_path_name(path), __func__, updated);
185 
186 	return 0;
187 }
188 
189 static const struct mtk_eth_muxc mtk_eth_muxc[] = {
190 	{
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,
194 	}, {
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,
198 	}, {
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,
202 	}, {
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,
206 	}, {
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,
210 	},
211 };
212 
213 static int mtk_eth_mux_setup(struct mtk_eth *eth, int path)
214 {
215 	int i, err = 0;
216 
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));
220 		return -EINVAL;
221 	}
222 
223 	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_MUX))
224 		return 0;
225 
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);
230 			if (err)
231 				goto out;
232 		} else {
233 			dev_dbg(eth->dev, "mux %s isn't present on the SoC\n",
234 				mtk_eth_muxc[i].name);
235 		}
236 	}
237 
238 out:
239 	return err;
240 }
241 
242 static int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id)
243 {
244 	unsigned int val = 0;
245 	int sid, err, path;
246 
247 	path = (mac_id == 0) ?  MTK_ETH_PATH_GMAC1_SGMII :
248 				MTK_ETH_PATH_GMAC2_SGMII;
249 
250 	/* Setup proper MUXes along the path */
251 	err = mtk_eth_mux_setup(eth, path);
252 	if (err)
253 		return err;
254 
255 	/* The path GMAC to SGMII will be enabled once the SGMIISYS is being
256 	 * setup done.
257 	 */
258 	regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
259 
260 	regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
261 			   SYSCFG0_SGMII_MASK, ~(u32)SYSCFG0_SGMII_MASK);
262 
263 	/* Decide how GMAC and SGMIISYS be mapped */
264 	sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ? 0 : mac_id;
265 
266 	/* Setup SGMIISYS with the determined property */
267 	if (MTK_HAS_FLAGS(eth->sgmii->flags[sid], MTK_SGMII_PHYSPEED_AN))
268 		err = mtk_sgmii_setup_mode_an(eth->sgmii, sid);
269 	else
270 		err = mtk_sgmii_setup_mode_force(eth->sgmii, sid);
271 
272 	if (err)
273 		return err;
274 
275 	regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
276 			   SYSCFG0_SGMII_MASK, val);
277 
278 	return 0;
279 }
280 
281 static int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id)
282 {
283 	int err, path = 0;
284 
285 	if (mac_id == 1)
286 		path = MTK_ETH_PATH_GMAC2_GEPHY;
287 
288 	if (!path)
289 		return -EINVAL;
290 
291 	/* Setup proper MUXes along the path */
292 	err = mtk_eth_mux_setup(eth, path);
293 	if (err)
294 		return err;
295 
296 	return 0;
297 }
298 
299 static int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id)
300 {
301 	int err, path;
302 
303 	path = (mac_id == 0) ?  MTK_ETH_PATH_GMAC1_RGMII :
304 				MTK_ETH_PATH_GMAC2_RGMII;
305 
306 	/* Setup proper MUXes along the path */
307 	err = mtk_eth_mux_setup(eth, path);
308 	if (err)
309 		return err;
310 
311 	return 0;
312 }
313 
314 int mtk_setup_hw_path(struct mtk_eth *eth, int mac_id, int phymode)
315 {
316 	int err;
317 
318 	switch (phymode) {
319 	case PHY_INTERFACE_MODE_TRGMII:
320 	case PHY_INTERFACE_MODE_RGMII_TXID:
321 	case PHY_INTERFACE_MODE_RGMII_RXID:
322 	case PHY_INTERFACE_MODE_RGMII_ID:
323 	case PHY_INTERFACE_MODE_RGMII:
324 	case PHY_INTERFACE_MODE_MII:
325 	case PHY_INTERFACE_MODE_REVMII:
326 	case PHY_INTERFACE_MODE_RMII:
327 		if (MTK_HAS_CAPS(eth->soc->caps, MTK_RGMII)) {
328 			err = mtk_gmac_rgmii_path_setup(eth, mac_id);
329 			if (err)
330 				return err;
331 		}
332 		break;
333 	case PHY_INTERFACE_MODE_SGMII:
334 		if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII)) {
335 			err = mtk_gmac_sgmii_path_setup(eth, mac_id);
336 			if (err)
337 				return err;
338 		}
339 		break;
340 	case PHY_INTERFACE_MODE_GMII:
341 		if (MTK_HAS_CAPS(eth->soc->caps, MTK_GEPHY)) {
342 			err = mtk_gmac_gephy_path_setup(eth, mac_id);
343 			if (err)
344 				return err;
345 		}
346 		break;
347 	default:
348 		break;
349 	}
350 
351 	return 0;
352 }
353