brintos

brintos / linux-shallow public Read only

0
0
Text · 6.0 KiB · 7c27a19 Raw
288 lines · c
1// SPDX-License-Identifier: GPL-2.02// Copyright (c) 2018-2019 MediaTek Inc.3 4/* A library for configuring path from GMAC/GDM to target PHY5 *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	else65		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		else151			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 288