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 int (*set_path)(struct mtk_eth *eth, int path); 17 }; 18 19 static const char * const mtk_eth_mux_name[] = { 20 "mux_gdm1_to_gmac1_esw", "mux_gmac2_gmac0_to_gephy", 21 "mux_u3_gmac2_to_qphy", "mux_gmac1_gmac2_to_sgmii_rgmii", 22 "mux_gmac12_to_gephy_sgmii", 23 }; 24 25 static const char * const mtk_eth_path_name[] = { 26 "gmac1_rgmii", "gmac1_trgmii", "gmac1_sgmii", "gmac2_rgmii", 27 "gmac2_sgmii", "gmac2_gephy", "gdm1_esw", 28 }; 29 30 static int set_mux_gdm1_to_gmac1_esw(struct mtk_eth *eth, int path) 31 { 32 bool updated = true; 33 u32 val, mask, set; 34 35 switch (path) { 36 case MTK_ETH_PATH_GMAC1_SGMII: 37 mask = ~(u32)MTK_MUX_TO_ESW; 38 set = 0; 39 break; 40 case MTK_ETH_PATH_GDM1_ESW: 41 mask = ~(u32)MTK_MUX_TO_ESW; 42 set = MTK_MUX_TO_ESW; 43 break; 44 default: 45 updated = false; 46 break; 47 }; 48 49 if (updated) { 50 val = mtk_r32(eth, MTK_MAC_MISC); 51 val = (val & mask) | set; 52 mtk_w32(eth, val, MTK_MAC_MISC); 53 } 54 55 dev_dbg(eth->dev, "path %s in %s updated = %d\n", 56 mtk_eth_path_name[path], __func__, updated); 57 58 return 0; 59 } 60 61 static int set_mux_gmac2_gmac0_to_gephy(struct mtk_eth *eth, int path) 62 { 63 unsigned int val = 0; 64 bool updated = true; 65 66 switch (path) { 67 case MTK_ETH_PATH_GMAC2_GEPHY: 68 val = ~(u32)GEPHY_MAC_SEL; 69 break; 70 default: 71 updated = false; 72 break; 73 } 74 75 if (updated) 76 regmap_update_bits(eth->infra, INFRA_MISC2, GEPHY_MAC_SEL, val); 77 78 dev_dbg(eth->dev, "path %s in %s updated = %d\n", 79 mtk_eth_path_name[path], __func__, updated); 80 81 return 0; 82 } 83 84 static int set_mux_u3_gmac2_to_qphy(struct mtk_eth *eth, int path) 85 { 86 unsigned int val = 0; 87 bool updated = true; 88 89 switch (path) { 90 case MTK_ETH_PATH_GMAC2_SGMII: 91 val = CO_QPHY_SEL; 92 break; 93 default: 94 updated = false; 95 break; 96 } 97 98 if (updated) 99 regmap_update_bits(eth->infra, INFRA_MISC2, CO_QPHY_SEL, val); 100 101 dev_dbg(eth->dev, "path %s in %s updated = %d\n", 102 mtk_eth_path_name[path], __func__, updated); 103 104 return 0; 105 } 106 107 static int set_mux_gmac1_gmac2_to_sgmii_rgmii(struct mtk_eth *eth, int path) 108 { 109 unsigned int val = 0; 110 bool updated = true; 111 112 switch (path) { 113 case MTK_ETH_PATH_GMAC1_SGMII: 114 val = SYSCFG0_SGMII_GMAC1; 115 break; 116 case MTK_ETH_PATH_GMAC2_SGMII: 117 val = SYSCFG0_SGMII_GMAC2; 118 break; 119 case MTK_ETH_PATH_GMAC1_RGMII: 120 case MTK_ETH_PATH_GMAC2_RGMII: 121 regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val); 122 val &= SYSCFG0_SGMII_MASK; 123 124 if ((path == MTK_GMAC1_RGMII && val == SYSCFG0_SGMII_GMAC1) || 125 (path == MTK_GMAC2_RGMII && val == SYSCFG0_SGMII_GMAC2)) 126 val = 0; 127 else 128 updated = false; 129 break; 130 default: 131 updated = false; 132 break; 133 }; 134 135 if (updated) 136 regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0, 137 SYSCFG0_SGMII_MASK, val); 138 139 dev_dbg(eth->dev, "path %s in %s updated = %d\n", 140 mtk_eth_path_name[path], __func__, updated); 141 142 return 0; 143 } 144 145 static int set_mux_gmac12_to_gephy_sgmii(struct mtk_eth *eth, int path) 146 { 147 unsigned int val = 0; 148 bool updated = true; 149 150 regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val); 151 152 switch (path) { 153 case MTK_ETH_PATH_GMAC1_SGMII: 154 val |= SYSCFG0_SGMII_GMAC1_V2; 155 break; 156 case MTK_ETH_PATH_GMAC2_GEPHY: 157 val &= ~(u32)SYSCFG0_SGMII_GMAC2_V2; 158 break; 159 case MTK_ETH_PATH_GMAC2_SGMII: 160 val |= SYSCFG0_SGMII_GMAC2_V2; 161 break; 162 default: 163 updated = false; 164 }; 165 166 if (updated) 167 regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0, 168 SYSCFG0_SGMII_MASK, val); 169 170 dev_dbg(eth->dev, "path %s in %s updated = %d\n", 171 mtk_eth_path_name[path], __func__, updated); 172 173 return 0; 174 } 175 176 static const struct mtk_eth_muxc mtk_eth_muxc[] = { 177 { .set_path = set_mux_gdm1_to_gmac1_esw, }, 178 { .set_path = set_mux_gmac2_gmac0_to_gephy, }, 179 { .set_path = set_mux_u3_gmac2_to_qphy, }, 180 { .set_path = set_mux_gmac1_gmac2_to_sgmii_rgmii, }, 181 { .set_path = set_mux_gmac12_to_gephy_sgmii, } 182 }; 183 184 static int mtk_eth_mux_setup(struct mtk_eth *eth, int path) 185 { 186 int i, err = 0; 187 188 if (!MTK_HAS_CAPS(eth->soc->caps, MTK_PATH_BIT(path))) { 189 dev_err(eth->dev, "path %s isn't support on the SoC\n", 190 mtk_eth_path_name[path]); 191 return -EINVAL; 192 } 193 194 if (!MTK_HAS_CAPS(eth->soc->caps, MTK_MUX)) 195 return 0; 196 197 /* Setup MUX in path fabric */ 198 for (i = 0; i < MTK_ETH_MUX_MAX; i++) { 199 if (MTK_HAS_CAPS(eth->soc->caps, MTK_MUX_BIT(i))) { 200 err = mtk_eth_muxc[i].set_path(eth, path); 201 if (err) 202 goto out; 203 } else { 204 dev_dbg(eth->dev, "mux %s isn't present on the SoC\n", 205 mtk_eth_mux_name[i]); 206 } 207 } 208 209 out: 210 return err; 211 } 212 213 static int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id) 214 { 215 unsigned int val = 0; 216 int sid, err, path; 217 218 path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_SGMII : 219 MTK_ETH_PATH_GMAC2_SGMII; 220 221 /* Setup proper MUXes along the path */ 222 err = mtk_eth_mux_setup(eth, path); 223 if (err) 224 return err; 225 226 /* The path GMAC to SGMII will be enabled once the SGMIISYS is being 227 * setup done. 228 */ 229 regmap_read(eth->ethsys, ETHSYS_SYSCFG0, &val); 230 231 regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0, 232 SYSCFG0_SGMII_MASK, ~(u32)SYSCFG0_SGMII_MASK); 233 234 /* Decide how GMAC and SGMIISYS be mapped */ 235 sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ? 0 : mac_id; 236 237 /* Setup SGMIISYS with the determined property */ 238 if (MTK_HAS_FLAGS(eth->sgmii->flags[sid], MTK_SGMII_PHYSPEED_AN)) 239 err = mtk_sgmii_setup_mode_an(eth->sgmii, sid); 240 else 241 err = mtk_sgmii_setup_mode_force(eth->sgmii, sid); 242 243 if (err) 244 return err; 245 246 regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0, 247 SYSCFG0_SGMII_MASK, val); 248 249 return 0; 250 } 251 252 static int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id) 253 { 254 int err, path = 0; 255 256 if (mac_id == 1) 257 path = MTK_ETH_PATH_GMAC2_GEPHY; 258 259 if (!path) 260 return -EINVAL; 261 262 /* Setup proper MUXes along the path */ 263 err = mtk_eth_mux_setup(eth, path); 264 if (err) 265 return err; 266 267 return 0; 268 } 269 270 static int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id) 271 { 272 int err, path; 273 274 path = (mac_id == 0) ? MTK_ETH_PATH_GMAC1_RGMII : 275 MTK_ETH_PATH_GMAC2_RGMII; 276 277 /* Setup proper MUXes along the path */ 278 err = mtk_eth_mux_setup(eth, path); 279 if (err) 280 return err; 281 282 return 0; 283 } 284 285 int mtk_setup_hw_path(struct mtk_eth *eth, int mac_id, int phymode) 286 { 287 int err; 288 289 switch (phymode) { 290 case PHY_INTERFACE_MODE_TRGMII: 291 case PHY_INTERFACE_MODE_RGMII_TXID: 292 case PHY_INTERFACE_MODE_RGMII_RXID: 293 case PHY_INTERFACE_MODE_RGMII_ID: 294 case PHY_INTERFACE_MODE_RGMII: 295 case PHY_INTERFACE_MODE_MII: 296 case PHY_INTERFACE_MODE_REVMII: 297 case PHY_INTERFACE_MODE_RMII: 298 if (MTK_HAS_CAPS(eth->soc->caps, MTK_RGMII)) { 299 err = mtk_gmac_rgmii_path_setup(eth, mac_id); 300 if (err) 301 return err; 302 } 303 break; 304 case PHY_INTERFACE_MODE_SGMII: 305 if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII)) { 306 err = mtk_gmac_sgmii_path_setup(eth, mac_id); 307 if (err) 308 return err; 309 } 310 break; 311 case PHY_INTERFACE_MODE_GMII: 312 if (MTK_HAS_CAPS(eth->soc->caps, MTK_GEPHY)) { 313 err = mtk_gmac_gephy_path_setup(eth, mac_id); 314 if (err) 315 return err; 316 } 317 break; 318 default: 319 break; 320 } 321 322 return 0; 323 } 324