1 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) 2 /* Copyright 2019 NXP */ 3 4 #include "dpaa2-eth.h" 5 #include "dpaa2-mac.h" 6 7 #define phylink_to_dpaa2_mac(config) \ 8 container_of((config), struct dpaa2_mac, phylink_config) 9 10 static int phy_mode(enum dpmac_eth_if eth_if, phy_interface_t *if_mode) 11 { 12 *if_mode = PHY_INTERFACE_MODE_NA; 13 14 switch (eth_if) { 15 case DPMAC_ETH_IF_RGMII: 16 *if_mode = PHY_INTERFACE_MODE_RGMII; 17 break; 18 case DPMAC_ETH_IF_USXGMII: 19 *if_mode = PHY_INTERFACE_MODE_USXGMII; 20 break; 21 case DPMAC_ETH_IF_QSGMII: 22 *if_mode = PHY_INTERFACE_MODE_QSGMII; 23 break; 24 case DPMAC_ETH_IF_SGMII: 25 *if_mode = PHY_INTERFACE_MODE_SGMII; 26 break; 27 case DPMAC_ETH_IF_XFI: 28 *if_mode = PHY_INTERFACE_MODE_10GBASER; 29 break; 30 default: 31 return -EINVAL; 32 } 33 34 return 0; 35 } 36 37 /* Caller must call of_node_put on the returned value */ 38 static struct device_node *dpaa2_mac_get_node(u16 dpmac_id) 39 { 40 struct device_node *dpmacs, *dpmac = NULL; 41 u32 id; 42 int err; 43 44 dpmacs = of_find_node_by_name(NULL, "dpmacs"); 45 if (!dpmacs) 46 return NULL; 47 48 while ((dpmac = of_get_next_child(dpmacs, dpmac)) != NULL) { 49 err = of_property_read_u32(dpmac, "reg", &id); 50 if (err) 51 continue; 52 if (id == dpmac_id) 53 break; 54 } 55 56 of_node_put(dpmacs); 57 58 return dpmac; 59 } 60 61 static int dpaa2_mac_get_if_mode(struct device_node *node, 62 struct dpmac_attr attr) 63 { 64 phy_interface_t if_mode; 65 int err; 66 67 err = of_get_phy_mode(node, &if_mode); 68 if (!err) 69 return if_mode; 70 71 err = phy_mode(attr.eth_if, &if_mode); 72 if (!err) 73 return if_mode; 74 75 return err; 76 } 77 78 static bool dpaa2_mac_phy_mode_mismatch(struct dpaa2_mac *mac, 79 phy_interface_t interface) 80 { 81 switch (interface) { 82 case PHY_INTERFACE_MODE_10GBASER: 83 case PHY_INTERFACE_MODE_USXGMII: 84 case PHY_INTERFACE_MODE_QSGMII: 85 case PHY_INTERFACE_MODE_SGMII: 86 case PHY_INTERFACE_MODE_RGMII: 87 case PHY_INTERFACE_MODE_RGMII_ID: 88 case PHY_INTERFACE_MODE_RGMII_RXID: 89 case PHY_INTERFACE_MODE_RGMII_TXID: 90 return (interface != mac->if_mode); 91 default: 92 return true; 93 } 94 } 95 96 static void dpaa2_mac_validate(struct phylink_config *config, 97 unsigned long *supported, 98 struct phylink_link_state *state) 99 { 100 struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config); 101 __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; 102 103 if (state->interface != PHY_INTERFACE_MODE_NA && 104 dpaa2_mac_phy_mode_mismatch(mac, state->interface)) { 105 goto empty_set; 106 } 107 108 phylink_set_port_modes(mask); 109 phylink_set(mask, Autoneg); 110 phylink_set(mask, Pause); 111 phylink_set(mask, Asym_Pause); 112 113 switch (state->interface) { 114 case PHY_INTERFACE_MODE_NA: 115 case PHY_INTERFACE_MODE_10GBASER: 116 case PHY_INTERFACE_MODE_USXGMII: 117 phylink_set(mask, 10000baseT_Full); 118 if (state->interface == PHY_INTERFACE_MODE_10GBASER) 119 break; 120 phylink_set(mask, 5000baseT_Full); 121 phylink_set(mask, 2500baseT_Full); 122 fallthrough; 123 case PHY_INTERFACE_MODE_SGMII: 124 case PHY_INTERFACE_MODE_QSGMII: 125 case PHY_INTERFACE_MODE_RGMII: 126 case PHY_INTERFACE_MODE_RGMII_ID: 127 case PHY_INTERFACE_MODE_RGMII_RXID: 128 case PHY_INTERFACE_MODE_RGMII_TXID: 129 phylink_set(mask, 10baseT_Full); 130 phylink_set(mask, 100baseT_Full); 131 phylink_set(mask, 1000baseT_Full); 132 break; 133 default: 134 goto empty_set; 135 } 136 137 linkmode_and(supported, supported, mask); 138 linkmode_and(state->advertising, state->advertising, mask); 139 140 return; 141 142 empty_set: 143 linkmode_zero(supported); 144 } 145 146 static void dpaa2_mac_config(struct phylink_config *config, unsigned int mode, 147 const struct phylink_link_state *state) 148 { 149 struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config); 150 struct dpmac_link_state *dpmac_state = &mac->state; 151 int err; 152 153 if (state->an_enabled) 154 dpmac_state->options |= DPMAC_LINK_OPT_AUTONEG; 155 else 156 dpmac_state->options &= ~DPMAC_LINK_OPT_AUTONEG; 157 158 err = dpmac_set_link_state(mac->mc_io, 0, 159 mac->mc_dev->mc_handle, dpmac_state); 160 if (err) 161 netdev_err(mac->net_dev, "%s: dpmac_set_link_state() = %d\n", 162 __func__, err); 163 } 164 165 static void dpaa2_mac_link_up(struct phylink_config *config, 166 struct phy_device *phy, 167 unsigned int mode, phy_interface_t interface, 168 int speed, int duplex, 169 bool tx_pause, bool rx_pause) 170 { 171 struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config); 172 struct dpmac_link_state *dpmac_state = &mac->state; 173 int err; 174 175 dpmac_state->up = 1; 176 177 if (mac->if_link_type == DPMAC_LINK_TYPE_PHY) { 178 /* If the DPMAC is configured for PHY mode, we need 179 * to pass the link parameters to the MC firmware. 180 */ 181 dpmac_state->rate = speed; 182 183 if (duplex == DUPLEX_HALF) 184 dpmac_state->options |= DPMAC_LINK_OPT_HALF_DUPLEX; 185 else if (duplex == DUPLEX_FULL) 186 dpmac_state->options &= ~DPMAC_LINK_OPT_HALF_DUPLEX; 187 188 /* This is lossy; the firmware really should take the pause 189 * enablement status rather than pause/asym pause status. 190 */ 191 if (rx_pause) 192 dpmac_state->options |= DPMAC_LINK_OPT_PAUSE; 193 else 194 dpmac_state->options &= ~DPMAC_LINK_OPT_PAUSE; 195 196 if (rx_pause ^ tx_pause) 197 dpmac_state->options |= DPMAC_LINK_OPT_ASYM_PAUSE; 198 else 199 dpmac_state->options &= ~DPMAC_LINK_OPT_ASYM_PAUSE; 200 } 201 202 err = dpmac_set_link_state(mac->mc_io, 0, 203 mac->mc_dev->mc_handle, dpmac_state); 204 if (err) 205 netdev_err(mac->net_dev, "%s: dpmac_set_link_state() = %d\n", 206 __func__, err); 207 } 208 209 static void dpaa2_mac_link_down(struct phylink_config *config, 210 unsigned int mode, 211 phy_interface_t interface) 212 { 213 struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config); 214 struct dpmac_link_state *dpmac_state = &mac->state; 215 int err; 216 217 dpmac_state->up = 0; 218 err = dpmac_set_link_state(mac->mc_io, 0, 219 mac->mc_dev->mc_handle, dpmac_state); 220 if (err) 221 netdev_err(mac->net_dev, "dpmac_set_link_state() = %d\n", err); 222 } 223 224 static const struct phylink_mac_ops dpaa2_mac_phylink_ops = { 225 .validate = dpaa2_mac_validate, 226 .mac_config = dpaa2_mac_config, 227 .mac_link_up = dpaa2_mac_link_up, 228 .mac_link_down = dpaa2_mac_link_down, 229 }; 230 231 bool dpaa2_mac_is_type_fixed(struct fsl_mc_device *dpmac_dev, 232 struct fsl_mc_io *mc_io) 233 { 234 struct dpmac_attr attr; 235 bool fixed = false; 236 u16 mc_handle = 0; 237 int err; 238 239 err = dpmac_open(mc_io, 0, dpmac_dev->obj_desc.id, 240 &mc_handle); 241 if (err || !mc_handle) 242 return false; 243 244 err = dpmac_get_attributes(mc_io, 0, mc_handle, &attr); 245 if (err) 246 goto out; 247 248 if (attr.link_type == DPMAC_LINK_TYPE_FIXED) 249 fixed = true; 250 251 out: 252 dpmac_close(mc_io, 0, mc_handle); 253 254 return fixed; 255 } 256 257 static int dpaa2_pcs_create(struct dpaa2_mac *mac, 258 struct device_node *dpmac_node, int id) 259 { 260 struct mdio_device *mdiodev; 261 struct device_node *node; 262 263 node = of_parse_phandle(dpmac_node, "pcs-handle", 0); 264 if (!node) { 265 /* do not error out on old DTS files */ 266 netdev_warn(mac->net_dev, "pcs-handle node not found\n"); 267 return 0; 268 } 269 270 if (!of_device_is_available(node)) { 271 netdev_err(mac->net_dev, "pcs-handle node not available\n"); 272 return -ENODEV; 273 } 274 275 mdiodev = of_mdio_find_device(node); 276 of_node_put(node); 277 if (!mdiodev) 278 return -EPROBE_DEFER; 279 280 mac->pcs = lynx_pcs_create(mdiodev); 281 if (!mac->pcs) { 282 netdev_err(mac->net_dev, "lynx_pcs_create() failed\n"); 283 put_device(&mdiodev->dev); 284 return -ENOMEM; 285 } 286 287 return 0; 288 } 289 290 static void dpaa2_pcs_destroy(struct dpaa2_mac *mac) 291 { 292 struct lynx_pcs *pcs = mac->pcs; 293 294 if (pcs) { 295 struct device *dev = &pcs->mdio->dev; 296 lynx_pcs_destroy(pcs); 297 put_device(dev); 298 mac->pcs = NULL; 299 } 300 } 301 302 int dpaa2_mac_connect(struct dpaa2_mac *mac) 303 { 304 struct fsl_mc_device *dpmac_dev = mac->mc_dev; 305 struct net_device *net_dev = mac->net_dev; 306 struct device_node *dpmac_node; 307 struct phylink *phylink; 308 struct dpmac_attr attr; 309 int err; 310 311 err = dpmac_open(mac->mc_io, 0, dpmac_dev->obj_desc.id, 312 &dpmac_dev->mc_handle); 313 if (err || !dpmac_dev->mc_handle) { 314 netdev_err(net_dev, "dpmac_open() = %d\n", err); 315 return -ENODEV; 316 } 317 318 err = dpmac_get_attributes(mac->mc_io, 0, dpmac_dev->mc_handle, &attr); 319 if (err) { 320 netdev_err(net_dev, "dpmac_get_attributes() = %d\n", err); 321 goto err_close_dpmac; 322 } 323 324 mac->if_link_type = attr.link_type; 325 326 dpmac_node = dpaa2_mac_get_node(attr.id); 327 if (!dpmac_node) { 328 netdev_err(net_dev, "No dpmac@%d node found.\n", attr.id); 329 err = -ENODEV; 330 goto err_close_dpmac; 331 } 332 333 err = dpaa2_mac_get_if_mode(dpmac_node, attr); 334 if (err < 0) { 335 err = -EINVAL; 336 goto err_put_node; 337 } 338 mac->if_mode = err; 339 340 /* The MAC does not have the capability to add RGMII delays so 341 * error out if the interface mode requests them and there is no PHY 342 * to act upon them 343 */ 344 if (of_phy_is_fixed_link(dpmac_node) && 345 (mac->if_mode == PHY_INTERFACE_MODE_RGMII_ID || 346 mac->if_mode == PHY_INTERFACE_MODE_RGMII_RXID || 347 mac->if_mode == PHY_INTERFACE_MODE_RGMII_TXID)) { 348 netdev_err(net_dev, "RGMII delay not supported\n"); 349 err = -EINVAL; 350 goto err_put_node; 351 } 352 353 if (attr.link_type == DPMAC_LINK_TYPE_PHY && 354 attr.eth_if != DPMAC_ETH_IF_RGMII) { 355 err = dpaa2_pcs_create(mac, dpmac_node, attr.id); 356 if (err) 357 goto err_put_node; 358 } 359 360 mac->phylink_config.dev = &net_dev->dev; 361 mac->phylink_config.type = PHYLINK_NETDEV; 362 363 phylink = phylink_create(&mac->phylink_config, 364 of_fwnode_handle(dpmac_node), mac->if_mode, 365 &dpaa2_mac_phylink_ops); 366 if (IS_ERR(phylink)) { 367 err = PTR_ERR(phylink); 368 goto err_pcs_destroy; 369 } 370 mac->phylink = phylink; 371 372 if (mac->pcs) 373 phylink_set_pcs(mac->phylink, &mac->pcs->pcs); 374 375 err = phylink_of_phy_connect(mac->phylink, dpmac_node, 0); 376 if (err) { 377 netdev_err(net_dev, "phylink_of_phy_connect() = %d\n", err); 378 goto err_phylink_destroy; 379 } 380 381 of_node_put(dpmac_node); 382 383 return 0; 384 385 err_phylink_destroy: 386 phylink_destroy(mac->phylink); 387 err_pcs_destroy: 388 dpaa2_pcs_destroy(mac); 389 err_put_node: 390 of_node_put(dpmac_node); 391 err_close_dpmac: 392 dpmac_close(mac->mc_io, 0, dpmac_dev->mc_handle); 393 return err; 394 } 395 396 void dpaa2_mac_disconnect(struct dpaa2_mac *mac) 397 { 398 if (!mac->phylink) 399 return; 400 401 phylink_disconnect_phy(mac->phylink); 402 phylink_destroy(mac->phylink); 403 dpaa2_pcs_destroy(mac); 404 405 dpmac_close(mac->mc_io, 0, mac->mc_dev->mc_handle); 406 } 407 408 static char dpaa2_mac_ethtool_stats[][ETH_GSTRING_LEN] = { 409 [DPMAC_CNT_ING_ALL_FRAME] = "[mac] rx all frames", 410 [DPMAC_CNT_ING_GOOD_FRAME] = "[mac] rx frames ok", 411 [DPMAC_CNT_ING_ERR_FRAME] = "[mac] rx frame errors", 412 [DPMAC_CNT_ING_FRAME_DISCARD] = "[mac] rx frame discards", 413 [DPMAC_CNT_ING_UCAST_FRAME] = "[mac] rx u-cast", 414 [DPMAC_CNT_ING_BCAST_FRAME] = "[mac] rx b-cast", 415 [DPMAC_CNT_ING_MCAST_FRAME] = "[mac] rx m-cast", 416 [DPMAC_CNT_ING_FRAME_64] = "[mac] rx 64 bytes", 417 [DPMAC_CNT_ING_FRAME_127] = "[mac] rx 65-127 bytes", 418 [DPMAC_CNT_ING_FRAME_255] = "[mac] rx 128-255 bytes", 419 [DPMAC_CNT_ING_FRAME_511] = "[mac] rx 256-511 bytes", 420 [DPMAC_CNT_ING_FRAME_1023] = "[mac] rx 512-1023 bytes", 421 [DPMAC_CNT_ING_FRAME_1518] = "[mac] rx 1024-1518 bytes", 422 [DPMAC_CNT_ING_FRAME_1519_MAX] = "[mac] rx 1519-max bytes", 423 [DPMAC_CNT_ING_FRAG] = "[mac] rx frags", 424 [DPMAC_CNT_ING_JABBER] = "[mac] rx jabber", 425 [DPMAC_CNT_ING_ALIGN_ERR] = "[mac] rx align errors", 426 [DPMAC_CNT_ING_OVERSIZED] = "[mac] rx oversized", 427 [DPMAC_CNT_ING_VALID_PAUSE_FRAME] = "[mac] rx pause", 428 [DPMAC_CNT_ING_BYTE] = "[mac] rx bytes", 429 [DPMAC_CNT_EGR_GOOD_FRAME] = "[mac] tx frames ok", 430 [DPMAC_CNT_EGR_UCAST_FRAME] = "[mac] tx u-cast", 431 [DPMAC_CNT_EGR_MCAST_FRAME] = "[mac] tx m-cast", 432 [DPMAC_CNT_EGR_BCAST_FRAME] = "[mac] tx b-cast", 433 [DPMAC_CNT_EGR_ERR_FRAME] = "[mac] tx frame errors", 434 [DPMAC_CNT_EGR_UNDERSIZED] = "[mac] tx undersized", 435 [DPMAC_CNT_EGR_VALID_PAUSE_FRAME] = "[mac] tx b-pause", 436 [DPMAC_CNT_EGR_BYTE] = "[mac] tx bytes", 437 }; 438 439 #define DPAA2_MAC_NUM_STATS ARRAY_SIZE(dpaa2_mac_ethtool_stats) 440 441 int dpaa2_mac_get_sset_count(void) 442 { 443 return DPAA2_MAC_NUM_STATS; 444 } 445 446 void dpaa2_mac_get_strings(u8 *data) 447 { 448 u8 *p = data; 449 int i; 450 451 for (i = 0; i < DPAA2_MAC_NUM_STATS; i++) { 452 strlcpy(p, dpaa2_mac_ethtool_stats[i], ETH_GSTRING_LEN); 453 p += ETH_GSTRING_LEN; 454 } 455 } 456 457 void dpaa2_mac_get_ethtool_stats(struct dpaa2_mac *mac, u64 *data) 458 { 459 struct fsl_mc_device *dpmac_dev = mac->mc_dev; 460 int i, err; 461 u64 value; 462 463 for (i = 0; i < DPAA2_MAC_NUM_STATS; i++) { 464 err = dpmac_get_counter(mac->mc_io, 0, dpmac_dev->mc_handle, 465 i, &value); 466 if (err) { 467 netdev_err_once(mac->net_dev, 468 "dpmac_get_counter error %d\n", err); 469 *(data + i) = U64_MAX; 470 continue; 471 } 472 *(data + i) = value; 473 } 474 } 475