0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/phy.h>
0011 #include <linux/regmap.h>
0012
0013 #include "mtk_eth_soc.h"
0014
0015 struct mtk_eth_muxc {
0016 const char *name;
0017 int cap_bit;
0018 int (*set_path)(struct mtk_eth *eth, int path);
0019 };
0020
0021 static const char *mtk_eth_path_name(int path)
0022 {
0023 switch (path) {
0024 case MTK_ETH_PATH_GMAC1_RGMII:
0025 return "gmac1_rgmii";
0026 case MTK_ETH_PATH_GMAC1_TRGMII:
0027 return "gmac1_trgmii";
0028 case MTK_ETH_PATH_GMAC1_SGMII:
0029 return "gmac1_sgmii";
0030 case MTK_ETH_PATH_GMAC2_RGMII:
0031 return "gmac2_rgmii";
0032 case MTK_ETH_PATH_GMAC2_SGMII:
0033 return "gmac2_sgmii";
0034 case MTK_ETH_PATH_GMAC2_GEPHY:
0035 return "gmac2_gephy";
0036 case MTK_ETH_PATH_GDM1_ESW:
0037 return "gdm1_esw";
0038 default:
0039 return "unknown path";
0040 }
0041 }
0042
0043 static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, int path)
0044 {
0045 bool updated = true;
0046 u32 val, mask, set;
0047
0048 switch (path) {
0049 case MTK_ETH_PATH_GMAC1_SGMII:
0050 mask = ~(u32)MTK_MUX_TO_ESW;
0051 set = 0;
0052 break;
0053 case MTK_ETH_PATH_GDM1_ESW:
0054 mask = ~(u32)MTK_MUX_TO_ESW;
0055 set = MTK_MUX_TO_ESW;
0056 break;
0057 default:
0058 updated = false;
0059 break;
0060 }
0061
0062 if (updated) {
0063 val = mtk_r32(eth, MTK_MAC_MISC);
0064 val = (val & mask) | set;
0065 mtk_w32(eth, val, MTK_MAC_MISC);
0066 }
0067
0068 dev_dbg(eth->dev, "path %s in %s updated = %d\n",
0069 mtk_eth_path_name(path), __func__, updated);
0070
0071 return 0;
0072 }
0073
0074 static int set_mux_gmac2_gmac0_to_gephy(struct mtk_eth *eth, int path)
0075 {
0076 unsigned int val = 0;
0077 bool updated = true;
0078
0079 switch (path) {
0080 case MTK_ETH_PATH_GMAC2_GEPHY:
0081 val = ~(u32)GEPHY_MAC_SEL;
0082 break;
0083 default:
0084 updated = false;
0085 break;
0086 }
0087
0088 if (updated)
0089 regmap_update_bits(eth->infra, INFRA_MISC2, GEPHY_MAC_SEL, val);
0090
0091 dev_dbg(eth->dev, "path %s in %s updated = %d\n",
0092 mtk_eth_path_name(path), __func__, updated);
0093
0094 return 0;
0095 }
0096
0097 static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, int path)
0098 {
0099 unsigned int val = 0;
0100 bool updated = true;
0101
0102 switch (path) {
0103 case MTK_ETH_PATH_GMAC2_SGMII:
0104 val = CO_QPHY_SEL;
0105 break;
0106 default:
0107 updated = false;
0108 break;
0109 }
0110
0111 if (updated)
0112 regmap_update_bits(eth->infra, INFRA_MISC2, CO_QPHY_SEL, val);
0113
0114 dev_dbg(eth->dev, "path %s in %s updated = %d\n",
0115 mtk_eth_path_name(path), __func__, updated);
0116
0117 return 0;
0118 }
0119
0120 static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, int path)
0121 {
0122 unsigned int val = 0;
0123 bool updated = true;
0124
0125 switch (path) {
0126 case MTK_ETH_PATH_GMAC1_SGMII:
0127 val = SYSCFG0_SGMII_GMAC1;
0128 break;
0129 case MTK_ETH_PATH_GMAC2_SGMII:
0130 val = SYSCFG0_SGMII_GMAC2;
0131 break;
0132 case MTK_ETH_PATH_GMAC1_RGMII:
0133 case MTK_ETH_PATH_GMAC2_RGMII:
0134 regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
0135 val &= SYSCFG0_SGMII_MASK;
0136
0137 if ((path == MTK_GMAC1_RGMII && val == SYSCFG0_SGMII_GMAC1) ||
0138 (path == MTK_GMAC2_RGMII && val == SYSCFG0_SGMII_GMAC2))
0139 val = 0;
0140 else
0141 updated = false;
0142 break;
0143 default:
0144 updated = false;
0145 break;
0146 }
0147
0148 if (updated)
0149 regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
0150 SYSCFG0_SGMII_MASK, val);
0151
0152 dev_dbg(eth->dev, "path %s in %s updated = %d\n",
0153 mtk_eth_path_name(path), __func__, updated);
0154
0155 return 0;
0156 }
0157
0158 static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth *eth, int path)
0159 {
0160 unsigned int val = 0;
0161 bool updated = true;
0162
0163 regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val);
0164
0165 switch (path) {
0166 case MTK_ETH_PATH_GMAC1_SGMII:
0167 val |= SYSCFG0_SGMII_GMAC1_V2;
0168 break;
0169 case MTK_ETH_PATH_GMAC2_GEPHY:
0170 val &= ~(u32)SYSCFG0_SGMII_GMAC2_V2;
0171 break;
0172 case MTK_ETH_PATH_GMAC2_SGMII:
0173 val |= SYSCFG0_SGMII_GMAC2_V2;
0174 break;
0175 default:
0176 updated = false;
0177 }
0178
0179 if (updated)
0180 regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
0181 SYSCFG0_SGMII_MASK, val);
0182
0183 dev_dbg(eth->dev, "path %s in %s updated = %d\n",
0184 mtk_eth_path_name(path), __func__, updated);
0185
0186 return 0;
0187 }
0188
0189 static const struct mtk_eth_muxc mtk_eth_muxc[] = {
0190 {
0191 .name = "mux_gdm1_to_gmac1_esw",
0192 .cap_bit = MTK_ETH_MUX_GDM1_TO_GMAC1_ESW,
0193 .set_path = set_mux_gdm1_to_gmac1_esw,
0194 }, {
0195 .name = "mux_gmac2_gmac0_to_gephy",
0196 .cap_bit = MTK_ETH_MUX_GMAC2_GMAC0_TO_GEPHY,
0197 .set_path = set_mux_gmac2_gmac0_to_gephy,
0198 }, {
0199 .name = "mux_u3_gmac2_to_qphy",
0200 .cap_bit = MTK_ETH_MUX_U3_GMAC2_TO_QPHY,
0201 .set_path = set_mux_u3_gmac2_to_qphy,
0202 }, {
0203 .name = "mux_gmac1_gmac2_to_sgmii_rgmii",
0204 .cap_bit = MTK_ETH_MUX_GMAC1_GMAC2_TO_SGMII_RGMII,
0205 .set_path = set_mux_gmac1_gmac2_to_sgmii_rgmii,
0206 }, {
0207 .name = "mux_gmac12_to_gephy_sgmii",
0208 .cap_bit = MTK_ETH_MUX_GMAC12_TO_GEPHY_SGMII,
0209 .set_path = set_mux_gmac12_to_gephy_sgmii,
0210 },
0211 };
0212
0213 static int mtk_eth_mux_setup(struct mtk_eth *eth, int path)
0214 {
0215 int i, err = 0;
0216
0217 if (!MTK_HAS_CAPS(eth->soc->caps, path)) {
0218 dev_err(eth->dev, "path %s isn't support on the SoC\n",
0219 mtk_eth_path_name(path));
0220 return -EINVAL;
0221 }
0222
0223 if (!MTK_HAS_CAPS(eth->soc->caps, MTK_MUX))
0224 return 0;
0225
0226
0227 for (i = 0; i < ARRAY_SIZE(mtk_eth_muxc); i++) {
0228 if (MTK_HAS_CAPS(eth->soc->caps, mtk_eth_muxc[i].cap_bit)) {
0229 err = mtk_eth_muxc[i].set_path(eth, path);
0230 if (err)
0231 goto out;
0232 } else {
0233 dev_dbg(eth->dev, "mux %s isn't present on the SoC\n",
0234 mtk_eth_muxc[i].name);
0235 }
0236 }
0237
0238 out:
0239 return err;
0240 }
0241
0242 int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id)
0243 {
0244 int path;
0245
0246 path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_SGMII :
0247 MTK_ETH_PATH_GMAC2_SGMII;
0248
0249
0250 return mtk_eth_mux_setup(eth, path);
0251 }
0252
0253 int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id)
0254 {
0255 int path = 0;
0256
0257 if (mac_id == 1)
0258 path = MTK_ETH_PATH_GMAC2_GEPHY;
0259
0260 if (!path)
0261 return -EINVAL;
0262
0263
0264 return mtk_eth_mux_setup(eth, path);
0265 }
0266
0267 int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id)
0268 {
0269 int path;
0270
0271 path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_RGMII :
0272 MTK_ETH_PATH_GMAC2_RGMII;
0273
0274
0275 return mtk_eth_mux_setup(eth, path);
0276 }
0277