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 default: 19 return -EINVAL; 20 } 21 22 return 0; 23 } 24 25 /* Caller must call of_node_put on the returned value */ 26 static struct device_node *dpaa2_mac_get_node(u16 dpmac_id) 27 { 28 struct device_node *dpmacs, *dpmac = NULL; 29 u32 id; 30 int err; 31 32 dpmacs = of_find_node_by_name(NULL, "dpmacs"); 33 if (!dpmacs) 34 return NULL; 35 36 while ((dpmac = of_get_next_child(dpmacs, dpmac)) != NULL) { 37 err = of_property_read_u32(dpmac, "reg", &id); 38 if (err) 39 continue; 40 if (id == dpmac_id) 41 break; 42 } 43 44 of_node_put(dpmacs); 45 46 return dpmac; 47 } 48 49 static int dpaa2_mac_get_if_mode(struct device_node *node, 50 struct dpmac_attr attr) 51 { 52 phy_interface_t if_mode; 53 int err; 54 55 err = of_get_phy_mode(node, &if_mode); 56 if (!err) 57 return if_mode; 58 59 err = phy_mode(attr.eth_if, &if_mode); 60 if (!err) 61 return if_mode; 62 63 return err; 64 } 65 66 static bool dpaa2_mac_phy_mode_mismatch(struct dpaa2_mac *mac, 67 phy_interface_t interface) 68 { 69 switch (interface) { 70 case PHY_INTERFACE_MODE_RGMII: 71 case PHY_INTERFACE_MODE_RGMII_ID: 72 case PHY_INTERFACE_MODE_RGMII_RXID: 73 case PHY_INTERFACE_MODE_RGMII_TXID: 74 return (interface != mac->if_mode); 75 default: 76 return true; 77 } 78 } 79 80 static void dpaa2_mac_validate(struct phylink_config *config, 81 unsigned long *supported, 82 struct phylink_link_state *state) 83 { 84 struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config); 85 __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; 86 87 if (state->interface != PHY_INTERFACE_MODE_NA && 88 dpaa2_mac_phy_mode_mismatch(mac, state->interface)) { 89 goto empty_set; 90 } 91 92 phylink_set_port_modes(mask); 93 phylink_set(mask, Autoneg); 94 phylink_set(mask, Pause); 95 phylink_set(mask, Asym_Pause); 96 97 switch (state->interface) { 98 case PHY_INTERFACE_MODE_RGMII: 99 case PHY_INTERFACE_MODE_RGMII_ID: 100 case PHY_INTERFACE_MODE_RGMII_RXID: 101 case PHY_INTERFACE_MODE_RGMII_TXID: 102 phylink_set(mask, 10baseT_Full); 103 phylink_set(mask, 100baseT_Full); 104 phylink_set(mask, 1000baseT_Full); 105 break; 106 default: 107 goto empty_set; 108 } 109 110 linkmode_and(supported, supported, mask); 111 linkmode_and(state->advertising, state->advertising, mask); 112 113 return; 114 115 empty_set: 116 linkmode_zero(supported); 117 } 118 119 static void dpaa2_mac_config(struct phylink_config *config, unsigned int mode, 120 const struct phylink_link_state *state) 121 { 122 struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config); 123 struct dpmac_link_state *dpmac_state = &mac->state; 124 int err; 125 126 if (state->speed != SPEED_UNKNOWN) 127 dpmac_state->rate = state->speed; 128 129 if (state->duplex != DUPLEX_UNKNOWN) { 130 if (!state->duplex) 131 dpmac_state->options |= DPMAC_LINK_OPT_HALF_DUPLEX; 132 else 133 dpmac_state->options &= ~DPMAC_LINK_OPT_HALF_DUPLEX; 134 } 135 136 if (state->an_enabled) 137 dpmac_state->options |= DPMAC_LINK_OPT_AUTONEG; 138 else 139 dpmac_state->options &= ~DPMAC_LINK_OPT_AUTONEG; 140 141 if (state->pause & MLO_PAUSE_RX) 142 dpmac_state->options |= DPMAC_LINK_OPT_PAUSE; 143 else 144 dpmac_state->options &= ~DPMAC_LINK_OPT_PAUSE; 145 146 if (!!(state->pause & MLO_PAUSE_RX) ^ !!(state->pause & MLO_PAUSE_TX)) 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, "dpmac_set_link_state() = %d\n", err); 155 } 156 157 static void dpaa2_mac_link_up(struct phylink_config *config, unsigned int mode, 158 phy_interface_t interface, struct phy_device *phy) 159 { 160 struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config); 161 struct dpmac_link_state *dpmac_state = &mac->state; 162 int err; 163 164 dpmac_state->up = 1; 165 err = dpmac_set_link_state(mac->mc_io, 0, 166 mac->mc_dev->mc_handle, dpmac_state); 167 if (err) 168 netdev_err(mac->net_dev, "dpmac_set_link_state() = %d\n", err); 169 } 170 171 static void dpaa2_mac_link_down(struct phylink_config *config, 172 unsigned int mode, 173 phy_interface_t interface) 174 { 175 struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config); 176 struct dpmac_link_state *dpmac_state = &mac->state; 177 int err; 178 179 dpmac_state->up = 0; 180 err = dpmac_set_link_state(mac->mc_io, 0, 181 mac->mc_dev->mc_handle, dpmac_state); 182 if (err) 183 netdev_err(mac->net_dev, "dpmac_set_link_state() = %d\n", err); 184 } 185 186 static const struct phylink_mac_ops dpaa2_mac_phylink_ops = { 187 .validate = dpaa2_mac_validate, 188 .mac_config = dpaa2_mac_config, 189 .mac_link_up = dpaa2_mac_link_up, 190 .mac_link_down = dpaa2_mac_link_down, 191 }; 192 193 bool dpaa2_mac_is_type_fixed(struct fsl_mc_device *dpmac_dev, 194 struct fsl_mc_io *mc_io) 195 { 196 struct dpmac_attr attr; 197 bool fixed = false; 198 u16 mc_handle = 0; 199 int err; 200 201 err = dpmac_open(mc_io, 0, dpmac_dev->obj_desc.id, 202 &mc_handle); 203 if (err || !mc_handle) 204 return false; 205 206 err = dpmac_get_attributes(mc_io, 0, mc_handle, &attr); 207 if (err) 208 goto out; 209 210 if (attr.link_type == DPMAC_LINK_TYPE_FIXED) 211 fixed = true; 212 213 out: 214 dpmac_close(mc_io, 0, mc_handle); 215 216 return fixed; 217 } 218 219 int dpaa2_mac_connect(struct dpaa2_mac *mac) 220 { 221 struct fsl_mc_device *dpmac_dev = mac->mc_dev; 222 struct net_device *net_dev = mac->net_dev; 223 struct device_node *dpmac_node; 224 struct phylink *phylink; 225 struct dpmac_attr attr; 226 int err; 227 228 err = dpmac_open(mac->mc_io, 0, dpmac_dev->obj_desc.id, 229 &dpmac_dev->mc_handle); 230 if (err || !dpmac_dev->mc_handle) { 231 netdev_err(net_dev, "dpmac_open() = %d\n", err); 232 return -ENODEV; 233 } 234 235 err = dpmac_get_attributes(mac->mc_io, 0, dpmac_dev->mc_handle, &attr); 236 if (err) { 237 netdev_err(net_dev, "dpmac_get_attributes() = %d\n", err); 238 goto err_close_dpmac; 239 } 240 241 dpmac_node = dpaa2_mac_get_node(attr.id); 242 if (!dpmac_node) { 243 netdev_err(net_dev, "No dpmac@%d node found.\n", attr.id); 244 err = -ENODEV; 245 goto err_close_dpmac; 246 } 247 248 err = dpaa2_mac_get_if_mode(dpmac_node, attr); 249 if (err < 0) { 250 err = -EINVAL; 251 goto err_put_node; 252 } 253 mac->if_mode = err; 254 255 /* The MAC does not have the capability to add RGMII delays so 256 * error out if the interface mode requests them and there is no PHY 257 * to act upon them 258 */ 259 if (of_phy_is_fixed_link(dpmac_node) && 260 (mac->if_mode == PHY_INTERFACE_MODE_RGMII_ID || 261 mac->if_mode == PHY_INTERFACE_MODE_RGMII_RXID || 262 mac->if_mode == PHY_INTERFACE_MODE_RGMII_TXID)) { 263 netdev_err(net_dev, "RGMII delay not supported\n"); 264 err = -EINVAL; 265 goto err_put_node; 266 } 267 268 mac->phylink_config.dev = &net_dev->dev; 269 mac->phylink_config.type = PHYLINK_NETDEV; 270 271 phylink = phylink_create(&mac->phylink_config, 272 of_fwnode_handle(dpmac_node), mac->if_mode, 273 &dpaa2_mac_phylink_ops); 274 if (IS_ERR(phylink)) { 275 err = PTR_ERR(phylink); 276 goto err_put_node; 277 } 278 mac->phylink = phylink; 279 280 err = phylink_of_phy_connect(mac->phylink, dpmac_node, 0); 281 if (err) { 282 netdev_err(net_dev, "phylink_of_phy_connect() = %d\n", err); 283 goto err_phylink_destroy; 284 } 285 286 of_node_put(dpmac_node); 287 288 return 0; 289 290 err_phylink_destroy: 291 phylink_destroy(mac->phylink); 292 err_put_node: 293 of_node_put(dpmac_node); 294 err_close_dpmac: 295 dpmac_close(mac->mc_io, 0, dpmac_dev->mc_handle); 296 return err; 297 } 298 299 void dpaa2_mac_disconnect(struct dpaa2_mac *mac) 300 { 301 if (!mac->phylink) 302 return; 303 304 phylink_disconnect_phy(mac->phylink); 305 phylink_destroy(mac->phylink); 306 dpmac_close(mac->mc_io, 0, mac->mc_dev->mc_handle); 307 } 308 309 static char dpaa2_mac_ethtool_stats[][ETH_GSTRING_LEN] = { 310 [DPMAC_CNT_ING_ALL_FRAME] = "[mac] rx all frames", 311 [DPMAC_CNT_ING_GOOD_FRAME] = "[mac] rx frames ok", 312 [DPMAC_CNT_ING_ERR_FRAME] = "[mac] rx frame errors", 313 [DPMAC_CNT_ING_FRAME_DISCARD] = "[mac] rx frame discards", 314 [DPMAC_CNT_ING_UCAST_FRAME] = "[mac] rx u-cast", 315 [DPMAC_CNT_ING_BCAST_FRAME] = "[mac] rx b-cast", 316 [DPMAC_CNT_ING_MCAST_FRAME] = "[mac] rx m-cast", 317 [DPMAC_CNT_ING_FRAME_64] = "[mac] rx 64 bytes", 318 [DPMAC_CNT_ING_FRAME_127] = "[mac] rx 65-127 bytes", 319 [DPMAC_CNT_ING_FRAME_255] = "[mac] rx 128-255 bytes", 320 [DPMAC_CNT_ING_FRAME_511] = "[mac] rx 256-511 bytes", 321 [DPMAC_CNT_ING_FRAME_1023] = "[mac] rx 512-1023 bytes", 322 [DPMAC_CNT_ING_FRAME_1518] = "[mac] rx 1024-1518 bytes", 323 [DPMAC_CNT_ING_FRAME_1519_MAX] = "[mac] rx 1519-max bytes", 324 [DPMAC_CNT_ING_FRAG] = "[mac] rx frags", 325 [DPMAC_CNT_ING_JABBER] = "[mac] rx jabber", 326 [DPMAC_CNT_ING_ALIGN_ERR] = "[mac] rx align errors", 327 [DPMAC_CNT_ING_OVERSIZED] = "[mac] rx oversized", 328 [DPMAC_CNT_ING_VALID_PAUSE_FRAME] = "[mac] rx pause", 329 [DPMAC_CNT_ING_BYTE] = "[mac] rx bytes", 330 [DPMAC_CNT_EGR_GOOD_FRAME] = "[mac] tx frames ok", 331 [DPMAC_CNT_EGR_UCAST_FRAME] = "[mac] tx u-cast", 332 [DPMAC_CNT_EGR_MCAST_FRAME] = "[mac] tx m-cast", 333 [DPMAC_CNT_EGR_BCAST_FRAME] = "[mac] tx b-cast", 334 [DPMAC_CNT_EGR_ERR_FRAME] = "[mac] tx frame errors", 335 [DPMAC_CNT_EGR_UNDERSIZED] = "[mac] tx undersized", 336 [DPMAC_CNT_EGR_VALID_PAUSE_FRAME] = "[mac] tx b-pause", 337 [DPMAC_CNT_EGR_BYTE] = "[mac] tx bytes", 338 }; 339 340 #define DPAA2_MAC_NUM_STATS ARRAY_SIZE(dpaa2_mac_ethtool_stats) 341 342 int dpaa2_mac_get_sset_count(void) 343 { 344 return DPAA2_MAC_NUM_STATS; 345 } 346 347 void dpaa2_mac_get_strings(u8 *data) 348 { 349 u8 *p = data; 350 int i; 351 352 for (i = 0; i < DPAA2_MAC_NUM_STATS; i++) { 353 strlcpy(p, dpaa2_mac_ethtool_stats[i], ETH_GSTRING_LEN); 354 p += ETH_GSTRING_LEN; 355 } 356 } 357 358 void dpaa2_mac_get_ethtool_stats(struct dpaa2_mac *mac, u64 *data) 359 { 360 struct fsl_mc_device *dpmac_dev = mac->mc_dev; 361 int i, err; 362 u64 value; 363 364 for (i = 0; i < DPAA2_MAC_NUM_STATS; i++) { 365 err = dpmac_get_counter(mac->mc_io, 0, dpmac_dev->mc_handle, 366 i, &value); 367 if (err) { 368 netdev_err_once(mac->net_dev, 369 "dpmac_get_counter error %d\n", err); 370 *(data + i) = U64_MAX; 371 continue; 372 } 373 *(data + i) = value; 374 } 375 } 376