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 static int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id) 243 { 244 unsigned int val = 0; 245 int sid, err, path; 246 247 path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_SGMII : 248 MTK_ETH_PATH_GMAC2_SGMII; 249 250 /* Setup proper MUXes along the path */ 251 err = mtk_eth_mux_setup(eth, path); 252 if (err) 253 return err; 254 255 /* The path GMAC to SGMII will be enabled once the SGMIISYS is being 256 * setup done. 257 */ 258 regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val); 259 260 regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0, 261 SYSCFG0_SGMII_MASK, ~(u32)SYSCFG0_SGMII_MASK); 262 263 /* Decide how GMAC and SGMIISYS be mapped */ 264 sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ? 0 : mac_id; 265 266 /* Setup SGMIISYS with the determined property */ 267 if (MTK_HAS_FLAGS(eth->sgmii->flags[sid], MTK_SGMII_PHYSPEED_AN)) 268 err = mtk_sgmii_setup_mode_an(eth->sgmii, sid); 269 else 270 err = mtk_sgmii_setup_mode_force(eth->sgmii, sid); 271 272 if (err) 273 return err; 274 275 regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0, 276 SYSCFG0_SGMII_MASK, val); 277 278 return 0; 279 } 280 281 static int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id) 282 { 283 int err, path = 0; 284 285 if (mac_id == 1) 286 path = MTK_ETH_PATH_GMAC2_GEPHY; 287 288 if (!path) 289 return -EINVAL; 290 291 /* Setup proper MUXes along the path */ 292 err = mtk_eth_mux_setup(eth, path); 293 if (err) 294 return err; 295 296 return 0; 297 } 298 299 static int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id) 300 { 301 int err, path; 302 303 path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_RGMII : 304 MTK_ETH_PATH_GMAC2_RGMII; 305 306 /* Setup proper MUXes along the path */ 307 err = mtk_eth_mux_setup(eth, path); 308 if (err) 309 return err; 310 311 return 0; 312 } 313 314 int mtk_setup_hw_path(struct mtk_eth *eth, int mac_id, int phymode) 315 { 316 int err; 317 318 switch (phymode) { 319 case PHY_INTERFACE_MODE_TRGMII: 320 case PHY_INTERFACE_MODE_RGMII_TXID: 321 case PHY_INTERFACE_MODE_RGMII_RXID: 322 case PHY_INTERFACE_MODE_RGMII_ID: 323 case PHY_INTERFACE_MODE_RGMII: 324 case PHY_INTERFACE_MODE_MII: 325 case PHY_INTERFACE_MODE_REVMII: 326 case PHY_INTERFACE_MODE_RMII: 327 if (MTK_HAS_CAPS(eth->soc->caps, MTK_RGMII)) { 328 err = mtk_gmac_rgmii_path_setup(eth, mac_id); 329 if (err) 330 return err; 331 } 332 break; 333 case PHY_INTERFACE_MODE_SGMII: 334 if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII)) { 335 err = mtk_gmac_sgmii_path_setup(eth, mac_id); 336 if (err) 337 return err; 338 } 339 break; 340 case PHY_INTERFACE_MODE_GMII: 341 if (MTK_HAS_CAPS(eth->soc->caps, MTK_GEPHY)) { 342 err = mtk_gmac_gephy_path_setup(eth, mac_id); 343 if (err) 344 return err; 345 } 346 break; 347 default: 348 break; 349 } 350 351 return 0; 352 } 353