1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Driver for MaxLinear MxL862xx switch family 4 * 5 * Copyright (C) 2024 MaxLinear Inc. 6 * Copyright (C) 2025 John Crispin <john@phrozen.org> 7 * Copyright (C) 2025 Daniel Golle <daniel@makrotopia.org> 8 */ 9 10 #include <linux/module.h> 11 #include <linux/delay.h> 12 #include <linux/of_device.h> 13 #include <linux/of_mdio.h> 14 #include <linux/phy.h> 15 #include <linux/phylink.h> 16 #include <net/dsa.h> 17 18 #include "mxl862xx.h" 19 #include "mxl862xx-api.h" 20 #include "mxl862xx-cmd.h" 21 #include "mxl862xx-host.h" 22 23 #define MXL862XX_API_WRITE(dev, cmd, data) \ 24 mxl862xx_api_wrap(dev, cmd, &(data), sizeof((data)), false, false) 25 #define MXL862XX_API_READ(dev, cmd, data) \ 26 mxl862xx_api_wrap(dev, cmd, &(data), sizeof((data)), true, false) 27 #define MXL862XX_API_READ_QUIET(dev, cmd, data) \ 28 mxl862xx_api_wrap(dev, cmd, &(data), sizeof((data)), true, true) 29 30 #define MXL862XX_SDMA_PCTRLP(p) (0xbc0 + ((p) * 0x6)) 31 #define MXL862XX_SDMA_PCTRL_EN BIT(0) 32 33 #define MXL862XX_FDMA_PCTRLP(p) (0xa80 + ((p) * 0x6)) 34 #define MXL862XX_FDMA_PCTRL_EN BIT(0) 35 36 #define MXL862XX_READY_TIMEOUT_MS 10000 37 #define MXL862XX_READY_POLL_MS 100 38 39 static enum dsa_tag_protocol mxl862xx_get_tag_protocol(struct dsa_switch *ds, 40 int port, 41 enum dsa_tag_protocol m) 42 { 43 return DSA_TAG_PROTO_MXL862; 44 } 45 46 /* PHY access via firmware relay */ 47 static int mxl862xx_phy_read_mmd(struct mxl862xx_priv *priv, int port, 48 int devadd, int reg) 49 { 50 struct mdio_relay_data param = { 51 .phy = port, 52 .mmd = devadd, 53 .reg = cpu_to_le16(reg), 54 }; 55 int ret; 56 57 ret = MXL862XX_API_READ(priv, INT_GPHY_READ, param); 58 if (ret) 59 return ret; 60 61 return le16_to_cpu(param.data); 62 } 63 64 static int mxl862xx_phy_write_mmd(struct mxl862xx_priv *priv, int port, 65 int devadd, int reg, u16 data) 66 { 67 struct mdio_relay_data param = { 68 .phy = port, 69 .mmd = devadd, 70 .reg = cpu_to_le16(reg), 71 .data = cpu_to_le16(data), 72 }; 73 74 return MXL862XX_API_WRITE(priv, INT_GPHY_WRITE, param); 75 } 76 77 static int mxl862xx_phy_read_mii_bus(struct mii_bus *bus, int port, int regnum) 78 { 79 return mxl862xx_phy_read_mmd(bus->priv, port, 0, regnum); 80 } 81 82 static int mxl862xx_phy_write_mii_bus(struct mii_bus *bus, int port, 83 int regnum, u16 val) 84 { 85 return mxl862xx_phy_write_mmd(bus->priv, port, 0, regnum, val); 86 } 87 88 static int mxl862xx_phy_read_c45_mii_bus(struct mii_bus *bus, int port, 89 int devadd, int regnum) 90 { 91 return mxl862xx_phy_read_mmd(bus->priv, port, devadd, regnum); 92 } 93 94 static int mxl862xx_phy_write_c45_mii_bus(struct mii_bus *bus, int port, 95 int devadd, int regnum, u16 val) 96 { 97 return mxl862xx_phy_write_mmd(bus->priv, port, devadd, regnum, val); 98 } 99 100 static int mxl862xx_wait_ready(struct dsa_switch *ds) 101 { 102 struct mxl862xx_sys_fw_image_version ver = {}; 103 unsigned long start = jiffies, timeout; 104 struct mxl862xx_priv *priv = ds->priv; 105 struct mxl862xx_cfg cfg = {}; 106 int ret; 107 108 timeout = start + msecs_to_jiffies(MXL862XX_READY_TIMEOUT_MS); 109 msleep(2000); /* it always takes at least 2 seconds */ 110 do { 111 ret = MXL862XX_API_READ_QUIET(priv, SYS_MISC_FW_VERSION, ver); 112 if (ret || !ver.iv_major) 113 goto not_ready_yet; 114 115 /* being able to perform CFGGET indicates that 116 * the firmware is ready 117 */ 118 ret = MXL862XX_API_READ_QUIET(priv, 119 MXL862XX_COMMON_CFGGET, 120 cfg); 121 if (ret) 122 goto not_ready_yet; 123 124 dev_info(ds->dev, "switch ready after %ums, firmware %u.%u.%u (build %u)\n", 125 jiffies_to_msecs(jiffies - start), 126 ver.iv_major, ver.iv_minor, 127 le16_to_cpu(ver.iv_revision), 128 le32_to_cpu(ver.iv_build_num)); 129 return 0; 130 131 not_ready_yet: 132 msleep(MXL862XX_READY_POLL_MS); 133 } while (time_before(jiffies, timeout)); 134 135 dev_err(ds->dev, "switch not responding after reset\n"); 136 return -ETIMEDOUT; 137 } 138 139 static int mxl862xx_setup_mdio(struct dsa_switch *ds) 140 { 141 struct mxl862xx_priv *priv = ds->priv; 142 struct device *dev = ds->dev; 143 struct device_node *mdio_np; 144 struct mii_bus *bus; 145 int ret; 146 147 bus = devm_mdiobus_alloc(dev); 148 if (!bus) 149 return -ENOMEM; 150 151 bus->priv = priv; 152 ds->user_mii_bus = bus; 153 bus->name = KBUILD_MODNAME "-mii"; 154 snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", dev_name(dev)); 155 bus->read_c45 = mxl862xx_phy_read_c45_mii_bus; 156 bus->write_c45 = mxl862xx_phy_write_c45_mii_bus; 157 bus->read = mxl862xx_phy_read_mii_bus; 158 bus->write = mxl862xx_phy_write_mii_bus; 159 bus->parent = dev; 160 bus->phy_mask = ~ds->phys_mii_mask; 161 162 mdio_np = of_get_child_by_name(dev->of_node, "mdio"); 163 if (!mdio_np) 164 return -ENODEV; 165 166 ret = devm_of_mdiobus_register(dev, bus, mdio_np); 167 of_node_put(mdio_np); 168 169 return ret; 170 } 171 172 static int mxl862xx_setup(struct dsa_switch *ds) 173 { 174 struct mxl862xx_priv *priv = ds->priv; 175 int ret; 176 177 ret = mxl862xx_reset(priv); 178 if (ret) 179 return ret; 180 181 ret = mxl862xx_wait_ready(ds); 182 if (ret) 183 return ret; 184 185 return mxl862xx_setup_mdio(ds); 186 } 187 188 static int mxl862xx_port_state(struct dsa_switch *ds, int port, bool enable) 189 { 190 struct mxl862xx_register_mod sdma = { 191 .addr = cpu_to_le16(MXL862XX_SDMA_PCTRLP(port)), 192 .data = cpu_to_le16(enable ? MXL862XX_SDMA_PCTRL_EN : 0), 193 .mask = cpu_to_le16(MXL862XX_SDMA_PCTRL_EN), 194 }; 195 struct mxl862xx_register_mod fdma = { 196 .addr = cpu_to_le16(MXL862XX_FDMA_PCTRLP(port)), 197 .data = cpu_to_le16(enable ? MXL862XX_FDMA_PCTRL_EN : 0), 198 .mask = cpu_to_le16(MXL862XX_FDMA_PCTRL_EN), 199 }; 200 int ret; 201 202 ret = MXL862XX_API_WRITE(ds->priv, MXL862XX_COMMON_REGISTERMOD, sdma); 203 if (ret) 204 return ret; 205 206 return MXL862XX_API_WRITE(ds->priv, MXL862XX_COMMON_REGISTERMOD, fdma); 207 } 208 209 static int mxl862xx_port_enable(struct dsa_switch *ds, int port, 210 struct phy_device *phydev) 211 { 212 return mxl862xx_port_state(ds, port, true); 213 } 214 215 static void mxl862xx_port_disable(struct dsa_switch *ds, int port) 216 { 217 if (mxl862xx_port_state(ds, port, false)) 218 dev_err(ds->dev, "failed to disable port %d\n", port); 219 } 220 221 static void mxl862xx_port_fast_age(struct dsa_switch *ds, int port) 222 { 223 struct mxl862xx_mac_table_clear param = { 224 .type = MXL862XX_MAC_CLEAR_PHY_PORT, 225 .port_id = port, 226 }; 227 228 if (MXL862XX_API_WRITE(ds->priv, MXL862XX_MAC_TABLECLEARCOND, param)) 229 dev_err(ds->dev, "failed to clear fdb on port %d\n", port); 230 } 231 232 static int mxl862xx_configure_ctp_port(struct dsa_switch *ds, int port, 233 u16 first_ctp_port_id, 234 u16 number_of_ctp_ports) 235 { 236 struct mxl862xx_ctp_port_assignment ctp_assign = { 237 .logical_port_id = port, 238 .first_ctp_port_id = cpu_to_le16(first_ctp_port_id), 239 .number_of_ctp_port = cpu_to_le16(number_of_ctp_ports), 240 .mode = cpu_to_le32(MXL862XX_LOGICAL_PORT_ETHERNET), 241 }; 242 243 return MXL862XX_API_WRITE(ds->priv, MXL862XX_CTP_PORTASSIGNMENTSET, 244 ctp_assign); 245 } 246 247 static int mxl862xx_configure_sp_tag_proto(struct dsa_switch *ds, int port, 248 bool enable) 249 { 250 struct mxl862xx_ss_sp_tag tag = { 251 .pid = port, 252 .mask = MXL862XX_SS_SP_TAG_MASK_RX | MXL862XX_SS_SP_TAG_MASK_TX, 253 .rx = enable ? MXL862XX_SS_SP_TAG_RX_TAG_NO_INSERT : 254 MXL862XX_SS_SP_TAG_RX_NO_TAG_INSERT, 255 .tx = enable ? MXL862XX_SS_SP_TAG_TX_TAG_NO_REMOVE : 256 MXL862XX_SS_SP_TAG_TX_TAG_REMOVE, 257 }; 258 259 return MXL862XX_API_WRITE(ds->priv, MXL862XX_SS_SPTAG_SET, tag); 260 } 261 262 static int mxl862xx_setup_cpu_bridge(struct dsa_switch *ds, int port) 263 { 264 struct mxl862xx_bridge_port_config br_port_cfg = {}; 265 struct mxl862xx_priv *priv = ds->priv; 266 u16 bridge_port_map = 0; 267 struct dsa_port *dp; 268 269 /* CPU port bridge setup */ 270 br_port_cfg.mask = cpu_to_le32(MXL862XX_BRIDGE_PORT_CONFIG_MASK_BRIDGE_PORT_MAP | 271 MXL862XX_BRIDGE_PORT_CONFIG_MASK_MC_SRC_MAC_LEARNING | 272 MXL862XX_BRIDGE_PORT_CONFIG_MASK_VLAN_BASED_MAC_LEARNING); 273 274 br_port_cfg.bridge_port_id = cpu_to_le16(port); 275 br_port_cfg.src_mac_learning_disable = false; 276 br_port_cfg.vlan_src_mac_vid_enable = true; 277 br_port_cfg.vlan_dst_mac_vid_enable = true; 278 279 /* include all assigned user ports in the CPU portmap */ 280 dsa_switch_for_each_user_port(dp, ds) { 281 /* it's safe to rely on cpu_dp being valid for user ports */ 282 if (dp->cpu_dp->index != port) 283 continue; 284 285 bridge_port_map |= BIT(dp->index); 286 } 287 br_port_cfg.bridge_port_map[0] |= cpu_to_le16(bridge_port_map); 288 289 return MXL862XX_API_WRITE(priv, MXL862XX_BRIDGEPORT_CONFIGSET, br_port_cfg); 290 } 291 292 static int mxl862xx_add_single_port_bridge(struct dsa_switch *ds, int port) 293 { 294 struct mxl862xx_bridge_port_config br_port_cfg = {}; 295 struct dsa_port *dp = dsa_to_port(ds, port); 296 struct mxl862xx_bridge_alloc br_alloc = {}; 297 int ret; 298 299 ret = MXL862XX_API_READ(ds->priv, MXL862XX_BRIDGE_ALLOC, br_alloc); 300 if (ret) { 301 dev_err(ds->dev, "failed to allocate a bridge for port %d\n", port); 302 return ret; 303 } 304 305 br_port_cfg.bridge_id = br_alloc.bridge_id; 306 br_port_cfg.bridge_port_id = cpu_to_le16(port); 307 br_port_cfg.mask = cpu_to_le32(MXL862XX_BRIDGE_PORT_CONFIG_MASK_BRIDGE_ID | 308 MXL862XX_BRIDGE_PORT_CONFIG_MASK_BRIDGE_PORT_MAP | 309 MXL862XX_BRIDGE_PORT_CONFIG_MASK_MC_SRC_MAC_LEARNING | 310 MXL862XX_BRIDGE_PORT_CONFIG_MASK_VLAN_BASED_MAC_LEARNING); 311 br_port_cfg.src_mac_learning_disable = true; 312 br_port_cfg.vlan_src_mac_vid_enable = false; 313 br_port_cfg.vlan_dst_mac_vid_enable = false; 314 /* As this function is only called for user ports it is safe to rely on 315 * cpu_dp being valid 316 */ 317 br_port_cfg.bridge_port_map[0] = cpu_to_le16(BIT(dp->cpu_dp->index)); 318 319 return MXL862XX_API_WRITE(ds->priv, MXL862XX_BRIDGEPORT_CONFIGSET, br_port_cfg); 320 } 321 322 static int mxl862xx_port_setup(struct dsa_switch *ds, int port) 323 { 324 struct dsa_port *dp = dsa_to_port(ds, port); 325 bool is_cpu_port = dsa_port_is_cpu(dp); 326 int ret; 327 328 /* disable port and flush MAC entries */ 329 ret = mxl862xx_port_state(ds, port, false); 330 if (ret) 331 return ret; 332 333 mxl862xx_port_fast_age(ds, port); 334 335 /* skip setup for unused and DSA ports */ 336 if (dsa_port_is_unused(dp) || 337 dsa_port_is_dsa(dp)) 338 return 0; 339 340 /* configure tag protocol */ 341 ret = mxl862xx_configure_sp_tag_proto(ds, port, is_cpu_port); 342 if (ret) 343 return ret; 344 345 /* assign CTP port IDs */ 346 ret = mxl862xx_configure_ctp_port(ds, port, port, 347 is_cpu_port ? 32 - port : 1); 348 if (ret) 349 return ret; 350 351 if (is_cpu_port) 352 /* assign user ports to CPU port bridge */ 353 return mxl862xx_setup_cpu_bridge(ds, port); 354 355 /* setup single-port bridge for user ports */ 356 return mxl862xx_add_single_port_bridge(ds, port); 357 } 358 359 static void mxl862xx_phylink_get_caps(struct dsa_switch *ds, int port, 360 struct phylink_config *config) 361 { 362 config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | MAC_10 | 363 MAC_100 | MAC_1000 | MAC_2500FD; 364 365 __set_bit(PHY_INTERFACE_MODE_INTERNAL, 366 config->supported_interfaces); 367 } 368 369 static const struct dsa_switch_ops mxl862xx_switch_ops = { 370 .get_tag_protocol = mxl862xx_get_tag_protocol, 371 .setup = mxl862xx_setup, 372 .port_setup = mxl862xx_port_setup, 373 .phylink_get_caps = mxl862xx_phylink_get_caps, 374 .port_enable = mxl862xx_port_enable, 375 .port_disable = mxl862xx_port_disable, 376 .port_fast_age = mxl862xx_port_fast_age, 377 }; 378 379 static void mxl862xx_phylink_mac_config(struct phylink_config *config, 380 unsigned int mode, 381 const struct phylink_link_state *state) 382 { 383 } 384 385 static void mxl862xx_phylink_mac_link_down(struct phylink_config *config, 386 unsigned int mode, 387 phy_interface_t interface) 388 { 389 } 390 391 static void mxl862xx_phylink_mac_link_up(struct phylink_config *config, 392 struct phy_device *phydev, 393 unsigned int mode, 394 phy_interface_t interface, 395 int speed, int duplex, 396 bool tx_pause, bool rx_pause) 397 { 398 } 399 400 static const struct phylink_mac_ops mxl862xx_phylink_mac_ops = { 401 .mac_config = mxl862xx_phylink_mac_config, 402 .mac_link_down = mxl862xx_phylink_mac_link_down, 403 .mac_link_up = mxl862xx_phylink_mac_link_up, 404 }; 405 406 static int mxl862xx_probe(struct mdio_device *mdiodev) 407 { 408 struct device *dev = &mdiodev->dev; 409 struct mxl862xx_priv *priv; 410 struct dsa_switch *ds; 411 412 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 413 if (!priv) 414 return -ENOMEM; 415 416 priv->mdiodev = mdiodev; 417 418 ds = devm_kzalloc(dev, sizeof(*ds), GFP_KERNEL); 419 if (!ds) 420 return -ENOMEM; 421 422 priv->ds = ds; 423 ds->dev = dev; 424 ds->priv = priv; 425 ds->ops = &mxl862xx_switch_ops; 426 ds->phylink_mac_ops = &mxl862xx_phylink_mac_ops; 427 ds->num_ports = MXL862XX_MAX_PORTS; 428 429 dev_set_drvdata(dev, ds); 430 431 return dsa_register_switch(ds); 432 } 433 434 static void mxl862xx_remove(struct mdio_device *mdiodev) 435 { 436 struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev); 437 438 if (!ds) 439 return; 440 441 dsa_unregister_switch(ds); 442 } 443 444 static void mxl862xx_shutdown(struct mdio_device *mdiodev) 445 { 446 struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev); 447 448 if (!ds) 449 return; 450 451 dsa_switch_shutdown(ds); 452 453 dev_set_drvdata(&mdiodev->dev, NULL); 454 } 455 456 static const struct of_device_id mxl862xx_of_match[] = { 457 { .compatible = "maxlinear,mxl86282" }, 458 { .compatible = "maxlinear,mxl86252" }, 459 { /* sentinel */ } 460 }; 461 MODULE_DEVICE_TABLE(of, mxl862xx_of_match); 462 463 static struct mdio_driver mxl862xx_driver = { 464 .probe = mxl862xx_probe, 465 .remove = mxl862xx_remove, 466 .shutdown = mxl862xx_shutdown, 467 .mdiodrv.driver = { 468 .name = "mxl862xx", 469 .of_match_table = mxl862xx_of_match, 470 }, 471 }; 472 473 mdio_module_driver(mxl862xx_driver); 474 475 MODULE_DESCRIPTION("Driver for MaxLinear MxL862xx switch family"); 476 MODULE_LICENSE("GPL"); 477