File Index
Files and directories
Sign in
FILE

mtk_eth_path.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/mediatek/mtk_eth_path.c C
  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
 15struct mtk_eth_muxc {
 16	const char	*name;
 17	u64		cap_bit;
 18	int		(*set_path)(struct mtk_eth *eth, u64 path);
 19};
 20
 21static const char *mtk_eth_path_name(u64 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_2P5GPHY:
 35		return "gmac2_2p5gphy";
 36	case MTK_ETH_PATH_GMAC2_GEPHY:
 37		return "gmac2_gephy";
 38	case MTK_ETH_PATH_GDM1_ESW:
 39		return "gdm1_esw";
 40	default:
 41		return "unknown path";
 42	}
 43}
 44
 45static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, u64 path)
 46{
 47	bool updated = true;
 48	u32 mask, set, reg;
 49
 50	switch (path) {
 51	case MTK_ETH_PATH_GMAC1_SGMII:
 52		mask = ~(u32)MTK_MUX_TO_ESW;
 53		set = 0;
 54		break;
 55	case MTK_ETH_PATH_GDM1_ESW:
 56		mask = ~(u32)MTK_MUX_TO_ESW;
 57		set = MTK_MUX_TO_ESW;
 58		break;
 59	default:
 60		updated = false;
 61		break;
 62	}
 63
 64	if (mtk_is_netsys_v3_or_greater(eth))
 65		reg = MTK_MAC_MISC_V3;
 66	else
 67		reg = MTK_MAC_MISC;
 68
 69	if (updated)
 70		mtk_m32(eth, mask, set, reg);
 71
 72	dev_dbg(eth->dev, "path %s in %s updated = %d\n",
 73		mtk_eth_path_name(path), __func__, updated);
 74
 75	return 0;
 76}
 77
 78static int set_mux_gmac2_gmac0_to_gephy(struct mtk_eth *eth, u64 path)
 79{
 80	unsigned int val = 0;
 81	bool updated = true;
 82
 83	switch (path) {
 84	case MTK_ETH_PATH_GMAC2_GEPHY:
 85		val = ~(u32)GEPHY_MAC_SEL;
 86		break;
 87	default:
 88		updated = false;
 89		break;
 90	}
 91
 92	if (updated)
 93		regmap_update_bits(eth->infra, INFRA_MISC2, GEPHY_MAC_SEL, val);
 94
 95	dev_dbg(eth->dev, "path %s in %s updated = %d\n",
 96		mtk_eth_path_name(path), __func__, updated);
 97
 98	return 0;
 99}
100
101static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, u64 path)
102{
103	unsigned int val = 0, mask = 0, reg = 0;
104	bool updated = true;
105
106	switch (path) {
107	case MTK_ETH_PATH_GMAC2_SGMII:
108		if (MTK_HAS_CAPS(eth->soc->caps, MTK_U3_COPHY_V2)) {
109			reg = USB_PHY_SWITCH_REG;
110			val = SGMII_QPHY_SEL;
111			mask = QPHY_SEL_MASK;
112		} else {
113			reg = INFRA_MISC2;
114			val = CO_QPHY_SEL;
115			mask = val;
116		}
117		break;
118	default:
119		updated = false;
120		break;
121	}
122
123	if (updated)
124		regmap_update_bits(eth->infra, reg, mask, val);
125
126	dev_dbg(eth->dev, "path %s in %s updated = %d\n",
127		mtk_eth_path_name(path), __func__, updated);
128
129	return 0;
130}
131
132static int set_mux_gmac2_to_2p5gphy(struct mtk_eth *eth, u64 path)
133{
134	int ret;
135
136	if (path == MTK_ETH_PATH_GMAC2_2P5GPHY) {
137		ret = regmap_clear_bits(eth->ethsys, ETHSYS_SYSCFG0,
138					SYSCFG0_SGMII_GMAC2_V2);
139		if (ret)
140			return ret;
141
142		/* Setup mux to 2p5g PHY */
143		ret = regmap_clear_bits(eth->infra, TOP_MISC_NETSYS_PCS_MUX,
144					MUX_G2_USXGMII_SEL);
145		if (ret)
146			return ret;
147
148		dev_dbg(eth->dev, "path %s in %s updated\n",
149			mtk_eth_path_name(path), __func__);
150	}
151
152	return 0;
153}
154
155static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, u64 path)
156{
157	unsigned int val = 0;
158	bool updated = true;
159
160	switch (path) {
161	case MTK_ETH_PATH_GMAC1_SGMII:
162		val = SYSCFG0_SGMII_GMAC1;
163		break;
164	case MTK_ETH_PATH_GMAC2_SGMII:
165		val = SYSCFG0_SGMII_GMAC2;
166		break;
167	case MTK_ETH_PATH_GMAC1_RGMII:
168	case MTK_ETH_PATH_GMAC2_RGMII:
169		regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
170		val &= SYSCFG0_SGMII_MASK;
171
172		if ((path == MTK_GMAC1_RGMII && val == SYSCFG0_SGMII_GMAC1) ||
173		    (path == MTK_GMAC2_RGMII && val == SYSCFG0_SGMII_GMAC2))
174			val = 0;
175		else
176			updated = false;
177		break;
178	default:
179		updated = false;
180		break;
181	}
182
183	if (updated)
184		regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
185				   SYSCFG0_SGMII_MASK, val);
186
187	dev_dbg(eth->dev, "path %s in %s updated = %d\n",
188		mtk_eth_path_name(path), __func__, updated);
189
190	return 0;
191}
192
193static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth *eth, u64 path)
194{
195	unsigned int val = 0;
196	bool updated = true;
197
198	regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
199
200	switch (path) {
201	case MTK_ETH_PATH_GMAC1_SGMII:
202		val |= SYSCFG0_SGMII_GMAC1_V2;
203		break;
204	case MTK_ETH_PATH_GMAC2_GEPHY:
205		val &= ~(u32)SYSCFG0_SGMII_GMAC2_V2;
206		break;
207	case MTK_ETH_PATH_GMAC2_SGMII:
208		val |= SYSCFG0_SGMII_GMAC2_V2;
209		break;
210	default:
211		updated = false;
212	}
213
214	if (updated)
215		regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
216				   SYSCFG0_SGMII_MASK, val);
217
218	dev_dbg(eth->dev, "path %s in %s updated = %d\n",
219		mtk_eth_path_name(path), __func__, updated);
220
221	return 0;
222}
223
224static const struct mtk_eth_muxc mtk_eth_muxc[] = {
225	{
226		.name = "mux_gdm1_to_gmac1_esw",
227		.cap_bit = MTK_ETH_MUX_GDM1_TO_GMAC1_ESW,
228		.set_path = set_mux_gdm1_to_gmac1_esw,
229	}, {
230		.name = "mux_gmac2_gmac0_to_gephy",
231		.cap_bit = MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY,
232		.set_path = set_mux_gmac2_gmac0_to_gephy,
233	}, {
234		.name = "mux_u3_gmac2_to_qphy",
235		.cap_bit = MTK_ETH_MUX_U3_GMAC2_TO_QPHY,
236		.set_path = set_mux_u3_gmac2_to_qphy,
237	}, {
238		.name = "mux_gmac2_to_2p5gphy",
239		.cap_bit = MTK_ETH_MUX_GMAC2_TO_2P5GPHY,
240		.set_path = set_mux_gmac2_to_2p5gphy,
241	}, {
242		.name = "mux_gmac1_gmac2_to_sgmii_rgmii",
243		.cap_bit = MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII,
244		.set_path = set_mux_gmac1_gmac2_to_sgmii_rgmii,
245	}, {
246		.name = "mux_gmac12_to_gephy_sgmii",
247		.cap_bit = MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII,
248		.set_path = set_mux_gmac12_to_gephy_sgmii,
249	},
250};
251
252static int mtk_eth_mux_setup(struct mtk_eth *eth, u64 path)
253{
254	int i, err = 0;
255
256	if (!MTK_HAS_CAPS(eth->soc->caps, path)) {
257		dev_err(eth->dev, "path %s isn't support on the SoC\n",
258			mtk_eth_path_name(path));
259		return -EINVAL;
260	}
261
262	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_MUX))
263		return 0;
264
265	/* Setup MUX in path fabric */
266	for (i = 0; i < ARRAY_SIZE(mtk_eth_muxc); i++) {
267		if (MTK_HAS_CAPS(eth->soc->caps, mtk_eth_muxc[i].cap_bit)) {
268			err = mtk_eth_muxc[i].set_path(eth, path);
269			if (err)
270				goto out;
271		} else {
272			dev_dbg(eth->dev, "mux %s isn't present on the SoC\n",
273				mtk_eth_muxc[i].name);
274		}
275	}
276
277out:
278	return err;
279}
280
281int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id)
282{
283	u64 path;
284
285	path = (mac_id == 0) ?  MTK_ETH_PATH_GMAC1_SGMII :
286				MTK_ETH_PATH_GMAC2_SGMII;
287
288	/* Setup proper MUXes along the path */
289	return mtk_eth_mux_setup(eth, path);
290}
291
292int mtk_gmac_2p5gphy_path_setup(struct mtk_eth *eth, int mac_id)
293{
294	u64 path = 0;
295
296	if (mac_id == MTK_GMAC2_ID)
297		path = MTK_ETH_PATH_GMAC2_2P5GPHY;
298
299	if (!path)
300		return -EINVAL;
301
302	/* Setup proper MUXes along the path */
303	return mtk_eth_mux_setup(eth, path);
304}
305
306int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id)
307{
308	u64 path = 0;
309
310	if (mac_id == 1)
311		path = MTK_ETH_PATH_GMAC2_GEPHY;
312
313	if (!path)
314		return -EINVAL;
315
316	/* Setup proper MUXes along the path */
317	return mtk_eth_mux_setup(eth, path);
318}
319
320int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id)
321{
322	u64 path;
323
324	path = (mac_id == 0) ?  MTK_ETH_PATH_GMAC1_RGMII :
325				MTK_ETH_PATH_GMAC2_RGMII;
326
327	/* Setup proper MUXes along the path */
328	return mtk_eth_mux_setup(eth, path);
329}
330
~/ Read-only file preview.