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 15 struct mtk_eth_muxc { 16 const char *name; 17 int cap_bit; 18 int (*set_path)(struct mtk_eth *eth, int path); 19 }; 20 21 static 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 43 static 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 74 static 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 97 static 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 120 static 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 158 static 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 189 static 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 213 static 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 238 out: 239 return err; 240 } 241 242 int 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 257 int 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 275 int 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 290