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 bus->name = KBUILD_MODNAME "-mii"; 153 snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", dev_name(dev)); 154 bus->read_c45 = mxl862xx_phy_read_c45_mii_bus; 155 bus->write_c45 = mxl862xx_phy_write_c45_mii_bus; 156 bus->read = mxl862xx_phy_read_mii_bus; 157 bus->write = mxl862xx_phy_write_mii_bus; 158 bus->parent = dev; 159 bus->phy_mask = ~ds->phys_mii_mask; 160 161 mdio_np = of_get_child_by_name(dev->of_node, "mdio"); 162 if (!mdio_np) 163 return -ENODEV; 164 165 ret = devm_of_mdiobus_register(dev, bus, mdio_np); 166 of_node_put(mdio_np); 167 168 return ret; 169 } 170 171 static int mxl862xx_setup(struct dsa_switch *ds) 172 { 173 struct mxl862xx_priv *priv = ds->priv; 174 int ret; 175 176 ret = mxl862xx_reset(priv); 177 if (ret) 178 return ret; 179 180 ret = mxl862xx_wait_ready(ds); 181 if (ret) 182 return ret; 183 184 return mxl862xx_setup_mdio(ds); 185 } 186 187 static int mxl862xx_port_state(struct dsa_switch *ds, int port, bool enable) 188 { 189 struct mxl862xx_register_mod sdma = { 190 .addr = cpu_to_le16(MXL862XX_SDMA_PCTRLP(port)), 191 .data = cpu_to_le16(enable ? MXL862XX_SDMA_PCTRL_EN : 0), 192 .mask = cpu_to_le16(MXL862XX_SDMA_PCTRL_EN), 193 }; 194 struct mxl862xx_register_mod fdma = { 195 .addr = cpu_to_le16(MXL862XX_FDMA_PCTRLP(port)), 196 .data = cpu_to_le16(enable ? MXL862XX_FDMA_PCTRL_EN : 0), 197 .mask = cpu_to_le16(MXL862XX_FDMA_PCTRL_EN), 198 }; 199 int ret; 200 201 ret = MXL862XX_API_WRITE(ds->priv, MXL862XX_COMMON_REGISTERMOD, sdma); 202 if (ret) 203 return ret; 204 205 return MXL862XX_API_WRITE(ds->priv, MXL862XX_COMMON_REGISTERMOD, fdma); 206 } 207 208 static int mxl862xx_port_enable(struct dsa_switch *ds, int port, 209 struct phy_device *phydev) 210 { 211 return mxl862xx_port_state(ds, port, true); 212 } 213 214 static void mxl862xx_port_disable(struct dsa_switch *ds, int port) 215 { 216 if (mxl862xx_port_state(ds, port, false)) 217 dev_err(ds->dev, "failed to disable port %d\n", port); 218 } 219 220 static void mxl862xx_port_fast_age(struct dsa_switch *ds, int port) 221 { 222 struct mxl862xx_mac_table_clear param = { 223 .type = MXL862XX_MAC_CLEAR_PHY_PORT, 224 .port_id = port, 225 }; 226 227 if (MXL862XX_API_WRITE(ds->priv, MXL862XX_MAC_TABLECLEARCOND, param)) 228 dev_err(ds->dev, "failed to clear fdb on port %d\n", port); 229 } 230 231 static int mxl862xx_configure_ctp_port(struct dsa_switch *ds, int port, 232 u16 first_ctp_port_id, 233 u16 number_of_ctp_ports) 234 { 235 struct mxl862xx_ctp_port_assignment ctp_assign = { 236 .logical_port_id = port, 237 .first_ctp_port_id = cpu_to_le16(first_ctp_port_id), 238 .number_of_ctp_port = cpu_to_le16(number_of_ctp_ports), 239 .mode = cpu_to_le32(MXL862XX_LOGICAL_PORT_ETHERNET), 240 }; 241 242 return MXL862XX_API_WRITE(ds->priv, MXL862XX_CTP_PORTASSIGNMENTSET, 243 ctp_assign); 244 } 245 246 static int mxl862xx_configure_sp_tag_proto(struct dsa_switch *ds, int port, 247 bool enable) 248 { 249 struct mxl862xx_ss_sp_tag tag = { 250 .pid = port, 251 .mask = MXL862XX_SS_SP_TAG_MASK_RX | MXL862XX_SS_SP_TAG_MASK_TX, 252 .rx = enable ? MXL862XX_SS_SP_TAG_RX_TAG_NO_INSERT : 253 MXL862XX_SS_SP_TAG_RX_NO_TAG_INSERT, 254 .tx = enable ? MXL862XX_SS_SP_TAG_TX_TAG_NO_REMOVE : 255 MXL862XX_SS_SP_TAG_TX_TAG_REMOVE, 256 }; 257 258 return MXL862XX_API_WRITE(ds->priv, MXL862XX_SS_SPTAG_SET, tag); 259 } 260 261 static int mxl862xx_setup_cpu_bridge(struct dsa_switch *ds, int port) 262 { 263 struct mxl862xx_bridge_port_config br_port_cfg = {}; 264 struct mxl862xx_priv *priv = ds->priv; 265 u16 bridge_port_map = 0; 266 struct dsa_port *dp; 267 268 /* CPU port bridge setup */ 269 br_port_cfg.mask = cpu_to_le32(MXL862XX_BRIDGE_PORT_CONFIG_MASK_BRIDGE_PORT_MAP | 270 MXL862XX_BRIDGE_PORT_CONFIG_MASK_MC_SRC_MAC_LEARNING | 271 MXL862XX_BRIDGE_PORT_CONFIG_MASK_VLAN_BASED_MAC_LEARNING); 272 273 br_port_cfg.bridge_port_id = cpu_to_le16(port); 274 br_port_cfg.src_mac_learning_disable = false; 275 br_port_cfg.vlan_src_mac_vid_enable = true; 276 br_port_cfg.vlan_dst_mac_vid_enable = true; 277 278 /* include all assigned user ports in the CPU portmap */ 279 dsa_switch_for_each_user_port(dp, ds) { 280 /* it's safe to rely on cpu_dp being valid for user ports */ 281 if (dp->cpu_dp->index != port) 282 continue; 283 284 bridge_port_map |= BIT(dp->index); 285 } 286 br_port_cfg.bridge_port_map[0] |= cpu_to_le16(bridge_port_map); 287 288 return MXL862XX_API_WRITE(priv, MXL862XX_BRIDGEPORT_CONFIGSET, br_port_cfg); 289 } 290 291 static int mxl862xx_add_single_port_bridge(struct dsa_switch *ds, int port) 292 { 293 struct mxl862xx_bridge_port_config br_port_cfg = {}; 294 struct dsa_port *dp = dsa_to_port(ds, port); 295 struct mxl862xx_bridge_alloc br_alloc = {}; 296 int ret; 297 298 ret = MXL862XX_API_READ(ds->priv, MXL862XX_BRIDGE_ALLOC, br_alloc); 299 if (ret) { 300 dev_err(ds->dev, "failed to allocate a bridge for port %d\n", port); 301 return ret; 302 } 303 304 br_port_cfg.bridge_id = br_alloc.bridge_id; 305 br_port_cfg.bridge_port_id = cpu_to_le16(port); 306 br_port_cfg.mask = cpu_to_le32(MXL862XX_BRIDGE_PORT_CONFIG_MASK_BRIDGE_ID | 307 MXL862XX_BRIDGE_PORT_CONFIG_MASK_BRIDGE_PORT_MAP | 308 MXL862XX_BRIDGE_PORT_CONFIG_MASK_MC_SRC_MAC_LEARNING | 309 MXL862XX_BRIDGE_PORT_CONFIG_MASK_VLAN_BASED_MAC_LEARNING); 310 br_port_cfg.src_mac_learning_disable = true; 311 br_port_cfg.vlan_src_mac_vid_enable = false; 312 br_port_cfg.vlan_dst_mac_vid_enable = false; 313 /* As this function is only called for user ports it is safe to rely on 314 * cpu_dp being valid 315 */ 316 br_port_cfg.bridge_port_map[0] = cpu_to_le16(BIT(dp->cpu_dp->index)); 317 318 return MXL862XX_API_WRITE(ds->priv, MXL862XX_BRIDGEPORT_CONFIGSET, br_port_cfg); 319 } 320 321 static int mxl862xx_port_setup(struct dsa_switch *ds, int port) 322 { 323 struct dsa_port *dp = dsa_to_port(ds, port); 324 bool is_cpu_port = dsa_port_is_cpu(dp); 325 int ret; 326 327 /* disable port and flush MAC entries */ 328 ret = mxl862xx_port_state(ds, port, false); 329 if (ret) 330 return ret; 331 332 mxl862xx_port_fast_age(ds, port); 333 334 /* skip setup for unused and DSA ports */ 335 if (dsa_port_is_unused(dp) || 336 dsa_port_is_dsa(dp)) 337 return 0; 338 339 /* configure tag protocol */ 340 ret = mxl862xx_configure_sp_tag_proto(ds, port, is_cpu_port); 341 if (ret) 342 return ret; 343 344 /* assign CTP port IDs */ 345 ret = mxl862xx_configure_ctp_port(ds, port, port, 346 is_cpu_port ? 32 - port : 1); 347 if (ret) 348 return ret; 349 350 if (is_cpu_port) 351 /* assign user ports to CPU port bridge */ 352 return mxl862xx_setup_cpu_bridge(ds, port); 353 354 /* setup single-port bridge for user ports */ 355 return mxl862xx_add_single_port_bridge(ds, port); 356 } 357 358 static void mxl862xx_phylink_get_caps(struct dsa_switch *ds, int port, 359 struct phylink_config *config) 360 { 361 config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | MAC_10 | 362 MAC_100 | MAC_1000 | MAC_2500FD; 363 364 __set_bit(PHY_INTERFACE_MODE_INTERNAL, 365 config->supported_interfaces); 366 } 367 368 static const struct dsa_switch_ops mxl862xx_switch_ops = { 369 .get_tag_protocol = mxl862xx_get_tag_protocol, 370 .setup = mxl862xx_setup, 371 .port_setup = mxl862xx_port_setup, 372 .phylink_get_caps = mxl862xx_phylink_get_caps, 373 .port_enable = mxl862xx_port_enable, 374 .port_disable = mxl862xx_port_disable, 375 .port_fast_age = mxl862xx_port_fast_age, 376 }; 377 378 static void mxl862xx_phylink_mac_config(struct phylink_config *config, 379 unsigned int mode, 380 const struct phylink_link_state *state) 381 { 382 } 383 384 static void mxl862xx_phylink_mac_link_down(struct phylink_config *config, 385 unsigned int mode, 386 phy_interface_t interface) 387 { 388 } 389 390 static void mxl862xx_phylink_mac_link_up(struct phylink_config *config, 391 struct phy_device *phydev, 392 unsigned int mode, 393 phy_interface_t interface, 394 int speed, int duplex, 395 bool tx_pause, bool rx_pause) 396 { 397 } 398 399 static const struct phylink_mac_ops mxl862xx_phylink_mac_ops = { 400 .mac_config = mxl862xx_phylink_mac_config, 401 .mac_link_down = mxl862xx_phylink_mac_link_down, 402 .mac_link_up = mxl862xx_phylink_mac_link_up, 403 }; 404 405 static int mxl862xx_probe(struct mdio_device *mdiodev) 406 { 407 struct device *dev = &mdiodev->dev; 408 struct mxl862xx_priv *priv; 409 struct dsa_switch *ds; 410 411 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 412 if (!priv) 413 return -ENOMEM; 414 415 priv->mdiodev = mdiodev; 416 417 ds = devm_kzalloc(dev, sizeof(*ds), GFP_KERNEL); 418 if (!ds) 419 return -ENOMEM; 420 421 priv->ds = ds; 422 ds->dev = dev; 423 ds->priv = priv; 424 ds->ops = &mxl862xx_switch_ops; 425 ds->phylink_mac_ops = &mxl862xx_phylink_mac_ops; 426 ds->num_ports = MXL862XX_MAX_PORTS; 427 428 dev_set_drvdata(dev, ds); 429 430 return dsa_register_switch(ds); 431 } 432 433 static void mxl862xx_remove(struct mdio_device *mdiodev) 434 { 435 struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev); 436 437 if (!ds) 438 return; 439 440 dsa_unregister_switch(ds); 441 } 442 443 static void mxl862xx_shutdown(struct mdio_device *mdiodev) 444 { 445 struct dsa_switch *ds = dev_get_drvdata(&mdiodev->dev); 446 447 if (!ds) 448 return; 449 450 dsa_switch_shutdown(ds); 451 452 dev_set_drvdata(&mdiodev->dev, NULL); 453 } 454 455 static const struct of_device_id mxl862xx_of_match[] = { 456 { .compatible = "maxlinear,mxl86282" }, 457 { .compatible = "maxlinear,mxl86252" }, 458 { /* sentinel */ } 459 }; 460 MODULE_DEVICE_TABLE(of, mxl862xx_of_match); 461 462 static struct mdio_driver mxl862xx_driver = { 463 .probe = mxl862xx_probe, 464 .remove = mxl862xx_remove, 465 .shutdown = mxl862xx_shutdown, 466 .mdiodrv.driver = { 467 .name = "mxl862xx", 468 .of_match_table = mxl862xx_of_match, 469 }, 470 }; 471 472 mdio_module_driver(mxl862xx_driver); 473 474 MODULE_DESCRIPTION("Driver for MaxLinear MxL862xx switch family"); 475 MODULE_LICENSE("GPL"); 476