Linux Audio

Check our new training course

Loading...
v6.8
  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	int		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_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
 43static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, u64 path)
 44{
 45	bool updated = true;
 46	u32 mask, set, reg;
 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 (mtk_is_netsys_v3_or_greater(eth))
 63		reg = MTK_MAC_MISC_V3;
 64	else
 65		reg = MTK_MAC_MISC;
 66
 67	if (updated)
 68		mtk_m32(eth, mask, set, reg);
 69
 70	dev_dbg(eth->dev, "path %s in %s updated = %d\n",
 71		mtk_eth_path_name(path), __func__, updated);
 72
 73	return 0;
 74}
 75
 76static int set_mux_gmac2_gmac0_to_gephy(struct mtk_eth *eth, u64 path)
 77{
 78	unsigned int val = 0;
 79	bool updated = true;
 80
 81	switch (path) {
 82	case MTK_ETH_PATH_GMAC2_GEPHY:
 83		val = ~(u32)GEPHY_MAC_SEL;
 84		break;
 85	default:
 86		updated = false;
 87		break;
 88	}
 89
 90	if (updated)
 91		regmap_update_bits(eth->infra, INFRA_MISC2, GEPHY_MAC_SEL, val);
 92
 93	dev_dbg(eth->dev, "path %s in %s updated = %d\n",
 94		mtk_eth_path_name(path), __func__, updated);
 95
 96	return 0;
 97}
 98
 99static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, u64 path)
100{
101	unsigned int val = 0, mask = 0, reg = 0;
102	bool updated = true;
103
104	switch (path) {
105	case MTK_ETH_PATH_GMAC2_SGMII:
106		if (MTK_HAS_CAPS(eth->soc->caps, MTK_U3_COPHY_V2)) {
107			reg = USB_PHY_SWITCH_REG;
108			val = SGMII_QPHY_SEL;
109			mask = QPHY_SEL_MASK;
110		} else {
111			reg = INFRA_MISC2;
112			val = CO_QPHY_SEL;
113			mask = val;
114		}
115		break;
116	default:
117		updated = false;
118		break;
119	}
120
121	if (updated)
122		regmap_update_bits(eth->infra, reg, mask, val);
123
124	dev_dbg(eth->dev, "path %s in %s updated = %d\n",
125		mtk_eth_path_name(path), __func__, updated);
126
127	return 0;
128}
129
130static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, u64 path)
131{
132	unsigned int val = 0;
133	bool updated = true;
134
135	switch (path) {
136	case MTK_ETH_PATH_GMAC1_SGMII:
137		val = SYSCFG0_SGMII_GMAC1;
138		break;
139	case MTK_ETH_PATH_GMAC2_SGMII:
140		val = SYSCFG0_SGMII_GMAC2;
141		break;
142	case MTK_ETH_PATH_GMAC1_RGMII:
143	case MTK_ETH_PATH_GMAC2_RGMII:
144		regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
145		val &= SYSCFG0_SGMII_MASK;
146
147		if ((path == MTK_GMAC1_RGMII && val == SYSCFG0_SGMII_GMAC1) ||
148		    (path == MTK_GMAC2_RGMII && val == SYSCFG0_SGMII_GMAC2))
149			val = 0;
150		else
151			updated = false;
152		break;
153	default:
154		updated = false;
155		break;
156	}
157
158	if (updated)
159		regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
160				   SYSCFG0_SGMII_MASK, val);
161
162	dev_dbg(eth->dev, "path %s in %s updated = %d\n",
163		mtk_eth_path_name(path), __func__, updated);
164
165	return 0;
166}
167
168static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth *eth, u64 path)
169{
170	unsigned int val = 0;
171	bool updated = true;
172
173	regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
174
175	switch (path) {
176	case MTK_ETH_PATH_GMAC1_SGMII:
177		val |= SYSCFG0_SGMII_GMAC1_V2;
178		break;
179	case MTK_ETH_PATH_GMAC2_GEPHY:
180		val &= ~(u32)SYSCFG0_SGMII_GMAC2_V2;
181		break;
182	case MTK_ETH_PATH_GMAC2_SGMII:
183		val |= SYSCFG0_SGMII_GMAC2_V2;
184		break;
185	default:
186		updated = false;
187	}
188
189	if (updated)
190		regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
191				   SYSCFG0_SGMII_MASK, val);
192
193	dev_dbg(eth->dev, "path %s in %s updated = %d\n",
194		mtk_eth_path_name(path), __func__, updated);
195
196	return 0;
197}
198
199static const struct mtk_eth_muxc mtk_eth_muxc[] = {
200	{
201		.name = "mux_gdm1_to_gmac1_esw",
202		.cap_bit = MTK_ETH_MUX_GDM1_TO_GMAC1_ESW,
203		.set_path = set_mux_gdm1_to_gmac1_esw,
204	}, {
205		.name = "mux_gmac2_gmac0_to_gephy",
206		.cap_bit = MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY,
207		.set_path = set_mux_gmac2_gmac0_to_gephy,
208	}, {
209		.name = "mux_u3_gmac2_to_qphy",
210		.cap_bit = MTK_ETH_MUX_U3_GMAC2_TO_QPHY,
211		.set_path = set_mux_u3_gmac2_to_qphy,
212	}, {
213		.name = "mux_gmac1_gmac2_to_sgmii_rgmii",
214		.cap_bit = MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII,
215		.set_path = set_mux_gmac1_gmac2_to_sgmii_rgmii,
216	}, {
217		.name = "mux_gmac12_to_gephy_sgmii",
218		.cap_bit = MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII,
219		.set_path = set_mux_gmac12_to_gephy_sgmii,
220	},
221};
222
223static int mtk_eth_mux_setup(struct mtk_eth *eth, u64 path)
224{
225	int i, err = 0;
226
227	if (!MTK_HAS_CAPS(eth->soc->caps, path)) {
228		dev_err(eth->dev, "path %s isn't support on the SoC\n",
229			mtk_eth_path_name(path));
230		return -EINVAL;
231	}
232
233	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_MUX))
234		return 0;
235
236	/* Setup MUX in path fabric */
237	for (i = 0; i < ARRAY_SIZE(mtk_eth_muxc); i++) {
238		if (MTK_HAS_CAPS(eth->soc->caps, mtk_eth_muxc[i].cap_bit)) {
239			err = mtk_eth_muxc[i].set_path(eth, path);
240			if (err)
241				goto out;
242		} else {
243			dev_dbg(eth->dev, "mux %s isn't present on the SoC\n",
244				mtk_eth_muxc[i].name);
245		}
246	}
247
248out:
249	return err;
250}
251
252int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id)
253{
254	u64 path;
255
256	path = (mac_id == 0) ?  MTK_ETH_PATH_GMAC1_SGMII :
257				MTK_ETH_PATH_GMAC2_SGMII;
258
259	/* Setup proper MUXes along the path */
260	return mtk_eth_mux_setup(eth, path);
261}
262
263int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id)
264{
265	u64 path = 0;
266
267	if (mac_id == 1)
268		path = MTK_ETH_PATH_GMAC2_GEPHY;
269
270	if (!path)
271		return -EINVAL;
272
273	/* Setup proper MUXes along the path */
274	return mtk_eth_mux_setup(eth, path);
275}
276
277int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id)
278{
279	u64 path;
280
281	path = (mac_id == 0) ?  MTK_ETH_PATH_GMAC1_RGMII :
282				MTK_ETH_PATH_GMAC2_RGMII;
283
284	/* Setup proper MUXes along the path */
285	return mtk_eth_mux_setup(eth, path);
286}
287
v5.14.15
  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	int		cap_bit;
 18	int		(*set_path)(struct mtk_eth *eth, int path);
 19};
 20
 21static 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
 43static 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
 74static 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
 97static 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
120static 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
158static 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
189static 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
213static 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
238out:
239	return err;
240}
241
242int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id)
243{
244	int path;
245
246	path = (mac_id == 0) ?  MTK_ETH_PATH_GMAC1_SGMII :
247				MTK_ETH_PATH_GMAC2_SGMII;
248
249	/* Setup proper MUXes along the path */
250	return mtk_eth_mux_setup(eth, path);
251}
252
253int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id)
254{
255	int path = 0;
256
257	if (mac_id == 1)
258		path = MTK_ETH_PATH_GMAC2_GEPHY;
259
260	if (!path)
261		return -EINVAL;
262
263	/* Setup proper MUXes along the path */
264	return mtk_eth_mux_setup(eth, path);
265}
266
267int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id)
268{
269	int path;
270
271	path = (mac_id == 0) ?  MTK_ETH_PATH_GMAC1_RGMII :
272				MTK_ETH_PATH_GMAC2_RGMII;
273
274	/* Setup proper MUXes along the path */
275	return mtk_eth_mux_setup(eth, path);
276}
277