Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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 err, 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	err = mtk_eth_mux_setup(eth, path);
251	if (err)
252		return err;
253
254	return 0;
255}
256
257int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id)
258{
259	int err, path = 0;
260
261	if (mac_id == 1)
262		path = MTK_ETH_PATH_GMAC2_GEPHY;
263
264	if (!path)
265		return -EINVAL;
266
267	/* Setup proper MUXes along the path */
268	err = mtk_eth_mux_setup(eth, path);
269	if (err)
270		return err;
271
272	return 0;
273}
274
275int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id)
276{
277	int err, path;
278
279	path = (mac_id == 0) ?  MTK_ETH_PATH_GMAC1_RGMII :
280				MTK_ETH_PATH_GMAC2_RGMII;
281
282	/* Setup proper MUXes along the path */
283	err = mtk_eth_mux_setup(eth, path);
284	if (err)
285		return err;
286
287	return 0;
288}
289