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